Matrix: invite somebody into a room
Closes #74. This client could accept an invitation and decline one, and never send one - so a room created here could never gain a second member here, and every other member of a room was somebody who had arrived by some other route. It sits beside kick and ban because it is the same shape of call decided by the same authority: a room's power levels say who may invite exactly as they say who may remove. A Matrix address or nothing. The server would refuse anything else anyway, but its refusal names an endpoint rather than the thing that was typed. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -85,6 +85,23 @@ pub async fn kick_member(state: &AppState, account_id: &str, buffer_id: &str, ta
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Asks somebody into a room.
|
||||
///
|
||||
/// Lives here beside kick and ban because it is the same shape of call and
|
||||
/// the same authority decides it - a room's power levels say who may invite
|
||||
/// exactly as they say who may remove. It is the opposite action, which is
|
||||
/// why its absence was odd: a room made here could gain no second member
|
||||
/// from here.
|
||||
pub async fn invite_member(state: &AppState, account_id: &str, buffer_id: &str, target_user_id: &str) -> Result<()> {
|
||||
let (homeserver_url, access_token, room_id) = homeserver_token_room(state, account_id, buffer_id).await?;
|
||||
let base = homeserver_url.trim_end_matches('/');
|
||||
let url = format!("{base}/_matrix/client/v3/rooms/{}/invite", url::form_urlencoded::byte_serialize(room_id.as_bytes()).collect::<String>());
|
||||
http::post_json(&url, Some(&access_token), serde_json::json!({ "user_id": target_user_id }))
|
||||
.await
|
||||
.context("inviting member")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn ban_member(state: &AppState, account_id: &str, buffer_id: &str, target_user_id: &str, reason: Option<&str>) -> Result<()> {
|
||||
let (homeserver_url, access_token, room_id) = homeserver_token_room(state, account_id, buffer_id).await?;
|
||||
let base = homeserver_url.trim_end_matches('/');
|
||||
|
||||
@@ -2223,6 +2223,32 @@ pub async fn dispatch(
|
||||
}
|
||||
}
|
||||
|
||||
// Asking somebody into a room. Its absence was the odd one out: this
|
||||
// client could accept an invitation and decline one, and never send
|
||||
// one - so a room created here could never gain a second member here.
|
||||
"inviteMatrixMember" => {
|
||||
let (account_id, buffer_id, user_id) =
|
||||
match (p_str_opt(params, "accountId"), p_str_opt(params, "bufferId"), p_str_opt(params, "userId")) {
|
||||
(Some(a), Some(b), Some(u)) => (a, b, u),
|
||||
_ => {
|
||||
return (
|
||||
None,
|
||||
Some("inviteMatrixMember requires \"accountId\", \"bufferId\" and \"userId\"".to_string()),
|
||||
)
|
||||
}
|
||||
};
|
||||
// A Matrix id or nothing. The server would refuse anything else
|
||||
// anyway, but its error names an endpoint rather than the thing
|
||||
// that was typed.
|
||||
if !user_id.starts_with('@') || !user_id.contains(':') {
|
||||
return (None, Some(format!("\"{user_id}\" is not a Matrix address - they look like @someone:server")));
|
||||
}
|
||||
match backend::matrix::moderation::invite_member(state, account_id, buffer_id, user_id).await {
|
||||
Ok(()) => (Some(ok_node()), None),
|
||||
Err(e) => (None, Some(format!("{e:#}"))),
|
||||
}
|
||||
}
|
||||
|
||||
"banMatrixMember" => {
|
||||
let (account_id, buffer_id, user_id) =
|
||||
match (p_str_opt(params, "accountId"), p_str_opt(params, "bufferId"), p_str_opt(params, "userId")) {
|
||||
|
||||
Reference in New Issue
Block a user