Merge pull request #3 from ethanrusz/random-god

Pick a random god from Smite API!
This commit is contained in:
Em (Ethan) Ruszanowski 2023-01-31 22:20:05 -05:00 committed by GitHub
commit 584d4ef62c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 139 additions and 10 deletions

87
src/commands/api.rs Normal file
View file

@ -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<String>,
}
async fn get_utc_timestamp() -> Result<String, Error> {
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<String, Error> {
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<Session, 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 = "createsession";
let timestamp: String = get_utc_timestamp().await?;
let signature: String = get_signature(&dev_id, &method, &auth_key, &timestamp).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<Vec<God>, 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, &timestamp).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<God> = response.json().await?;
return Ok(gods);
}
pub async fn get_random_god() -> Result<String, Error> {
let gods: Vec<God> = 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);
}

View file

@ -1,3 +1,5 @@
// Group all commands for registration
pub(crate) mod slur;
pub(crate) mod team;
mod api;
pub mod random;
pub mod slur;
pub mod team;

36
src/commands/random.rs Normal file
View file

@ -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(())
}

View file

@ -8,17 +8,17 @@ use std::{
/// Basically a ping command
#[poise::command(slash_command, prefix_command)]
pub(crate) 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
pub async fn slur(ctx: Context<'_>) -> Result<(), Error> {
let file: File = File::open("quotes.txt").unwrap_or_else(|_e| panic!("Quote file missing.")); // Open the quotes file
let file: BufReader<File> = 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)
})

View file

@ -18,7 +18,7 @@ fn team_to_ping(team: &[&String]) -> String {
/// Splits up players for custom matches
#[poise::command(slash_command)]
pub(crate) async fn team(
pub async fn team(
ctx: Context<'_>,
#[description = "Your order voice channel"]
#[rename = "order"]

View file

@ -2,7 +2,7 @@ use poise::serenity_prelude as serenity;
mod commands;
struct Data {}
pub struct Data {}
type Error = Box<dyn std::error::Error + Send + Sync>;
type Context<'a> = poise::Context<'a, Data, Error>;
@ -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"))