Update template with changes

This commit is contained in:
Nwero 2025-03-20 14:38:03 +11:00
parent 61d545c462
commit 6eaffb993a
12 changed files with 294 additions and 394 deletions

@ -1,2 +1,2 @@
[registries.gitea]
index = "https://git.toast-server.net/toast/_cargo-index"
index = "https://git.toast-server.net/nwerosama/_cargo-index"

494
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -3,7 +3,7 @@ WORKDIR /builder
COPY . .
FROM adelielinux/adelie:1.0-beta6@sha256:7126a96c19be064a487ba7176baa58200a26ce8fda02b851b4a0bef760b1f469
LABEL org.opencontainers.image.source="https://git.toast-server.net/toast/Rustbot"
LABEL org.opencontainers.image.source="https://git.toast-server.net/nwerosama/Rustbot"
RUN apk add --no-cache libgcc
WORKDIR /rustbot
COPY --from=base /builder/target/x86_64-unknown-linux-musl/release/rustbot .

@ -1,11 +1,7 @@
use {
poise::{
CreateReply,
serenity_prelude::{
ChannelId,
ShardId,
ShardRunnerInfo
}
serenity_prelude::ChannelId
},
rustbot_lib::{
RustbotContext,
@ -13,7 +9,7 @@ use {
}
};
async fn format_shard_info(
/* async fn format_shard_info(
id: &ShardId,
runner: &ShardRunnerInfo,
ctx: &RustbotContext<'_>
@ -35,7 +31,7 @@ async fn format_shard_info(
string.push_str(&format!("> Guilds: **{guild_count}**"));
string
}
} */
/// Developer commands
#[poise::command(
@ -44,7 +40,7 @@ async fn format_shard_info(
owners_only,
install_context = "Guild|User",
interaction_context = "Guild|BotDm|PrivateChannel",
subcommands("deploy", "servers", "shards", "echo")
subcommands("deploy", "servers", "echo")
)]
pub async fn dev(_: RustbotContext<'_>) -> RustbotResult<()> { Ok(()) }
@ -62,7 +58,10 @@ async fn servers(ctx: RustbotContext<'_>) -> RustbotResult<()> {
Ok(())
}
/// View the status of available shards
// Re-enable when proper implementation takes place, since
// it got removed during Serenity's gateway refactor.
// -----
/* /// View the status of available shards
#[poise::command(slash_command)]
async fn shards(ctx: RustbotContext<'_>) -> RustbotResult<()> {
let shard_runners = ctx.framework().shard_manager().runners.clone();
@ -82,7 +81,7 @@ async fn shards(ctx: RustbotContext<'_>) -> RustbotResult<()> {
ctx.reply(shard_info.join("\n\n")).await?;
Ok(())
}
} */
/// Turn your message into a bot message
#[poise::command(slash_command)]

@ -1,6 +1,6 @@
services:
app:
container_name: rustbot-app
#image: 'git.toast-server.net/toast/rustbot:main'
#image: 'git.toast-server.net/nwerosama/rustbot:main'
build: .
restart: unless-stopped

@ -1,32 +1,34 @@
mod ready;
mod shards;
use {
poise::serenity_prelude::FullEvent,
rustbot_lib::{
RustbotFwCtx,
RustbotResult
}
poise::serenity_prelude::{
Context,
EventHandler,
Ready,
async_trait
},
std::num::NonZero
};
pub const RUSTBOT_EVENT: &str = "RustbotEvent";
struct EventProcessor<'a> {
framework: RustbotFwCtx<'a>
}
pub struct RustbotEvents;
pub async fn processor(
framework: RustbotFwCtx<'_>,
event: &FullEvent
) -> RustbotResult<()> {
let processor = EventProcessor { framework };
match event {
FullEvent::Ready { data_about_bot } => processor.on_ready(data_about_bot).await?,
FullEvent::ShardsReady { total_shards } => processor.on_shards_ready(total_shards).await?,
FullEvent::ShardStageUpdate { event } => processor.on_shards_stageupdate(event).await?,
_ => {}
#[async_trait]
impl EventHandler for RustbotEvents {
async fn ready(
&self,
ctx: Context,
ready: Ready
) {
ready::on_ready(ctx, ready).await.unwrap()
}
Ok(())
async fn shards_ready(
&self,
_: Context,
total_shards: NonZero<u16>
) {
println!("{RUSTBOT_EVENT}[ShardsReady] {total_shards} shards are up and ready!")
}
}

@ -1,18 +1,15 @@
use super::{
EventProcessor,
RUSTBOT_EVENT
};
use super::RUSTBOT_EVENT;
use {
poise::serenity_prelude::{
ChannelId,
Context,
CreateEmbed,
CreateEmbedAuthor,
CreateMessage,
Ready
},
rustbot_lib::{
RustbotFwCtx,
RustbotResult,
config::BINARY_PROPERTIES,
utils::{
@ -20,41 +17,31 @@ use {
GIT_COMMIT_BRANCH,
GIT_COMMIT_HASH
}
},
std::sync::atomic::{
AtomicBool,
Ordering::Relaxed
}
};
static READY_ONCE: AtomicBool = AtomicBool::new(false);
async fn ready_once(
ready: &Ready,
framework: RustbotFwCtx<'_>
ctx: &Context,
ready: &Ready
) -> RustbotResult<()> {
let sid = ctx.shard_id;
#[cfg(not(feature = "production"))]
{
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?;
println!("{RUSTBOT_EVENT}[Ready:Notice:S{sid}]: Detected a development environment!",);
let gateway = ctx.http.get_bot_gateway().await?;
let session = gateway.session_start_limit;
println!(
"{RUSTBOT_EVENT}[Ready:Notice:S{}]: Session limit: {}/{}",
framework.serenity_context.shard_id, session.remaining, session.total
"{RUSTBOT_EVENT}[Ready:Notice:S{sid}]: Session limit: {}/{}",
session.remaining, session.total
);
}
println!(
"{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
"{RUSTBOT_EVENT}[Ready:S{sid}]: Build version: v{} ({GIT_COMMIT_HASH}:{GIT_COMMIT_BRANCH})",
*BOT_VERSION
);
println!("{RUSTBOT_EVENT}[Ready:S{sid}]: Connected to API as {}", ready.user.name);
let message = CreateMessage::new();
let ready_embed = CreateEmbed::new()
@ -63,23 +50,21 @@ async fn ready_once(
.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))
.send_message(&ctx.http, message.add_embed(ready_embed))
.await?;
Ok(())
}
impl EventProcessor<'_> {
pub async fn on_ready(
&self,
data_about_bot: &Ready
) -> RustbotResult<()> {
if !READY_ONCE.swap(true, Relaxed) {
ready_once(data_about_bot, self.framework)
.await
.expect("Failed to call ready_once method");
}
pub async fn on_ready(
ctx: Context,
ready: Ready
) -> RustbotResult<()> {
let shard_id = ctx.shard_id;
Ok(())
if shard_id.0 == 0 {
ready_once(&ctx, &ready).await.expect("Failed to call ready_once method");
}
Ok(())
}

@ -1,32 +0,0 @@
use super::{
EventProcessor,
RUSTBOT_EVENT
};
use {
poise::serenity_prelude::ShardStageUpdateEvent,
rustbot_lib::RustbotResult,
std::num::NonZero
};
impl EventProcessor<'_> {
pub async fn on_shards_ready(
&self,
total_shards: &NonZero<u16>
) -> RustbotResult<()> {
let is_singular = total_shards.get() == 1;
println!(
"{RUSTBOT_EVENT}[ShardsReady]: {total_shards} {} ready!",
if is_singular { "shard is" } else { "shards are" }
);
Ok(())
}
pub async fn on_shards_stageupdate(
&self,
event: &ShardStageUpdateEvent
) -> RustbotResult<()> {
println!("{RUSTBOT_EVENT}[ShardStageUpdate:S{}]: {event:#?}", event.shard_id);
Ok(())
}
}

@ -1,4 +1,6 @@
pub mod events;
mod events;
pub use events::RustbotEvents;
// use serde_json::json;
/* use poise::serenity_prelude::{

@ -19,7 +19,6 @@ pub async fn fw_errors(error: FrameworkError<'_, RustbotData, RustbotError>) {
.await
.expect("Error sending message");
},
poise::FrameworkError::EventHandler { error, event, .. } => println!("PoiseEventHandlerError({}): {error}", event.snake_case_name()),
poise::FrameworkError::NotAnOwner { ctx, .. } => {
println!(
"PoiseNotAnOwner: {} tried to execute a developer-level command ({})",

@ -11,7 +11,7 @@ use {
builder::CreateAllowedMentions
},
rustbot_cmds::collect,
rustbot_events::events::processor,
rustbot_events::RustbotEvents,
rustbot_lib::{
RustbotData,
config::BINARY_PROPERTIES,
@ -66,7 +66,6 @@ async fn main() {
allowed_mentions: Some(CreateAllowedMentions::default().empty_users()),
initialize_owners: true,
skip_checks_for_owners: true,
event_handler: |framework, event| Box::pin(processor(framework, event)),
..Default::default()
})
.build();
@ -76,6 +75,7 @@ async fn main() {
GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT
)
.framework(framework)
.event_handler(RustbotEvents)
.data(Arc::clone(&data))
.activity(ActivityData::custom("nep nep!"))
.await
@ -84,15 +84,19 @@ async fn main() {
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 exit_signal = tokio::spawn(async move { shutdown::gracefully_shutdown().await });
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:#?}");
tokio::select! {
client_result = client.start() => {
if let Err(why) = client_result {
eprintln!("Client error: {why:#?}")
}
},
shutdown = exit_signal => {
if shutdown.unwrap() {
std::process::exit(0)
}
}
}
}

@ -6,7 +6,7 @@ use tokio::{
}
};
pub async fn gracefully_shutdown() {
pub async fn gracefully_shutdown() -> bool {
let [mut s1, mut s2, mut s3] = [
signal(SignalKind::interrupt()).unwrap(),
signal(SignalKind::hangup()).unwrap(),
@ -20,4 +20,5 @@ pub async fn gracefully_shutdown() {
);
println!("\nRustbot says goodbye! 👋");
true
}