From 84dd3174e7e8c3e93d19e075e287afc06958daa3 Mon Sep 17 00:00:00 2001 From: trivernis Date: Thu, 22 Apr 2021 16:31:22 +0200 Subject: [PATCH] Add xkcd command Signed-off-by: trivernis --- Cargo.lock | 17 ++++++++++++++- Cargo.toml | 3 ++- src/client.rs | 2 -- src/commands/misc/mod.rs | 4 +++- src/commands/misc/xkcd.rs | 35 +++++++++++++++++++++++++++++ src/messages/mod.rs | 1 + src/messages/xkcd.rs | 46 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 src/commands/misc/xkcd.rs create mode 100644 src/messages/xkcd.rs diff --git a/Cargo.lock b/Cargo.lock index 525b073..27b4dae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2526,7 +2526,7 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tobi-rs" -version = "0.8.0" +version = "0.8.1" dependencies = [ "aspotify", "bot-coreutils", @@ -2557,6 +2557,7 @@ dependencies = [ "tokio", "trigram", "typemap_rev", + "xkcd-search", "youtube-metadata", ] @@ -3052,6 +3053,20 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "xkcd-search" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b456f115f18547c3a1185788837a000201bc29893dd5b70a12437f11d2ded190" +dependencies = [ + "lazy_static", + "reqwest", + "scraper", + "serde", + "thiserror", + "trigram", +] + [[package]] name = "xml5ever" version = "0.16.1" diff --git a/Cargo.toml b/Cargo.toml index 179312e..f6dc194 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tobi-rs" -version = "0.8.0" +version = "0.8.1" authors = ["trivernis "] edition = "2018" @@ -39,4 +39,5 @@ rustc_version_runtime = "0.2.0" trigram = "0.4.4" typemap_rev = "0.1.5" youtube-metadata = "0.1.1" +xkcd-search = "0.1.0" lavalink-rs = {version="0.7.1", features=["native", "serenity"]} \ No newline at end of file diff --git a/src/client.rs b/src/client.rs index 386dda2..81feb50 100644 --- a/src/client.rs +++ b/src/client.rs @@ -19,12 +19,10 @@ use crate::utils::context_data::{ use crate::utils::error::{BotError, BotResult}; use lavalink_rs::LavalinkClient; use serenity::framework::standard::buckets::LimitedFor; -use serenity_rich_interaction::menu::EventDrivenMessageContainer; use serenity_rich_interaction::RegisterRichInteractions; use std::env; use std::sync::Arc; use std::time::SystemTime; -use tokio::sync::Mutex; pub async fn get_client() -> BotResult { let token = env::var("BOT_TOKEN").map_err(|_| BotError::MissingToken)?; diff --git a/src/commands/misc/mod.rs b/src/commands/misc/mod.rs index 494b8d5..a0fa73e 100644 --- a/src/commands/misc/mod.rs +++ b/src/commands/misc/mod.rs @@ -11,6 +11,7 @@ use shutdown::SHUTDOWN_COMMAND; use stats::STATS_COMMAND; use time::TIME_COMMAND; use timezones::TIMEZONES_COMMAND; +use xkcd::XKCD_COMMAND; mod about; mod add_media; @@ -24,9 +25,10 @@ mod shutdown; mod stats; mod time; mod timezones; +mod xkcd; #[group] #[commands( - ping, stats, shutdown, time, timezones, qalc, about, add_media, media, pain, clear + ping, stats, shutdown, time, timezones, qalc, about, add_media, media, pain, clear, xkcd )] pub struct Misc; diff --git a/src/commands/misc/xkcd.rs b/src/commands/misc/xkcd.rs new file mode 100644 index 0000000..c267fc7 --- /dev/null +++ b/src/commands/misc/xkcd.rs @@ -0,0 +1,35 @@ +use crate::messages::xkcd::create_xkcd_menu; +use serenity::client::Context; +use serenity::framework::standard::macros::command; +use serenity::framework::standard::{Args, CommandResult}; +use serenity::model::channel::Message; +use xkcd_search::get_comic; + +#[command] +#[description("Retrieves xkcd comics")] +#[usage("[(|)]")] +#[bucket("general")] +async fn xkcd(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { + let comics = if let Ok(id) = args.single::() { + if let Ok(comic) = xkcd_search::get_comic(id).await { + vec![comic] + } else { + vec![] + } + } else if !args.is_empty() { + let query = args.message(); + let results = xkcd_search::search(query).await?; + let comics = + futures::future::join_all(results.into_iter().map(|(_, id)| get_comic(id))).await; + comics + .into_iter() + .filter_map(|result| result.ok()) + .collect() + } else { + vec![xkcd_search::get_latest_comic().await?] + }; + + create_xkcd_menu(ctx, msg.channel_id, comics).await?; + + Ok(()) +} diff --git a/src/messages/mod.rs b/src/messages/mod.rs index 1d4e4a4..bad0c06 100644 --- a/src/messages/mod.rs +++ b/src/messages/mod.rs @@ -8,6 +8,7 @@ pub mod gifs; pub mod minecraft; pub mod music; pub mod sauce; +pub mod xkcd; /// Adds an ephemeral message to the database pub async fn add_ephemeral_handle_to_database( diff --git a/src/messages/xkcd.rs b/src/messages/xkcd.rs new file mode 100644 index 0000000..9dc3434 --- /dev/null +++ b/src/messages/xkcd.rs @@ -0,0 +1,46 @@ +use crate::utils::error::BotResult; +use serenity::builder::CreateMessage; +use serenity::client::Context; +use serenity::model::id::ChannelId; +use serenity_rich_interaction::core::LONG_TIMEOUT; +use serenity_rich_interaction::menu::{MenuBuilder, Page}; +use xkcd_search::Comic; + +/// Creates a new xkcd menu +pub async fn create_xkcd_menu( + ctx: &Context, + channel_id: ChannelId, + comics: Vec, +) -> BotResult<()> { + let mut builder = if comics.len() > 1 { + MenuBuilder::new_paginator() + } else { + MenuBuilder::default() + }; + if comics.is_empty() { + let mut message = CreateMessage::default(); + message.content("No Comics found"); + builder = builder.add_page(Page::new_static(message)); + } + builder + .add_pages(comics.into_iter().map(|c| create_xkcd_page(c))) + .timeout(LONG_TIMEOUT) + .build(ctx, channel_id) + .await?; + + Ok(()) +} + +/// Creates an xkcd message +fn create_xkcd_page<'a>(comic: Comic) -> Page<'a> { + let mut message = CreateMessage::default(); + + message.embed(|e| { + e.title(format!("#{} - {}", comic.num, comic.title)) + .image(&comic.img) + .url(format!("https://xkcd.com/{}", comic.num)) + .footer(|f| f.text(format!("{} | xkcd.com", comic.alt))) + }); + + Page::new_static(message) +}