diff --git a/Cargo.lock b/Cargo.lock index e3025d8..9074cb2 100755 --- a/Cargo.lock +++ b/Cargo.lock @@ -1034,8 +1034,10 @@ version = "0.2.8" dependencies = [ "owoify 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)", "serenity 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "sys-info 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "urbandict 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1421,6 +1423,14 @@ dependencies = [ "tokio 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "toml" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.105 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tower-service" version = "0.3.0" @@ -1897,6 +1907,7 @@ dependencies = [ "checksum tokio 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "0fa5e81d6bc4e67fe889d5783bd2a128ab2e0cfa487e0be16b6a8d177b101616" "checksum tokio-rustls 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4adb8b3e5f86b707f1b54e7c15b6de52617a823608ccda98a15d3a24222f265a" "checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" +"checksum toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" "checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" diff --git a/Cargo.toml b/Cargo.toml index 6e87d67..1c72cea 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,9 +9,14 @@ edition = "2018" [dependencies] serenity = "0.8.0" rand = "0.7.3" +toml = "0.5.6" sys-info = "0.6.0" urbandict = "0.2.0" owoify = "0.1.5" [patch.crates-io] openssl = { git = "https://github.com/ishitatsuyuki/rust-openssl", branch = "0.9.x" } + +[dependencies.serde] +version = "1.0.105" +features = ["derive"] diff --git a/src/main.rs b/src/main.rs index 5c77915..f8d3804 100755 --- a/src/main.rs +++ b/src/main.rs @@ -33,7 +33,10 @@ impl EventHandler for Handler { } #[group] -#[commands(init, ping, halt, list_srv, host, ship, headpat, uwu, gayculator, waffle, sausage, help, compare_bot, what, owo, info)] +#[commands( + init, ping, halt, list_srv, host, ship, headpat, uwu, gayculator, waffle, sausage, help, embed, + what, owo, info +)] struct General; fn main() { @@ -131,10 +134,9 @@ fn list_srv(ctx: &mut Context, message: &Message) -> CommandResult { let guild = guild_lock.read(); list.push_str(&format!("{}: {}\n", index, guild.name)); } - let _ = message.channel_id.say( - &ctx.http, - list.replace("@", "@\u{200B}"), - ); + let _ = message + .channel_id + .say(&ctx.http, list.replace("@", "@\u{200B}")); Ok(()) } @@ -155,60 +157,142 @@ fn host(ctx: &mut Context, message: &Message) -> CommandResult { } #[command] -fn ship(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { - /*use std::collections::hash_map::DefaultHasher; - use std::hash::{Hash, Hasher}; +#[checks(Owner)] +fn embed(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { + use serde::Deserialize; + use serenity::utils::Colour; - let first = calculate_hash( - &args - .single::() - .unwrap_or_else(|_| "Null".to_string()), - ); - let second = calculate_hash( - &args - .single::() - .unwrap_or_else(|_| "Null".to_string()), - ); - let mut slider = String::new(); - let res = (first % second) / 100000000000000000; + #[derive(Deserialize)] + struct EmbedProperties { + author: [Option; 2], + colour: u32, + description: Option, + fields: Vec<(String, String, bool)>, + footer: [Option; 2], + image: Option, + timestamp: Option, + title: Option, + url: Option, + } + + let input_embed: EmbedProperties = + toml::from_str(args.rest().trim()).unwrap_or(EmbedProperties { + author: [None, None], + colour: 0x000000, + description: None, + fields: vec![], + footer: [None, None], + image: None, + timestamp: None, + title: None, + url: None, + }); - let mut num = 0; - while num < res / 10 { - slider.push('▬'); - num += 1; - } - slider.push_str(":purple_heart:"); - num = 0; - while num < (10 - res / 10) { - slider.push('▬'); - num += 1; - } let _ = message.channel_id.send_message(&ctx.http, |m| { m.embed(|e| { - e.title(format!("{}%", res)) - .description(slider) - .color(0xffd1dc) - }) + // Set embed author unless empty + if input_embed.author != [None, None] { + let auth = input_embed.author; + e.author(|a| { + //assumin first array element is name and second is icon url + a.name(auth[0].as_ref().unwrap()); + a.icon_url(auth[1].as_ref().unwrap()); + + a + }); + } + + e.color(Colour::new(input_embed.colour)); + // Set embed description unless empty + if input_embed.description != None { + e.description(input_embed.description.unwrap()); + } + e.fields(input_embed.fields); + + // Set embed footer unless empty + if input_embed.footer != [None, None] { + let foot = input_embed.footer; + e.footer(|f| { + f.text(&foot[0].as_ref().unwrap()); + f.icon_url(&foot[1].as_ref().unwrap()); + + f + }); + } + + if input_embed.image != None { + e.image(input_embed.image.unwrap()); + } + + if input_embed.timestamp != None { + e.timestamp(input_embed.timestamp.unwrap()); + } + + if input_embed.title != None { + e.title(input_embed.title.unwrap()); + } + + if input_embed.url != None { + e.url(input_embed.url.unwrap()); + } + + e + }); + m }); + Ok(()) +} + +#[command] +fn ship(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { + use rand::{rngs::StdRng, SeedableRng}; + use std::collections::hash_map::DefaultHasher; + use std::hash::{Hash, Hasher}; + + // Calculates hash of a type that implements Hash fn calculate_hash(t: &T) -> u64 { let mut s = DefaultHasher::new(); t.hash(&mut s); s.finish() - } */ + } + // Get input names let names: String = args.rest().trim().to_string(); - let names = names.split_whitespace().map(|x| x.to_owned()).collect::>(); + // Calculate compatibility based on hash + let compat: u64 = StdRng::seed_from_u64(calculate_hash(&names)).gen_range(0, 100); + + // Initialize a bar to display compatibility percentage + let mut compbar = String::new(); + + let mut num = 0; + while num < compat / 10 { + compbar.push('▬'); + num += 1; + } + compbar.push_str(":purple_heart:"); + num = 0; + while num < (10 - compat / 10) { + compbar.push('▬'); + num += 1; + } + + // Convert names to a Vec + let names = names + .split_whitespace() + .map(|x| x.to_owned()) + .collect::>(); + let shipname: Result = match names.len() { 0 => Err(()), 1 => Ok(names[0].clone()), _ => { let mut first_halves = String::new(); - for name in &names[0..names.len()-1] { + for name in &names[0..names.len() - 1] { first_halves.push_str(&name[0..name.len() / 2]); } let first_halves = first_halves.as_str(); - let last_half = &names[names.len()-1][(names.len() / 2)+1..]; + let last_half = &names[names.len() - 1][(names.len() / 2) + 1..]; Ok(format!("{}{}", first_halves, last_half)) } @@ -216,8 +300,13 @@ fn ship(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { let _ = message.channel_id.send_message(&ctx.http, |m| { m.embed(|e| { - e.title("Ship name:".to_string()) - .description(shipname.unwrap_or_else(|_| "Invalid input!".to_string())) + e.title(format!("Original names: {}", args.rest().trim())) + .description(format!( + "Ship name:\n{}\nCompatibility: **{}%**\n{}", + shipname.unwrap_or_else(|_| "Invalid input!".to_string()), + compat, + compbar + )) .color(0xffd1dc) }) }); @@ -349,26 +438,27 @@ fn help(ctx: &mut Context, message: &Message) -> CommandResult { ("owo sausage", "sosig", false), ("owo help", "Help the fellow humanz!", false), ("owo info", "Show information about me!", false), - ( + /* ( "owo compare_bot ``bot's name``", "Compare me to other robots!", false, - ), + ), */ ( "owo what's this ``word``", "Find a definition of word", false, ), - ( - "owo ship ``name 1`` ``name 2``", - "*shipping intensifies*", - false, - ), + ("owo ship ``[names]``", "*shipping intensifies*", false), ("owo headpat ``name``", "Headpat someone", false), ("owo owo ``text``", "owoify input text", false), ("Admin commands:", "\u{200B}", true), ("owo halt", "kill me", false), ("owo list_srv", "list my servers", false), + ( + "owo embed ``[args]``", + "Create an embed from a Toml object", + false, + ), ("owo host", "Display host info", false), ]) .color(0xffd1dc) @@ -395,6 +485,7 @@ fn info(ctx: &mut Context, message: &Message) -> CommandResult { Ok(()) } +/* #[command] #[aliases("compare")] fn compare_bot(ctx: &mut Context, message: &Message, mut args: Args) -> CommandResult { @@ -417,6 +508,7 @@ fn compare_bot(ctx: &mut Context, message: &Message, mut args: Args) -> CommandR } Ok(()) } +*/ #[command] #[aliases("what's this")] @@ -425,9 +517,7 @@ fn what(ctx: &mut Context, message: &Message, args: Args) -> CommandResult { let defs = &urbandict::get_definitions(&text); match defs { Err(_e) => { - let _ = message - .channel_id - .say(&ctx.http, "Invalid query >w<".to_string()); + let _ = message.channel_id.say(&ctx.http, "Invalid query >w<"); } Ok(v) => { if !v.is_empty() {