forked from sorceress/rustcord
Move long commands to separate files
This commit is contained in:
parent
eb77c2ca37
commit
4332bf5200
|
@ -0,0 +1,54 @@
|
||||||
|
use serenity::{
|
||||||
|
framework::standard::{macros::command, Args, CommandError, CommandResult},
|
||||||
|
model::channel::Message,
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
// brainfuck interpreter
|
||||||
|
#[command]
|
||||||
|
#[aliases("bf", "brainfrick")]
|
||||||
|
fn brainfuck(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
||||||
|
use brainfrick::Brainfuck;
|
||||||
|
|
||||||
|
let input = match args.rest().trim() {
|
||||||
|
"" => {
|
||||||
|
return Err(CommandError(s!("Called without input!")));
|
||||||
|
}
|
||||||
|
v @ _ => v,
|
||||||
|
};
|
||||||
|
let output = Brainfuck::execute(input);
|
||||||
|
|
||||||
|
match output {
|
||||||
|
Ok(v) => {
|
||||||
|
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
||||||
|
m.embed(|e| {
|
||||||
|
e.title("Brainfuck interpreter")
|
||||||
|
.description(format!(
|
||||||
|
"Input\n```brainfuck\n{}\n```\nOutput:\n```{}\n```",
|
||||||
|
input, v
|
||||||
|
))
|
||||||
|
.author(|a| {
|
||||||
|
a.name(&message.author.name)
|
||||||
|
.icon_url(message.author.avatar_url().unwrap())
|
||||||
|
})
|
||||||
|
.colour(0xffd1dc)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
||||||
|
m.embed(|e| {
|
||||||
|
e.title("Brainfuck interpreter")
|
||||||
|
.description(format!("Error at:\n```\n{}:{}\n```", err.line(), err.col()))
|
||||||
|
.author(|a| {
|
||||||
|
a.name(&message.author.name)
|
||||||
|
.icon_url(message.author.avatar_url().unwrap())
|
||||||
|
})
|
||||||
|
.colour(0xff6961)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
use serenity::{
|
||||||
|
framework::standard::{macros::command, Args, CommandError, CommandResult},
|
||||||
|
model::channel::Message,
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Urban Dictionary lookup
|
||||||
|
#[command]
|
||||||
|
#[aliases("what's this")]
|
||||||
|
fn define(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
||||||
|
let text: String = args.rest().trim().to_string();
|
||||||
|
let defs = &urbandict::get_definitions(&text);
|
||||||
|
if !args.is_empty() {
|
||||||
|
match defs {
|
||||||
|
Err(_e) => {
|
||||||
|
return Err(CommandError(s!("Invalid query >w<")));
|
||||||
|
}
|
||||||
|
Ok(v) => {
|
||||||
|
if !v.is_empty() {
|
||||||
|
let def = &v[0];
|
||||||
|
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
||||||
|
m.embed(|e| {
|
||||||
|
e.title(format!("Query: {}, Author: {}", text, def.author))
|
||||||
|
.field(
|
||||||
|
"Definition: ",
|
||||||
|
def.definition.replace(|c| c == '[' || c == ']', ""),
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.color(0xffd1dc)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Err(CommandError(s!("No results!")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
use serenity::{
|
||||||
|
framework::standard::{macros::command, Args, CommandError, CommandResult},
|
||||||
|
model::channel::Message,
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
#[command]
|
||||||
|
fn embed(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serenity::utils::Colour;
|
||||||
|
use std::{fs, io::prelude::*};
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct EmbedProperties {
|
||||||
|
author: Option<(String, String)>,
|
||||||
|
colour: Option<String>,
|
||||||
|
description: Option<String>,
|
||||||
|
fields: Option<Vec<(String, String, bool)>>,
|
||||||
|
footer: Option<(String, String)>,
|
||||||
|
image: Option<String>,
|
||||||
|
thumbnail: Option<String>,
|
||||||
|
timestamp: Option<String>,
|
||||||
|
title: Option<String>,
|
||||||
|
url: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// print documentation from src/embed-docs.txt
|
||||||
|
if s!(&args.rest().trim()) == "help" {
|
||||||
|
let mut file = fs::File::open("./src/commands/embed-docs.txt")?;
|
||||||
|
let mut help_string = String::new();
|
||||||
|
file.read_to_string(&mut help_string)?;
|
||||||
|
|
||||||
|
let _ = message.channel_id.say(&ctx.http, help_string);
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let input_embed: EmbedProperties = match toml::from_str(&args.rest().trim()) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(CommandError(format!("Deserialization error: {:?}", e)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
||||||
|
m.embed(|e| {
|
||||||
|
// Set embed author unless empty
|
||||||
|
if input_embed.author.is_some() {
|
||||||
|
let auth = input_embed.author.unwrap();
|
||||||
|
e.author(|a| {
|
||||||
|
//assuming first array element is name and second is icon url
|
||||||
|
a.name(auth.0);
|
||||||
|
a.icon_url(auth.1);
|
||||||
|
|
||||||
|
a
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set embed colour unless empty
|
||||||
|
if input_embed.colour.is_some() {
|
||||||
|
e.color(Colour::new(
|
||||||
|
u32::from_str_radix(&input_embed.colour.unwrap(), 16)
|
||||||
|
.ok()
|
||||||
|
.unwrap_or(0x000000),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set embed description unless empty
|
||||||
|
if input_embed.description.is_some() {
|
||||||
|
e.description(input_embed.description.unwrap());
|
||||||
|
}
|
||||||
|
// Set embed fields unless empty
|
||||||
|
if input_embed.fields.is_some() {
|
||||||
|
e.fields(input_embed.fields.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set embed footer unless empty
|
||||||
|
if input_embed.footer.is_some() {
|
||||||
|
let foot = input_embed.footer.unwrap();
|
||||||
|
e.footer(|f| {
|
||||||
|
//assuming first array element is name and second is icon url
|
||||||
|
f.text(foot.0);
|
||||||
|
f.icon_url(foot.1);
|
||||||
|
|
||||||
|
f
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if input_embed.image.is_some() {
|
||||||
|
e.image(input_embed.image.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if input_embed.thumbnail.is_some() {
|
||||||
|
e.thumbnail(input_embed.thumbnail.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if input_embed.timestamp.is_some() {
|
||||||
|
e.timestamp(input_embed.timestamp.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if input_embed.title.is_some() {
|
||||||
|
e.title(input_embed.title.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if input_embed.url.is_some() {
|
||||||
|
e.url(input_embed.url.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
e
|
||||||
|
});
|
||||||
|
m
|
||||||
|
});
|
||||||
|
|
||||||
|
let _ = message
|
||||||
|
.channel_id
|
||||||
|
.say(&ctx.http, format!("Embed requested by: {}", message.author));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
use serenity::{
|
||||||
|
framework::standard::{macros::command, CommandResult},
|
||||||
|
model::channel::Message,
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
fn help(ctx: &mut Context, message: &Message) -> CommandResult {
|
||||||
|
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
||||||
|
m.embed(|e| {
|
||||||
|
e.title("Availble commands:")
|
||||||
|
.description("All commands are case-insensitive")
|
||||||
|
.fields(vec![
|
||||||
|
("owo!init", "Introduce me", true),
|
||||||
|
("owo!ping", "Pong", true),
|
||||||
|
("owo!sausage", "Sosig", true),
|
||||||
|
("owo!help", "Help the fellow humanz!", true),
|
||||||
|
("owo!info", "Show information about me!", true),
|
||||||
|
(
|
||||||
|
"owo!what's this ``word``",
|
||||||
|
"Find a definition of word",
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"owo!embed ``[args]`` *OR* help",
|
||||||
|
"Create an embed from a Toml object",
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
("owo!desc", "Display channel's topic", true),
|
||||||
|
(
|
||||||
|
"owo!pinned ``num`` ``<channel>``",
|
||||||
|
"Display channel's Nth pinned message. Channel name is optional",
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
("owo!pfp ``@username``", "Post user's profile picture", true),
|
||||||
|
("owo!brainfuck ``input``", "Execute input code", true),
|
||||||
|
("owo!ship ``[names]``", "*Shipping intensifies*", true),
|
||||||
|
("owo!headpat ``name``", "Headpat someone", true),
|
||||||
|
("owo!owo ``text``", "owoify input text", true),
|
||||||
|
("\u{200B}", "**Admin commands:**", false),
|
||||||
|
("owo!halt", "Kill the bot process", true),
|
||||||
|
("owo!status ``[args]``", "Sets the bot status", true),
|
||||||
|
("owo!servers", "List the servers I'm in", true),
|
||||||
|
("owo!host", "Display host info", true),
|
||||||
|
])
|
||||||
|
.color(0xffd1dc)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
pub mod brainfuck;
|
||||||
|
pub mod define;
|
||||||
|
pub mod embed;
|
||||||
|
pub mod help;
|
||||||
|
pub mod pinned;
|
||||||
|
pub mod ship;
|
|
@ -0,0 +1,55 @@
|
||||||
|
use serenity::{
|
||||||
|
framework::standard::{macros::command, Args, CommandError, CommandResult},
|
||||||
|
model::{channel::Message, id::ChannelId},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Prints Nth pinned message
|
||||||
|
#[command]
|
||||||
|
fn pinned(ctx: &mut Context, message: &Message, mut args: Args) -> CommandResult {
|
||||||
|
// defaults to latest pinned message if no args are provided
|
||||||
|
let mut idx = args.single::<usize>().unwrap_or(1);
|
||||||
|
// Makes pinned messages 1-indexed
|
||||||
|
if idx != 0 {
|
||||||
|
idx -= 1;
|
||||||
|
}
|
||||||
|
let target_channel = match args.single::<ChannelId>() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(_) => message.channel_id,
|
||||||
|
};
|
||||||
|
let pinned = match target_channel.pins(&ctx.http) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
return Err(CommandError(s!(format!(
|
||||||
|
"Could not get pinned messages! Error: {}",
|
||||||
|
e
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if pinned.is_empty() {
|
||||||
|
return Err(CommandError(s!("No pinned messages found!")));
|
||||||
|
}
|
||||||
|
if idx > pinned.len() - 1 {
|
||||||
|
return Err(CommandError(s!("Index out of bounds!")));
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
||||||
|
m.embed(|e| {
|
||||||
|
e.title(format!("Pinned message #{}", idx + 1))
|
||||||
|
.description(&pinned[idx].content)
|
||||||
|
.timestamp(&pinned[idx].timestamp);
|
||||||
|
e.author(|a| {
|
||||||
|
a.name(&pinned[idx].author.name)
|
||||||
|
.icon_url(&pinned[idx].author.avatar_url().unwrap())
|
||||||
|
});
|
||||||
|
e.colour(0xffd1dc);
|
||||||
|
if !&pinned[idx].attachments.is_empty() {
|
||||||
|
e.image(&pinned[idx].attachments[0].url);
|
||||||
|
}
|
||||||
|
|
||||||
|
e
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
use crate::utils::calculate_hash;
|
||||||
|
use rand::Rng;
|
||||||
|
use serenity::{
|
||||||
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
|
model::channel::Message,
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[command]
|
||||||
|
fn ship(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
||||||
|
use rand::{rngs::StdRng, SeedableRng};
|
||||||
|
|
||||||
|
// Get input names
|
||||||
|
let names: String = args.rest().trim().to_string();
|
||||||
|
// Calculate compatibility based on hash
|
||||||
|
let compat: u64 = StdRng::seed_from_u64(calculate_hash(&names)).gen_range(50, 100);
|
||||||
|
|
||||||
|
// Initialize a bar to display compatibility percentage
|
||||||
|
let mut compbar = String::from("----------");
|
||||||
|
compbar.insert_str((compat / 10) as usize, ":purple_heart:");
|
||||||
|
|
||||||
|
// Convert names to a Vec<String>
|
||||||
|
let names = names
|
||||||
|
.split_whitespace()
|
||||||
|
.map(|x| x.to_owned())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
|
// Concatenate names together
|
||||||
|
let shipname: Result<String, String> = match names.len() {
|
||||||
|
0 => Err(s!("Invalid input!")),
|
||||||
|
1 => Ok(names[0].clone()),
|
||||||
|
_ => {
|
||||||
|
let mut first_halves = String::new();
|
||||||
|
for name in &names[0..names.len() - 1] {
|
||||||
|
first_halves += &name[0..name.len() / 2];
|
||||||
|
}
|
||||||
|
let first_halves = first_halves.as_str();
|
||||||
|
let last_half = &names[names.len() - 1][(names.len() / 2) + 1..];
|
||||||
|
|
||||||
|
Ok(format!("{}{}", first_halves, last_half))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = shipname {
|
||||||
|
let _ = message.channel_id.say(&ctx.http, e);
|
||||||
|
} else {
|
||||||
|
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
||||||
|
m.embed(|e| {
|
||||||
|
e.title(format!("Original names: {}", args.rest().trim()))
|
||||||
|
.description(format!(
|
||||||
|
"Ship name:\n**{}**\nCompatibility: **{}%**\n{}",
|
||||||
|
shipname.unwrap(),
|
||||||
|
compat,
|
||||||
|
compbar
|
||||||
|
))
|
||||||
|
.color(0xffd1dc)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
365
src/main.rs
365
src/main.rs
|
@ -15,12 +15,7 @@ use serenity::{
|
||||||
Args, CheckResult, CommandError, CommandOptions, CommandResult, DispatchError, Reason,
|
Args, CheckResult, CommandError, CommandOptions, CommandResult, DispatchError, Reason,
|
||||||
StandardFramework,
|
StandardFramework,
|
||||||
},
|
},
|
||||||
model::{
|
model::{channel::Message, gateway::Ready, id::UserId, user::OnlineStatus},
|
||||||
channel::Message,
|
|
||||||
gateway::Ready,
|
|
||||||
id::{ChannelId, UserId},
|
|
||||||
user::OnlineStatus,
|
|
||||||
},
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
use std::{env, process, sync::Arc};
|
use std::{env, process, sync::Arc};
|
||||||
|
@ -29,6 +24,9 @@ use std::{env, process, sync::Arc};
|
||||||
mod utils;
|
mod utils;
|
||||||
use utils::*;
|
use utils::*;
|
||||||
|
|
||||||
|
mod commands;
|
||||||
|
use commands::{brainfuck::*, define::*, embed::*, help::*, pinned::*, ship::*};
|
||||||
|
|
||||||
struct Handler;
|
struct Handler;
|
||||||
|
|
||||||
struct ShardManagerContainer;
|
struct ShardManagerContainer;
|
||||||
|
@ -76,7 +74,6 @@ lazy_static! {
|
||||||
vec![UserId(254310746450690048), UserId(687740609703706630)];
|
vec![UserId(254310746450690048), UserId(687740609703706630)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut client = Client::new(&env::var("DISCORD_TOKEN").expect("Invalid token"), Handler)
|
let mut client = Client::new(&env::var("DISCORD_TOKEN").expect("Invalid token"), Handler)
|
||||||
.expect("Error creating client");
|
.expect("Error creating client");
|
||||||
|
@ -176,9 +173,9 @@ fn ping(ctx: &mut Context, message: &Message) -> CommandResult {
|
||||||
let shard_manager = match data.get::<ShardManagerContainer>() {
|
let shard_manager = match data.get::<ShardManagerContainer>() {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => {
|
None => {
|
||||||
return Err(CommandError(
|
return Err(CommandError(s!(
|
||||||
s!("There was a problem getting the shard manager!"),
|
"There was a problem getting the shard manager!"
|
||||||
))
|
)))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -298,120 +295,6 @@ fn host(ctx: &mut Context, message: &Message) -> CommandResult {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
|
||||||
fn embed(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
|
||||||
use serde::Deserialize;
|
|
||||||
use serenity::utils::Colour;
|
|
||||||
use std::{fs, io::prelude::*};
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct EmbedProperties {
|
|
||||||
author: Option<(String, String)>,
|
|
||||||
colour: Option<String>,
|
|
||||||
description: Option<String>,
|
|
||||||
fields: Option<Vec<(String, String, bool)>>,
|
|
||||||
footer: Option<(String, String)>,
|
|
||||||
image: Option<String>,
|
|
||||||
thumbnail: Option<String>,
|
|
||||||
timestamp: Option<String>,
|
|
||||||
title: Option<String>,
|
|
||||||
url: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
// print documentation from src/embed-docs.txt
|
|
||||||
if s!(&args.rest().trim()) == "help" {
|
|
||||||
let mut file = fs::File::open("./src/embed-docs.txt")?;
|
|
||||||
let mut help_string = String::new();
|
|
||||||
file.read_to_string(&mut help_string)?;
|
|
||||||
|
|
||||||
let _ = message.channel_id.say(&ctx.http, help_string);
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let input_embed: EmbedProperties = match toml::from_str(&args.rest().trim()) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(CommandError(format!("Deserialization error: {:?}", e)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
|
||||||
m.embed(|e| {
|
|
||||||
// Set embed author unless empty
|
|
||||||
if input_embed.author.is_some() {
|
|
||||||
let auth = input_embed.author.unwrap();
|
|
||||||
e.author(|a| {
|
|
||||||
//assuming first array element is name and second is icon url
|
|
||||||
a.name(auth.0);
|
|
||||||
a.icon_url(auth.1);
|
|
||||||
|
|
||||||
a
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set embed colour unless empty
|
|
||||||
if input_embed.colour.is_some() {
|
|
||||||
e.color(Colour::new(
|
|
||||||
u32::from_str_radix(&input_embed.colour.unwrap(), 16)
|
|
||||||
.ok()
|
|
||||||
.unwrap_or(0x000000),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set embed description unless empty
|
|
||||||
if input_embed.description.is_some() {
|
|
||||||
e.description(input_embed.description.unwrap());
|
|
||||||
}
|
|
||||||
// Set embed fields unless empty
|
|
||||||
if input_embed.fields.is_some() {
|
|
||||||
e.fields(input_embed.fields.unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set embed footer unless empty
|
|
||||||
if input_embed.footer.is_some() {
|
|
||||||
let foot = input_embed.footer.unwrap();
|
|
||||||
e.footer(|f| {
|
|
||||||
//assuming first array element is name and second is icon url
|
|
||||||
f.text(foot.0);
|
|
||||||
f.icon_url(foot.1);
|
|
||||||
|
|
||||||
f
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if input_embed.image.is_some() {
|
|
||||||
e.image(input_embed.image.unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
if input_embed.thumbnail.is_some() {
|
|
||||||
e.thumbnail(input_embed.thumbnail.unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
if input_embed.timestamp.is_some() {
|
|
||||||
e.timestamp(input_embed.timestamp.unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
if input_embed.title.is_some() {
|
|
||||||
e.title(input_embed.title.unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
if input_embed.url.is_some() {
|
|
||||||
e.url(input_embed.url.unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
e
|
|
||||||
});
|
|
||||||
m
|
|
||||||
});
|
|
||||||
|
|
||||||
let _ = message
|
|
||||||
.channel_id
|
|
||||||
.say(&ctx.http, format!("Embed requested by: {}", message.author));
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate a random number using a keysmash as seed
|
// generate a random number using a keysmash as seed
|
||||||
#[command]
|
#[command]
|
||||||
fn bottom_rng(ctx: &mut Context, message: &Message, mut args: Args) -> CommandResult {
|
fn bottom_rng(ctx: &mut Context, message: &Message, mut args: Args) -> CommandResult {
|
||||||
|
@ -445,61 +328,6 @@ fn bottom_rng(ctx: &mut Context, message: &Message, mut args: Args) -> CommandRe
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
|
||||||
fn ship(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
|
||||||
use rand::{rngs::StdRng, SeedableRng};
|
|
||||||
|
|
||||||
// Get input names
|
|
||||||
let names: String = args.rest().trim().to_string();
|
|
||||||
// Calculate compatibility based on hash
|
|
||||||
let compat: u64 = StdRng::seed_from_u64(calculate_hash(&names)).gen_range(50, 100);
|
|
||||||
|
|
||||||
// Initialize a bar to display compatibility percentage
|
|
||||||
let mut compbar = String::from("----------");
|
|
||||||
compbar.insert_str((compat / 10) as usize, ":purple_heart:");
|
|
||||||
|
|
||||||
// Convert names to a Vec<String>
|
|
||||||
let names = names
|
|
||||||
.split_whitespace()
|
|
||||||
.map(|x| x.to_owned())
|
|
||||||
.collect::<Vec<String>>();
|
|
||||||
|
|
||||||
// Concatenate names together
|
|
||||||
let shipname: Result<String, String> = match names.len() {
|
|
||||||
0 => Err(s!("Invalid input!")),
|
|
||||||
1 => Ok(names[0].clone()),
|
|
||||||
_ => {
|
|
||||||
let mut first_halves = String::new();
|
|
||||||
for name in &names[0..names.len() - 1] {
|
|
||||||
first_halves += &name[0..name.len() / 2];
|
|
||||||
}
|
|
||||||
let first_halves = first_halves.as_str();
|
|
||||||
let last_half = &names[names.len() - 1][(names.len() / 2) + 1..];
|
|
||||||
|
|
||||||
Ok(format!("{}{}", first_halves, last_half))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(e) = shipname {
|
|
||||||
let _ = message.channel_id.say(&ctx.http, e);
|
|
||||||
} else {
|
|
||||||
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
|
||||||
m.embed(|e| {
|
|
||||||
e.title(format!("Original names: {}", args.rest().trim()))
|
|
||||||
.description(format!(
|
|
||||||
"Ship name:\n**{}**\nCompatibility: **{}%**\n{}",
|
|
||||||
shipname.unwrap(),
|
|
||||||
compat,
|
|
||||||
compbar
|
|
||||||
))
|
|
||||||
.color(0xffd1dc)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
#[aliases("pat")]
|
#[aliases("pat")]
|
||||||
fn headpat(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
fn headpat(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
||||||
|
@ -590,52 +418,6 @@ fn sausage(ctx: &mut Context, message: &Message) -> CommandResult {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
|
||||||
fn help(ctx: &mut Context, message: &Message) -> CommandResult {
|
|
||||||
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
|
||||||
m.embed(|e| {
|
|
||||||
e.title("Availble commands:")
|
|
||||||
.description("All commands are case-insensitive")
|
|
||||||
.fields(vec![
|
|
||||||
("owo!init", "Introduce me", true),
|
|
||||||
("owo!ping", "Pong", true),
|
|
||||||
("owo!sausage", "Sosig", true),
|
|
||||||
("owo!help", "Help the fellow humanz!", true),
|
|
||||||
("owo!info", "Show information about me!", true),
|
|
||||||
(
|
|
||||||
"owo!what's this ``word``",
|
|
||||||
"Find a definition of word",
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"owo!embed ``[args]`` *OR* help",
|
|
||||||
"Create an embed from a Toml object",
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
("owo!desc", "Display channel's topic", true),
|
|
||||||
(
|
|
||||||
"owo!pinned ``num`` ``<channel>``",
|
|
||||||
"Display channel's Nth pinned message. Channel name is optional",
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
("owo!pfp ``@username``", "Post user's profile picture", true),
|
|
||||||
("owo!brainfuck ``input``", "Execute input code", true),
|
|
||||||
("owo!ship ``[names]``", "*Shipping intensifies*", true),
|
|
||||||
("owo!headpat ``name``", "Headpat someone", true),
|
|
||||||
("owo!owo ``text``", "owoify input text", true),
|
|
||||||
("\u{200B}", "**Admin commands:**", false),
|
|
||||||
("owo!halt", "Kill the bot process", true),
|
|
||||||
("owo!status ``[args]``", "Sets the bot status", true),
|
|
||||||
("owo!servers", "List the servers I'm in", true),
|
|
||||||
("owo!host", "Display host info", true),
|
|
||||||
])
|
|
||||||
.color(0xffd1dc)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
fn info(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
fn info(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
||||||
if !args.is_empty() {
|
if !args.is_empty() {
|
||||||
|
@ -660,41 +442,6 @@ fn info(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Urban Dictionary lookup
|
|
||||||
#[command]
|
|
||||||
#[aliases("what's this")]
|
|
||||||
fn define(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
|
||||||
let text: String = args.rest().trim().to_string();
|
|
||||||
let defs = &urbandict::get_definitions(&text);
|
|
||||||
if !args.is_empty() {
|
|
||||||
match defs {
|
|
||||||
Err(_e) => {
|
|
||||||
return Err(CommandError(s!("Invalid query >w<")));
|
|
||||||
}
|
|
||||||
Ok(v) => {
|
|
||||||
if !v.is_empty() {
|
|
||||||
let def = &v[0];
|
|
||||||
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
|
||||||
m.embed(|e| {
|
|
||||||
e.title(format!("Query: {}, Author: {}", text, def.author))
|
|
||||||
.field(
|
|
||||||
"Definition: ",
|
|
||||||
def.definition.replace(|c| c == '[' || c == ']', ""),
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.color(0xffd1dc)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return Err(CommandError(s!("No results!")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
fn pfp(ctx: &mut Context, message: &Message) -> CommandResult {
|
fn pfp(ctx: &mut Context, message: &Message) -> CommandResult {
|
||||||
// Get username from first mention, otherwise use current username
|
// Get username from first mention, otherwise use current username
|
||||||
|
@ -764,101 +511,3 @@ fn desc(ctx: &mut Context, message: &Message) -> CommandResult {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prints Nth pinned message
|
|
||||||
#[command]
|
|
||||||
fn pinned(ctx: &mut Context, message: &Message, mut args: Args) -> CommandResult {
|
|
||||||
// defaults to latest pinned message if no args are provided
|
|
||||||
let mut idx = args.single::<usize>().unwrap_or(1);
|
|
||||||
// Makes pinned messages 1-indexed
|
|
||||||
if idx != 0 {
|
|
||||||
idx -= 1;
|
|
||||||
}
|
|
||||||
let target_channel = match args.single::<ChannelId>() {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(_) => message.channel_id,
|
|
||||||
};
|
|
||||||
let pinned = match target_channel.pins(&ctx.http) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(CommandError(
|
|
||||||
s!(format!("Could not get pinned messages! Error: {}", e)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if pinned.is_empty() {
|
|
||||||
return Err(CommandError(s!("No pinned messages found!")));
|
|
||||||
}
|
|
||||||
if idx > pinned.len() - 1 {
|
|
||||||
return Err(CommandError(s!("Index out of bounds!")));
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
|
||||||
m.embed(|e| {
|
|
||||||
e.title(format!("Pinned message #{}", idx + 1))
|
|
||||||
.description(&pinned[idx].content)
|
|
||||||
.timestamp(&pinned[idx].timestamp);
|
|
||||||
e.author(|a| {
|
|
||||||
a.name(&pinned[idx].author.name)
|
|
||||||
.icon_url(&pinned[idx].author.avatar_url().unwrap())
|
|
||||||
});
|
|
||||||
e.colour(0xffd1dc);
|
|
||||||
if !&pinned[idx].attachments.is_empty() {
|
|
||||||
e.image(&pinned[idx].attachments[0].url);
|
|
||||||
}
|
|
||||||
|
|
||||||
e
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// brainfuck interpreter
|
|
||||||
#[command]
|
|
||||||
#[aliases("bf", "brainfrick")]
|
|
||||||
fn brainfuck(ctx: &mut Context, message: &Message, args: Args) -> CommandResult {
|
|
||||||
use brainfrick::Brainfuck;
|
|
||||||
|
|
||||||
let input = match args.rest().trim() {
|
|
||||||
"" => {
|
|
||||||
return Err(CommandError(s!("Called without input!")));
|
|
||||||
}
|
|
||||||
v @ _ => v,
|
|
||||||
};
|
|
||||||
let output = Brainfuck::execute(input);
|
|
||||||
|
|
||||||
match output {
|
|
||||||
Ok(v) => {
|
|
||||||
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
|
||||||
m.embed(|e| {
|
|
||||||
e.title("Brainfuck interpreter")
|
|
||||||
.description(format!(
|
|
||||||
"Input\n```brainfuck\n{}\n```\nOutput:\n```{}\n```",
|
|
||||||
input, v
|
|
||||||
))
|
|
||||||
.author(|a| {
|
|
||||||
a.name(&message.author.name)
|
|
||||||
.icon_url(message.author.avatar_url().unwrap())
|
|
||||||
})
|
|
||||||
.colour(0xffd1dc)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
let _ = message.channel_id.send_message(&ctx.http, |m| {
|
|
||||||
m.embed(|e| {
|
|
||||||
e.title("Brainfuck interpreter")
|
|
||||||
.description(format!("Error at:\n```\n{}:{}\n```", err.line(), err.col()))
|
|
||||||
.author(|a| {
|
|
||||||
a.name(&message.author.name)
|
|
||||||
.icon_url(message.author.avatar_url().unwrap())
|
|
||||||
})
|
|
||||||
.colour(0xff6961)
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
use std::{collections::hash_map::DefaultHasher, hash::{Hasher, Hash}};
|
use std::{
|
||||||
|
collections::hash_map::DefaultHasher,
|
||||||
|
hash::{Hash, Hasher},
|
||||||
|
};
|
||||||
|
|
||||||
|
// shorter version of .to_string()
|
||||||
macro_rules!s( ( $e:expr ) => ( ($e).to_string() ) );
|
macro_rules!s( ( $e:expr ) => ( ($e).to_string() ) );
|
||||||
|
|
||||||
// Calculates hash of a type that implements Hash
|
// Calculates hash of a type that implements Hash
|
||||||
|
|
Loading…
Reference in New Issue