mod horse; mod joke; mod llama; mod react; mod starboard; mod sus; mod xbasic; use crate::config::LlamaConfig; use crate::handlers::horse::HorseHandler; use crate::handlers::joke::*; use crate::handlers::react::*; use crate::handlers::starboard::StarboardHandler; use crate::handlers::sus::*; use crate::handlers::xbasic::*; use diesel::{Connection, PgConnection}; use dotenv::dotenv; use serenity::async_trait; use serenity::model::channel::Message; use serenity::model::prelude::{Reaction, Ready}; use serenity::prelude::*; use std::env; use std::sync::Arc; use tokio::sync::Mutex; use self::llama::LlamaHandler; #[async_trait] pub(crate) trait LineHandler: Send + Sync { async fn message(&self, ctx: &Context, msg: &Message) { for line in msg.content.split('\n') { self.line(ctx, msg, line).await } } async fn line(&self, _ctx: &Context, _msg: &Message, _line: &str) {} } #[async_trait] pub(crate) trait ReactionHandler: Send + Sync { async fn reaction_add(&self, ctx: &Context, reaction: &Reaction); async fn reaction_del(&self, ctx: &Context, reaction: &Reaction); } pub(crate) struct Dispatcher { handlers: Vec<Box<dyn LineHandler>>, reacts: Vec<Box<dyn ReactionHandler>>, } #[async_trait] impl EventHandler for Dispatcher { async fn message(&self, ctx: Context, msg: Message) { for h in &self.handlers { h.message(&ctx, &msg).await; } } async fn reaction_add(&self, ctx: Context, reaction: Reaction) { for r in &self.reacts { r.reaction_add(&ctx, &reaction).await; } } async fn reaction_remove(&self, ctx: Context, reaction: Reaction) { for r in &self.reacts { r.reaction_del(&ctx, &reaction).await; } } async fn ready(&self, _: Context, ready: Ready) { println!("{} is connected", ready.user.name); } } impl Dispatcher { pub fn new(llama_config: Option<LlamaConfig>) -> Self { let conn = Arc::new(Mutex::new(establish_connection())); let mut handlers: Vec<Box<dyn LineHandler>> = vec![ Box::new(XbasicHandler::new(conn.clone())), Box::<JokeHandler>::default(), Box::<ReactHandler>::default(), Box::<SusHandler>::default(), Box::<HorseHandler>::default(), ]; if let Some(lc) = llama_config { handlers.push(Box::new(LlamaHandler::new(lc))); } Self { handlers, reacts: vec![Box::new(StarboardHandler::new(conn))], } } } fn establish_connection() -> PgConnection { dotenv().ok(); let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); PgConnection::establish(&database_url).expect("Error connecting to database") }