summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs285
1 files changed, 84 insertions, 201 deletions
diff --git a/src/main.rs b/src/main.rs
index 51f0f3c..d4914e9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,232 +1,115 @@
-use once_cell::sync::Lazy;
-use serenity::async_trait;
-use serenity::framework::standard::macros::{command, group};
-use serenity::framework::standard::{CommandResult, StandardFramework};
-use serenity::model::application::command::Command;
-use serenity::model::prelude::*;
-use serenity::prelude::*;
-use utils::parse_snowflake_from_env;
+use std::time::Duration;
+use std::{env, error};
+use crate::commands::*;
+use crate::consts::*;
use crate::pinboard::PinBoard;
-use crate::utils::parse_snowflakes_from_env;
+use log::*;
+use poise::serenity_prelude as serentiy;
+use poise::serenity_prelude::*;
mod api;
mod commands;
mod consts;
+mod handler;
mod pinboard;
mod utils;
-const TEAWIE_GUILD: GuildId = GuildId(1055663552679137310);
-const BOT: UserId = UserId(1056467120986271764);
+type Error = Box<dyn error::Error + Send + Sync>;
+type Context<'a> = poise::Context<'a, Data, Error>;
-fn is_guild_allowed(gid: GuildId) -> bool {
- // Had to be global state because Serenity doesn't allow you to store
- // extra state in frameworks
- static ALLOWED_GUILDS: Lazy<Vec<GuildId>> = Lazy::new(|| {
- parse_snowflakes_from_env("ALLOWED_GUILDS", GuildId)
- .unwrap_or_else(|| vec![TEAWIE_GUILD, GuildId(1091969030694375444)])
- });
-
- ALLOWED_GUILDS.contains(&gid)
+#[derive(Clone)]
+pub struct Data {
+ bot: serentiy::UserId,
+ pin_board: Option<PinBoard>,
}
-#[group]
-#[commands(bing, ask, random_lore, random_teawie, teawiespam)]
-struct General;
-
-struct Handler {
- bot: UserId,
- pin_board: Option<PinBoard>,
+impl Default for Data {
+ fn default() -> Self {
+ Self::new()
+ }
}
-impl Handler {
+impl Data {
pub fn new() -> Self {
- let bot = parse_snowflake_from_env("BOT", UserId).unwrap_or(BOT);
+ let bot = utils::parse_snowflake_from_env("BOT", UserId).unwrap_or(consts::BOT);
let pin_board = PinBoard::new();
Self { bot, pin_board }
}
- fn should_echo(&self, msg: &Message) -> bool {
- // Don't echo to anything we posted ourselves, and don't echo at all unless on certain
- // servers
- if msg.author.id == self.bot || !is_guild_allowed(msg.guild_id.unwrap_or_default()) {
- return false;
- }
-
- let content = &msg.content;
-
- content == "🗿"
- || consts::TEAMOJIS.contains(&content.as_str())
- || content.to_ascii_lowercase() == "moyai"
- || content
- .to_ascii_lowercase()
- .contains("twitter's recommendation algorithm")
- }
}
-#[async_trait]
-impl EventHandler for Handler {
- /*
- * echo some messages when they're sent
- */
- async fn message(&self, ctx: Context, msg: Message) {
- if self.should_echo(&msg) {
- let send = msg.reply(&ctx, &msg.content);
- if let Err(why) = send.await {
- println!("error when replying to {:?}: {:?}", msg.content, why);
- }
+async fn on_error(error: poise::FrameworkError<'_, Data, Error>) {
+ match error {
+ poise::FrameworkError::Setup { error, .. } => panic!("failed to start bot: {error:?}"),
+ poise::FrameworkError::Command { error, ctx } => {
+ error!("error in command {}: {:?}", ctx.command().name, error);
}
- }
-
- async fn channel_pins_update(&self, ctx: Context, pin: ChannelPinsUpdateEvent) {
- let Some(pin_board) = &self.pin_board else {
- return;
- };
-
- println!(
- "audit log: {:#?}",
- pin.guild_id
- .unwrap()
- .audit_logs(
- &ctx.http,
- Some(Action::Message(MessageAction::Pin).num()),
- None,
- None,
- Some(1),
- )
- .await
- );
- pin_board.handle_pin(&ctx, &pin).await;
- }
-
- async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
- if let Interaction::ApplicationCommand(command) = interaction {
- println!("Received command interaction: {command:#?}");
- let content = match command.data.name.as_str() {
- "ask" => commands::ask::run(&command.data.options),
- "bottom" => commands::bottom::run(&command.data.options),
- "convertto" => commands::convert::run(&command.data.options),
- "copypasta" => {
- commands::copypasta::run(&command.data.options, command.channel_id, &ctx.http)
- .await
- }
- "random_lore" => commands::random_lore::run(&command.data.options),
- "random_shiggy" => commands::random_shiggy::run(&command.data.options).await,
- "random_teawie" => commands::random_teawie::run(&command.data.options).await,
- _ => "not implemented :(".to_string(),
- };
-
- if let Err(why) = command
- .create_interaction_response(&ctx.http, |response| {
- response
- .kind(InteractionResponseType::ChannelMessageWithSource)
- .interaction_response_data(|message| message.content(content))
- })
- .await
- {
- println!("cannot respond to slash command: {why}");
+ error => {
+ if let Err(e) = poise::builtins::on_error(error).await {
+ error!("error while handling an error: {}", e);
}
}
}
-
- async fn ready(&self, ctx: Context, ready: Ready) {
- println!("connected as {:?}", ready.user.name);
-
- let guild_commands =
- GuildId::set_application_commands(&TEAWIE_GUILD, &ctx.http, |commands| {
- commands.create_application_command(commands::copypasta::register)
- })
- .await;
-
- println!("registered guild commands: {guild_commands:#?}");
-
- let commands = Command::set_global_application_commands(&ctx.http, |commands| {
- commands
- .create_application_command(commands::ask::register)
- .create_application_command(commands::bottom::register)
- .create_application_command(commands::convert::register)
- .create_application_command(commands::random_lore::register)
- .create_application_command(commands::random_shiggy::register)
- .create_application_command(commands::random_teawie::register)
- })
- .await;
-
- println!("registered global commands: {commands:#?}");
- }
}
#[tokio::main]
async fn main() {
- let framework = StandardFramework::new()
- .configure(|c| c.prefix("!"))
- .group(&GENERAL_GROUP);
-
- let token = std::env::var("TOKEN").expect("couldn't find token in environment.");
-
- let intents = GatewayIntents::all();
- let handler = Handler::new();
-
- let mut client = Client::builder(token, intents)
- .event_handler(handler)
- .framework(framework)
- .await
- .expect("error creating client");
-
- if let Err(why) = client.start().await {
- println!("an error occurred: {:?}", why);
- }
-}
-
-#[command]
-async fn bing(ctx: &Context, msg: &Message) -> CommandResult {
- msg.channel_id
- .send_message(&ctx.http, |m| m.content("bong"))
- .await?;
-
- Ok(())
-}
-
-#[command]
-async fn ask(ctx: &Context, msg: &Message) -> CommandResult {
- let resp = utils::get_random_response();
- msg.channel_id
- .send_message(&ctx.http, |m| m.content(resp))
- .await?;
-
- Ok(())
-}
-
-#[command]
-async fn random_lore(ctx: &Context, msg: &Message) -> CommandResult {
- let resp = utils::get_random_lore();
- msg.channel_id
- .send_message(&ctx.http, |m| m.content(resp))
- .await?;
-
- Ok(())
-}
-
-#[command]
-async fn random_teawie(ctx: &Context, msg: &Message) -> CommandResult {
- let resp = api::guzzle::get_random_teawie().await;
- msg.channel_id
- .send_message(&ctx.http, |m| m.content(resp))
- .await?;
-
- Ok(())
-}
-
-#[command]
-async fn teawiespam(ctx: &Context, msg: &Message) -> CommandResult {
- if !is_guild_allowed(msg.guild_id.unwrap_or_default()) {
- return Ok(());
- }
-
- let resp = "<:teawiesmile:1056438046440042546>".repeat(50);
-
- msg.channel_id
- .send_message(&ctx.http, |m| m.content(resp))
- .await?;
+ env_logger::init();
+ dotenvy::dotenv().unwrap();
+
+ let guild_commands = vec![copypasta::copypasta(), teawiespam::teawiespam()];
+
+ let options = poise::FrameworkOptions {
+ commands: vec![
+ ask::ask(),
+ bing::bing(),
+ bottom::bottom(),
+ convert::convert(),
+ random_lore::random_lore(),
+ random_shiggy::random_shiggy(),
+ random_teawie::random_teawie(),
+ copypasta::copypasta(),
+ teawiespam::teawiespam(),
+ ],
+ event_handler: |ctx, event, _, data| {
+ Box::pin(async move {
+ // yes this is dumb. no i don't care.
+ let handler = handler::Handler::new(data.clone());
+ event.clone().dispatch(ctx.clone(), &handler).await;
+ Ok(())
+ })
+ },
+ prefix_options: poise::PrefixFrameworkOptions {
+ prefix: Some("!".into()),
+ edit_tracker: Some(poise::EditTracker::for_timespan(Duration::from_secs(3600))),
+ ..Default::default()
+ },
+ on_error: |error| Box::pin(on_error(error)),
+ command_check: Some(|ctx| {
+ Box::pin(async move {
+ Ok(ctx.author().id != ctx.framework().bot_id && ctx.author().id != consts::BOT)
+ })
+ }),
+ ..Default::default()
+ };
+
+ let framework = poise::Framework::builder()
+ .options(options)
+ .token(env::var("TOKEN").expect("couldn't find token in environment."))
+ .intents(serentiy::GatewayIntents::all())
+ .setup(|ctx, _ready, framework| {
+ Box::pin(async move {
+ info!("logged in as {}", _ready.user.name);
+
+ poise::builtins::register_globally(ctx, &framework.options().commands).await?;
+ info!("registered global commands!");
+ poise::builtins::register_in_guild(ctx, &guild_commands, TEAWIE_GUILD).await?;
+ info!("registered guild commands!");
+
+ Ok(Data::new())
+ })
+ });
- Ok(())
+ framework.run().await.unwrap()
}