phoebe/src/discord.rs

125 lines
3.4 KiB
Rust
Raw Normal View History

2021-09-12 02:59:13 +00:00
use log::info;
2021-08-12 09:47:38 +00:00
use serenity::{async_trait, model::prelude::*, prelude::*};
2021-09-10 04:44:00 +00:00
use tokio::sync::mpsc;
2021-08-12 09:47:38 +00:00
2021-09-12 02:59:13 +00:00
use crate::{
channels::ChannelReference,
message_ast::{self, format_discord},
2021-09-13 02:08:35 +00:00
messages::{MessageAuthor, MessageEvent, MessageReference, SentMessage},
2021-09-12 02:59:13 +00:00
};
2021-09-10 04:44:00 +00:00
pub use serenity::client::Context;
pub use serenity::model::id::ChannelId;
2021-08-12 09:47:38 +00:00
impl From<&Message> for MessageReference {
fn from(message: &Message) -> Self {
Self::Discord(message.channel_id.0, message.id.0)
}
}
2021-09-10 04:44:00 +00:00
struct DiscordHandler {
ctx_tx: mpsc::UnboundedSender<Context>,
event_tx: mpsc::UnboundedSender<MessageEvent>,
2021-09-10 04:44:00 +00:00
}
2021-08-12 09:47:38 +00:00
#[async_trait]
2021-09-10 04:44:00 +00:00
impl EventHandler for DiscordHandler {
async fn ready(&self, ctx: Context, _ready: Ready) {
let _ = self.ctx_tx.send(ctx);
2021-09-12 02:59:13 +00:00
info!("Discord ready!");
2021-09-10 04:44:00 +00:00
// TODO: Scan for channels to link
2021-08-12 09:47:38 +00:00
}
2021-09-12 02:59:13 +00:00
async fn message(&self, ctx: Context, message: Message) {
if message.author.id == ctx.cache.current_user_id().await {
return;
}
if let Some(target) = message.content.strip_prefix("phoebe!link ") {
if message
.member(&ctx)
.await
.unwrap()
.roles(&ctx)
.await
.unwrap()
.iter()
.any(|r| r.name == "Phoebe")
{
let _ = self.event_tx.send(MessageEvent::AdminLinkChannels(vec![
ChannelReference::Discord(message.channel_id.0),
ChannelReference::Matrix(target.to_string()),
]));
message.reply(&ctx, "Linking with matrix.").await.unwrap();
return;
}
}
2021-09-10 04:44:00 +00:00
let message_ref = MessageReference::from(&message);
2021-08-12 09:47:38 +00:00
let content = discord_message_format::parse(&message.content);
2021-09-10 04:44:00 +00:00
let content = message_ast::convert_discord(&content);
2021-08-12 09:47:38 +00:00
2021-09-13 19:41:55 +00:00
let replies_to = message
.referenced_message
.as_ref()
.map(|m| MessageReference::from(m.as_ref()));
let _ = self.event_tx.send(MessageEvent::Send(SentMessage {
2021-09-10 04:44:00 +00:00
source: message_ref,
content,
2021-09-12 02:59:13 +00:00
author: MessageAuthor {
display_name: message
.author_nick(&ctx.http)
.await
.unwrap_or(message.author.name),
},
2021-09-13 19:41:55 +00:00
replies_to,
2021-09-13 02:08:35 +00:00
}));
2021-08-12 09:47:38 +00:00
}
}
2021-09-10 04:44:00 +00:00
pub async fn forward_to_discord(
discord_ctx: &Context,
channel: ChannelId,
message: &SentMessage,
2021-09-13 19:41:55 +00:00
reply: Option<(u64, u64)>,
) -> Option<MessageReference> {
channel
.send_message(&discord_ctx.http, |m| {
2021-09-13 19:41:55 +00:00
let b = m.content(format_discord(&message.content));
if let Some((channel_id, message_id)) = reply {
b.reference_message((ChannelId(channel_id), MessageId(message_id)))
} else {
b
}
})
.await
.as_ref()
.ok()
.map(MessageReference::from)
}
2021-09-10 04:44:00 +00:00
pub async fn create_discord_client(
ctx_tx: mpsc::UnboundedSender<Context>,
2021-09-13 02:08:35 +00:00
message_tx: mpsc::UnboundedSender<MessageEvent>,
2021-09-10 04:44:00 +00:00
token: &str,
) -> Client {
let handler = DiscordHandler {
ctx_tx,
event_tx: message_tx,
};
2021-09-10 04:44:00 +00:00
2021-09-12 02:59:13 +00:00
info!("Discord logging in…");
let client = Client::builder(token)
2021-09-10 04:44:00 +00:00
.event_handler(handler)
.await
2021-09-12 02:59:13 +00:00
.expect("Failed to create discord client");
info!("Discord starting…");
client
2021-09-10 04:44:00 +00:00
}