aboutsummaryrefslogtreecommitdiff
path: root/src/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/commands')
-rw-r--r--src/commands/game.rs14
-rw-r--r--src/commands/meme/history.rs33
-rw-r--r--src/commands/meme/invoke.rs23
-rw-r--r--src/commands/meme/mod.rs16
-rw-r--r--src/commands/mod.rs10
-rw-r--r--src/commands/playback.rs12
-rw-r--r--src/commands/sound_levels.rs71
-rw-r--r--src/commands/today/mod.rs7
8 files changed, 133 insertions, 53 deletions
diff --git a/src/commands/game.rs b/src/commands/game.rs
index 78c08ee..3a47b32 100644
--- a/src/commands/game.rs
+++ b/src/commands/game.rs
@@ -307,14 +307,6 @@ async fn _game(
users
};
- let inferred = users.is_empty();
-
- if inferred && users.len() < 2 || !inferred && users.is_empty() {
- tracing::info!("too few known users to make game comparison");
- util::reply(ctx, "yer too lonely").await?;
- return Ok(());
- }
-
let client = {
let data = ctx.serenity_context().data.read().await;
data.get::<HttpKey>().unwrap().clone()
@@ -333,6 +325,12 @@ async fn _game(
})
.collect::<FnvHashMap<_, _>>();
+ if user_indexes.len() < 2 {
+ tracing::info!("too few known users to make game comparison");
+ util::reply(ctx, "yer too lonely").await?;
+ return Ok(());
+ }
+
let data_ref = &data;
let user_games = user_indexes
.iter()
diff --git a/src/commands/meme/history.rs b/src/commands/meme/history.rs
index 1acb019..270ae9a 100644
--- a/src/commands/meme/history.rs
+++ b/src/commands/meme/history.rs
@@ -1,16 +1,3 @@
-use crate::{
- commands::game::get_user_id,
- db::{
- self,
- connection,
- InvocationRecord,
- Meme,
- Metadata,
- },
- util,
- PoiseContext,
- CONFIG,
-};
use chrono::TimeZone;
use diesel::{
result::Error as DieselError,
@@ -34,7 +21,20 @@ use timeago::{
Formatter,
TimeUnit,
};
-use windows::core::s;
+
+use crate::{
+ commands::game::get_user_id,
+ config::CONFIG,
+ db::{
+ self,
+ connection,
+ InvocationRecord,
+ Meme,
+ Metadata,
+ },
+ util,
+ PoiseContext,
+};
lazy_static! {
static ref TIME_FORMATTER: Formatter = {
@@ -393,10 +393,7 @@ pub async fn query(ctx: PoiseContext<'_>, rest: util::RestVec) -> anyhow::Result
use regex::Regex;
use serenity::model::id::UserId;
- use crate::{
- db,
- CONFIG,
- };
+ use crate::db;
lazy_static! {
static ref CREATOR_REGEX: Regex = Regex::new(r"(?i)(?:by|creator)=(.*)").unwrap();
diff --git a/src/commands/meme/invoke.rs b/src/commands/meme/invoke.rs
index aff5c23..4b361a3 100644
--- a/src/commands/meme/invoke.rs
+++ b/src/commands/meme/invoke.rs
@@ -1,6 +1,5 @@
use diesel::{
result::Error as DieselError,
- row::NamedRow,
NotFound,
};
use grate::tracing;
@@ -93,10 +92,10 @@ pub(crate) async fn _meme(
x.id,
false,
)
- .await?;
+ .await?;
x
- }
+ },
Err(e) => {
return if let Some(NotFound) = e.downcast_ref::<DieselError>() {
tracing::info!("requested meme not found in database");
@@ -107,7 +106,7 @@ pub(crate) async fn _meme(
util::reply(ctx, "what in ryan's name").await?;
Err(e.into())
};
- }
+ },
};
send_meme(ctx, &mem, &mut conn).await
@@ -135,15 +134,15 @@ async fn rand_meme(ctx: PoiseContext<'_>, audio_playback: AudioPlayback) -> anyh
mem.id,
true,
)
- .await?;
+ .await?;
send_meme(ctx, &mem, &mut conn).await?;
Ok(())
- }
+ },
Ok(None) => {
tracing::info!("random meme not found");
util::reply(ctx, "i don't know any :(").await?;
Ok(())
- }
+ },
Err(e) => {
if let Some(NotFound) = e.downcast_ref::<DieselError>() {
tracing::info!("random meme not found");
@@ -154,7 +153,7 @@ async fn rand_meme(ctx: PoiseContext<'_>, audio_playback: AudioPlayback) -> anyh
util::reply(ctx, "HELP").await?;
Err(e.into())
- }
+ },
}
}
@@ -177,16 +176,16 @@ pub async fn rare_meme(ctx: PoiseContext<'_>) -> anyhow::Result<()> {
meme.id,
true,
)
- .await?;
+ .await?;
send_meme(ctx, &meme, &mut conn).await
- }
+ },
Ok(None) => {
tracing::info!("rare meme not found");
util::reply(ctx, "i don't know any :(").await?;
Ok(())
- }
+ },
Err(e) => {
if let Some(NotFound) = e.downcast_ref::<DieselError>() {
@@ -199,6 +198,6 @@ pub async fn rare_meme(ctx: PoiseContext<'_>) -> anyhow::Result<()> {
util::reply(ctx, "THE MEME MARKET IS IN FREEFALL").await?;
Err(e.into())
- }
+ },
}
}
diff --git a/src/commands/meme/mod.rs b/src/commands/meme/mod.rs
index eb6aa1d..3883f3e 100644
--- a/src/commands/meme/mod.rs
+++ b/src/commands/meme/mod.rs
@@ -1,3 +1,8 @@
+use std::{
+ borrow::ToOwned,
+ default::Default,
+};
+
use diesel_async::AsyncPgConnection;
use grate::tracing;
use rand::random;
@@ -19,10 +24,6 @@ use songbird::input::{
Compose,
Input,
};
-use std::{
- borrow::ToOwned,
- default::Default,
-};
pub use self::{
create::*,
@@ -38,7 +39,6 @@ use crate::{
},
util,
PoiseContext,
- CONFIG,
};
mod create;
@@ -113,6 +113,9 @@ async fn send_meme(
return Ok(());
};
+ let volume = util::volume(ctx).await;
+ tracing::debug!(volume);
+
{
let (_sb, call) = songbird(ctx).await?;
let mut call = call.lock().await;
@@ -121,7 +124,8 @@ async fn send_meme(
call.join(voice_channel).await?;
}
- call.enqueue_input(Input::Lazy(Box::new(audio))).await;
+ let handle = call.enqueue_input(Input::Lazy(Box::new(audio))).await;
+ handle.set_volume(volume as _)?;
}
util::react(ctx, ReactionType::Unicode("📣".to_owned())).await?;
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
index 2729580..b0ef83b 100644
--- a/src/commands/mod.rs
+++ b/src/commands/mod.rs
@@ -19,8 +19,14 @@ pub(crate) mod today;
pub use self::meme::*;
pub fn commands() -> Vec<poise::Command<crate::PoiseData, anyhow::Error>> {
- let mut commands =
- vec![sound_levels::mute(), sound_levels::unmute(), roll::roll(), today::today(), help()];
+ let mut commands = vec![
+ sound_levels::mute(),
+ sound_levels::unmute(),
+ sound_levels::volume(),
+ roll::roll(),
+ today::today(),
+ help(),
+ ];
commands.extend(playback::commands());
diff --git a/src/commands/playback.rs b/src/commands/playback.rs
index 8121136..4d6d0be 100644
--- a/src/commands/playback.rs
+++ b/src/commands/playback.rs
@@ -14,7 +14,6 @@ use crate::{
util,
PoiseContext,
PoiseData,
- CONFIG,
};
pub fn commands() -> impl IntoIterator<Item = poise::Command<PoiseData, anyhow::Error>> {
@@ -74,6 +73,9 @@ pub async fn _play(ctx: PoiseContext<'_>, url: &url::Url) -> anyhow::Result<()>
data.get::<HttpKey>().unwrap().clone()
};
+ let volume = util::volume(ctx).await;
+ tracing::debug!(volume);
+
{
let (_sb, call) = songbird(ctx).await?;
let mut call = call.lock().await;
@@ -86,9 +88,11 @@ pub async fn _play(ctx: PoiseContext<'_>, url: &url::Url) -> anyhow::Result<()>
YoutubeDl::new_ytdl_like(&crate::config::YTDL_COMMAND, client.clone(), url.to_string());
let track = input.conv::<songbird::tracks::Track>();
+
// TODO: store enqueueing channel so songbird handler can switch channels
- call.enqueue(track).await;
+ let queued = call.enqueue(track).await;
+ queued.set_volume(volume as _)?;
}
util::react(ctx, '📣').await?;
@@ -197,7 +201,9 @@ pub async fn list(ctx: PoiseContext<'_>) -> anyhow::Result<()> {
let call = call.lock().await;
let queue = call.queue();
- util::reply(ctx, "(command fix work-in-progress)").await?;
+ if queue.current_queue().is_empty() {
+ util::reply(ctx, "nothing queued").await?;
+ }
for track in queue.current_queue().into_iter() {
let info = track.get_info().await?;
diff --git a/src/commands/sound_levels.rs b/src/commands/sound_levels.rs
index 4946f47..2b9048e 100644
--- a/src/commands/sound_levels.rs
+++ b/src/commands/sound_levels.rs
@@ -1,10 +1,18 @@
+use std::error::Error;
+
+use serenity::all::{
+ Context,
+ Message,
+};
+
use crate::{
commands::playback::songbird,
+ util,
PoiseContext,
};
/// Mute audio (don't pause).
-#[poise::command(prefix_command, guild_only)]
+#[poise::command(prefix_command, guild_only, category = "playback")]
pub async fn mute(ctx: PoiseContext<'_>) -> anyhow::Result<()> {
let (_sb, call) = songbird(ctx).await?;
@@ -15,7 +23,7 @@ pub async fn mute(ctx: PoiseContext<'_>) -> anyhow::Result<()> {
}
/// Unmute audio.
-#[poise::command(prefix_command, guild_only)]
+#[poise::command(prefix_command, guild_only, category = "playback")]
pub async fn unmute(ctx: PoiseContext<'_>) -> anyhow::Result<()> {
let (_sb, call) = songbird(ctx).await?;
@@ -24,3 +32,62 @@ pub async fn unmute(ctx: PoiseContext<'_>) -> anyhow::Result<()> {
Ok(())
}
+
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
+struct PercentArg(f64);
+
+lazy_static::lazy_static! {
+ static ref ARG_PCT: regex::Regex = regex::Regex::new(r#"(\d+(?:\.\d+)?)\s*%?(.*)"#).unwrap();
+}
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, thiserror::Error)]
+#[error("expected a number with an optional trailing %")]
+struct NonPctError;
+
+#[poise::async_trait]
+impl<'a> poise::PopArgument<'a> for PercentArg {
+ async fn pop_from(
+ args: &'a str,
+ attachment_index: usize,
+ _ctx: &Context,
+ _msg: &Message,
+ ) -> Result<(&'a str, usize, Self), (Box<dyn Error + Send + Sync>, Option<String>)> {
+ let Some(mtch) = ARG_PCT.captures(args) else {
+ return Err((Box::new(NonPctError), None));
+ };
+
+ let pct = mtch.get(1).unwrap().as_str().parse::<f64>().unwrap();
+ let prop = pct / 100.;
+ let rest = mtch.get(2).unwrap().as_str();
+
+ Ok((rest, attachment_index, Self(prop)))
+ }
+}
+
+/// Set volume by percent.
+#[poise::command(prefix_command, guild_only, category = "playback")]
+pub async fn volume(ctx: PoiseContext<'_>, volume: Option<PercentArg>) -> anyhow::Result<()> {
+ let Some(volume) = volume else {
+ let cur_vol = util::volume(ctx).await * 100.;
+
+ util::reply(ctx, format!("{cur_vol:.0}%")).await?;
+ return Ok(());
+ };
+
+ {
+ let data = ctx.serenity_context().data.read().await;
+ let vol = data.get::<crate::bot::VolumeKey>().unwrap();
+ vol.insert(util::guild_id(ctx)?, volume.0);
+ }
+
+ let (_sb, call) = songbird(ctx).await?;
+ let call = call.lock().await;
+
+ call.queue().modify_queue(|q| {
+ for elt in q {
+ elt.set_volume(volume.0 as _)?;
+ }
+
+ anyhow::Ok(())
+ })
+}
diff --git a/src/commands/today/mod.rs b/src/commands/today/mod.rs
index e48983c..f8f38c7 100644
--- a/src/commands/today/mod.rs
+++ b/src/commands/today/mod.rs
@@ -13,7 +13,6 @@ use crate::{
commands::playback::songbird,
util,
PoiseContext,
- CONFIG,
};
mod prelude;
@@ -103,6 +102,9 @@ pub async fn today(ctx: PoiseContext<'_>, #[rest] _rest: Option<String>) -> anyh
return Ok(());
};
+ let volume = util::volume(ctx).await;
+ tracing::debug!(volume);
+
let (_sb, call) = songbird(ctx).await?;
let mut call = call.lock().await;
@@ -118,7 +120,8 @@ pub async fn today(ctx: PoiseContext<'_>, #[rest] _rest: Option<String>) -> anyh
let input =
YoutubeDl::new_ytdl_like("yt-dlp", client.clone(), play_args.url.conv::<String>());
- call.enqueue_input(input.into()).await;
+ let handle = call.enqueue_input(input.into()).await;
+ handle.set_volume(volume as _)?;
let q = call.queue();
q.pause()?;