mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-11-13 04:06:54 +00:00
feat: Move room state commands to the room group
This commit is contained in:
4 files changed
+74
-118
No files matched your search
@@ -6,17 +6,15 @@ use std::{
|
||||
};
|
||||
|
||||
use conduwuit::{
|
||||
Err, Result, at, debug_error, err, info,
|
||||
Err, Result, debug_error, err, info,
|
||||
matrix::{
|
||||
Event, StateKey,
|
||||
Event,
|
||||
pdu::{PduEvent, PduId, RawPduId},
|
||||
},
|
||||
state_res::EventTypeExt,
|
||||
trace, utils,
|
||||
utils::{
|
||||
stream::{BroadbandExt, IterStream, ReadyExt},
|
||||
string::EMPTY,
|
||||
to_canonical_object,
|
||||
},
|
||||
warn,
|
||||
};
|
||||
@@ -27,11 +25,8 @@ use resolvematrix::{
|
||||
server::{MatrixResolver, MatrixResolverBuilder},
|
||||
};
|
||||
use ruma::{
|
||||
CanonicalJsonObject, CanonicalJsonValue, EventId, OwnedEventId, OwnedRoomId,
|
||||
OwnedRoomOrAliasId, OwnedServerName, RoomId, RoomVersionId, UInt,
|
||||
api::federation::event::get_room_state,
|
||||
events::{AnyStateEvent, StateEventType},
|
||||
serde::Raw,
|
||||
CanonicalJsonObject, CanonicalJsonValue, EventId, OwnedEventId, OwnedRoomId, OwnedServerName,
|
||||
RoomId, RoomVersionId, UInt, api::federation::event::get_room_state,
|
||||
};
|
||||
use service::rooms::{
|
||||
short::{ShortEventId, ShortRoomId},
|
||||
@@ -518,88 +513,6 @@ impl crate::Context<'_> {
|
||||
.await
|
||||
}
|
||||
|
||||
pub(super) async fn get_state_at(&self, event_id: OwnedEventId) -> Result {
|
||||
self.bail_restricted()?;
|
||||
|
||||
let shortstatehash = self
|
||||
.services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.pdu_shortstatehash(&event_id)
|
||||
.await?;
|
||||
|
||||
let state_ids: Vec<OwnedEventId> = self
|
||||
.services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.state_full_ids(shortstatehash)
|
||||
.map(at!(1))
|
||||
.collect()
|
||||
.await;
|
||||
|
||||
let mut pdus: HashMap<(StateEventType, StateKey), CanonicalJsonObject> = state_ids
|
||||
.iter()
|
||||
.try_stream::<conduwuit::Error>()
|
||||
.and_then(|id| async {
|
||||
let pdu_json = self.services.rooms.timeline.get_pdu_json(id).await?;
|
||||
let event_type = pdu_json
|
||||
.get("type")
|
||||
.and_then(CanonicalJsonValue::as_str)
|
||||
.expect("event type must be present in events");
|
||||
let state_key = pdu_json
|
||||
.get("state_key")
|
||||
.and_then(CanonicalJsonValue::as_str)
|
||||
.expect("state keys must be present for events in the room state");
|
||||
Ok(((event_type.into(), state_key.into()), pdu_json))
|
||||
})
|
||||
.try_collect()
|
||||
.await?;
|
||||
|
||||
let pdu = self.services.rooms.timeline.get_pdu(&event_id).await?;
|
||||
if let Some(state_key) = pdu.state_key() {
|
||||
pdus.insert(pdu.kind().with_state_key(state_key), to_canonical_object(pdu)?);
|
||||
}
|
||||
|
||||
let json =
|
||||
serde_json::to_string_pretty(&pdus.values().collect::<Vec<_>>()).map_err(|e| {
|
||||
err!(Database(
|
||||
"Failed to convert room state events to pretty JSON, possible invalid room \
|
||||
state events in our database {e}",
|
||||
))
|
||||
})?;
|
||||
|
||||
let out = format!("```json\n{json}\n```");
|
||||
self.write_str(&out).await
|
||||
}
|
||||
|
||||
pub(super) async fn get_room_state(&self, room: OwnedRoomOrAliasId) -> Result {
|
||||
self.bail_restricted()?;
|
||||
|
||||
let room_id = self.services.rooms.alias.resolve(&room).await?;
|
||||
let room_state: Vec<Raw<AnyStateEvent>> = self
|
||||
.services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.room_state_full_pdus(&room_id)
|
||||
.map_ok(Event::into_format)
|
||||
.try_collect()
|
||||
.await?;
|
||||
|
||||
if room_state.is_empty() {
|
||||
return Err!("Unable to find room state in our database (vector is empty)",);
|
||||
}
|
||||
|
||||
let json = serde_json::to_string_pretty(&room_state).map_err(|e| {
|
||||
err!(Database(
|
||||
"Failed to convert room state events to pretty JSON, possible invalid room \
|
||||
state events in our database {e}",
|
||||
))
|
||||
})?;
|
||||
|
||||
let out = format!("```json\n{json}\n```");
|
||||
self.write_str(&out).await
|
||||
}
|
||||
|
||||
pub(super) async fn ping(&self, server: OwnedServerName) -> Result {
|
||||
if server == self.services.globals.server_name() {
|
||||
return Err!("Not allowed to send federation requests to ourselves.");
|
||||
|
||||
+1
-24
@@ -3,7 +3,7 @@ pub(crate) mod tester;
|
||||
|
||||
use clap::Subcommand;
|
||||
use conduwuit::Result;
|
||||
use ruma::{OwnedEventId, OwnedRoomId, OwnedRoomOrAliasId, OwnedServerName};
|
||||
use ruma::{OwnedEventId, OwnedRoomId, OwnedServerName};
|
||||
use service::rooms::short::{ShortEventId, ShortRoomId};
|
||||
|
||||
use self::tester::TesterCommand;
|
||||
@@ -80,29 +80,6 @@ pub enum DebugCommand {
|
||||
force: bool,
|
||||
},
|
||||
|
||||
/// Gets all the room state events for the specified room.
|
||||
///
|
||||
/// This is functionally equivalent to `GET
|
||||
/// /_matrix/client/v3/rooms/{roomid}/state`, except the admin command does
|
||||
/// *not* check if the sender user is allowed to see state events. This is
|
||||
/// done because it's implied that server admins here have database access
|
||||
/// and can see/get room info themselves anyways if they were malicious
|
||||
/// admins.
|
||||
///
|
||||
/// Of course the check is still done on the actual client API.
|
||||
GetRoomState {
|
||||
/// Room ID
|
||||
room_id: OwnedRoomOrAliasId,
|
||||
},
|
||||
|
||||
/// Gets all the room state events at the specified event.
|
||||
///
|
||||
/// State at event might not be available for some PDUs, such as rejected
|
||||
/// ones.
|
||||
GetStateAt {
|
||||
event_id: OwnedEventId,
|
||||
},
|
||||
|
||||
/// Sends a federation request to the remote server's
|
||||
/// `/_matrix/federation/v1/version` endpoint and measures the latency it
|
||||
/// took for the server to respond
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use conduwuit::{Err, Result};
|
||||
use conduwuit::{Err, Event, Result, err};
|
||||
use futures::StreamExt;
|
||||
use ruma::OwnedRoomId;
|
||||
#[allow(unused_imports)]
|
||||
use ruma::state_res::Event as _;
|
||||
use ruma::{OwnedEventId, OwnedRoomId, OwnedRoomOrAliasId};
|
||||
|
||||
use crate::{PAGE_SIZE, get_room_info};
|
||||
|
||||
@@ -82,4 +84,57 @@ impl crate::Context<'_> {
|
||||
|
||||
self.write_str(&format!("{result}")).await
|
||||
}
|
||||
|
||||
pub(super) async fn export_state(
|
||||
&self,
|
||||
room: OwnedRoomOrAliasId,
|
||||
event_id: Option<OwnedEventId>,
|
||||
) -> Result {
|
||||
self.bail_restricted()?;
|
||||
|
||||
let room_id = self.services.rooms.alias.resolve(&room).await?;
|
||||
let shortstatehash = match &event_id {
|
||||
| Some(event_id) =>
|
||||
self.services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.pdu_shortstatehash(event_id)
|
||||
.await?,
|
||||
| None =>
|
||||
self.services
|
||||
.rooms
|
||||
.state
|
||||
.get_room_shortstatehash(&room_id)
|
||||
.await?,
|
||||
};
|
||||
let mut state_at: Vec<_> = self
|
||||
.services
|
||||
.rooms
|
||||
.state_accessor
|
||||
.state_full_pdus(shortstatehash)
|
||||
.map(Event::into_pdu)
|
||||
.collect()
|
||||
.await;
|
||||
|
||||
if let Some(event_id) = event_id {
|
||||
let pdu = self.services.rooms.timeline.get_pdu(&event_id).await?;
|
||||
if let Some(state_key) = pdu.state_key() {
|
||||
state_at.retain(|p| p.kind() != pdu.kind() || p.state_key() != Some(state_key));
|
||||
state_at.push(pdu);
|
||||
}
|
||||
}
|
||||
|
||||
if state_at.is_empty() {
|
||||
return Err!(Request(NotFound("No state found.")));
|
||||
}
|
||||
|
||||
let json = serde_json::to_string_pretty(&state_at).map_err(|e| {
|
||||
err!(Database(
|
||||
"Failed to convert room state events to pretty JSON, possible invalid room \
|
||||
state events in the database: {e:?}",
|
||||
))
|
||||
})?;
|
||||
|
||||
self.write_str(&format!("```json\n{json}\n```")).await
|
||||
}
|
||||
}
|
||||
+12
-1
@@ -6,7 +6,7 @@ mod moderation;
|
||||
|
||||
use clap::Subcommand;
|
||||
use conduwuit::Result;
|
||||
use ruma::OwnedRoomId;
|
||||
use ruma::{OwnedEventId, OwnedRoomId, OwnedRoomOrAliasId};
|
||||
|
||||
use self::{
|
||||
alias::RoomAliasCommand, directory::RoomDirectoryCommand, info::RoomInfoCommand,
|
||||
@@ -60,4 +60,15 @@ pub enum RoomCommand {
|
||||
Exists {
|
||||
room_id: OwnedRoomId,
|
||||
},
|
||||
|
||||
/// Exports the room's current state as a JSON file.
|
||||
/// If an event ID is supplied, the state at that event (the state preceding
|
||||
/// it, plus any change made by the named event) is returned instead, if it
|
||||
/// is known.
|
||||
ExportState {
|
||||
/// The room ID or alias to get the state for.
|
||||
room: OwnedRoomOrAliasId,
|
||||
/// The event ID to get the state at, if any.
|
||||
event_id: Option<OwnedEventId>,
|
||||
},
|
||||
}
|
||||
Reference in new issue
Block a user