**Does not yet work!** Currently, state resolution does not correctly resolve conflicting states. Everything else appears to work as expected, so stateres will be fixed soon, then we should be clear for takeoff. Also: a lot of things currently accept a nullable room ID that really just don't need to. This will need tidying up before merge. Some authentication checks have also been disabled temporarily but nothing important. A lot of things are tagged with `TODO(hydra)`, those need resolving before merge. External contributors should PR to the `hydra/public` branch, *not* ` main`. --- This PR should be squash merged. Reviewed-on: https://forgejo.ellis.link/continuwuation/continuwuity/pulls/943 Co-authored-by: nexy7574 <git@nexy7574.co.uk> Co-committed-by: nexy7574 <git@nexy7574.co.uk>
98 lines
3 KiB
Rust
98 lines
3 KiB
Rust
use std::collections::BTreeMap;
|
|
|
|
use axum::extract::State;
|
|
use conduwuit::{Err, Result, err, matrix::pdu::PduBuilder, utils};
|
|
use ruma::{api::client::message::send_message_event, events::MessageLikeEventType};
|
|
use serde_json::from_str;
|
|
|
|
use crate::Ruma;
|
|
|
|
/// # `PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}`
|
|
///
|
|
/// Send a message event into the room.
|
|
///
|
|
/// - Is a NOOP if the txn id was already used before and returns the same event
|
|
/// id again
|
|
/// - The only requirement for the content is that it has to be valid json
|
|
/// - Tries to send the event into the room, auth rules will determine if it is
|
|
/// allowed
|
|
pub(crate) async fn send_message_event_route(
|
|
State(services): State<crate::State>,
|
|
body: Ruma<send_message_event::v3::Request>,
|
|
) -> Result<send_message_event::v3::Response> {
|
|
let sender_user = body.sender_user();
|
|
let sender_device = body.sender_device.as_deref();
|
|
let appservice_info = body.appservice_info.as_ref();
|
|
if services.users.is_suspended(sender_user).await? {
|
|
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
|
}
|
|
|
|
// Forbid m.room.encrypted if encryption is disabled
|
|
if MessageLikeEventType::RoomEncrypted == body.event_type && !services.config.allow_encryption
|
|
{
|
|
return Err!(Request(Forbidden("Encryption has been disabled")));
|
|
}
|
|
|
|
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
|
|
|
if body.event_type == MessageLikeEventType::CallInvite
|
|
&& services.rooms.directory.is_public_room(&body.room_id).await
|
|
{
|
|
return Err!(Request(Forbidden("Room call invites are not allowed in public rooms")));
|
|
}
|
|
|
|
// Check if this is a new transaction id
|
|
if let Ok(response) = services
|
|
.transaction_ids
|
|
.existing_txnid(sender_user, sender_device, &body.txn_id)
|
|
.await
|
|
{
|
|
// The client might have sent a txnid of the /sendToDevice endpoint
|
|
// This txnid has no response associated with it
|
|
if response.is_empty() {
|
|
return Err!(Request(InvalidParam(
|
|
"Tried to use txn id already used for an incompatible endpoint."
|
|
)));
|
|
}
|
|
|
|
return Ok(send_message_event::v3::Response {
|
|
event_id: utils::string_from_bytes(&response)
|
|
.map(TryInto::try_into)
|
|
.map_err(|e| err!(Database("Invalid event_id in txnid data: {e:?}")))??,
|
|
});
|
|
}
|
|
|
|
let mut unsigned = BTreeMap::new();
|
|
unsigned.insert("transaction_id".to_owned(), body.txn_id.to_string().into());
|
|
|
|
let content = from_str(body.body.body.json().get())
|
|
.map_err(|e| err!(Request(BadJson("Invalid JSON body: {e}"))))?;
|
|
|
|
let event_id = services
|
|
.rooms
|
|
.timeline
|
|
.build_and_append_pdu(
|
|
PduBuilder {
|
|
event_type: body.event_type.clone().into(),
|
|
content,
|
|
unsigned: Some(unsigned),
|
|
timestamp: appservice_info.and(body.timestamp),
|
|
..Default::default()
|
|
},
|
|
sender_user,
|
|
Some(&body.room_id),
|
|
&state_lock,
|
|
)
|
|
.await?;
|
|
|
|
services.transaction_ids.add_txnid(
|
|
sender_user,
|
|
sender_device,
|
|
&body.txn_id,
|
|
event_id.as_bytes(),
|
|
);
|
|
|
|
drop(state_lock);
|
|
|
|
Ok(send_message_event::v3::Response { event_id })
|
|
}
|