Update template with changes
This commit is contained in:
parent
1afad09caf
commit
56e1419b32
881
Cargo.lock
generated
881
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,7 @@ cargo_toml = "0.20.5"
|
||||
poise = "0.6.1"
|
||||
regex = "1.11.0"
|
||||
serde = "1.0.210"
|
||||
tokio = { version = "1.40.0", features = ["macros", "rt-multi-thread"] }
|
||||
tokio = { version = "1.40.0", features = ["macros", "signal", "rt-multi-thread"] }
|
||||
reqwest = { version = "0.12.8", features = ["native-tls-vendored"] }
|
||||
|
||||
[dependencies]
|
||||
|
@ -1,25 +1,22 @@
|
||||
mod ready;
|
||||
mod shards;
|
||||
|
||||
use poise::serenity_prelude::FullEvent;
|
||||
use rustbot_lib::{
|
||||
RustbotError,
|
||||
RustbotData
|
||||
};
|
||||
use poise::{
|
||||
FrameworkContext,
|
||||
serenity_prelude::FullEvent
|
||||
RustbotFwCtx,
|
||||
RustbotResult
|
||||
};
|
||||
|
||||
pub const RUSTBOT_EVENT: &str = "RustbotEvent";
|
||||
|
||||
struct EventProcessor<'a> {
|
||||
framework: FrameworkContext<'a, RustbotData, RustbotError>
|
||||
framework: RustbotFwCtx<'a>
|
||||
}
|
||||
|
||||
pub async fn processor(
|
||||
framework: FrameworkContext<'_, RustbotData, RustbotError>,
|
||||
framework: RustbotFwCtx<'_>,
|
||||
event: &FullEvent
|
||||
) -> Result<(), RustbotError> {
|
||||
) -> RustbotResult<()> {
|
||||
let processor = EventProcessor { framework };
|
||||
|
||||
match event {
|
||||
|
@ -1,11 +1,11 @@
|
||||
use crate::PoiseFwCtx;
|
||||
use super::{
|
||||
EventProcessor,
|
||||
RUSTBOT_EVENT
|
||||
};
|
||||
|
||||
use rustbot_lib::{
|
||||
RustbotError,
|
||||
RustbotFwCtx,
|
||||
RustbotResult,
|
||||
utils::{
|
||||
BOT_VERSION,
|
||||
GIT_COMMIT_HASH,
|
||||
@ -15,7 +15,7 @@ use rustbot_lib::{
|
||||
};
|
||||
use std::sync::atomic::{
|
||||
AtomicBool,
|
||||
Ordering
|
||||
Ordering::Relaxed
|
||||
};
|
||||
use poise::serenity_prelude::{
|
||||
Ready,
|
||||
@ -29,8 +29,8 @@ static READY_ONCE: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
async fn ready_once(
|
||||
ready: &Ready,
|
||||
framework: PoiseFwCtx<'_>
|
||||
) -> Result<(), RustbotError> {
|
||||
framework: RustbotFwCtx<'_>
|
||||
) -> RustbotResult<()> {
|
||||
#[cfg(not(feature = "production"))]
|
||||
{
|
||||
println!("{RUSTBOT_EVENT}[Ready:Notice:S{}]: Detected a non-production environment!", framework.serenity_context.shard_id);
|
||||
@ -57,8 +57,8 @@ impl EventProcessor<'_> {
|
||||
pub async fn on_ready(
|
||||
&self,
|
||||
data_about_bot: &Ready
|
||||
) -> Result<(), RustbotError> {
|
||||
if !READY_ONCE.swap(true, Ordering::Relaxed) {
|
||||
) -> RustbotResult<()> {
|
||||
if !READY_ONCE.swap(true, Relaxed) {
|
||||
ready_once(data_about_bot, self.framework).await.expect("Failed to call ready_once method");
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,14 @@ use super::{
|
||||
};
|
||||
|
||||
use std::num::NonZero;
|
||||
use rustbot_lib::RustbotError;
|
||||
use rustbot_lib::RustbotResult;
|
||||
use poise::serenity_prelude::ShardStageUpdateEvent;
|
||||
|
||||
impl EventProcessor<'_> {
|
||||
pub async fn on_shards_ready(
|
||||
&self,
|
||||
total_shards: &NonZero<u16>
|
||||
) -> Result<(), RustbotError> {
|
||||
) -> RustbotResult<()> {
|
||||
let shards = if *total_shards == NonZero::new(1).unwrap() { "shard is" } else { "shards are" };
|
||||
println!("{RUSTBOT_EVENT}[ShardsReady]: {total_shards} {shards} ready!");
|
||||
|
||||
@ -21,7 +21,7 @@ impl EventProcessor<'_> {
|
||||
pub async fn on_shards_stageupdate(
|
||||
&self,
|
||||
event: &ShardStageUpdateEvent
|
||||
) -> Result<(), RustbotError> {
|
||||
) -> RustbotResult<()> {
|
||||
println!("{RUSTBOT_EVENT}[ShardStageUpdate:S{}]: {event:#?}", event.shard_id);
|
||||
|
||||
Ok(())
|
||||
|
@ -1,19 +1,10 @@
|
||||
pub mod events;
|
||||
|
||||
// use serde_json::json;
|
||||
use rustbot_lib::{
|
||||
RustbotData,
|
||||
RustbotError
|
||||
};
|
||||
use poise::{
|
||||
FrameworkContext,
|
||||
/* serenity_prelude::{
|
||||
/* use poise::serenity_prelude::{
|
||||
Context,
|
||||
WebhookId
|
||||
} */
|
||||
};
|
||||
|
||||
type PoiseFwCtx<'a> = FrameworkContext<'a, RustbotData, RustbotError>;
|
||||
}; */
|
||||
|
||||
/* async fn hook_logger(
|
||||
ctx: &Context,
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::sync::LazyLock;
|
||||
|
||||
pub struct ConfigMeta {
|
||||
pub env: String,
|
||||
pub env: &'static str,
|
||||
pub embed_color: u32,
|
||||
pub rustbot_logs: u64,
|
||||
pub developers: Vec<u64>
|
||||
@ -13,16 +13,16 @@ pub static BINARY_PROPERTIES: LazyLock<ConfigMeta> = LazyLock::new(ConfigMeta::n
|
||||
#[cfg(not(feature = "production"))]
|
||||
pub static BINARY_PROPERTIES: LazyLock<ConfigMeta> = LazyLock::new(||
|
||||
ConfigMeta::new()
|
||||
.env(String::from("dev"))
|
||||
.env("dev")
|
||||
.embed_color(0xf1d63c)
|
||||
);
|
||||
|
||||
impl ConfigMeta {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
env: String::from("prod"),
|
||||
env: "prod",
|
||||
embed_color: 0xf1d63c,
|
||||
rustbot_logs: 1276874302314254448,
|
||||
rustbot_logs: 1311282815601741844,
|
||||
developers: vec![
|
||||
190407856527376384 // toast.ts
|
||||
]
|
||||
@ -31,7 +31,7 @@ impl ConfigMeta {
|
||||
|
||||
// Scalable functions below;
|
||||
#[cfg(not(feature = "production"))]
|
||||
fn env(mut self, env: String) -> Self {
|
||||
fn env(mut self, env: &'static str) -> Self {
|
||||
self.env = env;
|
||||
self
|
||||
}
|
||||
|
@ -3,5 +3,7 @@ mod data;
|
||||
pub use data::RustbotData;
|
||||
pub mod utils;
|
||||
|
||||
pub type RustbotError = Box<dyn std::error::Error + Send + Sync>;
|
||||
pub type RustbotCtx<'a> = poise::Context<'a, RustbotData, RustbotError>;
|
||||
type RustbotError = Box<dyn std::error::Error + Send + Sync>;
|
||||
pub type RustbotContext<'a> = poise::Context<'a, RustbotData, RustbotError>;
|
||||
pub type RustbotFwCtx<'a> = poise::FrameworkContext<'a, RustbotData, RustbotError>;
|
||||
pub type RustbotResult<T> = Result<T, RustbotError>;
|
||||
|
@ -21,7 +21,7 @@ pub fn format_timestamp(timestamp: i64) -> String {
|
||||
format!("<t:{timestamp}>\n<t:{timestamp}:R>")
|
||||
}
|
||||
|
||||
pub fn mention_dev(ctx: super::RustbotCtx<'_>) -> Option<String> {
|
||||
pub fn mention_dev(ctx: super::RustbotContext<'_>) -> Option<String> {
|
||||
let devs = super::config::BINARY_PROPERTIES.developers.clone();
|
||||
let app_owners = ctx.framework().options().owners.clone();
|
||||
|
||||
@ -40,7 +40,7 @@ pub fn mention_dev(ctx: super::RustbotCtx<'_>) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_guild_name(ctx: super::RustbotCtx<'_>) -> String {
|
||||
pub fn get_guild_name(ctx: super::RustbotContext<'_>) -> String {
|
||||
match ctx.guild() {
|
||||
Some(guild) => guild.name.clone().to_string(),
|
||||
None => String::from("DM")
|
||||
@ -63,7 +63,7 @@ pub fn format_duration(secs: u64) -> String {
|
||||
let formatted_string: Vec<String> = components
|
||||
.iter()
|
||||
.filter(|&&(value, _)| value > 0)
|
||||
.map(|&(value, suffix)| format!("{}{}", value, suffix))
|
||||
.map(|&(value, suffix)| format!("{value}{suffix}"))
|
||||
.collect();
|
||||
|
||||
formatted_string.join(", ")
|
||||
|
@ -8,8 +8,6 @@ pub use eightball::eightball;
|
||||
pub use ping::ping;
|
||||
pub use uptime::uptime;
|
||||
|
||||
type PoiseContext<'a> = rustbot_lib::RustbotCtx<'a>;
|
||||
|
||||
macro_rules! collect {
|
||||
() => {
|
||||
vec![
|
||||
|
@ -1,53 +1,82 @@
|
||||
use crate::RustbotError;
|
||||
use super::PoiseContext;
|
||||
|
||||
use rustbot_lib::{
|
||||
RustbotContext,
|
||||
RustbotResult
|
||||
};
|
||||
use poise::{
|
||||
CreateReply,
|
||||
serenity_prelude::ChannelId
|
||||
serenity_prelude::{
|
||||
ChannelId,
|
||||
ShardId,
|
||||
ShardRunnerInfo
|
||||
}
|
||||
};
|
||||
|
||||
async fn format_shard_info(
|
||||
id: &ShardId,
|
||||
runner: &ShardRunnerInfo,
|
||||
ctx: &RustbotContext<'_>
|
||||
) -> String {
|
||||
let mut string = String::new();
|
||||
|
||||
let heartbeat = match runner.latency {
|
||||
Some(lat) => format!("`{}ms`", lat.as_millis()),
|
||||
None => "Waiting for heartbeat...".to_string()
|
||||
};
|
||||
|
||||
let status = runner.stage.to_string();
|
||||
let shard_count = ctx.cache().shard_count();
|
||||
let guild_count = ctx.cache().guilds().into_iter().filter(|g| g.shard_id(shard_count) == id.0).count() as u64;
|
||||
|
||||
string.push_str(&format!("**Shard {id}**\n"));
|
||||
string.push_str(&format!("> Heartbeat: {heartbeat}\n"));
|
||||
string.push_str(&format!("> Status: `{status}`\n"));
|
||||
string.push_str(&format!("> Guilds: **{guild_count}**"));
|
||||
|
||||
string
|
||||
}
|
||||
|
||||
/// Developer commands
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
prefix_command,
|
||||
slash_command,
|
||||
owners_only,
|
||||
install_context = "Guild|User",
|
||||
interaction_context = "Guild|BotDm|PrivateChannel",
|
||||
subcommands("deploy", "servers", "shards", "echo")
|
||||
)]
|
||||
pub async fn dev(_: PoiseContext<'_>) -> Result<(), RustbotError> {
|
||||
pub async fn dev(_: RustbotContext<'_>) -> RustbotResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Deploy commands to this guild or globally
|
||||
#[poise::command(prefix_command)]
|
||||
async fn deploy(ctx: PoiseContext<'_>) -> Result<(), RustbotError> {
|
||||
async fn deploy(ctx: RustbotContext<'_>) -> RustbotResult<()> {
|
||||
poise::builtins::register_application_commands_buttons(ctx).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// View how many servers the bot is in
|
||||
#[poise::command(prefix_command)]
|
||||
async fn servers(ctx: PoiseContext<'_>) -> Result<(), RustbotError> {
|
||||
#[poise::command(slash_command)]
|
||||
async fn servers(ctx: RustbotContext<'_>) -> RustbotResult<()> {
|
||||
poise::builtins::servers(ctx).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// View the status of available shards
|
||||
#[poise::command(prefix_command)]
|
||||
async fn shards(ctx: PoiseContext<'_>) -> Result<(), RustbotError> {
|
||||
#[poise::command(slash_command)]
|
||||
async fn shards(ctx: RustbotContext<'_>) -> RustbotResult<()> {
|
||||
let shard_runners = ctx.framework().shard_manager().runners.clone();
|
||||
let runners = shard_runners.lock().await;
|
||||
|
||||
if runners.is_empty() {
|
||||
ctx.reply("`ShardsReady` event hasn't fired yet!").await?;
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
let mut shard_info = Vec::new();
|
||||
for (id, runner) in runners.iter() {
|
||||
shard_info.push(format!(
|
||||
"**Shard {}**\n> Heartbeat: {}\n> Status: `{}`",
|
||||
id,
|
||||
match runner.latency {
|
||||
Some(lat) => format!("`{}ms`", lat.as_millis()),
|
||||
None => "Waiting for heartbeat...".to_string()
|
||||
},
|
||||
runner.stage
|
||||
))
|
||||
let info = format_shard_info(id, runner, &ctx).await;
|
||||
shard_info.push(info);
|
||||
}
|
||||
|
||||
ctx.reply(shard_info.join("\n\n")).await?;
|
||||
@ -58,11 +87,11 @@ async fn shards(ctx: PoiseContext<'_>) -> Result<(), RustbotError> {
|
||||
/// Turn your message into a bot message
|
||||
#[poise::command(slash_command)]
|
||||
async fn echo(
|
||||
ctx: super::PoiseContext<'_>,
|
||||
ctx: RustbotContext<'_>,
|
||||
#[description = "Message to be echoed as a bot"] message: String,
|
||||
#[description = "Channel to send this to"]
|
||||
#[channel_types("Text", "PublicThread", "PrivateThread")] channel: Option<ChannelId>
|
||||
) -> Result<(), RustbotError> {
|
||||
) -> RustbotResult<()> {
|
||||
ctx.defer_ephemeral().await?;
|
||||
|
||||
let channel = match channel {
|
||||
|
@ -1,22 +1,32 @@
|
||||
use crate::RustbotError;
|
||||
use super::PoiseContext;
|
||||
|
||||
use rustbot_lib::config::BINARY_PROPERTIES;
|
||||
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: PoiseContext<'_>,
|
||||
#[description = "Your yes/no question"] question: String
|
||||
) -> Result<(), RustbotError> {
|
||||
if question.to_ascii_lowercase().contains("rustbot, show list") {
|
||||
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();
|
||||
@ -29,7 +39,7 @@ pub async fn eightball(
|
||||
}
|
||||
}
|
||||
|
||||
if question.to_ascii_lowercase().contains("rustbot, show chicken list") {
|
||||
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();
|
||||
@ -42,10 +52,9 @@ pub async fn eightball(
|
||||
}
|
||||
}
|
||||
|
||||
let rand_resp = if question.to_ascii_lowercase().contains("chicken") {
|
||||
get_random_chicken_response()
|
||||
} else {
|
||||
get_random_response()
|
||||
let rand_resp = match mode {
|
||||
Some(ResponseMode::Chicken) => get_random_chicken_response(),
|
||||
_ => get_random_response()
|
||||
};
|
||||
|
||||
ctx.reply(format!("> {question}\n{rand_resp}")).await?;
|
||||
@ -53,7 +62,7 @@ pub async fn eightball(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
const RESPONSES: [&str; 30] = [
|
||||
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
|
||||
@ -88,9 +97,24 @@ const RESPONSES: [&str; 30] = [
|
||||
"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; 35] = [
|
||||
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
|
||||
@ -126,6 +150,25 @@ const CHICKEN_RESPONSES: [&str; 35] = [
|
||||
"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 {
|
||||
|
@ -1,7 +1,8 @@
|
||||
use crate::RustbotError;
|
||||
use super::PoiseContext;
|
||||
|
||||
use serde::Deserialize;
|
||||
use rustbot_lib::{
|
||||
RustbotContext,
|
||||
RustbotResult
|
||||
};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct StatusPage {
|
||||
@ -18,9 +19,13 @@ struct Summary {
|
||||
mean: f64
|
||||
}
|
||||
|
||||
/// Check latency of the bot's WS connection and Discord's API
|
||||
#[poise::command(slash_command)]
|
||||
pub async fn ping(ctx: PoiseContext<'_>) -> Result<(), RustbotError> {
|
||||
/// Check latency between bot and WebSocket as well as Discord's API latency
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
install_context = "Guild|User",
|
||||
interaction_context = "Guild|BotDm|PrivateChannel"
|
||||
)]
|
||||
pub async fn ping(ctx: RustbotContext<'_>) -> RustbotResult<()> {
|
||||
let statuspage: StatusPage = reqwest::get("https://discordstatus.com/metrics-display/5k2rt9f7pmny/day.json")
|
||||
.await.unwrap()
|
||||
.json()
|
||||
@ -29,6 +34,7 @@ pub async fn ping(ctx: PoiseContext<'_>) -> Result<(), RustbotError> {
|
||||
let mut latencies = Vec::new();
|
||||
latencies.push(format!("Discord: `{:.0?}ms`", statuspage.metrics[0].summary.mean));
|
||||
latencies.push(format!("WebSocket: `{:.0?}`", ctx.ping().await));
|
||||
latencies.push(format!("Shard ID: `{}`", ctx.serenity_context().shard_id));
|
||||
|
||||
ctx.reply(latencies.join("\n")).await?;
|
||||
|
||||
|
@ -1,6 +1,3 @@
|
||||
use crate::RustbotError;
|
||||
use super::PoiseContext;
|
||||
|
||||
use sysinfo::System;
|
||||
use uptime_lib::get;
|
||||
use std::{
|
||||
@ -17,11 +14,15 @@ use std::{
|
||||
BufReader
|
||||
}
|
||||
};
|
||||
use rustbot_lib::utils::{
|
||||
use rustbot_lib::{
|
||||
RustbotContext,
|
||||
RustbotResult,
|
||||
utils::{
|
||||
BOT_VERSION,
|
||||
GIT_COMMIT_HASH,
|
||||
GIT_COMMIT_BRANCH,
|
||||
format_duration
|
||||
}
|
||||
};
|
||||
|
||||
fn get_os_info() -> String {
|
||||
@ -63,7 +64,7 @@ fn fmt_mem(bytes: u64) -> String {
|
||||
|
||||
/// Retrieve host and bot uptimes
|
||||
#[poise::command(slash_command)]
|
||||
pub async fn uptime(ctx: PoiseContext<'_>) -> Result<(), RustbotError> {
|
||||
pub async fn uptime(ctx: RustbotContext<'_>) -> RustbotResult<()> {
|
||||
let bot = ctx.http().get_current_user().await.unwrap();
|
||||
let mut sys = System::new_all();
|
||||
sys.refresh_all();
|
||||
|
24
src/main.rs
24
src/main.rs
@ -1,8 +1,9 @@
|
||||
mod commands;
|
||||
mod shutdown;
|
||||
// https://cdn.toast-server.net/RustFSHiearchy.png
|
||||
// Using the new filesystem hierarchy
|
||||
|
||||
use rustbot_tokens::token_path;
|
||||
use rustbot_tokens::discord_token;
|
||||
use poise::serenity_prelude::{
|
||||
builder::CreateAllowedMentions,
|
||||
ClientBuilder,
|
||||
@ -14,7 +15,6 @@ use rustbot_lib::{
|
||||
mention_dev,
|
||||
get_guild_name
|
||||
},
|
||||
RustbotError,
|
||||
RustbotData,
|
||||
config::BINARY_PROPERTIES
|
||||
};
|
||||
@ -47,20 +47,19 @@ async fn main() {
|
||||
};
|
||||
|
||||
println!(
|
||||
"Discord[{}:S{}]: {} ran {}{} {}",
|
||||
"Discord[{}:S{}]: {} ran {prefix}{} {get_guild_channel_name}",
|
||||
get_guild_name(ctx),
|
||||
ctx.serenity_context().shard_id,
|
||||
ctx.author().name,
|
||||
prefix,
|
||||
ctx.command().qualified_name,
|
||||
get_guild_channel_name);
|
||||
);
|
||||
}),
|
||||
prefix_options: poise::PrefixFrameworkOptions {
|
||||
prefix,
|
||||
case_insensitive_commands: true,
|
||||
ignore_bots: true,
|
||||
execute_self_messages: false,
|
||||
mention_as_prefix: false,
|
||||
case_insensitive_commands: true,
|
||||
execute_self_messages: false,
|
||||
..Default::default()
|
||||
},
|
||||
on_error: |error| Box::pin(async move {
|
||||
@ -118,7 +117,7 @@ async fn main() {
|
||||
.build();
|
||||
|
||||
let mut client = ClientBuilder::new(
|
||||
&token_path().await.main,
|
||||
discord_token().await,
|
||||
GatewayIntents::GUILDS
|
||||
| GatewayIntents::GUILD_MESSAGES
|
||||
| GatewayIntents::MESSAGE_CONTENT
|
||||
@ -128,7 +127,14 @@ async fn main() {
|
||||
.activity(ActivityData::custom("nep nep!"))
|
||||
.await.expect("Error creating client");
|
||||
|
||||
let shard_manager = client.shard_manager.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
shutdown::gracefully_shutdown().await;
|
||||
shard_manager.shutdown_all().await;
|
||||
});
|
||||
|
||||
if let Err(why) = client.start_autosharded().await {
|
||||
println!("Error starting client: {:#?}", why);
|
||||
println!("Error starting client: {why:#?}");
|
||||
}
|
||||
}
|
||||
|
23
src/shutdown.rs
Normal file
23
src/shutdown.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use tokio::{
|
||||
select,
|
||||
signal::unix::{
|
||||
signal,
|
||||
SignalKind
|
||||
}
|
||||
};
|
||||
|
||||
pub async fn gracefully_shutdown() {
|
||||
let [mut s1, mut s2, mut s3] = [
|
||||
signal(SignalKind::interrupt()).unwrap(),
|
||||
signal(SignalKind::terminate()).unwrap(),
|
||||
signal(SignalKind::hangup()).unwrap()
|
||||
];
|
||||
|
||||
select!(
|
||||
v = s1.recv() => v.unwrap(),
|
||||
v = s2.recv() => v.unwrap(),
|
||||
v = s3.recv() => v.unwrap()
|
||||
);
|
||||
|
||||
println!("\nRustbot says goodbye! 👋");
|
||||
}
|
@ -6,6 +6,6 @@ Only things that are needing to be changed before deploying this template to rea
|
||||
- library (rustbot_lib), and its references
|
||||
- tsclient (rustbot_tokens), and its references
|
||||
|
||||
Search by Rustbot in its usual form (all-caps, pascalcase, and such) to find all the references that need to be changed too.
|
||||
Search by Rustbot in its usual form (ALL-CAPS, PascalCase, and such) to find all the references that need to be changed too.
|
||||
|
||||
(and delete this file too!)
|
||||
|
@ -4,5 +4,6 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
poise = { workspace = true }
|
||||
tokenservice-client = { version = "0.4.1", registry = "gitea" }
|
||||
tokio = { workspace = true }
|
||||
|
@ -1,5 +1,9 @@
|
||||
use std::sync::LazyLock;
|
||||
use poise::serenity_prelude::Token;
|
||||
use tokio::sync::Mutex;
|
||||
use std::{
|
||||
str::FromStr,
|
||||
sync::LazyLock
|
||||
};
|
||||
use tokenservice_client::{
|
||||
TokenService,
|
||||
TokenServiceApi
|
||||
@ -33,3 +37,8 @@ static TSCLIENT: LazyLock<Mutex<TSClient>> = LazyLock::new(|| Mutex::new(TSClien
|
||||
pub async fn token_path() -> TokenServiceApi {
|
||||
TSCLIENT.lock().await.get().await.unwrap()
|
||||
}
|
||||
|
||||
pub async fn discord_token() -> Token {
|
||||
Token::from_str(&token_path().await.main)
|
||||
.expect("Serenity couldn't parse the bot token!")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user