Look up linked channels in the database

We also have a Discord convenience command that lets you link to a
Matrix room as long as you have a 'Phoebe' role
legacy
Charlotte Som 2021-09-13 04:20:49 +01:00
parent fee137f947
commit f8ab672453
5 changed files with 114 additions and 16 deletions

View File

@ -3,6 +3,7 @@ use std::{cell::RefCell, str::FromStr, sync::Mutex};
use sled::Db;
use crate::{
channels::ChannelReference,
discord::{self, forward_to_discord},
matrix::{self, forward_to_matrix},
messages::{MessageReference, SentMessage},
@ -26,25 +27,85 @@ impl Bridgers {
}
fn get_linked_discord_channel(&self, source: &MessageReference) -> Option<discord::ChannelId> {
let discord_channels = self
.db
.open_tree("discord_channels")
.expect("Failed to open discord channels tree");
match source {
MessageReference::Matrix(_room_id, _event_id) => {
// TODO: Look up the linked channel
Some(discord::ChannelId(885690775193661463))
MessageReference::Matrix(room_id, _) => {
let channel_ref = ChannelReference::Matrix(room_id.to_string());
let channel_ref = bincode::serialize(&channel_ref).unwrap();
discord_channels
.get(channel_ref)
.unwrap()
.map(|bytes| bincode::deserialize::<u64>(&bytes).unwrap())
.map(discord::ChannelId)
}
_ => None,
}
}
fn get_linked_matrix_room(&self, source: &MessageReference) -> Option<matrix::RoomId> {
let matrix_channels = self
.db
.open_tree("matrix_channels")
.expect("Failed to open matrix channels tree");
match source {
MessageReference::Discord(_, _) => {
// TODO: Look up the linked channel
Some(matrix::RoomId::from_str("!SjQatGOikRshcWNcln:matrix.org").unwrap())
MessageReference::Discord(channel_id, _) => {
let channel_ref = ChannelReference::Discord(*channel_id);
let channel_ref = bincode::serialize(&channel_ref).unwrap();
matrix_channels
.get(channel_ref)
.unwrap()
.map(|bytes| bincode::deserialize::<String>(&bytes).unwrap())
.as_deref()
.map(matrix::RoomId::from_str)
.map(Result::unwrap)
}
_ => None,
}
}
pub fn link_channels(&self, channels: &[ChannelReference]) {
let discord_channels = self
.db
.open_tree("discord_channels")
.expect("Failed to open discord channels tree");
let matrix_channels = self
.db
.open_tree("matrix_channels")
.expect("Failed to open matrix channels tree");
for channel in channels.iter() {
let other_channels = channels
.iter()
.filter(|r| r != &channel)
.collect::<Vec<_>>();
match channel {
ChannelReference::Discord(channel_id) => {
for other_channel in other_channels {
let key = bincode::serialize(other_channel).unwrap();
let value = bincode::serialize(channel_id).unwrap();
discord_channels.insert(key, value).unwrap();
}
}
ChannelReference::Matrix(room_id) => {
for other_channel in other_channels {
let key = bincode::serialize(other_channel).unwrap();
let value = bincode::serialize(room_id.as_str()).unwrap();
matrix_channels.insert(key, value).unwrap();
}
}
}
}
}
pub async fn send_message(&self, message: SentMessage) -> Vec<MessageReference> {
let mut related_messages = vec![message.source.clone()];
@ -64,17 +125,17 @@ impl Bridgers {
}
}
let tree = self
.db
.open_tree("message_relations")
.expect("Failed to open relations tree");
for source in related_messages.iter() {
let relations = related_messages
.iter()
.filter(|r| r != &source)
.collect::<Vec<_>>();
let tree = self
.db
.open_tree("message_relations")
.expect("Failed to open relations tree");
tree.insert(
bincode::serialize(source).expect("Failed to serialize message reference"),
bincode::serialize(&relations).expect("Failed to serialize message relations"),

7
src/channels.rs Normal file
View File

@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Clone, PartialEq)]
pub enum ChannelReference {
Discord(u64),
Matrix(String),
}

View File

@ -3,6 +3,7 @@ use serenity::{async_trait, model::prelude::*, prelude::*};
use tokio::sync::mpsc;
use crate::{
channels::ChannelReference,
message_ast::{self, format_discord},
messages::{MessageAuthor, MessageEvent, MessageReference, SentMessage},
};
@ -18,7 +19,7 @@ impl From<&Message> for MessageReference {
struct DiscordHandler {
ctx_tx: mpsc::UnboundedSender<Context>,
message_tx: mpsc::UnboundedSender<MessageEvent>,
event_tx: mpsc::UnboundedSender<MessageEvent>,
}
#[async_trait]
@ -35,12 +36,33 @@ impl EventHandler for DiscordHandler {
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;
}
}
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 {
let _ = self.event_tx.send(MessageEvent::Send(SentMessage {
source: message_ref,
content,
author: MessageAuthor {
@ -73,7 +95,10 @@ pub async fn create_discord_client(
message_tx: mpsc::UnboundedSender<MessageEvent>,
token: &str,
) -> Client {
let handler = DiscordHandler { ctx_tx, message_tx };
let handler = DiscordHandler {
ctx_tx,
event_tx: message_tx,
};
info!("Discord logging in…");
let client = Client::builder(token)

View File

@ -4,6 +4,7 @@ use discord::create_discord_client;
use matrix::create_matrix_client;
mod bridgers;
mod channels;
mod message_ast;
mod messages;
@ -89,9 +90,12 @@ async fn main() {
MessageEvent::Send(sent_message) => {
let _ = bridgers.send_message(sent_message).await;
}
MessageEvent::Edit(edited_message) => {
MessageEvent::Edit(_edited_message) => {
todo!();
}
MessageEvent::AdminLinkChannels(channels) => {
bridgers.link_channels(&channels);
}
}
}
}

View File

@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};
use crate::message_ast::MessageContent;
use crate::{channels::ChannelReference, message_ast::MessageContent};
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
pub enum MessageReference {
@ -25,6 +25,7 @@ pub struct EditedMessage {
}
pub enum MessageEvent {
AdminLinkChannels(Vec<ChannelReference>),
Send(SentMessage),
Edit(EditedMessage),
}