use phoebe::{ mid_chat::{self, ChatMessage, ChatMessageReference, ChatReference}, prelude::*, DynServiceLookup, }; use serenity::{client::Context, Client}; use tracing::{debug, info}; mod chat_conv; mod handler; mod lookup; mod sender; pub fn discord_reference(id: impl ToString) -> mid_chat::ChatReference { mid_chat::ChatReference { service: "discord", id: id.to_string(), } } pub struct DiscordService { pub core_db: SqlitePool, pub discord_media_db: SqlitePool, pub ctx: Context, pub dyn_service: DynServiceLookup, } pub async fn setup( core_db: SqlitePool, tx: ChatEventSender, dyn_service: DynServiceLookup, ) -> Result { info!("Setting up Discord service…"); let discord_media_db = phoebe::db::open("discord_media").await?; sqlx::migrate!().run(&discord_media_db).await?; let (ctx_tx, mut ctx_rx) = tokio::sync::mpsc::unbounded_channel::(); let discord_handler = handler::DiscordHandler { core_db: core_db.clone(), discord_media_db: discord_media_db.clone(), chat_event_tx: tx, ctx_tx, }; debug!("Logging in…"); let discord_token = std::env::var("PHOEBE_DISCORD_TOKEN") .expect("PHOEBE_DISCORD_TOKEN environment variable was not set!"); let mut client = Client::builder(&discord_token) .event_handler(discord_handler) .await?; tokio::spawn(async move { client .start() .await .expect("Failed to start Discord client") }); let discord_ctx = ctx_rx.recv().await.expect("Couldn't get Discord context"); debug!("Logged in!"); Ok(DiscordService { core_db, discord_media_db, ctx: discord_ctx, dyn_service, }) } #[async_trait] impl Service for DiscordService { fn tag(&self) -> &'static str { "discord" } async fn send_chat_message( &mut self, source: &ChatMessage, destination_channel: ChatReference, ) -> Vec { assert_eq!(destination_channel.service, "discord"); sender::send_discord_message(self, source, destination_channel) .await .ok() .into_iter() .collect() } async fn delete_message(&mut self, message: &ChatMessageReference) -> bool { assert_eq!(message.channel.service, "discord"); sender::delete_discord_message(self, message).await.is_ok() } }