Skip to content

Commit

Permalink
commands: add fun module starting with an xkcd command.
Browse files Browse the repository at this point in the history
  • Loading branch information
evieluvsrainbows committed Jul 19, 2024
1 parent 7ac042b commit f7bc928
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 24 deletions.
1 change: 1 addition & 0 deletions src/commands/fun/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod xkcd;
47 changes: 47 additions & 0 deletions src/commands/fun/xkcd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use poise::command;
use reqwest::StatusCode;
use serde::Deserialize;
use serenity::all::{CreateActionRow, CreateButton, CreateEmbed, CreateEmbedFooter};

use crate::{data::ReqwestContainer, Context, Error};

#[derive(Debug, Deserialize)]
struct XkcdComic {
num: u16, // the numeric ID of the xkcd comic.
alt: String, // the caption of the xkcd comic.
img: String, // the image URL of the xkcd comic.
title: String, // the title of the xkcd comic.
}

/// Retrieves the latest or a specific comic from xkcd.
#[command(slash_command)]
pub async fn xkcd(ctx: Context<'_>, #[description = "The specific comic no. to retrieve."] number: Option<u16>) -> Result<(), Error> {
let comic = match number {
None => "https://xkcd.com/info.0.json".to_string(),
Some(number) => format!("https://xkcd.com/{number}/info.0.json").to_string(),
};

let client = ctx.serenity_context().data.read().await.get::<ReqwestContainer>().cloned().unwrap();
let request = client.get(comic).send().await?;
if request.status() == StatusCode::NOT_FOUND {
ctx.reply("You did not provide a valid comic id.").await?;
return Ok(());
}

let response: XkcdComic = request.json().await?;
let num = response.num;
let page = format!("https://xkcd.com/{num}/");
let wiki = format!("https://explainxkcd.com/wiki/index.php/{num}");

let embed = CreateEmbed::new()
.title(&response.title)
.color(0xfafafa)
.description(&response.alt)
.image(&response.img)
.footer(CreateEmbedFooter::new(format!("xkcd comic no. {num}")));

let links = CreateActionRow::Buttons(vec![CreateButton::new_link(page).label("View on xkcd"), CreateButton::new_link(wiki).label("View wiki")]);
ctx.send(poise::CreateReply::default().embed(embed).components(vec![links])).await?;

Ok(())
}
1 change: 1 addition & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod fun;
pub mod utilities;
2 changes: 2 additions & 0 deletions src/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/// The user agent used for the reqwest client.
pub const REQWEST_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));
22 changes: 1 addition & 21 deletions src/data.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,8 @@
use aspotify::Client as SpotifyClient;
use reqwest::Client as ReqwestClient;
use serenity::{client::bridge::gateway::ShardManager, prelude::TypeMapKey};
use std::sync::Arc;
use tokio::sync::Mutex;
use serenity::prelude::TypeMapKey;

use crate::config::ConfigurationData;

pub struct ShardManagerContainer;
pub struct ConfigContainer;
pub struct ReqwestContainer;
pub struct SpotifyContainer;

impl TypeMapKey for ShardManagerContainer {
type Value = Arc<Mutex<ShardManager>>;
}

impl TypeMapKey for ConfigContainer {
type Value = ConfigurationData;
}

impl TypeMapKey for ReqwestContainer {
type Value = ReqwestClient;
}

impl TypeMapKey for SpotifyContainer {
type Value = SpotifyClient;
}
26 changes: 23 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
use crate::serenity::GatewayIntents;
use constants::REQWEST_USER_AGENT;
use data::ReqwestContainer;
use listeners::handler::Handler;
use poise::serenity_prelude as serenity;
use poise::{Framework, FrameworkOptions};
use reqwest::redirect::Policy;
use reqwest::Client;
use tracing::{info, Level};
use tracing_log::LogTracer;
use tracing_subscriber::{EnvFilter, FmtSubscriber};
use utils::read_config;

mod commands;
mod config;
mod constants;
mod data;
mod listeners;
mod utils;

Expand Down Expand Up @@ -45,7 +51,12 @@ async fn main() -> Result<(), Error> {
let token = configuration.bot.discord.token;
let framework = Framework::builder()
.options(FrameworkOptions {
commands: vec![commands::utilities::hello(), commands::utilities::help(), commands::utilities::source()],
commands: vec![
commands::fun::xkcd::xkcd(),
commands::utilities::hello(),
commands::utilities::help(),
commands::utilities::source()
],
..Default::default()
})
.setup(move |ctx, _ready, framework| {
Expand All @@ -62,8 +73,17 @@ async fn main() -> Result<(), Error> {
let commands_str: String = framework.options().commands.iter().map(|c| &c.name).cloned().collect::<Vec<String>>().join(", ");
info!("Initialized {} commands: {}", command_count, commands_str);

let client = serenity::Client::builder(token, GatewayIntents::all()).event_handler(Handler).framework(framework).await;
client.unwrap().start().await.unwrap();
let mut client = serenity::Client::builder(token, GatewayIntents::all()).event_handler(Handler).framework(framework).await?;

{
let mut data = client.data.write().await;
let http = Client::builder().user_agent(REQWEST_USER_AGENT).redirect(Policy::none()).build()?;
data.insert::<ReqwestContainer>(http);
}

if let Err(why) = client.start_autosharded().await {
eprintln!("An error occurred while running the client: {why:?}");
}

Ok(())
}

0 comments on commit f7bc928

Please sign in to comment.