2023-12-04 16:35:42 +11:00
|
|
|
mod commands;
|
2024-03-25 18:32:10 +11:00
|
|
|
mod controllers;
|
|
|
|
mod models;
|
2024-03-16 09:47:21 +11:00
|
|
|
mod internals;
|
2024-08-09 18:19:59 -04:00
|
|
|
// https://cdn.toast-server.net/RustFSHiearchy.png
|
|
|
|
// Using the new filesystem hierarchy
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
internals::{
|
|
|
|
utils::{
|
|
|
|
BOT_VERSION,
|
|
|
|
token_path,
|
|
|
|
mention_dev
|
|
|
|
},
|
|
|
|
config::BINARY_PROPERTIES
|
|
|
|
},
|
|
|
|
controllers::database::DatabaseController
|
|
|
|
};
|
2023-12-04 16:35:42 +11:00
|
|
|
|
2024-03-13 20:27:16 +11:00
|
|
|
use std::{
|
2024-08-09 18:19:59 -04:00
|
|
|
thread::current,
|
|
|
|
sync::{
|
|
|
|
Arc,
|
|
|
|
atomic::{
|
|
|
|
AtomicBool,
|
|
|
|
Ordering
|
|
|
|
}
|
|
|
|
}
|
2024-03-13 20:27:16 +11:00
|
|
|
};
|
2024-03-21 09:03:09 +11:00
|
|
|
use poise::serenity_prelude::{
|
2024-01-12 13:59:46 +11:00
|
|
|
builder::{
|
|
|
|
CreateMessage,
|
|
|
|
CreateEmbed,
|
|
|
|
CreateEmbedAuthor
|
|
|
|
},
|
2024-03-11 10:06:40 +11:00
|
|
|
Ready,
|
2024-08-09 18:19:59 -04:00
|
|
|
Context,
|
|
|
|
FullEvent,
|
2024-01-12 13:59:46 +11:00
|
|
|
ClientBuilder,
|
2024-03-21 09:03:09 +11:00
|
|
|
ChannelId,
|
|
|
|
Command,
|
2024-01-12 13:59:46 +11:00
|
|
|
GatewayIntents
|
|
|
|
};
|
2023-12-04 16:35:42 +11:00
|
|
|
|
2024-08-09 18:19:59 -04:00
|
|
|
type Error = Box<dyn std::error::Error + Send + Sync>;
|
|
|
|
static TASK_RUNNING: AtomicBool = AtomicBool::new(false);
|
2023-12-04 16:35:42 +11:00
|
|
|
|
2024-08-09 18:19:59 -04:00
|
|
|
#[cfg(feature = "production")]
|
|
|
|
pub static GIT_COMMIT_HASH: &str = env!("GIT_COMMIT_HASH");
|
|
|
|
#[cfg(not(feature = "production"))]
|
|
|
|
pub static GIT_COMMIT_HASH: &str = "devel";
|
2023-12-07 11:22:16 +11:00
|
|
|
|
2023-12-04 16:35:42 +11:00
|
|
|
async fn on_ready(
|
2024-03-11 10:06:40 +11:00
|
|
|
ctx: &Context,
|
|
|
|
ready: &Ready,
|
2023-12-04 16:35:42 +11:00
|
|
|
framework: &poise::Framework<(), Error>
|
|
|
|
) -> Result<(), Error> {
|
2024-08-09 18:19:59 -04:00
|
|
|
#[cfg(not(feature = "production"))]
|
|
|
|
{
|
|
|
|
println!("Event[Ready][Notice]: Detected a non-production environment!");
|
|
|
|
let gateway = ctx.http.get_bot_gateway().await?;
|
|
|
|
let session = gateway.session_start_limit;
|
|
|
|
println!("Event[Ready][Notice]: Session limit: {}/{}", session.remaining, session.total);
|
|
|
|
}
|
|
|
|
|
|
|
|
println!("Event[Ready]: Build version: {} ({})", BOT_VERSION.to_string(), GIT_COMMIT_HASH);
|
|
|
|
println!("Event[Ready]: Connected to API as {}", ready.user.name);
|
2023-12-04 16:35:42 +11:00
|
|
|
|
2024-01-12 13:59:46 +11:00
|
|
|
let message = CreateMessage::new();
|
|
|
|
let ready_embed = CreateEmbed::new()
|
2024-08-09 18:19:59 -04:00
|
|
|
.color(BINARY_PROPERTIES.embed_color)
|
2024-01-12 13:59:46 +11:00
|
|
|
.thumbnail(ready.user.avatar_url().unwrap_or_default())
|
2024-08-09 18:19:59 -04:00
|
|
|
.author(CreateEmbedAuthor::new(format!("{} is ready!", ready.user.name)));
|
2024-01-12 13:59:46 +11:00
|
|
|
|
2024-08-09 18:19:59 -04:00
|
|
|
ChannelId::new(BINARY_PROPERTIES.ready_notify).send_message(&ctx.http, message.add_embed(ready_embed)).await?;
|
2023-12-06 08:38:19 +11:00
|
|
|
|
2024-08-09 18:19:59 -04:00
|
|
|
if BINARY_PROPERTIES.deploy_commands {
|
2023-12-05 14:25:20 +11:00
|
|
|
let builder = poise::builtins::create_application_commands(&framework.options().commands);
|
2024-03-21 09:03:09 +11:00
|
|
|
let commands = Command::set_global_commands(&ctx.http, builder).await;
|
2024-08-09 18:19:59 -04:00
|
|
|
let mut commands_deployed = std::collections::HashSet::new();
|
2023-12-05 14:25:20 +11:00
|
|
|
|
|
|
|
match commands {
|
2023-12-31 16:03:49 +11:00
|
|
|
Ok(cmdmap) => for command in cmdmap.iter() {
|
2024-08-09 18:19:59 -04:00
|
|
|
commands_deployed.insert(command.name.clone());
|
2024-03-11 10:06:40 +11:00
|
|
|
},
|
2024-08-09 18:19:59 -04:00
|
|
|
Err(y) => eprintln!("Error registering commands: {:?}", y)
|
|
|
|
}
|
|
|
|
|
|
|
|
if commands_deployed.len() > 0 {
|
|
|
|
println!("Event[Ready]: Deployed the commands globally:\n- {}", commands_deployed.into_iter().collect::<Vec<_>>().join("\n- "));
|
2023-12-05 14:25:20 +11:00
|
|
|
}
|
2023-12-05 13:11:45 +11:00
|
|
|
}
|
2023-12-04 16:35:42 +11:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-08-09 18:19:59 -04:00
|
|
|
async fn event_processor(
|
|
|
|
ctx: &Context,
|
|
|
|
event: &FullEvent,
|
|
|
|
framework: poise::FrameworkContext<'_, (), Error>
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
match event {
|
|
|
|
FullEvent::Ratelimit { data } => {
|
|
|
|
println!("Event[Ratelimit]: {:#?}", data);
|
|
|
|
}
|
|
|
|
FullEvent::Message { new_message } => {
|
|
|
|
if new_message.author.bot || !new_message.guild_id.is_none() {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
if new_message.content.to_lowercase().starts_with("deploy") && new_message.author.id == BINARY_PROPERTIES.developers[0] {
|
|
|
|
let builder = poise::builtins::create_application_commands(&framework.options().commands);
|
|
|
|
let commands = Command::set_global_commands(&ctx.http, builder).await;
|
|
|
|
let mut commands_deployed = std::collections::HashSet::new();
|
|
|
|
|
|
|
|
match commands {
|
|
|
|
Ok(cmdmap) => for command in cmdmap.iter() {
|
|
|
|
commands_deployed.insert(command.name.clone());
|
|
|
|
},
|
|
|
|
Err(y) => {
|
|
|
|
eprintln!("Error registering commands: {:?}", y);
|
|
|
|
new_message.reply(&ctx.http, "Deployment failed, check console for more details!").await?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if commands_deployed.len() > 0 {
|
|
|
|
new_message.reply(&ctx.http, format!(
|
|
|
|
"Deployed the commands globally:\n- {}",
|
|
|
|
commands_deployed.into_iter().collect::<Vec<_>>().join("\n- ")
|
|
|
|
)).await?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FullEvent::Ready { .. } => {
|
|
|
|
let thread_id = format!("{:?}", current().id());
|
|
|
|
let thread_num: String = thread_id.chars().filter(|c| c.is_digit(10)).collect();
|
|
|
|
println!("Event[Ready]: Task Scheduler operating on thread {}", thread_num);
|
|
|
|
|
|
|
|
let ctx = Arc::new(ctx.clone());
|
|
|
|
|
|
|
|
if !TASK_RUNNING.load(Ordering::SeqCst) {
|
|
|
|
TASK_RUNNING.store(true, Ordering::SeqCst);
|
|
|
|
|
|
|
|
tokio::spawn(async move {
|
|
|
|
match internals::tasks::sample::sample(ctx).await {
|
|
|
|
Ok(_) => {},
|
|
|
|
Err(y) => {
|
|
|
|
eprintln!("TaskScheduler[Main:Sample:Error]: Task execution failed: {}", y);
|
|
|
|
if let Some(source) = y.source() {
|
|
|
|
eprintln!("TaskScheduler[Main:Sample:Error]: Task execution failed caused by: {:#?}", source);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TASK_RUNNING.store(false, Ordering::SeqCst);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
println!("TaskScheduler[Main:Notice]: Another thread is already running, ignoring");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-12-04 16:35:42 +11:00
|
|
|
#[tokio::main]
|
|
|
|
async fn main() {
|
2024-08-09 18:19:59 -04:00
|
|
|
DatabaseController::new().await.expect("Error initializing database");
|
2023-12-04 16:35:42 +11:00
|
|
|
|
2024-01-12 13:59:46 +11:00
|
|
|
let framework = poise::Framework::builder()
|
2023-12-04 16:35:42 +11:00
|
|
|
.options(poise::FrameworkOptions {
|
|
|
|
commands: vec![
|
2023-12-05 14:18:30 +11:00
|
|
|
commands::ping::ping(),
|
2024-08-09 18:19:59 -04:00
|
|
|
commands::sample::sample(),
|
|
|
|
commands::midi::midi_to_wav(),
|
|
|
|
commands::uptime::uptime()
|
2023-12-04 16:35:42 +11:00
|
|
|
],
|
2023-12-08 12:34:57 +11:00
|
|
|
pre_command: |ctx| Box::pin(async move {
|
2023-12-10 21:03:52 +11:00
|
|
|
let get_guild_name = match ctx.guild() {
|
|
|
|
Some(guild) => guild.name.clone(),
|
2024-08-09 18:19:59 -04:00
|
|
|
None => String::from("Direct Message")
|
2023-12-10 21:03:52 +11:00
|
|
|
};
|
2024-08-09 18:19:59 -04:00
|
|
|
println!("Discord[{}]: {} ran /{}", get_guild_name, ctx.author().name, ctx.command().qualified_name);
|
2023-12-10 21:03:52 +11:00
|
|
|
}),
|
2024-03-11 10:06:40 +11:00
|
|
|
on_error: |error| Box::pin(async move {
|
|
|
|
match error {
|
|
|
|
poise::FrameworkError::Command { error, ctx, .. } => {
|
|
|
|
println!("PoiseCommandError({}): {}", ctx.command().qualified_name, error);
|
2024-08-09 18:19:59 -04:00
|
|
|
ctx.reply(format!(
|
|
|
|
"Encountered an error during command execution, ask {} to check console for more details!",
|
|
|
|
mention_dev(ctx).unwrap_or_default()
|
|
|
|
)).await.expect("Error sending message");
|
|
|
|
},
|
|
|
|
poise::FrameworkError::EventHandler { error, event, .. } => println!("PoiseEventHandlerError({}): {}", event.snake_case_name(), error),
|
|
|
|
poise::FrameworkError::Setup { error, .. } => println!("PoiseSetupError: {}", error),
|
|
|
|
poise::FrameworkError::UnknownInteraction { interaction, .. } => println!(
|
|
|
|
"PoiseUnknownInteractionError: {} tried to execute an unknown interaction ({})",
|
|
|
|
interaction.user.name,
|
|
|
|
interaction.data.name
|
|
|
|
),
|
|
|
|
other => println!("PoiseOtherError: {}", other)
|
2024-03-11 10:06:40 +11:00
|
|
|
}
|
|
|
|
}),
|
|
|
|
initialize_owners: true,
|
2024-08-09 18:19:59 -04:00
|
|
|
event_handler: |ctx, event, framework, _| Box::pin(event_processor(ctx, event, framework)),
|
2023-12-04 16:35:42 +11:00
|
|
|
..Default::default()
|
2023-12-10 21:03:52 +11:00
|
|
|
})
|
|
|
|
.setup(|ctx, ready, framework| Box::pin(on_ready(ctx, ready, framework)))
|
2024-01-12 13:59:46 +11:00
|
|
|
.build();
|
|
|
|
|
2024-08-09 18:19:59 -04:00
|
|
|
let mut client = ClientBuilder::new(
|
|
|
|
token_path().await.main,
|
|
|
|
GatewayIntents::GUILDS
|
|
|
|
| GatewayIntents::MESSAGE_CONTENT
|
|
|
|
| GatewayIntents::DIRECT_MESSAGES
|
|
|
|
)
|
|
|
|
.framework(framework)
|
|
|
|
.await.expect("Error creating client");
|
2023-12-04 16:35:42 +11:00
|
|
|
|
|
|
|
if let Err(why) = client.start().await {
|
2024-08-09 18:19:59 -04:00
|
|
|
println!("Error starting client: {:#?}", why);
|
2023-12-04 16:35:42 +11:00
|
|
|
}
|
|
|
|
}
|