sillybot init
This commit is contained in:
commit
6e1e91936f
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
.env
|
3188
Cargo.lock
generated
Normal file
3188
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "sillycord-bot"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
dotenv = "0.15.0"
|
||||
poise = "0.6.1"
|
||||
serenity = "0.12.4"
|
||||
sqlx = { version = "0.8", features = [ "runtime-tokio", "tls-rustls-ring", "mysql" ] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tracing = "0.1.40"
|
||||
tracing-subscriber = "0.3.18"
|
||||
serde = { version = "1.0.215", features = ["derive"] }
|
1
src/commands/mod.rs
Normal file
1
src/commands/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod ping;
|
16
src/commands/ping.rs
Normal file
16
src/commands/ping.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use crate::{Context, Error};
|
||||
|
||||
#[poise::command(slash_command)]
|
||||
pub async fn ping(ctx: Context<'_>) -> Result<(), Error> {
|
||||
let start = std::time::Instant::now();
|
||||
let msg = ctx.say("Pong?").await?;
|
||||
|
||||
let latency = start.elapsed();
|
||||
msg.edit(
|
||||
ctx,
|
||||
poise::CreateReply::default().content(format!("Pong! Latency: {:?}", latency)),
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
29
src/events.rs
Normal file
29
src/events.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use crate::{Data, Error};
|
||||
use poise::serenity_prelude::{self as serenity, ActivityData, Interaction, OnlineStatus};
|
||||
use tracing::{info, warn};
|
||||
|
||||
// Create a span for every event
|
||||
#[tracing::instrument(skip(ctx, event, framework, data))]
|
||||
pub async fn event_handler(
|
||||
ctx: &serenity::Context,
|
||||
event: &serenity::FullEvent,
|
||||
framework: poise::FrameworkContext<'_, Data, Error>,
|
||||
data: &Data,
|
||||
) -> Result<(), Error> {
|
||||
match event {
|
||||
serenity::FullEvent::Ready { .. } => {
|
||||
info!("Bot is ready");
|
||||
ctx.set_presence(
|
||||
Some(ActivityData::watching("sillycord")),
|
||||
OnlineStatus::Online,
|
||||
);
|
||||
}
|
||||
|
||||
serenity::FullEvent::ShardsReady { total_shards, .. } => {
|
||||
info!("All shards emitted Ready, using {} shards", total_shards);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
0
src/handlers/mod.rs
Normal file
0
src/handlers/mod.rs
Normal file
131
src/main.rs
Normal file
131
src/main.rs
Normal file
@ -0,0 +1,131 @@
|
||||
mod commands;
|
||||
mod events;
|
||||
|
||||
use events::event_handler;
|
||||
use serenity::all::{ClientBuilder, GatewayIntents};
|
||||
use sqlx::mysql::MySqlPoolOptions;
|
||||
use sqlx::MySqlPool;
|
||||
use tracing::{event, info, info_span, Level};
|
||||
|
||||
fn check_required_env_vars() {
|
||||
let env_span = info_span!("check_required_env_vars");
|
||||
|
||||
let required_vars = vec!["DATABASE_URL", "BOT_TOKEN"];
|
||||
// Enter into the span then check the required environment variables
|
||||
let _enter = env_span.enter();
|
||||
for var in required_vars {
|
||||
info!("checking {}", var);
|
||||
if std::env::var(var).is_err() {
|
||||
event!(
|
||||
Level::ERROR,
|
||||
"required environment variable {} is not set",
|
||||
var
|
||||
);
|
||||
panic!(
|
||||
"required environment variable {} is not set, cannot continue",
|
||||
var
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
info!("all required environment variables are set");
|
||||
|
||||
// Exit the span
|
||||
drop(_enter);
|
||||
}
|
||||
|
||||
static MIGRATOR: sqlx::migrate::Migrator = sqlx::migrate!("./migrations");
|
||||
|
||||
async fn init_sqlx() -> MySqlPool {
|
||||
let sqlx_span = info_span!("init_sqlx");
|
||||
|
||||
// Enter into the span then initialize SQLx
|
||||
let _enter = sqlx_span.enter();
|
||||
|
||||
// Create a pooled connection to the database
|
||||
info!("creating a database connection pool");
|
||||
let pool = MySqlPoolOptions::new()
|
||||
.max_connections(5)
|
||||
.connect(&std::env::var("DATABASE_URL").unwrap())
|
||||
.await
|
||||
.expect("failed to create a database connection pool");
|
||||
|
||||
info!("database connection pool created");
|
||||
|
||||
// Ensure database schema is up to date
|
||||
info!("running database migrations");
|
||||
MIGRATOR
|
||||
.run(&pool)
|
||||
.await
|
||||
.expect("Migrations did not succeed");
|
||||
|
||||
info!("database migrations completed");
|
||||
info!("SQLx initialized");
|
||||
|
||||
// Exit the span
|
||||
drop(_enter);
|
||||
pool
|
||||
}
|
||||
|
||||
struct Data {
|
||||
sqlx_pool: MySqlPool,
|
||||
} // User data, which is stored and accessible in all command invocations
|
||||
type Error = Box<dyn std::error::Error + Send + Sync>;
|
||||
type Context<'a> = poise::Context<'a, Data, Error>;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let start_time = std::time::Instant::now();
|
||||
|
||||
tracing_subscriber::fmt::init();
|
||||
let init_span = info_span!("init");
|
||||
let main_span = info_span!("main");
|
||||
|
||||
let _enter = init_span.enter();
|
||||
info!("loading dotenv");
|
||||
dotenv::dotenv().ok();
|
||||
|
||||
info!("checking required environment variables");
|
||||
check_required_env_vars();
|
||||
|
||||
info!("initializing SQLx");
|
||||
let pool = init_sqlx().await;
|
||||
|
||||
info!("initializing bot");
|
||||
let intents = GatewayIntents::non_privileged();
|
||||
|
||||
let framework = poise::Framework::builder()
|
||||
.options(poise::FrameworkOptions::<Data, Error> {
|
||||
commands: vec![commands::ping::ping()],
|
||||
event_handler: |ctx, event, framework, data| {
|
||||
Box::pin(event_handler(ctx, event, framework, data))
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.setup(|ctx, _ready, framework| {
|
||||
Box::pin(async move {
|
||||
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
|
||||
Ok(Data {
|
||||
// Initialize user data here
|
||||
sqlx_pool: pool,
|
||||
})
|
||||
})
|
||||
})
|
||||
.build();
|
||||
|
||||
let mut client = ClientBuilder::new(std::env::var("BOT_TOKEN").unwrap(), intents)
|
||||
.framework(framework)
|
||||
.await
|
||||
.expect("Error creating client");
|
||||
|
||||
info!("bot initialized");
|
||||
drop(_enter);
|
||||
|
||||
let _enter = main_span.enter();
|
||||
|
||||
info!("init done in {:?}", start_time.elapsed());
|
||||
info!("starting bot");
|
||||
if let Err(why) = client.start().await {
|
||||
event!(Level::ERROR, "Client error: {:?}", why);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user