Compare commits

...

8 Commits

Author SHA1 Message Date
kozabrada123 9791b13921
Merge 7683ce49a3 into e4dd31ef78 2024-08-08 17:14:57 +00:00
kozabrada123 7683ce49a3 feat: add create_pomelo_migration 2024-08-08 19:14:39 +02:00
Flori e4dd31ef78
sqlx related improvements (#542)
* Bump sqlx to 0.8.0

* Update sqlx syntax to 0.8.0, change MySql for sqlx:: Any

* Update sqlx syntax to 0.8.0, change MySql for sqlx:: Any

* Modify chorus_macros::SqlxBitflagDerive to use sqlx::Any over sqlx::MySql (broken!)

* Fix: `cannot infer type for type parameter `DB` declared on the trait...`

* Change remaining impls of sqlx traits for MySql to sqlx::Any

* Alter chorus_macros to correctly derive SqlxBitFlag for sqlx::Any

* rustc/clippy>=v1.80.0: Do not warn when encountering cfg(tarpaulin_include)

* Port compare_* methods to sqlx v0.8.0
2024-08-04 13:08:56 +02:00
Flori ab82a5d49a
Update MSRV (#540)
* Update msrv
2024-08-02 21:12:38 +02:00
Flori 2bd9fbaa9c
bump versions of packages to latest compatible versions (#536) 2024-07-28 12:35:26 +02:00
bitfl0wer f2f45b4b86
bump versions of packages to latest compatible versions 2024-07-28 12:28:56 +02:00
Flori 582173234f
Manually implement std::default::Default for GatewayHeartbeat and Gat… (#535)
Manually implement std::default::Default for GatewayHeartbeat and
GatewayHeartbeatAck with the correct opcodes.
2024-07-28 11:49:49 +02:00
bitfl0wer 7bba7c6fcb
Manually implement std::default::Default for GatewayHeartbeat and GatewayHeartbeatAck 2024-07-27 15:31:47 +02:00
12 changed files with 292 additions and 155 deletions

143
Cargo.lock generated
View File

@ -34,7 +34,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"getrandom",
"once_cell", "once_cell",
"version_check", "version_check",
"zerocopy", "zerocopy",
@ -292,6 +291,15 @@ dependencies = [
"zeroize", "zeroize",
] ]
[[package]]
name = "concurrent-queue"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
dependencies = [
"crossbeam-utils",
]
[[package]] [[package]]
name = "console_error_panic_hook" name = "console_error_panic_hook"
version = "0.1.7" version = "0.1.7"
@ -541,9 +549,14 @@ dependencies = [
[[package]] [[package]]
name = "event-listener" name = "event-listener"
version = "2.5.3" version = "5.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba"
dependencies = [
"concurrent-queue",
"parking",
"pin-project-lite",
]
[[package]] [[package]]
name = "fastrand" name = "fastrand"
@ -773,9 +786,9 @@ dependencies = [
[[package]] [[package]]
name = "hashlink" name = "hashlink"
version = "0.8.4" version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af"
dependencies = [ dependencies = [
"hashbrown 0.14.5", "hashbrown 0.14.5",
] ]
@ -806,12 +819,9 @@ dependencies = [
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.4.1" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
dependencies = [
"unicode-segmentation",
]
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
@ -1141,9 +1151,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]] [[package]]
name = "libsqlite3-sys" name = "libsqlite3-sys"
version = "0.27.0" version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f"
dependencies = [ dependencies = [
"cc", "cc",
"pkg-config", "pkg-config",
@ -1227,13 +1237,14 @@ dependencies = [
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.8.11" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
dependencies = [ dependencies = [
"hermit-abi",
"libc", "libc",
"wasi", "wasi",
"windows-sys 0.48.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -1345,16 +1356,6 @@ dependencies = [
"libm", "libm",
] ]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]] [[package]]
name = "object" name = "object"
version = "0.36.1" version = "0.36.1"
@ -1376,6 +1377,12 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "parking"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.12.3" version = "0.12.3"
@ -1597,9 +1604,9 @@ dependencies = [
[[package]] [[package]]
name = "pubserve" name = "pubserve"
version = "1.1.0-alpha.1" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1781b2a51798c98a381e839e61bc5ce6426bd89bb9c3f9142de2086a80591cd" checksum = "6a2cf5f495fc9c61de736666ebcbc473fe28a2a1aaf7e5619e5925b13c0275a4"
dependencies = [ dependencies = [
"async-trait", "async-trait",
] ]
@ -1972,9 +1979,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_with" name = "serde_with"
version = "3.8.3" version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e73139bc5ec2d45e6c5fd85be5a46949c1c39a4c18e56915f5eb4c12f975e377" checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"chrono", "chrono",
@ -1990,9 +1997,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_with_macros" name = "serde_with_macros"
version = "3.8.3" version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b80d3d6b56b64335c0180e5ffde23b3c5e08c14c585b51a15bd0e95393f46703" checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350"
dependencies = [ dependencies = [
"darling", "darling",
"proc-macro2", "proc-macro2",
@ -2068,6 +2075,9 @@ name = "smallvec"
version = "1.13.2" version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "socket2" name = "socket2"
@ -2116,9 +2126,9 @@ dependencies = [
[[package]] [[package]]
name = "sqlx" name = "sqlx"
version = "0.7.4" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" checksum = "27144619c6e5802f1380337a209d2ac1c431002dd74c6e60aebff3c506dc4f0c"
dependencies = [ dependencies = [
"sqlx-core", "sqlx-core",
"sqlx-macros", "sqlx-macros",
@ -2129,11 +2139,10 @@ dependencies = [
[[package]] [[package]]
name = "sqlx-core" name = "sqlx-core"
version = "0.7.4" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6" checksum = "a999083c1af5b5d6c071d34a708a19ba3e02106ad82ef7bbd69f5e48266b613b"
dependencies = [ dependencies = [
"ahash",
"atoi", "atoi",
"byteorder", "byteorder",
"bytes", "bytes",
@ -2147,6 +2156,7 @@ dependencies = [
"futures-intrusive", "futures-intrusive",
"futures-io", "futures-io",
"futures-util", "futures-util",
"hashbrown 0.14.5",
"hashlink", "hashlink",
"hex", "hex",
"indexmap 2.2.6", "indexmap 2.2.6",
@ -2173,22 +2183,22 @@ dependencies = [
[[package]] [[package]]
name = "sqlx-macros" name = "sqlx-macros"
version = "0.7.4" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127" checksum = "a23217eb7d86c584b8cbe0337b9eacf12ab76fe7673c513141ec42565698bb88"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"sqlx-core", "sqlx-core",
"sqlx-macros-core", "sqlx-macros-core",
"syn 1.0.109", "syn 2.0.70",
] ]
[[package]] [[package]]
name = "sqlx-macros-core" name = "sqlx-macros-core"
version = "0.7.4" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" checksum = "1a099220ae541c5db479c6424bdf1b200987934033c2584f79a0e1693601e776"
dependencies = [ dependencies = [
"dotenvy", "dotenvy",
"either", "either",
@ -2204,7 +2214,7 @@ dependencies = [
"sqlx-mysql", "sqlx-mysql",
"sqlx-postgres", "sqlx-postgres",
"sqlx-sqlite", "sqlx-sqlite",
"syn 1.0.109", "syn 2.0.70",
"tempfile", "tempfile",
"tokio", "tokio",
"url", "url",
@ -2212,12 +2222,12 @@ dependencies = [
[[package]] [[package]]
name = "sqlx-mysql" name = "sqlx-mysql"
version = "0.7.4" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" checksum = "5afe4c38a9b417b6a9a5eeffe7235d0a106716495536e7727d1c7f4b1ff3eba6"
dependencies = [ dependencies = [
"atoi", "atoi",
"base64 0.21.7", "base64 0.22.1",
"bitflags 2.6.0", "bitflags 2.6.0",
"byteorder", "byteorder",
"bytes", "bytes",
@ -2255,12 +2265,12 @@ dependencies = [
[[package]] [[package]]
name = "sqlx-postgres" name = "sqlx-postgres"
version = "0.7.4" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" checksum = "b1dbb157e65f10dbe01f729339c06d239120221c9ad9fa0ba8408c4cc18ecf21"
dependencies = [ dependencies = [
"atoi", "atoi",
"base64 0.21.7", "base64 0.22.1",
"bitflags 2.6.0", "bitflags 2.6.0",
"byteorder", "byteorder",
"chrono", "chrono",
@ -2295,9 +2305,9 @@ dependencies = [
[[package]] [[package]]
name = "sqlx-sqlite" name = "sqlx-sqlite"
version = "0.7.4" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" checksum = "9b2cdd83c008a622d94499c0006d8ee5f821f36c89b7d625c900e5dc30b5c5ee"
dependencies = [ dependencies = [
"atoi", "atoi",
"chrono", "chrono",
@ -2311,10 +2321,10 @@ dependencies = [
"log", "log",
"percent-encoding", "percent-encoding",
"serde", "serde",
"serde_urlencoded",
"sqlx-core", "sqlx-core",
"tracing", "tracing",
"url", "url",
"urlencoding",
] ]
[[package]] [[package]]
@ -2412,18 +2422,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.61" version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.61" version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2478,26 +2488,25 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.38.0" version = "1.39.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
"libc", "libc",
"mio", "mio",
"num_cpus",
"pin-project-lite", "pin-project-lite",
"socket2", "socket2",
"tokio-macros", "tokio-macros",
"windows-sys 0.48.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
name = "tokio-macros" name = "tokio-macros"
version = "2.3.0" version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2685,12 +2694,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291"
[[package]]
name = "unicode-segmentation"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
[[package]] [[package]]
name = "unicode_categories" name = "unicode_categories"
version = "0.1.1" version = "0.1.1"
@ -2730,12 +2733,6 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "urlencoding"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]] [[package]]
name = "utf-8" name = "utf-8"
version = "0.7.6" version = "0.7.6"

View File

@ -8,7 +8,7 @@ repository = "https://github.com/polyphony-chat/chorus"
readme = "README.md" readme = "README.md"
keywords = ["spacebar", "discord", "polyphony"] keywords = ["spacebar", "discord", "polyphony"]
website = ["https://discord.com/invite/m3FpcapGDD"] website = ["https://discord.com/invite/m3FpcapGDD"]
rust-version = "1.67.1" rust-version = "1.70.0"
[features] [features]
@ -22,33 +22,33 @@ voice_udp = ["dep:discortp", "dep:crypto_secretbox"]
voice_gateway = [] voice_gateway = []
[dependencies] [dependencies]
tokio = { version = "1.35.1", features = ["macros", "sync"] } tokio = { version = "1.38.1", features = ["macros", "sync"] }
serde = { version = "1.0.195", features = ["derive", "rc"] } serde = { version = "1.0.204", features = ["derive", "rc"] }
serde_json = { version = "1.0.111", features = ["raw_value"] } serde_json = { version = "1.0.120", features = ["raw_value"] }
serde-aux = "4.3.1" serde-aux = "4.5.0"
serde_with = "3.4.0" serde_with = "3.9.0"
serde_repr = "0.1.18" serde_repr = "0.1.19"
reqwest = { features = [ reqwest = { features = [
"multipart", "multipart",
"json", "json",
"rustls-tls-webpki-roots", "rustls-tls-webpki-roots",
], version = "=0.11.26", default-features = false } ], version = "=0.11.26", default-features = false }
url = "2.5.0" url = "2.5.2"
chrono = { version = "0.4.31", features = ["serde"] } chrono = { version = "0.4.38", features = ["serde"] }
regex = "1.10.2" regex = "1.10.5"
custom_error = "1.9.2" custom_error = "1.9.2"
futures-util = "0.3.30" futures-util = "0.3.30"
http = "0.2.12" http = "0.2.12"
base64 = "0.21.7" base64 = "0.21.7"
bitflags = { version = "2.4.1", features = ["serde"] } bitflags = { version = "2.6.0", features = ["serde"] }
lazy_static = "1.4.0" lazy_static = "1.5.0"
poem = { version = "3.0.1", features = ["multipart"], optional = true } poem = { version = "3.0.1", features = ["multipart"], optional = true }
thiserror = "1.0.56" thiserror = "1.0.63"
jsonwebtoken = "8.3.0" jsonwebtoken = "8.3.0"
log = "0.4.20" log = "0.4.22"
async-trait = "0.1.77" async-trait = "0.1.81"
chorus-macros = { path = "./chorus-macros", version = "0" } # Note: version here is used when releasing. This will use the latest release. Make sure to republish the crate when code in macros is changed! chorus-macros = { path = "./chorus-macros", version = "0" } # Note: version here is used when releasing. This will use the latest release. Make sure to republish the crate when code in macros is changed!
sqlx = { version = "0.7.3", features = [ sqlx = { version = "0.8.0", features = [
"mysql", "mysql",
"sqlite", "sqlite",
"json", "json",
@ -66,24 +66,27 @@ crypto_secretbox = { version = "0.1.1", optional = true }
rand = "0.8.5" rand = "0.8.5"
flate2 = { version = "1.0.30", optional = true } flate2 = { version = "1.0.30", optional = true }
webpki-roots = "0.26.3" webpki-roots = "0.26.3"
pubserve = { version = "1.1.0-alpha.1", features = ["async", "send"] } pubserve = { version = "1.1.0", features = ["async", "send"] }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]
rustls = "0.21.10" rustls = "0.21.12"
tokio-tungstenite = { version = "0.20.1", features = [ tokio-tungstenite = { version = "0.20.1", features = [
"rustls-tls-webpki-roots", "rustls-tls-webpki-roots",
] } ] }
hostname = "0.3.1" hostname = "0.3.1"
getrandom = { version = "0.2.12" } getrandom = { version = "0.2.15" }
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2.12", features = ["js"] } getrandom = { version = "0.2.15", features = ["js"] }
ws_stream_wasm = "0.7.4" ws_stream_wasm = "0.7.4"
wasm-bindgen-futures = "0.4.39" wasm-bindgen-futures = "0.4.42"
wasmtimer = "0.2.0" wasmtimer = "0.2.0"
[dev-dependencies] [dev-dependencies]
lazy_static = "1.4.0" lazy_static = "1.5.0"
wasm-bindgen-test = "0.3.42" wasm-bindgen-test = "0.3.42"
wasm-bindgen = "0.2.92" wasm-bindgen = "0.2.92"
simple_logger = { version = "5.0.0", default-features = false } simple_logger = { version = "5.0.0", default-features = false }
[lints.rust]
unexpected_cfgs = { level = "allow", check-cfg = ['cfg(tarpaulin_include)'] }

View File

@ -119,11 +119,11 @@ We recommend checking out the "examples" directory, as well as the documentation
## MSRV (Minimum Supported Rust Version) ## MSRV (Minimum Supported Rust Version)
Rust **1.67.1**. This number might change at any point while Chorus is not yet at version 1.0.0. Rust **1.70.0**. This number might change at any point while Chorus is not yet at version 1.0.0.
## Development Setup ## Development Setup
Make sure that you have at least Rust 1.67.1 installed. You can check your Rust version by running `cargo --version` Make sure that you have at least Rust 1.70.0 installed. You can check your Rust version by running `cargo --version`
in your terminal. To compile for `wasm32-unknown-unknown`, you need to install the `wasm32-unknown-unknown` target. in your terminal. To compile for `wasm32-unknown-unknown`, you need to install the `wasm32-unknown-unknown` target.
You can do this by running `rustup target add wasm32-unknown-unknown`. You can do this by running `rustup target add wasm32-unknown-unknown`.

View File

@ -156,7 +156,6 @@ pub fn composite_derive(input: TokenStream) -> TokenStream {
} }
} }
#[proc_macro_derive(SqlxBitFlags)] #[proc_macro_derive(SqlxBitFlags)]
pub fn sqlx_bitflag_derive(input: TokenStream) -> TokenStream { pub fn sqlx_bitflag_derive(input: TokenStream) -> TokenStream {
let ast: syn::DeriveInput = syn::parse(input).unwrap(); let ast: syn::DeriveInput = syn::parse(input).unwrap();
@ -165,25 +164,46 @@ pub fn sqlx_bitflag_derive(input: TokenStream) -> TokenStream {
quote!{ quote!{
#[cfg(feature = "sqlx")] #[cfg(feature = "sqlx")]
impl sqlx::Type<sqlx::MySql> for #name { impl sqlx::Type<sqlx::Any> for #name {
fn type_info() -> sqlx::mysql::MySqlTypeInfo { fn type_info() -> sqlx::any::AnyTypeInfo {
u64::type_info() <Vec<u8> as sqlx::Type<sqlx::Any>>::type_info()
} }
} }
#[cfg(feature = "sqlx")] #[cfg(feature = "sqlx")]
impl<'q> sqlx::Encode<'q, sqlx::MySql> for #name { impl<'q> sqlx::Encode<'q, sqlx::Any> for #name {
fn encode_by_ref(&self, buf: &mut <sqlx::MySql as sqlx::database::HasArguments<'q>>::ArgumentBuffer) -> sqlx::encode::IsNull { fn encode_by_ref(&self, buf: &mut <sqlx::Any as sqlx::Database>::ArgumentBuffer<'q>) -> Result<sqlx::encode::IsNull, sqlx::error::BoxDynError> {
u64::encode_by_ref(&self.bits(), buf) <Vec<u8> as sqlx::Encode<sqlx::Any>>::encode_by_ref(&self.bits().to_be_bytes().into(), buf)
} }
} }
#[cfg(feature = "sqlx")] #[cfg(feature = "sqlx")]
impl<'q> sqlx::Decode<'q, sqlx::MySql> for #name { impl<'q> sqlx::Decode<'q, sqlx::Any> for #name {
fn decode(value: <sqlx::MySql as sqlx::database::HasValueRef<'q>>::ValueRef) -> Result<Self, sqlx::error::BoxDynError> { fn decode(value: <sqlx::Any as sqlx::Database>::ValueRef<'q>) -> Result<Self, sqlx::error::BoxDynError> {
u64::decode(value).map(|d| #name::from_bits(d).unwrap()) let vec = <Vec<u8> as sqlx::Decode<sqlx::Any>>::decode(value)?;
Ok(Self::from_bits(vec_u8_to_u64(vec)).unwrap())
} }
} }
/// Converts a [Vec<u8>] to an unsigned, 64 bit integer. The [u64] is created using [u64::from_be_bytes].
///
/// Empty vectors will result in an output of `0_u64`. Only the first 8 values from the vector are
/// being processed. Any additional values will be skipped.
///
/// Vectors holding less than 8 values will be treated as a vector holding 8 values, where the
/// missing values are padded with `0_u8`.
fn vec_u8_to_u64(vec: Vec<u8>) -> u64 {
let mut buf: [u8; 8] = [0; 8];
let mut position = 0;
for read in vec.iter() {
buf[position] = *read;
position += 1;
if position > 7 {
break;
}
}
u64::from_be_bytes(buf)
}
} }
.into() .into()
} }

View File

@ -12,7 +12,10 @@ use crate::{
instance::{ChorusUser, Instance}, instance::{ChorusUser, Instance},
ratelimiter::ChorusRequest, ratelimiter::ChorusRequest,
types::{ types::{
DeleteDisableUserSchema, GetPomeloEligibilityReturn, GetPomeloSuggestionsReturn, GetUserProfileSchema, LimitType, PublicUser, Snowflake, User, UserModifyProfileSchema, UserModifySchema, UserProfile, UserProfileMetadata, UserSettings, VerifyUserEmailChangeResponse, VerifyUserEmailChangeSchema DeleteDisableUserSchema, GetPomeloEligibilityReturn, GetPomeloSuggestionsReturn,
GetUserProfileSchema, LimitType, PublicUser, Snowflake, User, UserModifyProfileSchema,
UserModifySchema, UserProfile, UserProfileMetadata, UserSettings,
VerifyUserEmailChangeResponse, VerifyUserEmailChangeSchema,
}, },
}; };
@ -225,6 +228,9 @@ impl ChorusUser {
/// This endpoint returns a token which can be used with [Self::modify] /// This endpoint returns a token which can be used with [Self::modify]
/// to set a new email address (email_token). /// to set a new email address (email_token).
/// ///
/// As of 2024/08/08, Spacebar does not yet implement this endpoint.
// FIXME: Does this mean PUT users/@me/email is different?
///
/// # Reference /// # Reference
/// See <https://docs.discord.sex/resources/user#modify-user-email> /// See <https://docs.discord.sex/resources/user#modify-user-email>
pub async fn verify_email_change( pub async fn verify_email_change(
@ -254,9 +260,11 @@ impl ChorusUser {
/// "This endpoint is used during the pomelo migration flow. /// "This endpoint is used during the pomelo migration flow.
/// ///
/// The user must be in the rollout to use this endpoint." /// The user must be in the rollout to use this endpoint."
/// ///
/// If a user has already migrated, this endpoint will likely return a 401 Unauthorized /// If a user has already migrated, this endpoint will likely return a 401 Unauthorized
/// ([ChorusError::NoPermission]) /// ([ChorusError::NoPermission])
///
/// As of 2024/08/08, Spacebar does not yet implement this endpoint.
/// ///
/// See <https://docs.discord.sex/resources/user#get-pomelo-suggestions> /// See <https://docs.discord.sex/resources/user#get-pomelo-suggestions>
pub async fn get_pomelo_suggestions(&mut self) -> ChorusResult<String> { pub async fn get_pomelo_suggestions(&mut self) -> ChorusResult<String> {
@ -274,12 +282,14 @@ impl ChorusUser {
chorus_request chorus_request
.deserialize_response::<GetPomeloSuggestionsReturn>(self) .deserialize_response::<GetPomeloSuggestionsReturn>(self)
.await .await
.map(|returned| returned.username) .map(|returned| returned.username)
} }
/// Checks whether a unique username is available. /// Checks whether a unique username is available.
/// ///
/// Returns whether the username is not taken yet. /// Returns whether the username is not taken yet.
///
/// As of 2024/08/08, Spacebar does not yet implement this endpoint.
/// ///
/// See <https://docs.discord.sex/resources/user#get-pomelo-eligibility> /// See <https://docs.discord.sex/resources/user#get-pomelo-eligibility>
pub async fn get_pomelo_eligibility(&mut self, username: &String) -> ChorusResult<bool> { pub async fn get_pomelo_eligibility(&mut self, username: &String) -> ChorusResult<bool> {
@ -289,8 +299,8 @@ impl ChorusUser {
self.belongs_to.read().unwrap().urls.api self.belongs_to.read().unwrap().urls.api
)) ))
.header("Authorization", self.token()) .header("Authorization", self.token())
// FIXME: should we create a type for this? // FIXME: should we create a type for this?
.body(format!(r#"{{ "username": {:?} }}"#, username)) .body(format!(r#"{{ "username": {:?} }}"#, username))
.header("Content-Type", "application/json"); .header("Content-Type", "application/json");
let chorus_request = ChorusRequest { let chorus_request = ChorusRequest {
@ -300,7 +310,53 @@ impl ChorusUser {
chorus_request chorus_request
.deserialize_response::<GetPomeloEligibilityReturn>(self) .deserialize_response::<GetPomeloEligibilityReturn>(self)
.await .await
.map(|returned| !returned.taken) .map(|returned| !returned.taken)
}
/// Migrates the user from the username#discriminator to the unique username system.
///
/// Fires a [UserUpdate](crate::types::UserUpdate) gateway event.
///
/// Updates [Self::object] to an updated representation returned by the server.
// FIXME: Is this appropriate behaviour?
///
/// Note:
///
/// "This endpoint is used during the pomelo migration flow.
///
/// The user must be in the rollout to use this endpoint."
///
/// If a user has already migrated, this endpoint will likely return a 401 Unauthorized
/// ([ChorusError::NoPermission])
//
/// As of 2024/08/08, Spacebar does not yet implement this endpoint.
///
/// See <https://docs.discord.sex/resources/user#create-pomelo-migration>
pub async fn create_pomelo_migration(&mut self, username: &String) -> ChorusResult<()> {
let request = Client::new()
.post(format!(
"{}/users/@me/pomelo",
self.belongs_to.read().unwrap().urls.api
))
.header("Authorization", self.token())
// FIXME: should we create a type for this?
.body(format!(r#"{{ "username": {:?} }}"#, username))
.header("Content-Type", "application/json");
let chorus_request = ChorusRequest {
request,
limit_type: LimitType::default(),
};
let result = chorus_request.deserialize_response::<User>(self).await;
// FIXME: Does UserUpdate do this automatically? or would a user need to manually observe ChorusUser::object
if let Ok(new_object) = result {
*self.object.write().unwrap() = new_object;
return ChorusResult::Ok(());
}
ChorusResult::Err(result.err().unwrap())
} }
} }

View File

@ -162,9 +162,11 @@ impl Display for GuildFeaturesList {
} }
#[cfg(feature = "sqlx")] #[cfg(feature = "sqlx")]
impl<'r> sqlx::Decode<'r, sqlx::MySql> for GuildFeaturesList { impl<'r> sqlx::Decode<'r, sqlx::Any> for GuildFeaturesList {
fn decode(value: <sqlx::MySql as sqlx::database::HasValueRef<'r>>::ValueRef) -> Result<Self, sqlx::error::BoxDynError> { fn decode(
let v = <String as sqlx::Decode<sqlx::MySql>>::decode(value)?; value: <sqlx::Any as sqlx::Database>::ValueRef<'r>,
) -> Result<Self, sqlx::error::BoxDynError> {
let v = <String as sqlx::Decode<sqlx::Any>>::decode(value)?;
Ok(Self( Ok(Self(
v.split(',') v.split(',')
.filter(|f| !f.is_empty()) .filter(|f| !f.is_empty())
@ -175,10 +177,13 @@ impl<'r> sqlx::Decode<'r, sqlx::MySql> for GuildFeaturesList {
} }
#[cfg(feature = "sqlx")] #[cfg(feature = "sqlx")]
impl<'q> sqlx::Encode<'q, sqlx::MySql> for GuildFeaturesList { impl<'q> sqlx::Encode<'q, sqlx::Any> for GuildFeaturesList {
fn encode_by_ref(&self, buf: &mut <sqlx::MySql as sqlx::database::HasArguments<'q>>::ArgumentBuffer) -> sqlx::encode::IsNull { fn encode_by_ref(
&self,
buf: &mut <sqlx::Any as sqlx::Database>::ArgumentBuffer<'q>,
) -> Result<sqlx::encode::IsNull, Box<dyn std::error::Error + Send + Sync>> {
if self.is_empty() { if self.is_empty() {
return sqlx::encode::IsNull::Yes; return Ok(sqlx::encode::IsNull::Yes);
} }
let features = self let features = self
.iter() .iter()
@ -186,18 +191,18 @@ impl<'q> sqlx::Encode<'q, sqlx::MySql> for GuildFeaturesList {
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(","); .join(",");
<String as sqlx::Encode<sqlx::MySql>>::encode_by_ref(&features, buf) <String as sqlx::Encode<sqlx::Any>>::encode_by_ref(&features, buf)
} }
} }
#[cfg(feature = "sqlx")] #[cfg(feature = "sqlx")]
impl sqlx::Type<sqlx::MySql> for GuildFeaturesList { impl sqlx::Type<sqlx::Any> for GuildFeaturesList {
fn type_info() -> sqlx::mysql::MySqlTypeInfo { fn type_info() -> sqlx::any::AnyTypeInfo {
<String as sqlx::Type<sqlx::MySql>>::type_info() <String as sqlx::Type<sqlx::Any>>::type_info()
} }
fn compatible(ty: &sqlx::mysql::MySqlTypeInfo) -> bool { fn compatible(ty: &sqlx::any::AnyTypeInfo) -> bool {
<String as sqlx::Type<sqlx::MySql>>::compatible(ty) <String as sqlx::Type<sqlx::Any>>::compatible(ty)
} }
} }

View File

@ -102,7 +102,10 @@ fn compare_install_params(
b: &Option<sqlx::types::Json<InstallParams>>, b: &Option<sqlx::types::Json<InstallParams>>,
) -> bool { ) -> bool {
match (a, b) { match (a, b) {
(Some(a), Some(b)) => a.encode_to_string() == b.encode_to_string(), (Some(a), Some(b)) => match (a.encode_to_string(), b.encode_to_string()) {
(Ok(a), Ok(b)) => a == b,
_ => false,
},
(None, None) => true, (None, None) => true,
_ => false, _ => false,
} }

View File

@ -51,7 +51,10 @@ fn compare_options(
b: &Option<sqlx::types::Json<AuditEntryInfo>>, b: &Option<sqlx::types::Json<AuditEntryInfo>>,
) -> bool { ) -> bool {
match (a, b) { match (a, b) {
(Some(a), Some(b)) => a.encode_to_string() == b.encode_to_string(), (Some(a), Some(b)) => match (a.encode_to_string(), b.encode_to_string()) {
(Ok(a), Ok(b)) => a == b,
_ => false,
},
(None, None) => true, (None, None) => true,
_ => false, _ => false,
} }
@ -69,7 +72,10 @@ fn compare_changes(
a: &sqlx::types::Json<Option<Vec<Shared<AuditLogChange>>>>, a: &sqlx::types::Json<Option<Vec<Shared<AuditLogChange>>>>,
b: &sqlx::types::Json<Option<Vec<Shared<AuditLogChange>>>>, b: &sqlx::types::Json<Option<Vec<Shared<AuditLogChange>>>>,
) -> bool { ) -> bool {
a.encode_to_string() == b.encode_to_string() match (a.encode_to_string(), b.encode_to_string()) {
(Ok(a), Ok(b)) => a == b,
_ => false,
}
} }
#[cfg(not(tarpaulin_include))] #[cfg(not(tarpaulin_include))]

View File

@ -156,7 +156,10 @@ fn compare_permission_overwrites(
b: &Option<Json<Vec<PermissionOverwrite>>>, b: &Option<Json<Vec<PermissionOverwrite>>>,
) -> bool { ) -> bool {
match (a, b) { match (a, b) {
(Some(a), Some(b)) => a.encode_to_string() == b.encode_to_string(), (Some(a), Some(b)) => match (a.encode_to_string(), b.encode_to_string()) {
(Ok(a), Ok(b)) => a == b,
_ => false,
},
(None, None) => true, (None, None) => true,
_ => false, _ => false,
} }

View File

@ -116,32 +116,32 @@ impl TryFrom<Vec<u8>> for ThemeColors {
#[cfg(feature = "sqlx")] #[cfg(feature = "sqlx")]
// TODO: Add tests for Encode and Decode. // TODO: Add tests for Encode and Decode.
impl<'q> sqlx::Encode<'q, sqlx::MySql> for ThemeColors { impl<'q> sqlx::Encode<'q, sqlx::Any> for ThemeColors {
fn encode_by_ref( fn encode_by_ref(
&self, &self,
buf: &mut <sqlx::MySql as sqlx::database::HasArguments<'q>>::ArgumentBuffer, buf: &mut <sqlx::Any as sqlx::Database>::ArgumentBuffer<'q>,
) -> sqlx::encode::IsNull { ) -> Result<sqlx::encode::IsNull, Box<dyn std::error::Error + Send + Sync>> {
let mut vec_u8 = Vec::new(); let mut vec_u8 = Vec::new();
vec_u8.extend_from_slice(&self.inner.0.to_be_bytes()); vec_u8.extend_from_slice(&self.inner.0.to_be_bytes());
vec_u8.extend_from_slice(&self.inner.1.to_be_bytes()); vec_u8.extend_from_slice(&self.inner.1.to_be_bytes());
<Vec<u8> as sqlx::Encode<'q, sqlx::MySql>>::encode_by_ref(&vec_u8, buf) <Vec<u8> as sqlx::Encode<sqlx::Any>>::encode_by_ref(&vec_u8, buf)
} }
} }
#[cfg(feature = "sqlx")] #[cfg(feature = "sqlx")]
impl<'d> sqlx::Decode<'d, sqlx::MySql> for ThemeColors { impl<'d> sqlx::Decode<'d, sqlx::Any> for ThemeColors {
fn decode( fn decode(
value: <sqlx::MySql as sqlx::database::HasValueRef<'d>>::ValueRef, value: <sqlx::Any as sqlx::Database>::ValueRef<'d>,
) -> Result<Self, sqlx::error::BoxDynError> { ) -> Result<Self, sqlx::error::BoxDynError> {
let value_vec = <Vec<u8> as sqlx::Decode<'d, sqlx::MySql>>::decode(value)?; let value_vec = <Vec<u8> as sqlx::Decode<'d, sqlx::Any>>::decode(value)?;
value_vec.try_into().map_err(|e: ChorusError| e.into()) value_vec.try_into().map_err(|e: ChorusError| e.into())
} }
} }
#[cfg(feature = "sqlx")] #[cfg(feature = "sqlx")]
impl sqlx::Type<sqlx::MySql> for ThemeColors { impl sqlx::Type<sqlx::Any> for ThemeColors {
fn type_info() -> <sqlx::MySql as sqlx::Database>::TypeInfo { fn type_info() -> <sqlx::Any as sqlx::Database>::TypeInfo {
<String as sqlx::Type<sqlx::MySql>>::type_info() <String as sqlx::Type<sqlx::Any>>::type_info()
} }
} }

View File

@ -5,14 +5,52 @@
use crate::types::events::WebSocketEvent; use crate::types::events::WebSocketEvent;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Deserialize, Serialize, WebSocketEvent, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(
Debug, Deserialize, Serialize, WebSocketEvent, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord,
)]
pub struct GatewayHeartbeat { pub struct GatewayHeartbeat {
pub op: u8, pub op: u8,
pub d: Option<u64>, pub d: Option<u64>,
} }
#[derive(Debug, Default, Deserialize, Serialize, Clone, WebSocketEvent, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] impl GatewayHeartbeat {
/// The Heartbeat packet a server would receive from a new or fresh Gateway connection.
pub fn first() -> Self {
Self::default()
}
/// Quickly create a [GatewayHeartbeat] with the correct `opcode` and the given `sequence_number`.
///
/// Shorthand for
/// ```rs
/// Self {
/// op: 1,
/// d: Some(sequence_number)
/// }
/// ```
pub fn new(sequence_number: u64) -> Self {
Self {
op: 1,
d: Some(sequence_number),
}
}
}
impl std::default::Default for GatewayHeartbeat {
fn default() -> Self {
Self { op: 1, d: None }
}
}
#[derive(
Debug, Deserialize, Serialize, Clone, WebSocketEvent, Copy, PartialEq, Eq, Hash, PartialOrd, Ord,
)]
pub struct GatewayHeartbeatAck { pub struct GatewayHeartbeatAck {
pub op: i32, pub op: i32,
} }
impl std::default::Default for GatewayHeartbeatAck {
fn default() -> Self {
Self { op: 11 }
}
}

View File

@ -99,23 +99,29 @@ impl<'de> serde::Deserialize<'de> for Snowflake {
} }
#[cfg(feature = "sqlx")] #[cfg(feature = "sqlx")]
impl sqlx::Type<sqlx::MySql> for Snowflake { impl sqlx::Type<sqlx::Any> for Snowflake {
fn type_info() -> <sqlx::MySql as sqlx::Database>::TypeInfo { fn type_info() -> <sqlx::Any as sqlx::Database>::TypeInfo {
<String as sqlx::Type<sqlx::MySql>>::type_info() <String as sqlx::Type<sqlx::Any>>::type_info()
} }
} }
#[cfg(feature = "sqlx")] #[cfg(feature = "sqlx")]
impl<'q> sqlx::Encode<'q, sqlx::MySql> for Snowflake { impl<'q> sqlx::Encode<'q, sqlx::Any> for Snowflake {
fn encode_by_ref(&self, buf: &mut <sqlx::MySql as sqlx::database::HasArguments<'q>>::ArgumentBuffer) -> sqlx::encode::IsNull { fn encode_by_ref(
<String as sqlx::Encode<'q, sqlx::MySql>>::encode_by_ref(&self.0.to_string(), buf) &self,
buf: &mut <sqlx::Any as sqlx::Database>::ArgumentBuffer<'q>,
) -> Result<sqlx::encode::IsNull, sqlx::error::BoxDynError> {
<String as sqlx::Encode<'q, sqlx::Any>>::encode_by_ref(&self.0.to_string(), buf)
} }
} }
#[cfg(feature = "sqlx")] #[cfg(feature = "sqlx")]
impl<'d> sqlx::Decode<'d, sqlx::MySql> for Snowflake { impl<'d> sqlx::Decode<'d, sqlx::Any> for Snowflake {
fn decode(value: <sqlx::MySql as sqlx::database::HasValueRef<'d>>::ValueRef) -> Result<Self, sqlx::error::BoxDynError> { fn decode(
<String as sqlx::Decode<'d, sqlx::MySql>>::decode(value).map(|s| s.parse::<u64>().map(Snowflake).unwrap()) value: <sqlx::Any as sqlx::Database>::ValueRef<'d>,
) -> Result<Self, sqlx::error::BoxDynError> {
<String as sqlx::Decode<'d, sqlx::Any>>::decode(value)
.map(|s| s.parse::<u64>().map(Snowflake).unwrap())
} }
} }