Update template with changes
This commit is contained in:
parent
ef52e95e03
commit
05c9bed1f8
18
Cargo.lock
generated
18
Cargo.lock
generated
@ -1463,15 +1463,23 @@ name = "rustbot"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"poise",
|
"poise",
|
||||||
"rand",
|
"rustbot_cmds",
|
||||||
"reqwest",
|
|
||||||
"rustbot_events",
|
"rustbot_events",
|
||||||
"rustbot_lib",
|
"rustbot_lib",
|
||||||
"rustbot_tokens",
|
"rustbot_tokens",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustbot_cmds"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"poise",
|
||||||
|
"rand",
|
||||||
|
"reqwest",
|
||||||
|
"rustbot_lib",
|
||||||
"serde",
|
"serde",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
"time",
|
|
||||||
"tokio",
|
|
||||||
"uptime_lib",
|
"uptime_lib",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1492,7 +1500,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustbot_lib"
|
name = "rustbot_lib"
|
||||||
version = "0.1.19"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cargo_toml",
|
"cargo_toml",
|
||||||
"poise",
|
"poise",
|
||||||
|
23
Cargo.toml
23
Cargo.toml
@ -5,6 +5,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
|
"cmds",
|
||||||
"events",
|
"events",
|
||||||
"jobs",
|
"jobs",
|
||||||
"library",
|
"library",
|
||||||
@ -16,21 +17,21 @@ cargo_toml = "0.21.0"
|
|||||||
poise = "0.6.1"
|
poise = "0.6.1"
|
||||||
regex = "1.11.0"
|
regex = "1.11.0"
|
||||||
serde = "1.0.210"
|
serde = "1.0.210"
|
||||||
tokio = { version = "1.40.0", features = ["macros", "signal", "rt-multi-thread"] }
|
|
||||||
reqwest = { version = "0.12.8", features = ["native-tls-vendored"] }
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
rustbot_events = { path = "events" }
|
|
||||||
rustbot_lib = { path = "library" }
|
|
||||||
rustbot_tokens = { path = "tsclient" }
|
|
||||||
poise = { workspace = true }
|
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
reqwest = { workspace = true }
|
|
||||||
serde = { workspace = true }
|
|
||||||
sysinfo = "0.33.0"
|
sysinfo = "0.33.0"
|
||||||
time = "0.3.36"
|
time = "0.3.36"
|
||||||
tokio = { workspace = true }
|
|
||||||
uptime_lib = "0.3.1"
|
uptime_lib = "0.3.1"
|
||||||
|
tokio = { version = "1.40.0", features = ["macros", "signal", "rt-multi-thread"] }
|
||||||
|
reqwest = { version = "0.12.8", features = ["native-tls-vendored"] }
|
||||||
|
rustbot_lib = { path = "library" }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
poise = { workspace = true }
|
||||||
|
rustbot_cmds = { path = "cmds" }
|
||||||
|
rustbot_events = { path = "events" }
|
||||||
|
rustbot_lib = { workspace = true }
|
||||||
|
rustbot_tokens = { path = "tsclient" }
|
||||||
|
tokio = { workspace = true }
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
poise = { git = "https://github.com/serenity-rs/poise", branch = "serenity-next" }
|
poise = { git = "https://github.com/serenity-rs/poise", branch = "serenity-next" }
|
||||||
|
13
cmds/Cargo.toml
Normal file
13
cmds/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "rustbot_cmds"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
poise = { workspace = true }
|
||||||
|
rand = { workspace = true }
|
||||||
|
reqwest = { workspace = true }
|
||||||
|
rustbot_lib = { workspace = true }
|
||||||
|
serde = { workspace = true }
|
||||||
|
sysinfo = { workspace = true }
|
||||||
|
uptime_lib = { workspace = true }
|
26
cmds/src/dispatch.rs
Normal file
26
cmds/src/dispatch.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
mod dev;
|
||||||
|
mod eightball;
|
||||||
|
mod ping;
|
||||||
|
mod uptime;
|
||||||
|
|
||||||
|
pub use {
|
||||||
|
dev::dev,
|
||||||
|
eightball::eightball,
|
||||||
|
ping::ping,
|
||||||
|
uptime::uptime
|
||||||
|
};
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! collect {
|
||||||
|
() => {
|
||||||
|
vec![
|
||||||
|
// Developer command(s)
|
||||||
|
$crate::dev(),
|
||||||
|
// Utility commands
|
||||||
|
$crate::ping(),
|
||||||
|
$crate::uptime(),
|
||||||
|
// Unsorted mess
|
||||||
|
$crate::eightball(),
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
@ -1,14 +1,16 @@
|
|||||||
use rustbot_lib::{
|
use {
|
||||||
RustbotContext,
|
poise::{
|
||||||
RustbotResult
|
|
||||||
};
|
|
||||||
use poise::{
|
|
||||||
CreateReply,
|
CreateReply,
|
||||||
serenity_prelude::{
|
serenity_prelude::{
|
||||||
ChannelId,
|
ChannelId,
|
||||||
ShardId,
|
ShardId,
|
||||||
ShardRunnerInfo
|
ShardRunnerInfo
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
rustbot_lib::{
|
||||||
|
RustbotContext,
|
||||||
|
RustbotResult
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async fn format_shard_info(
|
async fn format_shard_info(
|
||||||
@ -44,9 +46,7 @@ async fn format_shard_info(
|
|||||||
interaction_context = "Guild|BotDm|PrivateChannel",
|
interaction_context = "Guild|BotDm|PrivateChannel",
|
||||||
subcommands("deploy", "servers", "shards", "echo")
|
subcommands("deploy", "servers", "shards", "echo")
|
||||||
)]
|
)]
|
||||||
pub async fn dev(_: RustbotContext<'_>) -> RustbotResult<()> {
|
pub async fn dev(_: RustbotContext<'_>) -> RustbotResult<()> { Ok(()) }
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deploy commands to this guild or globally
|
/// Deploy commands to this guild or globally
|
||||||
#[poise::command(prefix_command)]
|
#[poise::command(prefix_command)]
|
||||||
@ -90,7 +90,8 @@ async fn echo(
|
|||||||
ctx: RustbotContext<'_>,
|
ctx: RustbotContext<'_>,
|
||||||
#[description = "Message to be echoed as a bot"] message: String,
|
#[description = "Message to be echoed as a bot"] message: String,
|
||||||
#[description = "Channel to send this to"]
|
#[description = "Channel to send this to"]
|
||||||
#[channel_types("Text", "PublicThread", "PrivateThread")] channel: Option<ChannelId>
|
#[channel_types("Text", "PublicThread", "PrivateThread")]
|
||||||
|
channel: Option<ChannelId>
|
||||||
) -> RustbotResult<()> {
|
) -> RustbotResult<()> {
|
||||||
ctx.defer_ephemeral().await?;
|
ctx.defer_ephemeral().await?;
|
||||||
|
|
||||||
@ -101,18 +102,10 @@ async fn echo(
|
|||||||
|
|
||||||
match ChannelId::new(channel.get()).say(ctx.http(), message).await {
|
match ChannelId::new(channel.get()).say(ctx.http(), message).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
ctx.send(
|
ctx.send(CreateReply::new().content("Sent!").ephemeral(true)).await?;
|
||||||
CreateReply::new()
|
|
||||||
.content("Sent!")
|
|
||||||
.ephemeral(true)
|
|
||||||
).await?;
|
|
||||||
},
|
},
|
||||||
Err(y) => {
|
Err(y) => {
|
||||||
ctx.send(
|
ctx.send(CreateReply::new().content(format!("Failed... `{y}`")).ephemeral(true)).await?;
|
||||||
CreateReply::new()
|
|
||||||
.content(format!("Failed... `{y}`"))
|
|
||||||
.ephemeral(true)
|
|
||||||
).await?;
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
276
cmds/src/dispatch/eightball.rs
Executable file
276
cmds/src/dispatch/eightball.rs
Executable file
@ -0,0 +1,276 @@
|
|||||||
|
use {
|
||||||
|
poise::{
|
||||||
|
builtins::paginate,
|
||||||
|
serenity_prelude::UserId
|
||||||
|
},
|
||||||
|
rand::random,
|
||||||
|
rustbot_lib::{
|
||||||
|
RustbotContext,
|
||||||
|
RustbotResult,
|
||||||
|
config::BINARY_PROPERTIES
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(poise::ChoiceParameter, Clone)]
|
||||||
|
enum ResponseMode {
|
||||||
|
Normal,
|
||||||
|
Chicken,
|
||||||
|
#[name = "Chaotic & Unhinged"]
|
||||||
|
Chaotic
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ask the Magic 8-Ball a yes/no question and get an unpredictable answer
|
||||||
|
#[poise::command(
|
||||||
|
slash_command,
|
||||||
|
install_context = "Guild|User",
|
||||||
|
interaction_context = "Guild|BotDm|PrivateChannel",
|
||||||
|
rename = "8ball"
|
||||||
|
)]
|
||||||
|
pub async fn eightball(
|
||||||
|
ctx: RustbotContext<'_>,
|
||||||
|
#[description = "Your yes/no question"] question: String,
|
||||||
|
#[description = "Response modes"] mode: Option<ResponseMode>
|
||||||
|
) -> RustbotResult<()> {
|
||||||
|
if question.to_ascii_lowercase().contains("niko, show list") {
|
||||||
|
show_list(ctx, mode.clone().unwrap_or(ResponseMode::Normal)).await?;
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
let rand_resp = match mode {
|
||||||
|
Some(ResponseMode::Chicken) => get_random_chicken_response(),
|
||||||
|
Some(ResponseMode::Chaotic) => get_random_chaotic_response(),
|
||||||
|
_ => get_random_response()
|
||||||
|
};
|
||||||
|
|
||||||
|
ctx.reply(format!("> {question}\n{rand_resp}")).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn show_list(
|
||||||
|
ctx: RustbotContext<'_>,
|
||||||
|
list_type: ResponseMode
|
||||||
|
) -> RustbotResult<()> {
|
||||||
|
if ctx.author().id != UserId::new(BINARY_PROPERTIES.developers[0]) {
|
||||||
|
ctx
|
||||||
|
.reply("The list knows you're looking, but it's playing a game of hide and seek. For now, it wins.")
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let chunks: Vec<String> = match list_type {
|
||||||
|
ResponseMode::Normal => RESPONSES.chunks(10).map(|chunk| chunk.join("\n\n")).collect(),
|
||||||
|
ResponseMode::Chicken => CHICKEN_RESPONSES.chunks(10).map(|chunk| chunk.join("\n\n")).collect(),
|
||||||
|
ResponseMode::Chaotic => CHAOTIC_RESPONSES.chunks(10).map(|chunk| chunk.join("\n\n")).collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
let pages: Vec<&str> = chunks.iter().map(|s| s.as_str()).collect();
|
||||||
|
paginate(ctx, &pages).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
const RESPONSES: [&str; 45] = [
|
||||||
|
"Reply hazy. Look it up on Google.", // no
|
||||||
|
"Meh — Figure it out yourself.", // no
|
||||||
|
"I don't know, what do you think?", // no
|
||||||
|
"Yes.", // yes
|
||||||
|
"No.", // no
|
||||||
|
"It is decidedly so", // yes
|
||||||
|
"Signs point to... maybe... depends on... hold on, let me get my glasses, this is getting pretty tiny... depends on whether you'd be up to \
|
||||||
|
getting to know your Magic 8-Ball a little better.", // no
|
||||||
|
"Signs point to... ~~yes~~ no.", // no
|
||||||
|
"Why do you want to know the answer? It's obviously a yes.", // yes
|
||||||
|
"Outlook not so good.", // no
|
||||||
|
"Outlook hazy.", // no
|
||||||
|
"What are you, stupid?", // no
|
||||||
|
"How the hell do you not know that?", // no
|
||||||
|
"Really? Making a decision based on what the plastic 8-Ball says? Jesus...", // no
|
||||||
|
"Try asking later...", // no
|
||||||
|
"I don't know, whip out the ouija board and try again?", // no
|
||||||
|
"The answer is yes.", // yes
|
||||||
|
"Yes, actually no. Wait, nevermind.", // no
|
||||||
|
"Maybeee...", // yes
|
||||||
|
"Definitely!", // yes
|
||||||
|
"It is decidedly so.", // yes
|
||||||
|
"My reply is no.", // no
|
||||||
|
"My sources confirms that the answer is no.\nSource: :sparkles: *i made it up* :sparkles:", // no
|
||||||
|
"As I see it, yes.", // yes
|
||||||
|
"Don't count on it.", // no
|
||||||
|
"Whoa! Why do I have to answer this?", // no
|
||||||
|
"Highly unlikely.", // no
|
||||||
|
"Sure, but with extreme cautions.", // yes
|
||||||
|
"What kind of stupid question is that?? No! I'm not answering that!", // no
|
||||||
|
"Try asking this to a chicken. Probably knows it better than I do!", // no
|
||||||
|
"Not in a million years!", // no
|
||||||
|
"As a matter of fact, yes.", // yes
|
||||||
|
"It's a no, better go ask someone else.", // no
|
||||||
|
"In the end, it's not a bad choice.", // yes
|
||||||
|
"Nope, not today.", // no
|
||||||
|
"Cross your fingers, the answer is yes!", // yes
|
||||||
|
"Nope. *shakes head*", // no
|
||||||
|
"The fortune cookie said yes.", // yes
|
||||||
|
"Sorry, the fortune cookie over there said no.", // no
|
||||||
|
"Sorry, not happening.", // no
|
||||||
|
"I'll have to consult my sources... *flips coin*... no.", // no
|
||||||
|
"I'll have to consult the magic 8-ball... *shakes*... no.", // no
|
||||||
|
"I'm not sure to be honest, let's ask your friend. Oh wait...", // no
|
||||||
|
"This question flew over my head, I'll pass.", // no
|
||||||
|
"Oops, the Magic 8-Ball shattered itself when you asked that! I'll take that as a no." // no
|
||||||
|
];
|
||||||
|
|
||||||
|
const CHICKEN_RESPONSES: [&str; 54] = [
|
||||||
|
"Cluck cluck... Reply hazy, try pecking Google.", // no
|
||||||
|
"Meh... Figure it out yourself, or scratch around a bit.", // no
|
||||||
|
"I don't know... what do you think? *pecks at ground*", // no
|
||||||
|
"BAWK! YES!", // yes
|
||||||
|
"Cluck... no.", // no
|
||||||
|
"It is decidedly so! *flaps wings*", // yes
|
||||||
|
"Signs point to... maybe... hold on, let me fluff my feathers... depends on whether you'd get to know your Magic Chicken a bit better.", // no
|
||||||
|
"Signs point to... ~~yes~~ cluck no.", // no
|
||||||
|
"Why do you want to know? It's a big cluckin' yes!", // yes
|
||||||
|
"Outlook not so clucking good.", // no
|
||||||
|
"Outlook cluckin' hazy.", // no
|
||||||
|
"What are you, a lost chick? Cluck!", // no
|
||||||
|
"How the cluck do you not know that?", // no
|
||||||
|
"Really? Asking a chicken to decide your fate? *clucks judgmentally*", // no
|
||||||
|
"Peck back later, I'm nesting...", // no
|
||||||
|
"I don't know, try flapping your wings and ask again?", // no
|
||||||
|
"The answer is a big ol' yes! *flaps happily*", // yes
|
||||||
|
"Yes... wait, actually... no. Cluck, I'm confused.", // no
|
||||||
|
"Maaaaybe... *chicken waddle*?", // yes
|
||||||
|
"Definitely! *struts confidently*", // yes
|
||||||
|
"It is decidedly so. *struts with pride*", // yes
|
||||||
|
"My reply is a solid *cluck* no.", // no
|
||||||
|
"My sources confirm it's a cluckin' no.\nSource: 🐔 *I made it up* 🐔", // no
|
||||||
|
"As I see it, yes! *pecks approvingly*", // yes
|
||||||
|
"Don't count on it. *cluck cluck*", // no
|
||||||
|
"Whoa, why do I have to answer this? *fluffs feathers*", // no
|
||||||
|
"Highly unlikely. *chicken stare*", // no
|
||||||
|
"Sure, but with extreme cluckin' caution.", // yes
|
||||||
|
"What kind of stupid question is that?? No! *angry clucks*", // no
|
||||||
|
"Try asking this to a fellow chicken. They probably know better than I do!", // no
|
||||||
|
"Cluck yes! *does a happy chicken dance*", // yes
|
||||||
|
"No way, not even for a big bag of feed.", // no
|
||||||
|
"Yes! *lays egg of approval*", // yes
|
||||||
|
"It's a no, better go scratch somewhere else.", // no
|
||||||
|
"Cluck-tastic! That's a definite yes.", // yes
|
||||||
|
"Cluck yeah! *struts proudly*", // yes
|
||||||
|
"Nope, not today. *shakes head*", // no
|
||||||
|
"Feathers crossed, the answer is yes!", // yes
|
||||||
|
"Chicken says nope. *tilts head*", // no
|
||||||
|
"Absolutely! *clucks happily*", // yes
|
||||||
|
"Not a chance. *fluffs feathers*", // no
|
||||||
|
"Eggcellent choice! Yes!", // yes
|
||||||
|
"Not in a million clucks!", // no
|
||||||
|
"As a matter of cluck, yes! *clucks approvingly*", // yes
|
||||||
|
"It's a nopity nope, better go ask another chicken.", // no
|
||||||
|
"In the end, it's not a bad cluck", // yes
|
||||||
|
"Nope, not today. *clucks sadly*", // no
|
||||||
|
"Cross your feathers, the answer is yes!", // yes
|
||||||
|
"The fortune cookie said yes. *clucks in agreement*", // yes
|
||||||
|
"Sorry, the fortune cookie over there said no. *clucks in disagreement*", // no
|
||||||
|
"I'll have to consult my sources... *flips corn*... no.", // no
|
||||||
|
"I'll have to consult the magic 8-cluck... *shakes*... no.", // no
|
||||||
|
"I'm not sure to be honest, let's ask your chicken friend. Oh wait...", // no
|
||||||
|
"This question floated over my head, I'll pass. *clucks dismissively*" // no
|
||||||
|
];
|
||||||
|
|
||||||
|
const CHAOTIC_RESPONSES: [&str; 90] = [
|
||||||
|
"Oops! The Magic 8-Ball shattered upon hearing your question. Coincidence?", // no
|
||||||
|
"Reply hazy. Ask Google’s evil twin, Froogle.", // no
|
||||||
|
"Meh — Consult the ancient texts of Netflix subtitles.", // no
|
||||||
|
"I don't know, but your cat probably does.", // no
|
||||||
|
"Yes, but only if you wear a clown wig.", // yes
|
||||||
|
"No. Unless the moon winks at you first.", // no
|
||||||
|
"It is decidedly a resounding honk-honk!", // yes
|
||||||
|
"Signs point to... maybe... or not... or wait... oh look, a squirrel!", // no
|
||||||
|
"Signs point to... ~~yes~~ pancakes. Definitely pancakes.", // no
|
||||||
|
"Why do you want to know? It’s obviously a yes — trust the donut prophecy.", // yes
|
||||||
|
"Outlook not so good. Blame Mercury retrograde or your Wi-Fi.", // no
|
||||||
|
"Outlook hazy. Consult the nearest fortune-telling hamster.", // no
|
||||||
|
"What are you, a toaster in disguise?", // no
|
||||||
|
"How the heck do you not know this? Ask a sock puppet!", // no
|
||||||
|
"Really? Making life choices based on a magic ball? Bold move, friend.", // no
|
||||||
|
"Try asking later... when I’m less busy binge-watching.", // no
|
||||||
|
"I don't know, summon a raven and whisper your question into the void.", // no
|
||||||
|
"The answer is yes, as foretold by the mystical spaghetti.", // yes
|
||||||
|
"Yes, actually no. Wait, yes? Let’s go with potato.", // no
|
||||||
|
"Maybeee... if the stars align and your pizza has extra cheese.", // yes
|
||||||
|
"Definitely! Unless gravity stops working.", // yes
|
||||||
|
"It is decidedly so. So what? Buy a llama and see what happens.", // yes
|
||||||
|
"My reply is no, and also banana pudding.", // no
|
||||||
|
"My sources confirm that the answer is no.\nSource: A suspicious pigeon.", // no
|
||||||
|
"As I see it, yes. As the chicken sees it, no. Trust who you like.", // yes
|
||||||
|
"Don't count on it. Count on marshmallows instead.", // no
|
||||||
|
"Whoa! Why do I have to answer this? Ask a rubber duck.", // no
|
||||||
|
"Highly unlikely. Unless it’s Tuesday on Mars.", // no
|
||||||
|
"Sure, but with extreme caution and a tinfoil hat.", // yes
|
||||||
|
"What kind of silly question is that?? No! Also, here’s a kazoo.", // no
|
||||||
|
"Try asking this to a chicken. They’re the true oracles.", // no
|
||||||
|
"Not in a million years! Unless the earth is made of cheese.", // no
|
||||||
|
"As a matter of fact, yes. And it’s raining tacos.", // yes
|
||||||
|
"It's a no, but the raccoons might know better.", // no
|
||||||
|
"In the end, it’s not a bad choice. Or is it? Mwahaha.", // yes
|
||||||
|
"Nope, not today. Try tomorrow after coffee.", // no
|
||||||
|
"Cross your fingers! Or better yet, cross the streams.", // yes
|
||||||
|
"Nope. *shakes head like a very judgmental parrot*", // no
|
||||||
|
"The fortune cookie said yes, but it was written in crayon.", // yes
|
||||||
|
"Sorry, the fortune cookie over there said no. Blame it.", // no
|
||||||
|
"Sorry, not happening. But you get a virtual sticker for trying!", // no
|
||||||
|
"I'll have to consult my sources... *flips a pancake*... no.", // no
|
||||||
|
"I'll have to consult the magic 8-ball... *shakes it violently*... still no.", // no
|
||||||
|
"I'm not sure, but your imaginary friend says yes.", // yes
|
||||||
|
"This question flew over my head, so I’ll just say 'llama'.", // no
|
||||||
|
"The answer is yes, but only if you do it while wearing socks on your hands.", // yes
|
||||||
|
"No, and I think you broke the space-time continuum by asking.", // no
|
||||||
|
"Why not? What’s the worst that could happen? Oh wait...", // no
|
||||||
|
"The stars say yes, but the planets are still debating.", // yes
|
||||||
|
"The universe just facepalmed at your question.", // no
|
||||||
|
"Ask again while juggling flaming pineapples for a clearer answer.", // no
|
||||||
|
"Nope, not unless you bribe me with tacos.", // no
|
||||||
|
"I consulted the oracle... she’s out to lunch. Try later.", // no
|
||||||
|
"Yes, but only if you can lick your elbow right now.", // yes
|
||||||
|
"No, because I said so and I’m very wise. Also, I’m a plastic ball.", // no
|
||||||
|
"Yes. No. Wait, I’ve lost track. Did you hear that noise?", // no
|
||||||
|
"Absolutely, as long as you bring me a rubber chicken as tribute.", // yes
|
||||||
|
"I asked a wizard, and they just laughed hysterically.", // no
|
||||||
|
"The spirits say no, but the ghosts are nodding yes.", // no
|
||||||
|
"Yes, if you believe in unicorns and the power of friendship.", // yes
|
||||||
|
"No, and also you might want to move. Something’s behind you.", // no
|
||||||
|
"Ask again, but this time with interpretive dance.", // no
|
||||||
|
"Definitely! Unless the moon turns into cheese. Then no.", // yes
|
||||||
|
"I see... wait, no, I don’t see. My crystal ball is buffering.", // no
|
||||||
|
"Sure! But only after a karaoke duet with a raccoon.", // yes
|
||||||
|
"Yes, but only if you promise not to tell the ducks.", // yes
|
||||||
|
"No way, unless you can recite the alphabet backwards in one breath.", // no
|
||||||
|
"Ask the magic mushroom. It’s way more in touch with reality than I am.", // no
|
||||||
|
"No, because gravity disagrees with your premise.", // no
|
||||||
|
"Yes, but first you must complete the sacred quest for nachos.", // yes
|
||||||
|
"The answer is hidden in the folds of your laundry. Go check.", // no
|
||||||
|
"I would answer, but I’m legally obligated to stay mysterious.", // no
|
||||||
|
"Absolutely! If you can solve this riddle: What walks on four legs in the morning, two legs at noon, and... oh wait, wrong universe.", // yes
|
||||||
|
"The council of frogs says yes, but only if you croak like one.", // yes
|
||||||
|
"No, but only because the Magic 8-Ball union forbids it.", // no
|
||||||
|
"Yes, if the dog wags its tail twice before the clock strikes midnight.", // yes
|
||||||
|
"Try again after doing three cartwheels and making a wish.", // no
|
||||||
|
"The ducks in my dreams say no. They’re rarely wrong.", // no
|
||||||
|
"Not today, Satan. Not today.", // no
|
||||||
|
"Yes, but only on Wednesdays during a full moon.", // yes
|
||||||
|
"No, because bananas don’t grow in winter.", // no
|
||||||
|
"The answer is locked in a time capsule. Check back in 50 years.", // no
|
||||||
|
"I don’t know, but it smells like trouble.", // no
|
||||||
|
"Why not? The penguins approve, and that’s good enough for me.", // yes
|
||||||
|
"Sure, but only if you say 'bubblegum' ten times fast.", // yes
|
||||||
|
"No, unless you can outsmart a sentient toaster.", // no
|
||||||
|
"The answer is yes, but it comes with a plot twist.", // yes
|
||||||
|
"Flip a coin, spin three times, and consult your nearest cactus. Good luck!", // no
|
||||||
|
"Only on the condition that you buy me a donut.", // yes
|
||||||
|
"Yes, but proceed at your own risk. The llamas are watching." // yes
|
||||||
|
];
|
||||||
|
|
||||||
|
fn get_random_response() -> &'static str { RESPONSES[random::<usize>() % RESPONSES.len()] }
|
||||||
|
|
||||||
|
fn get_random_chicken_response() -> &'static str { CHICKEN_RESPONSES[random::<usize>() % CHICKEN_RESPONSES.len()] }
|
||||||
|
|
||||||
|
fn get_random_chaotic_response() -> &'static str { CHAOTIC_RESPONSES[random::<usize>() % CHAOTIC_RESPONSES.len()] }
|
@ -1,7 +1,9 @@
|
|||||||
use serde::Deserialize;
|
use {
|
||||||
use rustbot_lib::{
|
rustbot_lib::{
|
||||||
RustbotContext,
|
RustbotContext,
|
||||||
RustbotResult
|
RustbotResult
|
||||||
|
},
|
||||||
|
serde::Deserialize
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
@ -20,16 +22,14 @@ struct Summary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Check latency between bot and WebSocket as well as Discord's API latency
|
/// Check latency between bot and WebSocket as well as Discord's API latency
|
||||||
#[poise::command(
|
#[poise::command(slash_command, install_context = "Guild|User", interaction_context = "Guild|BotDm|PrivateChannel")]
|
||||||
slash_command,
|
|
||||||
install_context = "Guild|User",
|
|
||||||
interaction_context = "Guild|BotDm|PrivateChannel"
|
|
||||||
)]
|
|
||||||
pub async fn ping(ctx: RustbotContext<'_>) -> RustbotResult<()> {
|
pub async fn ping(ctx: RustbotContext<'_>) -> RustbotResult<()> {
|
||||||
let statuspage: StatusPage = reqwest::get("https://discordstatus.com/metrics-display/5k2rt9f7pmny/day.json")
|
let statuspage: StatusPage = reqwest::get("https://discordstatus.com/metrics-display/5k2rt9f7pmny/day.json")
|
||||||
.await.unwrap()
|
.await
|
||||||
|
.unwrap()
|
||||||
.json()
|
.json()
|
||||||
.await.unwrap();
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut latencies = Vec::new();
|
let mut latencies = Vec::new();
|
||||||
latencies.push(format!("Discord: `{:.0?}ms`", statuspage.metrics[0].summary.mean));
|
latencies.push(format!("Discord: `{:.0?}ms`", statuspage.metrics[0].summary.mean));
|
@ -1,28 +1,31 @@
|
|||||||
use sysinfo::System;
|
use {
|
||||||
use uptime_lib::get;
|
rustbot_lib::{
|
||||||
use std::{
|
RustbotContext,
|
||||||
|
RustbotResult,
|
||||||
|
config::BINARY_PROPERTIES,
|
||||||
|
utils::{
|
||||||
|
BOT_VERSION,
|
||||||
|
GIT_COMMIT_BRANCH,
|
||||||
|
GIT_COMMIT_HASH,
|
||||||
|
format_duration
|
||||||
|
}
|
||||||
|
},
|
||||||
|
std::{
|
||||||
env::var,
|
env::var,
|
||||||
fs::File,
|
fs::File,
|
||||||
|
io::{
|
||||||
|
BufRead,
|
||||||
|
BufReader
|
||||||
|
},
|
||||||
path::Path,
|
path::Path,
|
||||||
time::{
|
time::{
|
||||||
Duration,
|
Duration,
|
||||||
SystemTime,
|
SystemTime,
|
||||||
UNIX_EPOCH
|
UNIX_EPOCH
|
||||||
|
}
|
||||||
},
|
},
|
||||||
io::{
|
sysinfo::System,
|
||||||
BufRead,
|
uptime_lib::get
|
||||||
BufReader
|
|
||||||
}
|
|
||||||
};
|
|
||||||
use rustbot_lib::{
|
|
||||||
RustbotContext,
|
|
||||||
RustbotResult,
|
|
||||||
utils::{
|
|
||||||
BOT_VERSION,
|
|
||||||
GIT_COMMIT_HASH,
|
|
||||||
GIT_COMMIT_BRANCH,
|
|
||||||
format_duration
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn get_os_info() -> String {
|
fn get_os_info() -> String {
|
||||||
@ -33,13 +36,11 @@ fn get_os_info() -> String {
|
|||||||
if let Ok(file) = File::open(path) {
|
if let Ok(file) = File::open(path) {
|
||||||
let reader = BufReader::new(file);
|
let reader = BufReader::new(file);
|
||||||
let set_value = |s: String| s.split('=').nth(1).unwrap_or_default().trim_matches('"').to_string();
|
let set_value = |s: String| s.split('=').nth(1).unwrap_or_default().trim_matches('"').to_string();
|
||||||
reader.lines().map_while(Result::ok).for_each(|line| {
|
reader.lines().map_while(Result::ok).for_each(|line| match line {
|
||||||
match line {
|
|
||||||
l if l.starts_with("NAME=") => name = set_value(l),
|
l if l.starts_with("NAME=") => name = set_value(l),
|
||||||
l if l.starts_with("VERSION=") => version = set_value(l),
|
l if l.starts_with("VERSION=") => version = set_value(l),
|
||||||
l if l.starts_with("VERSION_ID=") => version = set_value(l),
|
l if l.starts_with("VERSION_ID=") => version = set_value(l),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,16 +96,21 @@ pub async fn uptime(ctx: RustbotContext<'_>) -> RustbotResult<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the node hostname from envvar
|
// Fetch the node hostname from envvar
|
||||||
let docker_node = match var("DOCKER_HOSTNAME") {
|
let node_hostname = if BINARY_PROPERTIES.env.contains("prod") {
|
||||||
|
match var("DOCKER_HOSTNAME") {
|
||||||
Ok(h) => h.to_string(),
|
Ok(h) => h.to_string(),
|
||||||
Err(_) => "DOCKER_HOSTNAME is empty!".to_string()
|
Err(_) => "DOCKER_HOSTNAME is empty!".to_string()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let hostname = std::process::Command::new("hostname").output().unwrap().stdout;
|
||||||
|
String::from_utf8(hostname).unwrap().trim().to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
let stat_msg = [
|
let stat_msg = [
|
||||||
format!("**{} v{}** `{GIT_COMMIT_HASH}:{GIT_COMMIT_BRANCH}`", bot.name, *BOT_VERSION),
|
format!("**{} v{}** `{GIT_COMMIT_HASH}:{GIT_COMMIT_BRANCH}`", bot.name, *BOT_VERSION),
|
||||||
format!(">>> System: `{}`", format_duration(sys_uptime)),
|
format!(">>> System: `{}`", format_duration(sys_uptime)),
|
||||||
format!("Process: `{}`", format_duration(proc_uptime)),
|
format!("Process: `{}`", format_duration(proc_uptime)),
|
||||||
format!("Node: `{docker_node}`"),
|
format!("Node: `{node_hostname}`"),
|
||||||
format!("CPU: `{}`", cpu[0].brand()),
|
format!("CPU: `{}`", cpu[0].brand()),
|
||||||
format!("RAM: `{pram}` (`{sram}/{sram_total}`)"),
|
format!("RAM: `{pram}` (`{sram}/{sram_total}`)"),
|
||||||
format!("OS: `{}`", get_os_info())
|
format!("OS: `{}`", get_os_info())
|
2
cmds/src/lib.rs
Normal file
2
cmds/src/lib.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
mod dispatch;
|
||||||
|
pub use dispatch::*;
|
@ -4,8 +4,8 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rustbot_lib = { path = "../library" }
|
|
||||||
poise = { workspace = true }
|
poise = { workspace = true }
|
||||||
|
rustbot_lib = { workspace = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
production = ["rustbot_lib/production"]
|
production = ["rustbot_lib/production"]
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
mod ready;
|
mod ready;
|
||||||
mod shards;
|
mod shards;
|
||||||
|
|
||||||
use poise::serenity_prelude::FullEvent;
|
use {
|
||||||
use rustbot_lib::{
|
poise::serenity_prelude::FullEvent,
|
||||||
|
rustbot_lib::{
|
||||||
RustbotFwCtx,
|
RustbotFwCtx,
|
||||||
RustbotResult
|
RustbotResult
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const RUSTBOT_EVENT: &str = "RustbotEvent";
|
pub const RUSTBOT_EVENT: &str = "RustbotEvent";
|
||||||
|
@ -3,26 +3,28 @@ use super::{
|
|||||||
RUSTBOT_EVENT
|
RUSTBOT_EVENT
|
||||||
};
|
};
|
||||||
|
|
||||||
use rustbot_lib::{
|
use {
|
||||||
RustbotFwCtx,
|
poise::serenity_prelude::{
|
||||||
RustbotResult,
|
ChannelId,
|
||||||
|
CreateEmbed,
|
||||||
|
CreateEmbedAuthor,
|
||||||
|
CreateMessage,
|
||||||
|
Ready
|
||||||
|
},
|
||||||
|
rustbot_lib::{
|
||||||
|
config::BINARY_PROPERTIES,
|
||||||
utils::{
|
utils::{
|
||||||
BOT_VERSION,
|
BOT_VERSION,
|
||||||
GIT_COMMIT_HASH,
|
GIT_COMMIT_BRANCH,
|
||||||
GIT_COMMIT_BRANCH
|
GIT_COMMIT_HASH
|
||||||
},
|
},
|
||||||
config::BINARY_PROPERTIES
|
RustbotFwCtx,
|
||||||
};
|
RustbotResult
|
||||||
use std::sync::atomic::{
|
},
|
||||||
|
std::sync::atomic::{
|
||||||
AtomicBool,
|
AtomicBool,
|
||||||
Ordering::Relaxed
|
Ordering::Relaxed
|
||||||
};
|
}
|
||||||
use poise::serenity_prelude::{
|
|
||||||
Ready,
|
|
||||||
ChannelId,
|
|
||||||
CreateMessage,
|
|
||||||
CreateEmbed,
|
|
||||||
CreateEmbedAuthor
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static READY_ONCE: AtomicBool = AtomicBool::new(false);
|
static READY_ONCE: AtomicBool = AtomicBool::new(false);
|
||||||
@ -33,14 +35,26 @@ async fn ready_once(
|
|||||||
) -> RustbotResult<()> {
|
) -> RustbotResult<()> {
|
||||||
#[cfg(not(feature = "production"))]
|
#[cfg(not(feature = "production"))]
|
||||||
{
|
{
|
||||||
println!("{RUSTBOT_EVENT}[Ready:Notice:S{}]: Detected a non-production environment!", framework.serenity_context.shard_id);
|
println!(
|
||||||
|
"{RUSTBOT_EVENT}[Ready:Notice:S{}]: Detected a non-production environment!",
|
||||||
|
framework.serenity_context.shard_id
|
||||||
|
);
|
||||||
let gateway = framework.serenity_context.http.get_bot_gateway().await?;
|
let gateway = framework.serenity_context.http.get_bot_gateway().await?;
|
||||||
let session = gateway.session_start_limit;
|
let session = gateway.session_start_limit;
|
||||||
println!("{RUSTBOT_EVENT}[Ready:Notice:S{}]: Session limit: {}/{}", framework.serenity_context.shard_id, session.remaining, session.total);
|
println!(
|
||||||
|
"{RUSTBOT_EVENT}[Ready:Notice:S{}]: Session limit: {}/{}",
|
||||||
|
framework.serenity_context.shard_id, session.remaining, session.total
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{RUSTBOT_EVENT}[Ready:S{}]: Build version: {} ({}:{})", framework.serenity_context.shard_id, *BOT_VERSION, GIT_COMMIT_HASH, GIT_COMMIT_BRANCH);
|
println!(
|
||||||
println!("{RUSTBOT_EVENT}[Ready:S{}]: Connected to API as {}", framework.serenity_context.shard_id, ready.user.name);
|
"{RUSTBOT_EVENT}[Ready:S{}]: Build version: {} ({GIT_COMMIT_HASH}:{GIT_COMMIT_BRANCH})",
|
||||||
|
framework.serenity_context.shard_id, *BOT_VERSION
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"{RUSTBOT_EVENT}[Ready:S{}]: Connected to API as {}",
|
||||||
|
framework.serenity_context.shard_id, ready.user.name
|
||||||
|
);
|
||||||
|
|
||||||
let message = CreateMessage::new();
|
let message = CreateMessage::new();
|
||||||
let ready_embed = CreateEmbed::new()
|
let ready_embed = CreateEmbed::new()
|
||||||
@ -48,7 +62,9 @@ async fn ready_once(
|
|||||||
.thumbnail(ready.user.avatar_url().unwrap_or_default())
|
.thumbnail(ready.user.avatar_url().unwrap_or_default())
|
||||||
.author(CreateEmbedAuthor::new(format!("{} is ready!", ready.user.name)));
|
.author(CreateEmbedAuthor::new(format!("{} is ready!", ready.user.name)));
|
||||||
|
|
||||||
ChannelId::new(BINARY_PROPERTIES.rustbot_logs).send_message(&framework.serenity_context.http, message.add_embed(ready_embed)).await?;
|
ChannelId::new(BINARY_PROPERTIES.rustbot_logs)
|
||||||
|
.send_message(&framework.serenity_context.http, message.add_embed(ready_embed))
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -59,7 +75,9 @@ impl EventProcessor<'_> {
|
|||||||
data_about_bot: &Ready
|
data_about_bot: &Ready
|
||||||
) -> RustbotResult<()> {
|
) -> RustbotResult<()> {
|
||||||
if !READY_ONCE.swap(true, Relaxed) {
|
if !READY_ONCE.swap(true, Relaxed) {
|
||||||
ready_once(data_about_bot, self.framework).await.expect("Failed to call ready_once method");
|
ready_once(data_about_bot, self.framework)
|
||||||
|
.await
|
||||||
|
.expect("Failed to call ready_once method");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -3,16 +3,22 @@ use super::{
|
|||||||
RUSTBOT_EVENT
|
RUSTBOT_EVENT
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::num::NonZero;
|
use {
|
||||||
use rustbot_lib::RustbotResult;
|
poise::serenity_prelude::ShardStageUpdateEvent,
|
||||||
use poise::serenity_prelude::ShardStageUpdateEvent;
|
rustbot_lib::RustbotResult,
|
||||||
|
std::num::NonZero
|
||||||
|
};
|
||||||
|
|
||||||
impl EventProcessor<'_> {
|
impl EventProcessor<'_> {
|
||||||
pub async fn on_shards_ready(
|
pub async fn on_shards_ready(
|
||||||
&self,
|
&self,
|
||||||
total_shards: &NonZero<u16>
|
total_shards: &NonZero<u16>
|
||||||
) -> RustbotResult<()> {
|
) -> RustbotResult<()> {
|
||||||
let shards = if *total_shards == NonZero::new(1).unwrap() { "shard is" } else { "shards are" };
|
let shards = if *total_shards == NonZero::new(1).unwrap() {
|
||||||
|
"shard is"
|
||||||
|
} else {
|
||||||
|
"shards are"
|
||||||
|
};
|
||||||
println!("{RUSTBOT_EVENT}[ShardsReady]: {total_shards} {shards} ready!");
|
println!("{RUSTBOT_EVENT}[ShardsReady]: {total_shards} {shards} ready!");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
use crate::RUSTBOT_SCHEDULER;
|
use crate::RUSTBOT_SCHEDULER;
|
||||||
|
|
||||||
use tokio::{
|
use {
|
||||||
|
std::{
|
||||||
|
future::Future,
|
||||||
|
sync::Arc
|
||||||
|
},
|
||||||
|
tokio::{
|
||||||
task,
|
task,
|
||||||
time::{
|
time::{
|
||||||
interval,
|
interval,
|
||||||
Duration
|
Duration
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
use std::{
|
|
||||||
sync::Arc,
|
|
||||||
future::Future
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Scheduler;
|
pub struct Scheduler;
|
||||||
|
|
||||||
impl Scheduler {
|
impl Scheduler {
|
||||||
pub fn new() -> Arc<Self> {
|
pub fn new() -> Arc<Self> { Arc::new(Self) }
|
||||||
Arc::new(Self)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn spawn_job<F, E>(
|
pub async fn spawn_job<F, E>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rustbot_lib"
|
name = "rustbot_lib"
|
||||||
version = "0.1.19"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -23,15 +23,4 @@ fn main() {
|
|||||||
println!("cargo:rustc-env=GIT_COMMIT_BRANCH=not_found");
|
println!("cargo:rustc-env=GIT_COMMIT_BRANCH=not_found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
let hostname = std::process::Command::new("hostname")
|
|
||||||
.output()
|
|
||||||
.expect("Command execution failed: hostname");
|
|
||||||
|
|
||||||
if hostname.status.success() {
|
|
||||||
let hostname = String::from_utf8(hostname.stdout).expect("Invalid UTF-8 sequence").trim().to_string();
|
|
||||||
println!("cargo:rustc-env=DOCKER_HOSTNAME={}", &hostname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,33 +11,35 @@ pub struct ConfigMeta {
|
|||||||
pub static BINARY_PROPERTIES: LazyLock<ConfigMeta> = LazyLock::new(ConfigMeta::new);
|
pub static BINARY_PROPERTIES: LazyLock<ConfigMeta> = LazyLock::new(ConfigMeta::new);
|
||||||
|
|
||||||
#[cfg(not(feature = "production"))]
|
#[cfg(not(feature = "production"))]
|
||||||
pub static BINARY_PROPERTIES: LazyLock<ConfigMeta> = LazyLock::new(||
|
pub static BINARY_PROPERTIES: LazyLock<ConfigMeta> = LazyLock::new(|| ConfigMeta::new().env("dev").embed_color(0xF1D63C));
|
||||||
ConfigMeta::new()
|
|
||||||
.env("dev")
|
|
||||||
.embed_color(0xf1d63c)
|
|
||||||
);
|
|
||||||
|
|
||||||
impl ConfigMeta {
|
impl ConfigMeta {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
env: "prod",
|
env: "prod",
|
||||||
embed_color: 0xf1d63c,
|
embed_color: 0xF1D63C,
|
||||||
rustbot_logs: 1311282815601741844,
|
rustbot_logs: 1311282815601741844,
|
||||||
developers: vec![
|
developers: vec![
|
||||||
190407856527376384 // toast.ts
|
190407856527376384, // toast.ts
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scalable functions below;
|
// Scalable functions below;
|
||||||
#[cfg(not(feature = "production"))]
|
#[cfg(not(feature = "production"))]
|
||||||
fn env(mut self, env: &'static str) -> Self {
|
fn env(
|
||||||
|
mut self,
|
||||||
|
env: &'static str
|
||||||
|
) -> Self {
|
||||||
self.env = env;
|
self.env = env;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "production"))]
|
#[cfg(not(feature = "production"))]
|
||||||
fn embed_color(mut self, color: u32) -> Self {
|
fn embed_color(
|
||||||
|
mut self,
|
||||||
|
color: u32
|
||||||
|
) -> Self {
|
||||||
self.embed_color = color;
|
self.embed_color = color;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use poise::serenity_prelude::UserId;
|
use {
|
||||||
use cargo_toml::Manifest;
|
cargo_toml::Manifest,
|
||||||
use std::sync::LazyLock;
|
poise::serenity_prelude::UserId,
|
||||||
|
std::sync::LazyLock
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "production")]
|
#[cfg(feature = "production")]
|
||||||
pub static GIT_COMMIT_HASH: &str = env!("GIT_COMMIT_HASH");
|
pub static GIT_COMMIT_HASH: &str = env!("GIT_COMMIT_HASH");
|
||||||
@ -17,9 +19,7 @@ pub static BOT_VERSION: LazyLock<String> = LazyLock::new(|| {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
pub fn format_timestamp(timestamp: i64) -> String {
|
pub fn format_timestamp(timestamp: i64) -> String { format!("<t:{timestamp}>\n<t:{timestamp}:R>") }
|
||||||
format!("<t:{timestamp}>\n<t:{timestamp}:R>")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mention_dev(ctx: super::RustbotContext<'_>) -> Option<String> {
|
pub fn mention_dev(ctx: super::RustbotContext<'_>) -> Option<String> {
|
||||||
let devs = super::config::BINARY_PROPERTIES.developers.clone();
|
let devs = super::config::BINARY_PROPERTIES.developers.clone();
|
||||||
@ -53,12 +53,7 @@ pub fn format_duration(secs: u64) -> String {
|
|||||||
let minutes = (secs % 3600) / 60;
|
let minutes = (secs % 3600) / 60;
|
||||||
let seconds = secs % 60;
|
let seconds = secs % 60;
|
||||||
|
|
||||||
let components = [
|
let components = [(days, "d"), (hours, "h"), (minutes, "m"), (seconds, "s")];
|
||||||
(days, "d"),
|
|
||||||
(hours, "h"),
|
|
||||||
(minutes, "m"),
|
|
||||||
(seconds, "s"),
|
|
||||||
];
|
|
||||||
|
|
||||||
let formatted_string: Vec<String> = components
|
let formatted_string: Vec<String> = components
|
||||||
.iter()
|
.iter()
|
||||||
|
4
run.sh
4
run.sh
@ -1,6 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
export DOCKER_HOSTNAME=$(hostname)
|
|
||||||
export $(cat .env.bot | xargs)
|
export $(cat .env.bot | xargs)
|
||||||
clear && cargo run
|
clear && cargo fmt && cargo run
|
||||||
unset DOCKER_HOSTNAME
|
|
||||||
|
2
rust-toolchain
Normal file
2
rust-toolchain
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[toolchain]
|
||||||
|
channel = "nightly"
|
20
rustfmt.toml
Normal file
20
rustfmt.toml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
edition = "2024"
|
||||||
|
hex_literal_case = "Upper"
|
||||||
|
binop_separator = "Front"
|
||||||
|
brace_style = "SameLineWhere"
|
||||||
|
fn_params_layout = "Vertical"
|
||||||
|
imports_layout = "Vertical"
|
||||||
|
imports_granularity = "One"
|
||||||
|
fn_single_line = true
|
||||||
|
format_strings = true
|
||||||
|
max_width = 150
|
||||||
|
tab_spaces = 2
|
||||||
|
hard_tabs = false
|
||||||
|
trailing_comma = "Never"
|
||||||
|
match_block_trailing_comma = true
|
||||||
|
reorder_imports = true
|
||||||
|
reorder_modules = true
|
||||||
|
reorder_impl_items = true
|
||||||
|
trailing_semicolon = false
|
||||||
|
struct_field_align_threshold = 20
|
||||||
|
condense_wildcard_suffixes = true
|
@ -1,26 +0,0 @@
|
|||||||
mod dev;
|
|
||||||
mod eightball;
|
|
||||||
mod ping;
|
|
||||||
mod uptime;
|
|
||||||
|
|
||||||
pub use dev::dev;
|
|
||||||
pub use eightball::eightball;
|
|
||||||
pub use ping::ping;
|
|
||||||
pub use uptime::uptime;
|
|
||||||
|
|
||||||
macro_rules! collect {
|
|
||||||
() => {
|
|
||||||
vec![
|
|
||||||
// Developer command(s)
|
|
||||||
commands::dev(),
|
|
||||||
|
|
||||||
// Utility commands
|
|
||||||
commands::ping(),
|
|
||||||
commands::uptime(),
|
|
||||||
|
|
||||||
// Unsorted mess
|
|
||||||
commands::eightball(),
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
pub(crate) use collect;
|
|
@ -1,180 +0,0 @@
|
|||||||
use rustbot_lib::{
|
|
||||||
RustbotContext,
|
|
||||||
RustbotResult,
|
|
||||||
config::BINARY_PROPERTIES
|
|
||||||
};
|
|
||||||
use poise::{
|
|
||||||
serenity_prelude::UserId,
|
|
||||||
builtins::paginate
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(poise::ChoiceParameter)]
|
|
||||||
enum ResponseMode {
|
|
||||||
Normal,
|
|
||||||
Chicken
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ask the Magic 8-Ball a yes/no question and get an unpredictable answer
|
|
||||||
#[poise::command(
|
|
||||||
slash_command,
|
|
||||||
install_context = "Guild|User",
|
|
||||||
interaction_context = "Guild|BotDm|PrivateChannel",
|
|
||||||
rename = "8ball"
|
|
||||||
)]
|
|
||||||
pub async fn eightball(
|
|
||||||
ctx: RustbotContext<'_>,
|
|
||||||
#[description = "Your yes/no question"] question: String,
|
|
||||||
#[description = "Response modes"] mode: Option<ResponseMode>
|
|
||||||
) -> RustbotResult<()> {
|
|
||||||
if question.to_ascii_lowercase().contains("niko, show list") {
|
|
||||||
if ctx.author().id == UserId::new(BINARY_PROPERTIES.developers[0]) {
|
|
||||||
let chunks: Vec<String> = RESPONSES.chunks(10).map(|chunk| chunk.join("\n\n")).collect();
|
|
||||||
let pages: Vec<&str> = chunks.iter().map(|s| s.as_str()).collect();
|
|
||||||
paginate(ctx, &pages).await?;
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
} else {
|
|
||||||
ctx.reply("No.").await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if question.to_ascii_lowercase().contains("niko, show chicken list") {
|
|
||||||
if ctx.author().id == UserId::new(BINARY_PROPERTIES.developers[0]) {
|
|
||||||
let chunks: Vec<String> = CHICKEN_RESPONSES.chunks(10).map(|chunk| chunk.join("\n\n")).collect();
|
|
||||||
let pages: Vec<&str> = chunks.iter().map(|s| s.as_str()).collect();
|
|
||||||
paginate(ctx, &pages).await?;
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
} else {
|
|
||||||
ctx.reply("No.").await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let rand_resp = match mode {
|
|
||||||
Some(ResponseMode::Chicken) => get_random_chicken_response(),
|
|
||||||
_ => get_random_response()
|
|
||||||
};
|
|
||||||
|
|
||||||
ctx.reply(format!("> {question}\n{rand_resp}")).await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
const RESPONSES: [&str; 45] = [
|
|
||||||
"Reply hazy. Look it up on Google.", // no
|
|
||||||
"Meh — Figure it out yourself.", // no
|
|
||||||
"I don't know, what do you think?", // no
|
|
||||||
"Yes.", // yes
|
|
||||||
"No.", // no
|
|
||||||
"It is decidedly so", // yes
|
|
||||||
"Signs point to... maybe... depends on... \
|
|
||||||
hold on, let me get my glasses, this is getting \
|
|
||||||
pretty tiny... depends on whether you'd be up \
|
|
||||||
to getting to know your Magic 8-Ball a little better.", // no
|
|
||||||
"Signs point to... ~~yes~~ no.", // no
|
|
||||||
"Why do you want to know the answer? It's obviously a yes.", // yes
|
|
||||||
"Outlook not so good.", // no
|
|
||||||
"Outlook hazy.", // no
|
|
||||||
"What are you, stupid?", // no
|
|
||||||
"How the hell do you not know that?", // no
|
|
||||||
"Really? Making a decision based on what the plastic 8-Ball says? Jesus...", // no
|
|
||||||
"Try asking later...", // no
|
|
||||||
"I don't know, whip out the ouija board and try again?", // no
|
|
||||||
"The answer is yes.", // yes
|
|
||||||
"Yes, actually no. Wait, nevermind.", // no
|
|
||||||
"Maybeee...", // yes
|
|
||||||
"Definitely!", // yes
|
|
||||||
"It is decidedly so.", // yes
|
|
||||||
"My reply is no.", // no
|
|
||||||
"My sources confirms that the answer is no.\n\
|
|
||||||
Source: :sparkles: *i made it up* :sparkles:", // no
|
|
||||||
"As I see it, yes.", // yes
|
|
||||||
"Don't count on it.", // no
|
|
||||||
"Whoa! Why do I have to answer this?", // no
|
|
||||||
"Highly unlikely.", // no
|
|
||||||
"Sure, but with extreme cautions.", // yes
|
|
||||||
"What kind of stupid question is that?? No! I'm not answering that!", // no
|
|
||||||
"Try asking this to a chicken. Probably knows it better than I do!", // no
|
|
||||||
"Not in a million years!", // no
|
|
||||||
"As a matter of fact, yes.", // yes
|
|
||||||
"It's a no, better go ask someone else.", // no
|
|
||||||
"In the end, it's not a bad choice.", // yes
|
|
||||||
"Nope, not today.", // no
|
|
||||||
"Cross your fingers, the answer is yes!", // yes
|
|
||||||
"Nope. *shakes head*", // no
|
|
||||||
"The fortune cookie said yes.", // yes
|
|
||||||
"Sorry, the fortune cookie over there said no.", // no
|
|
||||||
"Sorry, not happening.", // no
|
|
||||||
"I'll have to consult my sources... *flips coin*... no.", // no
|
|
||||||
"I'll have to consult the magic 8-ball... *shakes*... no.", // no
|
|
||||||
"I'm not sure to be honest, let's ask your friend. Oh wait...", // no
|
|
||||||
"This question flew over my head, I'll pass.", // no
|
|
||||||
"Oops, the Magic 8-Ball shattered itself when you asked that! I'll take that as a no.", // no
|
|
||||||
];
|
|
||||||
|
|
||||||
const CHICKEN_RESPONSES: [&str; 54] = [
|
|
||||||
"Cluck cluck... Reply hazy, try pecking Google.", // no
|
|
||||||
"Meh... Figure it out yourself, or scratch around a bit.", // no
|
|
||||||
"I don't know... what do you think? *pecks at ground*", // no
|
|
||||||
"BAWK! YES!", // yes
|
|
||||||
"Cluck... no.", // no
|
|
||||||
"It is decidedly so! *flaps wings*", // yes
|
|
||||||
"Signs point to... maybe... hold on, let me fluff my feathers... depends on whether you'd get to know your Magic Chicken a bit better.", // no
|
|
||||||
"Signs point to... ~~yes~~ cluck no.", // no
|
|
||||||
"Why do you want to know? It's a big cluckin' yes!", // yes
|
|
||||||
"Outlook not so clucking good.", // no
|
|
||||||
"Outlook cluckin' hazy.", // no
|
|
||||||
"What are you, a lost chick? Cluck!", // no
|
|
||||||
"How the cluck do you not know that?", // no
|
|
||||||
"Really? Asking a chicken to decide your fate? *clucks judgmentally*", // no
|
|
||||||
"Peck back later, I'm nesting...", // no
|
|
||||||
"I don't know, try flapping your wings and ask again?", // no
|
|
||||||
"The answer is a big ol' yes! *flaps happily*", // yes
|
|
||||||
"Yes... wait, actually... no. Cluck, I'm confused.", // no
|
|
||||||
"Maaaaybe... *chicken waddle*?", // yes
|
|
||||||
"Definitely! *struts confidently*", // yes
|
|
||||||
"It is decidedly so. *struts with pride*", // yes
|
|
||||||
"My reply is a solid *cluck* no.", // no
|
|
||||||
"My sources confirm it's a cluckin' no.\nSource: 🐔 *I made it up* 🐔", // no
|
|
||||||
"As I see it, yes! *pecks approvingly*", // yes
|
|
||||||
"Don't count on it. *cluck cluck*", // no
|
|
||||||
"Whoa, why do I have to answer this? *fluffs feathers*", // no
|
|
||||||
"Highly unlikely. *chicken stare*", // no
|
|
||||||
"Sure, but with extreme cluckin' caution.", // yes
|
|
||||||
"What kind of stupid question is that?? No! *angry clucks*", // no
|
|
||||||
"Try asking this to a fellow chicken. They probably know better than I do!", // no
|
|
||||||
"Cluck yes! *does a happy chicken dance*", // yes
|
|
||||||
"No way, not even for a big bag of feed.", // no
|
|
||||||
"Yes! *lays egg of approval*", // yes
|
|
||||||
"It's a no, better go scratch somewhere else.", // no
|
|
||||||
"Cluck-tastic! That's a definite yes.", // yes
|
|
||||||
"Cluck yeah! *struts proudly*", // yes
|
|
||||||
"Nope, not today. *shakes head*", // no
|
|
||||||
"Feathers crossed, the answer is yes!", // yes
|
|
||||||
"Chicken says nope. *tilts head*", // no
|
|
||||||
"Absolutely! *clucks happily*", // yes
|
|
||||||
"Not a chance. *fluffs feathers*", // no
|
|
||||||
"Eggcellent choice! Yes!", // yes
|
|
||||||
"Not in a million clucks!", // no
|
|
||||||
"As a matter of cluck, yes! *clucks approvingly*", // yes
|
|
||||||
"It's a nopity nope, better go ask another chicken.", // no
|
|
||||||
"In the end, it's not a bad cluck", // yes
|
|
||||||
"Nope, not today. *clucks sadly*", // no
|
|
||||||
"Cross your feathers, the answer is yes!", // yes
|
|
||||||
"The fortune cookie said yes. *clucks in agreement*", // yes
|
|
||||||
"Sorry, the fortune cookie over there said no. *clucks in disagreement*", // no
|
|
||||||
"I'll have to consult my sources... *flips corn*... no.", // no
|
|
||||||
"I'll have to consult the magic 8-cluck... *shakes*... no.", // no
|
|
||||||
"I'm not sure to be honest, let's ask your chicken friend. Oh wait...", // no
|
|
||||||
"This question floated over my head, I'll pass. *clucks dismissively*", // no
|
|
||||||
];
|
|
||||||
|
|
||||||
fn get_random_response() -> &'static str {
|
|
||||||
RESPONSES[rand::random::<usize>() % RESPONSES.len()]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_random_chicken_response() -> &'static str {
|
|
||||||
CHICKEN_RESPONSES[rand::random::<usize>() % CHICKEN_RESPONSES.len()]
|
|
||||||
}
|
|
97
src/main.rs
97
src/main.rs
@ -1,27 +1,29 @@
|
|||||||
mod commands;
|
|
||||||
mod shutdown;
|
mod shutdown;
|
||||||
// https://cdn.toast-server.net/RustFSHiearchy.png
|
// https://cdn.toast-server.net/RustFSHiearchy.png
|
||||||
// Using the new filesystem hierarchy
|
// Using the new filesystem hierarchy
|
||||||
|
|
||||||
use rustbot_tokens::discord_token;
|
use {
|
||||||
use poise::serenity_prelude::{
|
poise::serenity_prelude::{
|
||||||
builder::CreateAllowedMentions,
|
builder::CreateAllowedMentions,
|
||||||
ClientBuilder,
|
|
||||||
ActivityData,
|
ActivityData,
|
||||||
|
ClientBuilder,
|
||||||
GatewayIntents
|
GatewayIntents
|
||||||
};
|
|
||||||
use rustbot_lib::{
|
|
||||||
utils::{
|
|
||||||
mention_dev,
|
|
||||||
get_guild_name
|
|
||||||
},
|
},
|
||||||
RustbotData,
|
rustbot_cmds::collect,
|
||||||
config::BINARY_PROPERTIES
|
rustbot_events::events::processor,
|
||||||
};
|
rustbot_lib::{
|
||||||
use rustbot_events::events::processor;
|
config::BINARY_PROPERTIES,
|
||||||
use std::{
|
utils::{
|
||||||
sync::Arc,
|
get_guild_name,
|
||||||
borrow::Cow
|
mention_dev
|
||||||
|
},
|
||||||
|
RustbotData
|
||||||
|
},
|
||||||
|
rustbot_tokens::discord_token,
|
||||||
|
std::{
|
||||||
|
borrow::Cow,
|
||||||
|
sync::Arc
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
@ -32,11 +34,11 @@ async fn main() {
|
|||||||
Some(Cow::Borrowed("pg!"))
|
Some(Cow::Borrowed("pg!"))
|
||||||
};
|
};
|
||||||
|
|
||||||
let commands = commands::collect!();
|
|
||||||
let framework = poise::Framework::builder()
|
let framework = poise::Framework::builder()
|
||||||
.options(poise::FrameworkOptions {
|
.options(poise::FrameworkOptions {
|
||||||
commands,
|
commands: collect!(),
|
||||||
pre_command: |ctx| Box::pin(async move {
|
pre_command: |ctx| {
|
||||||
|
Box::pin(async move {
|
||||||
let get_guild_channel_name = match ctx.guild_channel().await {
|
let get_guild_channel_name = match ctx.guild_channel().await {
|
||||||
Some(channel) => format!("in #{}", channel.name.clone()),
|
Some(channel) => format!("in #{}", channel.name.clone()),
|
||||||
None => String::from("")
|
None => String::from("")
|
||||||
@ -53,7 +55,8 @@ async fn main() {
|
|||||||
ctx.author().name,
|
ctx.author().name,
|
||||||
ctx.command().qualified_name,
|
ctx.command().qualified_name,
|
||||||
);
|
);
|
||||||
}),
|
})
|
||||||
|
},
|
||||||
prefix_options: poise::PrefixFrameworkOptions {
|
prefix_options: poise::PrefixFrameworkOptions {
|
||||||
prefix,
|
prefix,
|
||||||
ignore_bots: true,
|
ignore_bots: true,
|
||||||
@ -62,52 +65,69 @@ async fn main() {
|
|||||||
execute_self_messages: false,
|
execute_self_messages: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
on_error: |error| Box::pin(async move {
|
on_error: |error| {
|
||||||
|
Box::pin(async move {
|
||||||
match error {
|
match error {
|
||||||
poise::FrameworkError::Command { error, ctx, .. } => {
|
poise::FrameworkError::Command { error, ctx, .. } => {
|
||||||
println!("PoiseCommandError({}): {}", ctx.command().qualified_name, error);
|
println!("PoiseCommandError({}): {}", ctx.command().qualified_name, error);
|
||||||
ctx.reply(format!(
|
ctx
|
||||||
|
.reply(format!(
|
||||||
"Encountered an error during command execution, ask {} to check console for more details!",
|
"Encountered an error during command execution, ask {} to check console for more details!",
|
||||||
mention_dev(ctx).unwrap_or_default()
|
mention_dev(ctx).unwrap_or_default()
|
||||||
)).await.expect("Error sending message");
|
))
|
||||||
|
.await
|
||||||
|
.expect("Error sending message");
|
||||||
},
|
},
|
||||||
poise::FrameworkError::EventHandler { error, event, .. } => println!("PoiseEventHandlerError({}): {}", event.snake_case_name(), error),
|
poise::FrameworkError::EventHandler { error, event, .. } => println!("PoiseEventHandlerError({}): {}", event.snake_case_name(), error),
|
||||||
poise::FrameworkError::NotAnOwner { ctx, .. } => {
|
poise::FrameworkError::NotAnOwner { ctx, .. } => {
|
||||||
println!("PoiseNotAnOwner: {} tried to execute a developer-level command ({})", ctx.author().name, ctx.command().qualified_name);
|
println!(
|
||||||
ctx.reply("Whoa, you discovered a hidden command! Too bad, I can't allow you to execute it as you're not my creator.").await.expect("Error sending message");
|
"PoiseNotAnOwner: {} tried to execute a developer-level command ({})",
|
||||||
|
ctx.author().name,
|
||||||
|
ctx.command().qualified_name
|
||||||
|
);
|
||||||
|
ctx
|
||||||
|
.reply("Whoa, you discovered a hidden command! Too bad, I can't allow you to execute it as you're not my creator.")
|
||||||
|
.await
|
||||||
|
.expect("Error sending message");
|
||||||
},
|
},
|
||||||
poise::FrameworkError::UnknownInteraction { interaction, .. } => println!(
|
poise::FrameworkError::UnknownInteraction { interaction, .. } => println!(
|
||||||
"PoiseUnknownInteractionError: {} tried to execute an unknown interaction ({})",
|
"PoiseUnknownInteractionError: {} tried to execute an unknown interaction ({})",
|
||||||
interaction.user.name,
|
interaction.user.name, interaction.data.name
|
||||||
interaction.data.name
|
|
||||||
),
|
),
|
||||||
poise::FrameworkError::UnknownCommand { msg, .. } => println!(
|
poise::FrameworkError::UnknownCommand { msg, .. } => println!(
|
||||||
"PoiseUnknownCommandError: {} tried to execute an unknown command ({})",
|
"PoiseUnknownCommandError: {} tried to execute an unknown command ({})",
|
||||||
msg.author.name,
|
msg.author.name, msg.content
|
||||||
msg.content
|
|
||||||
),
|
),
|
||||||
poise::FrameworkError::ArgumentParse { ctx, error, .. } => {
|
poise::FrameworkError::ArgumentParse { ctx, error, .. } => {
|
||||||
println!("PoiseArgumentParseError: {}", error);
|
println!("PoiseArgumentParseError: {}", error);
|
||||||
ctx.reply(format!("Error parsing argument(s): {error}")).await.expect("Error sending message");
|
ctx
|
||||||
|
.reply(format!("Error parsing argument(s): {error}"))
|
||||||
|
.await
|
||||||
|
.expect("Error sending message");
|
||||||
},
|
},
|
||||||
poise::FrameworkError::CommandPanic { ctx, payload, .. } => {
|
poise::FrameworkError::CommandPanic { ctx, payload, .. } => {
|
||||||
if let Some(payload) = payload.clone() {
|
if let Some(payload) = payload.clone() {
|
||||||
println!("PoiseCommandPanic: {payload}");
|
println!("PoiseCommandPanic: {payload}");
|
||||||
ctx.reply(format!(
|
ctx
|
||||||
|
.reply(format!(
|
||||||
"The command panicked, please tell my developer about this!\n**Error:**```\n{payload}\n```"
|
"The command panicked, please tell my developer about this!\n**Error:**```\n{payload}\n```"
|
||||||
)).await.expect("Error sending message");
|
))
|
||||||
|
.await
|
||||||
|
.expect("Error sending message");
|
||||||
} else {
|
} else {
|
||||||
println!("PoiseCommandPanic: No payload provided");
|
println!("PoiseCommandPanic: No payload provided");
|
||||||
let uh_oh = [
|
let uh_oh = [
|
||||||
"Well, this is concerning... Hopefully you notified my developer about this!",
|
"Well, this is concerning... Hopefully you notified my developer about this!",
|
||||||
"The command panicked, but didn't leave any trace behind... Suspicious!",
|
"The command panicked, but didn't leave any trace behind... Suspicious!"
|
||||||
].join("\n");
|
]
|
||||||
|
.join("\n");
|
||||||
ctx.reply(uh_oh).await.expect("Error sending message");
|
ctx.reply(uh_oh).await.expect("Error sending message");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
other => println!("PoiseOtherError: {other}")
|
other => println!("PoiseOtherError: {other}")
|
||||||
}
|
}
|
||||||
}),
|
})
|
||||||
|
},
|
||||||
allowed_mentions: Some(CreateAllowedMentions::default().empty_users()),
|
allowed_mentions: Some(CreateAllowedMentions::default().empty_users()),
|
||||||
initialize_owners: true,
|
initialize_owners: true,
|
||||||
skip_checks_for_owners: true,
|
skip_checks_for_owners: true,
|
||||||
@ -118,14 +138,13 @@ async fn main() {
|
|||||||
|
|
||||||
let mut client = ClientBuilder::new(
|
let mut client = ClientBuilder::new(
|
||||||
discord_token().await,
|
discord_token().await,
|
||||||
GatewayIntents::GUILDS
|
GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT
|
||||||
| GatewayIntents::GUILD_MESSAGES
|
|
||||||
| GatewayIntents::MESSAGE_CONTENT
|
|
||||||
)
|
)
|
||||||
.framework(framework)
|
.framework(framework)
|
||||||
.data(Arc::new(RustbotData {}))
|
.data(Arc::new(RustbotData {}))
|
||||||
.activity(ActivityData::custom("nep nep!"))
|
.activity(ActivityData::custom("nep nep!"))
|
||||||
.await.expect("Error creating client");
|
.await
|
||||||
|
.expect("Error creating client");
|
||||||
|
|
||||||
let shard_manager = client.shard_manager.clone();
|
let shard_manager = client.shard_manager.clone();
|
||||||
|
|
||||||
|
@ -7,16 +7,11 @@ use tokio::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub async fn gracefully_shutdown() {
|
pub async fn gracefully_shutdown() {
|
||||||
let [mut s1, mut s2, mut s3] = [
|
let [mut s1, mut s2] = [signal(SignalKind::interrupt()).unwrap(), signal(SignalKind::hangup()).unwrap()];
|
||||||
signal(SignalKind::interrupt()).unwrap(),
|
|
||||||
signal(SignalKind::terminate()).unwrap(),
|
|
||||||
signal(SignalKind::hangup()).unwrap()
|
|
||||||
];
|
|
||||||
|
|
||||||
select!(
|
select!(
|
||||||
v = s1.recv() => v.unwrap(),
|
v = s1.recv() => v.unwrap(),
|
||||||
v = s2.recv() => v.unwrap(),
|
v = s2.recv() => v.unwrap()
|
||||||
v = s3.recv() => v.unwrap()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
println!("\nRustbot says goodbye! 👋");
|
println!("\nRustbot says goodbye! 👋");
|
||||||
|
@ -5,5 +5,5 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
poise = { workspace = true }
|
poise = { workspace = true }
|
||||||
tokenservice-client = { version = "0.4.1", registry = "gitea" }
|
tokenservice-client = { version = "0.4.2", registry = "gitea" }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
use poise::serenity_prelude::Token;
|
use {
|
||||||
use tokio::sync::Mutex;
|
poise::serenity_prelude::Token,
|
||||||
use std::{
|
std::{
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
sync::LazyLock
|
sync::LazyLock
|
||||||
};
|
},
|
||||||
use tokenservice_client::{
|
tokenservice_client::{
|
||||||
TokenService,
|
TokenService,
|
||||||
TokenServiceApi
|
TokenServiceApi
|
||||||
|
},
|
||||||
|
tokio::sync::Mutex
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct TSClient(TokenService);
|
pub struct TSClient(TokenService);
|
||||||
|
|
||||||
impl Default for TSClient {
|
impl Default for TSClient {
|
||||||
fn default() -> Self {
|
fn default() -> Self { Self::new() }
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TSClient {
|
impl TSClient {
|
||||||
@ -34,11 +34,6 @@ impl TSClient {
|
|||||||
|
|
||||||
static TSCLIENT: LazyLock<Mutex<TSClient>> = LazyLock::new(|| Mutex::new(TSClient::new()));
|
static TSCLIENT: LazyLock<Mutex<TSClient>> = LazyLock::new(|| Mutex::new(TSClient::new()));
|
||||||
|
|
||||||
pub async fn token_path() -> TokenServiceApi {
|
pub async fn token_path() -> TokenServiceApi { TSCLIENT.lock().await.get().await.unwrap() }
|
||||||
TSCLIENT.lock().await.get().await.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn discord_token() -> Token {
|
pub async fn discord_token() -> Token { Token::from_str(&token_path().await.main).expect("Serenity couldn't parse the bot token!") }
|
||||||
Token::from_str(&token_path().await.main)
|
|
||||||
.expect("Serenity couldn't parse the bot token!")
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user