chore: refactor VCs to use a watch channel internally (but I'm going to rework this in the next commit anyway)
This commit is contained in:
@@ -50,9 +50,6 @@ enum GetGuildAndVoiceChannelIdError {
|
|||||||
/// there is no user who invoked this command
|
/// there is no user who invoked this command
|
||||||
NoUser,
|
NoUser,
|
||||||
|
|
||||||
/// there are no voice chats in this guild
|
|
||||||
NoVCsInGuild,
|
|
||||||
|
|
||||||
/// the user is not in a voice chat in this guild
|
/// the user is not in a voice chat in this guild
|
||||||
UserNotInVC,
|
UserNotInVC,
|
||||||
}
|
}
|
||||||
@@ -70,9 +67,11 @@ fn get_guild_and_voice_channel_id(
|
|||||||
.and_then(|member| member.user.as_ref().map(|user| user.id))
|
.and_then(|member| member.user.as_ref().map(|user| user.id))
|
||||||
.context(NoUserSnafu)?;
|
.context(NoUserSnafu)?;
|
||||||
|
|
||||||
let guild_vcs = vcs.get(&guild_id).context(NoVCsInGuildSnafu)?;
|
let voice_channel_id = vcs
|
||||||
|
.with_guild(guild_id, |guild_vcs| {
|
||||||
let &voice_channel_id = guild_vcs.get_left_for(&user_id).context(UserNotInVCSnafu)?;
|
guild_vcs.get_left_for(&user_id).copied()
|
||||||
|
})
|
||||||
|
.context(UserNotInVCSnafu)?;
|
||||||
|
|
||||||
Ok((guild_id, voice_channel_id))
|
Ok((guild_id, voice_channel_id))
|
||||||
}
|
}
|
||||||
@@ -85,9 +84,6 @@ fn get_guild_and_vc_error_to_embed(error: GetGuildAndVoiceChannelIdError) -> Emb
|
|||||||
GetGuildAndVoiceChannelIdError::NoUser => {
|
GetGuildAndVoiceChannelIdError::NoUser => {
|
||||||
EmbedBuilder::new().title("Not invoked by a user").description("This command works by joining the same VC as the user, but this bot didn't receive any user data. So did no user invoke it?! (This error should be impossible!)").validate().unwrap().build()
|
EmbedBuilder::new().title("Not invoked by a user").description("This command works by joining the same VC as the user, but this bot didn't receive any user data. So did no user invoke it?! (This error should be impossible!)").validate().unwrap().build()
|
||||||
},
|
},
|
||||||
GetGuildAndVoiceChannelIdError::NoVCsInGuild => {
|
|
||||||
EmbedBuilder::new().title("No VCs in this server").description("This bot can't find a VC to join because there aren't any in this server right now.").validate().unwrap().build()
|
|
||||||
},
|
|
||||||
GetGuildAndVoiceChannelIdError::UserNotInVC => {
|
GetGuildAndVoiceChannelIdError::UserNotInVC => {
|
||||||
EmbedBuilder::new().title("You're not in a VC").description("This bot can't follow you into VC if you aren't in one in this server.").validate().unwrap().build()
|
EmbedBuilder::new().title("You're not in a VC").description("This bot can't follow you into VC if you aren't in one in this server.").validate().unwrap().build()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -37,9 +37,6 @@ pub enum GetGuildAndVoiceChannelIdError {
|
|||||||
/// there is no user who invoked this command
|
/// there is no user who invoked this command
|
||||||
NoUser,
|
NoUser,
|
||||||
|
|
||||||
/// there are no voice chats in this guild
|
|
||||||
NoVCsInGuild,
|
|
||||||
|
|
||||||
/// the bot is not in a voice chat in this guild
|
/// the bot is not in a voice chat in this guild
|
||||||
BotNotInVC,
|
BotNotInVC,
|
||||||
}
|
}
|
||||||
@@ -58,10 +55,10 @@ pub fn get_user_and_guild_and_voice_channel_id(
|
|||||||
|
|
||||||
let guild_id = interaction.guild_id.context(NotInGuildSnafu)?;
|
let guild_id = interaction.guild_id.context(NotInGuildSnafu)?;
|
||||||
|
|
||||||
let guild_vcs = vcs.get(&guild_id).context(NoVCsInGuildSnafu)?;
|
let voice_channel_id = vcs
|
||||||
|
.with_guild(guild_id, |guild_vcs| {
|
||||||
let &voice_channel_id = guild_vcs
|
guild_vcs.get_left_for(&bot_user_id).copied()
|
||||||
.get_left_for(&bot_user_id)
|
})
|
||||||
.context(BotNotInVCSnafu)?;
|
.context(BotNotInVCSnafu)?;
|
||||||
|
|
||||||
Ok((user_id, guild_id, voice_channel_id))
|
Ok((user_id, guild_id, voice_channel_id))
|
||||||
@@ -75,9 +72,6 @@ fn get_guild_and_vc_error_to_embed(error: GetGuildAndVoiceChannelIdError) -> Emb
|
|||||||
GetGuildAndVoiceChannelIdError::NoUser => {
|
GetGuildAndVoiceChannelIdError::NoUser => {
|
||||||
EmbedBuilder::new().title("Not invoked by a user").description("This command works by joining the same VC as the user, but this bot didn't receive any user data. So did no user invoke it?! (This error should be impossible!)").validate().unwrap().build()
|
EmbedBuilder::new().title("Not invoked by a user").description("This command works by joining the same VC as the user, but this bot didn't receive any user data. So did no user invoke it?! (This error should be impossible!)").validate().unwrap().build()
|
||||||
},
|
},
|
||||||
GetGuildAndVoiceChannelIdError::NoVCsInGuild => {
|
|
||||||
EmbedBuilder::new().title("No VCs in this server").description("This bot can't leave VC because there aren't any in this server right now (therefore the bot must not be in any).").validate().unwrap().build()
|
|
||||||
},
|
|
||||||
GetGuildAndVoiceChannelIdError::BotNotInVC => {
|
GetGuildAndVoiceChannelIdError::BotNotInVC => {
|
||||||
EmbedBuilder::new().title("Not in a VC").description("This bot can't leave VC if it isn't in one in this server.").validate().unwrap().build()
|
EmbedBuilder::new().title("Not in a VC").description("This bot can't leave VC if it isn't in one in this server.").validate().unwrap().build()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use std::collections::BTreeMap;
|
|||||||
|
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use futures::{StreamExt, stream::FuturesUnordered};
|
use futures::{StreamExt, stream::FuturesUnordered};
|
||||||
|
use tokio::sync::watch;
|
||||||
use twilight_model::{
|
use twilight_model::{
|
||||||
gateway::payload::incoming::VoiceStateUpdate,
|
gateway::payload::incoming::VoiceStateUpdate,
|
||||||
id::{
|
id::{
|
||||||
@@ -16,7 +17,37 @@ pub type GuildVoiceChannelToTextChannel =
|
|||||||
BTreeMap<Id<GuildMarker>, OneToOneBTreeMap<Id<ChannelMarker>, Id<ChannelMarker>>>;
|
BTreeMap<Id<GuildMarker>, OneToOneBTreeMap<Id<ChannelMarker>, Id<ChannelMarker>>>;
|
||||||
|
|
||||||
type VCsInGuild = OneToManyUniqueBTreeMapWithData<Id<ChannelMarker>, Id<UserMarker>, UserInVCData>;
|
type VCsInGuild = OneToManyUniqueBTreeMapWithData<Id<ChannelMarker>, Id<UserMarker>, UserInVCData>;
|
||||||
pub type VCs = DashMap<Id<GuildMarker>, VCsInGuild>;
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct VCs(DashMap<Id<GuildMarker>, watch::Sender<VCsInGuild>>);
|
||||||
|
|
||||||
|
impl Extend<(Id<GuildMarker>, VCsInGuild)> for VCs {
|
||||||
|
fn extend<T: IntoIterator<Item = (Id<GuildMarker>, VCsInGuild)>>(&mut self, iter: T) {
|
||||||
|
for (id, guild_vcs) in iter {
|
||||||
|
self.0.insert(id, watch::Sender::new(guild_vcs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VCs {
|
||||||
|
pub fn with_guild<R>(&self, id: Id<GuildMarker>, f: impl FnOnce(&VCsInGuild) -> R) -> R {
|
||||||
|
f(&*self.0.entry(id).or_default().borrow())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_guild<R>(&self, id: Id<GuildMarker>, f: impl FnOnce(&mut VCsInGuild) -> R) -> R {
|
||||||
|
let mut ret_opt = None;
|
||||||
|
self.0.entry(id).or_default().send_modify(|guild_vcs| {
|
||||||
|
let ret = f(guild_vcs);
|
||||||
|
_ = ret_opt.insert(ret);
|
||||||
|
});
|
||||||
|
let ret = ret_opt.unwrap();
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subscribe_to_guild<R>(&self, id: Id<GuildMarker>) -> watch::Receiver<VCsInGuild> {
|
||||||
|
self.0.entry(id).or_default().subscribe()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(discord_client), ret)]
|
#[tracing::instrument(skip(discord_client), ret)]
|
||||||
async fn initialize_user_in_vc(
|
async fn initialize_user_in_vc(
|
||||||
@@ -107,9 +138,9 @@ pub fn update_vcs(voice_state_update: &VoiceStateUpdate, vcs: &VCs) {
|
|||||||
.build();
|
.build();
|
||||||
let user_in_vc_data = voice_status.into();
|
let user_in_vc_data = voice_status.into();
|
||||||
|
|
||||||
vcs.entry(guild_id)
|
vcs.update_guild(guild_id, |guild_vcs| {
|
||||||
.or_default()
|
guild_vcs.insert(channel_id, user_id, user_in_vc_data)
|
||||||
.insert(channel_id, user_id, user_in_vc_data);
|
});
|
||||||
|
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
?guild_id,
|
?guild_id,
|
||||||
@@ -120,9 +151,7 @@ pub fn update_vcs(voice_state_update: &VoiceStateUpdate, vcs: &VCs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
None => {
|
None => {
|
||||||
if let Some(mut channel_vcers) = vcs.get_mut(&guild_id) {
|
vcs.update_guild(guild_id, |guild_vcs| guild_vcs.remove_right(&user_id));
|
||||||
channel_vcers.remove_right(&user_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
tracing::info!(?guild_id, ?user_id, "disconnected");
|
tracing::info!(?guild_id, ?user_id, "disconnected");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user