diff --git a/Cargo.lock b/Cargo.lock index 00b7a67fa..cde0aa97a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,6 +76,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -1502,6 +1503,15 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "core_maths" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b02505ccb8c50b0aa21ace0fc08c3e53adebd4e58caa18a36152803c7709a3" +dependencies = [ + "libm", +] + [[package]] name = "cpufeatures" version = "0.2.2" @@ -1618,12 +1628,44 @@ dependencies = [ "typenum", ] +[[package]] +name = "cssparser" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.11.2", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote 1.0.37", + "syn 2.0.76", +] + [[package]] name = "ct-codecs" 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" @@ -1787,6 +1829,12 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" +[[package]] +name = "data-url" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" + [[package]] name = "deadqueue" version = "0.2.4" @@ -1857,6 +1905,17 @@ dependencies = [ "syn 1.0.107", ] +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote 1.0.37", + "syn 2.0.76", +] + [[package]] name = "devise" version = "0.4.2" @@ -1923,6 +1982,21 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + [[package]] name = "dyn-clone" version = "1.0.5" @@ -1969,6 +2043,12 @@ dependencies = [ "getrandom", ] +[[package]] +name = "ego-tree" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12a0bb14ac04a9fcf170d0bbbef949b44cc492f4452bd20c095636956f653642" + [[package]] name = "either" version = "1.6.1" @@ -2251,6 +2331,29 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "fontconfig-parser" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fcfcd44ca6e90c921fee9fa665d530b21ef1327a4c1a6c5250ea44b776ada7" +dependencies = [ + "roxmltree", +] + +[[package]] +name = "fontdb" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3a6f9af55fb97ad673fb7a69533eb2f967648a06fa21f8c9bb2cd6d33975716" +dependencies = [ + "fontconfig-parser", + "log", + "memmap2", + "slotmap", + "tinyvec", + "ttf-parser", +] + [[package]] name = "foreign-types" version = "0.3.2" @@ -2308,6 +2411,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures" version = "0.3.21" @@ -2429,6 +2542,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generator" version = "0.7.0" @@ -2461,6 +2583,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" version = "0.2.14" @@ -2766,6 +2897,20 @@ dependencies = [ "winapi", ] +[[package]] +name = "html5ever" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote 1.0.37", + "syn 2.0.76", +] + [[package]] name = "http" version = "0.2.12" @@ -3463,6 +3608,16 @@ dependencies = [ "mutate_once", ] +[[package]] +name = "kurbo" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f" +dependencies = [ + "arrayvec", + "smallvec", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -3700,12 +3855,32 @@ version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9106e1d747ffd48e6be5bb2d97fa706ed25b144fbee4d5c02eae110cd8d6badd" +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + [[package]] name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" +[[package]] +name = "markup5ever" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" +dependencies = [ + "log", + "phf 0.11.2", + "phf_codegen 0.11.2", + "string_cache", + "string_cache_codegen", + "tendril", +] + [[package]] name = "match_cfg" version = "0.1.0" @@ -3758,6 +3933,15 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + [[package]] name = "metrics" version = "0.18.1" @@ -4496,6 +4680,102 @@ dependencies = [ "sha-1 0.8.2", ] +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_shared 0.10.0", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote 1.0.37", + "syn 2.0.76", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project" version = "1.0.10" @@ -4606,6 +4886,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "pretty_env_logger" version = "0.4.0" @@ -5231,9 +5517,26 @@ dependencies = [ "quick-error 1.2.3", ] +[[package]] +name = "resvg" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a325d5e8d1cebddd070b13f44cec8071594ab67d1012797c121f27a669b7958" +dependencies = [ + "gif", + "image-webp", + "log", + "pico-args", + "rgb", + "svgtypes", + "tiny-skia", + "usvg", + "zune-jpeg", +] + [[package]] name = "revolt-autumn" -version = "0.7.14" +version = "0.7.18" dependencies = [ "axum", "axum-macros", @@ -5270,7 +5573,7 @@ dependencies = [ [[package]] name = "revolt-bonfire" -version = "0.7.16" +version = "0.7.18" dependencies = [ "async-channel 2.3.1", "async-std", @@ -5300,7 +5603,7 @@ dependencies = [ [[package]] name = "revolt-config" -version = "0.7.16" +version = "0.7.18" dependencies = [ "async-std", "cached", @@ -5317,7 +5620,7 @@ dependencies = [ [[package]] name = "revolt-database" -version = "0.7.16" +version = "0.7.18" dependencies = [ "amqprs", "async-lock 2.8.0", @@ -5366,7 +5669,7 @@ dependencies = [ [[package]] name = "revolt-delta" -version = "0.7.16" +version = "0.7.18" dependencies = [ "amqprs", "async-channel 1.6.1", @@ -5414,33 +5717,49 @@ dependencies = [ [[package]] name = "revolt-files" -version = "0.7.16" +version = "0.7.18" dependencies = [ "aes-gcm", "aws-config", "aws-sdk-s3", "base64 0.22.1", + "ffprobe", + "image", + "imagesize", + "jxl-oxide", + "resvg", "revolt-config", "revolt-result", + "tempfile", + "tiny-skia", + "tracing", "typenum", + "usvg", + "webp", ] [[package]] name = "revolt-january" -version = "0.7.14" +version = "0.7.18" dependencies = [ + "async-recursion", "axum", "axum-extra", + "encoding_rs", "lazy_static", "mime", "moka", + "regex", "reqwest 0.12.4", "revolt-config", + "revolt-files", "revolt-models", "revolt-result", + "scraper", "serde", "serde_json", "tokio 1.40.0", + "tempfile", "tracing", "tracing-subscriber", "utoipa", @@ -5449,7 +5768,7 @@ dependencies = [ [[package]] name = "revolt-models" -version = "0.7.16" +version = "0.7.18" dependencies = [ "indexmap 1.9.3", "iso8601-timestamp 0.2.11", @@ -5467,7 +5786,7 @@ dependencies = [ [[package]] name = "revolt-nodejs-bindings" -version = "0.7.16" +version = "0.7.18" dependencies = [ "async-std", "neon", @@ -5480,7 +5799,7 @@ dependencies = [ [[package]] name = "revolt-permissions" -version = "0.7.16" +version = "0.7.18" dependencies = [ "async-std", "async-trait", @@ -5495,7 +5814,7 @@ dependencies = [ [[package]] name = "revolt-presence" -version = "0.7.16" +version = "0.7.18" dependencies = [ "async-std", "log", @@ -5530,7 +5849,7 @@ dependencies = [ [[package]] name = "revolt-result" -version = "0.7.16" +version = "0.7.18" dependencies = [ "axum", "revolt_okapi", @@ -5857,6 +6176,12 @@ dependencies = [ "serde", ] +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + [[package]] name = "rsa" version = "0.7.2" @@ -6058,6 +6383,24 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" +[[package]] +name = "rustybuzz" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85d1ccd519e61834798eb52c4e886e8c2d7d698dd3d6ce0b1b47eb8557f1181" +dependencies = [ + "bitflags 2.6.0", + "bytemuck", + "core_maths", + "log", + "smallvec", + "ttf-parser", + "unicode-bidi-mirroring", + "unicode-ccc", + "unicode-properties", + "unicode-script", +] + [[package]] name = "ryu" version = "1.0.10" @@ -6111,6 +6454,22 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scraper" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90460b31bfe1fc07be8262e42c665ad97118d4585869de9345a84d501a9eaf0" +dependencies = [ + "ahash 0.8.11", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "once_cell", + "selectors", + "tendril", +] + [[package]] name = "sct" version = "0.7.0" @@ -6175,6 +6534,25 @@ dependencies = [ "libc", ] +[[package]] +name = "selectors" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" +dependencies = [ + "bitflags 2.6.0", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf 0.10.1", + "phf_codegen 0.10.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + [[package]] name = "semver" version = "0.9.0" @@ -6424,6 +6802,15 @@ dependencies = [ "syn 1.0.107", ] +[[package]] +name = "servo_arc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "sha-1" version = "0.8.2" @@ -6540,12 +6927,42 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" +[[package]] +name = "simplecss" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a11be7c62927d9427e9f40f3444d5499d868648e2edbc4e2116de69e7ec0e89d" +dependencies = [ + "log", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "version_check", +] + [[package]] name = "sluice" version = "0.5.5" @@ -6617,6 +7034,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "state" version = "0.6.0" @@ -6626,6 +7049,41 @@ dependencies = [ "loom", ] +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +dependencies = [ + "float-cmp", +] + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote 1.0.37", +] + [[package]] name = "stringprep" version = "0.1.2" @@ -6667,6 +7125,16 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "svgtypes" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794de53cc48eaabeed0ab6a3404a65f40b3e38c067e4435883a65d2aa4ca000e" +dependencies = [ + "kurbo", + "siphasher 1.0.1", +] + [[package]] name = "syn" version = "0.11.11" @@ -6823,6 +7291,17 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + [[package]] name = "termcolor" version = "1.1.3" @@ -6901,6 +7380,32 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "png", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -7252,6 +7757,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "ttf-parser" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a" +dependencies = [ + "core_maths", +] + [[package]] name = "tungstenite" version = "0.17.2" @@ -7379,6 +7893,18 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +[[package]] +name = "unicode-bidi-mirroring" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64af057ad7466495ca113126be61838d8af947f41d93a949980b2389a118082f" + +[[package]] +name = "unicode-ccc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "260bc6647b3893a9a90668360803a15f96b85a5257b1c3a0c3daf6ae2496de42" + [[package]] name = "unicode-ident" version = "1.0.0" @@ -7394,12 +7920,36 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + +[[package]] +name = "unicode-script" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" + [[package]] name = "unicode-segmentation" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +[[package]] +name = "unicode-vo" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "unicode-xid" version = "0.0.4" @@ -7474,6 +8024,33 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" +[[package]] +name = "usvg" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7447e703d7223b067607655e625e0dbca80822880248937da65966194c4864e6" +dependencies = [ + "base64 0.22.1", + "data-url", + "flate2", + "fontdb", + "imagesize", + "kurbo", + "log", + "pico-args", + "roxmltree", + "rustybuzz", + "simplecss", + "siphasher 1.0.1", + "strict-num", + "svgtypes", + "tiny-skia-path", + "unicode-bidi", + "unicode-script", + "unicode-vo", + "xmlwriter", +] + [[package]] name = "utf-8" version = "0.7.6" @@ -8124,6 +8701,12 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" +[[package]] +name = "xmlwriter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" + [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/crates/bindings/node/Cargo.toml b/crates/bindings/node/Cargo.toml index b3982fd25..7c8892743 100644 --- a/crates/bindings/node/Cargo.toml +++ b/crates/bindings/node/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "revolt-nodejs-bindings" -version = "0.7.16" +version = "0.7.18" description = "Node.js bindings for the Revolt software" authors = ["Paul Makles "] license = "MIT" @@ -20,6 +20,6 @@ serde = { version = "1", features = ["derive"] } async-std = "1.12.0" -revolt-config = { version = "0.7.16", path = "../../core/config" } -revolt-result = { version = "0.7.16", path = "../../core/result" } -revolt-database = { version = "0.7.16", path = "../../core/database" } +revolt-config = { version = "0.7.18", path = "../../core/config" } +revolt-result = { version = "0.7.18", path = "../../core/result" } +revolt-database = { version = "0.7.18", path = "../../core/database" } diff --git a/crates/bonfire/Cargo.toml b/crates/bonfire/Cargo.toml index 69341ba24..f25dc19e5 100644 --- a/crates/bonfire/Cargo.toml +++ b/crates/bonfire/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "revolt-bonfire" -version = "0.7.16" +version = "0.7.18" license = "AGPL-3.0-or-later" edition = "2021" @@ -41,7 +41,7 @@ revolt-result = { path = "../core/result" } revolt-models = { path = "../core/models" } revolt-config = { path = "../core/config" } revolt-database = { path = "../core/database" } -revolt-permissions = { version = "0.7.16", path = "../core/permissions" } +revolt-permissions = { version = "0.7.18", path = "../core/permissions" } revolt-presence = { path = "../core/presence", features = ["redis-is-patched"] } # redis diff --git a/crates/core/config/Cargo.toml b/crates/core/config/Cargo.toml index 81161841a..2fc05f925 100644 --- a/crates/core/config/Cargo.toml +++ b/crates/core/config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "revolt-config" -version = "0.7.16" +version = "0.7.18" edition = "2021" license = "MIT" authors = ["Paul Makles "] @@ -35,4 +35,4 @@ pretty_env_logger = "0.4.0" sentry = "0.31.5" # Core -revolt-result = { version = "0.7.16", path = "../result", optional = true } +revolt-result = { version = "0.7.18", path = "../result", optional = true } diff --git a/crates/core/database/Cargo.toml b/crates/core/database/Cargo.toml index 0eb61e2f1..3e0dcdc5b 100644 --- a/crates/core/database/Cargo.toml +++ b/crates/core/database/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "revolt-database" -version = "0.7.16" +version = "0.7.18" edition = "2021" license = "AGPL-3.0-or-later" authors = ["Paul Makles "] @@ -24,15 +24,15 @@ default = ["mongodb", "async-std-runtime", "tasks"] [dependencies] # Core -revolt-config = { version = "0.7.16", path = "../config", features = [ +revolt-config = { version = "0.7.18", path = "../config", features = [ "report-macros", ] } -revolt-result = { version = "0.7.16", path = "../result" } -revolt-models = { version = "0.7.16", path = "../models", features = [ +revolt-result = { version = "0.7.18", path = "../result" } +revolt-models = { version = "0.7.18", path = "../models", features = [ "validator", ] } -revolt-presence = { version = "0.7.16", path = "../presence" } -revolt-permissions = { version = "0.7.16", path = "../permissions", features = [ +revolt-presence = { version = "0.7.18", path = "../presence" } +revolt-permissions = { version = "0.7.18", path = "../permissions", features = [ "serde", "bson", ] } diff --git a/crates/core/database/src/models/messages/model.rs b/crates/core/database/src/models/messages/model.rs index 2758afba2..c4f42fb5a 100644 --- a/crates/core/database/src/models/messages/model.rs +++ b/crates/core/database/src/models/messages/model.rs @@ -381,7 +381,34 @@ impl Message { } if !mentions.is_empty() { - message.mentions.replace(mentions.into_iter().collect()); + // FIXME: temp fix to stop spam attacks + match channel { + Channel::DirectMessage { ref recipients, .. } + | Channel::Group { ref recipients, .. } => { + let recipients_hash: HashSet<&String, RandomState> = + HashSet::from_iter(recipients.iter()); + + mentions.retain(|m| recipients_hash.contains(m)); + } + Channel::TextChannel { ref server, .. } + | Channel::VoiceChannel { ref server, .. } => { + let mentions_vec = Vec::from_iter(mentions.iter().cloned()); + let valid_members = db.fetch_members(server.as_str(), &mentions_vec[..]).await; + if let Ok(valid_members) = valid_members { + let valid_ids: HashSet = HashSet::from_iter( + valid_members.iter().map(|member| member.id.user.clone()), + ); + mentions.retain(|m| valid_ids.contains(m)); + } else { + revolt_config::capture_error(&valid_members.unwrap_err()); + } + } + Channel::SavedMessages { .. } => mentions.clear(), + } + + if !mentions.is_empty() { + message.mentions.replace(mentions.into_iter().collect()); + } } if !replies.is_empty() { diff --git a/crates/core/files/Cargo.toml b/crates/core/files/Cargo.toml index a340894ff..d75ad107c 100644 --- a/crates/core/files/Cargo.toml +++ b/crates/core/files/Cargo.toml @@ -1,12 +1,18 @@ [package] name = "revolt-files" -version = "0.7.16" +version = "0.7.18" edition = "2021" license = "AGPL-3.0-or-later" authors = ["Paul Makles "] description = "Revolt Backend: S3 and encryption subroutines" [dependencies] +tracing = "0.1" + +ffprobe = "0.4.0" +imagesize = "0.13.0" +tempfile = "3.12.0" + base64 = "0.22.1" aes-gcm = "0.10.3" typenum = "1.17.0" @@ -14,7 +20,19 @@ typenum = "1.17.0" aws-config = "1.5.5" aws-sdk-s3 = { version = "1.46.0", features = ["behavior-version-latest"] } -revolt-config = { version = "0.7.16", path = "../config", features = [ +revolt-config = { version = "0.7.18", path = "../config", features = [ "report-macros", ] } -revolt-result = { version = "0.7.16", path = "../result" } +revolt-result = { version = "0.7.18", path = "../result" } + +# image processing +jxl-oxide = "0.8.1" +image = { version = "0.25.2" } + +# svg rendering +usvg = "0.44.0" +resvg = "0.44.0" +tiny-skia = "0.11.4" + +# encoding +webp = "0.3.0" diff --git a/crates/core/files/src/lib.rs b/crates/core/files/src/lib.rs index 5d2bdbd64..d4e2b2ab7 100644 --- a/crates/core/files/src/lib.rs +++ b/crates/core/files/src/lib.rs @@ -1,9 +1,10 @@ -use std::io::Write; +use std::io::{BufRead, Read, Seek, Write}; use aes_gcm::{ aead::{AeadCore, AeadMutInPlace, OsRng}, Aes256Gcm, Key, KeyInit, Nonce, }; +use image::{DynamicImage, ImageBuffer}; use revolt_config::{config, report_internal_error, FilesS3}; use revolt_result::{create_error, Result}; @@ -13,6 +14,8 @@ use aws_sdk_s3::{ }; use base64::prelude::*; +use tempfile::NamedTempFile; +use tiny_skia::Pixmap; /// Size of the authentication tag in the buffer pub const AUTHENTICATION_TAG_SIZE_BYTES: usize = 16; @@ -108,3 +111,162 @@ pub async fn upload_to_s3(bucket_id: &str, path: &str, buf: &[u8]) -> Result Option<(usize, usize)> { + if let Ok(size) = imagesize::size(f.path()) + .inspect_err(|err| tracing::error!("Failed to generate image size! {err:?}")) + { + Some((size.width, size.height)) + } else { + None + } +} + +/// Determine size of image with buffer +pub fn image_size_vec(v: &[u8], mime: &str) -> Option<(usize, usize)> { + match mime { + "image/svg+xml" => { + let tree = + report_internal_error!(usvg::Tree::from_data(v, &Default::default())).ok()?; + + let size = tree.size(); + Some((size.width() as usize, size.height() as usize)) + } + _ => { + if let Ok(size) = imagesize::blob_size(v) + .inspect_err(|err| tracing::error!("Failed to generate image size! {err:?}")) + { + Some((size.width, size.height)) + } else { + None + } + } + } +} + +/// Determine size of video at temp file +pub fn video_size(f: &NamedTempFile) -> Option<(i64, i64)> { + if let Ok(data) = ffprobe::ffprobe(f.path()) + .inspect_err(|err| tracing::error!("Failed to ffprobe file! {err:?}")) + { + // Use first valid stream + for stream in data.streams { + if let (Some(w), Some(h)) = (stream.width, stream.height) { + return Some((w, h)); + } + } + + None + } else { + None + } +} + +/// Decode image from reader +pub fn decode_image(reader: &mut R, mime: &str) -> Result { + match mime { + // Read image using jxl-oxide crate + "image/jxl" => { + let jxl_image = report_internal_error!(jxl_oxide::JxlImage::builder().read(reader))?; + if let Ok(frame) = jxl_image.render_frame(0) { + match frame.color_channels().len() { + 3 => Ok(DynamicImage::ImageRgb8( + DynamicImage::ImageRgb32F( + ImageBuffer::from_vec( + jxl_image.width(), + jxl_image.height(), + frame.image().buf().to_vec(), + ) + .ok_or_else(|| create_error!(ImageProcessingFailed))?, + ) + .to_rgb8(), + )), + 4 => Ok(DynamicImage::ImageRgba8( + DynamicImage::ImageRgba32F( + ImageBuffer::from_vec( + jxl_image.width(), + jxl_image.height(), + frame.image().buf().to_vec(), + ) + .ok_or_else(|| create_error!(ImageProcessingFailed))?, + ) + .to_rgba8(), + )), + _ => Err(create_error!(ImageProcessingFailed)), + } + } else { + Err(create_error!(ImageProcessingFailed)) + } + } + // Read image using resvg + "image/svg+xml" => { + // usvg doesn't support Read trait so copy to buffer + let mut buf = Vec::new(); + report_internal_error!(reader.read_to_end(&mut buf))?; + + let tree = report_internal_error!(usvg::Tree::from_data(&buf, &Default::default()))?; + let size = tree.size(); + let mut pixmap = Pixmap::new(size.width() as u32, size.height() as u32) + .ok_or_else(|| create_error!(ImageProcessingFailed))?; + + let mut pixmap_mut = pixmap.as_mut(); + resvg::render(&tree, Default::default(), &mut pixmap_mut); + + Ok(DynamicImage::ImageRgba8( + ImageBuffer::from_vec( + size.width() as u32, + size.height() as u32, + pixmap.data().to_vec(), + ) + .ok_or_else(|| create_error!(ImageProcessingFailed))?, + )) + } + // Check if we can read using image-rs crate + _ => report_internal_error!(report_internal_error!( + image::ImageReader::new(reader).with_guessed_format() + )? + .decode()), + } +} + +/// Check whether given reader has a valid image +pub fn is_valid_image(reader: &mut R, mime: &str) -> bool { + match mime { + // Check if we can read using jxl-oxide crate + "image/jxl" => jxl_oxide::JxlImage::builder() + .read(reader) + .inspect_err(|err| tracing::error!("Failed to read JXL! {err:?}")) + .is_ok(), + // Check if we can read using image-rs crate + _ => !matches!( + image::ImageReader::new(reader) + .with_guessed_format() + .inspect_err(|err| tracing::error!("Failed to read image! {err:?}")) + .map(|f| f.decode()), + Err(_) | Ok(Err(_)) + ), + } +} + +/// Create thumbnail from given image +pub async fn create_thumbnail(image: DynamicImage, tag: &str) -> Vec { + // Load configuration + let config = config().await; + let [w, h] = config.files.preview.get(tag).unwrap(); + + // Create thumbnail + //.resize(width as u32, height as u32, image::imageops::FilterType::Gaussian) + // resize is about 2.5x slower, + // thumbnail doesn't have terrible quality + // so we use thumbnail + let image = image.thumbnail(image.width().min(*w as u32), image.height().min(*h as u32)); + + // Encode it into WEBP + let encoder = webp::Encoder::from_image(&image).expect("Could not create encoder."); + if config.files.webp_quality != 100.0 { + encoder.encode(config.files.webp_quality).to_vec() + } else { + encoder.encode_lossless().to_vec() + } +} diff --git a/crates/core/models/Cargo.toml b/crates/core/models/Cargo.toml index 77f9f54a5..805ef8f5c 100644 --- a/crates/core/models/Cargo.toml +++ b/crates/core/models/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "revolt-models" -version = "0.7.16" +version = "0.7.18" edition = "2021" license = "MIT" authors = ["Paul Makles "] @@ -20,8 +20,8 @@ default = ["serde", "partials", "rocket"] [dependencies] # Core -revolt-config = { version = "0.7.16", path = "../config" } -revolt-permissions = { version = "0.7.16", path = "../permissions" } +revolt-config = { version = "0.7.18", path = "../config" } +revolt-permissions = { version = "0.7.18", path = "../permissions" } # Utility regex = "1" diff --git a/crates/core/models/src/v0/embeds.rs b/crates/core/models/src/v0/embeds.rs index ca1f97f9f..4944afaec 100644 --- a/crates/core/models/src/v0/embeds.rs +++ b/crates/core/models/src/v0/embeds.rs @@ -14,9 +14,9 @@ auto_derived!( /// URL to the original image pub url: String, /// Width of the image - pub width: isize, + pub width: usize, /// Height of the image - pub height: isize, + pub height: usize, /// Positioning and size pub size: ImageSize, } @@ -26,9 +26,9 @@ auto_derived!( /// URL to the original video pub url: String, /// Width of the video - pub width: isize, + pub width: usize, /// Height of the video - pub height: isize, + pub height: usize, } /// Type of remote Twitch content @@ -86,7 +86,7 @@ auto_derived!( }, AppleMusic { album_id: String, - + #[serde(skip_serializing_if = "Option::is_none")] track_id: Option, }, @@ -119,8 +119,6 @@ auto_derived!( #[serde(skip_serializing_if = "Option::is_none")] pub video: Option