renamed, add profile pictures

This commit is contained in:
TriMill 2023-05-25 17:38:17 -04:00
parent b13ccb50b1
commit 1f13b0cdfd
11 changed files with 170 additions and 94 deletions

138
Cargo.lock generated
View File

@ -2,6 +2,22 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "abridged"
version = "0.1.0"
dependencies = [
"async-trait",
"env_logger",
"futures",
"irc",
"log",
"matrix-sdk",
"serde",
"serenity",
"tokio",
"toml 0.7.4",
]
[[package]]
name = "adler"
version = "1.0.2"
@ -123,9 +139,9 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@ -134,9 +150,9 @@ version = "0.1.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@ -200,9 +216,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.21.1"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105"
checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
[[package]]
name = "base64ct"
@ -259,9 +275,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.12.2"
version = "3.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b"
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
[[package]]
name = "byteorder"
@ -483,7 +499,7 @@ checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
dependencies = [
"fnv",
"ident_case",
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"strsim",
"syn 1.0.109",
@ -539,7 +555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4"
dependencies = [
"darling",
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 1.0.109",
]
@ -586,9 +602,9 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@ -860,9 +876,9 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@ -1205,9 +1221,9 @@ dependencies = [
[[package]]
name = "io-lifetimes"
version = "1.0.10"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi 0.3.1",
"libc",
@ -1593,22 +1609,6 @@ dependencies = [
"windows-sys 0.45.0",
]
[[package]]
name = "multibridge"
version = "0.1.0"
dependencies = [
"async-trait",
"env_logger",
"futures",
"irc",
"log",
"matrix-sdk",
"serde",
"serenity",
"tokio",
"toml 0.7.4",
]
[[package]]
name = "native-tls"
version = "0.2.11"
@ -1689,9 +1689,9 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@ -1813,9 +1813,9 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@ -1884,9 +1884,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.56"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
dependencies = [
"unicode-ident",
]
@ -1909,7 +1909,7 @@ checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4"
dependencies = [
"anyhow",
"itertools",
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 1.0.109",
]
@ -1929,7 +1929,7 @@ version = "1.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
]
[[package]]
@ -2138,9 +2138,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.8.1"
version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390"
dependencies = [
"aho-corasick",
"memchr",
@ -2149,9 +2149,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.7.1"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
[[package]]
name = "reqwest"
@ -2159,7 +2159,7 @@ version = "0.11.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
dependencies = [
"base64 0.21.1",
"base64 0.21.2",
"bytes",
"encoding_rs",
"futures-core",
@ -2304,7 +2304,7 @@ checksum = "0f82e91eb61cd86d9287303133ee55b54618eccb75a522cc22a42c15f5bda340"
dependencies = [
"once_cell",
"proc-macro-crate",
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"ruma-identifiers-validation",
"serde",
@ -2369,7 +2369,7 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
dependencies = [
"base64 0.21.1",
"base64 0.21.2",
]
[[package]]
@ -2480,9 +2480,9 @@ version = "1.0.163"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@ -2673,18 +2673,18 @@ version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.15"
version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"unicode-ident",
]
@ -2726,9 +2726,9 @@ version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@ -2807,9 +2807,9 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@ -2925,9 +2925,9 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.19.9"
version = "0.19.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92d964908cec0d030b812013af25a0e57fddfadb1e066ecc6681d86253129d4f"
checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
dependencies = [
"indexmap",
"serde",
@ -2961,9 +2961,9 @@ version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
]
[[package]]
@ -3032,9 +3032,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
[[package]]
name = "unicode-ident"
version = "1.0.8"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
[[package]]
name = "unicode-normalization"
@ -3199,9 +3199,9 @@ dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
"wasm-bindgen-shared",
]
@ -3233,9 +3233,9 @@ version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -3560,7 +3560,7 @@ version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.59",
"quote 1.0.27",
"syn 2.0.15",
"syn 2.0.16",
]

View File

@ -1,8 +1,9 @@
[package]
name = "multibridge"
name = "abridged"
version = "0.1.0"
edition = "2021"
description = "Bridging between IRC, Discord, and Matrix"
description = "Configurable and fault-tolerant bridge for Discord, Matrix, and IRC"
readme = "README.md"
[features]
# platforms

View File

@ -0,0 +1,29 @@
# Abridged
Abridged is a configurable and fault-tolerant bridge for Discord, IRC, and Matrix.
## Features
- Bridge between multiple IRC servers and multiple Discord/Matrix bots
- Automatically and independently restart bridge nodes on error
- Feature flags to enable/disable each supported platform
## Configuration
An example configuration is provided in [example-config.toml](example-config.toml). The path to the configuration should be passed as the first command-line argument.
## Building
```sh
cargo build --release
```
The following feature flags are enabled:
- `irc` - enable IRC support
- `discord` - enable Discord support
- `matrix` - enable Matrix support
- `matrix-e2ee` - enable end-to-end encryption support for Matrix
- `tls-rustls` use rustls for TLS
- `tls-native` use the native TLS library (probably OpenSSL) for TLS
`tls-rustls` and `tls-native` are mutually exclusive. By default, all platforms and platform-specific features are enabled and rustls is used for TLS.

View File

@ -29,6 +29,7 @@ platform = "discord"
[nodes.cccc.config]
token = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.ABCDEF.0123456789abcdefghijklmnopqrstuvwxyzab"
webhooks = { "123456789012345678" = "9123456789123456789" }
[nodes.cccc.links]
"123456789012345678" = "example-link"

View File

@ -37,12 +37,11 @@ impl Task for DiscordTask {
let bridge_handler = async move {
loop {
let msg = rx.recv().await?;
handle_bridge_msg(msg, id, &self.links, http.as_ref()).await?;
self.handle_bridge_msg(msg, id, http.as_ref()).await?;
}
};
debug!("{id}: built client, starting");
debug!("{id}: entering event loop");
tokio::select! {
result = bridge_handler => result,
result = client.start() => result.map_err(|e| e.into()),
@ -50,18 +49,29 @@ impl Task for DiscordTask {
}
}
async fn handle_bridge_msg(msg: BMessage, id: Id, links: &Linkmap<ChannelId>, http: &Http) -> TaskResult {
let content = format!("<{}> {}", msg.author, msg.content);
impl DiscordTask {
async fn handle_bridge_msg(&self, msg: BMessage, id: Id, http: &Http) -> TaskResult {
let content = format!("<{}> {}", msg.author, msg.content);
for channel in links.get_channels(&msg.link) {
if msg.origin.0 == id && msg.origin.1 == channel.to_string() {
continue
for channel in self.links.get_channels(&msg.link) {
if msg.origin.0 == id && msg.origin.1 == channel.to_string() {
continue
}
debug!("{id}: bridging message from {:?}/{:?} to {channel:?}", msg.origin, msg.link);
if let Some(hook) = self.config.webhooks.get(channel) {
let hook = http.get_webhook(*hook.as_u64()).await?;
hook.execute(http, false, |hook| {
hook.username(&msg.author)
.content(&msg.content)
.avatar_url(msg.avatar.as_ref().map(|s| s.as_str()).unwrap_or(""))
}).await?;
} else {
channel.say(http, &content).await?;
}
}
debug!("{id}: bridging message from {:?}/{:?} to {channel:?}", msg.origin, msg.link);
channel.say(http, &content).await?;
}
Ok(())
Ok(())
}
}
struct Handler {
@ -73,10 +83,11 @@ struct Handler {
#[async_trait]
impl EventHandler for Handler {
async fn message(&self, ctx: Context, msg: Message) {
if msg.author.id == ctx.cache.current_user_id() {
if msg.author.bot {
return
}
let avatar = msg.author.avatar_url();
let Some(link) = self.links.get_link(&msg.channel_id) else { return };
let author = msg.author.nick_in(ctx.http, msg.guild_id.expect("failed to get guild ID"))
.await.unwrap_or(msg.author.name);
@ -88,6 +99,7 @@ impl EventHandler for Handler {
link: link.clone(),
author,
content: msg.content,
avatar,
}).expect("failed to broadcast message");
}

View File

@ -1,6 +1,11 @@
use std::collections::HashMap;
use serde::Deserialize;
use serenity::model::prelude::{WebhookId, ChannelId};
#[derive(Debug, Deserialize)]
pub struct DiscordConfig {
pub token: String,
#[serde(default)]
pub webhooks: HashMap<ChannelId, WebhookId>,
}

View File

@ -41,6 +41,7 @@ impl IrcTask {
link: link.clone(),
author: author.to_owned(),
content: message.clone(),
avatar: None,
})?;
}
Ok(())

View File

@ -1,10 +1,16 @@
use serde::Deserialize;
const fn default_port() -> u16 { 6667 }
const fn default_tls() -> bool { true }
#[derive(Clone, Debug, Deserialize)]
pub struct IrcConfig {
pub server: String,
#[serde(default="default_port")]
pub port: u16,
#[serde(default="default_tls")]
pub tls: bool,
pub nick: String,
#[serde(default)]
pub alt_nicks: Vec<String>,
}

View File

@ -4,7 +4,7 @@ use async_trait::async_trait;
use futures::StreamExt;
use log::debug;
use matrix_sdk::{Client, config::SyncSettings, event_handler::Ctx, room::Room};
use matrix_sdk::ruma::RoomId;
use matrix_sdk::ruma::{RoomId, MxcUri};
use matrix_sdk::ruma::events::room::message::{SyncRoomMessageEvent, RoomMessageEventContent};
use serde::Deserialize;
use tokio::select;
@ -65,6 +65,23 @@ impl Task for MatrixTask {
}
}
async fn mxc_thumbnail(client: &Client, mxc: &MxcUri, width: u32, height: u32) -> Option<String> {
let mut hs = client.homeserver().await;
let (server_name, media_id) = mxc.parts().ok()?;
hs.path_segments_mut().ok()?
.extend(["_matrix", "media", "v3", "thumbnail"])
.push(server_name.as_str())
.push(media_id);
hs.query_pairs_mut()
.append_pair("width", &width.to_string())
.append_pair("height", &height.to_string());
Some(hs.to_string())
}
async fn handle_matrix_msg(ev: SyncRoomMessageEvent, client: Client, room: Room, ctx: Ctx<Arc<Context>>) -> TaskResult {
if Some(ev.sender()) == client.user_id() { return Ok(()) }
let SyncRoomMessageEvent::Original(ev) = ev else { return Ok(()) };
@ -72,13 +89,19 @@ async fn handle_matrix_msg(ev: SyncRoomMessageEvent, client: Client, room: Room,
let Some(link) = ctx.rooms.get_link(room.room_id().as_str()) else { return Ok(()) };
let body = ev.content.body();
let avatar = match sender.avatar_url() {
None => None,
Some(u) => mxc_thumbnail(&client, u, 128, 128).await,
};
println!("AVATAR: {:?}", avatar);
debug!("{}: broadcasting message from {:?} to {:?}", ctx.id, room, link);
debug!("{}: broadcasting message from {:?} ({}) to {:?}", ctx.id, room.name(), room.room_id(), link);
ctx.tx.send(Message {
origin: (ctx.id, room.room_id().to_string()),
link: link.clone(),
author: sender.name().to_owned(),
content: body.to_owned(),
avatar,
})?;
Ok(())
}
@ -96,7 +119,7 @@ async fn handle_bridge_msg(id: Id, client: &Client, links: &Linkmap<String>, msg
let Ok(room) = <&RoomId>::try_from(room.as_str()) else { continue };
let Some(Room::Joined(room)) = client.get_room(room) else { continue };
debug!("{id}: bridging message from {:?}/{:?} to {room:?}", msg.origin, msg.link);
debug!("{id}: bridging message from {:?}/{:?} to {:?} ({})", msg.origin, msg.link, room.name(), room.room_id());
room.send(content.clone(), None).await?;
}
Ok(())

View File

@ -32,12 +32,9 @@ async fn main() -> ExitCode {
let cmd_name = args.next()
.unwrap_or_else(|| env!("CARGO_PKG_NAME").to_owned());
let conf_filename = match args.next() {
Some(f) => f,
None => {
eprintln!("Usage: {cmd_name} <config>");
return ExitCode::FAILURE
}
let Some(conf_filename) = args.next() else {
eprintln!("Usage: {cmd_name} <config>");
return ExitCode::FAILURE
};
debug!("reading config file");

View File

@ -37,6 +37,7 @@ pub struct Message {
pub link: Link,
pub author: String,
pub content: String,
pub avatar: Option<String>,
}
pub type Sender = tokio::sync::broadcast::Sender<Message>;