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' rolelegacy
parent
fee137f947
commit
f8ab672453
|
@ -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"),
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize, Clone, PartialEq)]
|
||||
pub enum ChannelReference {
|
||||
Discord(u64),
|
||||
Matrix(String),
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue