char/phoebe

git clone https://git.t4t.associates/char/phoebe

videogame hackerAdd message editing support & impl for Discord4fc8c15

main
2.8 KiB106 linesraw
1use phoebe::{
2    mid_chat::{self, ChatMessage, ChatMessageEdit, ChatMessageReference, ChatReference},
3    prelude::*,
4    DynServiceLookup,
5};
6use serenity::{client::Context, Client};
7use tracing::{debug, info};
8
9mod chat_conv;
10mod handler;
11mod lookup;
12mod sender;
13
14pub fn discord_reference(id: impl ToString) -> mid_chat::ChatReference {
15    mid_chat::ChatReference {
16        service: "discord",
17        id: id.to_string(),
18    }
19}
20
21pub struct DiscordService {
22    pub core_db: SqlitePool,
23    pub discord_media_db: SqlitePool,
24    pub ctx: Context,
25    pub dyn_service: DynServiceLookup,
26}
27
28pub async fn setup(
29    core_db: SqlitePool,
30    tx: ChatEventSender,
31    dyn_service: DynServiceLookup,
32) -> Result<DiscordService> {
33    info!("Setting up Discord service…");
34
35    let discord_media_db = phoebe::db::open("discord_media").await?;
36    sqlx::migrate!().run(&discord_media_db).await?;
37
38    let (ctx_tx, mut ctx_rx) = tokio::sync::mpsc::unbounded_channel::<Context>();
39
40    let discord_handler = handler::DiscordHandler {
41        core_db: core_db.clone(),
42        discord_media_db: discord_media_db.clone(),
43        chat_event_tx: tx,
44        ctx_tx,
45    };
46
47    debug!("Logging in…");
48    let discord_token = std::env::var("PHOEBE_DISCORD_TOKEN")
49        .expect("PHOEBE_DISCORD_TOKEN environment variable was not set!");
50
51    let mut client = Client::builder(&discord_token)
52        .event_handler(discord_handler)
53        .await?;
54
55    tokio::spawn(async move {
56        client
57            .start()
58            .await
59            .expect("Failed to start Discord client")
60    });
61
62    let discord_ctx = ctx_rx.recv().await.expect("Couldn't get Discord context");
63    debug!("Logged in!");
64
65    Ok(DiscordService {
66        core_db,
67        discord_media_db,
68        ctx: discord_ctx,
69        dyn_service,
70    })
71}
72
73#[async_trait]
74impl Service for DiscordService {
75    fn tag(&self) -> &'static str {
76        "discord"
77    }
78
79    async fn send_chat_message(
80        &mut self,
81        source: &ChatMessage,
82        destination_channel: ChatReference,
83    ) -> Vec<ChatMessageReference> {
84        assert_eq!(destination_channel.service, "discord");
85        sender::send_discord_message(self, source, destination_channel)
86            .await
87            .ok()
88            .into_iter()
89            .collect()
90    }
91
92    async fn delete_message(&mut self, message: &ChatMessageReference) -> bool {
93        assert_eq!(message.channel.service, "discord");
94        sender::delete_discord_message(self, message).await.is_ok()
95    }
96
97    async fn edit_message(
98        &mut self,
99        prev_origin: &ChatMessageReference,
100        new_message: &ChatMessageEdit,
101    ) -> Vec<ChatMessageReference> {
102        assert_eq!(prev_origin.channel.service, "discord");
103        let _ = sender::edit_discord_message(self, prev_origin, new_message).await;
104        vec![]
105    }
106}