phoebe/services/phoebe-discord/src/lib.rs

97 lines
2.5 KiB
Rust

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<DiscordService> {
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::<Context>();
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<ChatMessageReference> {
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()
}
}