feat: don't block bot startup waiting to initialize vcs

This commit is contained in:
2026-05-31 14:24:09 -04:00
parent f5b6dc5c76
commit 5e989289bd
2 changed files with 38 additions and 44 deletions

View File

@@ -285,14 +285,14 @@ async fn main() -> Result<(), MainError> {
let discord_opt_in_command_name = discord_opt_in_command.name.into(); let discord_opt_in_command_name = discord_opt_in_command.name.into();
let discord_opt_out_command_name = discord_opt_out_command.name.into(); let discord_opt_out_command_name = discord_opt_out_command.name.into();
let vcs = initialize_vcs(&discord_client).await;
let command_router = CommandRouter::from_iter(commands); let command_router = CommandRouter::from_iter(commands);
let command_router = Arc::new(command_router); let command_router = Arc::new(command_router);
let discord_client = Arc::new(discord_client); let discord_client = Arc::new(discord_client);
let songbird = Arc::new(songbird); let songbird = Arc::new(songbird);
let vcs_sender = VCsSender::new(vcs); let vcs_sender = VCsSender::new(Default::default());
let initializing_vcs = initialize_vcs(&vcs_sender, &discord_client);
let bot_data = bot_data.into_inner(); let bot_data = bot_data.into_inner();
let recording_data = recording_data.into_inner(); let recording_data = recording_data.into_inner();
@@ -327,7 +327,7 @@ async fn main() -> Result<(), MainError> {
cancellation_token: cancellation_token.clone(), cancellation_token: cancellation_token.clone(),
discord_application_id, discord_application_id,
discord_bot_owner_user_id, discord_bot_owner_user_id,
discord_client, discord_client: discord_client.clone(),
discord_info_command_id, discord_info_command_id,
discord_info_command_name, discord_info_command_name,
discord_opt_in_command_id, discord_opt_in_command_id,
@@ -340,7 +340,7 @@ async fn main() -> Result<(), MainError> {
render_manager, render_manager,
songbird, songbird,
user_manager, user_manager,
vcs_sender, vcs_sender: vcs_sender.clone(),
}; };
let heat_seeking = tokio::spawn(heat_seek(state.clone())); let heat_seeking = tokio::spawn(heat_seek(state.clone()));
@@ -394,6 +394,7 @@ async fn main() -> Result<(), MainError> {
}); });
let finished_naturally = async move { let finished_naturally = async move {
initializing_vcs.await;
heat_seeking.await.unwrap(); heat_seeking.await.unwrap();
run_shards.await; run_shards.await;
}; };

View File

@@ -20,76 +20,69 @@ pub type VCsInGuild =
pub type VCs = BTreeMap<Id<GuildMarker>, VCsInGuild>; pub type VCs = BTreeMap<Id<GuildMarker>, VCsInGuild>;
pub type VCsSender = watch::Sender<VCs>; pub type VCsSender = watch::Sender<VCs>;
#[tracing::instrument(skip(discord_client), ret)] #[tracing::instrument(skip(vcs_sender, discord_client))]
async fn initialize_user_in_vc( async fn initialize_user_in_vc(
vcs_sender: &VCsSender,
discord_client: &twilight_http::Client, discord_client: &twilight_http::Client,
guild_id: Id<GuildMarker>, guild_id: Id<GuildMarker>,
user_id: Id<UserMarker>, user_id: Id<UserMarker>,
) -> Option<(Id<ChannelMarker>, UserInVCData)> { ) {
if let Ok(voice_state_res) = discord_client.user_voice_state(guild_id, user_id).await if let Ok(voice_state_res) = discord_client.user_voice_state(guild_id, user_id).await
&& let Ok(voice_state) = voice_state_res.model().await && let Ok(voice_state) = voice_state_res.model().await
{ {
tracing::info!(?user_id, ?voice_state); tracing::info!(?user_id, ?voice_state);
let voice_status = VoiceStatus::builder() if let Some(voice_channel_id) = voice_state.channel_id {
.self_deafened(voice_state.self_deaf) let voice_status = VoiceStatus::builder()
.self_muted(voice_state.self_mute) .self_deafened(voice_state.self_deaf)
.server_deafened(voice_state.deaf) .self_muted(voice_state.self_mute)
.server_muted(voice_state.mute) .server_deafened(voice_state.deaf)
.camming(voice_state.self_video) .server_muted(voice_state.mute)
.streaming(voice_state.self_stream) .camming(voice_state.self_video)
.build(); .streaming(voice_state.self_stream)
let user_in_vc_data = voice_status.into(); .build();
let user_in_vc_data = voice_status.into();
voice_state vcs_sender.send_modify(|vcs| {
.channel_id vcs.entry(guild_id)
.map(|channel_id| (channel_id, user_in_vc_data)) .or_default()
} else { .insert(voice_channel_id, user_id, user_in_vc_data);
None // TODO });
}
} }
} }
#[tracing::instrument(skip(discord_client), ret)] #[tracing::instrument(skip(vcs_sender, discord_client))]
async fn initialize_server_vcs( async fn initialize_server_vcs(
vcs_sender: &VCsSender,
discord_client: &twilight_http::Client, discord_client: &twilight_http::Client,
id: Id<GuildMarker>, id: Id<GuildMarker>,
) -> VCsInGuild { ) {
if let Ok(guild_members_res) = discord_client.guild_members(id).limit(999).await if let Ok(guild_members_res) = discord_client.guild_members(id).limit(999).await
&& let Ok(guild_members) = guild_members_res.model().await && let Ok(guild_members) = guild_members_res.model().await
{ {
FuturesUnordered::from_iter(guild_members.into_iter().map(|member| async move { FuturesUnordered::from_iter(
( guild_members.into_iter().map(|member| {
member.user.id, initialize_user_in_vc(vcs_sender, discord_client, id, member.user.id)
initialize_user_in_vc(discord_client, id, member.user.id).await, }),
)
}))
.filter_map(
|(user_id, channel_id_and_user_in_vc_data_option)| async move {
channel_id_and_user_in_vc_data_option
.map(|(channel_id, user_in_vc_data)| (channel_id, user_id, user_in_vc_data))
},
) )
.collect() .collect()
.await .await
} else {
Default::default()
} }
} }
#[tracing::instrument(skip(discord_client), ret)] #[tracing::instrument(skip(discord_client), ret)]
pub async fn initialize_vcs(discord_client: &twilight_http::Client) -> VCs { pub async fn initialize_vcs(vcs_sender: &VCsSender, discord_client: &twilight_http::Client) {
if let Ok(guilds_res) = discord_client.current_user_guilds().limit(200).await if let Ok(guilds_res) = discord_client.current_user_guilds().limit(200).await
&& let Ok(guilds) = guilds_res.model().await && let Ok(guilds) = guilds_res.model().await
{ {
FuturesUnordered::from_iter(guilds.into_iter().map(|guild| async move { FuturesUnordered::from_iter(
let guild_vcs = initialize_server_vcs(discord_client, guild.id).await; guilds
.into_iter()
(guild.id, guild_vcs) .map(|guild| initialize_server_vcs(vcs_sender, discord_client, guild.id)),
})) )
.collect() .collect()
.await .await
} else {
Default::default()
} }
} }