2 Commits

Author SHA1 Message Date
ecbe4885c1 Can get information about rooms 2025-11-21 14:52:21 +01:00
1385afc974 Add more information to websocket messages 2025-11-21 11:40:51 +01:00
8 changed files with 92 additions and 10 deletions

View File

@@ -11,7 +11,7 @@ pub type BroadcastSender = tokio::sync::broadcast::Sender<BroadcastMessage>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BxRoomEvent<E> { pub struct BxRoomEvent<E> {
pub user: UserEmail, pub user: UserEmail,
pub event: Box<E>, pub data: Box<E>,
pub room: Room, pub room: Room,
} }

View File

@@ -0,0 +1,58 @@
use crate::controllers::HttpResult;
use crate::extractors::matrix_client_extractor::MatrixClientExtractor;
use actix_web::{HttpResponse, web};
use futures_util::{StreamExt, stream};
use matrix_sdk::ruma::{OwnedRoomId, OwnedUserId};
use matrix_sdk::{Room, RoomMemberships};
#[derive(serde::Serialize)]
pub struct APIRoomInfo {
id: OwnedRoomId,
name: Option<String>,
members: Vec<OwnedUserId>,
has_avatar: bool,
}
impl APIRoomInfo {
async fn from_room(r: &Room) -> anyhow::Result<Self> {
Ok(Self {
id: r.room_id().to_owned(),
name: r.name(),
members: r
.members(RoomMemberships::ACTIVE)
.await?
.into_iter()
.map(|r| r.user_id().to_owned())
.collect::<Vec<_>>(),
has_avatar: r.avatar_url().is_some(),
})
}
}
/// Get the list of joined rooms of the user
pub async fn joined_rooms(client: MatrixClientExtractor) -> HttpResult {
let list = stream::iter(client.client.client.joined_rooms())
.then(async |room| APIRoomInfo::from_room(&room).await)
.collect::<Vec<_>>()
.await
.into_iter()
.collect::<Result<Vec<_>, _>>()?;
Ok(HttpResponse::Ok().json(list))
}
#[derive(serde::Deserialize)]
pub struct RoomIdInPath {
id: OwnedRoomId,
}
/// Get the list of joined rooms of the user
pub async fn single_room_info(
client: MatrixClientExtractor,
path: web::Path<RoomIdInPath>,
) -> HttpResult {
Ok(match client.client.client.get_room(&path.id) {
None => HttpResponse::NotFound().json("Room not found"),
Some(r) => HttpResponse::Ok().json(APIRoomInfo::from_room(&r).await?),
})
}

View File

@@ -0,0 +1 @@
pub mod matrix_room_controller;

View File

@@ -3,6 +3,7 @@ use actix_web::{HttpResponse, ResponseError};
use std::error::Error; use std::error::Error;
pub mod auth_controller; pub mod auth_controller;
pub mod matrix;
pub mod matrix_link_controller; pub mod matrix_link_controller;
pub mod matrix_sync_thread_controller; pub mod matrix_sync_thread_controller;
pub mod server_controller; pub mod server_controller;

View File

@@ -10,10 +10,10 @@ use actix_web::dev::Payload;
use actix_web::{FromRequest, HttpRequest, HttpResponse, web}; use actix_web::{FromRequest, HttpRequest, HttpResponse, web};
use actix_ws::Message; use actix_ws::Message;
use futures_util::StreamExt; use futures_util::StreamExt;
use matrix_sdk::ruma::OwnedRoomId;
use matrix_sdk::ruma::events::reaction::ReactionEventContent; use matrix_sdk::ruma::events::reaction::ReactionEventContent;
use matrix_sdk::ruma::events::room::message::RoomMessageEventContent; use matrix_sdk::ruma::events::room::message::RoomMessageEventContent;
use matrix_sdk::ruma::events::room::redaction::RoomRedactionEventContent; use matrix_sdk::ruma::events::room::redaction::RoomRedactionEventContent;
use matrix_sdk::ruma::{MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, OwnedUserId};
use ractor::ActorRef; use ractor::ActorRef;
use std::time::Instant; use std::time::Instant;
use tokio::sync::broadcast; use tokio::sync::broadcast;
@@ -22,8 +22,11 @@ use tokio::time::interval;
#[derive(Debug, serde::Serialize)] #[derive(Debug, serde::Serialize)]
pub struct WsRoomEvent<E> { pub struct WsRoomEvent<E> {
pub event: Box<E>,
pub room_id: OwnedRoomId, pub room_id: OwnedRoomId,
pub event_id: OwnedEventId,
pub sender: OwnedUserId,
pub origin_server_ts: MilliSecondsSinceUnixEpoch,
pub data: Box<E>,
} }
/// Messages sent to the client /// Messages sent to the client
@@ -45,20 +48,29 @@ impl WsMessage {
match msg { match msg {
BroadcastMessage::RoomMessageEvent(evt) if &evt.user == user => { BroadcastMessage::RoomMessageEvent(evt) if &evt.user == user => {
Some(Self::RoomMessageEvent(WsRoomEvent { Some(Self::RoomMessageEvent(WsRoomEvent {
event: Box::new(evt.event.content.clone()),
room_id: evt.room.room_id().to_owned(), room_id: evt.room.room_id().to_owned(),
event_id: evt.data.event_id.clone(),
sender: evt.data.sender.clone(),
origin_server_ts: evt.data.origin_server_ts,
data: Box::new(evt.data.content.clone()),
})) }))
} }
BroadcastMessage::ReactionEvent(evt) if &evt.user == user => { BroadcastMessage::ReactionEvent(evt) if &evt.user == user => {
Some(Self::RoomReactionEvent(WsRoomEvent { Some(Self::RoomReactionEvent(WsRoomEvent {
event: Box::new(evt.event.content.clone()),
room_id: evt.room.room_id().to_owned(), room_id: evt.room.room_id().to_owned(),
event_id: evt.data.event_id.clone(),
sender: evt.data.sender.clone(),
origin_server_ts: evt.data.origin_server_ts,
data: Box::new(evt.data.content.clone()),
})) }))
} }
BroadcastMessage::RoomRedactionEvent(evt) if &evt.user == user => { BroadcastMessage::RoomRedactionEvent(evt) if &evt.user == user => {
Some(Self::RoomRedactionEvent(WsRoomEvent { Some(Self::RoomRedactionEvent(WsRoomEvent {
event: Box::new(evt.event.content.clone()),
room_id: evt.room.room_id().to_owned(), room_id: evt.room.room_id().to_owned(),
event_id: evt.data.event_id.clone(),
sender: evt.data.sender.clone(),
origin_server_ts: evt.data.origin_server_ts,
data: Box::new(evt.data.content.clone()),
})) }))
} }
_ => None, _ => None,

View File

@@ -9,6 +9,7 @@ use actix_web::{App, HttpServer, web};
use matrixgw_backend::app_config::AppConfig; use matrixgw_backend::app_config::AppConfig;
use matrixgw_backend::broadcast_messages::BroadcastMessage; use matrixgw_backend::broadcast_messages::BroadcastMessage;
use matrixgw_backend::constants; use matrixgw_backend::constants;
use matrixgw_backend::controllers::matrix::matrix_room_controller;
use matrixgw_backend::controllers::{ use matrixgw_backend::controllers::{
auth_controller, matrix_link_controller, matrix_sync_thread_controller, server_controller, auth_controller, matrix_link_controller, matrix_sync_thread_controller, server_controller,
tokens_controller, ws_controller, tokens_controller, ws_controller,
@@ -134,6 +135,15 @@ async fn main() -> std::io::Result<()> {
web::get().to(matrix_sync_thread_controller::status), web::get().to(matrix_sync_thread_controller::status),
) )
.service(web::resource("/api/ws").route(web::get().to(ws_controller::ws))) .service(web::resource("/api/ws").route(web::get().to(ws_controller::ws)))
// Matrix room controller
.route(
"/api/matrix/room/joined",
web::get().to(matrix_room_controller::joined_rooms),
)
.route(
"/api/matrix/room/{id}",
web::get().to(matrix_room_controller::single_room_info),
)
}) })
.workers(4) .workers(4)
.bind(&AppConfig::get().listen_address)? .bind(&AppConfig::get().listen_address)?

View File

@@ -91,7 +91,7 @@ pub struct FinishMatrixAuth {
pub struct MatrixClient { pub struct MatrixClient {
manager: ActorRef<MatrixManagerMsg>, manager: ActorRef<MatrixManagerMsg>,
pub email: UserEmail, pub email: UserEmail,
client: Client, pub client: Client,
} }
impl MatrixClient { impl MatrixClient {

View File

@@ -58,7 +58,7 @@ async fn sync_thread_task(
async move |event: OriginalSyncRoomMessageEvent, room: Room| { async move |event: OriginalSyncRoomMessageEvent, room: Room| {
if let Err(e) = tx_msg_handle.send(BroadcastMessage::RoomMessageEvent(BxRoomEvent { if let Err(e) = tx_msg_handle.send(BroadcastMessage::RoomMessageEvent(BxRoomEvent {
user: user_msg_handle.clone(), user: user_msg_handle.clone(),
event: Box::new(event), data: Box::new(event),
room, room,
})) { })) {
log::warn!("Failed to forward room message event! {e}"); log::warn!("Failed to forward room message event! {e}");
@@ -72,7 +72,7 @@ async fn sync_thread_task(
async move |event: OriginalSyncReactionEvent, room: Room| { async move |event: OriginalSyncReactionEvent, room: Room| {
if let Err(e) = tx_reac_handle.send(BroadcastMessage::ReactionEvent(BxRoomEvent { if let Err(e) = tx_reac_handle.send(BroadcastMessage::ReactionEvent(BxRoomEvent {
user: user_reac_handle.clone(), user: user_reac_handle.clone(),
event: Box::new(event), data: Box::new(event),
room, room,
})) { })) {
log::warn!("Failed to forward reaction event! {e}"); log::warn!("Failed to forward reaction event! {e}");
@@ -87,7 +87,7 @@ async fn sync_thread_task(
if let Err(e) = if let Err(e) =
tx_redac_handle.send(BroadcastMessage::RoomRedactionEvent(BxRoomEvent { tx_redac_handle.send(BroadcastMessage::RoomRedactionEvent(BxRoomEvent {
user: user_redac_handle.clone(), user: user_redac_handle.clone(),
event: Box::new(event), data: Box::new(event),
room, room,
})) }))
{ {