feat: image thumbnails

next
timokoesters 2020-05-19 18:31:34 +02:00
parent 61f4f2c716
commit d544d28b6e
No known key found for this signature in database
GPG Key ID: 24DA7517711A2BA4
6 changed files with 365 additions and 112 deletions

294
Cargo.lock generated
View File

@ -1,5 +1,11 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "adler32"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
[[package]]
name = "arc-swap"
version = "0.4.6"
@ -24,9 +30,9 @@ version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26c4f3195085c36ea8d24d32b2f828d23296a9370a28aa39d111f6f16bef9f3b"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.5",
"syn 1.0.21",
"proc-macro2 1.0.13",
"quote 1.0.6",
"syn 1.0.22",
]
[[package]]
@ -96,6 +102,12 @@ version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5356f1d23ee24a1f785a56d1d1a5f0fd5b0f6a0c0fb2412ce11da71649ab78f6"
[[package]]
name = "bytemuck"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37fa13df2292ecb479ec23aa06f4507928bef07839be9ef15281411076629431"
[[package]]
name = "byteorder"
version = "1.3.4"
@ -110,9 +122,9 @@ checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1"
[[package]]
name = "cc"
version = "1.0.52"
version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d"
checksum = "404b1fe4f65288577753b17e3b36a04596ee784493ec249bf81c7f2d2acd751c"
[[package]]
name = "cfg-if"
@ -129,6 +141,12 @@ dependencies = [
"bitflags",
]
[[package]]
name = "color_quant"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd"
[[package]]
name = "conduit"
version = "0.1.0"
@ -136,6 +154,7 @@ dependencies = [
"base64 0.12.1",
"directories",
"http",
"image",
"js_int",
"log",
"rand",
@ -224,6 +243,16 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "deflate"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7e5d2a2273fed52a7f947ee55b092c4057025d7a3e04e5ecdbd25d6c3fb1bd7"
dependencies = [
"adler32",
"byteorder",
]
[[package]]
name = "devise"
version = "0.3.0"
@ -239,7 +268,7 @@ version = "0.3.0"
source = "git+https://github.com/SergioBenitez/Devise.git?rev=e58b3ac9a#e58b3ac9afc3b6ff10a8aaf02a3e768a8f530089"
dependencies = [
"devise_core",
"quote 1.0.5",
"quote 1.0.6",
]
[[package]]
@ -248,9 +277,9 @@ version = "0.3.0"
source = "git+https://github.com/SergioBenitez/Devise.git?rev=e58b3ac9a#e58b3ac9afc3b6ff10a8aaf02a3e768a8f530089"
dependencies = [
"bitflags",
"proc-macro2 1.0.12",
"quote 1.0.5",
"syn 1.0.21",
"proc-macro2 1.0.13",
"quote 1.0.6",
"syn 1.0.22",
]
[[package]]
@ -292,9 +321,9 @@ dependencies = [
[[package]]
name = "fnv"
version = "1.0.6"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
@ -392,9 +421,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39"
dependencies = [
"proc-macro-hack",
"proc-macro2 1.0.12",
"quote 1.0.5",
"syn 1.0.21",
"proc-macro2 1.0.13",
"quote 1.0.6",
"syn 1.0.22",
]
[[package]]
@ -452,6 +481,16 @@ dependencies = [
"wasi",
]
[[package]]
name = "gif"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "471d90201b3b223f3451cd4ad53e34295f16a1df17b1edf3736d47761c3981af"
dependencies = [
"color_quant",
"lzw",
]
[[package]]
name = "h2"
version = "0.2.5"
@ -482,9 +521,9 @@ dependencies = [
[[package]]
name = "hermit-abi"
version = "0.1.12"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61565ff7aaace3525556587bd2dc31d4a07071957be715e63ce7b1eccf51a8f4"
checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
dependencies = [
"libc",
]
@ -564,6 +603,22 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "image"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9117f4167a8f21fa2bb3f17a652a760acd7572645281c98e3b612a26242c96ee"
dependencies = [
"bytemuck",
"byteorder",
"gif",
"jpeg-decoder",
"num-iter",
"num-rational",
"num-traits",
"png",
]
[[package]]
name = "indexmap"
version = "1.3.2"
@ -573,6 +628,15 @@ dependencies = [
"autocfg",
]
[[package]]
name = "inflate"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
dependencies = [
"adler32",
]
[[package]]
name = "iovec"
version = "0.1.4"
@ -588,6 +652,15 @@ version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
[[package]]
name = "jpeg-decoder"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b47b4c4e017b01abdc5bcc126d2d1002e5a75bbe3ce73f9f4f311a916363704"
dependencies = [
"byteorder",
]
[[package]]
name = "js-sys"
version = "0.3.39"
@ -646,6 +719,12 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "lzw"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
[[package]]
name = "matches"
version = "0.1.8"
@ -760,6 +839,47 @@ dependencies = [
"winapi 0.3.8",
]
[[package]]
name = "num-integer"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
@ -869,22 +989,22 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pin-project"
version = "0.4.16"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81d480cb4e89522ccda96d0eed9af94180b7a5f93fb28f66e1fd7d68431663d1"
checksum = "edc93aeee735e60ecb40cf740eb319ff23eab1c5748abfdb5c180e4ce49f7791"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "0.4.16"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a82996f11efccb19b685b14b5df818de31c1edcee3daa256ab5775dd98e72feb"
checksum = "e58db2081ba5b4c93bd6be09c40fd36cb9193a8336c384f3b40012e531aa7e40"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.5",
"syn 1.0.21",
"proc-macro2 1.0.13",
"quote 1.0.6",
"syn 1.0.22",
]
[[package]]
@ -906,10 +1026,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
[[package]]
name = "ppv-lite86"
version = "0.2.6"
name = "png"
version = "0.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
checksum = "2c68a431ed29933a4eb5709aca9800989758c97759345860fa5db3cfced0b65d"
dependencies = [
"bitflags",
"crc32fast",
"deflate",
"inflate",
]
[[package]]
name = "ppv-lite86"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
[[package]]
name = "proc-macro-hack"
@ -934,9 +1066,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.12"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319"
checksum = "53f5ffe53a6b28e37c9c1ce74893477864d64f74778a93a4beb43c8fa167f639"
dependencies = [
"unicode-xid 0.2.0",
]
@ -952,11 +1084,11 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.5"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42934bc9c8ab0d3b273a16d8551c8f0fcff46be73276ca083ec2414c15c4ba5e"
checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
dependencies = [
"proc-macro2 1.0.12",
"proc-macro2 1.0.13",
]
[[package]]
@ -1108,7 +1240,7 @@ source = "git+https://github.com/SergioBenitez/Rocket.git?branch=async#78c8ac8cc
dependencies = [
"devise",
"indexmap",
"quote 1.0.5",
"quote 1.0.6",
"rocket_http",
"version_check 0.9.1",
"yansi 0.5.0",
@ -1145,7 +1277,7 @@ dependencies = [
"percent-encoding 2.1.0",
"ruma-api-macros",
"ruma-identifiers",
"ruma-serde 0.2.0",
"ruma-serde 0.2.1",
"serde",
"serde_json",
"strum",
@ -1157,16 +1289,15 @@ version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52b82b4567b9af9b40a86f7778821c016ea961f55e4fee255f8f24bb28ee7452"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.5",
"syn 1.0.21",
"proc-macro2 1.0.13",
"quote 1.0.6",
"syn 1.0.22",
]
[[package]]
name = "ruma-client-api"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a57433fc6dded259aef2b12ceb91d78d3607b182278f648edd5c19c23d81cd"
source = "git+https://github.com/ruma/ruma-client-api.git#3a3ccabbf22c34da5c9de7cac54d9fbd3e571dcf"
dependencies = [
"http",
"js_int",
@ -1174,7 +1305,7 @@ dependencies = [
"ruma-common",
"ruma-events",
"ruma-identifiers",
"ruma-serde 0.1.3",
"ruma-serde 0.2.1",
"serde",
"serde_json",
"strum",
@ -1182,39 +1313,40 @@ dependencies = [
[[package]]
name = "ruma-common"
version = "0.1.1"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "235f2fed35114ef3fbff1b7d5350f22ac712cffff55cc7b7732d39ae4adf6966"
checksum = "253416d67b4bde281f2781424232a58a946a4f1c451d5f857a8d0705d58eaf2a"
dependencies = [
"ruma-serde 0.1.3",
"matches",
"ruma-serde 0.2.1",
"serde",
"serde_json",
]
[[package]]
name = "ruma-events"
version = "0.21.1"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e952b80bddd83666a84db842d3e4d2ea43f8b4df8134864835c1807bd843fe21"
checksum = "0afc6d4da07d10213478d32dc42b6222df0a1ea319e9ced9f8a341617952d909"
dependencies = [
"js_int",
"ruma-common",
"ruma-events-macros",
"ruma-identifiers",
"ruma-serde 0.1.3",
"ruma-serde 0.2.1",
"serde",
"serde_json",
]
[[package]]
name = "ruma-events-macros"
version = "0.21.1"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60256afd4cb1bcdbcd9676e88cbbd09afc2541bd7b0858a559ce9ad7c6cfbb2a"
checksum = "fc706c4a53cc54c3a198cfbcd7dfff20448599d84f90e636d96034d0df5a9ac9"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.5",
"syn 1.0.21",
"proc-macro2 1.0.13",
"quote 1.0.6",
"syn 1.0.22",
]
[[package]]
@ -1257,9 +1389,9 @@ dependencies = [
[[package]]
name = "ruma-serde"
version = "0.2.0"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb00252245980b8f8d9833632e611aba8e1657c9fbefefe2b35c2817fc2b58a4"
checksum = "0dd3d04c6755bae23101dec7426d044b773ef517932f23d5a6254c4caa1cfce3"
dependencies = [
"dtoa",
"itoa",
@ -1387,9 +1519,9 @@ version = "1.0.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.5",
"syn 1.0.21",
"proc-macro2 1.0.13",
"quote 1.0.6",
"syn 1.0.22",
]
[[package]]
@ -1481,9 +1613,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c"
dependencies = [
"heck",
"proc-macro2 1.0.12",
"quote 1.0.5",
"syn 1.0.21",
"proc-macro2 1.0.13",
"quote 1.0.6",
"syn 1.0.22",
]
[[package]]
@ -1499,12 +1631,12 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.21"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4696caa4048ac7ce2bcd2e484b3cef88c1004e41b8e945a277e2c25dc0b72060"
checksum = "1425de3c33b0941002740a420b1a906a350b88d08b82b2c8a01035a3f9447bac"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.5",
"proc-macro2 1.0.13",
"quote 1.0.6",
"unicode-xid 0.2.0",
]
@ -1524,22 +1656,22 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.17"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "467e5ff447618a916519a4e0d62772ab14f434897f3d63f05d8700ef1e9b22c1"
checksum = "5976891d6950b4f68477850b5b9e5aa64d955961466f9e174363f573e54e8ca7"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.17"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e63c1091225b9834089b429bc4a2e01223470e3183e891582909e9d1c4cb55d9"
checksum = "ab81dbd1cd69cd2ce22ecfbdd3bdb73334ba25350649408cc6c085f46d89573d"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.5",
"syn 1.0.21",
"proc-macro2 1.0.13",
"quote 1.0.6",
"syn 1.0.22",
]
[[package]]
@ -1581,16 +1713,16 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.5",
"syn 1.0.21",
"proc-macro2 1.0.13",
"quote 1.0.6",
"syn 1.0.22",
]
[[package]]
name = "tokio-rustls"
version = "0.12.2"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "141afec0978abae6573065a48882c6bae44c5cc61db9b511ac4abf6a09bfd9cc"
checksum = "3068d891551949b37681724d6b73666787cc63fa8e255c812a41d2513aff9775"
dependencies = [
"futures-core",
"rustls",
@ -1760,9 +1892,9 @@ dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2 1.0.12",
"quote 1.0.5",
"syn 1.0.21",
"proc-macro2 1.0.13",
"quote 1.0.6",
"syn 1.0.22",
"wasm-bindgen-shared",
]
@ -1784,7 +1916,7 @@ version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cd85aa2c579e8892442954685f0d801f9129de24fa2136b2c6a539c76b65776"
dependencies = [
"quote 1.0.5",
"quote 1.0.6",
"wasm-bindgen-macro-support",
]
@ -1794,9 +1926,9 @@ version = "0.2.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eb197bd3a47553334907ffd2f16507b4f4f01bbec3ac921a7719e0decdfe72a"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.5",
"syn 1.0.21",
"proc-macro2 1.0.13",
"quote 1.0.6",
"syn 1.0.22",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]

View File

@ -14,10 +14,10 @@ edition = "2018"
[dependencies]
rocket = { git = "https://github.com/SergioBenitez/Rocket.git", branch = "async", features = ["tls"] }
http = "0.2.1"
ruma-client-api = "0.8.0"
ruma-client-api = { git = "https://github.com/ruma/ruma-client-api.git" }
ruma-identifiers = { version = "0.16.1", features = ["rand"] }
ruma-api = "0.16.1"
ruma-events = "0.21.1"
ruma-events = "0.21.2"
ruma-signatures = { git = "https://github.com/ruma/ruma-signatures.git", rev = "1ca545cba8dfd43e0fc8e3c18e1311fb73390a97" }
ruma-federation-api = { git = "https://github.com/ruma/ruma-federation-api.git", rev = "ccbf216f39bbbaa59131cc200eae5bd18aa1947c" }
log = "0.4.8"
@ -31,5 +31,6 @@ rand = "0.7.3"
rust-argon2 = "0.8.2"
reqwest = "0.10.4"
base64 = "0.12.1"
thiserror = "1.0.17"
ruma-common = "0.1.1"
thiserror = "1.0.18"
ruma-common = "0.1.2"
image = { version = "0.23.4", default-features = false, features = ["jpeg", "png", "gif"] }

View File

@ -26,13 +26,14 @@ A fast Matrix homeserver that's optimized for smaller, personal servers, instead
- [x] Typing indications
- [x] Invites, user search
- [x] Password hashing
- [x] Riot E2EE
- [x] Media
- [ ] Basic federation
- [ ] State resolution
- [ ] Permission system
- [ ] Notifications (push rules)
- [ ] Riot presence
- [ ] Proper room creation
- [ ] Riot E2EE
#### How can I contribute?

View File

@ -16,7 +16,7 @@ use ruma_client_api::{
directory::{self, get_public_rooms, get_public_rooms_filtered},
filter::{self, create_filter, get_filter},
keys::{claim_keys, get_keys, upload_keys},
media::{create_content, get_content_thumbnail, get_content, get_media_config},
media::{create_content, get_content, get_content_thumbnail, get_media_config},
membership::{
forget_room, get_member_events, invite_user, join_room_by_id, join_room_by_id_or_alias,
leave_room,
@ -1307,9 +1307,7 @@ pub fn create_message_event_route(
)
.expect("message events are always okay");
MatrixResult(Ok(create_message_event::Response {
event_id: Some(event_id),
}))
MatrixResult(Ok(create_message_event::Response { event_id }))
}
#[put(
@ -1339,9 +1337,7 @@ pub fn create_state_event_for_key_route(
)
.unwrap();
MatrixResult(Ok(create_state_event_for_key::Response {
event_id: Some(event_id),
}))
MatrixResult(Ok(create_state_event_for_key::Response { event_id }))
}
#[put(
@ -1370,9 +1366,7 @@ pub fn create_state_event_for_empty_key_route(
)
.unwrap();
MatrixResult(Ok(create_state_event_for_empty_key::Response {
event_id: Some(event_id),
}))
MatrixResult(Ok(create_state_event_for_empty_key::Response { event_id }))
}
#[get("/_matrix/client/r0/rooms/<_room_id>/state", data = "<body>")]
@ -1805,7 +1799,6 @@ pub fn send_event_to_device_route(
#[get("/_matrix/media/r0/config")]
pub fn get_media_config_route() -> MatrixResult<get_media_config::Response> {
warn!("TODO: get_media_config_route");
MatrixResult(Ok(get_media_config::Response {
upload_size: (20_u32 * 1024 * 1024).into(), // 20 MB
}))
@ -1816,24 +1809,38 @@ pub fn create_content_route(
db: State<'_, Database>,
body: Ruma<create_content::Request>,
) -> MatrixResult<create_content::Response> {
let mxc = format!("mxc://{}/{}", db.globals.server_name(), utils::random_string(MXC_LENGTH));
let mxc = format!(
"mxc://{}/{}",
db.globals.server_name(),
utils::random_string(MXC_LENGTH)
);
db.media
.create(mxc.clone(), body.filename.as_ref(), &body.content_type, &body.file)
.create(
mxc.clone(),
body.filename.as_ref(),
&body.content_type,
&body.file,
)
.unwrap();
MatrixResult(Ok(create_content::Response {
content_uri: mxc,
}))
MatrixResult(Ok(create_content::Response { content_uri: mxc }))
}
#[get("/_matrix/media/r0/download/<_server_name>/<_media_id>", data = "<body>")]
#[get(
"/_matrix/media/r0/download/<_server_name>/<_media_id>",
data = "<body>"
)]
pub fn get_content_route(
db: State<'_, Database>,
body: Ruma<get_content::Request>,
_server_name: String,
_media_id: String,
) -> MatrixResult<get_content::Response> {
if let Some((filename, content_type, file)) = db.media.get(format!("mxc://{}/{}", body.server_name, body.media_id)).unwrap() {
if let Some((filename, content_type, file)) = db
.media
.get(format!("mxc://{}/{}", body.server_name, body.media_id))
.unwrap()
{
MatrixResult(Ok(get_content::Response {
file,
content_type,
@ -1848,18 +1855,26 @@ pub fn get_content_route(
}
}
#[get("/_matrix/media/r0/thumbnail/<_server_name>/<_media_id>", data = "<body>")]
#[get(
"/_matrix/media/r0/thumbnail/<_server_name>/<_media_id>",
data = "<body>"
)]
pub fn get_content_thumbnail_route(
db: State<'_, Database>,
body: Ruma<get_content_thumbnail::Request>,
_server_name: String,
_media_id: String,
) -> MatrixResult<get_content_thumbnail::Response> {
if let Some((_, content_type, file)) = db.media.get(format!("mxc://{}/{}", body.server_name, body.media_id)).unwrap() {
MatrixResult(Ok(get_content_thumbnail::Response {
file,
content_type,
}))
if let Some((_, content_type, file)) = db
.media
.get_thumbnail(
format!("mxc://{}/{}", body.server_name, body.media_id),
body.width.try_into().unwrap(),
body.height.try_into().unwrap(),
)
.unwrap()
{
MatrixResult(Ok(get_content_thumbnail::Response { file, content_type }))
} else {
MatrixResult(Err(Error {
kind: ErrorKind::NotFound,

View File

@ -1,7 +1,8 @@
use crate::{utils, Error, Result};
use std::mem;
pub struct Media {
pub(super) mediaid_file: sled::Tree, // MediaId = MXC + Filename + ContentType
pub(super) mediaid_file: sled::Tree, // MediaId = MXC + WidthHeight + Filename + ContentType
}
impl Media {
@ -15,6 +16,9 @@ impl Media {
) -> Result<()> {
let mut key = mxc.as_bytes().to_vec();
key.push(0xff);
key.extend_from_slice(&0_u32.to_be_bytes()); // Width = 0 if it's not a thumbnail
key.extend_from_slice(&0_u32.to_be_bytes()); // Height = 0 if it's not a thumbnail
key.push(0xff);
key.extend_from_slice(filename.map(|f| f.as_bytes()).unwrap_or_default());
key.push(0xff);
key.extend_from_slice(content_type.as_bytes());
@ -28,10 +32,19 @@ impl Media {
pub fn get(&self, mxc: String) -> Result<Option<(Option<String>, String, Vec<u8>)>> {
let mut prefix = mxc.as_bytes().to_vec();
prefix.push(0xff);
prefix.extend_from_slice(&0_u32.to_be_bytes()); // Width = 0 if it's not a thumbnail
prefix.extend_from_slice(&0_u32.to_be_bytes()); // Height = 0 if it's not a thumbnail
prefix.push(0xff);
if let Some(r) = self.mediaid_file.scan_prefix(&prefix).next() {
let (key, file) = r?;
let mut parts = key.split(|&b| b == 0xff).skip(1);
let mut parts = key.rsplit(|&b| b == 0xff);
let content_type = utils::string_from_bytes(
parts
.next()
.ok_or(Error::BadDatabase("mediaid is invalid"))?,
)?;
let filename_bytes = parts
.next()
@ -42,13 +55,99 @@ impl Media {
Some(utils::string_from_bytes(filename_bytes)?)
};
Ok(Some((filename, content_type, file.to_vec())))
} else {
Ok(None)
}
}
/// Downloads a file's thumbnail.
pub fn get_thumbnail(
&self,
mxc: String,
width: u32,
height: u32,
) -> Result<Option<(Option<String>, String, Vec<u8>)>> {
let mut main_prefix = mxc.as_bytes().to_vec();
main_prefix.push(0xff);
let mut thumbnail_prefix = main_prefix.clone();
thumbnail_prefix.extend_from_slice(&width.to_be_bytes());
thumbnail_prefix.extend_from_slice(&height.to_be_bytes());
thumbnail_prefix.push(0xff);
let mut original_prefix = main_prefix;
original_prefix.extend_from_slice(&0_u32.to_be_bytes()); // Width = 0 if it's not a thumbnail
original_prefix.extend_from_slice(&0_u32.to_be_bytes()); // Height = 0 if it's not a thumbnail
original_prefix.push(0xff);
if let Some(r) = self.mediaid_file.scan_prefix(&thumbnail_prefix).next() {
// Using saved thumbnail
let (key, file) = r?;
let mut parts = key.rsplit(|&b| b == 0xff);
let content_type = utils::string_from_bytes(
parts
.next()
.ok_or(Error::BadDatabase("mediaid is invalid"))?,
)?;
let filename_bytes = parts
.next()
.ok_or(Error::BadDatabase("mediaid is invalid"))?;
let filename = if filename_bytes.is_empty() {
None
} else {
Some(utils::string_from_bytes(filename_bytes)?)
};
Ok(Some((filename, content_type, file.to_vec())))
} else if let Some(r) = self.mediaid_file.scan_prefix(&original_prefix).next() {
// Generate a thumbnail
let (key, file) = r?;
let mut parts = key.rsplit(|&b| b == 0xff);
let content_type = utils::string_from_bytes(
parts
.next()
.ok_or(Error::BadDatabase("mediaid is invalid"))?,
)?;
let filename_bytes = parts
.next()
.ok_or(Error::BadDatabase("mediaid is invalid"))?;
let filename = if filename_bytes.is_empty() {
None
} else {
Some(utils::string_from_bytes(filename_bytes)?)
};
if let Ok(image) = image::load_from_memory(&file) {
let thumbnail = image.thumbnail(width, height);
let mut thumbnail_bytes = Vec::new();
thumbnail.write_to(&mut thumbnail_bytes, image::ImageOutputFormat::Jpeg(75))?;
// Save thumbnail in database so we don't have to generate it again next time
let mut thumbnail_key = key.to_vec();
let width_index = thumbnail_key
.iter()
.position(|&b| b == 0xff)
.ok_or(Error::BadDatabase("mediaid is invalid"))?
+ 1;
let mut widthheight = width.to_be_bytes().to_vec();
widthheight.extend_from_slice(&height.to_be_bytes());
thumbnail_key.splice(
width_index..width_index + 2 * mem::size_of::<u32>(),
widthheight,
);
self.mediaid_file.insert(thumbnail_key, &*thumbnail_bytes)?;
Ok(Some((filename, content_type, thumbnail_bytes)))
} else {
Ok(None)
}
} else {
Ok(None)
}

View File

@ -29,6 +29,11 @@ pub enum Error {
#[from]
source: ruma_events::InvalidEvent,
},
#[error("could not generate image")]
ImageError {
#[from]
source: image::error::ImageError,
},
#[error("bad request")]
BadRequest(&'static str),
#[error("problem in that database")]