feat: update to songbird 0.6, make joining calls work by spawning everything as required in songbird's documentation

This commit is contained in:
2026-04-07 23:08:20 -04:00
parent 1bd8b9b203
commit 288a784870
6 changed files with 1059 additions and 48 deletions

View File

@@ -82,7 +82,7 @@ fn get_guild_and_channel_id(
Ok((guild_id, channel_id))
}
#[tracing::instrument]
#[tracing::instrument(skip(state))]
pub async fn handle(state: State, interaction: Interaction) {
let vcs = state.vcs;
@@ -126,13 +126,22 @@ pub async fn handle(state: State, interaction: Interaction) {
.await
.expect("TODO");
let call = tokio::spawn({
let songbird = state.songbird.clone();
async move { songbird.join(guild_id, channel_id).await }
})
.await
.unwrap()
.expect("TODO");
let call = loop {
tracing::error!("TODO: about to try joining");
match state.songbird.join(guild_id, channel_id).await {
Ok(call) => break call,
Err(error) => {
tracing::error!(?error, "I'm still here");
if error.should_leave_server() {
state.songbird.leave(guild_id).await.expect("TODO");
} else if error.should_reconnect_driver() {
todo!();
}
}
}
};
let channel_mention = format!("<#{channel_id}>");
@@ -150,4 +159,5 @@ pub async fn handle(state: State, interaction: Interaction) {
tracing::error!(?call, "TODO");
let call_guard = call.lock().await;
tracing::error!(?call_guard, "TODO");
}

View File

@@ -23,12 +23,12 @@ pub struct State {
}
type Return = ();
type BoxedHandler = Box<dyn Fn(State, Interaction) -> BoxFuture<'static, Return>>;
type BoxedHandler = Box<dyn Send + Sync + Fn(State, Interaction) -> BoxFuture<'static, Return>>;
fn box_handler<Handler, Fut>(handler: Handler) -> BoxedHandler
where
Fut: Future<Output = Return> + Send + 'static,
Handler: Fn(State, Interaction) -> Fut + 'static,
Handler: Send + Sync + Fn(State, Interaction) -> Fut + 'static,
{
Box::new(move |state, interaction| Box::pin(handler(state, interaction)))
}
@@ -50,7 +50,7 @@ impl Router {
fn add_route<Fut, Handler>(&mut self, name: &str, handler: Handler)
where
Fut: Future<Output = Return> + Send + 'static,
Handler: Fn(State, Interaction) -> Fut + 'static,
Handler: Send + Sync + Fn(State, Interaction) -> Fut + 'static,
{
self.add_route_already_boxed(name, box_handler(handler));
}

View File

@@ -170,6 +170,7 @@ async fn main() -> Result<(), MainError> {
.expect("failed to deserialize set commands"); // TODO
let command_router = CommandRouter::from_iter(commands);
let command_router = Arc::new(command_router);
let vcs = initialize_vcs(&discord_client).await;
@@ -187,7 +188,7 @@ async fn main() -> Result<(), MainError> {
while let Some(event_res) = next_event.await {
match event_res {
Ok(event) => {
handle_event(&command_router, state.clone(), event).await;
handle_event(command_router.clone(), state.clone(), event).await;
}
Err(error) => {
tracing::error!(?error);
@@ -201,7 +202,7 @@ async fn main() -> Result<(), MainError> {
}
#[tracing::instrument(skip(command_router))]
async fn handle_event(command_router: &CommandRouter, state: State, event: Event) {
async fn handle_event(command_router: Arc<CommandRouter>, state: State, event: Event) {
state.songbird.process(&event).await;
match event {
Event::VoiceStateUpdate(voice_state_update) => {
@@ -215,10 +216,12 @@ async fn handle_event(command_router: &CommandRouter, state: State, event: Event
tracing::warn!("missing expected interaction data");
}
Some(InteractionData::ApplicationCommand(command_data)) => {
let command_name = &command_data.name.clone();
command_router
.handle(state, command_name, interaction)
.await;
let command_name = command_data.name.clone();
tokio::spawn(async move {
command_router
.handle(state, &command_name, interaction)
.await;
});
}
Some(InteractionData::MessageComponent(component_data)) => {

View File

@@ -87,6 +87,7 @@ pub async fn initialize_vcs(discord_client: &twilight_http::Client) -> VCs {
}
}
#[tracing::instrument(skip(vcs))]
pub fn update_vcs(voice_state_update: &VoiceStateUpdate, vcs: &VCs) {
let user_id = voice_state_update.user_id;
match voice_state_update.guild_id {