use log::info; use serenity::{async_trait, model::prelude::*, prelude::*}; use tokio::sync::mpsc; use crate::{ message_ast::{self, format_discord}, messages::{MessageAuthor, MessageEvent, MessageReference, SentMessage}, }; pub use serenity::client::Context; pub use serenity::model::id::ChannelId; impl From<&Message> for MessageReference { fn from(message: &Message) -> Self { Self::Discord(message.channel_id.0, message.id.0) } } struct DiscordHandler { ctx_tx: mpsc::UnboundedSender, message_tx: mpsc::UnboundedSender, } #[async_trait] impl EventHandler for DiscordHandler { async fn ready(&self, ctx: Context, _ready: Ready) { let _ = self.ctx_tx.send(ctx); info!("Discord ready!"); // TODO: Scan for channels to link } async fn message(&self, ctx: Context, message: Message) { if message.author.id == ctx.cache.current_user_id().await { return; } let message_ref = MessageReference::from(&message); let content = discord_message_format::parse(&message.content); let content = message_ast::convert_discord(&content); let _ = self.message_tx.send(MessageEvent::Send(SentMessage { source: message_ref, content, author: MessageAuthor { display_name: message .author_nick(&ctx.http) .await .unwrap_or(message.author.name), }, })); } } pub async fn forward_to_discord( discord_ctx: &Context, channel: ChannelId, message: &SentMessage, ) -> Option { channel .send_message(&discord_ctx.http, |m| { m.content(format_discord(&message.content)) }) .await .as_ref() .ok() .map(MessageReference::from) } pub async fn create_discord_client( ctx_tx: mpsc::UnboundedSender, message_tx: mpsc::UnboundedSender, token: &str, ) -> Client { let handler = DiscordHandler { ctx_tx, message_tx }; info!("Discord logging in…"); let client = Client::builder(token) .event_handler(handler) .await .expect("Failed to create discord client"); info!("Discord starting…"); client }