diff options
| author | Nathan Perry <np@nathanperry.dev> | 2024-05-08 14:15:42 -0400 |
|---|---|---|
| committer | Nathan Perry <np@nathanperry.dev> | 2024-05-08 14:16:01 -0400 |
| commit | 47817c4166937af24041a93e56ad9f841bf1e8f1 (patch) | |
| tree | a8ec0a674a5a4e5046e1bc92c1c317a48b5e4815 | |
| parent | ffba60b278162707bc4eb004c3bfb6b2e9595213 (diff) | |
fixups: memes working
| -rw-r--r-- | Cargo.lock | 166 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/bot.rs | 77 | ||||
| -rw-r--r-- | src/commands/meme/create.rs | 6 | ||||
| -rw-r--r-- | src/commands/meme/history.rs | 124 | ||||
| -rw-r--r-- | src/commands/meme/mod.rs | 10 | ||||
| -rw-r--r-- | src/commands/mod.rs | 3 | ||||
| -rw-r--r-- | src/commands/playback.rs | 6 | ||||
| -rw-r--r-- | src/config.rs | 2 | ||||
| -rw-r--r-- | src/game.rs | 138 | ||||
| -rw-r--r-- | src/util.rs | 9 |
11 files changed, 377 insertions, 165 deletions
@@ -510,6 +510,12 @@ dependencies = [ ] [[package]] +name = "extended" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" + +[[package]] name = "fallible-iterator" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2420,11 +2426,99 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "815c942ae7ee74737bb00f965fa5b5a2ac2ce7b6c01c0cc169bbeaf7abd5f5a9" dependencies = [ "lazy_static", + "symphonia-bundle-flac", + "symphonia-bundle-mp3", + "symphonia-codec-aac", + "symphonia-codec-adpcm", + "symphonia-codec-alac", + "symphonia-codec-pcm", + "symphonia-codec-vorbis", + "symphonia-core", + "symphonia-format-caf", + "symphonia-format-isomp4", + "symphonia-format-mkv", + "symphonia-format-ogg", + "symphonia-format-riff", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-bundle-flac" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72e34f34298a7308d4397a6c7fbf5b84c5d491231ce3dd379707ba673ab3bd97" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-bundle-mp3" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c01c2aae70f0f1fb096b6f0ff112a930b1fb3626178fba3ae68b09dce71706d4" +dependencies = [ + "lazy_static", + "log", "symphonia-core", "symphonia-metadata", ] [[package]] +name = "symphonia-codec-aac" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdbf25b545ad0d3ee3e891ea643ad115aff4ca92f6aec472086b957a58522f70" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-adpcm" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c94e1feac3327cd616e973d5be69ad36b3945f16b06f19c6773fc3ac0b426a0f" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-alac" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d8a6666649a08412906476a8b0efd9b9733e241180189e9f92b09c08d0e38f3" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-pcm" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f395a67057c2ebc5e84d7bb1be71cce1a7ba99f64e0f0f0e303a03f79116f89b" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-vorbis" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a98765fb46a0a6732b007f7e2870c2129b6f78d87db7987e6533c8f164a9f30" +dependencies = [ + "log", + "symphonia-core", + "symphonia-utils-xiph", +] + +[[package]] name = "symphonia-core" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2438,6 +2532,67 @@ dependencies = [ ] [[package]] +name = "symphonia-format-caf" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e43c99c696a388295a29fe71b133079f5d8b18041cf734c5459c35ad9097af50" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-format-isomp4" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abfdf178d697e50ce1e5d9b982ba1b94c47218e03ec35022d9f0e071a16dc844" +dependencies = [ + "encoding_rs", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-mkv" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb43471a100f7882dc9937395bd5ebee8329298e766250b15b3875652fe3d6f" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-ogg" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ada3505789516bcf00fc1157c67729eded428b455c27ca370e41f4d785bfa931" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-riff" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f7be232f962f937f4b7115cbe62c330929345434c834359425e043bfd15f50" +dependencies = [ + "extended", + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] name = "symphonia-metadata" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2450,6 +2605,16 @@ dependencies = [ ] [[package]] +name = "symphonia-utils-xiph" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "484472580fa49991afda5f6550ece662237b00c6f562c7d9638d1b086ed010fe" +dependencies = [ + "symphonia-core", + "symphonia-metadata", +] + +[[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2577,6 +2742,7 @@ dependencies = [ "sha1", "songbird", "statrs", + "symphonia", "tap", "thiserror", "time", @@ -43,6 +43,7 @@ envconfig_derive = "0.10" tap = "1.0" songbird = { version = "0.4", features = ["builtin-queue"] } tokio = { version = "1.37", features = ["full"]} +symphonia = { version = "0.5", features = ["all"]} [dependencies.serenity] version = "0.12" @@ -5,7 +5,7 @@ use std::{ pin::Pin, result::Result as StdResult, str::FromStr, - sync::Mutex, + sync::Arc, }; use chrono::Datelike; @@ -26,6 +26,7 @@ use serenity::{ GuildId, ReactionType, }, + async_trait, framework::{ standard::{ BucketBuilder, @@ -45,7 +46,15 @@ use serenity::{ }, prelude::*, }; -use songbird::SerenityInit; +use songbird::{ + Call, + CoreEvent, + Event, + EventContext, + SerenityInit, + TrackEvent, +}; +use tokio::sync::Mutex; use crate::{ commands::register_commands, @@ -82,14 +91,20 @@ impl EventHandler for Handler { #[cfg(not(debug_assertions))] let botname = "thulani"; - use serenity::futures::StreamExt; - serenity::futures::stream::iter(guild.iter()) - .for_each(|g| async move { - if let Err(e) = g.id.edit_nickname(&ctx, Some(botname)).await { - error!("changing nickname: {:?}", e); - } - }) - .await; + if let Some(guild) = guild { + if let Err(e) = guild.id.edit_nickname(&ctx, Some(botname)).await { + error!("changing nickname: {:?}", e); + } + } + + let sb = songbird::get(&ctx).await.unwrap(); + + let c = sb.get_or_insert(CONFIG.discord.guild()); + let mut call = c.lock().await; + + call.remove_all_global_events(); + + call.add_global_event(Event::Track(TrackEvent::End), SongbirdHandler(c.clone())); } async fn resume(&self, _ctx: Context, _resume: ResumedEvent) { @@ -103,7 +118,21 @@ impl EventHandler for Handler { deleted_message_id: MessageId, _: Option<GuildId>, ) { - MESSAGE_WATCH.lock().unwrap().remove(&deleted_message_id); + MESSAGE_WATCH.lock().await.remove(&deleted_message_id); + } +} + +struct SongbirdHandler(Arc<Mutex<Call>>); + +#[async_trait] +impl songbird::events::EventHandler for SongbirdHandler { + async fn act(&self, _ctx: &EventContext<'_>) -> Option<Event> { + let mut call = self.0.lock().await; + if call.queue().is_empty() { + let _ = call.leave().await; + } + + None } } @@ -162,11 +191,11 @@ async fn framework() -> StandardFramework { register_commands(framework) } -fn before_handle( - ctx: &Context, - message: &Message, - cmd: &str, -) -> Pin<Box<dyn Future<Output = bool> + Send>> { +fn before_handle<'fut>( + ctx: &'fut Context, + message: &'fut Message, + cmd: &'fut str, +) -> Pin<Box<dyn Future<Output = bool> + Send + 'fut>> { debug!("got command '{}' from user '{}' ({})", cmd, message.author.name, message.author.id); Box::pin(async move { @@ -206,7 +235,7 @@ fn before_handle( match util::send_result(ctx, message.channel_id, "no", message.tts).await { Err(e) => error!("sending restricted prefix response: {}", e), Ok(msg_id) => { - let mut mp = MESSAGE_WATCH.lock().unwrap(); + let mut mp = MESSAGE_WATCH.lock().await; mp.insert(message.id, msg_id); }, } @@ -257,15 +286,13 @@ pub async fn run() -> Result<()> { let shard_manager = client.shard_manager.clone(); - ctrlc::set_handler(move || { - info!("shutting down"); + tokio::spawn(async move { + tokio::signal::ctrl_c().await.unwrap(); + warn!("got ctrl c"); - let shard_manager = shard_manager.clone(); - tokio::task::spawn(async move { - shard_manager.shutdown_all().await; - }); - }) - .expect("unable to create SIGINT/SIGTERM handlers"); + shard_manager.shutdown_all().await; + info!("shutdown"); + }); client.start().await?; diff --git a/src/commands/meme/create.rs b/src/commands/meme/create.rs index 1c12f2a..ef6090e 100644 --- a/src/commands/meme/create.rs +++ b/src/commands/meme/create.rs @@ -110,6 +110,8 @@ pub async fn addmeme(ctx: &Context, msg: &Message, args: Args) -> CommandResult #[command] pub async fn addaudiomeme(ctx: &Context, msg: &Message, args: Args) -> CommandResult { + debug!("running addaudiomeme"); + let mut args = Args::new(args.rest(), DELIMS.as_ref()); let title = args.single_quoted::<String>()?; @@ -117,7 +119,7 @@ pub async fn addaudiomeme(ctx: &Context, msg: &Message, args: Args) -> CommandRe let elems = audio_str.split_whitespace().collect::<Vec<_>>(); - if elems.len() == 0 { + if elems.is_empty() { util::send(ctx, msg.channel_id, "are you stupid", msg.tts).await?; return Err(anyhow!("no audio link was provided").into()); } @@ -127,6 +129,7 @@ pub async fn addaudiomeme(ctx: &Context, msg: &Message, args: Args) -> CommandRe let (start, end) = parse_times(opts); let youtube_url = util::ytdl_url(audio_link.as_str()).await?; + debug!("got download url: {youtube_url}"); let duration_opts = if let Some(e) = end { vec![ @@ -184,6 +187,7 @@ pub async fn addaudiomeme(ctx: &Context, msg: &Message, args: Args) -> CommandRe let mut audio_data = Vec::new(); let bytes = audio_reader.read_to_end(&mut audio_data).await?; + debug!("downloaded audio ({} bytes)", audio_data.len()); if bytes == 0 { debug!("read 0 bytes from audio reader"); diff --git a/src/commands/meme/history.rs b/src/commands/meme/history.rs index ed50e27..33a2de2 100644 --- a/src/commands/meme/history.rs +++ b/src/commands/meme/history.rs @@ -2,7 +2,6 @@ use anyhow::anyhow; use diesel::{ result::Error as DieselError, NotFound, - PgConnection, }; use itertools::Itertools; use lazy_static::lazy_static; @@ -115,8 +114,6 @@ pub async fn wat(ctx: &Context, msg: &Message, _: Args) -> CommandResult { #[command] pub async fn history(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { - let mut conn = connection()?; - let n = args.single_quoted::<usize>().unwrap_or(CONFIG.default_hist); if n > CONFIG.max_hist { @@ -126,7 +123,10 @@ pub async fn history(ctx: &Context, msg: &Message, mut args: Args) -> CommandRes let n = n.min(CONFIG.max_hist); - let records = InvocationRecord::last_n(&mut conn, n)?; + let records = { + let mut conn = connection()?; + InvocationRecord::last_n(&mut conn, n)? + }; if records.len() == 0 { info!("no memes in history"); @@ -138,74 +138,70 @@ pub async fn history(ctx: &Context, msg: &Message, mut args: Args) -> CommandRes info!("reporting meme history (len {})", n); let resp = serenity::futures::stream::iter(records.into_iter().enumerate().rev()) - .then(|(i, rec)| ir_info(ctx, i, rec, &mut conn)) - .try_collect::<Vec<String>>() - .await?; - - let resp = resp.join("\n"); - - util::send(ctx, msg.channel_id, &resp, false).await.map_err(CommandError::from) -} + .then(|(i, rec)| async move { + let mut conn = connection()?; -async fn ir_info( - ctx: &Context, - i: usize, - rec: InvocationRecord, - conn: &mut PgConnection, -) -> Result<String, CommandError> { - let dt = chrono::DateTime::from_utc(rec.time, chrono::Utc {}); - let ago = TIME_FORMATTER.convert((chrono::Utc::now() - dt).to_std().unwrap()); - - let rand = if rec.random { - "R, " - } else { - "" - }; + let dt = chrono::DateTime::from_utc(rec.time, chrono::Utc {}); + let ago = TIME_FORMATTER.convert((chrono::Utc::now() - dt).to_std().unwrap()); - let meme = Meme::find(conn, rec.meme_id) - .and_then(|meme| Metadata::find(conn, meme.metadata_id).map(|metadata| (metadata, meme))); + let rand = if rec.random { + "R, " + } else { + "" + }; - let invoker_name = CONFIG - .discord - .guild() - .member(&ctx, rec.user_id as u64) - .await - .map(|m| m.display_name().to_owned()) - .unwrap_or("???".to_owned()); + let meme = Meme::find(&mut conn, rec.meme_id).and_then(|meme| { + Metadata::find(&mut conn, meme.metadata_id).map(|metadata| (metadata, meme)) + }); - let result = match meme { - Ok((metadata, meme)) => { - let author_name = CONFIG + let invoker_name = CONFIG .discord .guild() - .member(&ctx, metadata.created_by as u64) + .member(&ctx, rec.user_id as u64) .await .map(|m| m.display_name().to_owned()) .unwrap_or("???".to_owned()); - format!( - "{}. [{}{}] \"{}\" by {} ({}). invoked by {}.", - i + 1, - rand, - ago, - meme.title, - author_name, - metadata.created.date().format(CLEAN_DATE_FORMAT), - invoker_name - ) - }, - Err(e) => { - if let Some(variant) = e.downcast_ref::<DieselError>() { - if *variant != NotFound { - error!("error encountered loading meme history: {}", e); - } - } + let result = match meme { + Ok((metadata, meme)) => { + let author_name = CONFIG + .discord + .guild() + .member(&ctx, metadata.created_by as u64) + .await + .map(|m| m.display_name().to_owned()) + .unwrap_or("???".to_owned()); - format!("{}. [{}{}] not found. invoked by {}.", i + 1, rand, ago, invoker_name) - }, - }; + format!( + "{}. [{}{}] \"{}\" by {} ({}). invoked by {}.", + i + 1, + rand, + ago, + meme.title, + author_name, + metadata.created.date().format(CLEAN_DATE_FORMAT), + invoker_name + ) + }, + Err(e) => { + if let Some(variant) = e.downcast_ref::<DieselError>() { + if *variant != NotFound { + error!("error encountered loading meme history: {}", e); + } + } + + format!("{}. [{}{}] not found. invoked by {}.", i + 1, rand, ago, invoker_name) + }, + }; - Ok(result) + Result::<_, CommandError>::Ok(result) + }) + .try_collect::<Vec<String>>() + .await?; + + let resp = resp.join("\n"); + + util::send(ctx, msg.channel_id, &resp, false).await.map_err(CommandError::from) } #[command] @@ -328,12 +324,12 @@ pub async fn query(ctx: &Context, msg: &Message, mut args: Args) -> CommandResul static ref AGE_REGEX: Regex = Regex::new(r"(?i)(?:age|order)=(.*)").unwrap(); } - let guild = - msg.channel_id.to_channel(&ctx).await?.guild().ok_or(anyhow!("couldn't find guild"))?; + let creator: Option<u64> = { + let guild = + msg.channel_id.to_channel(&ctx).await?.guild().ok_or(anyhow!("couldn't find guild"))?; - let guild = guild.guild(&ctx).ok_or(anyhow!("couldn't find guild"))?; + let guild = guild.guild(&ctx).ok_or(anyhow!("couldn't find guild"))?; - let creator: Option<u64> = { let creator = args.quoted().current().map(|s| CREATOR_REGEX.is_match(s)).unwrap_or(false); if creator { args.single_quoted::<String>() diff --git a/src/commands/meme/mod.rs b/src/commands/meme/mod.rs index 24fc50d..fe69b1c 100644 --- a/src/commands/meme/mod.rs +++ b/src/commands/meme/mod.rs @@ -16,7 +16,10 @@ use serenity::{ prelude::*, }; use songbird::input::{ - core::io::MediaSource, + core::{ + io::MediaSource, + probe::Hint, + }, AudioStream, AudioStreamError, Compose, @@ -127,9 +130,12 @@ impl Compose for Audio { let ms = std::io::Cursor::new(self.data.clone()); let ms: Box<dyn MediaSource> = Box::new(ms); + let mut hint = Hint::new(); + hint.mime_type("audio/opus"); + Ok(AudioStream { input: ms, - hint: None, + hint: Some(hint), }) } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index c8a7014..3f69a3b 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -21,7 +21,6 @@ pub(crate) mod today; mod help; #[group] -#[prefix = ""] #[only_in(guild)] #[commands(roll, today)] struct General; @@ -52,7 +51,7 @@ pub fn register_commands(f: StandardFramework) -> StandardFramework { }, }; - let _ = _play(ctx, msg, &url); + let _ = _play(ctx, msg, url).await; }) }) } diff --git a/src/commands/playback.rs b/src/commands/playback.rs index 7ecef47..1c3ab95 100644 --- a/src/commands/playback.rs +++ b/src/commands/playback.rs @@ -110,7 +110,7 @@ pub async fn _play(ctx: &Context, msg: &Message, url: &str) -> CommandResult { #[command] pub async fn play(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { - if args.len() == 0 { + if args.is_empty() { return _resume(ctx, msg).await; } @@ -168,9 +168,11 @@ pub async fn skip(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { pub async fn die(ctx: &Context, msg: &Message, _: Args) -> CommandResult { let (_sb, call) = songbird(ctx, msg).await?; - let call = call.lock().await; + let mut call = call.lock().await; call.queue().stop(); + call.leave().await?; + Ok(()) } diff --git a/src/config.rs b/src/config.rs index 59bb4c3..84ee88b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -17,7 +17,7 @@ lazy_static! { Config::init_from_env().unwrap() }; pub static ref FFMPEG_COMMAND: String = { - let result = CONFIG.ffmpeg.clone().unwrap_or("youtube-dl".to_owned()); + let result = CONFIG.ffmpeg.clone().unwrap_or("ffmpeg".to_owned()); log::debug!("got ffmpeg: {}", result); result diff --git a/src/game.rs b/src/game.rs index 47ae18c..d3b0785 100644 --- a/src/game.rs +++ b/src/game.rs @@ -55,7 +55,6 @@ use crate::{ }; #[group] -#[prefix = "game"] #[commands(game, installedgame, ownedgame, updategaem)] pub struct Game; @@ -234,80 +233,85 @@ async fn _game( mut args: Args, min_status: GameStatus, ) -> CommandResult { - let guild = - msg.channel_id.to_channel(&ctx).await?.guild().ok_or(anyhow!("couldn't find guild"))?; - let guild = guild.guild(&ctx).ok_or_else(|| anyhow!("couldn't find guild"))?; + let users = { + let guild = + msg.channel_id.to_channel(&ctx).await?.guild().ok_or(anyhow!("couldn't find guild"))?; + let guild = guild.guild(&ctx).ok_or_else(|| anyhow!("couldn't find guild"))?; - let user_args: Vec<String> = if args.rest().is_empty() { - Vec::new() - } else { - args.quoted().iter::<String>().collect::<StdResult<Vec<_>, ArgError<Infallible>>>()? - }; + let user_args: Vec<String> = if args.rest().is_empty() { + Vec::new() + } else { + args.quoted().iter::<String>().collect::<StdResult<Vec<_>, ArgError<Infallible>>>()? + }; - let mut users = user_args - .into_iter() - .filter_map(|u| { - use std::borrow::Borrow; + let mut users = user_args + .into_iter() + .filter_map(|u| { + use std::borrow::Borrow; - let possible = get_user_id(guild.borrow(), &u); + let possible = get_user_id(guild.borrow(), &u); - debug!("parsed userid {:?}", possible); + debug!("parsed userid {:?}", possible); - match possible { - Err(UserLookupError::NotFound) => { - let _ = util::send( - ctx, - msg.channel_id, - &format!("didn't recognize {}", &u), - msg.tts, - ); - None - }, - Ok(x) => Some(x), - Err(UserLookupError::Ambiguous(x)) => { - let _ = util::send( - ctx, - msg.channel_id, - &format!("too many matches ({}) for {}", x, &u), - msg.tts, - ); - None - }, - } - }) - .filter_map(|uid| { - let res = DISCORD_MAP.get(&uid).map(|s| s.to_lowercase()); + match possible { + Err(UserLookupError::NotFound) => { + let _ = util::send( + ctx, + msg.channel_id, + &format!("didn't recognize {}", &u), + msg.tts, + ); + None + }, + Ok(x) => Some(x), + Err(UserLookupError::Ambiguous(x)) => { + let _ = util::send( + ctx, + msg.channel_id, + &format!("too many matches ({}) for {}", x, &u), + msg.tts, + ); + None + }, + } + }) + .filter_map(|uid| { + let res = DISCORD_MAP.get(&uid).map(|s| s.to_lowercase()); - if let None = res { - let _ = info!("user {} is not recognized", uid); - } + if let None = res { + let _ = info!("user {} is not recognized", uid); + } - res - }) - .collect::<FnvHashSet<_>>(); + res + }) + .collect::<FnvHashSet<_>>(); - let inferred = users.len() == 0; + if users.len() == 0 { + let pairs = guild + .voice_states + .iter() + .filter_map(|(uid, voice)| voice.channel_id.map(|cid| (*uid, cid))) + .collect::<FnvHashMap<_, _>>(); - if users.len() == 0 { - let pairs = guild - .voice_states - .iter() - .filter_map(|(uid, voice)| voice.channel_id.map(|cid| (*uid, cid))) - .collect::<FnvHashMap<_, _>>(); + let channel = + pairs.get(&msg.author.id).cloned().unwrap_or(CONFIG.discord.voice_channel()); - let channel = pairs.get(&msg.author.id).cloned().unwrap_or(CONFIG.discord.voice_channel()); + users = pairs + .iter() + .filter_map(|(uid, cid)| { + if *cid == channel { + DISCORD_MAP.get(uid).map(|s| s.to_lowercase()) + } else { + None + } + }) + .collect::<FnvHashSet<_>>(); + } - users = pairs - .iter() - .filter_map(|(uid, cid)| { - if *cid == channel { - DISCORD_MAP.get(uid).map(|s| s.to_lowercase()) - } else { - None - } - }) - .collect::<FnvHashSet<_>>(); - } + users + }; + + let inferred = users.len() == 0; if inferred && users.len() < 2 || !inferred && users.len() < 1 { info!("too few known users to make game comparison"); @@ -434,7 +438,7 @@ pub async fn updategaem(ctx: &Context, msg: &Message, mut args: Args) -> Command let client = { let data = ctx.data.read().await; - data.get::<HttpKey>().unwrap() + data.get::<HttpKey>().unwrap().clone() }; let arg_user = args.single_quoted::<String>(); @@ -472,7 +476,7 @@ pub async fn updategaem(ctx: &Context, msg: &Message, mut args: Args) -> Command }, }; - let spreadsheet = load_spreadsheet(client).await?; + let spreadsheet = load_spreadsheet(&client).await?; let user_column = (0..spreadsheet.len()) .find(|x| spreadsheet[*x][0].to_lowercase() == username.to_lowercase()); @@ -537,7 +541,7 @@ pub async fn updategaem(ctx: &Context, msg: &Message, mut args: Args) -> Command let client = { let data = ctx.data.read().await; - data.get::<HttpKey>().unwrap() + data.get::<HttpKey>().unwrap().clone() }; let games_owned = client diff --git a/src/util.rs b/src/util.rs index d59c4da..0fd746b 100644 --- a/src/util.rs +++ b/src/util.rs @@ -120,7 +120,14 @@ pub async fn ytdl_url(uri: &str) -> Result<String> { uri,
];
- let out = Command::new(&*YTDL_COMMAND).args(&args).stdin(Stdio::null()).output().await?;
+ debug!("downloading info for uri: {uri}");
+
+ let mut command = Command::new(&*YTDL_COMMAND);
+ command.args(&args).stdin(Stdio::null());
+
+ debug!("running command: {command:?}");
+
+ let out = command.output().await?;
if !out.status.success() {
return Err(anyhow::anyhow!("running ytdl: {out:?}"));
|
