diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml
index 0d5a76042..58e186d0b 100644
--- a/.github/workflows/docker.yaml
+++ b/.github/workflows/docker.yaml
@@ -61,7 +61,7 @@ jobs:
if: github.event_name != 'pull_request'
strategy:
matrix:
- project: [delta, bonfire, autumn, january]
+ project: [delta, bonfire, autumn, january, pushd]
name: Build ${{ matrix.project }} image
steps:
# Configure build environment
@@ -106,6 +106,10 @@ jobs:
"january": {
"path": "crates/services/january",
"tag": "${{ github.repository_owner }}/january"
+ },
+ "pushd": {
+ "path": "crates/daemons/pushd",
+ "tag": "${{ github.repository_owner }}/pushd"
}
}
export_to: output
diff --git a/Cargo.lock b/Cargo.lock
index 6d80054b5..a3a8571b2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -23,15 +23,6 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
-[[package]]
-name = "aead"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
-dependencies = [
- "generic-array 0.14.5",
-]
-
[[package]]
name = "aead"
version = "0.5.2"
@@ -42,18 +33,6 @@ dependencies = [
"generic-array 0.14.5",
]
-[[package]]
-name = "aes"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
-dependencies = [
- "cfg-if",
- "cipher 0.3.0",
- "cpufeatures",
- "opaque-debug 0.3.0",
-]
-
[[package]]
name = "aes"
version = "0.8.4"
@@ -61,35 +40,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
- "cipher 0.4.4",
+ "cipher",
"cpufeatures",
]
-[[package]]
-name = "aes-gcm"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc3be92e19a7ef47457b8e6f90707e12b6ac5d20c6f3866584fa3be0787d839f"
-dependencies = [
- "aead 0.4.3",
- "aes 0.7.5",
- "cipher 0.3.0",
- "ctr 0.7.0",
- "ghash 0.4.4",
- "subtle",
-]
-
[[package]]
name = "aes-gcm"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
dependencies = [
- "aead 0.5.2",
- "aes 0.8.4",
- "cipher 0.4.4",
- "ctr 0.9.2",
- "ghash 0.5.1",
+ "aead",
+ "aes",
+ "cipher",
+ "ctr",
+ "ghash",
"subtle",
]
@@ -138,6 +103,31 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
+[[package]]
+name = "amqp_serde"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "787581044ca08ad61cdb3a4e21afba087fb8cdba3bb3e23ce69a7d091808014d"
+dependencies = [
+ "bytes 1.5.0",
+ "serde",
+ "serde_bytes_ng",
+]
+
+[[package]]
+name = "amqprs"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f1b4afcbd862e16c272b7625b6b057930b052d63c720bc90f6afab0d9abe8a8"
+dependencies = [
+ "amqp_serde",
+ "async-trait",
+ "bytes 1.5.0",
+ "serde",
+ "serde_bytes_ng",
+ "tokio 1.40.0",
+]
+
[[package]]
name = "android-tzdata"
version = "0.1.1"
@@ -264,7 +254,7 @@ dependencies = [
"futures-lite",
"once_cell",
"tokio 0.2.25",
- "tokio 1.35.1",
+ "tokio 1.40.0",
]
[[package]]
@@ -450,16 +440,16 @@ version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
"libc",
"winapi",
]
[[package]]
name = "authifier"
-version = "1.0.8"
+version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30269caf0aaf1e1b542b150030e9688bf41d50026e09a51efd9408f332636c9d"
+checksum = "9ba4df3b5df5cf1a08d4af71c407fb56a675b6aaf4d1fec704da32595497d73d"
dependencies = [
"async-std",
"async-trait",
@@ -557,7 +547,7 @@ dependencies = [
"http 0.2.12",
"ring 0.17.8",
"time",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tracing",
"url",
"zeroize",
@@ -740,7 +730,7 @@ checksum = "62220bc6e97f946ddd51b5f1361f78996e704677afc518a4ff66b7a72ea1378c"
dependencies = [
"futures-util",
"pin-project-lite 0.2.13",
- "tokio 1.35.1",
+ "tokio 1.40.0",
]
[[package]]
@@ -838,7 +828,7 @@ dependencies = [
"pin-project-lite 0.2.13",
"pin-utils",
"rustls 0.21.12",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tracing",
]
@@ -854,7 +844,7 @@ dependencies = [
"http 0.2.12",
"http 1.1.0",
"pin-project-lite 0.2.13",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tracing",
"zeroize",
]
@@ -881,8 +871,8 @@ dependencies = [
"ryu",
"serde",
"time",
- "tokio 1.35.1",
- "tokio-util 0.7.2",
+ "tokio 1.40.0",
+ "tokio-util",
]
[[package]]
@@ -927,7 +917,7 @@ dependencies = [
"matchit",
"memchr",
"mime",
- "multer 3.1.0",
+ "multer",
"percent-encoding",
"pin-project-lite 0.2.13",
"rustversion",
@@ -936,7 +926,7 @@ dependencies = [
"serde_path_to_error",
"serde_urlencoded",
"sync_wrapper 1.0.1",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tower",
"tower-layer",
"tower-service",
@@ -1014,7 +1004,7 @@ dependencies = [
"futures-util",
"tempfile",
"thiserror",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"uuid 1.4.1",
]
@@ -1296,7 +1286,7 @@ dependencies = [
"instant",
"once_cell",
"thiserror",
- "tokio 1.35.1",
+ "tokio 1.40.0",
]
[[package]]
@@ -1376,15 +1366,6 @@ dependencies = [
"windows-targets 0.52.6",
]
-[[package]]
-name = "cipher"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
-dependencies = [
- "generic-array 0.14.5",
-]
-
[[package]]
name = "cipher"
version = "0.4.4"
@@ -1432,8 +1413,8 @@ dependencies = [
"futures-core",
"memchr",
"pin-project-lite 0.2.13",
- "tokio 1.35.1",
- "tokio-util 0.7.2",
+ "tokio 1.40.0",
+ "tokio-util",
]
[[package]]
@@ -1493,18 +1474,11 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]]
name = "cookie"
-version = "0.16.0"
+version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05"
+checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
dependencies = [
- "aes-gcm 0.9.2",
- "base64 0.13.0",
- "hkdf",
- "hmac",
"percent-encoding",
- "rand 0.8.5",
- "sha2",
- "subtle",
"time",
"version_check",
]
@@ -1685,22 +1659,13 @@ version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3b7eb4404b8195a9abb6356f4ac07d8ba267045c8d6d220ac4dc992e6cc75df"
-[[package]]
-name = "ctr"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a232f92a03f37dd7d7dd2adc67166c77e9cd88de5b019b9a9eecfaeaf7bfd481"
-dependencies = [
- "cipher 0.3.0",
-]
-
[[package]]
name = "ctr"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
- "cipher 0.4.4",
+ "cipher",
]
[[package]]
@@ -1870,7 +1835,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16a2561fd313df162315935989dceb8c99db4ee1933358270a57a3cfb8c957f3"
dependencies = [
"crossbeam-queue",
- "tokio 1.35.1",
+ "tokio 1.40.0",
]
[[package]]
@@ -1946,9 +1911,9 @@ dependencies = [
[[package]]
name = "devise"
-version = "0.3.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50c7580b072f1c8476148f16e0a0d5dedddab787da98d86c5082c5e9ed8ab595"
+checksum = "f1d90b0c4c777a2cad215e3c7be59ac7c15adf45cf76317009b7d096d46f651d"
dependencies = [
"devise_codegen",
"devise_core",
@@ -1956,9 +1921,9 @@ dependencies = [
[[package]]
name = "devise_codegen"
-version = "0.3.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "123c73e7a6e51b05c75fe1a1b2f4e241399ea5740ed810b0e3e6cacd9db5e7b2"
+checksum = "71b28680d8be17a570a2334922518be6adc3f58ecc880cbb404eaeb8624fd867"
dependencies = [
"devise_core",
"quote 1.0.37",
@@ -1966,15 +1931,15 @@ dependencies = [
[[package]]
name = "devise_core"
-version = "0.3.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "841ef46f4787d9097405cac4e70fb8644fc037b526e8c14054247c0263c400d0"
+checksum = "b035a542cf7abf01f2e3c4d5a7acbaebfefe120ae4efc7bde3df98186e4b8af7"
dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.6.0",
"proc-macro2",
"proc-macro2-diagnostics",
"quote 1.0.37",
- "syn 1.0.107",
+ "syn 2.0.76",
]
[[package]]
@@ -2420,9 +2385,9 @@ dependencies = [
"redis-protocol",
"semver 1.0.23",
"socket2 0.5.5",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tokio-stream",
- "tokio-util 0.7.2",
+ "tokio-util",
"url",
"urlencoding",
]
@@ -2514,7 +2479,7 @@ checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06"
dependencies = [
"futures-channel",
"futures-task",
- "tokio 1.35.1",
+ "tokio 1.40.0",
]
[[package]]
@@ -2639,16 +2604,6 @@ dependencies = [
"syn 1.0.107",
]
-[[package]]
-name = "ghash"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
-dependencies = [
- "opaque-debug 0.3.0",
- "polyval 0.5.3",
-]
-
[[package]]
name = "ghash"
version = "0.5.1"
@@ -2656,7 +2611,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
dependencies = [
"opaque-debug 0.3.0",
- "polyval 0.6.2",
+ "polyval",
]
[[package]]
@@ -2731,8 +2686,8 @@ dependencies = [
"http 0.2.12",
"indexmap 2.0.1",
"slab",
- "tokio 1.35.1",
- "tokio-util 0.7.2",
+ "tokio 1.40.0",
+ "tokio-util",
"tracing",
]
@@ -2750,8 +2705,8 @@ dependencies = [
"http 1.1.0",
"indexmap 2.0.1",
"slab",
- "tokio 1.35.1",
- "tokio-util 0.7.2",
+ "tokio 1.40.0",
+ "tokio-util",
"tracing",
]
@@ -2858,6 +2813,18 @@ dependencies = [
"libc",
]
+[[package]]
+name = "hermit-abi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
+[[package]]
+name = "hermit-abi"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
+
[[package]]
name = "hex"
version = "0.4.3"
@@ -3026,7 +2993,7 @@ dependencies = [
"itoa",
"pin-project-lite 0.2.13",
"socket2 0.5.5",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tower-service",
"tracing",
"want",
@@ -3049,7 +3016,7 @@ dependencies = [
"itoa",
"pin-project-lite 0.2.13",
"smallvec",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"want",
]
@@ -3065,7 +3032,7 @@ dependencies = [
"log",
"rustls 0.21.12",
"rustls-native-certs",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tokio-rustls 0.24.1",
]
@@ -3081,7 +3048,7 @@ dependencies = [
"hyper-util",
"rustls 0.22.4",
"rustls-pki-types",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tokio-rustls 0.25.0",
"tower-service",
"webpki-roots 0.26.3",
@@ -3096,7 +3063,7 @@ dependencies = [
"bytes 1.5.0",
"hyper 0.14.30",
"native-tls",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tokio-native-tls",
]
@@ -3111,7 +3078,7 @@ dependencies = [
"hyper 1.3.1",
"hyper-util",
"native-tls",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tokio-native-tls",
"tower-service",
]
@@ -3130,7 +3097,7 @@ dependencies = [
"hyper 1.3.1",
"pin-project-lite 0.2.13",
"socket2 0.5.5",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tower",
"tower-service",
"tracing",
@@ -3327,6 +3294,17 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
+[[package]]
+name = "is-terminal"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b"
+dependencies = [
+ "hermit-abi 0.4.0",
+ "libc",
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "isahc"
version = "1.7.2"
@@ -4014,13 +3992,14 @@ dependencies = [
[[package]]
name = "mio"
-version = "0.8.10"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
+checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
dependencies = [
+ "hermit-abi 0.3.9",
"libc",
"wasi",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -4038,7 +4017,7 @@ dependencies = [
"log",
"metrics",
"thiserror",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tracing",
"tracing-subscriber",
]
@@ -4114,9 +4093,9 @@ dependencies = [
"strsim 0.10.0",
"take_mut",
"thiserror",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tokio-rustls 0.23.4",
- "tokio-util 0.7.2",
+ "tokio-util",
"trust-dns-proto",
"trust-dns-resolver",
"typed-builder",
@@ -4124,26 +4103,6 @@ dependencies = [
"webpki-roots 0.22.3",
]
-[[package]]
-name = "multer"
-version = "2.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f8f35e687561d5c1667590911e6698a8cb714a134a7505718a182e7bc9d3836"
-dependencies = [
- "bytes 1.5.0",
- "encoding_rs",
- "futures-util",
- "http 0.2.12",
- "httparse",
- "log",
- "memchr",
- "mime",
- "spin 0.9.8",
- "tokio 1.35.1",
- "tokio-util 0.6.10",
- "version_check",
-]
-
[[package]]
name = "multer"
version = "3.1.0"
@@ -4158,6 +4117,8 @@ dependencies = [
"memchr",
"mime",
"spin 0.9.8",
+ "tokio 1.40.0",
+ "tokio-util",
"version_check",
]
@@ -4369,7 +4330,7 @@ version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
"libc",
]
@@ -4597,9 +4558,9 @@ dependencies = [
[[package]]
name = "pear"
-version = "0.2.3"
+version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15e44241c5e4c868e3eaa78b7c1848cadd6344ed4f54d029832d32b415a58702"
+checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467"
dependencies = [
"inlinable_string",
"pear_codegen",
@@ -4608,14 +4569,14 @@ dependencies = [
[[package]]
name = "pear_codegen"
-version = "0.2.3"
+version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82a5ca643c2303ecb740d506539deba189e16f2754040a42901cd8105d0282d0"
+checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147"
dependencies = [
"proc-macro2",
"proc-macro2-diagnostics",
"quote 1.0.37",
- "syn 1.0.107",
+ "syn 2.0.76",
]
[[package]]
@@ -4894,18 +4855,6 @@ dependencies = [
"winapi",
]
-[[package]]
-name = "polyval"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
-dependencies = [
- "cfg-if",
- "cpufeatures",
- "opaque-debug 0.3.0",
- "universal-hash 0.4.0",
-]
-
[[package]]
name = "polyval"
version = "0.6.2"
@@ -4915,7 +4864,7 @@ dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug 0.3.0",
- "universal-hash 0.5.1",
+ "universal-hash",
]
[[package]]
@@ -4985,13 +4934,13 @@ dependencies = [
[[package]]
name = "proc-macro2-diagnostics"
-version = "0.9.1"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada"
+checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
dependencies = [
"proc-macro2",
"quote 1.0.37",
- "syn 1.0.107",
+ "syn 2.0.76",
"version_check",
"yansi",
]
@@ -5333,8 +5282,8 @@ dependencies = [
"pin-project-lite 0.2.13",
"ryu",
"sha1_smol",
- "tokio 1.35.1",
- "tokio-util 0.7.2",
+ "tokio 1.40.0",
+ "tokio-util",
"url",
]
@@ -5353,8 +5302,8 @@ dependencies = [
"percent-encoding",
"pin-project-lite 0.2.13",
"ryu",
- "tokio 1.35.1",
- "tokio-util 0.7.2",
+ "tokio 1.40.0",
+ "tokio-util",
"url",
]
@@ -5494,7 +5443,7 @@ dependencies = [
"serde",
"serde_json",
"serde_urlencoded",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tokio-native-tls",
"url",
"wasm-bindgen",
@@ -5535,7 +5484,7 @@ dependencies = [
"serde_urlencoded",
"sync_wrapper 0.1.2",
"system-configuration",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tokio-native-tls",
"tower-service",
"url",
@@ -5599,7 +5548,7 @@ dependencies = [
"simdutf8",
"strum_macros",
"tempfile",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tower-http",
"tracing",
"tracing-subscriber",
@@ -5659,6 +5608,7 @@ dependencies = [
name = "revolt-database"
version = "0.7.19"
dependencies = [
+ "amqprs",
"async-lock 2.8.0",
"async-recursion",
"async-std",
@@ -5707,6 +5657,7 @@ dependencies = [
name = "revolt-delta"
version = "0.7.19"
dependencies = [
+ "amqprs",
"async-channel 1.6.1",
"async-std",
"authifier",
@@ -5753,7 +5704,7 @@ dependencies = [
name = "revolt-files"
version = "0.7.19"
dependencies = [
- "aes-gcm 0.10.3",
+ "aes-gcm",
"aws-config",
"aws-sdk-s3",
"base64 0.22.1",
@@ -5793,7 +5744,7 @@ dependencies = [
"serde",
"serde_json",
"tempfile",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tracing",
"tracing-subscriber",
"utoipa",
@@ -5857,6 +5808,30 @@ dependencies = [
"redis-kiss",
]
+[[package]]
+name = "revolt-pushd"
+version = "0.1.0"
+dependencies = [
+ "amqprs",
+ "async-trait",
+ "authifier",
+ "base64 0.22.1",
+ "fcm_v1",
+ "isahc",
+ "iso8601-timestamp 0.2.11",
+ "log",
+ "revolt-config",
+ "revolt-database",
+ "revolt-models",
+ "revolt_a2",
+ "revolt_optional_struct",
+ "serde",
+ "serde_json",
+ "tokio 1.40.0",
+ "ulid 1.1.3",
+ "web-push",
+]
+
[[package]]
name = "revolt-result"
version = "0.7.19"
@@ -5892,7 +5867,7 @@ dependencies = [
"serde",
"serde_json",
"thiserror",
- "tokio 1.35.1",
+ "tokio 1.40.0",
]
[[package]]
@@ -5925,9 +5900,9 @@ dependencies = [
[[package]]
name = "revolt_rocket_okapi"
-version = "0.9.1"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "275e1e9bd3343f75225cafa64f4bfb939c8b21c5f861141180fc0e24769ff6cf"
+checksum = "cb113b281380c12c185c8d98c4887627ae6f7add16a510073382518ce34e42db"
dependencies = [
"either",
"log",
@@ -6026,23 +6001,22 @@ dependencies = [
[[package]]
name = "rocket"
-version = "0.5.0-rc.2"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98ead083fce4a405feb349cf09abdf64471c6077f14e0ce59364aa90d4b99317"
+checksum = "a516907296a31df7dc04310e7043b61d71954d703b603cc6867a026d7e72d73f"
dependencies = [
"async-stream",
"async-trait",
"atomic",
- "atty",
"binascii",
"bytes 1.5.0",
"either",
"figment",
"futures",
- "indexmap 1.9.3",
+ "indexmap 2.0.1",
"log",
"memchr",
- "multer 2.0.2",
+ "multer",
"num_cpus",
"parking_lot",
"pin-project-lite 0.2.13",
@@ -6055,9 +6029,9 @@ dependencies = [
"state",
"tempfile",
"time",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tokio-stream",
- "tokio-util 0.7.2",
+ "tokio-util",
"ubyte",
"version_check",
"yansi",
@@ -6065,9 +6039,9 @@ dependencies = [
[[package]]
name = "rocket_authifier"
-version = "1.0.8"
+version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f89a12311f60e9288833fc3ce6029bce5d5c61870ceef74d4a50668a8b520ad"
+checksum = "810753b79106c44a4e76247fc7576b660663133a9e8f4b0afeb303589ec51d59"
dependencies = [
"authifier",
"iso8601-timestamp 0.1.10",
@@ -6081,24 +6055,25 @@ dependencies = [
[[package]]
name = "rocket_codegen"
-version = "0.5.0-rc.2"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6aeb6bb9c61e9cd2c00d70ea267bf36f76a4cc615e5908b349c2f9d93999b47"
+checksum = "575d32d7ec1a9770108c879fc7c47815a80073f96ca07ff9525a94fcede1dd46"
dependencies = [
"devise",
"glob",
- "indexmap 1.9.3",
+ "indexmap 2.0.1",
"proc-macro2",
"quote 1.0.37",
"rocket_http",
- "syn 1.0.107",
+ "syn 2.0.76",
"unicode-xid 0.2.3",
+ "version_check",
]
[[package]]
name = "rocket_cors"
-version = "0.6.0-alpha1"
-source = "git+https://github.com/lawliet89/rocket_cors?rev=c17e8145baa4790319fdb6a473e465b960f55e7c#c17e8145baa4790319fdb6a473e465b960f55e7c"
+version = "0.6.0"
+source = "git+https://github.com/lawliet89/rocket_cors?rev=072d90359b23e9b291df6b672c07c93de9c46011#072d90359b23e9b291df6b672c07c93de9c46011"
dependencies = [
"http 0.2.12",
"log",
@@ -6113,9 +6088,9 @@ dependencies = [
[[package]]
name = "rocket_empty"
-version = "0.1.1"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c0922e47f981204fee38578a8efcf47a5c1a4ac0eb7f59e6bdfa3e61c8e3d69"
+checksum = "97a55000e1ef5f4a9b20ae3d9de2a0bd22620c78ebd1aa568776ae12276125a6"
dependencies = [
"revolt_okapi",
"revolt_rocket_okapi",
@@ -6124,16 +6099,16 @@ dependencies = [
[[package]]
name = "rocket_http"
-version = "0.5.0-rc.2"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ded65d127954de3c12471630bf4b81a2792f065984461e65b91d0fdaafc17a2"
+checksum = "e274915a20ee3065f611c044bd63c40757396b6dbc057d6046aec27f14f882b9"
dependencies = [
"cookie",
"either",
"futures",
"http 0.2.12",
"hyper 0.14.30",
- "indexmap 1.9.3",
+ "indexmap 2.0.1",
"log",
"memchr",
"pear",
@@ -6145,7 +6120,7 @@ dependencies = [
"stable-pattern",
"state",
"time",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"uncased",
]
@@ -6589,7 +6564,7 @@ dependencies = [
"sentry-debug-images",
"sentry-panic",
"sentry-tracing",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"ureq",
]
@@ -6700,6 +6675,15 @@ dependencies = [
"serde",
]
+[[package]]
+name = "serde_bytes_ng"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdb0ebce8684e2253f964e8b6ce51f0ccc6666bbb448fb4a6788088bda6544b6"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "serde_derive"
version = "1.0.209"
@@ -7027,9 +7011,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "state"
-version = "0.5.3"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b"
+checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8"
dependencies = [
"loom",
]
@@ -7419,28 +7403,27 @@ dependencies = [
[[package]]
name = "tokio"
-version = "1.35.1"
+version = "1.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
+checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998"
dependencies = [
"backtrace",
"bytes 1.5.0",
"libc",
"mio",
- "num_cpus",
"parking_lot",
"pin-project-lite 0.2.13",
"signal-hook-registry",
"socket2 0.5.5",
"tokio-macros",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
]
[[package]]
name = "tokio-macros"
-version = "2.2.0"
+version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
+checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [
"proc-macro2",
"quote 1.0.37",
@@ -7454,7 +7437,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
dependencies = [
"native-tls",
- "tokio 1.35.1",
+ "tokio 1.40.0",
]
[[package]]
@@ -7464,7 +7447,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
dependencies = [
"rustls 0.20.6",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"webpki",
]
@@ -7475,7 +7458,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
dependencies = [
"rustls 0.21.12",
- "tokio 1.35.1",
+ "tokio 1.40.0",
]
[[package]]
@@ -7486,7 +7469,7 @@ checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f"
dependencies = [
"rustls 0.22.4",
"rustls-pki-types",
- "tokio 1.35.1",
+ "tokio 1.40.0",
]
[[package]]
@@ -7497,21 +7480,7 @@ checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"
dependencies = [
"futures-core",
"pin-project-lite 0.2.13",
- "tokio 1.35.1",
-]
-
-[[package]]
-name = "tokio-util"
-version = "0.6.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
-dependencies = [
- "bytes 1.5.0",
- "futures-core",
- "futures-sink",
- "log",
- "pin-project-lite 0.2.13",
- "tokio 1.35.1",
+ "tokio 1.40.0",
]
[[package]]
@@ -7525,7 +7494,7 @@ dependencies = [
"futures-io",
"futures-sink",
"pin-project-lite 0.2.13",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tracing",
]
@@ -7594,7 +7563,7 @@ dependencies = [
"futures-util",
"pin-project",
"pin-project-lite 0.2.13",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tower-layer",
"tower-service",
"tracing",
@@ -7727,7 +7696,7 @@ dependencies = [
"smallvec",
"thiserror",
"tinyvec",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"url",
]
@@ -7747,7 +7716,7 @@ dependencies = [
"resolv-conf",
"smallvec",
"thiserror",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"trust-dns-proto",
]
@@ -7962,16 +7931,6 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
-[[package]]
-name = "universal-hash"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402"
-dependencies = [
- "generic-array 0.14.5",
- "subtle",
-]
-
[[package]]
name = "universal-hash"
version = "0.5.1"
@@ -8728,9 +8687,12 @@ dependencies = [
[[package]]
name = "yansi"
-version = "0.5.1"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
+checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
+dependencies = [
+ "is-terminal",
+]
[[package]]
name = "yup-oauth2"
@@ -8754,7 +8716,7 @@ dependencies = [
"serde",
"serde_json",
"time",
- "tokio 1.35.1",
+ "tokio 1.40.0",
"tower-service",
"url",
]
diff --git a/Cargo.toml b/Cargo.toml
index 61f6fa514..2779c26bb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,16 +1,15 @@
[workspace]
resolver = "2"
+
members = [
"crates/delta",
"crates/bonfire",
"crates/core/*",
"crates/services/*",
"crates/bindings/*",
+ "crates/daemons/pushd",
]
[patch.crates-io]
-# mobc-redis = { git = "https://github.com/insertish/mobc", rev = "8b880bb59f2ba80b4c7bc40c649c113d8857a186" }
redis22 = { package = "redis", version = "0.22.3", git = "https://github.com/revoltchat/redis-rs", rev = "1a41faf356fd21aebba71cea7eb7eb2653e5f0ef" }
redis23 = { package = "redis", version = "0.23.1", git = "https://github.com/revoltchat/redis-rs", rev = "f8ca28ab85da59d2ccde526b4d2fb390eff5a5f9" }
-# authifier = { package = "authifier", version = "1.0.8", path = "../authifier/crates/authifier" }
-# rocket_authifier = { package = "rocket_authifier", version = "1.0.8", path = "../authifier/crates/rocket_authifier" }
diff --git a/Dockerfile b/Dockerfile
index 57ef759ed..10112b667 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -29,6 +29,7 @@ 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/
+COPY crates/daemons/pushd/Cargo.toml ./crates/daemons/pushd/
RUN sh /tmp/build-image-layer.sh deps
# Build all apps
diff --git a/README.md b/README.md
index 490aa9059..ea8cab84b 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,7 @@ The services and libraries that power the Revolt service.
| `services/january` | [crates/services/january](crates/services/january) | Proxy server | ![License](https://img.shields.io/badge/license-AGPL--3.0--or--later-blue) |
| `services/autumn` | [crates/services/autumn](crates/services/autumn) | File server | ![License](https://img.shields.io/badge/license-AGPL--3.0--or--later-blue) |
| `bindings/node` | [crates/bindings/node](crates/bindings/node) | Node.js bindings for the Revolt software | ![License](https://img.shields.io/badge/license-AGPL--3.0--or--later-blue) |
+| `daemons/pushd` | [crates/daemons/pushd](crates/daemons/pushd) | Push notification daemon server | ![License](https://img.shields.io/badge/license-AGPL--3.0--or--later-blue) |
@@ -55,11 +56,12 @@ As a heads-up, the development environment uses the following ports:
| Service | Port |
| ------------------------- | :------------: |
-| MongoDB | 14017 |
-| Redis | 14079 |
+| MongoDB | 27017 |
+| Redis | 6379 |
| MinIO | 14009 |
| Maildev | 14025
14080 |
| Revolt Web App | 14701 |
+| RabbitMQ | 5672
15672 |
| `crates/delta` | 14702 |
| `crates/bonfire` | 14703 |
| `crates/services/autumn` | 14704 |
@@ -106,6 +108,8 @@ cargo run --bin revolt-bonfire
cargo run --bin revolt-autumn
# run the proxy server
cargo run --bin revolt-january
+# run the push daemon (not usually needed in regular development)
+cargo run --bin revolt-pushd
# hint:
# mold -run
diff --git a/compose.yml b/compose.yml
index 53d531ce4..31af45bad 100644
--- a/compose.yml
+++ b/compose.yml
@@ -3,13 +3,13 @@ services:
redis:
image: eqalpha/keydb
ports:
- - "14079:6379"
+ - "6379:6379"
# MongoDB
database:
image: mongo
ports:
- - "14017:27017"
+ - "27017:27017"
volumes:
- ./.data/db:/data/db
@@ -33,14 +33,25 @@ services:
depends_on:
- minio
entrypoint: >
- /bin/sh -c "
- while ! /usr/bin/mc ready minio; do
+ /bin/sh -c "while ! /usr/bin/mc ready minio; do
/usr/bin/mc config host add minio http://minio:9000 minioautumn minioautumn;
echo 'Waiting minio...' && sleep 1;
- done;
- /usr/bin/mc mb minio/revolt-uploads;
- exit 0;
- "
+ done; /usr/bin/mc mb minio/revolt-uploads; exit 0;"
+
+ # Rabbit
+ rabbit:
+ image: rabbitmq:3-management
+ environment:
+ RABBITMQ_DEFAULT_USER: rabbituser
+ RABBITMQ_DEFAULT_PASS: rabbitpass
+ volumes:
+ - ./.data/rabbit:/var/lib/rabbitmq
+ #- ./rabbit_plugins:/opt/rabbitmq/plugins/
+ #- ./rabbit_enabled_plugins:/etc/rabbitmq/enabled_plugins
+ # uncomment this if you need to enable other plugins
+ ports:
+ - "5672:5672"
+ - "15672:15672" # management UI, for development
# Mock SMTP server
maildev:
diff --git a/crates/bindings/node/src/lib.rs b/crates/bindings/node/src/lib.rs
index a2030d73c..85b391834 100644
--- a/crates/bindings/node/src/lib.rs
+++ b/crates/bindings/node/src/lib.rs
@@ -7,25 +7,25 @@ use neon::prelude::*;
use revolt_database::{Database, DatabaseInfo};
fn js_init(mut cx: FunctionContext) -> JsResult {
- static INIT: OnceLock<()> = OnceLock::new();
- if INIT.get().is_none() {
- INIT.get_or_init(|| {
- async_std::task::block_on(async {
- revolt_config::configure!(api);
-
- match DatabaseInfo::Auto.connect().await {
- Ok(db) => {
- let authifier_db = db.clone().to_authifier().await.database;
- revolt_database::tasks::start_workers(db, authifier_db);
- Ok(())
- }
- Err(err) => Err(err),
- }
- })
- .or_else(|err| cx.throw_error(err))
- .unwrap();
- });
- }
+ // static INIT: OnceLock<()> = OnceLock::new();
+ // if INIT.get().is_none() {
+ // INIT.get_or_init(|| {
+ // async_std::task::block_on(async {
+ // revolt_config::configure!(api);
+
+ // match DatabaseInfo::Auto.connect().await {
+ // Ok(db) => {
+ // let authifier_db = db.clone().to_authifier().await.database;
+ // revolt_database::tasks::start_workers(db, authifier_db);
+ // Ok(())
+ // }
+ // Err(err) => Err(err),
+ // }
+ // })
+ // .or_else(|err| cx.throw_error(err))
+ // .unwrap();
+ // });
+ // }
Ok(cx.undefined())
}
diff --git a/crates/bonfire/Cargo.toml b/crates/bonfire/Cargo.toml
index 151d1ded7..c91723b32 100644
--- a/crates/bonfire/Cargo.toml
+++ b/crates/bonfire/Cargo.toml
@@ -36,7 +36,7 @@ async-std = { version = "1.8.0", features = [
] }
# core
-authifier = { version = "1.0.8" }
+authifier = { version = "1.0.9" }
revolt-result = { path = "../core/result" }
revolt-models = { path = "../core/models" }
revolt-config = { path = "../core/config" }
diff --git a/crates/core/config/Revolt.test.toml b/crates/core/config/Revolt.test.toml
index 084a46ee0..7ac98ee26 100644
--- a/crates/core/config/Revolt.test.toml
+++ b/crates/core/config/Revolt.test.toml
@@ -1,3 +1,9 @@
[database]
mongodb = "mongodb://localhost"
redis = "redis://localhost/"
+
+[rabbit]
+host = "127.0.0.1"
+port = 5672
+username = "rabbituser"
+password = "rabbitpass"
diff --git a/crates/core/config/Revolt.toml b/crates/core/config/Revolt.toml
index 359c0e998..e18165972 100644
--- a/crates/core/config/Revolt.toml
+++ b/crates/core/config/Revolt.toml
@@ -20,6 +20,12 @@ january = "http://local.revolt.chat/january"
voso_legacy = ""
voso_legacy_ws = ""
+[rabbit]
+host = "127.0.0.1"
+port = 5672
+username = "guest"
+password = "guest"
+
[api]
[api.registration]
@@ -38,17 +44,45 @@ from_address = "noreply@example.com"
# port = 587
# use_tls = true
-[api.vapid]
-# Generate your own keys:
-# 1. Run `openssl ecparam -name prime256v1 -genkey -noout -out vapid_private.pem`
-# 2. Find `private_key` using `base64 vapid_private.pem`
-# 3. Find `public_key` using `openssl ec -in vapid_private.pem -outform DER|tail -c 65|base64|tr '/+' '_-'|tr -d '\n'`
+
+[api.security]
+# Authifier Shield API key
+authifier_shield_key = ""
+# Legacy voice server management token
+voso_legacy_token = ""
+# Whether services are behind the Cloudflare network
+trust_cloudflare = false
+
+[api.security.captcha]
+# hCaptcha configuration
+hcaptcha_key = ""
+hcaptcha_sitekey = ""
+
+[api.workers]
+# Maximum concurrent connections (to proxy server)
+max_concurrent_connections = 50
+
+[pushd]
+# this changes the names of the queues to not overlap
+# prod/beta if they happen to be on the same exchange/instance.
+# Usually they have to be, so that messages sent from one or the other get sent to everyone
+production = true
+
+# none of these should need changing
+exchange = "revolt.notifications"
+message_queue = "notifications.origin.message"
+fr_accepted_queue = "notifications.ingest.fr_accepted" # friend request accepted
+fr_received_queue = "notifications.ingest.fr_received" # friend request received
+generic_queue = "notifications.ingest.generic" # generic messages (title + body)
+ack_queue = "notifications.process.ack" # updates badges for apple devices
+
+[pushd.vapid]
+queue = "notifications.outbound.vapid"
private_key = "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUJSUWpyTWxLRnBiVWhsUHpUbERvcEliYk1yeVNrNXpKYzVYVzIxSjJDS3hvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFWnkrQkg2TGJQZ2hEa3pEempXOG0rUXVPM3pCajRXT1phdkR6ZU00c0pqbmFwd1psTFE0WAp1ZDh2TzVodU94QWhMQlU3WWRldVovWHlBdFpWZmNyQi9BPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo"
public_key = "BGcvgR-i2z4IQ5Mw841vJvkLjt8wY-FjmWrw83jOLCY52qcGZS0OF7nfLzuYbjsQISwVO2HXrmf18gLWVX3Kwfw="
-[api.fcm]
-# Google Firebase Cloud Messaging Service Account Key
-# Obtained from the cloud messaging console
+[pushd.fcm]
+queue = "notifications.outbound.fcm"
key_type = ""
project_id = ""
private_key_id = ""
@@ -60,29 +94,13 @@ token_uri = ""
auth_provider_x509_cert_url = ""
client_x509_cert_url = ""
-[api.apn]
-# Apple Push Notifications keys for sending notifications
+[pushd.apn]
sandbox = false
+queue = "notifications.outbound.apn"
pkcs8 = ""
key_id = ""
team_id = ""
-[api.security]
-# Authifier Shield API key
-authifier_shield_key = ""
-# Legacy voice server management token
-voso_legacy_token = ""
-# Whether services are behind the Cloudflare network
-trust_cloudflare = false
-
-[api.security.captcha]
-# hCaptcha configuration
-hcaptcha_key = ""
-hcaptcha_sitekey = ""
-
-[api.workers]
-# Maximum concurrent connections (to proxy server)
-max_concurrent_connections = 50
[files]
# Encryption key for stored files
@@ -149,10 +167,11 @@ region = "minio"
access_key_id = "minioautumn"
# S3 protocol access key
secret_access_key = "minioautumn"
-# Bucket to upload to by default
default_bucket = "revolt-uploads"
+
[features]
+# Bucket to upload to by default
# Feature gate options
webhooks_enabled = false
@@ -228,6 +247,11 @@ icons = 2_500_000
banners = 6_000_000
emojis = 500_000
+[features.advanced]
+# The max amount of messages the rabbitmq provider/db mention adder job will delay for before forcing handling of a channel.
+# default: 5
+process_message_delay_limit = 5
+
[sentry]
# Configuration for Sentry error reporting
api = ""
diff --git a/crates/core/config/src/lib.rs b/crates/core/config/src/lib.rs
index 8913dfb78..b103a0718 100644
--- a/crates/core/config/src/lib.rs
+++ b/crates/core/config/src/lib.rs
@@ -79,6 +79,14 @@ pub struct Database {
pub redis: String,
}
+#[derive(Deserialize, Debug, Clone)]
+pub struct Rabbit {
+ pub host: String,
+ pub port: u16,
+ pub username: String,
+ pub password: String,
+}
+
#[derive(Deserialize, Debug, Clone)]
pub struct Hosts {
pub app: String,
@@ -107,13 +115,15 @@ pub struct ApiSmtp {
}
#[derive(Deserialize, Debug, Clone)]
-pub struct ApiVapid {
+pub struct PushVapid {
+ pub queue: String,
pub private_key: String,
pub public_key: String,
}
#[derive(Deserialize, Debug, Clone)]
-pub struct ApiFcm {
+pub struct PushFcm {
+ pub queue: String,
pub key_type: String,
pub project_id: String,
pub private_key_id: String,
@@ -127,7 +137,8 @@ pub struct ApiFcm {
}
#[derive(Deserialize, Debug, Clone)]
-pub struct ApiApn {
+pub struct PushApn {
+ pub queue: String,
pub sandbox: bool,
pub pkcs8: String,
pub key_id: String,
@@ -157,13 +168,54 @@ pub struct ApiWorkers {
pub struct Api {
pub registration: ApiRegistration,
pub smtp: ApiSmtp,
- pub vapid: ApiVapid,
- pub fcm: ApiFcm,
- pub apn: ApiApn,
pub security: ApiSecurity,
pub workers: ApiWorkers,
}
+#[derive(Deserialize, Debug, Clone)]
+pub struct Pushd {
+ pub production: bool,
+ pub exchange: String,
+ pub message_queue: String,
+ pub fr_accepted_queue: String,
+ pub fr_received_queue: String,
+ pub generic_queue: String,
+ pub ack_queue: String,
+
+ pub vapid: PushVapid,
+ pub fcm: PushFcm,
+ pub apn: PushApn,
+}
+
+impl Pushd {
+ fn get_routing_key(&self, key: String) -> String {
+ match self.production {
+ true => key + "-prd",
+ false => key + "-tst",
+ }
+ }
+
+ pub fn get_ack_routing_key(&self) -> String {
+ self.get_routing_key(self.ack_queue.clone())
+ }
+
+ pub fn get_message_routing_key(&self) -> String {
+ self.get_routing_key(self.message_queue.clone())
+ }
+
+ pub fn get_fr_accepted_routing_key(&self) -> String {
+ self.get_routing_key(self.fr_accepted_queue.clone())
+ }
+
+ pub fn get_fr_received_routing_key(&self) -> String {
+ self.get_routing_key(self.fr_received_queue.clone())
+ }
+
+ pub fn get_generic_routing_key(&self) -> String {
+ self.get_routing_key(self.generic_queue.clone())
+ }
+}
+
#[derive(Deserialize, Debug, Clone)]
pub struct FilesLimit {
pub min_file_size: usize,
@@ -233,10 +285,26 @@ pub struct FeaturesLimitsCollection {
pub roles: HashMap,
}
+#[derive(Deserialize, Debug, Clone)]
+pub struct FeaturesAdvanced {
+ #[serde(default)]
+ pub process_message_delay_limit: u16,
+}
+
+impl Default for FeaturesAdvanced {
+ fn default() -> Self {
+ Self {
+ process_message_delay_limit: 5,
+ }
+ }
+}
+
#[derive(Deserialize, Debug, Clone)]
pub struct Features {
pub limits: FeaturesLimitsCollection,
pub webhooks_enabled: bool,
+ #[serde(default)]
+ pub advanced: FeaturesAdvanced,
}
#[derive(Deserialize, Debug, Clone)]
@@ -250,8 +318,10 @@ pub struct Sentry {
#[derive(Deserialize, Debug, Clone)]
pub struct Settings {
pub database: Database,
+ pub rabbit: Rabbit,
pub hosts: Hosts,
pub api: Api,
+ pub pushd: Pushd,
pub files: Files,
pub features: Features,
pub sentry: Sentry,
diff --git a/crates/core/database/Cargo.toml b/crates/core/database/Cargo.toml
index d1b280685..2be799feb 100644
--- a/crates/core/database/Cargo.toml
+++ b/crates/core/database/Cargo.toml
@@ -84,11 +84,11 @@ axum = { version = "0.7.5", optional = true }
# Rocket Impl
schemars = { version = "0.8.8", optional = true }
-rocket = { version = "0.5.0-rc.2", default-features = false, features = [
+rocket = { version = "0.5.1", default-features = false, features = [
"json",
], optional = true }
revolt_okapi = { version = "0.9.1", optional = true }
-revolt_rocket_okapi = { version = "0.9.1", optional = true }
+revolt_rocket_okapi = { version = "0.10.0", optional = true }
# Notifications
fcm_v1 = "0.3.0"
@@ -96,4 +96,7 @@ web-push = "0.10.0"
revolt_a2 = { version = "0.10", default-features = false, features = ["ring"] }
# Authifier
-authifier = { version = "1.0.8" }
+authifier = { version = "1.0.9", features = ["rocket_impl"] }
+
+# RabbitMQ
+amqprs = { version = "1.7.0" }
diff --git a/crates/core/database/src/amqp/amqp.rs b/crates/core/database/src/amqp/amqp.rs
new file mode 100644
index 000000000..39b4820eb
--- /dev/null
+++ b/crates/core/database/src/amqp/amqp.rs
@@ -0,0 +1,211 @@
+use std::collections::HashSet;
+
+use crate::events::rabbit::*;
+use crate::User;
+use amqprs::channel::BasicPublishArguments;
+use amqprs::{channel::Channel, connection::Connection, error::Error as AMQPError};
+use amqprs::{BasicProperties, FieldTable};
+use revolt_models::v0::PushNotification;
+use revolt_presence::filter_online;
+
+use serde_json::to_string;
+
+#[derive(Clone)]
+pub struct AMQP {
+ #[allow(unused)]
+ connection: Connection,
+ channel: Channel,
+}
+
+impl AMQP {
+ pub fn new(connection: Connection, channel: Channel) -> AMQP {
+ AMQP {
+ connection,
+ channel,
+ }
+ }
+
+ pub async fn friend_request_accepted(
+ &self,
+ accepted_request_user: &User,
+ sent_request_user: &User,
+ ) -> Result<(), AMQPError> {
+ let config = revolt_config::config().await;
+ let payload = FRAcceptedPayload {
+ accepted_user: accepted_request_user.to_owned(),
+ user: sent_request_user.id.clone(),
+ };
+ let payload = to_string(&payload).unwrap();
+
+ debug!(
+ "Sending friend request accept payload on channel {}: {}",
+ config.pushd.get_fr_accepted_routing_key(),
+ payload
+ );
+ self.channel
+ .basic_publish(
+ BasicProperties::default()
+ .with_content_type("application/json")
+ .with_persistence(true)
+ .finish(),
+ payload.into(),
+ BasicPublishArguments::new(
+ &config.pushd.exchange,
+ &config.pushd.get_fr_accepted_routing_key(),
+ ),
+ )
+ .await
+ }
+
+ pub async fn friend_request_received(
+ &self,
+ received_request_user: &User,
+ sent_request_user: &User,
+ ) -> Result<(), AMQPError> {
+ let config = revolt_config::config().await;
+ let payload = FRReceivedPayload {
+ from_user: sent_request_user.to_owned(),
+ user: received_request_user.id.clone(),
+ };
+ let payload = to_string(&payload).unwrap();
+
+ debug!(
+ "Sending friend request received payload on channel {}: {}",
+ config.pushd.get_fr_received_routing_key(),
+ payload
+ );
+
+ self.channel
+ .basic_publish(
+ BasicProperties::default()
+ .with_content_type("application/json")
+ .with_persistence(true)
+ .finish(),
+ payload.into(),
+ BasicPublishArguments::new(
+ &config.pushd.exchange,
+ &config.pushd.get_fr_received_routing_key(),
+ ),
+ )
+ .await
+ }
+
+ pub async fn generic_message(
+ &self,
+ user: &User,
+ title: String,
+ body: String,
+ icon: Option,
+ ) -> Result<(), AMQPError> {
+ let config = revolt_config::config().await;
+ let payload = GenericPayload {
+ title,
+ body,
+ icon,
+ user: user.to_owned(),
+ };
+ let payload = to_string(&payload).unwrap();
+
+ debug!(
+ "Sending generic payload on channel {}: {}",
+ config.pushd.get_generic_routing_key(),
+ payload
+ );
+
+ self.channel
+ .basic_publish(
+ BasicProperties::default()
+ .with_content_type("application/json")
+ .with_persistence(true)
+ .finish(),
+ payload.into(),
+ BasicPublishArguments::new(
+ &config.pushd.exchange,
+ &config.pushd.get_generic_routing_key(),
+ ),
+ )
+ .await
+ }
+
+ pub async fn message_sent(
+ &self,
+ recipients: Vec,
+ payload: PushNotification,
+ ) -> Result<(), AMQPError> {
+ if recipients.is_empty() {
+ return Ok(());
+ }
+
+ let config = revolt_config::config().await;
+
+ let online_ids = filter_online(&recipients).await;
+ let recipients = (&recipients.into_iter().collect::>() - &online_ids)
+ .into_iter()
+ .collect::>();
+
+ let payload = MessageSentPayload {
+ notification: payload,
+ users: recipients,
+ };
+ let payload = to_string(&payload).unwrap();
+
+ debug!(
+ "Sending message payload on channel {}: {}",
+ config.pushd.get_message_routing_key(),
+ payload
+ );
+
+ self.channel
+ .basic_publish(
+ BasicProperties::default()
+ .with_content_type("application/json")
+ .with_persistence(true)
+ .finish(),
+ payload.into(),
+ BasicPublishArguments::new(
+ &config.pushd.exchange,
+ &config.pushd.get_message_routing_key(),
+ ),
+ )
+ .await
+ }
+
+ pub async fn ack_message(
+ &self,
+ user_id: String,
+ channel_id: String,
+ message_id: String,
+ ) -> Result<(), AMQPError> {
+ let config = revolt_config::config().await;
+
+ let payload = AckPayload {
+ user_id: user_id.clone(),
+ channel_id: channel_id.clone(),
+ message_id,
+ };
+ let payload = to_string(&payload).unwrap();
+
+ info!(
+ "Sending ack payload on channel {}: {}",
+ config.pushd.ack_queue, payload
+ );
+
+ let mut headers = FieldTable::new();
+ headers.insert(
+ "x-deduplication-header".try_into().unwrap(),
+ format!("{}-{}", &user_id, &channel_id).into(),
+ );
+
+ self.channel
+ .basic_publish(
+ BasicProperties::default()
+ .with_content_type("application/json")
+ .with_persistence(true)
+ //.with_headers(headers)
+ .finish(),
+ payload.into(),
+ BasicPublishArguments::new(&config.pushd.exchange, &config.pushd.ack_queue),
+ )
+ .await
+ }
+}
diff --git a/crates/core/database/src/amqp/mod.rs b/crates/core/database/src/amqp/mod.rs
new file mode 100644
index 000000000..9ed09d345
--- /dev/null
+++ b/crates/core/database/src/amqp/mod.rs
@@ -0,0 +1,2 @@
+#[allow(clippy::module_inception)]
+pub mod amqp;
diff --git a/crates/core/database/src/events/mod.rs b/crates/core/database/src/events/mod.rs
index c07f47e0f..608984357 100644
--- a/crates/core/database/src/events/mod.rs
+++ b/crates/core/database/src/events/mod.rs
@@ -1,2 +1,3 @@
pub mod client;
+pub mod rabbit;
pub mod server;
diff --git a/crates/core/database/src/events/rabbit.rs b/crates/core/database/src/events/rabbit.rs
new file mode 100644
index 000000000..613047521
--- /dev/null
+++ b/crates/core/database/src/events/rabbit.rs
@@ -0,0 +1,59 @@
+use std::collections::HashMap;
+
+use revolt_models::v0::PushNotification;
+use serde::{Deserialize, Serialize};
+
+use crate::User;
+
+#[derive(Serialize, Deserialize)]
+pub struct MessageSentPayload {
+ pub notification: PushNotification,
+ pub users: Vec,
+}
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct FRAcceptedPayload {
+ pub accepted_user: User,
+ pub user: String,
+}
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct FRReceivedPayload {
+ pub from_user: User,
+ pub user: String,
+}
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct GenericPayload {
+ pub title: String,
+ pub body: String,
+ pub icon: Option,
+ pub user: User,
+}
+
+#[derive(Serialize, Deserialize)]
+#[serde(tag = "type", content = "data")]
+#[allow(clippy::large_enum_variant)]
+pub enum PayloadKind {
+ MessageNotification(PushNotification),
+ FRAccepted(FRAcceptedPayload),
+ FRReceived(FRReceivedPayload),
+ BadgeUpdate(usize),
+ Generic(GenericPayload),
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct PayloadToService {
+ pub notification: PayloadKind,
+ pub user_id: String,
+ pub session_id: String,
+ pub token: String,
+ pub extras: HashMap,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct AckPayload {
+ pub user_id: String,
+ pub channel_id: String,
+ pub message_id: String,
+}
diff --git a/crates/core/database/src/lib.rs b/crates/core/database/src/lib.rs
index e48821b40..48f93f81a 100644
--- a/crates/core/database/src/lib.rs
+++ b/crates/core/database/src/lib.rs
@@ -85,6 +85,9 @@ pub use models::*;
pub mod events;
pub mod tasks;
+mod amqp;
+pub use amqp::amqp::AMQP;
+
/// Utility function to check if a boolean value is false
pub fn if_false(t: &bool) -> bool {
!t
diff --git a/crates/core/database/src/models/channel_unreads/ops.rs b/crates/core/database/src/models/channel_unreads/ops.rs
index 4d115069e..6a6e98af3 100644
--- a/crates/core/database/src/models/channel_unreads/ops.rs
+++ b/crates/core/database/src/models/channel_unreads/ops.rs
@@ -26,6 +26,9 @@ pub trait AbstractChannelUnreads: Sync + Send {
message_ids: &[String],
) -> Result<()>;
+ /// Fetch all unreads with mentions for a user.
+ async fn fetch_unread_mentions(&self, user_id: &str) -> Result>;
+
/// Fetch all channel unreads for a user.
async fn fetch_unreads(&self, user_id: &str) -> Result>;
diff --git a/crates/core/database/src/models/channel_unreads/ops/mongodb.rs b/crates/core/database/src/models/channel_unreads/ops/mongodb.rs
index e2dfedb17..c237afc65 100644
--- a/crates/core/database/src/models/channel_unreads/ops/mongodb.rs
+++ b/crates/core/database/src/models/channel_unreads/ops/mongodb.rs
@@ -123,6 +123,18 @@ impl AbstractChannelUnreads for MongoDb {
)
}
+ async fn fetch_unread_mentions(&self, user_id: &str) -> Result> {
+ query! {
+ self,
+ find,
+ COL,
+ doc! {
+ "_id.user": user_id,
+ "mentions": {"$ne": null}
+ }
+ }
+ }
+
/// Fetch unread for a specific user in a channel.
async fn fetch_unread(&self, user_id: &str, channel_id: &str) -> Result