aboutsummaryrefslogtreecommitdiff
path: root/src/commands/meme
diff options
context:
space:
mode:
authorNathan Perry <np@nathanperry.dev>2024-05-08 10:28:04 -0400
committerNathan Perry <np@nathanperry.dev>2024-05-08 14:16:01 -0400
commitfe467f60d99efa54f2ef64606e7d39b9b06d7294 (patch)
treea62bb50fedb1959d1a155878f0ff0ab7b1f699b6 /src/commands/meme
parent48aa684dece2696e21fd871eb6f3825f28fe0200 (diff)
update all deps
Diffstat (limited to 'src/commands/meme')
-rw-r--r--src/commands/meme/create.rs127
-rw-r--r--src/commands/meme/delete.rs24
-rw-r--r--src/commands/meme/history.rs188
-rw-r--r--src/commands/meme/invoke.rs81
-rw-r--r--src/commands/meme/mod.rs115
5 files changed, 333 insertions, 202 deletions
diff --git a/src/commands/meme/create.rs b/src/commands/meme/create.rs
index 06cc4ef..97c5276 100644
--- a/src/commands/meme/create.rs
+++ b/src/commands/meme/create.rs
@@ -14,9 +14,9 @@ use log::{
};
use serenity::{
framework::standard::{
+ macros::command,
Args,
Delimiter,
- macros::command,
},
model::channel::Message,
prelude::*,
@@ -25,20 +25,28 @@ use url::Url;
use anyhow::anyhow;
use lazy_static::lazy_static;
+use serenity::{
+ all::ReactionType,
+ framework::standard::{
+ CommandError,
+ CommandResult,
+ },
+ futures::TryFutureExt,
+};
use crate::{
- Result,
audio::{
parse_times,
ytdl_url,
},
db::{
- Audio,
connection,
+ Audio,
Image,
NewMeme,
},
- util::CtxExt, FFMPEG_COMMAND,
+ util,
+ FFMPEG_COMMAND,
};
lazy_static! {
@@ -46,13 +54,17 @@ lazy_static! {
}
#[command]
-pub fn addmeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> {
+pub async fn addmeme(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
let mut args = Args::new(args.rest(), DELIMS.as_ref());
let title = args.single_quoted::<String>()?;
let text = args.rest().to_owned();
- let text = if text.is_empty() { None } else { Some(text) };
+ let text = if text.is_empty() {
+ None
+ } else {
+ Some(text)
+ };
let mut conn = connection()?;
@@ -60,13 +72,17 @@ pub fn addmeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> {
if image.is_none() && text.is_none() {
warn!("tried to create non-audio meme with no image or text");
- return ctx.send(msg.channel_id, "hahAA it's empty xdddd", msg.tts);
+ return util::send(ctx, msg.channel_id, "hahAA it's empty xdddd", msg.tts)
+ .map_err(CommandError::from)
+ .await;
}
- let image_id = image.map(|att| {
- let data = att.download()?;
- Image::create(&mut conn, &att.filename, data, msg.author.id.0)
- }).transpose()?;
+ let image_id = image
+ .map(|att| {
+ let data = att.download()?;
+ Image::create(&mut conn, &att.filename, data, msg.author.id.get())
+ })
+ .transpose()?;
let save_result = NewMeme {
title,
@@ -74,25 +90,31 @@ pub fn addmeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> {
image_id,
audio_id: None,
metadata_id: 0,
- }.save(&mut conn, msg.author.id.0).map(|_| {});
+ }
+ .save(&mut conn, msg.author.id.get())
+ .map(|_| {});
use diesel::result::DatabaseErrorKind;
match save_result {
Ok(_) => msg.react(&ctx, "👌"),
Err(e) => {
- if let Some(DieselError::DatabaseError(DatabaseErrorKind::UniqueViolation, _)) = e.downcast_ref::<DieselError>() {
+ if let Some(DieselError::DatabaseError(DatabaseErrorKind::UniqueViolation, _)) =
+ e.downcast_ref::<DieselError>()
+ {
error!("tried to create meme that already exists");
- msg.react(&ctx, "❌")?;
- return ctx.send(msg.channel_id, "that meme already exists", msg.tts);
+ msg.react(&ctx, ReactionType::Unicode("❌".to_owned())).await?;
+ return util::send(ctx, msg.channel_id, "that meme already exists", msg.tts)
+ .map_err(CommandError::from)
+ .await;
}
- return Err(e);
- }
+ return Err(e.into());
+ },
}
}
#[command]
-pub fn addaudiomeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> {
+pub async fn addaudiomeme(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
let mut args = Args::new(args.rest(), DELIMS.as_ref());
let title = args.single_quoted::<String>()?;
@@ -101,8 +123,8 @@ pub fn addaudiomeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()>
let elems = audio_str.split_whitespace().collect::<Vec<_>>();
if elems.len() == 0 {
- ctx.send(msg.channel_id, "are you stupid", msg.tts)?;
- return Err(anyhow!("no audio link was provided"))
+ util::send(ctx, msg.channel_id, "are you stupid", msg.tts).await?;
+ return Err(anyhow!("no audio link was provided").into());
}
let audio_link = Url::parse(elems[0])?;
@@ -112,16 +134,24 @@ pub fn addaudiomeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()>
let youtube_url = ytdl_url(audio_link.as_str())?;
let duration_opts = if let Some(e) = end {
- vec! [
- "-ss".to_owned(), start.map_or_else(
+ vec![
+ "-ss".to_owned(),
+ start.map_or_else(
|| "00:00:00".to_owned(),
- |s| format!("{:02}:{:02}:{:02}", s.num_hours(), s.num_minutes() % 60, s.num_seconds() % 60)
+ |s| {
+ format!(
+ "{:02}:{:02}:{:02}",
+ s.num_hours(),
+ s.num_minutes() % 60,
+ s.num_seconds() % 60
+ )
+ },
),
-
- "-to".to_owned(), format!("{:02}:{:02}:{:02}", e.num_hours(), e.num_minutes() % 60, e.num_seconds() % 60),
+ "-to".to_owned(),
+ format!("{:02}:{:02}:{:02}", e.num_hours(), e.num_minutes() % 60, e.num_seconds() % 60),
]
} else {
- vec! []
+ vec![]
};
let ffmpeg_command = Command::new(&*FFMPEG_COMMAND)
@@ -129,13 +159,8 @@ pub fn addaudiomeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()>
.arg(youtube_url)
.args(duration_opts)
.args(&[
- "-ac", "2",
- "-ar", "48000",
- "-f", "opus",
- "-acodec", "libopus",
- "-b:a", "96k",
- "-fs", "5M",
- "-",
+ "-ac", "2", "-ar", "48000", "-f", "opus", "-acodec", "libopus", "-b:a", "96k", "-fs",
+ "5M", "-",
])
.stdout(Stdio::piped())
.stderr(Stdio::null())
@@ -145,15 +170,21 @@ pub fn addaudiomeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()>
let mut audio_reader = ffmpeg_command.stdout.unwrap();
let text = args.rest().to_owned();
- let text = if text.is_empty() { None } else { Some(text) };
+ let text = if text.is_empty() {
+ None
+ } else {
+ Some(text)
+ };
let mut conn = connection()?;
- let image = msg.attachments.first()
+ let image = msg
+ .attachments
+ .first()
.ok_or(anyhow!("no attachment"))
.and_then(|att| {
let data = att.download()?;
- Image::create(&mut conn, &att.filename, data, msg.author.id.0)
+ Image::create(&mut conn, &att.filename, data, msg.author.id.get())
})
.ok();
@@ -162,10 +193,12 @@ pub fn addaudiomeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()>
if bytes == 0 {
debug!("read 0 bytes from audio reader");
- return ctx.send(msg.channel_id, "🔇🔇🔇🔕🔕🔕🔕🔕🔇🔕🔕🔇🔕🔕📣📢📣📢📣", msg.tts);
+ return util::send(ctx, msg.channel_id, "🔇🔇🔇🔕🔕🔕🔕🔕🔇🔕🔕🔇🔕🔕📣📢📣📢📣", msg.tts)
+ .map_err(CommandError::from)
+ .await;
}
- let audio_id = Audio::create(&mut conn, audio_data, msg.author.id.0)?;
+ let audio_id = Audio::create(&mut conn, audio_data, msg.author.id.get())?;
let save_result = NewMeme {
title,
@@ -173,19 +206,25 @@ pub fn addaudiomeme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()>
image_id: image,
audio_id: Some(audio_id),
metadata_id: 0,
- }.save(&mut conn, msg.author.id.0).map(|_| {});
+ }
+ .save(&mut conn, msg.author.id.get())
+ .map(|_| {});
use diesel::result::DatabaseErrorKind;
match save_result {
- Ok(_) => msg.react(&ctx, "👌"),
+ Ok(_) => msg.react(&ctx, ReactionType::Unicode("👌".to_owned())),
Err(e) => {
- if let Some(DieselError::DatabaseError(DatabaseErrorKind::UniqueViolation, _)) = e.downcast_ref::<DieselError>() {
+ if let Some(DieselError::DatabaseError(DatabaseErrorKind::UniqueViolation, _)) =
+ e.downcast_ref::<DieselError>()
+ {
error!("tried to create meme that already exists");
- msg.react(&ctx, "❌")?;
- return ctx.send(msg.channel_id, "that meme already exists", msg.tts);
+ msg.react(&ctx, ReactionType::Unicode("❌".to_owned())).await?;
+ return util::send(ctx, msg.channel_id, "that meme already exists", msg.tts)
+ .map_err(CommandError::from)
+ .await;
}
return Err(e);
- }
+ },
}
}
diff --git a/src/commands/meme/delete.rs b/src/commands/meme/delete.rs
index 7eafc80..c06e9d0 100644
--- a/src/commands/meme/delete.rs
+++ b/src/commands/meme/delete.rs
@@ -1,45 +1,49 @@
use diesel::{
- NotFound,
result::Error as DieselError,
+ NotFound,
};
use log::info;
use serenity::{
+ all::ReactionType,
framework::standard::{
- Args,
macros::command,
+ Args,
+ CommandResult,
},
model::channel::Message,
prelude::*,
};
use crate::{
- Result,
db::{
connection,
delete_meme,
},
- util::CtxExt,
+ util,
};
#[command]
#[aliases("delmem")]
-pub fn delmeme(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
+pub async fn delmeme(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
let title = args.single_quoted::<String>()?;
let mut conn = connection()?;
- match delete_meme(&mut conn, &title, msg.author.id.0) {
- Ok(_) => msg.react(ctx, "💀"),
+ match delete_meme(&mut conn, &title, msg.author.id.get()) {
+ Ok(_) => {
+ msg.react(ctx, ReactionType::Unicode("💀".to_owned())).await?;
+ Ok(())
+ },
Err(e) => {
if let Some(NotFound) = e.downcast_ref::<DieselError>() {
- msg.react(&ctx, "❓")?;
+ msg.react(&ctx, ReactionType::Unicode("❓".to_owned())).await?;
info!("attempted to delete nonexistent meme: '{}'", title);
- ctx.send(msg.channel_id, "nice try", msg.tts)?;
+ util::send(ctx, msg.channel_id, "nice try", msg.tts).await?;
return Ok(());
}
Err(e)?;
Ok(())
- }
+ },
}
}
diff --git a/src/commands/meme/history.rs b/src/commands/meme/history.rs
index f9e8851..5e200b1 100644
--- a/src/commands/meme/history.rs
+++ b/src/commands/meme/history.rs
@@ -1,6 +1,6 @@
use diesel::{
- NotFound,
result::Error as DieselError,
+ NotFound,
};
use log::{
debug,
@@ -9,8 +9,8 @@ use log::{
};
use serenity::{
framework::standard::{
- Args,
macros::command,
+ Args,
},
model::channel::Message,
prelude::*,
@@ -22,6 +22,13 @@ use timeago::{
use anyhow::anyhow;
use lazy_static::lazy_static;
+use serenity::{
+ framework::standard::{
+ CommandError,
+ CommandResult,
+ },
+ futures::TryFutureExt,
+};
use crate::{
db::{
@@ -31,9 +38,9 @@ use crate::{
Meme,
Metadata,
},
- CONFIG,
+ util,
Result,
- util::CtxExt,
+ CONFIG,
};
lazy_static! {
@@ -50,7 +57,7 @@ static CLEAN_DATE_FORMAT: &'static str = "%b %-e %Y";
#[command]
#[aliases("what")]
-pub fn wat(ctx: &mut Context, msg: &Message, _: Args) -> Result<()> {
+pub async fn wat(ctx: &Context, msg: &Message, _: Args) -> CommandResult {
let mut conn = connection()?;
let record = match InvocationRecord::last(&mut conn) {
@@ -58,11 +65,13 @@ pub fn wat(ctx: &mut Context, msg: &Message, _: Args) -> Result<()> {
Err(e) => {
if let Some(NotFound) = e.downcast_ref::<DieselError>() {
info!("found no memes in history");
- return ctx.send(msg.channel_id, "no one has ever memed before", msg.tts);
+ return util::send(ctx, msg.channel_id, "no one has ever memed before", msg.tts)
+ .map_err(CommandError::from)
+ .await;
}
- ctx.send(msg.channel_id, "BAD MEME BAD MEME", msg.tts)?;
- return Err(e);
+ util::send(ctx, msg.channel_id, "BAD MEME BAD MEME", msg.tts).await?;
+ return Err(e.into());
},
};
@@ -73,17 +82,27 @@ pub fn wat(ctx: &mut Context, msg: &Message, _: Args) -> Result<()> {
let metadata = Metadata::find(&mut conn, meme.metadata_id)?;
let author = CONFIG.discord.guild().member(&ctx, metadata.created_by as u64)?;
- ctx.send(msg.channel_id,
- &format!("that was \"{}\" by {} ({})",
- meme.title, author.mention(), metadata.created.date().format(CLEAN_DATE_FORMAT)), msg.tts)?
+ util::send(
+ ctx,
+ msg.channel_id,
+ &format!(
+ "that was \"{}\" by {} ({})",
+ meme.title,
+ author.mention(),
+ metadata.created.date().format(CLEAN_DATE_FORMAT)
+ ),
+ msg.tts,
+ )
+ .await?
},
Err(e) => {
if let Some(NotFound) = e.downcast_ref::<DieselError>() {
info!("last meme not found in database");
- return ctx.send(msg.channel_id, "heuueueeeeh?", msg.tts);
+ return util::send(ctx, msg.channel_id, "heuueueeeeh?", msg.tts).await;
}
- ctx.send(msg.channel_id, "do i look like i know what a jpeg is", msg.tts)?;
+ util::send(ctx, msg.channel_id, "do i look like i know what a jpeg is", msg.tts)
+ .await?;
return Err(e);
},
};
@@ -92,7 +111,7 @@ pub fn wat(ctx: &mut Context, msg: &Message, _: Args) -> Result<()> {
}
#[command]
-pub fn history(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
+pub async fn history(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
use itertools::Itertools;
let mut conn = connection()?;
@@ -101,7 +120,7 @@ pub fn history(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
if n > CONFIG.max_hist {
debug!("user requested more than MAX_HIST ({}) items from history", CONFIG.max_hist);
- ctx.send(msg.channel_id, "YER PUSHIN ME OVER THE FUCKIN LINE", true)?;
+ util::send(ctx, msg.channel_id, "YER PUSHIN ME OVER THE FUCKIN LINE", true).await?;
}
let n = n.min(CONFIG.max_hist);
@@ -110,7 +129,9 @@ pub fn history(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
if records.len() == 0 {
info!("no memes in history");
- return ctx.send(msg.channel_id, "i don't remember anything :(", msg.tts);
+ return util::send(ctx, msg.channel_id, "i don't remember anything :(", msg.tts)
+ .map_err(CommandError::from)
+ .await;
}
info!("reporting meme history (len {})", n);
@@ -119,18 +140,41 @@ pub fn history(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
.enumerate()
.rev()
.map(|(i, rec)| {
- let dt = chrono::DateTime::from_utc(rec.time, chrono::Utc{});
+ 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 rand = if rec.random {
+ "R, "
+ } else {
+ ""
+ };
Meme::find(&mut conn, rec.meme_id)
.and_then(|meme| {
Metadata::find(&mut conn, meme.metadata_id).map(|metadata| (metadata, meme))
})
.map(|(metadata, meme)| {
- let author_name = CONFIG.discord.guild().member(&ctx, metadata.created_by as u64).map(|m| m.display_name().into_owned()).unwrap_or("???".to_owned());
- let invoker_name = CONFIG.discord.guild().member(&ctx, rec.user_id as u64).map(|m| m.display_name().into_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)
+ let author_name = CONFIG
+ .discord
+ .guild()
+ .member(&ctx, metadata.created_by as u64)
+ .map(|m| m.display_name().into_owned())
+ .unwrap_or("???".to_owned());
+ let invoker_name = CONFIG
+ .discord
+ .guild()
+ .member(&ctx, rec.user_id as u64)
+ .map(|m| m.display_name().into_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
+ )
})
.unwrap_or_else(|e| {
if let Some(variant) = e.downcast_ref::<DieselError>() {
@@ -139,18 +183,23 @@ pub fn history(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
}
}
- let invoker_name = CONFIG.discord.guild().member(&ctx, rec.user_id as u64).map(|m| m.display_name().into_owned()).unwrap_or("???".to_owned());
+ let invoker_name = CONFIG
+ .discord
+ .guild()
+ .member(&ctx, rec.user_id as u64)
+ .map(|m| m.display_name().into_owned())
+ .unwrap_or("???".to_owned());
format!("{}. [{}{}] not found. invoked by {}.", i + 1, rand, ago, invoker_name)
})
})
.join("\n");
- ctx.send(msg.channel_id, &resp, false)
+ util::send(ctx, msg.channel_id, &resp, false).await
}
#[command]
#[aliases("stat")]
-pub fn stats(ctx: &mut Context, msg: &Message, _: Args) -> Result<()> {
+pub async fn stats(ctx: &Context, msg: &Message, _: Args) -> CommandResult {
use db;
use serenity::model::{
id::UserId,
@@ -162,8 +211,8 @@ pub fn stats(ctx: &mut Context, msg: &Message, _: Args) -> Result<()> {
debug!("reporting stats");
- let rand_user: User = UserId(stats.most_random_meme_user).to_user(&ctx)?;
- let direct_user: User = UserId(stats.most_directly_named_meme_user).to_user(&ctx)?;
+ let rand_user: User = UserId::new(stats.most_random_meme_user).to_user(&ctx)?;
+ let direct_user: User = UserId::new(stats.most_directly_named_meme_user).to_user(&ctx)?;
let rand_user = rand_user.nick_in(&ctx, CONFIG.discord.guild()).unwrap_or(rand_user.name);
let direct_user = direct_user.nick_in(&ctx, CONFIG.discord.guild()).unwrap_or(direct_user.name);
@@ -200,29 +249,35 @@ and *{}* was the most-memed overall ({})"#,
(stats.random_meme_invocations as f64) / (stats.total_meme_invocations as f64) * 100.,
stats.audio_meme_invocations,
(stats.audio_meme_invocations as f64) / (stats.total_meme_invocations as f64) * 100.,
- stats.most_active_day.format(CLEAN_DATE_FORMAT), stats.most_active_day_count,
- stats.most_audio_active_day.format(CLEAN_DATE_FORMAT), stats.most_audio_active_count,
- rand_user, stats.most_random_meme_user_count,
- direct_user, stats.most_directly_named_meme_count,
- stats.most_popular_named_meme, stats.most_popular_named_meme_count,
- stats.most_popular_random_meme, stats.most_popular_random_meme_count,
- stats.most_popular_meme_overall, stats.most_popular_meme_overall_count,
+ stats.most_active_day.format(CLEAN_DATE_FORMAT),
+ stats.most_active_day_count,
+ stats.most_audio_active_day.format(CLEAN_DATE_FORMAT),
+ stats.most_audio_active_count,
+ rand_user,
+ stats.most_random_meme_user_count,
+ direct_user,
+ stats.most_directly_named_meme_count,
+ stats.most_popular_named_meme,
+ stats.most_popular_named_meme_count,
+ stats.most_popular_random_meme,
+ stats.most_popular_random_meme_count,
+ stats.most_popular_meme_overall,
+ stats.most_popular_meme_overall_count,
);
- ctx.send(msg.channel_id, s, msg.tts)
+
+ util::send(ctx, msg.channel_id, s, msg.tts).map_err(CommandError::from).await
}
#[command]
-pub fn memers(ctx: &mut Context, msg: &Message, _args: Args) -> Result<()> {
+pub async fn memers(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
use db;
use itertools::Itertools;
- use serenity::model::{
- id::UserId,
- };
+ use serenity::model::id::UserId;
let s = db::memers()?
.into_iter()
.map(|info| {
- let user = UserId(info.user_id).to_user(&ctx)?;
+ let user = UserId::new(info.user_id).to_user(&ctx)?;
let username = user.nick_in(&ctx, CONFIG.discord.guild()).unwrap_or(user.name);
let res = format!(
@@ -241,11 +296,11 @@ pub fn memers(ctx: &mut Context, msg: &Message, _args: Args) -> Result<()> {
.into_iter()
.join("\n");
- ctx.send(msg.channel_id, &s, msg.tts)
+ util::send(ctx, msg.channel_id, &s, msg.tts).map_err(CommandError::from).await
}
#[command]
-pub fn query(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
+pub async fn query(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
use std::borrow::Borrow;
use itertools::Itertools;
@@ -253,8 +308,8 @@ pub fn query(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
use serenity::model::id::UserId;
use crate::{
- game::get_user_id,
db,
+ game::get_user_id,
CONFIG,
};
@@ -263,24 +318,21 @@ pub fn query(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
static ref AGE_REGEX: Regex = Regex::new(r"(?i)(?:age|order)=(.*)").unwrap();
}
- let guild = msg.channel_id.to_channel(&ctx)?
- .guild()
- .ok_or(anyhow!("couldn't find guild"))?;
+ let guild = msg.channel_id.to_channel(&ctx)?.guild().ok_or(anyhow!("couldn't find guild"))?;
- let guild = guild.read()
- .guild(&ctx)
- .ok_or(anyhow!("couldn't find guild"))?;
+ let guild = guild.read().guild(&ctx).ok_or(anyhow!("couldn't find guild"))?;
- let guild = guild
- .read();
+ let guild = guild.read();
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>()
.ok()
- .and_then(|s| CREATOR_REGEX.captures(&s).and_then(|c| c.get(1)).map(|x| x.as_str().to_owned()))
- .and_then(|s| get_user_id(guild.borrow(), s).ok().map(|s| s.0))
+ .and_then(|s| {
+ CREATOR_REGEX.captures(&s).and_then(|c| c.get(1)).map(|x| x.as_str().to_owned())
+ })
+ .and_then(|s| get_user_id(guild.borrow(), s).ok().map(UserId::get))
} else {
None
}
@@ -290,8 +342,11 @@ pub fn query(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
let order = args.quoted().current().map(|s| AGE_REGEX.is_match(s)).unwrap_or(false);
if order {
- args.single_quoted::<String>().ok()
- .and_then(|s| AGE_REGEX.captures(&s).and_then(|c| c.get(1)).map(|x| x.as_str().to_owned()))
+ args.single_quoted::<String>()
+ .ok()
+ .and_then(|s| {
+ AGE_REGEX.captures(&s).and_then(|c| c.get(1)).map(|x| x.as_str().to_owned())
+ })
.map(|s: String| s.contains("new"))
.unwrap_or(true)
} else {
@@ -302,16 +357,17 @@ pub fn query(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
let result = db::query_meme(args.rest(), creator, order)?
.into_iter()
.map(|(meme, metadata)| {
- let user = UserId(metadata.created_by as u64).to_user(&ctx)?;
+ let user = UserId::new(metadata.created_by as u64).to_user(&ctx)?;
let username = user.nick_in(&ctx, CONFIG.discord.guild()).unwrap_or(user.name);
- Ok(format!("*{}* by **{}** ({}). text length: **{}**, image: **{}**, audio: **{}**",
- meme.title,
- username,
- metadata.created.date().format(CLEAN_DATE_FORMAT),
- meme.content.map_or(0, |s| s.len()),
- meme.image_id.map_or("NO", |_s| "YES"),
- meme.audio_id.map_or("NO", |_s| "YES"),
+ Ok(format!(
+ "*{}* by **{}** ({}). text length: **{}**, image: **{}**, audio: **{}**",
+ meme.title,
+ username,
+ metadata.created.date().format(CLEAN_DATE_FORMAT),
+ meme.content.map_or(0, |s| s.len()),
+ meme.image_id.map_or("NO", |_s| "YES"),
+ meme.audio_id.map_or("NO", |_s| "YES"),
))
})
.collect::<Result<Vec<_>>>()?
@@ -329,9 +385,11 @@ pub fn query(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> {
if result.len() == 0 {
info!("no memes matched query");
- return ctx.send(msg.channel_id, "no match".to_owned(), msg.tts);
- }
+ return util::send(ctx, msg.channel_id, "no match".to_owned(), msg.tts)
+ .map_err(CommandError::from)
+ .await;
+ }
- ctx.send(msg.channel_id, &result, msg.tts)
+ util::send(ctx, msg.channel_id, &result, msg.tts).map_err(CommandError::from).await
}
diff --git a/src/commands/meme/invoke.rs b/src/commands/meme/invoke.rs
index de0272f..03c6251 100644
--- a/src/commands/meme/invoke.rs
+++ b/src/commands/meme/invoke.rs
@@ -1,63 +1,65 @@
use diesel::{
- NotFound,
result::Error as DieselError,
+ NotFound,
};
use itertools::Itertools;
use log::info;
use serenity::{
framework::standard::{
- Args,
macros::command,
+ Args,
+ CommandError,
+ CommandResult,
},
+ futures::TryFutureExt,
model::channel::Message,
prelude::*,
};
use crate::{
commands::meme::send_meme,
- Result,
db::{
self,
connection,
find_meme,
InvocationRecord,
},
- util::CtxExt,
+ util,
};
#[command]
#[aliases("mem")]
-pub fn meme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> {
+pub async fn meme(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
_meme(ctx, msg, args, AudioPlayback::Optional)
}
#[command]
-pub fn omen(ctx: &mut Context, msg: &Message, _args: Args) -> Result<()> {
+pub async fn omen(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
let args = Args::new("", &[]);
_meme(ctx, msg, args, AudioPlayback::Optional)
}
#[command]
-pub fn silentomen(ctx: &mut Context, msg: &Message, _args: Args) -> Result<()> {
+pub async fn silentomen(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
let args = Args::new("", &[]);
_meme(ctx, msg, args, AudioPlayback::Prohibited)
}
#[command]
-pub fn audioomen(ctx: &mut Context, msg: &Message, _args: Args) -> Result<()> {
+pub async fn audioomen(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
let args = Args::new("", &[]);
_meme(ctx, msg, args, AudioPlayback::Required)
}
#[command]
#[aliases("audiomeme", "audiomem")]
-pub fn audio_meme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> {
+pub async fn audio_meme(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
_meme(ctx, msg, args, AudioPlayback::Required)
}
#[command]
#[aliases("silentmeme", "silentmem")]
-pub fn silent_meme(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> {
+pub async fn silent_meme(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
_meme(ctx, msg, args, AudioPlayback::Prohibited)
}
@@ -68,9 +70,14 @@ enum AudioPlayback {
Prohibited,
}
-fn _meme(ctx: &mut Context, msg: &Message, args: Args, audio_playback: AudioPlayback) -> Result<()> {
+async fn _meme(
+ ctx: &Context,
+ msg: &Message,
+ args: Args,
+ audio_playback: AudioPlayback,
+) -> CommandResult {
if args.len() == 0 || audio_playback != AudioPlayback::Optional {
- return rand_meme(ctx, msg, audio_playback);
+ return rand_meme(ctx, msg, audio_playback).await;
}
let search = args.raw().join(" ");
@@ -78,28 +85,34 @@ fn _meme(ctx: &mut Context, msg: &Message, args: Args, audio_playback: AudioPlay
let mut conn = connection()?;
let mem = match find_meme(&mut conn, search) {
Ok(x) => {
- InvocationRecord::create(&mut conn, msg.author.id.0, msg.id.0, x.id, false)?;
+ InvocationRecord::create(&mut conn, msg.author.id.get(), msg.id.get(), x.id, false)?;
x
},
Err(e) => {
return if let Some(NotFound) = e.downcast_ref::<DieselError>() {
info!("requested meme not found in database");
- ctx.send(msg.channel_id, "c'mon baby, guesstimate", msg.tts)
+ util::send(ctx, msg.channel_id, "c'mon baby, guesstimate", msg.tts)
+ .await
+ .map_err(CommandError::from)
} else {
- ctx.send(msg.channel_id, "what in ryan's name", msg.tts)?;
- Err(e)
+ util::send(ctx, msg.channel_id, "what in ryan's name", msg.tts).await?;
+ Err(e.into())
};
},
};
- send_meme(ctx, &mem, &mut conn, msg)
+ send_meme(ctx, &mem, &mut conn, msg).await
}
-fn rand_meme(ctx: &Context, message: &Message, audio_playback: AudioPlayback) -> Result<()> {
+async fn rand_meme(
+ ctx: &Context,
+ message: &Message,
+ audio_playback: AudioPlayback,
+) -> CommandResult {
let mut conn = connection()?;
- let should_audio = ctx.users_listening()?;
+ let should_audio = util::users_listening(ctx).await?;
let mem = match audio_playback {
AudioPlayback::Required => db::rand_audio_meme(&mut conn),
@@ -109,28 +122,36 @@ fn rand_meme(ctx: &Context, message: &Message, audio_playback: AudioPlayback) ->
match mem {
Ok(mem) => {
- InvocationRecord::create(&mut conn, message.author.id.0, message.id.0, mem.id, true)?;
- send_meme(ctx, &mem, &mut conn, message)?;
+ InvocationRecord::create(
+ &mut conn,
+ message.author.id.get(),
+ message.id.get(),
+ mem.id,
+ true,
+ )?;
+ send_meme(ctx, &mem, &mut conn, message).await?;
Ok(())
},
Err(e) => {
match e.downcast_ref::<DieselError>() {
Some(NotFound) => {
info!("random meme not found");
- return ctx.send(message.channel_id, "i don't know any :(", message.tts)
+ return util::send(ctx, message.channel_id, "i don't know any :(", message.tts)
+ .map_err(CommandError::from)
+ .await;
},
_ => {},
}
- ctx.send(message.channel_id, "HELP", message.tts)?;
- return Err(e);
+ util::send(ctx, message.channel_id, "HELP", message.tts).await?;
+ return Err(e.into());
},
}
}
#[command]
#[aliases("rarememe", "raremem")]
-pub fn rare_meme(ctx: &mut Context, msg: &Message, _args: Args) -> Result<()> {
+pub async fn rare_meme(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
let should_audio = ctx.users_listening()?;
let mut conn = connection()?;
@@ -138,19 +159,23 @@ pub fn rare_meme(ctx: &mut Context, msg: &Message, _args: Args) -> Result<()> {
let meme = db::rare_meme(&mut conn, should_audio);
match meme {
Ok(meme) => {
- InvocationRecord::create(&mut conn, msg.author.id.0, msg.id.0, meme.id, true)?;
+ InvocationRecord::create(&mut conn, msg.author.id.get(), msg.id.get(), meme.id, true)?;
send_meme(ctx, &meme, &mut conn, msg)
},
Err(e) => {
match e.downcast_ref::<DieselError>() {
Some(NotFound) => {
info!("rare meme not found");
- return ctx.send(msg.channel_id, "i don't know any :(", msg.tts)
+ return util::send(ctx, msg.channel_id, "i don't know any :(", msg.tts)
+ .map_err(CommandError::from)
+ .await;
},
_ => {},
}
- ctx.send(msg.channel_id, "THE MEME MARKET IS IN FREEFALL", msg.tts)?;
+ util::send(ctx, msg.channel_id, "THE MEME MARKET IS IN FREEFALL", msg.tts)
+ .map_err(CommandError::from)
+ .await?;
Err(e)
},
diff --git a/src/commands/meme/mod.rs b/src/commands/meme/mod.rs
index 6ce30b6..31d9b78 100644
--- a/src/commands/meme/mod.rs
+++ b/src/commands/meme/mod.rs
@@ -1,9 +1,16 @@
use diesel::PgConnection;
use log::debug;
-use rand::{Rng, thread_rng};
+use rand::random;
use serenity::{
- framework::standard::macros::group,
- http::AttachmentType,
+ all::ReactionType,
+ builder::{
+ CreateAttachment,
+ CreateMessage,
+ },
+ framework::standard::{
+ macros::group,
+ CommandResult,
+ },
model::channel::Message,
prelude::*,
};
@@ -14,7 +21,6 @@ use crate::{
PlayQueue,
},
db::Meme,
- Result,
};
pub use self::{
@@ -24,68 +30,67 @@ pub use self::{
invoke::*,
};
-mod history;
mod create;
-mod invoke;
mod delete;
+mod history;
+mod invoke;
-group!({
- name: "memes",
- options: {
- only_in: "guild",
- },
- commands: [
- meme,
- audio_meme,
- silent_Meme,
- omen,
- audioomen,
- silentomen,
- addmeme,
- addaudiomeme,
- delmeme,
- wat,
- stats,
- history,
- rare_meme,
- memers,
- query,
- ],
-});
+#[group]
+#[commands(
+ meme,
+ audio_meme,
+ silent_meme,
+ omen,
+ audioomen,
+ silentomen,
+ addmeme,
+ addaudiomeme,
+ delmeme,
+ wat,
+ stats,
+ history,
+ rare_meme,
+ memers,
+ query
+)]
+struct Memes;
-fn send_meme(ctx: &Context, t: &Meme, conn: &mut PgConnection, msg: &Message) -> Result<()> {
- let should_tts = t.content.as_ref().map(|t| t.len() > 0).unwrap_or(false) &&
- thread_rng().gen::<u32>() % 25 == 0;
+async fn send_meme(
+ ctx: &Context,
+ t: &Meme,
+ conn: &mut PgConnection,
+ msg: &Message,
+) -> CommandResult {
+ let should_tts =
+ t.content.as_ref().map(|t| t.len() > 0).unwrap_or(false) && random::<u32>() % 25 == 0;
debug!("sending meme (tts: {}): {:?}", should_tts, t);
let image = t.image(conn);
let audio = t.audio(conn);
+ let cmsg = {
+ let ret = CreateMessage::default().tts(should_tts);
+
+ match t.content {
+ Some(ref text) if text.len() > 0 => ret.content(text),
+ _ => ret,
+ }
+ };
+
match image {
Some(image) => {
let image = image?;
- msg.channel_id.send_files(ctx, vec!(AttachmentType::Bytes((&image.data, &image.filename))), |m| {
- let ret = m.tts(should_tts);
+ let att = CreateAttachment::bytes(image.data.as_slice(), &image.filename);
- match t.content {
- Some(ref text) if text.len() > 0 => ret.content(text),
- _ => ret,
- }
- })?;
+ msg.channel_id.send_files(ctx, vec![att], cmsg).await?;
},
None => match t.content {
- Some(_) => { msg.channel_id.send_message(ctx, |m| {
- let ret = m.tts(should_tts);
-
- match t.content {
- Some(ref text) if text.len() > 0 => ret.content(text),
- _ => ret,
- }
- })?; },
+ Some(_) => {
+ msg.channel_id.send_message(ctx, cmsg).await?;
+ },
None => {},
-
},
};
@@ -96,19 +101,19 @@ fn send_meme(ctx: &Context, t: &Meme, conn: &mut PgConnection, msg: &Message) ->
let audio = audio?;
{
- let queue_lock = ctx.data.write().get::<PlayQueue>().cloned().unwrap();
+ let queue_lock = ctx.data.write().await.get::<PlayQueue>().cloned().unwrap();
let mut play_queue = queue_lock.write().unwrap();
- play_queue.meme_queue.push_back(PlayArgs{
- initiator: msg.author.name.clone(),
- data: ::either::Right(audio.data.clone()),
+ play_queue.meme_queue.push_back(PlayArgs {
+ initiator: msg.author.name.clone(),
+ data: ::either::Right(audio.data.clone()),
sender_channel: msg.channel_id,
- start: None,
- end: None,
+ start: None,
+ end: None,
});
}
- msg.react(ctx, "📣")?;
+ msg.react(ctx, ReactionType::Unicode("📣".to_owned())).await?;
}
Ok(())