From f8bbb22d37a9a8df2f851fa5cceeeb8f3a79b327 Mon Sep 17 00:00:00 2001 From: Ethan Ruszanowski Date: Tue, 31 Jan 2023 22:15:31 -0500 Subject: [PATCH] Connect to Smite API and pick random gods --- src/commands/api.rs | 87 ++++++++++++++++++++++++++++++++++++++++++ src/commands/mod.rs | 2 + src/commands/random.rs | 36 +++++++++++++++++ src/commands/slur.rs | 8 ++-- src/main.rs | 6 ++- 5 files changed, 134 insertions(+), 5 deletions(-) create mode 100644 src/commands/api.rs create mode 100644 src/commands/random.rs diff --git a/src/commands/api.rs b/src/commands/api.rs new file mode 100644 index 0000000..4a1ec37 --- /dev/null +++ b/src/commands/api.rs @@ -0,0 +1,87 @@ +use chrono; +use md5::Digest; +use rand::seq::SliceRandom; +use reqwest::{Error, Response}; +use serde::Deserialize; + +#[derive(Deserialize, Debug)] +struct Session { + ret_msg: String, + session_id: String, + timestamp: String, +} + +#[derive(Deserialize, Debug)] +pub struct God { + #[serde(rename = "Name")] + name: String, + ret_msg: Option, +} + +async fn get_utc_timestamp() -> Result { + let timestamp: String = chrono::Utc::now().format("%Y%m%d%H%M%S").to_string(); + return Ok(timestamp); +} + +async fn get_signature( + dev_id: &String, + method: &str, + auth_key: &String, + timestamp: &String, +) -> Result { + let hash: Digest = md5::compute(format!("{}{}{}{}", dev_id, method, auth_key, timestamp)); + let signature: String = format!("{:x}", hash); + return Ok(signature); +} + +async fn create_session() -> Result { + let dev_id: String = std::env::var("DEV_ID").expect("Missing DEV_ID"); + let auth_key: String = std::env::var("AUTH_KEY").expect("Missing AUTH_KEY"); + let method: &str = "createsession"; + + let timestamp: String = get_utc_timestamp().await?; + let signature: String = get_signature(&dev_id, &method, &auth_key, ×tamp).await?; + + let request: String = format!( + "https://api.smitegame.com/smiteapi.svc/createsessionJson/{dev_id}/{signature}/{timestamp}", + dev_id = dev_id, + signature = signature, + timestamp = timestamp + ); + + let response: Response = reqwest::get(&request).await?; + let session: Session = response.json().await?; + return Ok(session); +} + +async fn get_gods() -> Result, Error> { + let dev_id: String = std::env::var("DEV_ID").expect("Missing DEV_ID"); + let auth_key: String = std::env::var("AUTH_KEY").expect("Missing AUTH_KEY"); + let method: &str = "getgods"; + + let session_id: String = create_session().await?.session_id; + + let timestamp: String = get_utc_timestamp().await?; + let signature: String = get_signature(&dev_id, &method, &auth_key, ×tamp).await?; + + let request: String = format!( + "https://api.smitegame.com/smiteapi.svc/getgodsJson/{id}/{signature}/{session}/{timestamp}/1", + id = dev_id, + signature = signature, + session = session_id, + timestamp = timestamp, + ); + + let response: Response = reqwest::get(&request).await?; + let gods: Vec = response.json().await?; + return Ok(gods); +} + +pub async fn get_random_god() -> Result { + let gods: Vec = get_gods().await?; + let god: &God = gods + .choose(&mut rand::thread_rng()) + .expect("Couldn't pick random god."); + let name: String = god.name.clone(); + return Ok(name); +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 2a105ac..d6aa859 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,3 +1,5 @@ // Group all commands for registration +mod api; +pub mod random; pub mod slur; pub mod team; diff --git a/src/commands/random.rs b/src/commands/random.rs new file mode 100644 index 0000000..b8f1aca --- /dev/null +++ b/src/commands/random.rs @@ -0,0 +1,36 @@ +use crate::commands::api::get_random_god; +use crate::serenity; +use crate::{Context, Error}; + +/// Picks a random something +#[poise::command(slash_command, subcommands("god"))] +pub async fn random(_ctx: Context<'_>) -> Result<(), Error> { + Ok(()) +} + +/// Picks a random god +#[poise::command(slash_command)] +pub async fn god(ctx: Context<'_>) -> Result<(), Error> { + if ctx.author().id == serenity::UserId(310437480216395777) { + ctx.send(|f| { + f.embed(|f| { + f.title("Random God") + .description(format!("You main **Aphrodite**, idiot.")) + .color(serenity::Colour::from_rgb(227, 28, 121)) + }) + }) + .await?; + return Ok(()); + } + + let god: String = get_random_god().await?; + ctx.send(|f| { + f.embed(|f| { + f.title("Random God") + .description(format!("Try not to throw with **{}**, idiot.", god)) + .color(serenity::Colour::BLUE) + }) + }) + .await?; + Ok(()) +} diff --git a/src/commands/slur.rs b/src/commands/slur.rs index 68e225b..7308759 100644 --- a/src/commands/slur.rs +++ b/src/commands/slur.rs @@ -9,16 +9,16 @@ use std::{ /// Basically a ping command #[poise::command(slash_command, prefix_command)] pub async fn slur(ctx: Context<'_>) -> Result<(), Error> { - let file = File::open("quotes.txt").unwrap_or_else(|_e| panic!("Quote file missing.")); // Open the quotes file - let file = BufReader::new(file); // Read the quotes file + let file: File = File::open("quotes.txt").unwrap_or_else(|_e| panic!("Quote file missing.")); // Open the quotes file + let file: BufReader = BufReader::new(file); // Read the quotes file let quotes = file.lines().map(|res| res.expect("Failed to read line.")); - let quote = quotes + let quote: String = quotes .choose(&mut rand::thread_rng()) .expect("No lines in file."); // Pick a random quote ctx.send(|f| { f.embed(|f| { - f.title("DMBrandon Sez:") + f.title("DMBrandon Sez") .description(format!("\"{}\"", quote)) .color(serenity::Colour::GOLD) }) diff --git a/src/main.rs b/src/main.rs index 5485a97..11befb5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,11 @@ type Context<'a> = poise::Context<'a, Data, Error>; async fn main() { let framework = poise::Framework::builder() .options(poise::FrameworkOptions { - commands: vec![commands::slur::slur(), commands::team::team()], // IntelliJ doesn't like this, but it's fine. + commands: vec![ + commands::slur::slur(), + commands::team::team(), + commands::random::random(), + ], // IntelliJ doesn't like this, but it's fine. ..Default::default() }) .token(std::env::var("DISCORD_TOKEN").expect("Missing DISCORD_TOKEN"))