Merge branch '2-refactor-core-files' into 3-otel

This commit is contained in:
izzy
2026-01-25 19:49:08 +00:00
10 changed files with 81 additions and 170 deletions

161
Cargo.lock generated
View File

@@ -4671,7 +4671,7 @@ dependencies = [
"log",
"parking_lot",
"pbjson-types",
"prost 0.12.6",
"prost",
"rand 0.9.2",
"reqwest 0.11.27",
"scopeguard",
@@ -4693,7 +4693,7 @@ dependencies = [
"parking_lot",
"pbjson",
"pbjson-types",
"prost 0.12.6",
"prost",
"prost-types",
"serde",
"thiserror 1.0.69",
@@ -5484,90 +5484,6 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "opentelemetry"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0"
dependencies = [
"futures-core",
"futures-sink",
"js-sys",
"pin-project-lite 0.2.16",
"thiserror 2.0.18",
"tracing",
]
[[package]]
name = "opentelemetry-appender-tracing"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef6a1ac5ca3accf562b8c306fa8483c85f4390f768185ab775f242f7fe8fdcc2"
dependencies = [
"opentelemetry",
"tracing",
"tracing-core",
"tracing-subscriber",
]
[[package]]
name = "opentelemetry-http"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d"
dependencies = [
"async-trait",
"bytes 1.10.1",
"http 1.3.1",
"opentelemetry",
"reqwest 0.12.23",
]
[[package]]
name = "opentelemetry-otlp"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2366db2dca4d2ad033cad11e6ee42844fd727007af5ad04a1730f4cb8163bf"
dependencies = [
"http 1.3.1",
"opentelemetry",
"opentelemetry-http",
"opentelemetry-proto",
"opentelemetry_sdk",
"prost 0.14.3",
"reqwest 0.12.23",
"thiserror 2.0.18",
"tracing",
]
[[package]]
name = "opentelemetry-proto"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f"
dependencies = [
"opentelemetry",
"opentelemetry_sdk",
"prost 0.14.3",
"tonic",
"tonic-prost",
]
[[package]]
name = "opentelemetry_sdk"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd"
dependencies = [
"futures-channel",
"futures-executor",
"futures-util",
"opentelemetry",
"percent-encoding",
"rand 0.9.2",
"thiserror 2.0.18",
]
[[package]]
name = "ordered-multimap"
version = "0.4.3"
@@ -5696,7 +5612,7 @@ checksum = "2580e33f2292d34be285c5bc3dba5259542b083cfad6037b6d70345f24dcb735"
dependencies = [
"heck 0.4.1",
"itertools 0.11.0",
"prost 0.12.6",
"prost",
"prost-types",
]
@@ -5710,7 +5626,7 @@ dependencies = [
"chrono",
"pbjson",
"pbjson-build",
"prost 0.12.6",
"prost",
"prost-build",
"serde",
]
@@ -6293,17 +6209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29"
dependencies = [
"bytes 1.10.1",
"prost-derive 0.12.6",
]
[[package]]
name = "prost"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568"
dependencies = [
"bytes 1.10.1",
"prost-derive 0.14.3",
"prost-derive",
]
[[package]]
@@ -6320,7 +6226,7 @@ dependencies = [
"once_cell",
"petgraph",
"prettyplease",
"prost 0.12.6",
"prost",
"prost-types",
"regex",
"syn 2.0.106",
@@ -6340,26 +6246,13 @@ dependencies = [
"syn 2.0.106",
]
[[package]]
name = "prost-derive"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b"
dependencies = [
"anyhow",
"itertools 0.14.0",
"proc-macro2",
"quote 1.0.40",
"syn 2.0.106",
]
[[package]]
name = "prost-types"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0"
dependencies = [
"prost 0.12.6",
"prost",
]
[[package]]
@@ -6849,9 +6742,7 @@ dependencies = [
"base64 0.22.1",
"bytes 1.10.1",
"encoding_rs",
"futures-channel",
"futures-core",
"futures-util",
"h2 0.4.12",
"http 1.3.1",
"http-body 1.0.1",
@@ -6921,10 +6812,6 @@ dependencies = [
"lazy_static",
"moka",
"nanoid",
"opentelemetry",
"opentelemetry-appender-tracing",
"opentelemetry-otlp",
"opentelemetry_sdk",
"revolt-config",
"revolt-database",
"revolt-files",
@@ -7161,6 +7048,7 @@ dependencies = [
"serde",
"serde_json",
"tokio 1.49.0",
"tower-http 0.5.2",
"tracing",
"utoipa",
"utoipa-scalar",
@@ -9217,38 +9105,6 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
[[package]]
name = "tonic"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203"
dependencies = [
"async-trait",
"base64 0.22.1",
"bytes 1.10.1",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"percent-encoding",
"pin-project",
"sync_wrapper 1.0.2",
"tokio-stream",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tonic-prost"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67"
dependencies = [
"bytes 1.10.1",
"prost 0.14.3",
"tonic",
]
[[package]]
name = "totp-lite"
version = "2.0.1"
@@ -9291,7 +9147,6 @@ dependencies = [
"pin-project-lite 0.2.16",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]

View File

@@ -72,6 +72,7 @@ auto_derived!(
CanReceive,
CanPublish,
JoinedAt,
VoiceChannel,
}
/// Member removal intention
@@ -224,13 +225,14 @@ impl Member {
pub fn remove_field(&mut self, field: &FieldsMember) {
match field {
FieldsMember::JoinedAt => (),
FieldsMember::JoinedAt => {},
FieldsMember::Avatar => self.avatar = None,
FieldsMember::Nickname => self.nickname = None,
FieldsMember::Roles => self.roles.clear(),
FieldsMember::Timeout => self.timeout = None,
FieldsMember::CanReceive => self.can_receive = true,
FieldsMember::CanPublish => self.can_publish = true,
FieldsMember::VoiceChannel => {},
}
}

View File

@@ -330,14 +330,15 @@ impl AbstractServerMembers for MongoDb {
impl IntoDocumentPath for FieldsMember {
fn as_path(&self) -> Option<&'static str> {
Some(match self {
FieldsMember::JoinedAt => "joined_at",
FieldsMember::Avatar => "avatar",
FieldsMember::Nickname => "nickname",
FieldsMember::Roles => "roles",
FieldsMember::Timeout => "timeout",
FieldsMember::CanPublish => "can_publish",
FieldsMember::CanReceive => "can_receive",
})
match self {
FieldsMember::JoinedAt => Some("joined_at"),
FieldsMember::Avatar => Some("avatar"),
FieldsMember::Nickname => Some("nickname"),
FieldsMember::Roles => Some("roles"),
FieldsMember::Timeout => Some("timeout"),
FieldsMember::CanPublish => Some("can_publish"),
FieldsMember::CanReceive => Some("can_receive"),
FieldsMember::VoiceChannel => None,
}
}
}

View File

@@ -691,6 +691,7 @@ impl From<crate::FieldsMember> for FieldsMember {
crate::FieldsMember::CanReceive => FieldsMember::CanReceive,
crate::FieldsMember::CanPublish => FieldsMember::CanPublish,
crate::FieldsMember::JoinedAt => FieldsMember::JoinedAt,
crate::FieldsMember::VoiceChannel => FieldsMember::VoiceChannel,
}
}
}
@@ -705,6 +706,7 @@ impl From<FieldsMember> for crate::FieldsMember {
FieldsMember::CanReceive => crate::FieldsMember::CanReceive,
FieldsMember::CanPublish => crate::FieldsMember::CanPublish,
FieldsMember::JoinedAt => crate::FieldsMember::JoinedAt,
FieldsMember::VoiceChannel => crate::FieldsMember::VoiceChannel,
}
}
}

View File

@@ -95,6 +95,7 @@ auto_derived!(
CanReceive,
CanPublish,
JoinedAt,
VoiceChannel,
}
/// Member removal intention

View File

@@ -70,6 +70,15 @@ pub async fn web() -> Rocket<Build> {
.iter()
.map(|s| FromStr::from_str(s).unwrap())
.collect(),
expose_headers: [
"X-Ratelimit-Limit",
"X-Ratelimit-Bucket",
"X-Ratelimit-Remaining",
"X-Ratelimit-Reset-After",
]
.iter()
.map(|s| s.to_string())
.collect(),
..Default::default()
}
.to_cors()

View File

@@ -98,13 +98,21 @@ pub async fn edit(
permissions.throw_if_lacking_channel_permission(ChannelPermission::DeafenMembers)?;
}
let new_voice_channel = if let Some(new_channel) = &data.voice_channel {
if data.voice_channel.is_some() && data.remove.contains(&FieldsMember::VoiceChannel) {
return Err(create_error!(InvalidOperation))
}
if data.voice_channel.is_some() || data.remove.contains(&FieldsMember::VoiceChannel) {
if !voice_client.is_enabled() {
return Err(create_error!(LiveKitUnavailable));
};
permissions.throw_if_lacking_channel_permission(ChannelPermission::MoveMembers)?;
if member.id.user != user.id {
permissions.throw_if_lacking_channel_permission(ChannelPermission::MoveMembers)?;
}
}
let new_voice_channel = if let Some(new_channel) = &data.voice_channel {
// ensure the channel we are moving them to is in the server and is a voice channel
let channel = Reference::from_unchecked(new_channel)
@@ -116,6 +124,9 @@ pub async fn edit(
Err(create_error!(UnknownChannel))?
}
let channel_permissions = calculate_channel_permissions(&mut query.clone().channel(&channel)).await;
channel_permissions.throw_if_lacking_channel_permission(ChannelPermission::Connect)?;
if get_user_voice_channel_in_server(&target_user.id, &server.id)
.await?
.is_none()
@@ -189,10 +200,8 @@ pub async fn edit(
partial.avatar = Some(File::use_user_avatar(db, &avatar, &user.id, &user.id).await?);
}
let remove_contains_voice = remove.contains(FieldsMember::CanPublish) || remove.contains(FieldsMember::CanReceive);
member
.update(db, partial, remove.into_iter().map(Into::into).collect())
.update(db, partial, remove.clone().into_iter().map(Into::into).collect())
.await?;
if let Some(new_voice_channel) = new_voice_channel {
@@ -234,7 +243,7 @@ pub async fn edit(
.private(target_user.id.clone())
.await;
};
} else if can_publish.is_some() || can_receive.is_some() || remove_contains_voice {
} else if can_publish.is_some() || can_receive.is_some() || remove.contains(FieldsMember::CanPublish) || remove.contains(FieldsMember::CanReceive) {
if let Some(channel) = get_user_voice_channel_in_server(&target_user.id, &server.id).await?
{
let node = get_channel_node(&channel).await?.unwrap();
@@ -253,5 +262,14 @@ pub async fn edit(
};
};
if remove.contains(&FieldsMember::VoiceChannel) {
if let Some(channel) = get_user_voice_channel_in_server(&target_user.id, &server.id).await?
{
let node = get_channel_node(&channel).await?.unwrap();
voice_client.remove_user(&node, &user.id, &channel).await?;
};
}
Ok(Json(member.into()))
}

View File

@@ -33,6 +33,12 @@ pub async fn router() -> Router<AppState> {
let cors = CorsLayer::new()
.allow_methods([Method::POST])
.allow_headers(AllowHeaders::mirror_request())
.expose_headers(vec![
"X-RateLimit-Limit".try_into().unwrap(),
"X-RateLimit-Bucket".try_into().unwrap(),
"X-RateLimit-Remaining".try_into().unwrap(),
"X-RateLimit-Reset-After".try_into().unwrap(),
])
.allow_origin(Any);
Router::new()

View File

@@ -36,6 +36,7 @@ revolt-ratelimits = { version = "0.9.4", path = "../../core/ratelimits", feature
# Axum / web server
axum = { version = "0.7.5" }
axum-extra = { version = "0.9", features = ["typed-header"] }
tower-http = { version = "0.5.2", features = ["cors"] }
# OpenAPI & documentation generation
utoipa-scalar = { version = "0.1.0", features = ["axum"] }

View File

@@ -1,5 +1,9 @@
use crate::AppState;
use axum::routing::{get, Router};
use axum::{
http::Method,
routing::{get, Router},
};
use tower_http::cors::{AllowHeaders, Any, CorsLayer};
pub mod categories;
pub mod root;
@@ -7,9 +11,21 @@ pub mod search;
pub mod trending;
pub fn router() -> Router<AppState> {
let cors = CorsLayer::new()
.allow_methods([Method::GET])
.allow_headers(AllowHeaders::mirror_request())
.expose_headers(vec![
"X-RateLimit-Limit".try_into().unwrap(),
"X-RateLimit-Bucket".try_into().unwrap(),
"X-RateLimit-Remaining".try_into().unwrap(),
"X-RateLimit-Reset-After".try_into().unwrap(),
])
.allow_origin(Any);
Router::new()
.route("/", get(root::root))
.route("/categories", get(categories::categories))
.route("/search", get(search::search))
.route("/trending", get(trending::trending))
.layer(cors)
}