mirror of
https://github.com/stoatchat/stoatchat.git
synced 2026-07-14 05:26:59 +00:00
feat: scaffold services/january
This commit is contained in:
277
Cargo.lock
generated
277
Cargo.lock
generated
@@ -229,7 +229,7 @@ dependencies = [
|
||||
"async-channel 1.6.1",
|
||||
"async-executor",
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"async-lock 2.8.0",
|
||||
"blocking",
|
||||
"futures-lite",
|
||||
"once_cell",
|
||||
@@ -265,6 +265,17 @@ dependencies = [
|
||||
"event-listener 2.5.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
|
||||
dependencies = [
|
||||
"event-listener 5.3.1",
|
||||
"event-listener-strategy",
|
||||
"pin-project-lite 0.2.13",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-process"
|
||||
version = "1.4.0"
|
||||
@@ -303,7 +314,7 @@ dependencies = [
|
||||
"async-channel 1.6.1",
|
||||
"async-global-executor",
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"async-lock 2.8.0",
|
||||
"async-process",
|
||||
"crossbeam-utils",
|
||||
"futures-channel",
|
||||
@@ -435,7 +446,7 @@ dependencies = [
|
||||
"nanoid",
|
||||
"rand 0.8.5",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"reqwest 0.11.10",
|
||||
"revolt_okapi",
|
||||
"revolt_rocket_okapi",
|
||||
"rocket",
|
||||
@@ -899,6 +910,29 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-extra"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum-core",
|
||||
"bytes 1.5.0",
|
||||
"futures-util",
|
||||
"headers",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.0",
|
||||
"http-body-util",
|
||||
"mime",
|
||||
"pin-project-lite 0.2.13",
|
||||
"serde",
|
||||
"tower",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum_typed_multipart"
|
||||
version = "0.12.1"
|
||||
@@ -1407,6 +1441,24 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.5"
|
||||
@@ -1997,7 +2049,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc9ed4ed7618b2f7581edb6ce28794a10fcc335e196fc2bcf56afee99ad63d10"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"reqwest",
|
||||
"reqwest 0.11.10",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"yup-oauth2",
|
||||
@@ -2441,6 +2493,30 @@ dependencies = [
|
||||
"allocator-api2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "headers"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9"
|
||||
dependencies = [
|
||||
"base64 0.21.3",
|
||||
"bytes 1.5.0",
|
||||
"headers-core",
|
||||
"http 1.1.0",
|
||||
"httpdate",
|
||||
"mime",
|
||||
"sha1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "headers-core"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4"
|
||||
dependencies = [
|
||||
"http 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.0"
|
||||
@@ -2690,6 +2766,22 @@ dependencies = [
|
||||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-tls"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
|
||||
dependencies = [
|
||||
"bytes 1.5.0",
|
||||
"http-body-util",
|
||||
"hyper 1.3.1",
|
||||
"hyper-util",
|
||||
"native-tls",
|
||||
"tokio 1.35.1",
|
||||
"tokio-native-tls",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.5"
|
||||
@@ -2981,11 +3073,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
dependencies = [
|
||||
"spin 0.5.2",
|
||||
"spin 0.9.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3243,9 +3335,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.16"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
@@ -3303,6 +3395,30 @@ dependencies = [
|
||||
"redis 0.22.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "moka"
|
||||
version = "0.12.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32cf62eb4dd975d2dde76432fb1075c49e3ee2331cf36f1f8fd4b66550d32b6f"
|
||||
dependencies = [
|
||||
"async-lock 3.4.0",
|
||||
"async-trait",
|
||||
"crossbeam-channel",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
"event-listener 5.3.1",
|
||||
"futures-util",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"quanta",
|
||||
"rustc_version 0.4.0",
|
||||
"smallvec",
|
||||
"tagptr",
|
||||
"thiserror",
|
||||
"triomphe",
|
||||
"uuid 1.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mongodb"
|
||||
version = "2.2.2"
|
||||
@@ -4081,6 +4197,21 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quanta"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"raw-cpuid",
|
||||
"wasi",
|
||||
"web-sys",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "querystring"
|
||||
version = "1.1.0"
|
||||
@@ -4251,6 +4382,15 @@ dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-cpuid"
|
||||
version = "11.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rdrand"
|
||||
version = "0.4.0"
|
||||
@@ -4424,7 +4564,7 @@ dependencies = [
|
||||
"http 0.2.12",
|
||||
"http-body 0.4.5",
|
||||
"hyper 0.14.30",
|
||||
"hyper-tls",
|
||||
"hyper-tls 0.5.0",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"lazy_static",
|
||||
@@ -4445,6 +4585,48 @@ dependencies = [
|
||||
"winreg 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes 1.5.0",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"h2 0.4.5",
|
||||
"http 1.1.0",
|
||||
"http-body 1.0.0",
|
||||
"http-body-util",
|
||||
"hyper 1.3.1",
|
||||
"hyper-tls 0.6.0",
|
||||
"hyper-util",
|
||||
"ipnet",
|
||||
"js-sys",
|
||||
"log",
|
||||
"mime",
|
||||
"native-tls",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"pin-project-lite 0.2.13",
|
||||
"rustls-pemfile 2.1.2",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"sync_wrapper 0.1.2",
|
||||
"system-configuration",
|
||||
"tokio 1.35.1",
|
||||
"tokio-native-tls",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-futures",
|
||||
"web-sys",
|
||||
"winreg 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "resolv-conf"
|
||||
version = "0.7.0"
|
||||
@@ -4462,6 +4644,7 @@ dependencies = [
|
||||
"axum",
|
||||
"axum_typed_multipart",
|
||||
"revolt-config",
|
||||
"revolt-result",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
@@ -4522,7 +4705,7 @@ dependencies = [
|
||||
name = "revolt-database"
|
||||
version = "0.7.16"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"async-lock 2.8.0",
|
||||
"async-recursion",
|
||||
"async-std",
|
||||
"async-trait",
|
||||
@@ -4590,7 +4773,7 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
"redis-kiss",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"reqwest 0.11.10",
|
||||
"revolt-config",
|
||||
"revolt-database",
|
||||
"revolt-models",
|
||||
@@ -4621,6 +4804,28 @@ dependencies = [
|
||||
"aws-sdk-s3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "revolt-january"
|
||||
version = "0.7.14"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum-extra",
|
||||
"lazy_static",
|
||||
"mime",
|
||||
"moka",
|
||||
"reqwest 0.12.4",
|
||||
"revolt-config",
|
||||
"revolt-models",
|
||||
"revolt-result",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio 1.35.1",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"utoipa",
|
||||
"utoipa-scalar",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "revolt-models"
|
||||
version = "0.7.16"
|
||||
@@ -4635,6 +4840,7 @@ dependencies = [
|
||||
"rocket",
|
||||
"schemars",
|
||||
"serde",
|
||||
"utoipa",
|
||||
"validator 0.16.0",
|
||||
]
|
||||
|
||||
@@ -4680,12 +4886,14 @@ dependencies = [
|
||||
name = "revolt-result"
|
||||
version = "0.7.16"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"revolt_okapi",
|
||||
"revolt_rocket_okapi",
|
||||
"rocket",
|
||||
"schemars",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"utoipa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5325,7 +5533,7 @@ checksum = "01b0ad16faa5d12372f914ed40d00bda21a6d1bdcc99264c5e5e1c9495cf3654"
|
||||
dependencies = [
|
||||
"httpdate",
|
||||
"native-tls",
|
||||
"reqwest",
|
||||
"reqwest 0.11.10",
|
||||
"sentry-backtrace",
|
||||
"sentry-contexts",
|
||||
"sentry-core",
|
||||
@@ -5818,6 +6026,33 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"core-foundation",
|
||||
"system-configuration-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "system-configuration-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tagptr"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
|
||||
|
||||
[[package]]
|
||||
name = "take_mut"
|
||||
version = "0.2.2"
|
||||
@@ -6163,6 +6398,12 @@ dependencies = [
|
||||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "triomphe"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3"
|
||||
|
||||
[[package]]
|
||||
name = "trust-dns-proto"
|
||||
version = "0.21.2"
|
||||
@@ -7029,6 +7270,16 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xmlparser"
|
||||
version = "0.13.6"
|
||||
|
||||
@@ -28,6 +28,7 @@ COPY crates/core/permissions/Cargo.toml ./crates/core/permissions/
|
||||
COPY crates/core/presence/Cargo.toml ./crates/core/presence/
|
||||
COPY crates/core/result/Cargo.toml ./crates/core/result/
|
||||
COPY crates/services/autumn/Cargo.toml ./crates/services/autumn/
|
||||
COPY crates/services/january/Cargo.toml ./crates/services/january/
|
||||
RUN sh /tmp/build-image-layer.sh deps
|
||||
|
||||
# Build all apps
|
||||
|
||||
@@ -24,6 +24,7 @@ COPY crates/core/permissions/Cargo.toml ./crates/core/permissions/
|
||||
COPY crates/core/presence/Cargo.toml ./crates/core/presence/
|
||||
COPY crates/core/result/Cargo.toml ./crates/core/result/
|
||||
COPY crates/services/autumn/Cargo.toml ./crates/services/autumn/
|
||||
COPY crates/services/january/Cargo.toml ./crates/services/january/
|
||||
RUN sh /tmp/build-image-layer.sh deps
|
||||
|
||||
# Build all apps
|
||||
|
||||
@@ -11,9 +11,10 @@ description = "Revolt Backend: API Models"
|
||||
[features]
|
||||
serde = ["dep:serde", "revolt-permissions/serde", "indexmap/serde"]
|
||||
schemas = ["dep:schemars", "revolt-permissions/schemas"]
|
||||
utoipa = ["dep:utoipa"]
|
||||
validator = ["dep:validator"]
|
||||
rocket = ["dep:rocket"]
|
||||
partials = ["dep:revolt_optional_struct", "serde", "schemas"]
|
||||
partials = ["dep:revolt_optional_struct", "serde", "schemas", "utoipa"]
|
||||
|
||||
default = ["serde", "partials", "rocket"]
|
||||
|
||||
@@ -37,6 +38,7 @@ iso8601-timestamp = { version = "0.2.11", features = ["schema", "bson"] }
|
||||
|
||||
# Spec Generation
|
||||
schemars = { version = "0.8.8", optional = true, features = ["indexmap1"] }
|
||||
utoipa = { version = "4.2.3", optional = true }
|
||||
|
||||
# Validation
|
||||
validator = { version = "0.16.0", optional = true, features = ["derive"] }
|
||||
|
||||
@@ -6,6 +6,10 @@ extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate schemars;
|
||||
|
||||
#[cfg(feature = "utoipa")]
|
||||
#[macro_use]
|
||||
extern crate utoipa;
|
||||
|
||||
#[cfg(feature = "partials")]
|
||||
#[macro_use]
|
||||
extern crate revolt_optional_struct;
|
||||
@@ -18,6 +22,7 @@ macro_rules! auto_derived {
|
||||
$(
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "schemas", derive(JsonSchema))]
|
||||
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
$item
|
||||
)+
|
||||
|
||||
@@ -11,7 +11,9 @@ description = "Revolt Backend: Result and Error types"
|
||||
[features]
|
||||
serde = ["dep:serde"]
|
||||
schemas = ["dep:schemars"]
|
||||
utoipa = ["dep:utoipa"]
|
||||
rocket = ["dep:rocket", "dep:serde_json"]
|
||||
axum = ["dep:axum", "dep:serde_json"]
|
||||
okapi = ["dep:revolt_rocket_okapi", "dep:revolt_okapi", "schemas"]
|
||||
|
||||
default = ["serde"]
|
||||
@@ -23,8 +25,12 @@ serde = { version = "1", features = ["derive"], optional = true }
|
||||
|
||||
# Spec Generation
|
||||
schemars = { version = "0.8.8", optional = true }
|
||||
utoipa = { version = "4.2.3", optional = true }
|
||||
|
||||
# Rocket
|
||||
rocket = { optional = true, version = "0.5.0-rc.2", default-features = false }
|
||||
revolt_rocket_okapi = { version = "0.9.1", optional = true }
|
||||
revolt_okapi = { version = "0.9.1", optional = true }
|
||||
|
||||
# Axum
|
||||
axum = { version = "0.7.5", optional = true }
|
||||
|
||||
81
crates/core/result/src/axum.rs
Normal file
81
crates/core/result/src/axum.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
use axum::{http::StatusCode, response::IntoResponse, Json};
|
||||
|
||||
use crate::{Error, ErrorType};
|
||||
|
||||
/// HTTP response builder for Error enum
|
||||
impl IntoResponse for Error {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
let status = match self.error_type {
|
||||
ErrorType::LabelMe => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
|
||||
ErrorType::AlreadyOnboarded => StatusCode::FORBIDDEN,
|
||||
|
||||
ErrorType::UnknownUser => StatusCode::NOT_FOUND,
|
||||
ErrorType::InvalidUsername => StatusCode::BAD_REQUEST,
|
||||
ErrorType::UsernameTaken => StatusCode::CONFLICT,
|
||||
ErrorType::DiscriminatorChangeRatelimited => StatusCode::TOO_MANY_REQUESTS,
|
||||
ErrorType::AlreadyFriends => StatusCode::CONFLICT,
|
||||
ErrorType::AlreadySentRequest => StatusCode::CONFLICT,
|
||||
ErrorType::Blocked => StatusCode::CONFLICT,
|
||||
ErrorType::BlockedByOther => StatusCode::FORBIDDEN,
|
||||
ErrorType::NotFriends => StatusCode::FORBIDDEN,
|
||||
ErrorType::TooManyPendingFriendRequests { .. } => StatusCode::BAD_REQUEST,
|
||||
|
||||
ErrorType::UnknownChannel => StatusCode::NOT_FOUND,
|
||||
ErrorType::UnknownMessage => StatusCode::NOT_FOUND,
|
||||
ErrorType::UnknownAttachment => StatusCode::BAD_REQUEST,
|
||||
ErrorType::CannotEditMessage => StatusCode::FORBIDDEN,
|
||||
ErrorType::CannotJoinCall => StatusCode::BAD_REQUEST,
|
||||
ErrorType::TooManyAttachments { .. } => StatusCode::BAD_REQUEST,
|
||||
ErrorType::TooManyReplies { .. } => StatusCode::BAD_REQUEST,
|
||||
ErrorType::EmptyMessage => StatusCode::UNPROCESSABLE_ENTITY,
|
||||
ErrorType::PayloadTooLarge => StatusCode::UNPROCESSABLE_ENTITY,
|
||||
ErrorType::CannotRemoveYourself => StatusCode::BAD_REQUEST,
|
||||
ErrorType::GroupTooLarge { .. } => StatusCode::FORBIDDEN,
|
||||
ErrorType::AlreadyInGroup => StatusCode::CONFLICT,
|
||||
ErrorType::NotInGroup => StatusCode::NOT_FOUND,
|
||||
ErrorType::AlreadyPinned => StatusCode::BAD_REQUEST,
|
||||
ErrorType::NotPinned => StatusCode::BAD_REQUEST,
|
||||
|
||||
ErrorType::UnknownServer => StatusCode::NOT_FOUND,
|
||||
ErrorType::InvalidRole => StatusCode::NOT_FOUND,
|
||||
ErrorType::Banned => StatusCode::FORBIDDEN,
|
||||
ErrorType::AlreadyInServer => StatusCode::CONFLICT,
|
||||
|
||||
ErrorType::TooManyServers { .. } => StatusCode::BAD_REQUEST,
|
||||
ErrorType::TooManyEmbeds { .. } => StatusCode::BAD_REQUEST,
|
||||
ErrorType::TooManyEmoji { .. } => StatusCode::BAD_REQUEST,
|
||||
ErrorType::TooManyChannels { .. } => StatusCode::BAD_REQUEST,
|
||||
ErrorType::TooManyRoles { .. } => StatusCode::BAD_REQUEST,
|
||||
|
||||
ErrorType::ReachedMaximumBots => StatusCode::BAD_REQUEST,
|
||||
ErrorType::IsBot => StatusCode::BAD_REQUEST,
|
||||
ErrorType::BotIsPrivate => StatusCode::FORBIDDEN,
|
||||
|
||||
ErrorType::CannotReportYourself => StatusCode::BAD_REQUEST,
|
||||
|
||||
ErrorType::MissingPermission { .. } => StatusCode::FORBIDDEN,
|
||||
ErrorType::MissingUserPermission { .. } => StatusCode::FORBIDDEN,
|
||||
ErrorType::NotElevated => StatusCode::FORBIDDEN,
|
||||
ErrorType::NotPrivileged => StatusCode::FORBIDDEN,
|
||||
ErrorType::CannotGiveMissingPermissions => StatusCode::FORBIDDEN,
|
||||
ErrorType::NotOwner => StatusCode::FORBIDDEN,
|
||||
|
||||
ErrorType::DatabaseError { .. } => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ErrorType::InternalError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ErrorType::InvalidOperation => StatusCode::BAD_REQUEST,
|
||||
ErrorType::InvalidCredentials => StatusCode::UNAUTHORIZED,
|
||||
ErrorType::InvalidProperty => StatusCode::BAD_REQUEST,
|
||||
ErrorType::InvalidSession => StatusCode::UNAUTHORIZED,
|
||||
ErrorType::DuplicateNonce => StatusCode::CONFLICT,
|
||||
ErrorType::VosoUnavailable => StatusCode::BAD_REQUEST,
|
||||
ErrorType::NotFound => StatusCode::NOT_FOUND,
|
||||
ErrorType::NoEffect => StatusCode::OK,
|
||||
ErrorType::FailedValidation { .. } => StatusCode::BAD_REQUEST,
|
||||
|
||||
ErrorType::ProxyError => StatusCode::BAD_REQUEST,
|
||||
};
|
||||
|
||||
(status, Json(&self)).into_response()
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,16 @@ extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate schemars;
|
||||
|
||||
#[cfg(feature = "utoipa")]
|
||||
#[macro_use]
|
||||
extern crate utoipa;
|
||||
|
||||
#[cfg(feature = "rocket")]
|
||||
pub mod rocket;
|
||||
|
||||
#[cfg(feature = "axum")]
|
||||
pub mod axum;
|
||||
|
||||
#[cfg(feature = "okapi")]
|
||||
pub mod okapi;
|
||||
|
||||
@@ -20,6 +27,7 @@ pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||
/// Error information
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "schemas", derive(JsonSchema))]
|
||||
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Error {
|
||||
/// Type of error and additional information
|
||||
@@ -42,6 +50,7 @@ impl std::error::Error for Error {}
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(tag = "type"))]
|
||||
#[cfg_attr(feature = "schemas", derive(JsonSchema))]
|
||||
#[cfg_attr(feature = "utoipa", derive(ToSchema))]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ErrorType {
|
||||
/// This error was not labeled :(
|
||||
@@ -145,6 +154,9 @@ pub enum ErrorType {
|
||||
error: String,
|
||||
},
|
||||
|
||||
// ? Micro-service errors
|
||||
ProxyError,
|
||||
|
||||
// ? Legacy errors
|
||||
VosoUnavailable,
|
||||
}
|
||||
|
||||
@@ -78,6 +78,8 @@ impl<'r> Responder<'r, 'static> for Error {
|
||||
ErrorType::NotFound => Status::NotFound,
|
||||
ErrorType::NoEffect => Status::Ok,
|
||||
ErrorType::FailedValidation { .. } => Status::BadRequest,
|
||||
|
||||
ErrorType::ProxyError => Status::BadRequest,
|
||||
};
|
||||
|
||||
// Serialize the error data structure into JSON.
|
||||
|
||||
@@ -4,19 +4,29 @@ version = "0.7.14"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
# Serialisation
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0.68"
|
||||
|
||||
# Async runtime
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
|
||||
# Logging
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
# Core crates
|
||||
revolt-config = { version = "0.7.16", path = "../../core/config" }
|
||||
revolt-result = { version = "0.7.16", path = "../../core/result", features = [
|
||||
"utoipa",
|
||||
"axum",
|
||||
] }
|
||||
|
||||
# Axum / web server
|
||||
tempfile = "3.12.0"
|
||||
axum_typed_multipart = "0.12.1"
|
||||
axum = { version = "0.7.5", features = ["multipart"] }
|
||||
|
||||
# OpenAPI & documentation generation
|
||||
utoipa-scalar = { version = "0.1.0", features = ["axum"] }
|
||||
utoipa = { version = "4.2.3", features = ["axum_extras", "ulid"] }
|
||||
|
||||
@@ -28,6 +28,8 @@ async fn main() -> Result<(), std::io::Error> {
|
||||
),
|
||||
components(
|
||||
schemas(
|
||||
revolt_result::Error,
|
||||
revolt_result::ErrorType,
|
||||
api::RootResponse,
|
||||
api::Tag,
|
||||
api::UploadPayload,
|
||||
|
||||
40
crates/services/january/Cargo.toml
Normal file
40
crates/services/january/Cargo.toml
Normal file
@@ -0,0 +1,40 @@
|
||||
[package]
|
||||
name = "revolt-january"
|
||||
version = "0.7.14"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
# Utility
|
||||
mime = "0.3.17"
|
||||
lazy_static = "1.5.0"
|
||||
moka = { version = "0.12.8", features = ["future"] }
|
||||
|
||||
# Serialisation
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0.68"
|
||||
|
||||
# Async runtime
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
|
||||
# Web requests
|
||||
reqwest = { version = "0.12", features = ["json"] }
|
||||
|
||||
# Logging
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
# Core crates
|
||||
revolt-config = { version = "0.7.16", path = "../../core/config" }
|
||||
revolt-models = { version = "0.7.16", path = "../../core/models" }
|
||||
revolt-result = { version = "0.7.16", path = "../../core/result", features = [
|
||||
"utoipa",
|
||||
"axum",
|
||||
] }
|
||||
|
||||
# Axum / web server
|
||||
axum = { version = "0.7.5" }
|
||||
axum-extra = { version = "0.9", features = ["typed-header"] }
|
||||
|
||||
# OpenAPI & documentation generation
|
||||
utoipa-scalar = { version = "0.1.0", features = ["axum"] }
|
||||
utoipa = { version = "4.2.3", features = ["axum_extras", "ulid"] }
|
||||
85
crates/services/january/src/api.rs
Normal file
85
crates/services/january/src/api.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
use axum::{body::Bytes, extract::Query, routing::get, Json, Router};
|
||||
use revolt_models::v0::Embed;
|
||||
use revolt_result::Result;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use axum_extra::{
|
||||
headers::{authorization::Bearer, Authorization},
|
||||
TypedHeader,
|
||||
};
|
||||
|
||||
use crate::requests::Request;
|
||||
|
||||
pub async fn router() -> Router {
|
||||
Router::new()
|
||||
.route("/", get(root))
|
||||
.route("/proxy", get(proxy))
|
||||
.route("/embed", get(embed))
|
||||
}
|
||||
|
||||
/// Successful root response
|
||||
#[derive(Serialize, Debug, ToSchema)]
|
||||
pub struct RootResponse {
|
||||
january: &'static str,
|
||||
version: &'static str,
|
||||
}
|
||||
|
||||
/// Capture crate version from Cargo
|
||||
static CRATE_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
/// Root response from service
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/",
|
||||
responses(
|
||||
(status = 200, description = "Echo response", body = RootResponse)
|
||||
)
|
||||
)]
|
||||
async fn root() -> Json<RootResponse> {
|
||||
Json(RootResponse {
|
||||
january: "Hello, I am a media proxy server!",
|
||||
version: CRATE_VERSION,
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct UrlQuery {
|
||||
url: String,
|
||||
}
|
||||
|
||||
/// Proxy a given URL and load media
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/proxy",
|
||||
responses(
|
||||
(status = 200, description = "Requested media file", body = Vec<u8>)
|
||||
),
|
||||
params(
|
||||
("url" = String, Query, description = "URL to fetch")
|
||||
),
|
||||
)]
|
||||
async fn proxy(Query(UrlQuery { url }): Query<UrlQuery>) -> Result<Bytes> {
|
||||
Request::proxy_file(&url).await
|
||||
}
|
||||
|
||||
/// Generate embed for a given URL
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/embed",
|
||||
responses(
|
||||
(status = 200, description = "Generated embed information", body = Embed)
|
||||
),
|
||||
params(
|
||||
("url" = String, Query, description = "URL to fetch")
|
||||
),
|
||||
security(
|
||||
("api_key" = [])
|
||||
)
|
||||
)]
|
||||
async fn embed(
|
||||
Query(UrlQuery { url }): Query<UrlQuery>,
|
||||
TypedHeader(Authorization(_bearer)): TypedHeader<Authorization<Bearer>>,
|
||||
) -> Result<Json<Embed>> {
|
||||
Request::generate_embed(&url).await.map(Json)
|
||||
}
|
||||
71
crates/services/january/src/main.rs
Normal file
71
crates/services/january/src/main.rs
Normal file
@@ -0,0 +1,71 @@
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
|
||||
use axum::Router;
|
||||
|
||||
use tokio::net::TcpListener;
|
||||
use utoipa::{
|
||||
openapi::security::{Http, HttpAuthScheme, SecurityScheme},
|
||||
Modify, OpenApi,
|
||||
};
|
||||
use utoipa_scalar::{Scalar, Servable as ScalarServable};
|
||||
|
||||
mod api;
|
||||
pub mod requests;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), std::io::Error> {
|
||||
// Configure logging and environment
|
||||
revolt_config::configure!(api);
|
||||
|
||||
// Configure API schema
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(
|
||||
modifiers(&SecurityAddon),
|
||||
paths(
|
||||
api::root,
|
||||
api::proxy,
|
||||
api::embed
|
||||
),
|
||||
components(
|
||||
schemas(
|
||||
api::RootResponse,
|
||||
revolt_result::Error,
|
||||
revolt_result::ErrorType,
|
||||
revolt_models::v0::ImageSize,
|
||||
revolt_models::v0::Image,
|
||||
revolt_models::v0::Video,
|
||||
revolt_models::v0::TwitchType,
|
||||
revolt_models::v0::LightspeedType,
|
||||
revolt_models::v0::BandcampType,
|
||||
revolt_models::v0::Special,
|
||||
revolt_models::v0::WebsiteMetadata,
|
||||
revolt_models::v0::Text,
|
||||
revolt_models::v0::Embed
|
||||
)
|
||||
)
|
||||
)]
|
||||
struct ApiDoc;
|
||||
|
||||
struct SecurityAddon;
|
||||
|
||||
impl Modify for SecurityAddon {
|
||||
fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
|
||||
if let Some(components) = openapi.components.as_mut() {
|
||||
components.add_security_scheme(
|
||||
"api_key",
|
||||
SecurityScheme::Http(Http::new(HttpAuthScheme::Bearer)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Configure Axum and router
|
||||
let app = Router::new()
|
||||
.merge(Scalar::with_url("/scalar", ApiDoc::openapi()))
|
||||
.nest("/", api::router().await);
|
||||
|
||||
// Configure TCP listener and bind
|
||||
let address = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 3000));
|
||||
let listener = TcpListener::bind(&address).await?;
|
||||
axum::serve(listener, app.into_make_service()).await
|
||||
}
|
||||
91
crates/services/january/src/requests.rs
Normal file
91
crates/services/january/src/requests.rs
Normal file
@@ -0,0 +1,91 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use axum::body::Bytes;
|
||||
use lazy_static::lazy_static;
|
||||
use mime::Mime;
|
||||
use reqwest::{header::CONTENT_TYPE, redirect, Client, Response};
|
||||
use revolt_models::v0::Embed;
|
||||
use revolt_result::{create_error, Result};
|
||||
|
||||
lazy_static! {
|
||||
static ref CLIENT: Client = reqwest::Client::builder()
|
||||
.user_agent("Mozilla/5.0 (compatible; January/2.0; +https://github.com/revoltchat/backend)")
|
||||
.timeout(Duration::from_secs(10)) // TODO config
|
||||
.connect_timeout(Duration::from_secs(5)) // TODO config
|
||||
.redirect(redirect::Policy::custom(|attempt| {
|
||||
if attempt.previous().len() > 5 { // TODO config
|
||||
attempt.error("too many redirects")
|
||||
} else if attempt.url().host_str() == Some("jan.revolt.chat") { // TODO config
|
||||
attempt.stop()
|
||||
} else {
|
||||
attempt.follow()
|
||||
}
|
||||
}))
|
||||
.build()
|
||||
.expect("reqwest Client");
|
||||
|
||||
/// Cache for proxy results
|
||||
static ref PROXY_CACHE: moka::future::Cache<String, Result<Bytes>> = moka::future::Cache::builder()
|
||||
.max_capacity(10_000) // TODO config
|
||||
.time_to_live(Duration::from_secs(60)) // TODO config
|
||||
.build();
|
||||
|
||||
/// Cache for embed results
|
||||
static ref EMBED_CACHE: moka::future::Cache<String, Result<Embed>> = moka::future::Cache::builder()
|
||||
.max_capacity(1_000) // TODO config
|
||||
.time_to_live(Duration::from_secs(60)) // TODO config
|
||||
.build();
|
||||
}
|
||||
|
||||
/// Information about a successful request
|
||||
pub struct Request {
|
||||
response: Response,
|
||||
mime: Mime,
|
||||
}
|
||||
|
||||
impl Request {
|
||||
/// Proxy a given URL
|
||||
pub async fn proxy_file(url: &str) -> Result<Bytes> {
|
||||
if let Some(hit) = PROXY_CACHE.get(url).await {
|
||||
hit
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate embed for a given URL
|
||||
pub async fn generate_embed(url: &str) -> Result<Embed> {
|
||||
if let Some(hit) = EMBED_CACHE.get(url).await {
|
||||
hit
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a new request to a service
|
||||
pub async fn new(url: &str) -> Result<Request> {
|
||||
let response = CLIENT
|
||||
.get(url)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|_| create_error!(ProxyError))?;
|
||||
|
||||
if !response.status().is_success() {
|
||||
tracing::error!("{:?}", response);
|
||||
return Err(create_error!(ProxyError));
|
||||
}
|
||||
|
||||
let content_type = response
|
||||
.headers()
|
||||
.get(CONTENT_TYPE)
|
||||
.ok_or(create_error!(ProxyError))?
|
||||
.to_str()
|
||||
.map_err(|_| create_error!(ProxyError))?;
|
||||
|
||||
let mime: mime::Mime = content_type
|
||||
.parse()
|
||||
.map_err(|_| create_error!(ProxyError))?;
|
||||
|
||||
Ok(Request { response, mime })
|
||||
}
|
||||
}
|
||||
@@ -32,11 +32,13 @@ deps() {
|
||||
crates/core/permissions/src \
|
||||
crates/core/presence/src \
|
||||
crates/core/result/src \
|
||||
crates/services/autumn/src
|
||||
crates/services/autumn/src \
|
||||
crates/services/january/src
|
||||
echo 'fn main() { panic!("stub"); }' |
|
||||
tee crates/bonfire/src/main.rs |
|
||||
tee crates/delta/src/main.rs |
|
||||
tee crates/services/autumn/src/main.rs
|
||||
tee crates/services/autumn/src/main.rs |
|
||||
tee crates/services/january/src/main.rs
|
||||
echo '' |
|
||||
tee crates/bindings/node/src/lib.rs |
|
||||
tee crates/core/config/src/lib.rs |
|
||||
|
||||
Reference in New Issue
Block a user