mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2025-07-09 22:26:41 +02:00
Compare commits
8 commits
9bef2972ac
...
f62d8a42d4
Author | SHA1 | Date | |
---|---|---|---|
|
f62d8a42d4 | ||
|
f7dd4c6928 | ||
|
d1cb893db1 | ||
|
ebad3c78c6 | ||
|
c338fd8453 | ||
|
a331790058 | ||
|
2ccbd7d60b | ||
|
60960c6e09 |
8 changed files with 140 additions and 74 deletions
|
@ -19,11 +19,20 @@ outputs:
|
||||||
rustc_version:
|
rustc_version:
|
||||||
description: The rustc version installed
|
description: The rustc version installed
|
||||||
value: ${{ steps.rustc-version.outputs.version }}
|
value: ${{ steps.rustc-version.outputs.version }}
|
||||||
|
rustup_version:
|
||||||
|
description: The rustup version installed
|
||||||
|
value: ${{ steps.rustup-version.outputs.version }}
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: composite
|
using: composite
|
||||||
steps:
|
steps:
|
||||||
|
- name: Check if rustup is already installed
|
||||||
|
shell: bash
|
||||||
|
id: rustup-version
|
||||||
|
run: |
|
||||||
|
echo "version=$(rustup --version)" >> $GITHUB_OUTPUT
|
||||||
- name: Cache rustup toolchains
|
- name: Cache rustup toolchains
|
||||||
|
if: steps.rustup-version.outputs.version == ''
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
|
@ -33,6 +42,7 @@ runs:
|
||||||
# Requires repo to be cloned if toolchain is not specified
|
# Requires repo to be cloned if toolchain is not specified
|
||||||
key: ${{ runner.os }}-rustup-${{ inputs.toolchain || hashFiles('**/rust-toolchain.toml') }}
|
key: ${{ runner.os }}-rustup-${{ inputs.toolchain || hashFiles('**/rust-toolchain.toml') }}
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
|
if: steps.rustup-version.outputs.version == ''
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
if ! command -v rustup &> /dev/null ; then
|
if ! command -v rustup &> /dev/null ; then
|
||||||
|
|
|
@ -57,7 +57,6 @@ jobs:
|
||||||
|
|
||||||
build-image:
|
build-image:
|
||||||
runs-on: dind
|
runs-on: dind
|
||||||
container: ghcr.io/catthehacker/ubuntu:act-latest
|
|
||||||
needs: define-variables
|
needs: define-variables
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
@ -211,7 +210,6 @@ jobs:
|
||||||
|
|
||||||
merge:
|
merge:
|
||||||
runs-on: dind
|
runs-on: dind
|
||||||
container: ghcr.io/catthehacker/ubuntu:act-latest
|
|
||||||
needs: [define-variables, build-image]
|
needs: [define-variables, build-image]
|
||||||
steps:
|
steps:
|
||||||
- name: Download digests
|
- name: Download digests
|
||||||
|
|
|
@ -1641,19 +1641,29 @@
|
||||||
#
|
#
|
||||||
#server =
|
#server =
|
||||||
|
|
||||||
# This item is undocumented. Please contribute documentation for it.
|
# URL to a support page for the server, which will be served as part of
|
||||||
|
# the MSC1929 server support endpoint at /.well-known/matrix/support.
|
||||||
|
# Will be included alongside any contact information
|
||||||
#
|
#
|
||||||
#support_page =
|
#support_page =
|
||||||
|
|
||||||
# This item is undocumented. Please contribute documentation for it.
|
# Role string for server support contacts, to be served as part of the
|
||||||
|
# MSC1929 server support endpoint at /.well-known/matrix/support.
|
||||||
#
|
#
|
||||||
#support_role =
|
#support_role = "m.role.admin"
|
||||||
|
|
||||||
# This item is undocumented. Please contribute documentation for it.
|
# Email address for server support contacts, to be served as part of the
|
||||||
|
# MSC1929 server support endpoint.
|
||||||
|
# This will be used along with support_mxid if specified.
|
||||||
#
|
#
|
||||||
#support_email =
|
#support_email =
|
||||||
|
|
||||||
# This item is undocumented. Please contribute documentation for it.
|
# Matrix ID for server support contacts, to be served as part of the
|
||||||
|
# MSC1929 server support endpoint.
|
||||||
|
# This will be used along with support_email if specified.
|
||||||
|
#
|
||||||
|
# If no email or mxid is specified, all of the server's admins will be
|
||||||
|
# listed.
|
||||||
#
|
#
|
||||||
#support_mxid =
|
#support_mxid =
|
||||||
|
|
||||||
|
|
|
@ -73,9 +73,8 @@ pub(super) async fn purge_sync_tokens(&self, room: OwnedRoomOrAliasId) -> Result
|
||||||
let room_id = self.services.rooms.alias.resolve(&room).await?;
|
let room_id = self.services.rooms.alias.resolve(&room).await?;
|
||||||
|
|
||||||
// Delete all tokens for this room using the service method
|
// Delete all tokens for this room using the service method
|
||||||
let deleted_count = match self.services.rooms.user.delete_room_tokens(&room_id).await {
|
let Ok(deleted_count) = self.services.rooms.user.delete_room_tokens(&room_id).await else {
|
||||||
| Ok(count) => count,
|
return Err!("Failed to delete sync tokens for room {}", room_id);
|
||||||
| Err(_) => return Err!("Failed to delete sync tokens for room {}", room_id),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.write_str(&format!(
|
self.write_str(&format!(
|
||||||
|
@ -84,12 +83,23 @@ pub(super) async fn purge_sync_tokens(&self, room: OwnedRoomOrAliasId) -> Result
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Target options for room purging
|
||||||
|
#[derive(Default, Debug, clap::ValueEnum, Clone)]
|
||||||
|
pub(crate) enum RoomTargetOption {
|
||||||
|
#[default]
|
||||||
|
/// Target all rooms
|
||||||
|
All,
|
||||||
|
/// Target only disabled rooms
|
||||||
|
DisabledOnly,
|
||||||
|
/// Target only banned rooms
|
||||||
|
BannedOnly,
|
||||||
|
}
|
||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn purge_empty_room_tokens(
|
pub(super) async fn purge_empty_room_tokens(
|
||||||
&self,
|
&self,
|
||||||
yes: bool,
|
yes: bool,
|
||||||
target_disabled: bool,
|
target_option: Option<RoomTargetOption>,
|
||||||
target_banned: bool,
|
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
) -> Result {
|
) -> Result {
|
||||||
use conduwuit::{debug, info};
|
use conduwuit::{debug, info};
|
||||||
|
@ -103,11 +113,13 @@ pub(super) async fn purge_empty_room_tokens(
|
||||||
|
|
||||||
let mode = if dry_run { "Simulating" } else { "Starting" };
|
let mode = if dry_run { "Simulating" } else { "Starting" };
|
||||||
|
|
||||||
let mut total_rooms_processed = 0;
|
// strictly, we should check if these reach the max value after the loop and
|
||||||
let mut empty_rooms_processed = 0;
|
// warn the user that the count is too large
|
||||||
let mut total_tokens_deleted = 0;
|
let mut total_rooms_processed: usize = 0;
|
||||||
let mut error_count = 0;
|
let mut empty_rooms_processed: u32 = 0;
|
||||||
let mut skipped_rooms = 0;
|
let mut total_tokens_deleted: usize = 0;
|
||||||
|
let mut error_count: u32 = 0;
|
||||||
|
let mut skipped_rooms: u32 = 0;
|
||||||
|
|
||||||
info!("{} purge of sync tokens for rooms with no local users", mode);
|
info!("{} purge of sync tokens for rooms with no local users", mode);
|
||||||
|
|
||||||
|
@ -125,17 +137,24 @@ pub(super) async fn purge_empty_room_tokens(
|
||||||
// Filter rooms based on options
|
// Filter rooms based on options
|
||||||
let mut rooms = Vec::new();
|
let mut rooms = Vec::new();
|
||||||
for room_id in all_rooms {
|
for room_id in all_rooms {
|
||||||
// Filter rooms based on targeting options
|
if let Some(target) = &target_option {
|
||||||
let is_disabled = self.services.rooms.metadata.is_disabled(room_id).await;
|
match target {
|
||||||
let is_banned = self.services.rooms.metadata.is_banned(room_id).await;
|
| RoomTargetOption::DisabledOnly => {
|
||||||
|
if !self.services.rooms.metadata.is_disabled(room_id).await {
|
||||||
// If targeting specific types of rooms, only include matching rooms
|
debug!("Skipping room {} as it's not disabled", room_id);
|
||||||
if (target_disabled || target_banned)
|
skipped_rooms = skipped_rooms.saturating_add(1);
|
||||||
&& !((target_disabled && is_disabled) || (target_banned && is_banned))
|
continue;
|
||||||
{
|
}
|
||||||
debug!("Skipping room {} as it doesn't match targeting criteria", room_id);
|
},
|
||||||
skipped_rooms += 1;
|
| RoomTargetOption::BannedOnly => {
|
||||||
continue;
|
if !self.services.rooms.metadata.is_banned(room_id).await {
|
||||||
|
debug!("Skipping room {} as it's not banned", room_id);
|
||||||
|
skipped_rooms = skipped_rooms.saturating_add(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
| RoomTargetOption::All => {},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rooms.push(room_id);
|
rooms.push(room_id);
|
||||||
|
@ -150,7 +169,7 @@ pub(super) async fn purge_empty_room_tokens(
|
||||||
|
|
||||||
// Process each room
|
// Process each room
|
||||||
for room_id in rooms {
|
for room_id in rooms {
|
||||||
total_rooms_processed += 1;
|
total_rooms_processed = total_rooms_processed.saturating_add(1);
|
||||||
|
|
||||||
// Count local users in this room
|
// Count local users in this room
|
||||||
let local_users_count = self
|
let local_users_count = self
|
||||||
|
@ -163,7 +182,7 @@ pub(super) async fn purge_empty_room_tokens(
|
||||||
|
|
||||||
// Only process rooms with no local users
|
// Only process rooms with no local users
|
||||||
if local_users_count == 0 {
|
if local_users_count == 0 {
|
||||||
empty_rooms_processed += 1;
|
empty_rooms_processed = empty_rooms_processed.saturating_add(1);
|
||||||
|
|
||||||
// In dry run mode, just count what would be deleted, don't actually delete
|
// In dry run mode, just count what would be deleted, don't actually delete
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -182,13 +201,13 @@ pub(super) async fn purge_empty_room_tokens(
|
||||||
| Ok(count) =>
|
| Ok(count) =>
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
debug!("Would delete {} sync tokens for room {}", count, room_id);
|
debug!("Would delete {} sync tokens for room {}", count, room_id);
|
||||||
total_tokens_deleted += count;
|
total_tokens_deleted = total_tokens_deleted.saturating_add(count);
|
||||||
} else {
|
} else {
|
||||||
debug!("No sync tokens found for room {}", room_id);
|
debug!("No sync tokens found for room {}", room_id);
|
||||||
},
|
},
|
||||||
| Err(e) => {
|
| Err(e) => {
|
||||||
debug!("Error counting sync tokens for room {}: {:?}", room_id, e);
|
debug!("Error counting sync tokens for room {}: {:?}", room_id, e);
|
||||||
error_count += 1;
|
error_count = error_count.saturating_add(1);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -197,13 +216,13 @@ pub(super) async fn purge_empty_room_tokens(
|
||||||
| Ok(count) =>
|
| Ok(count) =>
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
debug!("Deleted {} sync tokens for room {}", count, room_id);
|
debug!("Deleted {} sync tokens for room {}", count, room_id);
|
||||||
total_tokens_deleted += count;
|
total_tokens_deleted = total_tokens_deleted.saturating_add(count);
|
||||||
} else {
|
} else {
|
||||||
debug!("No sync tokens found for room {}", room_id);
|
debug!("No sync tokens found for room {}", room_id);
|
||||||
},
|
},
|
||||||
| Err(e) => {
|
| Err(e) => {
|
||||||
debug!("Error purging sync tokens for room {}: {:?}", room_id, e);
|
debug!("Error purging sync tokens for room {}: {:?}", room_id, e);
|
||||||
error_count += 1;
|
error_count = error_count.saturating_add(1);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ mod info;
|
||||||
mod moderation;
|
mod moderation;
|
||||||
|
|
||||||
use clap::Subcommand;
|
use clap::Subcommand;
|
||||||
|
use commands::RoomTargetOption;
|
||||||
use conduwuit::Result;
|
use conduwuit::Result;
|
||||||
use ruma::{OwnedRoomId, OwnedRoomOrAliasId};
|
use ruma::{OwnedRoomId, OwnedRoomOrAliasId};
|
||||||
|
|
||||||
|
@ -22,13 +23,13 @@ pub(super) enum RoomCommand {
|
||||||
ListRooms {
|
ListRooms {
|
||||||
page: Option<usize>,
|
page: Option<usize>,
|
||||||
|
|
||||||
/// Only purge rooms that have federation disabled
|
/// Excludes rooms that we have federation disabled with
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
only_disabled: bool,
|
exclude_disabled: bool,
|
||||||
|
|
||||||
/// Only purge rooms that have been banned
|
/// Excludes rooms that we have banned
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
only_banned: bool,
|
exclude_banned: bool,
|
||||||
|
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
/// Whether to only output room IDs without supplementary room
|
/// Whether to only output room IDs without supplementary room
|
||||||
|
@ -66,21 +67,15 @@ pub(super) enum RoomCommand {
|
||||||
|
|
||||||
/// - Delete sync tokens for all rooms that have no local users
|
/// - Delete sync tokens for all rooms that have no local users
|
||||||
///
|
///
|
||||||
/// By default, processes all empty rooms. You can use --target-disabled
|
/// By default, processes all empty rooms.
|
||||||
/// and/or --target-banned to exclusively process rooms matching those
|
|
||||||
/// conditions.
|
|
||||||
PurgeEmptyRoomTokens {
|
PurgeEmptyRoomTokens {
|
||||||
/// Confirm you want to delete tokens from potentially many rooms
|
/// Confirm you want to delete tokens from potentially many rooms
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
yes: bool,
|
yes: bool,
|
||||||
|
|
||||||
/// Only purge rooms that have federation disabled
|
/// Target specific room types
|
||||||
#[arg(long)]
|
#[arg(long, value_enum)]
|
||||||
target_disabled: bool,
|
target_option: Option<RoomTargetOption>,
|
||||||
|
|
||||||
/// Only purge rooms that have been banned
|
|
||||||
#[arg(long)]
|
|
||||||
target_banned: bool,
|
|
||||||
|
|
||||||
/// Perform a dry run without actually deleting any tokens
|
/// Perform a dry run without actually deleting any tokens
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use axum::{Json, extract::State, response::IntoResponse};
|
use axum::{Json, extract::State, response::IntoResponse};
|
||||||
use conduwuit::{Error, Result};
|
use conduwuit::{Error, Result};
|
||||||
|
use futures::StreamExt;
|
||||||
use ruma::api::client::{
|
use ruma::api::client::{
|
||||||
discovery::{
|
discovery::{
|
||||||
discover_homeserver::{self, HomeserverInfo, SlidingSyncProxyInfo},
|
discover_homeserver::{self, HomeserverInfo, SlidingSyncProxyInfo},
|
||||||
|
@ -17,7 +18,7 @@ pub(crate) async fn well_known_client(
|
||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
_body: Ruma<discover_homeserver::Request>,
|
_body: Ruma<discover_homeserver::Request>,
|
||||||
) -> Result<discover_homeserver::Response> {
|
) -> Result<discover_homeserver::Response> {
|
||||||
let client_url = match services.server.config.well_known.client.as_ref() {
|
let client_url = match services.config.well_known.client.as_ref() {
|
||||||
| Some(url) => url.to_string(),
|
| Some(url) => url.to_string(),
|
||||||
| None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
|
| None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
|
||||||
};
|
};
|
||||||
|
@ -33,44 +34,63 @@ pub(crate) async fn well_known_client(
|
||||||
/// # `GET /.well-known/matrix/support`
|
/// # `GET /.well-known/matrix/support`
|
||||||
///
|
///
|
||||||
/// Server support contact and support page of a homeserver's domain.
|
/// Server support contact and support page of a homeserver's domain.
|
||||||
|
/// Implements MSC1929 for server discovery.
|
||||||
|
/// If no configuration is set, uses admin users as contacts.
|
||||||
pub(crate) async fn well_known_support(
|
pub(crate) async fn well_known_support(
|
||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
_body: Ruma<discover_support::Request>,
|
_body: Ruma<discover_support::Request>,
|
||||||
) -> Result<discover_support::Response> {
|
) -> Result<discover_support::Response> {
|
||||||
let support_page = services
|
let support_page = services
|
||||||
.server
|
|
||||||
.config
|
.config
|
||||||
.well_known
|
.well_known
|
||||||
.support_page
|
.support_page
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(ToString::to_string);
|
.map(ToString::to_string);
|
||||||
|
|
||||||
let role = services.server.config.well_known.support_role.clone();
|
let email_address = services.config.well_known.support_email.clone();
|
||||||
|
let matrix_id = services.config.well_known.support_mxid.clone();
|
||||||
// support page or role must be either defined for this to be valid
|
|
||||||
if support_page.is_none() && role.is_none() {
|
|
||||||
return Err(Error::BadRequest(ErrorKind::NotFound, "Not found."));
|
|
||||||
}
|
|
||||||
|
|
||||||
let email_address = services.server.config.well_known.support_email.clone();
|
|
||||||
let matrix_id = services.server.config.well_known.support_mxid.clone();
|
|
||||||
|
|
||||||
// if a role is specified, an email address or matrix id is required
|
|
||||||
if role.is_some() && (email_address.is_none() && matrix_id.is_none()) {
|
|
||||||
return Err(Error::BadRequest(ErrorKind::NotFound, "Not found."));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: support defining multiple contacts in the config
|
// TODO: support defining multiple contacts in the config
|
||||||
let mut contacts: Vec<Contact> = vec![];
|
let mut contacts: Vec<Contact> = vec![];
|
||||||
|
|
||||||
if let Some(role) = role {
|
let role_value = services
|
||||||
let contact = Contact { role, email_address, matrix_id };
|
.config
|
||||||
|
.well_known
|
||||||
|
.support_role
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| "m.role.admin".to_owned().into());
|
||||||
|
|
||||||
contacts.push(contact);
|
// Add configured contact if at least one contact method is specified
|
||||||
|
if email_address.is_some() || matrix_id.is_some() {
|
||||||
|
contacts.push(Contact {
|
||||||
|
role: role_value.clone(),
|
||||||
|
email_address: email_address.clone(),
|
||||||
|
matrix_id: matrix_id.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to add admin users as contacts if no contacts are configured
|
||||||
|
if contacts.is_empty() {
|
||||||
|
if let Ok(admin_room) = services.admin.get_admin_room().await {
|
||||||
|
let admin_users = services.rooms.state_cache.room_members(&admin_room);
|
||||||
|
let mut stream = admin_users;
|
||||||
|
|
||||||
|
while let Some(user_id) = stream.next().await {
|
||||||
|
// Skip server user
|
||||||
|
if *user_id == services.globals.server_user {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
contacts.push(Contact {
|
||||||
|
role: role_value.clone(),
|
||||||
|
email_address: None,
|
||||||
|
matrix_id: Some(user_id.to_owned()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// support page or role+contacts must be either defined for this to be valid
|
|
||||||
if contacts.is_empty() && support_page.is_none() {
|
if contacts.is_empty() && support_page.is_none() {
|
||||||
|
// No admin room, no configured contacts, and no support page
|
||||||
return Err(Error::BadRequest(ErrorKind::NotFound, "Not found."));
|
return Err(Error::BadRequest(ErrorKind::NotFound, "Not found."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,9 +104,9 @@ pub(crate) async fn well_known_support(
|
||||||
pub(crate) async fn syncv3_client_server_json(
|
pub(crate) async fn syncv3_client_server_json(
|
||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
) -> Result<impl IntoResponse> {
|
) -> Result<impl IntoResponse> {
|
||||||
let server_url = match services.server.config.well_known.client.as_ref() {
|
let server_url = match services.config.well_known.client.as_ref() {
|
||||||
| Some(url) => url.to_string(),
|
| Some(url) => url.to_string(),
|
||||||
| None => match services.server.config.well_known.server.as_ref() {
|
| None => match services.config.well_known.server.as_ref() {
|
||||||
| Some(url) => url.to_string(),
|
| Some(url) => url.to_string(),
|
||||||
| None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
|
| None => return Err(Error::BadRequest(ErrorKind::NotFound, "Not found.")),
|
||||||
},
|
},
|
||||||
|
|
|
@ -1897,12 +1897,28 @@ pub struct WellKnownConfig {
|
||||||
/// example: "matrix.example.com:443"
|
/// example: "matrix.example.com:443"
|
||||||
pub server: Option<OwnedServerName>,
|
pub server: Option<OwnedServerName>,
|
||||||
|
|
||||||
|
/// URL to a support page for the server, which will be served as part of
|
||||||
|
/// the MSC1929 server support endpoint at /.well-known/matrix/support.
|
||||||
|
/// Will be included alongside any contact information
|
||||||
pub support_page: Option<Url>,
|
pub support_page: Option<Url>,
|
||||||
|
|
||||||
|
/// Role string for server support contacts, to be served as part of the
|
||||||
|
/// MSC1929 server support endpoint at /.well-known/matrix/support.
|
||||||
|
///
|
||||||
|
/// default: "m.role.admin"
|
||||||
pub support_role: Option<ContactRole>,
|
pub support_role: Option<ContactRole>,
|
||||||
|
|
||||||
|
/// Email address for server support contacts, to be served as part of the
|
||||||
|
/// MSC1929 server support endpoint.
|
||||||
|
/// This will be used along with support_mxid if specified.
|
||||||
pub support_email: Option<String>,
|
pub support_email: Option<String>,
|
||||||
|
|
||||||
|
/// Matrix ID for server support contacts, to be served as part of the
|
||||||
|
/// MSC1929 server support endpoint.
|
||||||
|
/// This will be used along with support_email if specified.
|
||||||
|
///
|
||||||
|
/// If no email or mxid is specified, all of the server's admins will be
|
||||||
|
/// listed.
|
||||||
pub support_mxid: Option<OwnedUserId>,
|
pub support_mxid: Option<OwnedUserId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -166,9 +166,6 @@ pub async fn delete_room_tokens(&self, room_id: &RoomId) -> Result<usize> {
|
||||||
// short ID
|
// short ID
|
||||||
let prefix = &[shortroomid];
|
let prefix = &[shortroomid];
|
||||||
|
|
||||||
// Get all keys with this room prefix
|
|
||||||
let mut count = 0;
|
|
||||||
|
|
||||||
// Collect all keys into a Vec first, then delete them
|
// Collect all keys into a Vec first, then delete them
|
||||||
let keys = self
|
let keys = self
|
||||||
.db
|
.db
|
||||||
|
@ -184,8 +181,9 @@ pub async fn delete_room_tokens(&self, room_id: &RoomId) -> Result<usize> {
|
||||||
// Delete each key individually
|
// Delete each key individually
|
||||||
for key in &keys {
|
for key in &keys {
|
||||||
self.db.roomsynctoken_shortstatehash.del(key);
|
self.db.roomsynctoken_shortstatehash.del(key);
|
||||||
count += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let count = keys.len();
|
||||||
|
|
||||||
Ok(count)
|
Ok(count)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue