mirror of
https://github.com/stoatchat/stoatchat.git
synced 2026-08-31 08:12:31 +00:00
Merge remote-tracking branch 'origin/main' into feat/elasticsearch
Signed-off-by: Zomatree <me@zomatree.live>
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
{
|
||||
".": "0.14.3"
|
||||
".": "0.15.0"
|
||||
}
|
||||
13
CHANGELOG.md
13
CHANGELOG.md
@@ -1,5 +1,18 @@
|
||||
# Changelog
|
||||
|
||||
## [0.15.0](https://github.com/stoatchat/stoatchat/compare/v0.14.3...v0.15.0) (2026-08-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add an approximate member count to servers ([#884](https://github.com/stoatchat/stoatchat/issues/884)) ([ccfb5f1](https://github.com/stoatchat/stoatchat/commit/ccfb5f1a62f1be9177ac9c1c09fd18ea8e9c7f18))
|
||||
* add call event ([#873](https://github.com/stoatchat/stoatchat/issues/873)) ([457c770](https://github.com/stoatchat/stoatchat/commit/457c7709c75060cd8519cc45df3badcfc1b629ea))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* rewrite youtube embedder to use youtube oembed ([#878](https://github.com/stoatchat/stoatchat/issues/878)) ([0369451](https://github.com/stoatchat/stoatchat/commit/03694512b90be90367299c3ebfb072ebbc8a681d))
|
||||
|
||||
## [0.14.3](https://github.com/stoatchat/stoatchat/compare/v0.14.2...v0.14.3) (2026-07-22)
|
||||
|
||||
|
||||
|
||||
36
Cargo.lock
generated
36
Cargo.lock
generated
@@ -7257,7 +7257,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-autumn"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum-macros",
|
||||
@@ -7298,7 +7298,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-bonfire"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-tungstenite",
|
||||
@@ -7329,7 +7329,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-coalesced"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"indexmap 2.14.0",
|
||||
"lru",
|
||||
@@ -7338,7 +7338,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-config"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"cached",
|
||||
"config",
|
||||
@@ -7354,7 +7354,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-crond"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"futures-lite",
|
||||
@@ -7375,7 +7375,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-database"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-lock 2.8.0",
|
||||
@@ -7434,7 +7434,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-delta"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"bitfield",
|
||||
@@ -7482,7 +7482,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-files"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"anyhow",
|
||||
@@ -7510,7 +7510,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-gifbox"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum-extra",
|
||||
@@ -7533,7 +7533,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-january"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"async-recursion",
|
||||
"axum",
|
||||
@@ -7563,7 +7563,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-models"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"indexmap 2.14.0",
|
||||
"iso8601-timestamp",
|
||||
@@ -7583,14 +7583,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-parser"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"logos",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "revolt-permissions"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"auto_ops",
|
||||
@@ -7605,7 +7605,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-presence"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
@@ -7617,7 +7617,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-pushd"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -7647,7 +7647,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-ratelimits"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum",
|
||||
@@ -7663,7 +7663,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-result"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"log",
|
||||
@@ -7711,7 +7711,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "revolt-voice-ingress"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"futures",
|
||||
|
||||
22
Cargo.toml
22
Cargo.toml
@@ -197,14 +197,14 @@ futures-lite = "2.6.1"
|
||||
vergen = "7.5.0"
|
||||
|
||||
# Local packages
|
||||
revolt-coalesced = { version = "0.14.3", path = "crates/core/coalesced" }
|
||||
revolt-config = { version = "0.14.3", path = "crates/core/config" }
|
||||
revolt-database = { version = "0.14.3", path = "crates/core/database" }
|
||||
revolt-files = { version = "0.14.3", path = "crates/core/files" }
|
||||
revolt-models = { version = "0.14.3", path = "crates/core/models" }
|
||||
revolt-parser = { version = "0.14.3", path = "crates/core/parser" }
|
||||
revolt-permissions = { version = "0.14.3", path = "crates/core/permissions" }
|
||||
revolt-presence = { version = "0.14.3", path = "crates/core/presence" }
|
||||
revolt-ratelimits = { version = "0.14.3", path = "crates/core/ratelimits" }
|
||||
revolt-result = { version = "0.14.3", path = "crates/core/result" }
|
||||
revolt-search = { version = "0.13.7", path = "crates/core/search" }
|
||||
revolt-coalesced = { version = "0.15.0", path = "crates/core/coalesced" }
|
||||
revolt-config = { version = "0.15.0", path = "crates/core/config" }
|
||||
revolt-database = { version = "0.15.0", path = "crates/core/database" }
|
||||
revolt-files = { version = "0.15.0", path = "crates/core/files" }
|
||||
revolt-models = { version = "0.15.0", path = "crates/core/models" }
|
||||
revolt-parser = { version = "0.15.0", path = "crates/core/parser" }
|
||||
revolt-permissions = { version = "0.15.0", path = "crates/core/permissions" }
|
||||
revolt-presence = { version = "0.15.0", path = "crates/core/presence" }
|
||||
revolt-ratelimits = { version = "0.15.0", path = "crates/core/ratelimits" }
|
||||
revolt-result = { version = "0.15.0", path = "crates/core/result" }
|
||||
revolt-search = { version = "0.15.0", path = "crates/core/search" }
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-bonfire"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
license = "AGPL-3.0-or-later"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
@@ -307,7 +307,7 @@ impl State {
|
||||
Ok(EventV1::Ready {
|
||||
users: if fields.users { Some(users) } else { None },
|
||||
servers: if fields.servers {
|
||||
Some(servers.into_iter().map(Into::into).collect())
|
||||
Some(join_all(servers.into_iter().map(|server| server.into(db))).await)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-coalesced"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Paul Makles <me@insrt.uk>", "Zomatree <me@zomatree.live>"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-config"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -70,6 +70,8 @@ trust_cloudflare = false
|
||||
easypwned = ""
|
||||
# Tenor API Key
|
||||
tenor_key = ""
|
||||
# Admin keys for future admin api and for bonfire reported image fetching
|
||||
admin_keys = []
|
||||
|
||||
[api.security.captcha]
|
||||
# hCaptcha configuration
|
||||
|
||||
@@ -228,6 +228,7 @@ pub struct ApiSecurity {
|
||||
pub trust_cloudflare: bool,
|
||||
pub easypwned: String,
|
||||
pub tenor_key: String,
|
||||
pub admin_keys: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-database"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -176,7 +176,7 @@ impl Member {
|
||||
|
||||
EventV1::ServerCreate {
|
||||
id: server.id.clone(),
|
||||
server: server.clone().into(),
|
||||
server: server.clone().into(db).await,
|
||||
channels: channels
|
||||
.clone()
|
||||
.into_iter()
|
||||
@@ -317,9 +317,15 @@ impl Member {
|
||||
})
|
||||
{
|
||||
match intention {
|
||||
RemovalIntention::Leave => SystemMessage::UserLeft { id: self.id.user.clone() },
|
||||
RemovalIntention::Kick => SystemMessage::UserKicked { id: self.id.user.clone() },
|
||||
RemovalIntention::Ban => SystemMessage::UserBanned { id: self.id.user.clone() },
|
||||
RemovalIntention::Leave => SystemMessage::UserLeft {
|
||||
id: self.id.user.clone(),
|
||||
},
|
||||
RemovalIntention::Kick => SystemMessage::UserKicked {
|
||||
id: self.id.user.clone(),
|
||||
},
|
||||
RemovalIntention::Ban => SystemMessage::UserBanned {
|
||||
id: self.id.user.clone(),
|
||||
},
|
||||
}
|
||||
.into_message(id.to_string())
|
||||
// TODO: support notifications here in the future?
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use revolt_config::capture_error;
|
||||
use redis_kiss::{
|
||||
get_connection,
|
||||
redis::{SetExpiry, SetOptions},
|
||||
AsyncCommands,
|
||||
};
|
||||
use revolt_models::v0::{self, DataCreateServerChannel};
|
||||
use revolt_permissions::{OverrideField, DEFAULT_PERMISSION_SERVER};
|
||||
use revolt_result::Result;
|
||||
@@ -332,6 +337,30 @@ impl Server {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets a approximate count of the members in this server
|
||||
///
|
||||
/// this value is cached for one hour
|
||||
pub async fn get_approximate_member_count(&self, db: &Database) -> usize {
|
||||
let Ok(mut redis) = get_connection().await else {
|
||||
return 0;
|
||||
};
|
||||
let key = format!("member_count:{}", &self.id);
|
||||
|
||||
if let Some(count) = redis.get::<_, Option<usize>>(&key).await.ok().flatten() {
|
||||
count
|
||||
} else {
|
||||
let count = db.fetch_member_count(&self.id).await.unwrap_or(0);
|
||||
let _ = redis
|
||||
.set_options::<_, _, ()>(
|
||||
&key,
|
||||
count,
|
||||
SetOptions::default().with_expiration(SetExpiry::EX(60 * 60)),
|
||||
)
|
||||
.await;
|
||||
count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Role {
|
||||
|
||||
@@ -751,30 +751,29 @@ impl From<crate::RemovalIntention> for RemovalIntention {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::Server> for Server {
|
||||
fn from(value: crate::Server) -> Self {
|
||||
impl crate::Server {
|
||||
pub async fn into(self, db: &Database) -> Server {
|
||||
let approximate_member_count = self.get_approximate_member_count(db).await;
|
||||
|
||||
Server {
|
||||
id: value.id,
|
||||
owner: value.owner,
|
||||
name: value.name,
|
||||
description: value.description,
|
||||
channels: value.channels,
|
||||
categories: value
|
||||
id: self.id,
|
||||
owner: self.owner,
|
||||
name: self.name,
|
||||
description: self.description,
|
||||
channels: self.channels,
|
||||
categories: self
|
||||
.categories
|
||||
.map(|categories| categories.into_iter().map(|v| v.into()).collect()),
|
||||
system_messages: value.system_messages.map(|v| v.into()),
|
||||
roles: value
|
||||
.roles
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v.into()))
|
||||
.collect(),
|
||||
default_permissions: value.default_permissions,
|
||||
icon: value.icon.map(|f| f.into()),
|
||||
banner: value.banner.map(|f| f.into()),
|
||||
flags: value.flags.unwrap_or_default() as u32,
|
||||
nsfw: value.nsfw,
|
||||
analytics: value.analytics,
|
||||
discoverable: value.discoverable,
|
||||
system_messages: self.system_messages.map(|v| v.into()),
|
||||
roles: self.roles.into_iter().map(|(k, v)| (k, v.into())).collect(),
|
||||
default_permissions: self.default_permissions,
|
||||
icon: self.icon.map(|f| f.into()),
|
||||
banner: self.banner.map(|f| f.into()),
|
||||
flags: self.flags.unwrap_or_default() as u32,
|
||||
nsfw: self.nsfw,
|
||||
analytics: self.analytics,
|
||||
discoverable: self.discoverable,
|
||||
approximate_member_count,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -829,6 +828,7 @@ impl From<crate::PartialServer> for PartialServer {
|
||||
nsfw: value.nsfw,
|
||||
analytics: value.analytics,
|
||||
discoverable: value.discoverable,
|
||||
approximate_member_count: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-files"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-models"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -78,6 +78,9 @@ auto_derived_partial!(
|
||||
serde(skip_serializing_if = "crate::if_false", default)
|
||||
)]
|
||||
pub discoverable: bool,
|
||||
|
||||
/// Approximate amount of members in the server
|
||||
pub approximate_member_count: usize,
|
||||
},
|
||||
"PartialServer"
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-parser"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Zomatree <me@zomatree.live>", "Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-permissions"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-presence"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-ratelimits"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
authors = ["Zomatree <me@zomatree.live>", "Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-result"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-crond"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <me@insrt.uk>"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-pushd"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
publish = false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-voice-ingress"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
license = "AGPL-3.0-or-later"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-delta"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
license = "AGPL-3.0-or-later"
|
||||
authors = ["Paul Makles <paulmakles@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
@@ -28,7 +28,7 @@ pub async fn fetch(db: &State<Database>, target: Reference<'_>) -> Result<Json<v
|
||||
|
||||
v0::InviteResponse::Server {
|
||||
code: target.id.to_string(),
|
||||
member_count: db.fetch_member_count(&server.id).await? as i64,
|
||||
member_count: server.get_approximate_member_count(db).await as i64,
|
||||
server_id: server.id,
|
||||
server_name: server.name,
|
||||
server_icon: server.icon.map(|f| f.into()),
|
||||
|
||||
@@ -28,7 +28,7 @@ pub async fn join(
|
||||
|
||||
Ok(Json(InviteJoinResponse::Server {
|
||||
channels: channels.into_iter().map(|c| c.into()).collect(),
|
||||
server: server.into(),
|
||||
server: server.into(db).await,
|
||||
}))
|
||||
}
|
||||
Invite::Group {
|
||||
|
||||
@@ -78,5 +78,5 @@ pub async fn set_role_permission(
|
||||
sync_voice_permissions(db, voice_client, &channel, Some(&server), Some(&role_id)).await?;
|
||||
}
|
||||
|
||||
Ok(Json(server.into()))
|
||||
Ok(Json(server.into(db).await))
|
||||
}
|
||||
|
||||
@@ -66,5 +66,5 @@ pub async fn set_default_server_permissions(
|
||||
sync_voice_permissions(db, voice_client, &channel, Some(&server), None).await?;
|
||||
}
|
||||
|
||||
Ok(Json(server.into()))
|
||||
Ok(Json(server.into(db).await))
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ pub async fn edit_role_ranks(
|
||||
sync_voice_permissions(db, voice_client, &channel, Some(&server), None).await?;
|
||||
}
|
||||
|
||||
Ok(Json(server.into()))
|
||||
Ok(Json(server.into(db).await))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -52,7 +52,7 @@ pub async fn create_server(
|
||||
let (_, channels) = Member::create(db, &server, &user, Some(channels)).await?;
|
||||
|
||||
Ok(Json(v0::CreateServerLegacyResponse {
|
||||
server: server.into(),
|
||||
server: server.into(db).await,
|
||||
channels: channels.into_iter().map(|channel| channel.into()).collect(),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::collections::HashSet;
|
||||
|
||||
use revolt_database::{
|
||||
util::{permissions::DatabasePermissionQuery, reference::Reference},
|
||||
AuditLogEntryAction, Database, FieldsServer, File, PartialServer, User, ValidatedTicket
|
||||
AuditLogEntryAction, Database, FieldsServer, File, PartialServer, User, ValidatedTicket,
|
||||
};
|
||||
use revolt_models::v0;
|
||||
use revolt_permissions::{calculate_server_permissions, ChannelPermission};
|
||||
@@ -50,7 +50,7 @@ pub async fn edit(
|
||||
&& data.owner.is_none()
|
||||
&& data.remove.is_empty()
|
||||
{
|
||||
return Ok(Json(server.into()));
|
||||
return Ok(Json(server.into(db).await));
|
||||
} else if data.name.is_some()
|
||||
|| data.description.is_some()
|
||||
|| data.icon.is_some()
|
||||
@@ -195,5 +195,5 @@ pub async fn edit(
|
||||
.insert(db, server.id.clone(), reason, user.id, None)
|
||||
.await;
|
||||
|
||||
Ok(Json(server.into()))
|
||||
Ok(Json(server.into(db).await))
|
||||
}
|
||||
|
||||
@@ -39,10 +39,12 @@ pub async fn fetch(
|
||||
}
|
||||
|
||||
Ok(Json(v0::FetchServerResponse::ServerWithChannels {
|
||||
server: server.into(),
|
||||
server: server.into(db).await,
|
||||
channels: visible_channels,
|
||||
}))
|
||||
} else {
|
||||
Ok(Json(v0::FetchServerResponse::JustServer(server.into())))
|
||||
Ok(Json(v0::FetchServerResponse::JustServer(
|
||||
server.into(db).await,
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-autumn"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
publish = false
|
||||
|
||||
@@ -5,7 +5,7 @@ use std::{
|
||||
|
||||
use axum::{
|
||||
extract::{DefaultBodyLimit, Path, State},
|
||||
http::{header, Method},
|
||||
http::{header, HeaderMap, Method},
|
||||
response::{IntoResponse, Redirect, Response},
|
||||
routing::{get, post},
|
||||
Json, Router,
|
||||
@@ -58,6 +58,7 @@ pub async fn router() -> Router<AppState> {
|
||||
)
|
||||
.route("/:tag/:file_id", get(fetch_preview))
|
||||
.route("/:tag/:file_id/:file_name", get(fetch_file))
|
||||
.route("/mod/:tag/:file_id/:file_name", get(fetch_file_mod))
|
||||
.layer(cors)
|
||||
}
|
||||
|
||||
@@ -503,3 +504,67 @@ async fn fetch_file(
|
||||
.into_response()
|
||||
})
|
||||
}
|
||||
|
||||
/// Fetch original file (Moderation)
|
||||
///
|
||||
/// This is intentionally left out of the OpenApi docs.
|
||||
/// It uses the config key api.security.admin_keys to determine access. This is intended for server to server communication.
|
||||
async fn fetch_file_mod(
|
||||
State(db): State<Database>,
|
||||
headers: HeaderMap,
|
||||
Path((tag, file_id, file_name)): Path<(Tag, String, String)>,
|
||||
) -> Result<Response> {
|
||||
let config = revolt_config::config().await;
|
||||
|
||||
let token = headers
|
||||
.get("X-Admin-Token")
|
||||
.and_then(|value| value.to_str().ok())
|
||||
.ok_or_else(|| create_error!(NotAuthenticated))?;
|
||||
|
||||
if !config
|
||||
.api
|
||||
.security
|
||||
.admin_keys
|
||||
.iter()
|
||||
.any(|tok| tok == token)
|
||||
{
|
||||
return Err(create_error!(NotAuthenticated));
|
||||
}
|
||||
|
||||
let tag: &'static str = tag.clone().into();
|
||||
let file = db.fetch_attachment(tag, &file_id).await?;
|
||||
|
||||
// Ignore files that haven't been attached
|
||||
if file.used_for.is_none() {
|
||||
return Err(create_error!(NotFound));
|
||||
}
|
||||
|
||||
// Ensure filename is correct
|
||||
if file_name != file.filename {
|
||||
if file_name == "original" {
|
||||
let safe_filename = encode_component(&file.filename);
|
||||
|
||||
return Ok(
|
||||
Redirect::permanent(&format!("/{tag}/{file_id}/{}", safe_filename)).into_response(),
|
||||
);
|
||||
}
|
||||
|
||||
return Err(create_error!(NotFound));
|
||||
}
|
||||
|
||||
let hash = file.as_hash(&db).await?;
|
||||
retrieve_file_by_hash(&hash).await.map(|data| {
|
||||
(
|
||||
[
|
||||
(header::CONTENT_TYPE, hash.content_type),
|
||||
(header::CONTENT_DISPOSITION, "attachment".to_owned()),
|
||||
(
|
||||
header::CACHE_CONTROL,
|
||||
"private, max-age=300, must-revalidate".to_owned(),
|
||||
),
|
||||
],
|
||||
data,
|
||||
)
|
||||
.into_response()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-gifbox"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
publish = false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "revolt-january"
|
||||
version = "0.14.3"
|
||||
version = "0.15.0"
|
||||
edition = "2021"
|
||||
license = "AGPL-3.0-or-later"
|
||||
publish = false
|
||||
|
||||
@@ -25,7 +25,8 @@ pub async fn create_website_embed(original_url: &str, document: &str) -> Option<
|
||||
node.attr("property").or_else(|| node.attr("name")),
|
||||
node.attr("content"),
|
||||
) {
|
||||
meta.insert(property.to_string(), content.to_string());
|
||||
meta.entry(property.to_string())
|
||||
.or_insert(content.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
0.14.3
|
||||
0.15.0
|
||||
|
||||
Reference in New Issue
Block a user