feat: ability to join call with user

This commit is contained in:
2026-04-02 15:38:05 -04:00
parent 7f569629db
commit 663586a65c
3 changed files with 57 additions and 24 deletions

View File

@@ -1,10 +1,10 @@
use clap::Parser;
use fomo_reducer::{CommandRouter, State, VCs, all_commands, initialize_vcs, update_vcs};
use fomo_reducer::{CommandRouter, State, all_commands, initialize_vcs, update_vcs};
use opendal::{IntoOperatorUri, Operator, OperatorUri};
use secrecy::{ExposeSecret, SecretString};
use snafu::Snafu;
use songbird::shards::TwilightMap;
use std::{collections::HashMap, fmt::Debug, str::FromStr, sync::Arc};
use songbird::{Songbird, shards::TwilightMap};
use std::{fmt::Debug, str::FromStr, sync::Arc};
use tracing_subscriber::{EnvFilter, fmt::format::FmtSpan};
use twilight_gateway::{Event, EventTypeFlags, Intents, Shard, ShardId, StreamExt};
use twilight_model::{
@@ -62,7 +62,11 @@ struct AppArgs {
#[derive(Parser)]
struct LoggingArgs {
#[arg(long = "logging-directives", env = "RUST_LOG", default_value = "warn,fomo_reducer=debug")]
#[arg(
long = "logging-directives",
env = "RUST_LOG",
default_value = "warn,fomo_reducer=debug"
)]
env_filter: EnvFilter,
}
@@ -106,20 +110,18 @@ async fn main() -> Result<(), MainError> {
.install_default()
.unwrap();
let shard_id = ShardId::new(0, 1);
let intents = Intents::GUILD_VOICE_STATES;
let mut shard = Shard::new(shard_id, discord_token.expose_secret().to_owned(), intents);
let senders = TwilightMap::new(FromIterator::from_iter([(
shard.id().number(),
shard.sender(),
)]));
let event_types = EventTypeFlags::GUILD_VOICE_STATES | EventTypeFlags::INTERACTION_CREATE;
let mut next_event = shard.next_event(event_types);
let discord_client = twilight_http::Client::new(discord_token.expose_secret().to_owned());
let user = discord_client
.current_user()
.await
.expect("couldn't fetch current user") // TODO
.model()
.await
.expect("couldn't deserialize current user"); // TODO
let user_id = user.id;
let current_application = discord_client
.current_user_application()
.await
@@ -132,6 +134,22 @@ async fn main() -> Result<(), MainError> {
let application_id = current_application.id;
let shard_id = ShardId::new(0, 1);
let intents = Intents::GUILD_VOICE_STATES;
let mut shard = Shard::new(shard_id, discord_token.expose_secret().to_owned(), intents);
let senders = TwilightMap::new(FromIterator::from_iter([(
shard.id().number(),
shard.sender(),
)]));
let senders = Arc::new(senders);
let songbird = Songbird::twilight(senders, user_id);
let event_types = EventTypeFlags::GUILD_VOICE_STATES | EventTypeFlags::INTERACTION_CREATE;
let mut next_event = shard.next_event(event_types);
let interaction_client = discord_client.interaction(application_id);
let commands = all_commands();
@@ -155,12 +173,15 @@ async fn main() -> Result<(), MainError> {
let vcs = initialize_vcs(&discord_client).await;
let vcs = Arc::new(vcs);
let songbird = Arc::new(songbird);
let state = State { vcs, songbird };
while let Some(event_res) = next_event.await {
match event_res {
Ok(event) => {
tracing::debug!(?vcs, "before handling");
handle_event(&command_router, vcs.clone(), event).await;
tracing::debug!(?vcs, "after handling");
handle_event(&command_router, state.clone(), event).await;
}
Err(error) => {
tracing::error!(?error);
@@ -173,11 +194,12 @@ async fn main() -> Result<(), MainError> {
Ok(())
}
#[tracing::instrument(skip(command_router, vcs))]
async fn handle_event(command_router: &CommandRouter, vcs: Arc<VCs>, event: Event) {
#[tracing::instrument(skip(command_router))]
async fn handle_event(command_router: &CommandRouter, state: State, event: Event) {
state.songbird.process(&event).await;
match event {
Event::VoiceStateUpdate(voice_state_update) => {
update_vcs(&voice_state_update, &vcs);
update_vcs(&voice_state_update, &state.vcs);
}
Event::InteractionCreate(interaction_create) => {
let InteractionCreate(interaction) = *interaction_create;
@@ -188,7 +210,6 @@ async fn handle_event(command_router: &CommandRouter, vcs: Arc<VCs>, event: Even
}
Some(InteractionData::ApplicationCommand(command_data)) => {
let command_name = &command_data.name.clone();
let state = State { vcs };
command_router
.handle(state, command_name, interaction)
.await;