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 sled::Db;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
channels::ChannelReference,
|
||||||
discord::{self, forward_to_discord},
|
discord::{self, forward_to_discord},
|
||||||
matrix::{self, forward_to_matrix},
|
matrix::{self, forward_to_matrix},
|
||||||
messages::{MessageReference, SentMessage},
|
messages::{MessageReference, SentMessage},
|
||||||
|
@ -26,25 +27,85 @@ impl Bridgers {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_linked_discord_channel(&self, source: &MessageReference) -> Option<discord::ChannelId> {
|
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 {
|
match source {
|
||||||
MessageReference::Matrix(_room_id, _event_id) => {
|
MessageReference::Matrix(room_id, _) => {
|
||||||
// TODO: Look up the linked channel
|
let channel_ref = ChannelReference::Matrix(room_id.to_string());
|
||||||
Some(discord::ChannelId(885690775193661463))
|
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,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_linked_matrix_room(&self, source: &MessageReference) -> Option<matrix::RoomId> {
|
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 {
|
match source {
|
||||||
MessageReference::Discord(_, _) => {
|
MessageReference::Discord(channel_id, _) => {
|
||||||
// TODO: Look up the linked channel
|
let channel_ref = ChannelReference::Discord(*channel_id);
|
||||||
Some(matrix::RoomId::from_str("!SjQatGOikRshcWNcln:matrix.org").unwrap())
|
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,
|
_ => 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> {
|
pub async fn send_message(&self, message: SentMessage) -> Vec<MessageReference> {
|
||||||
let mut related_messages = vec![message.source.clone()];
|
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() {
|
for source in related_messages.iter() {
|
||||||
let relations = related_messages
|
let relations = related_messages
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|r| r != &source)
|
.filter(|r| r != &source)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let tree = self
|
|
||||||
.db
|
|
||||||
.open_tree("message_relations")
|
|
||||||
.expect("Failed to open relations tree");
|
|
||||||
|
|
||||||
tree.insert(
|
tree.insert(
|
||||||
bincode::serialize(source).expect("Failed to serialize message reference"),
|
bincode::serialize(source).expect("Failed to serialize message reference"),
|
||||||
bincode::serialize(&relations).expect("Failed to serialize message relations"),
|
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 tokio::sync::mpsc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
channels::ChannelReference,
|
||||||
message_ast::{self, format_discord},
|
message_ast::{self, format_discord},
|
||||||
messages::{MessageAuthor, MessageEvent, MessageReference, SentMessage},
|
messages::{MessageAuthor, MessageEvent, MessageReference, SentMessage},
|
||||||
};
|
};
|
||||||
|
@ -18,7 +19,7 @@ impl From<&Message> for MessageReference {
|
||||||
|
|
||||||
struct DiscordHandler {
|
struct DiscordHandler {
|
||||||
ctx_tx: mpsc::UnboundedSender<Context>,
|
ctx_tx: mpsc::UnboundedSender<Context>,
|
||||||
message_tx: mpsc::UnboundedSender<MessageEvent>,
|
event_tx: mpsc::UnboundedSender<MessageEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
@ -35,12 +36,33 @@ impl EventHandler for DiscordHandler {
|
||||||
return;
|
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 message_ref = MessageReference::from(&message);
|
||||||
|
|
||||||
let content = discord_message_format::parse(&message.content);
|
let content = discord_message_format::parse(&message.content);
|
||||||
let content = message_ast::convert_discord(&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,
|
source: message_ref,
|
||||||
content,
|
content,
|
||||||
author: MessageAuthor {
|
author: MessageAuthor {
|
||||||
|
@ -73,7 +95,10 @@ pub async fn create_discord_client(
|
||||||
message_tx: mpsc::UnboundedSender<MessageEvent>,
|
message_tx: mpsc::UnboundedSender<MessageEvent>,
|
||||||
token: &str,
|
token: &str,
|
||||||
) -> Client {
|
) -> Client {
|
||||||
let handler = DiscordHandler { ctx_tx, message_tx };
|
let handler = DiscordHandler {
|
||||||
|
ctx_tx,
|
||||||
|
event_tx: message_tx,
|
||||||
|
};
|
||||||
|
|
||||||
info!("Discord logging in…");
|
info!("Discord logging in…");
|
||||||
let client = Client::builder(token)
|
let client = Client::builder(token)
|
||||||
|
|
|
@ -4,6 +4,7 @@ use discord::create_discord_client;
|
||||||
use matrix::create_matrix_client;
|
use matrix::create_matrix_client;
|
||||||
|
|
||||||
mod bridgers;
|
mod bridgers;
|
||||||
|
mod channels;
|
||||||
mod message_ast;
|
mod message_ast;
|
||||||
mod messages;
|
mod messages;
|
||||||
|
|
||||||
|
@ -89,9 +90,12 @@ async fn main() {
|
||||||
MessageEvent::Send(sent_message) => {
|
MessageEvent::Send(sent_message) => {
|
||||||
let _ = bridgers.send_message(sent_message).await;
|
let _ = bridgers.send_message(sent_message).await;
|
||||||
}
|
}
|
||||||
MessageEvent::Edit(edited_message) => {
|
MessageEvent::Edit(_edited_message) => {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
MessageEvent::AdminLinkChannels(channels) => {
|
||||||
|
bridgers.link_channels(&channels);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::message_ast::MessageContent;
|
use crate::{channels::ChannelReference, message_ast::MessageContent};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
pub enum MessageReference {
|
pub enum MessageReference {
|
||||||
|
@ -25,6 +25,7 @@ pub struct EditedMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum MessageEvent {
|
pub enum MessageEvent {
|
||||||
|
AdminLinkChannels(Vec<ChannelReference>),
|
||||||
Send(SentMessage),
|
Send(SentMessage),
|
||||||
Edit(EditedMessage),
|
Edit(EditedMessage),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue