updated to serenity 0.10.8
This commit is contained in:
parent
9d3b6fd976
commit
22a7d6ff39
|
@ -5,13 +5,14 @@ authors = ["Raatty <'me@raatty.club'>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serenity = "0.7.1"
|
serenity = { version = "0.10.8", features = ["collector"]}
|
||||||
reqwest = { version = "0.9.22", default-features = false }
|
reqwest = { version = "0.11.3", default-features = false, features = ["rustls-tls"]}
|
||||||
serde = { version = "1.0.101", features = ["derive"] }
|
serde = { version = "1.0.101", features = ["derive"] }
|
||||||
rand = "0.6"
|
rand = "0.8.3"
|
||||||
typemap = "0.3"
|
typemap = "0.3"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
num-format = "0.4"
|
num-format = "0.4"
|
||||||
|
tokio = {version = "1.0", features= ["macros", "rt-multi-thread"]}
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
codegen-units = 1
|
codegen-units = 1
|
||||||
|
|
|
@ -1,25 +1,23 @@
|
||||||
use serenity::prelude::*;
|
use serenity::prelude::*;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
framework::standard::{macros::command, Args, CommandError, CommandResult},
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
model::channel::Message,
|
model::channel::Message,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
#[description = "displays your avatar"]
|
#[description = "displays your avatar"]
|
||||||
pub fn avatar(ctx: &mut Context, msg: &Message, _args: Args) -> CommandResult {
|
pub async fn avatar(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
||||||
let guild = &msg.guild_id.ok_or(CommandError("no guild".to_owned()))?;
|
if let Ok(member) = &msg.member(&ctx).await {
|
||||||
let member = guild.member(&ctx, &msg.author)?;
|
if let Some(user_avatar) = &msg.author.avatar_url() {
|
||||||
let name = member.display_name();
|
msg.channel_id
|
||||||
if let Some(user_avatar) = &msg.author.avatar_url() {
|
.send_message(&ctx, |m| {
|
||||||
msg.channel_id
|
m.embed(|e| {
|
||||||
.send_message(&ctx.http, |m| {
|
e.title(format!("Heres {}'s avatar", member.display_name()))
|
||||||
m.embed(|e| {
|
.image(user_avatar)
|
||||||
e.title(format!("Heres {}'s avatar", name))
|
})
|
||||||
.image(user_avatar)
|
|
||||||
})
|
})
|
||||||
})
|
.await?;
|
||||||
.ok();
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,22 +16,22 @@ const DOG_URLS: [&'static str; 3] = [
|
||||||
"https://dog.ceo/api/breeds/image/random",
|
"https://dog.ceo/api/breeds/image/random",
|
||||||
];
|
];
|
||||||
|
|
||||||
fn get_dog(url: &str) -> Result<String, reqwest::Error> {
|
async fn get_dog(url: &str) -> Result<String, reqwest::Error> {
|
||||||
let mut resp = reqwest::get(url)?;
|
let resp = reqwest::get(url).await?;
|
||||||
let jresp: HashMap<String, String> = resp.json()?;
|
let jresp: HashMap<String, String> = resp.json().await?;
|
||||||
let dog_url = &jresp["message"];
|
let dog_url = &jresp["message"];
|
||||||
Ok(dog_url.to_string())
|
Ok(dog_url.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
#[description = "sends a pic of a random pug"]
|
#[description = "sends a pic of a random pug"]
|
||||||
pub fn pug(ctx: &mut Context, msg: &Message, _args: Args) -> CommandResult {
|
pub async fn pug(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
||||||
let url = get_dog(&DOG_URLS[0].replace("{}", "pug"))?;
|
let url = get_dog(&DOG_URLS[0].replace("{}", "pug")).await?;
|
||||||
msg.channel_id
|
msg.channel_id
|
||||||
.send_message(&ctx.http, |m| {
|
.send_message(&ctx.http, |m| {
|
||||||
m.embed(|e| e.image(url).colour(Colour::BLUE))
|
m.embed(|e| e.image(url).colour(Colour::BLUE))
|
||||||
})
|
})
|
||||||
.ok();
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,43 +42,43 @@ struct DogList {
|
||||||
message: Vec<String>,
|
message: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_dog_list() -> Result<DogList, reqwest::Error> {
|
async fn get_dog_list() -> Result<DogList, reqwest::Error> {
|
||||||
let mut resp = reqwest::get(DOG_URLS[1])?;
|
let resp = reqwest::get(DOG_URLS[1]).await?;
|
||||||
let dlist: DogList = resp.json()?;
|
let dlist: DogList = resp.json().await?;
|
||||||
Ok(dlist)
|
Ok(dlist)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
#[description = "sends a pic of a random dog of a given bread"]
|
#[description = "sends a pic of a random dog of a given bread"]
|
||||||
pub fn dog(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult {
|
pub async fn dog(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||||
match args.single::<String>() {
|
match args.single::<String>() {
|
||||||
Ok(ref breed) if breed == "list" => {
|
Ok(ref breed) if breed == "list" => {
|
||||||
let list_of_breads = get_dog_list()?;
|
let list_of_breads = get_dog_list().await?;
|
||||||
msg.channel_id
|
msg.channel_id
|
||||||
.say(
|
.say(
|
||||||
&ctx.http,
|
&ctx.http,
|
||||||
format!(
|
format!(
|
||||||
"**Here is a list of valid dog breads**\n{:?}",
|
"**Here is a list of valid dog breeds**\n{:?}",
|
||||||
list_of_breads.message
|
list_of_breads.message
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.ok();
|
.await?;
|
||||||
}
|
}
|
||||||
Ok(bread) => {
|
Ok(bread) => {
|
||||||
let url = get_dog(&DOG_URLS[0].replace("{}", &bread))?;
|
let url = get_dog(&DOG_URLS[0].replace("{}", &bread)).await?;
|
||||||
msg.channel_id
|
msg.channel_id
|
||||||
.send_message(&ctx.http, |m| {
|
.send_message(&ctx.http, |m| {
|
||||||
m.embed(|e| e.image(url).colour(Colour::BLUE))
|
m.embed(|e| e.image(url).colour(Colour::BLUE))
|
||||||
})
|
})
|
||||||
.ok();
|
.await?;
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
let url = get_dog(&DOG_URLS[2])?;
|
let url = get_dog(&DOG_URLS[2]).await?;
|
||||||
msg.channel_id
|
msg.channel_id
|
||||||
.send_message(&ctx.http, |m| {
|
.send_message(&ctx.http, |m| {
|
||||||
m.embed(|e| e.image(url).colour(Colour::BLUE))
|
m.embed(|e| e.image(url).colour(Colour::BLUE))
|
||||||
})
|
})
|
||||||
.ok();
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,35 +1,93 @@
|
||||||
|
use rand::{seq::SliceRandom, thread_rng};
|
||||||
use serenity::prelude::*;
|
use serenity::prelude::*;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
framework::standard::{macros::command, Args, CommandResult},
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
model::channel::Message,
|
model::channel::{Message, ReactionType},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CRC_CHOICES: [&'static str; 3] = ["🐀", "🐱", "🧀"];
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
#[aliases("crc")]
|
#[aliases("crc")]
|
||||||
#[description = "paper sizzors rock basicly"]
|
#[description = "paper sizzors rock basicly"]
|
||||||
pub fn cat_rat_cheese(ctx: &mut Context, msg: &Message, _args: Args) -> CommandResult {
|
pub async fn cat_rat_cheese(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
||||||
if let Ok(sent_msg) = msg.channel_id.say(
|
let mut sent_msg = msg
|
||||||
&ctx.http,
|
.channel_id
|
||||||
"react with your choice, wait for the 3 reactions to load tho",
|
.say(
|
||||||
) {
|
&ctx.http,
|
||||||
for e in &['🐀', '🧀', '🐱'] {
|
"react with your choice, wait for the 3 reactions to load tho",
|
||||||
sent_msg.react(&ctx, *e).ok();
|
)
|
||||||
|
.await?;
|
||||||
|
for e in &['🐀', '🧀', '🐱'] {
|
||||||
|
sent_msg.react(&ctx, *e).await?;
|
||||||
|
}
|
||||||
|
let mut player_score = 0;
|
||||||
|
let mut bot_score = 0;
|
||||||
|
while player_score < 3 && bot_score < 3 {
|
||||||
|
if let Some(reaction) = sent_msg
|
||||||
|
.await_reaction(&ctx)
|
||||||
|
.timeout(std::time::Duration::from_secs(10))
|
||||||
|
.author_id(msg.author.id)
|
||||||
|
.filter(|e| {
|
||||||
|
if let ReactionType::Unicode(emoji) = &e.emoji {
|
||||||
|
match emoji.as_ref() {
|
||||||
|
"🐱" | "🐀" | "🧀" => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
if let ReactionType::Unicode(emoji) = &reaction.as_inner_ref().emoji {
|
||||||
|
let player: &str = emoji.as_ref();
|
||||||
|
let bot = *CRC_CHOICES.choose(&mut thread_rng()).unwrap();
|
||||||
|
let message_tail = if player == bot {
|
||||||
|
"draw"
|
||||||
|
} else if player == "🐀" {
|
||||||
|
if bot == "🧀" {
|
||||||
|
player_score += 1;
|
||||||
|
"your rat eats the cheese and you win!"
|
||||||
|
} else {
|
||||||
|
// bot = 🐱
|
||||||
|
bot_score += 1;
|
||||||
|
"my cat eats your rat and I win"
|
||||||
|
}
|
||||||
|
} else if player == "🧀" {
|
||||||
|
if bot == "🐱" {
|
||||||
|
player_score += 1;
|
||||||
|
"my cat ate your cheese but gets gets poisoned and dies, you win"
|
||||||
|
} else {
|
||||||
|
// bot = 🐀
|
||||||
|
bot_score += 1;
|
||||||
|
"bots rat eats the cheese and you lose"
|
||||||
|
}
|
||||||
|
} else if player == "🐱" {
|
||||||
|
if bot == "🐀" {
|
||||||
|
player_score += 1;
|
||||||
|
"your cat eats the rat so you win..."
|
||||||
|
} else {
|
||||||
|
// bot = 🧀
|
||||||
|
bot_score += 1;
|
||||||
|
"your cat eats the cheese but it gets poisoned and dies, I win"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"you shouldn't get this message"
|
||||||
|
};
|
||||||
|
let mut output = format!(
|
||||||
|
"your score: {} - my score {}\nbot picked: {}\n{}",
|
||||||
|
player_score, bot_score, bot, message_tail
|
||||||
|
);
|
||||||
|
if player_score == 3 {
|
||||||
|
output.push_str("\n**You win!**");
|
||||||
|
} else if bot_score == 3 {
|
||||||
|
output.push_str("\n**I win :)**");
|
||||||
|
}
|
||||||
|
sent_msg.edit(&ctx, |m| m.content(output)).await?;
|
||||||
|
&reaction.as_inner_ref().delete(&ctx).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
use crate::events;
|
|
||||||
ctx.data
|
|
||||||
.write()
|
|
||||||
.get_mut::<events::CRCGameStateStore>()
|
|
||||||
.expect("Expected CRCGameStateStore")
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.insert(
|
|
||||||
sent_msg.id.into(),
|
|
||||||
events::CRCGameState {
|
|
||||||
player_id: msg.author.id.into(),
|
|
||||||
player_score: 0,
|
|
||||||
bot_score: 0,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,12 @@ use serenity::{
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
#[description = "echos the message given"]
|
#[description = "echos the message given"]
|
||||||
pub fn echo(ctx: &mut Context, msg: &Message, args: Args) -> CommandResult {
|
pub async fn echo(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
msg.channel_id
|
msg.channel_id
|
||||||
.say(
|
.say(
|
||||||
&ctx.http,
|
&ctx.http,
|
||||||
utils::content_safe(&ctx, args.rest(), &utils::ContentSafeOptions::default()),
|
utils::content_safe(&ctx, args.rest(), &utils::ContentSafeOptions::default()).await,
|
||||||
)
|
)
|
||||||
.ok();
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use serenity::{
|
||||||
model::channel::Message,
|
model::channel::Message,
|
||||||
};
|
};
|
||||||
|
|
||||||
const EIGHTBALL_RESPONCES: [&'static str; 20] = [
|
const EIGHTBALL_RESPONSES: [&'static str; 20] = [
|
||||||
"it is certain",
|
"it is certain",
|
||||||
"it is decidedly so",
|
"it is decidedly so",
|
||||||
"without a doubt",
|
"without a doubt",
|
||||||
|
@ -31,12 +31,12 @@ const EIGHTBALL_RESPONCES: [&'static str; 20] = [
|
||||||
|
|
||||||
#[command("8ball")]
|
#[command("8ball")]
|
||||||
#[description = "asks the magic cheese ball you deepest desires"]
|
#[description = "asks the magic cheese ball you deepest desires"]
|
||||||
pub fn eightball(ctx: &mut Context, msg: &Message, _args: Args) -> CommandResult {
|
pub async fn eightball(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
||||||
let mut rng = thread_rng();
|
let choice = EIGHTBALL_RESPONSES.choose(&mut thread_rng());
|
||||||
if let Some(choice) = EIGHTBALL_RESPONCES.choose(&mut rng) {
|
if let Some(choice) = choice {
|
||||||
msg.channel_id
|
msg.channel_id
|
||||||
.say(&ctx.http, format!("🧀The cheese says {}", choice))
|
.say(&ctx.http, format!("🧀The cheese says {}", choice))
|
||||||
.ok();
|
.await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use serenity::{
|
||||||
#[command]
|
#[command]
|
||||||
#[description = "spams a given message a maximum of 10 times"]
|
#[description = "spams a given message a maximum of 10 times"]
|
||||||
#[usage("<count> <message>")]
|
#[usage("<count> <message>")]
|
||||||
pub fn spam(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult {
|
pub async fn spam(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||||
if let Ok(count) = args.single::<u32>() {
|
if let Ok(count) = args.single::<u32>() {
|
||||||
if count <= 10 {
|
if count <= 10 {
|
||||||
let to_spam = args.rest();
|
let to_spam = args.rest();
|
||||||
|
@ -16,12 +16,13 @@ pub fn spam(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult {
|
||||||
msg.channel_id
|
msg.channel_id
|
||||||
.say(
|
.say(
|
||||||
&ctx.http,
|
&ctx.http,
|
||||||
utils::content_safe(&ctx, to_spam, &utils::ContentSafeOptions::default()),
|
utils::content_safe(&ctx, to_spam, &utils::ContentSafeOptions::default())
|
||||||
|
.await,
|
||||||
)
|
)
|
||||||
.ok();
|
.await?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
msg.channel_id.say(&ctx.http, "no thats too many").ok();
|
msg.channel_id.say(&ctx.http, "no thats too many").await?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
|
use num_format::{Locale, ToFormattedString};
|
||||||
use serenity::prelude::*;
|
use serenity::prelude::*;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
framework::standard::{macros::command, Args, CommandResult},
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
model::channel::Message,
|
model::channel::Message,
|
||||||
};
|
};
|
||||||
use num_format::{Locale, ToFormattedString};
|
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
#[description = "echos the message given"]
|
#[description = "echos the message given"]
|
||||||
pub fn profile(ctx: &mut Context, msg: &Message, args: Args) -> CommandResult {
|
pub async fn profile(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
let rsn = args.rest().replace(" ", "%20");
|
let rsn = args.rest().replace(" ", "%20");
|
||||||
let mut resp = reqwest::get(&format!(
|
let resp = reqwest::get(&format!(
|
||||||
"https://apps.runescape.com/runemetrics/profile/profile?user={}&activities=20",
|
"https://apps.runescape.com/runemetrics/profile/profile?user={}&activities=20",
|
||||||
rsn
|
rsn
|
||||||
))?;
|
))
|
||||||
let profile: Profile = match resp.json::<Profile>() {
|
.await?;
|
||||||
|
let profile: Profile = match resp.json::<Profile>().await {
|
||||||
Ok(p) => p,
|
Ok(p) => p,
|
||||||
Err(why) => {
|
Err(why) => {
|
||||||
println!("{}", why);
|
println!("{}", why);
|
||||||
|
@ -49,25 +50,27 @@ pub fn profile(ctx: &mut Context, msg: &Message, args: Args) -> CommandResult {
|
||||||
let stat = &stats_extended[i];
|
let stat = &stats_extended[i];
|
||||||
left.push_str(&format!("{}{}", EMOJIS[stat.id as usize], stat.level));
|
left.push_str(&format!("{}{}", EMOJIS[stat.id as usize], stat.level));
|
||||||
}
|
}
|
||||||
msg.channel_id.send_message(&ctx.http, |m| {
|
msg.channel_id
|
||||||
m.embed(|e| {
|
.send_message(&ctx.http, |m| {
|
||||||
e.author(|a| a.name(format!("RuneMetrics profile of: {}", profile.name)))
|
m.embed(|e| {
|
||||||
.field("Levels", left, true)
|
e.author(|a| a.name(format!("RuneMetrics profile of: {}", profile.name)))
|
||||||
.field("Info", right, true)
|
.field("Levels", left, true)
|
||||||
|
.field("Info", right, true)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})?;
|
.await?;
|
||||||
let mut activities_out = String::new();
|
let mut activities_out = String::new();
|
||||||
for (i, a) in profile.activities.iter().enumerate() {
|
for (i, a) in profile.activities.iter().enumerate() {
|
||||||
{
|
{
|
||||||
activities_out.push_str(&format!("**{}** {}\n```{}```", a.date, a.text, a.details));
|
activities_out.push_str(&format!("**{}** {}\n```{}```", a.date, a.text, a.details));
|
||||||
}
|
}
|
||||||
if i == 10 {
|
if i == 10 {
|
||||||
msg.channel_id.say(&ctx.http, &activities_out)?;
|
msg.channel_id.say(&ctx.http, &activities_out).await?;
|
||||||
activities_out.clear();
|
activities_out.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !activities_out.is_empty() {
|
if !activities_out.is_empty() {
|
||||||
msg.channel_id.say(&ctx.http, &activities_out)?;
|
msg.channel_id.say(&ctx.http, &activities_out).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -157,12 +160,12 @@ static SKILL_NAMES: [&'static str; 28] = [
|
||||||
"Dungeoneering",
|
"Dungeoneering",
|
||||||
"Divination",
|
"Divination",
|
||||||
"Invention",
|
"Invention",
|
||||||
"Archeology"
|
"Archeology",
|
||||||
];
|
];
|
||||||
|
|
||||||
static ORDER: [u32; 28] = [
|
static ORDER: [u32; 28] = [
|
||||||
1, 7, 4, 2, 10, 13, 16, 12, 18, 17, 9, 15, 14, 6, 3, 8, 5, 11, 20, 21, 19, 23, 22, 24, 25, 26,
|
1, 7, 4, 2, 10, 13, 16, 12, 18, 17, 9, 15, 14, 6, 3, 8, 5, 11, 20, 21, 19, 23, 22, 24, 25, 26,
|
||||||
27, 28
|
27, 28,
|
||||||
];
|
];
|
||||||
|
|
||||||
static EMOJIS: [&'static str; 28] = [
|
static EMOJIS: [&'static str; 28] = [
|
||||||
|
@ -193,5 +196,5 @@ static EMOJIS: [&'static str; 28] = [
|
||||||
"<:Dungeoneering:406361343386451979>",
|
"<:Dungeoneering:406361343386451979>",
|
||||||
"<:Divination:406361343374131211>",
|
"<:Divination:406361343374131211>",
|
||||||
"<:Invention:406361343591972864>",
|
"<:Invention:406361343591972864>",
|
||||||
"<:Archeology:713541764874764289>"
|
"<:Archeology:713541764874764289>",
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
use serenity::prelude::Context;
|
use serenity::prelude::Context;
|
||||||
use serenity::{
|
use serenity::{
|
||||||
framework::standard::{macros::command, Args, CommandResult},
|
framework::standard::{macros::command, Args, CommandResult},
|
||||||
model::channel::Message,
|
model::channel::Message,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
#[description = "responds with pong"]
|
#[description = "responds with pong"]
|
||||||
pub fn ping(ctx: &mut Context, message: &Message, _args: Args) -> CommandResult {
|
pub async fn ping(ctx: &Context, message: &Message, _args: Args) -> CommandResult {
|
||||||
let now = message.timestamp;
|
let now = message.timestamp;
|
||||||
let mut msg = message.channel_id.say(&ctx.http, "Pong! 🏓")?;
|
if let Ok(mut msg) = message.channel_id.say(&ctx.http, "Pong! 🏓").await {
|
||||||
let msg_timestamp = msg.timestamp;
|
let msg_timestamp = msg.timestamp;
|
||||||
msg.edit(&ctx, |m| {
|
msg.edit(&ctx, |m| {
|
||||||
m.content(format!(
|
m.content(format!(
|
||||||
"Pong! 🏓 **took {}ms**",
|
"Pong! 🏓 **took {}ms**",
|
||||||
(msg_timestamp - now).num_milliseconds()
|
(msg_timestamp - now).num_milliseconds()
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.ok();
|
.await?;
|
||||||
Ok(())
|
}
|
||||||
}
|
Ok(())
|
||||||
|
}
|
||||||
|
|
197
src/events.rs
197
src/events.rs
|
@ -1,173 +1,24 @@
|
||||||
use serenity::{
|
use serenity::{
|
||||||
model::{channel::ReactionType, prelude::*},
|
async_trait,
|
||||||
prelude::TypeMapKey,
|
model::prelude::*,
|
||||||
prelude::{Context, EventHandler},
|
prelude::{Context, EventHandler},
|
||||||
};
|
};
|
||||||
|
pub struct Handler;
|
||||||
extern crate rand;
|
|
||||||
use rand::{
|
#[async_trait]
|
||||||
distributions::{Distribution, Standard},
|
impl EventHandler for Handler {
|
||||||
Rng,
|
async fn ready(&self, ctx: Context, r: Ready) {
|
||||||
};
|
println!("Successfully logged in as {}", r.user.name);
|
||||||
use std::collections::HashMap;
|
println!("Can see {} guilds", r.guilds.len());
|
||||||
use std::convert::TryFrom;
|
let game = Activity::listening("CHEESE");
|
||||||
use std::sync::{Arc, Mutex};
|
let status = OnlineStatus::DoNotDisturb;
|
||||||
pub struct Handler;
|
|
||||||
|
ctx.set_presence(Some(game), status).await;
|
||||||
impl EventHandler for Handler {
|
}
|
||||||
fn ready(&self, ctx: Context, r: Ready) {
|
|
||||||
println!("Successfully logged in as {}", r.user.name);
|
async fn message(&self, ctx: Context, new_message: Message) {
|
||||||
println!("Can see {} guilds", r.guilds.len());
|
if new_message.mentions_user_id(140652945032216576) {
|
||||||
let game = Activity::listening("CHEESE");
|
new_message.react(&ctx, '🐀').await.ok();
|
||||||
let status = OnlineStatus::DoNotDisturb;
|
}
|
||||||
|
}
|
||||||
ctx.set_presence(Some(game), status);
|
}
|
||||||
}
|
|
||||||
fn message(&self, ctx: Context, new_message: Message) {
|
|
||||||
if new_message.mentions_user_id(140652945032216576) {
|
|
||||||
new_message.react(&ctx, '🐀').ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn reaction_add(&self, context: Context, reaction: Reaction) {
|
|
||||||
let reaction_clone = reaction.clone();
|
|
||||||
if let ReactionType::Unicode(emoji) = reaction.emoji {
|
|
||||||
match emoji.as_ref() {
|
|
||||||
"🐱" | "🐀" | "🧀" => play_crc(reaction_clone, context, &emoji),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn play_crc(reaction: Reaction, mut context: Context, emoji: &str) {
|
|
||||||
let game_store = {
|
|
||||||
let mut data = context.data.write();
|
|
||||||
data.get_mut::<CRCGameStateStore>()
|
|
||||||
.expect("Expected CRCGameStateStore")
|
|
||||||
.clone()
|
|
||||||
};
|
|
||||||
let mut remove_message = false;
|
|
||||||
if let Some(current_game) = game_store
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.get_mut(&u64::from(reaction.message_id))
|
|
||||||
{
|
|
||||||
if reaction.user_id != current_game.player_id {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let message = current_game
|
|
||||||
.play(CRCChoices::try_from(emoji).unwrap())
|
|
||||||
.to_string();
|
|
||||||
let mut score_message = format!(
|
|
||||||
"your score: {} - my score {}\n{}",
|
|
||||||
current_game.player_score, current_game.bot_score, message
|
|
||||||
)
|
|
||||||
.to_string();
|
|
||||||
if current_game.player_score == 3 {
|
|
||||||
score_message.push_str("\n**You win!**");
|
|
||||||
remove_message = true;
|
|
||||||
} else if current_game.bot_score == 3 {
|
|
||||||
score_message.push_str("\n**I win :)**");
|
|
||||||
remove_message = true;
|
|
||||||
}
|
|
||||||
if let Ok(mut discord_message) = reaction.message(&mut context.http) {
|
|
||||||
discord_message
|
|
||||||
.edit(&context, |e| e.content(score_message))
|
|
||||||
.ok();
|
|
||||||
};
|
|
||||||
reaction.delete(&context).ok();
|
|
||||||
};
|
|
||||||
if remove_message {
|
|
||||||
game_store
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.remove(&reaction.message_id.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[derive(PartialEq)]
|
|
||||||
pub enum CRCChoices {
|
|
||||||
Cat,
|
|
||||||
Rat,
|
|
||||||
Cheese,
|
|
||||||
}
|
|
||||||
impl Distribution<CRCChoices> for Standard {
|
|
||||||
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> CRCChoices {
|
|
||||||
match rng.gen_range(0, 3) {
|
|
||||||
0 => CRCChoices::Cat,
|
|
||||||
1 => CRCChoices::Rat,
|
|
||||||
_ => CRCChoices::Cheese,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl TryFrom<&str> for CRCChoices {
|
|
||||||
type Error = String;
|
|
||||||
fn try_from(emoji: &str) -> Result<CRCChoices, Self::Error> {
|
|
||||||
use CRCChoices::*;
|
|
||||||
match emoji {
|
|
||||||
"🐀" => Ok(Rat),
|
|
||||||
"🐱" => Ok(Cat),
|
|
||||||
"🧀" => Ok(Cheese),
|
|
||||||
_ => Err("naughty emoji".to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CRCGameState {
|
|
||||||
pub player_id: u64,
|
|
||||||
pub player_score: u8,
|
|
||||||
pub bot_score: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CRCGameState {
|
|
||||||
pub fn play(&mut self, player: CRCChoices) -> String {
|
|
||||||
let bot = rand::random::<CRCChoices>();
|
|
||||||
use CRCChoices::*;
|
|
||||||
|
|
||||||
let message_tail = if bot == player {
|
|
||||||
"draw"
|
|
||||||
} else if player == Rat {
|
|
||||||
if bot == Cheese {
|
|
||||||
self.player_score += 1;
|
|
||||||
"your rat eats the cheese and you win!"
|
|
||||||
} else {
|
|
||||||
self.bot_score += 1;
|
|
||||||
"my cat eats your rat and I win"
|
|
||||||
}
|
|
||||||
} else if player == Cheese {
|
|
||||||
if bot == Rat {
|
|
||||||
self.bot_score += 1;
|
|
||||||
"bots rat eats the cheese and you lose"
|
|
||||||
} else {
|
|
||||||
self.player_score += 1;
|
|
||||||
"my cat eats your rat and I win"
|
|
||||||
}
|
|
||||||
} else if player == Cat {
|
|
||||||
if bot == Rat {
|
|
||||||
self.player_score += 1;
|
|
||||||
"your cat eats the rat so you win..."
|
|
||||||
} else {
|
|
||||||
self.bot_score += 1;
|
|
||||||
"your cat eats the cheese but it gets poisoned and dies, I win"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
"bug report plz"
|
|
||||||
};
|
|
||||||
format!("bot picked {} {}", bot, message_tail)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for CRCChoices {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
let string_form = match self {
|
|
||||||
CRCChoices::Rat => "🐀",
|
|
||||||
CRCChoices::Cat => "🐱",
|
|
||||||
CRCChoices::Cheese => "🧀",
|
|
||||||
};
|
|
||||||
write!(f, "{}", string_form)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CRCGameStateStore;
|
|
||||||
impl TypeMapKey for CRCGameStateStore {
|
|
||||||
type Value = Arc<Mutex<HashMap<u64, CRCGameState>>>;
|
|
||||||
}
|
|
||||||
|
|
84
src/main.rs
84
src/main.rs
|
@ -1,4 +1,4 @@
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use serenity::{
|
use serenity::{
|
||||||
client::Client,
|
client::Client,
|
||||||
|
@ -12,7 +12,6 @@ use serenity::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
mod commands;
|
mod commands;
|
||||||
use commands::{
|
use commands::{
|
||||||
AVATAR_COMMAND, CAT_RAT_CHEESE_COMMAND, DOG_COMMAND, ECHO_COMMAND, EIGHTBALL_COMMAND,
|
AVATAR_COMMAND, CAT_RAT_CHEESE_COMMAND, DOG_COMMAND, ECHO_COMMAND, EIGHTBALL_COMMAND,
|
||||||
|
@ -21,66 +20,55 @@ use commands::{
|
||||||
mod events;
|
mod events;
|
||||||
|
|
||||||
#[help]
|
#[help]
|
||||||
fn my_help(
|
async fn my_help(
|
||||||
ctx: &mut Context,
|
ctx: &Context,
|
||||||
msg: &Message,
|
msg: &Message,
|
||||||
args: Args,
|
args: Args,
|
||||||
help_options: &'static HelpOptions,
|
help_options: &'static HelpOptions,
|
||||||
groups: &[&'static CommandGroup],
|
groups: &[&'static CommandGroup],
|
||||||
owners: HashSet<UserId>,
|
owners: HashSet<UserId>,
|
||||||
) -> CommandResult {
|
) -> CommandResult {
|
||||||
help_commands::with_embeds(ctx, msg, args, &help_options, groups, owners)
|
help_commands::with_embeds(ctx, msg, args, &help_options, groups, owners).await;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
#[tokio::main]
|
||||||
let mut client = Client::new(&env::var("DISCORD_TOKEN").expect("token"), events::Handler)
|
async fn main() {
|
||||||
|
let mut client = Client::builder(&env::var("DISCORD_TOKEN").expect("token"))
|
||||||
|
.event_handler(events::Handler)
|
||||||
|
.framework(
|
||||||
|
StandardFramework::new()
|
||||||
|
.configure(|c| c.prefix("&"))
|
||||||
|
.help(&MY_HELP)
|
||||||
|
.group(&FUN_GROUP)
|
||||||
|
.group(&DISCORD_GROUP)
|
||||||
|
.group(&UTILITY_GROUP)
|
||||||
|
.group(&DOGS_GROUP)
|
||||||
|
.group(&RUNESCAPE_GROUP),
|
||||||
|
)
|
||||||
|
.await
|
||||||
.expect("Error creating client");
|
.expect("Error creating client");
|
||||||
client.with_framework(
|
if let Err(why) = client.start().await {
|
||||||
StandardFramework::new()
|
|
||||||
.configure(|c| c.prefix("&"))
|
|
||||||
.help(&MY_HELP)
|
|
||||||
.group(&FUN_GROUP)
|
|
||||||
.group(&DISCORD_GROUP)
|
|
||||||
.group(&UTILITY_GROUP)
|
|
||||||
.group(&DOGS_GROUP)
|
|
||||||
.group(&RUNESCAPE_GROUP),
|
|
||||||
);
|
|
||||||
{
|
|
||||||
let mut data = client.data.write();
|
|
||||||
let crc_game: HashMap<u64, events::CRCGameState> = HashMap::new();
|
|
||||||
data.insert::<events::CRCGameStateStore>(Arc::new(Mutex::new(crc_game)));
|
|
||||||
}
|
|
||||||
if let Err(why) = client.start() {
|
|
||||||
println!("An error occurred while running the client: {:?}", why);
|
println!("An error occurred while running the client: {:?}", why);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
group!({
|
#[group]
|
||||||
name: "fun",
|
#[commands(cat_rat_cheese, echo, spam, eightball)]
|
||||||
options: {},
|
struct Fun;
|
||||||
commands: [cat_rat_cheese, echo, spam, eightball],
|
|
||||||
});
|
|
||||||
|
|
||||||
group!({
|
#[group]
|
||||||
name: "discord",
|
#[commands(avatar)]
|
||||||
options: {},
|
struct Discord;
|
||||||
commands: [avatar]
|
|
||||||
});
|
|
||||||
|
|
||||||
group!({
|
#[group]
|
||||||
name: "utility",
|
#[commands(ping)]
|
||||||
options: {},
|
struct Utility;
|
||||||
commands: [ping]
|
|
||||||
});
|
|
||||||
|
|
||||||
group!({
|
#[group]
|
||||||
name: "dogs",
|
#[commands(pug, dog)]
|
||||||
options: {},
|
struct Dogs;
|
||||||
commands: [pug, dog]
|
|
||||||
});
|
|
||||||
|
|
||||||
group!({
|
#[group]
|
||||||
name: "runescape",
|
#[commands(profile)]
|
||||||
options: {},
|
struct Runescape;
|
||||||
commands: [profile]
|
|
||||||
});
|
|
||||||
|
|
Loading…
Reference in New Issue