Update template with changes

This commit is contained in:
toast 2025-02-15 10:55:41 +11:00
parent 8c7e5aeed0
commit 81941ab6f5
13 changed files with 635 additions and 300 deletions

131
Cargo.lock generated
View File

@ -160,9 +160,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.9.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
[[package]] [[package]]
name = "bytestring" name = "bytestring"
@ -582,10 +582,22 @@ dependencies = [
"cfg-if", "cfg-if",
"js-sys", "js-sys",
"libc", "libc",
"wasi", "wasi 0.11.0+wasi-snapshot-preview1",
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "getrandom"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
dependencies = [
"cfg-if",
"libc",
"wasi 0.13.3+wasi-0.2.2",
"windows-targets",
]
[[package]] [[package]]
name = "gimli" name = "gimli"
version = "0.31.1" version = "0.31.1"
@ -1014,7 +1026,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
dependencies = [ dependencies = [
"libc", "libc",
"wasi", "wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
@ -1225,7 +1237,7 @@ version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [ dependencies = [
"zerocopy", "zerocopy 0.7.35",
] ]
[[package]] [[package]]
@ -1262,8 +1274,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d"
dependencies = [ dependencies = [
"bytes", "bytes",
"getrandom", "getrandom 0.2.15",
"rand", "rand 0.8.5",
"ring", "ring",
"rustc-hash", "rustc-hash",
"rustls", "rustls",
@ -1305,8 +1317,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [ dependencies = [
"libc", "libc",
"rand_chacha", "rand_chacha 0.3.1",
"rand_core", "rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.0",
"zerocopy 0.8.18",
] ]
[[package]] [[package]]
@ -1316,7 +1339,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [ dependencies = [
"ppv-lite86", "ppv-lite86",
"rand_core", "rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core 0.9.0",
] ]
[[package]] [[package]]
@ -1325,7 +1358,17 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [ dependencies = [
"getrandom", "getrandom 0.2.15",
]
[[package]]
name = "rand_core"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff"
dependencies = [
"getrandom 0.3.1",
"zerocopy 0.8.18",
] ]
[[package]] [[package]]
@ -1446,7 +1489,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
dependencies = [ dependencies = [
"cc", "cc",
"cfg-if", "cfg-if",
"getrandom", "getrandom 0.2.15",
"libc", "libc",
"spin", "spin",
"untrusted", "untrusted",
@ -1461,6 +1504,7 @@ dependencies = [
"rustbot_cmds", "rustbot_cmds",
"rustbot_events", "rustbot_events",
"rustbot_lib", "rustbot_lib",
"rustbot_tasks",
"rustbot_tokens", "rustbot_tokens",
"tokio", "tokio",
] ]
@ -1469,8 +1513,9 @@ dependencies = [
name = "rustbot_cmds" name = "rustbot_cmds"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bytes",
"poise", "poise",
"rand", "rand 0.9.0",
"reqwest", "reqwest",
"rustbot_lib", "rustbot_lib",
"serde", "serde",
@ -1486,13 +1531,6 @@ dependencies = [
"rustbot_lib", "rustbot_lib",
] ]
[[package]]
name = "rustbot_jobs"
version = "0.1.0"
dependencies = [
"tokio",
]
[[package]] [[package]]
name = "rustbot_lib" name = "rustbot_lib"
version = "0.1.0" version = "0.1.0"
@ -1501,6 +1539,15 @@ dependencies = [
"poise", "poise",
] ]
[[package]]
name = "rustbot_tasks"
version = "0.1.0"
dependencies = [
"poise",
"rustbot_lib",
"tokio",
]
[[package]] [[package]]
name = "rustbot_tokens" name = "rustbot_tokens"
version = "0.1.0" version = "0.1.0"
@ -1928,7 +1975,7 @@ checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"fastrand", "fastrand",
"getrandom", "getrandom 0.2.15",
"once_cell", "once_cell",
"rustix", "rustix",
"windows-sys 0.59.0", "windows-sys 0.59.0",
@ -2247,7 +2294,7 @@ dependencies = [
"http", "http",
"httparse", "httparse",
"log", "log",
"rand", "rand 0.8.5",
"rustls", "rustls",
"rustls-pki-types", "rustls-pki-types",
"sha1", "sha1",
@ -2388,6 +2435,15 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasi"
version = "0.13.3+wasi-0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
dependencies = [
"wit-bindgen-rt",
]
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.100" version = "0.2.100"
@ -2706,6 +2762,15 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "wit-bindgen-rt"
version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
dependencies = [
"bitflags",
]
[[package]] [[package]]
name = "write16" name = "write16"
version = "1.0.0" version = "1.0.0"
@ -2749,7 +2814,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"zerocopy-derive", "zerocopy-derive 0.7.35",
]
[[package]]
name = "zerocopy"
version = "0.8.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79386d31a42a4996e3336b0919ddb90f81112af416270cff95b5f5af22b839c2"
dependencies = [
"zerocopy-derive 0.8.18",
] ]
[[package]] [[package]]
@ -2763,6 +2837,17 @@ dependencies = [
"syn 2.0.96", "syn 2.0.96",
] ]
[[package]]
name = "zerocopy-derive"
version = "0.8.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76331675d372f91bf8d17e13afbd5fe639200b73d01f0fc748bb059f9cca2db7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.96",
]
[[package]] [[package]]
name = "zerofrom" name = "zerofrom"
version = "0.1.5" version = "0.1.5"

View File

@ -7,12 +7,13 @@ edition = "2024"
members = [ members = [
"cmds", "cmds",
"events", "events",
"jobs", "tasks",
"library", "library",
"tsclient" "tsclient"
] ]
[workspace.dependencies] [workspace.dependencies]
bytes = "1.10.0"
cargo_toml = "0.21.0" cargo_toml = "0.21.0"
poise = "0.6.1" poise = "0.6.1"
regex = "1.11.1" regex = "1.11.1"
@ -21,7 +22,7 @@ rand = "0.9.0"
sysinfo = "0.33.1" sysinfo = "0.33.1"
time = "0.3.37" time = "0.3.37"
uptime_lib = "0.3.1" uptime_lib = "0.3.1"
tokio = { version = "1.43.0", features = ["macros", "signal", "rt-multi-thread"] } tokio = { version = "1.43.0", features = ["rt-multi-thread", "macros", "signal"] }
reqwest = { version = "0.12.12", features = ["native-tls-vendored"] } reqwest = { version = "0.12.12", features = ["native-tls-vendored"] }
rustbot_lib = { path = "library" } rustbot_lib = { path = "library" }
@ -31,6 +32,7 @@ rustbot_cmds = { path = "cmds" }
rustbot_events = { path = "events" } rustbot_events = { path = "events" }
rustbot_lib = { workspace = true } rustbot_lib = { workspace = true }
rustbot_tokens = { path = "tsclient" } rustbot_tokens = { path = "tsclient" }
rustbot_tasks = { path = "tasks" }
tokio = { workspace = true } tokio = { workspace = true }
[patch.crates-io] [patch.crates-io]

View File

@ -2,7 +2,7 @@ FROM scratch AS base
WORKDIR /builder WORKDIR /builder
COPY . . COPY . .
FROM alpine:3.21@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c FROM adelielinux/adelie:1.0-beta6
LABEL org.opencontainers.image.source="https://git.toast-server.net/toast/Rustbot" LABEL org.opencontainers.image.source="https://git.toast-server.net/toast/Rustbot"
RUN apk add --no-cache libgcc RUN apk add --no-cache libgcc
WORKDIR /rustbot WORKDIR /rustbot

View File

@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
bytes = { workspace = true }
poise = { workspace = true } poise = { workspace = true }
rand = { workspace = true } rand = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }

View File

@ -1,13 +1,22 @@
use { use {
bytes::Bytes,
poise::{ poise::{
builtins::paginate, CreateReply,
serenity_prelude::UserId serenity_prelude::{
CreateAttachment,
UserId
}
}, },
rand::random, rand::random,
rustbot_lib::{ rustbot_lib::{
RustbotContext, RustbotContext,
RustbotResult, RustbotResult,
config::BINARY_PROPERTIES config::BINARY_PROPERTIES
},
std::fmt::{
Display,
Formatter,
Result
} }
}; };
@ -16,7 +25,24 @@ enum ResponseMode {
Normal, Normal,
Chicken, Chicken,
#[name = "Chaotic & Unhinged"] #[name = "Chaotic & Unhinged"]
Chaotic Chaotic,
#[name = "UwU"]
Uwu
}
impl Display for ResponseMode {
fn fmt(
&self,
f: &mut Formatter<'_>
) -> Result {
let resp = match self {
ResponseMode::Normal => "Normal",
ResponseMode::Chicken => "Chicken",
ResponseMode::Chaotic => "Chaotic & Unhinged",
ResponseMode::Uwu => "UwU"
};
write!(f, "{resp}")
}
} }
/// Ask the Magic 8-Ball a yes/no question and get an unpredictable answer /// Ask the Magic 8-Ball a yes/no question and get an unpredictable answer
@ -31,7 +57,7 @@ pub async fn eightball(
#[description = "Your yes/no question"] question: String, #[description = "Your yes/no question"] question: String,
#[description = "Response modes"] mode: Option<ResponseMode> #[description = "Response modes"] mode: Option<ResponseMode>
) -> RustbotResult<()> { ) -> RustbotResult<()> {
if question.to_ascii_lowercase().contains("niko, show list") { if question.to_ascii_lowercase().contains("rustbot, show list") {
show_list(ctx, mode.clone().unwrap_or(ResponseMode::Normal)).await?; show_list(ctx, mode.clone().unwrap_or(ResponseMode::Normal)).await?;
return Ok(()) return Ok(())
} }
@ -39,6 +65,7 @@ pub async fn eightball(
let rand_resp = match mode { let rand_resp = match mode {
Some(ResponseMode::Chicken) => get_random_chicken_response(), Some(ResponseMode::Chicken) => get_random_chicken_response(),
Some(ResponseMode::Chaotic) => get_random_chaotic_response(), Some(ResponseMode::Chaotic) => get_random_chaotic_response(),
Some(ResponseMode::Uwu) => get_random_uwu_response(),
_ => get_random_response() _ => get_random_response()
}; };
@ -58,219 +85,377 @@ async fn show_list(
return Ok(()); return Ok(());
} }
let chunks: Vec<String> = match list_type { let selected_responses = match list_type {
ResponseMode::Normal => RESPONSES.chunks(10).map(|chunk| chunk.join("\n\n")).collect(), ResponseMode::Normal => RESPONSES.to_vec(),
ResponseMode::Chicken => CHICKEN_RESPONSES.chunks(10).map(|chunk| chunk.join("\n\n")).collect(), ResponseMode::Chicken => CHICKEN_RESPONSES.to_vec(),
ResponseMode::Chaotic => CHAOTIC_RESPONSES.chunks(10).map(|chunk| chunk.join("\n\n")).collect() ResponseMode::Chaotic => CHAOTIC_RESPONSES.to_vec(),
ResponseMode::Uwu => UWU_RESPONSES.to_vec()
}; };
let pages: Vec<&str> = chunks.iter().map(|s| s.as_str()).collect(); let total_yes = selected_responses.iter().filter(|&&(_, yes)| yes).count();
paginate(ctx, &pages).await?; let total_no = selected_responses.len() - total_yes;
let response_strings: Vec<String> = selected_responses.iter().map(|&(resp, _)| resp.to_string()).collect();
let response_mode = format!("Response mode: {list_type}");
let content = [
response_mode.clone(),
"Totals:".to_string(),
format!(" - Yes: {total_yes}"),
format!(" - No: {total_no}"),
format!(" - Strings: {}", selected_responses.len()),
"-".to_string().repeat(response_mode.len()),
response_strings.join("\n")
]
.join("\n");
let filename = match list_type {
ResponseMode::Normal => "responses.txt",
ResponseMode::Chicken => "chicken_responses.txt",
ResponseMode::Chaotic => "chaotic_responses.txt",
ResponseMode::Uwu => "uwu_responses.txt"
};
ctx
.send(CreateReply::new().attachment(CreateAttachment::bytes(Bytes::from(content), filename)))
.await?;
Ok(()) Ok(())
} }
const RESPONSES: [&str; 45] = [ const RESPONSES: [(&str, bool); 55] = [
"Reply hazy. Look it up on Google.", // no ("Reply hazy. Look it up on Google.", false),
"Meh — Figure it out yourself.", // no ("Meh — Figure it out yourself.", false),
"I don't know, what do you think?", // no ("I don't know, what do you think?", false),
"Yes.", // yes ("Yes.", true),
"No.", // no ("No.", false),
"It is decidedly so", // yes ("It is decidedly so", true),
"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... maybe... depends on... hold on, let me get my glasses, this is getting pretty tiny... depends on whether you'd be up to \
"Signs point to... ~~yes~~ no.", // no getting to know your Magic 8-Ball a little better.",
"Why do you want to know the answer? It's obviously a yes.", // yes false
"Outlook not so good.", // no ),
"Outlook hazy.", // no ("Signs point to... ~~yes~~ no.", false),
"What are you, stupid?", // no ("Why do you want to know the answer? It's obviously a yes.", true),
"How the hell do you not know that?", // no ("Outlook not so good.", false),
"Really? Making a decision based on what the plastic 8-Ball says? Jesus...", // no ("Outlook hazy.", false),
"Try asking later...", // no ("What are you, stupid?", false),
"I don't know, whip out the ouija board and try again?", // no ("How the hell do you not know that?", false),
"The answer is yes.", // yes ("Really? Making a decision based on what the plastic 8-Ball says? Jesus...", false),
"Yes, actually no. Wait, nevermind.", // no ("Try asking later...", false),
"Maybeee...", // yes ("I don't know, whip out the ouija board and try again?", false),
"Definitely!", // yes ("The answer is yes.", true),
"It is decidedly so.", // yes ("Yes, actually no. Wait, nevermind.", false),
"My reply is no.", // no ("Maybeee...", true),
"My sources confirms that the answer is no.\nSource: :sparkles: *i made it up* :sparkles:", // no ("Definitely!", true),
"As I see it, yes.", // yes ("It is decidedly so.", true),
"Don't count on it.", // no ("My reply is no.", false),
"Whoa! Why do I have to answer this?", // no (
"Highly unlikely.", // no "My sources confirms that the answer is no.\nSource: :sparkles: *i made it up* :sparkles;",
"Sure, but with extreme cautions.", // yes false
"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 ("As I see it, yes.", true),
"Not in a million years!", // no ("Don't count on it.", false),
"As a matter of fact, yes.", // yes ("Whoa! Why do I have to answer this?", false),
"It's a no, better go ask someone else.", // no ("Highly unlikely.", false),
"In the end, it's not a bad choice.", // yes ("Sure, but with extreme cautions.", true),
"Nope, not today.", // no ("What kind of stupid question is that?? No! I'm not answering that!", false),
"Cross your fingers, the answer is yes!", // yes ("Try asking this to a chicken. Probably knows it better than I do!", false),
"Nope. *shakes head*", // no ("Not in a million years!", false),
"The fortune cookie said yes.", // yes ("As a matter of fact, yes.", true),
"Sorry, the fortune cookie over there said no.", // no ("It's a no, better go ask someone else.", false),
"Sorry, not happening.", // no ("In the end, it's not a bad choice.", true),
"I'll have to consult my sources... *flips coin*... no.", // no ("Nope, not today.", false),
"I'll have to consult the magic 8-ball... *shakes*... no.", // no ("Cross your fingers, the answer is yes!", true),
"I'm not sure to be honest, let's ask your friend. Oh wait...", // no ("Nope. *shakes head*", false),
"This question flew over my head, I'll pass.", // no ("The fortune cookie said yes.", true),
"Oops, the Magic 8-Ball shattered itself when you asked that! I'll take that as a no." // no ("Sorry, the fortune cookie over there said no.", false),
("Sorry, not happening.", false),
("I'll have to consult my sources... *flips coin*... no.", false),
("I'll have to consult the magic 8-ball... *shakes*... no.", false),
("I'm not sure to be honest, let's ask your friend. Oh wait...", false),
("This question flew over my head, I'll pass.", false),
(
"Oops, the Magic 8-Ball shattered itself when you asked that! I'll take that as a no.",
false
),
("Absolutely not, but keep trying!", false),
("Yes, in a galaxy far far away!", true),
("Ask yourself and find the answer.", false),
("The stars align for a yes.", true),
("Chances are slim, but possible.", false),
("Without a doubt, the universe agrees.", true),
("Better not tell you now.", false),
("Certainly in your favor.", true),
("Look within for the answer.", false),
("Everything points to yes!", true)
]; ];
const CHICKEN_RESPONSES: [&str; 54] = [ const CHICKEN_RESPONSES: [(&str, bool); 54] = [
"Cluck cluck... Reply hazy, try pecking Google.", // no ("Cluck cluck... Reply hazy, try pecking Google.", false),
"Meh... Figure it out yourself, or scratch around a bit.", // no ("Meh... Figure it out yourself, or scratch around a bit.", false),
"I don't know... what do you think? *pecks at ground*", // no ("I don't know... what do you think? *pecks at ground*", false),
"BAWK! YES!", // yes ("BAWK! YES!", true),
"Cluck... no.", // no ("Cluck... no.", false),
"It is decidedly so! *flaps wings*", // yes ("It is decidedly so! *flaps wings*", true),
"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 "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.",
"Why do you want to know? It's a big cluckin' yes!", // yes false
"Outlook not so clucking good.", // no ),
"Outlook cluckin' hazy.", // no ("Signs point to... ~~yes~~ cluck no.", false),
"What are you, a lost chick? Cluck!", // no ("Why do you want to know? It's a big cluckin' yes!", true),
"How the cluck do you not know that?", // no ("Outlook not so clucking good.", false),
"Really? Asking a chicken to decide your fate? *clucks judgmentally*", // no ("Outlook cluckin' hazy.", false),
"Peck back later, I'm nesting...", // no ("What are you, a lost chick? Cluck!", false),
"I don't know, try flapping your wings and ask again?", // no ("How the cluck do you not know that?", false),
"The answer is a big ol' yes! *flaps happily*", // yes ("Really? Asking a chicken to decide your fate? *clucks judgmentally*", false),
"Yes... wait, actually... no. Cluck, I'm confused.", // no ("Peck back later, I'm nesting...", false),
"Maaaaybe... *chicken waddle*?", // yes ("I don't know, try flapping your wings and ask again?", false),
"Definitely! *struts confidently*", // yes ("The answer is a big ol' yes! *flaps happily*", true),
"It is decidedly so. *struts with pride*", // yes ("Yes... wait, actually... no. Cluck, I'm confused.", false),
"My reply is a solid *cluck* no.", // no ("Maaaaybe... *chicken waddle*?", true),
"My sources confirm it's a cluckin' no.\nSource: 🐔 *I made it up* 🐔", // no ("Definitely! *struts confidently*", true),
"As I see it, yes! *pecks approvingly*", // yes ("It is decidedly so. *struts with pride*", true),
"Don't count on it. *cluck cluck*", // no ("My reply is a solid *cluck* no.", false),
"Whoa, why do I have to answer this? *fluffs feathers*", // no ("My sources confirm it's a cluckin' no.\nSource: 🐔 *I made it up* 🐔", false),
"Highly unlikely. *chicken stare*", // no ("As I see it, yes! *pecks approvingly*", true),
"Sure, but with extreme cluckin' caution.", // yes ("Don't count on it. *cluck cluck*", false),
"What kind of stupid question is that?? No! *angry clucks*", // no ("Whoa, why do I have to answer this? *fluffs feathers*", false),
"Try asking this to a fellow chicken. They probably know better than I do!", // no ("Highly unlikely. *chicken stare*", false),
"Cluck yes! *does a happy chicken dance*", // yes ("Sure, but with extreme cluckin' caution.", true),
"No way, not even for a big bag of feed.", // no ("What kind of stupid question is that?? No! *angry clucks*", false),
"Yes! *lays egg of approval*", // yes ("Try asking this to a fellow chicken. They probably know better than I do!", false),
"It's a no, better go scratch somewhere else.", // no ("Cluck yes! *does a happy chicken dance*", true),
"Cluck-tastic! That's a definite yes.", // yes ("No way, not even for a big bag of feed.", false),
"Cluck yeah! *struts proudly*", // yes ("Yes! *lays egg of approval*", true),
"Nope, not today. *shakes head*", // no ("It's a no, better go scratch somewhere else.", false),
"Feathers crossed, the answer is yes!", // yes ("Cluck-tastic! That's a definite yes.", true),
"Chicken says nope. *tilts head*", // no ("Cluck yeah! *struts proudly*", true),
"Absolutely! *clucks happily*", // yes ("Nope, not today. *shakes head*", false),
"Not a chance. *fluffs feathers*", // no ("Feathers crossed, the answer is yes!", true),
"Eggcellent choice! Yes!", // yes ("Chicken says nope. *tilts head*", false),
"Not in a million clucks!", // no ("Absolutely! *clucks happily*", true),
"As a matter of cluck, yes! *clucks approvingly*", // yes ("Not a chance. *fluffs feathers*", false),
"It's a nopity nope, better go ask another chicken.", // no ("Eggcellent choice! Yes!", true),
"In the end, it's not a bad cluck", // yes ("Not in a million clucks!", false),
"Nope, not today. *clucks sadly*", // no ("As a matter of cluck, yes! *clucks approvingly*", true),
"Cross your feathers, the answer is yes!", // yes ("It's a nopity nope, better go ask another chicken.", false),
"The fortune cookie said yes. *clucks in agreement*", // yes ("In the end, it's not a bad cluck", true),
"Sorry, the fortune cookie over there said no. *clucks in disagreement*", // no ("Nope, not today. *clucks sadly*", false),
"I'll have to consult my sources... *flips corn*... no.", // no ("Cross your feathers, the answer is yes!", true),
"I'll have to consult the magic 8-cluck... *shakes*... no.", // no ("The fortune cookie said yes. *clucks in agreement*", true),
"I'm not sure to be honest, let's ask your chicken friend. Oh wait...", // no ("Sorry, the fortune cookie over there said no. *clucks in disagreement*", false),
"This question floated over my head, I'll pass. *clucks dismissively*" // no ("I'll have to consult my sources... *flips corn*... no.", false),
("I'll have to consult the magic 8-cluck... *shakes*... no.", false),
("I'm not sure to be honest, let's ask your chicken friend. Oh wait...", false),
("This question floated over my head, I'll pass. *clucks dismissively*", false)
]; ];
const CHAOTIC_RESPONSES: [&str; 90] = [ const CHAOTIC_RESPONSES: [(&str, bool); 143] = [
"Oops! The Magic 8-Ball shattered upon hearing your question. Coincidence?", // no ("Oops! The Magic 8-Ball shattered upon hearing your question. Coincidence?", false),
"Reply hazy. Ask Googles evil twin, Froogle.", // no ("Reply hazy. Ask Google's evil twin, Froogle.", false),
"Meh — Consult the ancient texts of Netflix subtitles.", // no ("Meh — Consult the ancient texts of Netflix subtitles.", false),
"I don't know, but your cat probably does.", // no ("I don't know, but your cat probably does.", false),
"Yes, but only if you wear a clown wig.", // yes ("Yes, but only if you wear a clown wig.", true),
"No. Unless the moon winks at you first.", // no ("No. Unless the moon winks at you first.", false),
"It is decidedly a resounding honk-honk!", // yes ("It is decidedly a resounding honk-honk!", true),
"Signs point to... maybe... or not... or wait... oh look, a squirrel!", // no ("Signs point to... maybe... or not... or wait... oh look, a squirrel!", false),
"Signs point to... ~~yes~~ pancakes. Definitely pancakes.", // no ("Signs point to... ~~yes~~ pancakes. Definitely pancakes.", false),
"Why do you want to know? Its obviously a yes — trust the donut prophecy.", // yes ("Why do you want to know? It's obviously a yes — trust the donut prophecy.", true),
"Outlook not so good. Blame Mercury retrograde or your Wi-Fi.", // no ("Outlook not so good. Blame Mercury retrograde or your Wi-Fi.", false),
"Outlook hazy. Consult the nearest fortune-telling hamster.", // no ("Outlook hazy. Consult the nearest fortune-telling hamster.", false),
"What are you, a toaster in disguise?", // no ("What are you, a toaster in disguise?", false),
"How the heck do you not know this? Ask a sock puppet!", // no ("How the heck do you not know this? Ask a sock puppet!", false),
"Really? Making life choices based on a magic ball? Bold move, friend.", // no ("Really? Making life choices based on a magic ball? Bold move, friend.", false),
"Try asking later... when Im less busy binge-watching.", // no ("Try asking later... when I'm less busy binge-watching.", false),
"I don't know, summon a raven and whisper your question into the void.", // no ("I don't know, summon a raven and whisper your question into the void.", false),
"The answer is yes, as foretold by the mystical spaghetti.", // yes ("The answer is yes, as foretold by the mystical spaghetti.", true),
"Yes, actually no. Wait, yes? Lets go with potato.", // no ("Yes, actually no. Wait, yes? Let's go with potato.", false),
"Maybeee... if the stars align and your pizza has extra cheese.", // yes ("Maybeee... if the stars align and your pizza has extra cheese.", true),
"Definitely! Unless gravity stops working.", // yes ("Definitely! Unless gravity stops working.", true),
"It is decidedly so. So what? Buy a llama and see what happens.", // yes ("It is decidedly so. So what? Buy a llama and see what happens.", true),
"My reply is no, and also banana pudding.", // no ("My reply is no, and also banana pudding.", false),
"My sources confirm that the answer is no.\nSource: A suspicious pigeon.", // no ("My sources confirm that the answer is no.\nSource: A suspicious pigeon.", false),
"As I see it, yes. As the chicken sees it, no. Trust who you like.", // yes ("As I see it, yes. As the chicken sees it, no. Trust who you like.", true),
"Don't count on it. Count on marshmallows instead.", // no ("Don't count on it. Count on marshmallows instead.", false),
"Whoa! Why do I have to answer this? Ask a rubber duck.", // no ("Whoa! Why do I have to answer this? Ask a rubber duck.", false),
"Highly unlikely. Unless its Tuesday on Mars.", // no ("Highly unlikely. Unless it's Tuesday on Mars.", false),
"Sure, but with extreme caution and a tinfoil hat.", // yes ("Sure, but with extreme caution and a tinfoil hat.", true),
"What kind of silly question is that?? No! Also, heres a kazoo.", // no ("What kind of silly question is that?? No! Also, here's a kazoo.", false),
"Try asking this to a chicken. Theyre the true oracles.", // no ("Try asking this to a chicken. They're the true oracles.", false),
"Not in a million years! Unless the earth is made of cheese.", // no ("Not in a million years! Unless the earth is made of cheese.", false),
"As a matter of fact, yes. And its raining tacos.", // yes ("As a matter of fact, yes. And it's raining tacos.", true),
"It's a no, but the raccoons might know better.", // no ("It's a no, but the raccoons might know better.", false),
"In the end, its not a bad choice. Or is it? Mwahaha.", // yes ("In the end, it's not a bad choice. Or is it? Mwahaha.", true),
"Nope, not today. Try tomorrow after coffee.", // no ("Nope, not today. Try tomorrow after coffee.", false),
"Cross your fingers! Or better yet, cross the streams.", // yes ("Cross your fingers! Or better yet, cross the streams.", true),
"Nope. *shakes head like a very judgmental parrot*", // no ("Nope. *shakes head like a very judgmental parrot*", false),
"The fortune cookie said yes, but it was written in crayon.", // yes ("The fortune cookie said yes, but it was written in crayon.", true),
"Sorry, the fortune cookie over there said no. Blame it.", // no ("Sorry, the fortune cookie over there said no. Blame it.", false),
"Sorry, not happening. But you get a virtual sticker for trying!", // no ("Sorry, not happening. But you get a virtual sticker for trying!", false),
"I'll have to consult my sources... *flips a pancake*... no.", // no ("I'll have to consult my sources... *flips a pancake*... no.", false),
"I'll have to consult the magic 8-ball... *shakes it violently*... still no.", // no ("I'll have to consult the magic 8-ball... *shakes it violently*... still no.", false),
"I'm not sure, but your imaginary friend says yes.", // yes ("I'm not sure, but your imaginary friend says yes.", true),
"This question flew over my head, so Ill just say 'llama'.", // no ("This question flew over my head, so I'll just say 'llama'.", false),
"The answer is yes, but only if you do it while wearing socks on your hands.", // yes ("The answer is yes, but only if you do it while wearing socks on your hands.", true),
"No, and I think you broke the space-time continuum by asking.", // no ("No, and I think you broke the space-time continuum by asking.", false),
"Why not? Whats the worst that could happen? Oh wait...", // no ("Why not? What's the worst that could happen? Oh wait...", false),
"The stars say yes, but the planets are still debating.", // yes ("The stars say yes, but the planets are still debating.", true),
"The universe just facepalmed at your question.", // no ("The universe just facepalmed at your question.", false),
"Ask again while juggling flaming pineapples for a clearer answer.", // no ("Ask again while juggling flaming pineapples for a clearer answer.", false),
"Nope, not unless you bribe me with tacos.", // no ("Nope, not unless you bribe me with tacos.", false),
"I consulted the oracle... shes out to lunch. Try later.", // no ("I consulted the oracle... she's out to lunch. Try later.", false),
"Yes, but only if you can lick your elbow right now.", // yes ("Yes, but only if you can lick your elbow right now.", true),
"No, because I said so and Im very wise. Also, Im a plastic ball.", // no ("No, because I said so and I'm very wise. Also, I'm a plastic ball.", false),
"Yes. No. Wait, Ive lost track. Did you hear that noise?", // no ("Yes. No. Wait, I've lost track. Did you hear that noise?", false),
"Absolutely, as long as you bring me a rubber chicken as tribute.", // yes ("Absolutely, as long as you bring me a rubber chicken as tribute.", true),
"I asked a wizard, and they just laughed hysterically.", // no ("I asked a wizard, and they just laughed hysterically.", false),
"The spirits say no, but the ghosts are nodding yes.", // no ("The spirits say no, but the ghosts are nodding yes.", false),
"Yes, if you believe in unicorns and the power of friendship.", // yes ("Yes, if you believe in unicorns and the power of friendship.", true),
"No, and also you might want to move. Somethings behind you.", // no ("No, and also you might want to move. Something's behind you.", false),
"Ask again, but this time with interpretive dance.", // no ("Ask again, but this time with interpretive dance.", false),
"Definitely! Unless the moon turns into cheese. Then no.", // yes ("Definitely! Unless the moon turns into cheese. Then no.", true),
"I see... wait, no, I dont see. My crystal ball is buffering.", // no ("I see... wait, no, I don't see. My crystal ball is buffering.", false),
"Sure! But only after a karaoke duet with a raccoon.", // yes ("Sure! But only after a karaoke duet with a raccoon.", true),
"Yes, but only if you promise not to tell the ducks.", // yes ("Yes, but only if you promise not to tell the ducks.", true),
"No way, unless you can recite the alphabet backwards in one breath.", // no ("No way, unless you can recite the alphabet backwards in one breath.", false),
"Ask the magic mushroom. Its way more in touch with reality than I am.", // no ("Ask the magic mushroom. It's way more in touch with reality than I am.", false),
"No, because gravity disagrees with your premise.", // no ("No, because gravity disagrees with your premise.", false),
"Yes, but first you must complete the sacred quest for nachos.", // yes ("Yes, but first you must complete the sacred quest for nachos.", true),
"The answer is hidden in the folds of your laundry. Go check.", // no ("The answer is hidden in the folds of your laundry. Go check.", false),
"I would answer, but Im legally obligated to stay mysterious.", // no ("I would answer, but I'm legally obligated to stay mysterious.", false),
"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 cats says yes, but only if you meow like one.", true),
"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.", false),
"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.", true),
"Yes, if the dog wags its tail twice before the clock strikes midnight.", // yes ("Try again after doing three cartwheels and making a wish.", false),
"Try again after doing three cartwheels and making a wish.", // no ("The ducks in my dreams say no. They're rarely wrong.", false),
"The ducks in my dreams say no. Theyre rarely wrong.", // no ("Not today, Satan. Not today.", false),
"Not today, Satan. Not today.", // no ("Yes, but only on Wednesdays during a full moon.", true),
"Yes, but only on Wednesdays during a full moon.", // yes ("No, because bananas don't grow in winter.", false),
"No, because bananas dont grow in winter.", // no ("The answer is locked in a time capsule. Check back in 50 years.", false),
"The answer is locked in a time capsule. Check back in 50 years.", // no ("I don't know, but it smells like trouble.", false),
"I dont know, but it smells like trouble.", // no ("Why not? The penguins approve, and that's good enough for me.", true),
"Why not? The penguins approve, and thats good enough for me.", // yes ("Sure, but only if you say 'bubblegum' ten times fast.", true),
"Sure, but only if you say 'bubblegum' ten times fast.", // yes ("No, unless you can outsmart a sentient toaster.", false),
"No, unless you can outsmart a sentient toaster.", // no ("The answer is yes, but it comes with a plot twist.", true),
"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!", false),
"Flip a coin, spin three times, and consult your nearest cactus. Good luck!", // no ("Only on the condition that you buy me a donut.", true),
"Only on the condition that you buy me a donut.", // yes ("Yes, but proceed at your own risk. The llamas are watching.", true),
"Yes, but proceed at your own risk. The llamas are watching." // yes ("Yes, but only if you drive like a maniac.", true),
("Absolutely, and the crabs are hosting a rave.", true),
("No, but a mischievous gnome just winked at me, so.. yes.", true),
("Yes, but you'll have to fight off a pack of ninja turtles first.", true),
("Nope. The Magic 8-Ball union called for a strike, try later.", false),
("The answer is clear: definitely a turtle. Wait, what was the question again?", false),
("Yes, but only if you perform the forbidden kazoo solo.", true),
("No, because I just consulted a very grumpy cloud.", false),
("Sure, but beware of the ominous whispers in the wind.", true),
("Absolutely not! Unless you bribe me with pancakes... then maybe.", false),
("The prophecy foretells a yes, but only after you do a somersault.", true),
("Negative, captain! The squirrels have spoken.", false),
("Ask again after you defeat a level 70 pancake god.", false),
("Yes, but only if you shout 'pineapple' while hopping on one foot.", true),
("The stars say no, but the pigeons disagree. Trust your instincts.", false),
("Yes, but at great personal risk to your snack supply.", true),
("No way. Unless you're wearing a hat shaped like a pineapple.", false),
("Consult the oracle of toasters. They hold the real truth.", false),
("The vibes are off. Try again with a disco ball in hand.", false),
("Yes, but the llamas demand a dance-off first.", true),
("Nope. Also, why does your question smell like burnt toast?", false),
("Yes, but the fabric of reality might unravel. Worth it?", true),
("No, because an interdimensional ferret stole the answer.", false),
("Absolutely! But only if you chant 'banana' three times at sunrise.", true),
("No, unless you appease the gummy bear council with offerings.", false),
("Maybe, but the answer is hidden in the Great Taco of Wisdom.", false),
("Yes, but don't trust the robot vacuum. It knows too much.", true),
("I see a yes in your future... or a spaghetti monster. Hard to say.", true),
("Ask a sock puppet again, but this time in interpretive mime.", false),
("It's a no, but the goldfish thinks otherwise. Who do you trust?", false),
("Signs point to yes, but only if you name a star after a pineapple.", true),
("The answer is no. Unless it's opposite day, then yes.", false),
("Yes, but only if the answer doesn't involve marmalade.", true),
("I'm sorry, Dave, I can't do that. Oh wait, wrong universe. No.", false),
("The Magic 8-Ball has declared a state of confusion, try again.", false),
("Yes, but it might result in spontaneous interpretive breakdancing.", true),
("The frogs are undecided. Maybe bribe them with flies?", false),
("A resounding yes! Unless you're allergic to good luck.", true),
("No, and also stop shaking me so hard! I'm fragile!", false),
("Yes, but only if you can out-dance a crab at karaoke night.", true),
("Nope, the answer is currently orbiting Jupiter. Check back in a century.", false),
("ASK AGAIN—wait, no, don't! I'm on break", false),
("Hahahahaha.. no!", false),
("I'm an 8-ball, not your therapist.. But yes!", true),
("God has increased your difficulty to insane, 8-ball said go ahead!", true),
("**Error 404:** Answer not found", false),
("All signs to point to—ỳ̸̹͈́e̵̥̝͐̋s̶̺͍̉", true),
("The spirits are busy! Leave a message after the beep. *extremely loud beep*", false),
("Sorry, I accidentally threw your question into the trash.", false),
("Yes!! Now go and cause some mayhem!!!", true),
("Yes, you weirdo...", true),
("ya", true),
(
"Bro, you spoke some gibberish sentence to the god, he sighed and signalled **yes** back!",
true
),
("Yes, but tell no one. THEY are listening!", true)
]; ];
fn get_random_response() -> &'static str { RESPONSES[random::<usize>() % RESPONSES.len()] } const UWU_RESPONSES: [(&str, bool); 50] = [
("Oopsie! The magic baww got fwightened by youw question, sowwy! >_<", false),
("Hmmm... wet me consuwt my pwushie cowwection... OwO it's a 'maybe?'", false),
("Oh nyo~ the staws awe too shy to answew >w<", false),
("Yes! UwU but onwy if you give me a headpat fiwst!", true),
("Nyope! But I bet chu' can twy again watew! >w<", false),
("Mmmm... I dink it's a 'pwobabwy?' OwO", true),
("The mysticaw fwuffbaww says 'no', but chu awe stiww amazing! >w<", false),
("Oh my fwuff! It's a big YES! UwU", true),
("No way, but chu can get a snuggwe instead! UwU", false),
("Hmmm... nyani?? The answew wawned away! O.O", false),
("Yippee! The answew is absowutewy YES, nyu~!", true),
("Nuuuuu, the wittwe magic is feewing shy... twy again watew, pwomise!", false),
("Hewwo? Hewwo? Magic baww says... oh, it feww asweep >w<", false),
("Maybe! But onwy if chu' twy wif youw happiest smiwe! UwU", true),
("No, but chu awe stiww pwetty bwoomin' paw-some!", false),
("The fwuffies awe undecided... ask a bun bun fwiend! >w<", false),
("Yes, but onwy if chu bwink wike a wittwe kitty! ^w^", true),
("Magic baww is wooking into it... uh-oh! It got stuck in fwuff o.O", false),
("Noooo, but chu can have a tummy wub to cheew chu up! UwU", false),
("Mmmm... I smeww a 'yes', wike fwuffy pancakies! >w<", true),
("Huwwo? Staws awe purring, chu' get a soft nyes~", true),
("Oops, chu bwew my mind wif dat one. Wet's caww it a nyope~", false),
("The answew is a fwuffy YES! Now go do a happy dance~ UwU", true),
("Nyani?? Magic baww says 'no', but chu awe stiww cute >_<", false),
("Hmm, I dink chu awe wooking fow... YESSS! UwU", true),
("Nyu-uh! But chu can twy asking a cheeky pidgeon! UwU", false),
("Yes! But chu must pwomise to make fwiends wif a cuddwy bunny~", true),
("Mmmm... nyope! Sowwy, but chu'we stiww bwoomin' pawsome! >w<", false),
("Yes, yes, aww the yesses in the wowwd fow chu! >w<", true),
("Nyooooope! But chu awe too fwuffy to be sad >w<", false),
("OwO it's a paw-sitive YES fwom me uwu!", true),
("UwU Magic fwuff says 'nyope', but gives chu a cozy bwankie!", false),
("M-m-maybe! Chu might need to twy a cute head tiwt fiwst~", false),
("Yes, UwU! But make suwe to cwink a toastie wif milkies~", true),
("Mmmm... I dink chu awe onto something gweat! It's YESSS! UwU", true),
("Nyaww, magic baww says no, but chu awe stiww adorable~ >w<", false),
("The staws awe wispiewing 'Yes' just fow chu! >w<", true),
("Oh nyo, the cosmic fwuff says 'nyope', but chu awe bwoomin' bwootiful!", false),
("Yes! Go fo' it wike a puppy chasing da sunshine~", true),
("Nuh-uh, not dis time. But chu'we so fwuffin' cute dat it's okay! UwU", false),
("Pawsitively YES! But pwomise chu'ww keep being pwecious~ >_<", true),
("Nyaww, it's a 'no', but chu awe stiww pwetty amazing! UwU", false),
("Yes! Go get it wike a kitty pwouncing on its favouwite toyyy! OwO", true),
("Hmmm... Magic fwuffies awe undeciwded. Twy a hug fiwst? >w<", false),
("Oh nyes! But chu must say 'Nyan nyan' to seaw da deaw!", true),
("Nyani?? Magic baww says nyope, but a kissy on da cheek fixes evewyfing! UwU", false),
("OwO The magic wainbows awe wifting chu to a 'yes'! Go fow it!", true),
("Oh nyo... the fwuffies awe shy dis time. Twy again wif an extwa cwute smiwe~ >w<", false),
("OwO yus yus! Definitewy a big YES!!", true),
("Uwu~ oh nyo, it wooks wike a no... sowwy!", false)
];
fn get_random_chicken_response() -> &'static str { CHICKEN_RESPONSES[random::<usize>() % CHICKEN_RESPONSES.len()] } fn get_random_response() -> &'static str { RESPONSES[random::<u32>() as usize % RESPONSES.len()].0 }
fn get_random_chaotic_response() -> &'static str { CHAOTIC_RESPONSES[random::<usize>() % CHAOTIC_RESPONSES.len()] } fn get_random_chicken_response() -> &'static str { CHICKEN_RESPONSES[random::<u32>() as usize % CHICKEN_RESPONSES.len()].0 }
fn get_random_chaotic_response() -> &'static str { CHAOTIC_RESPONSES[random::<u32>() as usize % CHAOTIC_RESPONSES.len()].0 }
fn get_random_uwu_response() -> &'static str { UWU_RESPONSES[random::<u32>() as usize % UWU_RESPONSES.len()].0 }

View File

@ -14,13 +14,11 @@ impl EventProcessor<'_> {
&self, &self,
total_shards: &NonZero<u16> total_shards: &NonZero<u16>
) -> RustbotResult<()> { ) -> RustbotResult<()> {
let shards = if *total_shards == NonZero::new(1).unwrap() { let is_singular = total_shards.get() == 1;
"shard is" println!(
} else { "{RUSTBOT_EVENT}[ShardsReady]: {total_shards} {} ready!",
"shards are" if is_singular { "shard is" } else { "shards are" }
}; );
println!("{RUSTBOT_EVENT}[ShardsReady]: {total_shards} {shards} ready!");
Ok(()) Ok(())
} }
@ -29,7 +27,6 @@ impl EventProcessor<'_> {
event: &ShardStageUpdateEvent event: &ShardStageUpdateEvent
) -> RustbotResult<()> { ) -> RustbotResult<()> {
println!("{RUSTBOT_EVENT}[ShardStageUpdate:S{}]: {event:#?}", event.shard_id); println!("{RUSTBOT_EVENT}[ShardStageUpdate:S{}]: {event:#?}", event.shard_id);
Ok(()) Ok(())
} }
} }

View File

@ -1,3 +0,0 @@
pub mod tasks;
const RUSTBOT_SCHEDULER: &str = "RustbotScheduler";

View File

@ -1,43 +0,0 @@
use crate::RUSTBOT_SCHEDULER;
use {
std::{
future::Future,
sync::Arc
},
tokio::{
task,
time::{
Duration,
interval
}
}
};
pub struct Scheduler;
impl Scheduler {
pub fn new() -> Arc<Self> { Arc::new(Self) }
pub async fn spawn_job<F, E>(
&self,
interval_secs: u64,
job: Arc<dyn Fn() -> F + Send + Sync + 'static>
) where
F: Future<Output = Result<(), E>> + Send + 'static,
E: std::fmt::Debug
{
let mut interval = interval(Duration::from_secs(interval_secs));
loop {
interval.tick().await;
let job_clone = job.clone();
task::spawn(async move {
if let Err(y) = job_clone().await {
eprintln!("{RUSTBOT_SCHEDULER}[Job:Error]: {y:?}");
}
});
}
}
}

View File

@ -17,6 +17,7 @@ use {
config::BINARY_PROPERTIES, config::BINARY_PROPERTIES,
utils::get_guild_name utils::get_guild_name
}, },
rustbot_tasks::spawn_task,
rustbot_tokens::discord_token, rustbot_tokens::discord_token,
std::{ std::{
borrow::Cow, borrow::Cow,
@ -26,11 +27,9 @@ use {
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let prefix = if BINARY_PROPERTIES.env.contains("prod") { let prefix = Some(Cow::Borrowed(if BINARY_PROPERTIES.env.contains("prod") { "pg." } else { "pg!" }));
Some(Cow::Borrowed("pg."))
} else { let data = Arc::new(RustbotData {});
Some(Cow::Borrowed("pg!"))
};
let framework = poise::Framework::builder() let framework = poise::Framework::builder()
.options(poise::FrameworkOptions { .options(poise::FrameworkOptions {
@ -41,10 +40,10 @@ async fn main() {
Some(channel) => format!("in #{}", channel.name.clone()), Some(channel) => format!("in #{}", channel.name.clone()),
None => String::from("") None => String::from("")
}; };
let prefix = match ctx.command().prefix_action { let prefix = ctx
Some(_) => ctx.framework().options.prefix_options.prefix.as_ref().unwrap(), .command()
None => "/" .prefix_action
}; .map_or("/", |_| ctx.framework().options.prefix_options.prefix.as_ref().unwrap());
println!( println!(
"Discord[{}:S{}]: {} ran {prefix}{} {get_guild_channel_name}", "Discord[{}:S{}]: {} ran {prefix}{} {get_guild_channel_name}",
@ -77,11 +76,14 @@ async fn main() {
GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT
) )
.framework(framework) .framework(framework)
.data(Arc::new(RustbotData {})) .data(Arc::clone(&data))
.activity(ActivityData::custom("nep nep!")) .activity(ActivityData::custom("nep nep!"))
.await .await
.expect("Error creating client"); .expect("Error creating client");
spawn_task(example_task::ExampleTask, Arc::clone(&data)).await;
spawn_task(example_task2::ExampleTask2, Arc::clone(&data)).await;
let shard_manager = client.shard_manager.clone(); let shard_manager = client.shard_manager.clone();
tokio::spawn(async move { tokio::spawn(async move {
@ -93,3 +95,65 @@ async fn main() {
println!("Error starting client: {why:#?}"); println!("Error starting client: {why:#?}");
} }
} }
mod example_task {
use {
poise::serenity_prelude::async_trait,
rustbot_lib::{
RustbotData,
RustbotResult
},
rustbot_tasks::TaskCoordinator,
std::sync::Arc,
tokio::time::Duration
};
#[derive(Clone)]
pub struct ExampleTask;
#[async_trait]
impl TaskCoordinator for ExampleTask {
fn name(&self) -> &'static str { "example_task" }
fn interval(&self) -> Duration { Duration::from_secs(10) }
async fn run(
&self,
_: Arc<RustbotData>
) -> RustbotResult<()> {
println!("hello from ExampleTask !");
Ok(())
}
}
}
mod example_task2 {
use {
poise::serenity_prelude::async_trait,
rustbot_lib::{
RustbotData,
RustbotResult
},
rustbot_tasks::TaskCoordinator,
std::sync::Arc,
tokio::time::Duration
};
#[derive(Clone)]
pub struct ExampleTask2;
#[async_trait]
impl TaskCoordinator for ExampleTask2 {
fn name(&self) -> &'static str { "example_task2" }
fn interval(&self) -> Duration { Duration::from_secs(5) }
async fn run(
&self,
_: Arc<RustbotData>
) -> RustbotResult<()> {
println!("hello from ExampleTask2 !");
Ok(())
}
}
}

View File

@ -7,11 +7,16 @@ use tokio::{
}; };
pub async fn gracefully_shutdown() { pub async fn gracefully_shutdown() {
let [mut s1, mut s2] = [signal(SignalKind::interrupt()).unwrap(), signal(SignalKind::hangup()).unwrap()]; let [mut s1, mut s2, mut s3] = [
signal(SignalKind::interrupt()).unwrap(),
signal(SignalKind::hangup()).unwrap(),
signal(SignalKind::terminate()).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! 👋");

View File

@ -2,7 +2,7 @@ Only things that are needing to be changed before deploying this template to rea
- The project name (Rustbot) - The project name (Rustbot)
- Dockerfile image tag and its service in compose file - Dockerfile image tag and its service in compose file
- events (rustbot_events), and its references - events (rustbot_events), and its references
- jobs (rustbot_jobs), and its references - tasks (rustbot_tasks), and its references
- library (rustbot_lib), and its references - library (rustbot_lib), and its references
- tsclient (rustbot_tokens), and its references - tsclient (rustbot_tokens), and its references

View File

@ -1,7 +1,9 @@
[package] [package]
name = "rustbot_jobs" name = "rustbot_tasks"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
tokio = { workspace = true } tokio = { workspace = true }
rustbot_lib = {workspace = true }
poise = { workspace = true }

40
tasks/src/lib.rs Executable file
View File

@ -0,0 +1,40 @@
use {
poise::serenity_prelude::async_trait,
rustbot_lib::{
RustbotData,
RustbotResult
},
std::sync::Arc,
tokio::time::{
Duration,
interval
}
};
#[async_trait]
pub trait TaskCoordinator: Send + Sync {
fn name(&self) -> &'static str;
fn interval(&self) -> Duration;
async fn run(
&self,
data: Arc<RustbotData>
) -> RustbotResult<()>;
}
pub async fn spawn_task<T: TaskCoordinator + 'static>(
task: T,
data: Arc<RustbotData>
) {
let t_name = task.name().to_string();
let t_interval = task.interval();
tokio::spawn(async move {
let mut interval = interval(t_interval);
loop {
interval.tick().await;
if let Err(e) = task.run(data.clone()).await {
eprintln!("TaskCoordinator[Err:{t_name}] {e}")
}
}
});
}