Use pict-rs's background uploading feature
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Aode (Lion) 2022-05-02 20:38:46 -05:00
parent e6878e771b
commit 903134c7c7
16 changed files with 776 additions and 352 deletions

372
Cargo.lock generated
View file

@ -218,9 +218,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.56"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
[[package]]
name = "async-stream"
@ -304,6 +304,49 @@ dependencies = [
"tokio",
]
[[package]]
name = "axum"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4af7447fc1214c1f3a1ace861d0216a6c8bb13965b64bbad9650f375b67689a"
dependencies = [
"async-trait",
"axum-core",
"bitflags",
"bytes",
"futures-util",
"http",
"http-body",
"hyper",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"serde",
"sync_wrapper",
"tokio",
"tower",
"tower-http",
"tower-layer",
"tower-service",
]
[[package]]
name = "axum-core"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da31c0ed7b4690e2c78fe4b880d21cd7db04a346ebc658b4270251b695437f17"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http",
"http-body",
"mime",
]
[[package]]
name = "base64"
version = "0.13.0"
@ -381,22 +424,21 @@ dependencies = [
[[package]]
name = "console-api"
version = "0.1.2"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc347c19eb5b940f396ac155822caee6662f850d97306890ac3773ed76c90c5a"
checksum = "24cb05777feccbb2642d4f2df44d0505601a2cd88ca517d8c913f263a5a8dc8b"
dependencies = [
"prost",
"prost-types",
"tonic",
"tonic-build",
"prost 0.10.1",
"prost-types 0.10.1",
"tonic 0.7.1",
"tracing-core",
]
[[package]]
name = "console-subscriber"
version = "0.1.3"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "565a7dfea2d10dd0e5c57cc394d5d441b1910960d8c9211ed14135e0e6ec3a20"
checksum = "8f21a16ee925aa9d2bad2e296beffd6c5b1bfaad50af509d305b8e7f23af20fb"
dependencies = [
"console-api",
"crossbeam-channel",
@ -404,13 +446,13 @@ dependencies = [
"futures",
"hdrhistogram",
"humantime",
"prost-types",
"prost-types 0.10.1",
"serde",
"serde_json",
"thread_local",
"tokio",
"tokio-stream",
"tonic",
"tonic 0.7.1",
"tracing",
"tracing-core",
"tracing-subscriber",
@ -537,9 +579,9 @@ checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e"
[[package]]
name = "flate2"
version = "1.0.22"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af"
dependencies = [
"cfg-if",
"crc32fast",
@ -571,6 +613,7 @@ checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
@ -610,6 +653,17 @@ version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
[[package]]
name = "futures-macro"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.21"
@ -631,6 +685,7 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
@ -718,9 +773,9 @@ dependencies = [
[[package]]
name = "http"
version = "0.2.6"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb"
dependencies = [
"bytes",
"fnv",
@ -739,10 +794,16 @@ dependencies = [
]
[[package]]
name = "httparse"
version = "1.6.0"
name = "http-range-header"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4"
checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29"
[[package]]
name = "httparse"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c"
[[package]]
name = "httpdate"
@ -839,9 +900,9 @@ checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
[[package]]
name = "js-sys"
version = "0.3.56"
version = "0.3.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397"
dependencies = [
"wasm-bindgen",
]
@ -860,9 +921,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.122"
version = "0.2.125"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259"
checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
[[package]]
name = "local-channel"
@ -894,9 +955,9 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.16"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
@ -916,6 +977,12 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "matchit"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb"
[[package]]
name = "md5"
version = "0.7.0"
@ -924,9 +991,9 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771"
[[package]]
name = "memchr"
version = "2.4.1"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "mime"
@ -953,12 +1020,11 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.4.4"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082"
dependencies = [
"adler",
"autocfg",
]
[[package]]
@ -1033,9 +1099,9 @@ dependencies = [
[[package]]
name = "num-integer"
version = "0.1.44"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
@ -1118,10 +1184,10 @@ dependencies = [
"futures-util",
"http",
"opentelemetry",
"prost",
"prost 0.9.0",
"thiserror",
"tokio",
"tonic",
"tonic 0.6.2",
"tonic-build",
]
@ -1137,9 +1203,9 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.2"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37"
checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
dependencies = [
"cfg-if",
"libc",
@ -1172,7 +1238,7 @@ dependencies = [
[[package]]
name = "pict-rs-proxy"
version = "0.3.1"
version = "0.4.0-alpha.1"
dependencies = [
"actix-rt",
"actix-web",
@ -1187,6 +1253,7 @@ dependencies = [
"opentelemetry-otlp",
"ructe",
"serde",
"serde_qs",
"structopt",
"thiserror",
"tracing",
@ -1222,9 +1289,9 @@ dependencies = [
[[package]]
name = "pin-project-lite"
version = "0.2.8"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]]
name = "pin-utils"
@ -1278,7 +1345,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001"
dependencies = [
"bytes",
"prost-derive",
"prost-derive 0.9.0",
]
[[package]]
name = "prost"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a07b0857a71a8cb765763950499cae2413c3f9cede1133478c43600d9e146890"
dependencies = [
"bytes",
"prost-derive 0.10.1",
]
[[package]]
@ -1294,8 +1371,8 @@ dependencies = [
"log",
"multimap",
"petgraph",
"prost",
"prost-types",
"prost 0.9.0",
"prost-types 0.9.0",
"regex",
"tempfile",
"which",
@ -1314,6 +1391,19 @@ dependencies = [
"syn",
]
[[package]]
name = "prost-derive"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b670f45da57fb8542ebdbb6105a925fe571b67f9e7ed9f47a06a84e72b4e7cc"
dependencies = [
"anyhow",
"itertools",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "prost-types"
version = "0.9.0"
@ -1321,14 +1411,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534b7a0e836e3c482d2693070f982e39e7611da9695d4d1f5a4b186b51faef0a"
dependencies = [
"bytes",
"prost",
"prost 0.9.0",
]
[[package]]
name = "prost-types"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68"
dependencies = [
"bytes",
"prost 0.10.1",
]
[[package]]
name = "quote"
version = "1.0.17"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58"
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
dependencies = [
"proc-macro2",
]
@ -1461,24 +1561,24 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
version = "1.0.7"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d65bd28f48be7196d222d95b9243287f48d27aca604e08497513019ff0502cc4"
checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd"
[[package]]
name = "serde"
version = "1.0.136"
version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.136"
version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
dependencies = [
"proc-macro2",
"quote",
@ -1487,15 +1587,28 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.79"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
checksum = "f972498cf015f7c0746cac89ebe1d6ef10c293b94175a243a2d9442c163d9944"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_qs"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6af4cee6cd4b23b45e6709150d1e9af5c748131de7e3316a7c2b3008051ed725"
dependencies = [
"actix-web",
"futures",
"percent-encoding",
"serde",
"thiserror",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
@ -1591,15 +1704,21 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.91"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "sync_wrapper"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8"
[[package]]
name = "tempfile"
version = "3.3.0"
@ -1625,18 +1744,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.30"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.30"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
dependencies = [
"proc-macro2",
"quote",
@ -1665,9 +1784,9 @@ dependencies = [
[[package]]
name = "tinyvec"
version = "1.5.1"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
@ -1680,9 +1799,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.17.0"
version = "1.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
checksum = "dce653fb475565de9f6fb0614b28bca8df2c430c0cf84bcd9c843f15de5414cc"
dependencies = [
"bytes",
"libc",
@ -1778,8 +1897,8 @@ dependencies = [
"hyper-timeout",
"percent-encoding",
"pin-project",
"prost",
"prost-derive",
"prost 0.9.0",
"prost-derive 0.9.0",
"tokio",
"tokio-stream",
"tokio-util 0.6.9",
@ -1790,6 +1909,38 @@ dependencies = [
"tracing-futures",
]
[[package]]
name = "tonic"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30fb54bf1e446f44d870d260d99957e7d11fb9d0a0f5bd1a662ad1411cc103f9"
dependencies = [
"async-stream",
"async-trait",
"axum",
"base64",
"bytes",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"hyper",
"hyper-timeout",
"percent-encoding",
"pin-project",
"prost 0.10.1",
"prost-derive 0.10.1",
"tokio",
"tokio-stream",
"tokio-util 0.7.1",
"tower",
"tower-layer",
"tower-service",
"tracing",
"tracing-futures",
]
[[package]]
name = "tonic-build"
version = "0.6.2"
@ -1822,6 +1973,25 @@ dependencies = [
"tracing",
]
[[package]]
name = "tower-http"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e980386f06883cf4d0578d6c9178c81f68b45d77d00f2c2c1bc034b3439c2c56"
dependencies = [
"bitflags",
"bytes",
"futures-core",
"futures-util",
"http",
"http-body",
"http-range-header",
"pin-project-lite",
"tower",
"tower-layer",
"tower-service",
]
[[package]]
name = "tower-layer"
version = "0.3.1"
@ -1836,9 +2006,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]]
name = "tracing"
version = "0.1.32"
version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09"
dependencies = [
"cfg-if",
"log",
@ -1864,9 +2034,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
version = "0.1.20"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b"
checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
dependencies = [
"proc-macro2",
"quote",
@ -1892,9 +2062,9 @@ dependencies = [
[[package]]
name = "tracing-core"
version = "0.1.24"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90442985ee2f57c9e1b548ee72ae842f4a9a20e3f417cc38dbc5dc684d9bb4ee"
checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f"
dependencies = [
"lazy_static",
"valuable",
@ -1922,9 +2092,9 @@ dependencies = [
[[package]]
name = "tracing-log"
version = "0.1.2"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3"
checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
dependencies = [
"lazy_static",
"log",
@ -1946,9 +2116,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
version = "0.3.10"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9df98b037d039d03400d9dd06b0f8ce05486b5f25e9a2d7d36196e142ebbc52"
checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596"
dependencies = [
"ansi_term",
"lazy_static",
@ -1976,9 +2146,9 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]]
name = "unicode-bidi"
version = "0.3.7"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]]
name = "unicode-normalization"
@ -2003,9 +2173,9 @@ checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
[[package]]
name = "url"
@ -2070,9 +2240,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.79"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@ -2080,9 +2250,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.79"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4"
dependencies = [
"bumpalo",
"lazy_static",
@ -2095,9 +2265,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.79"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -2105,9 +2275,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.79"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
dependencies = [
"proc-macro2",
"quote",
@ -2118,9 +2288,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.79"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744"
[[package]]
name = "which"
@ -2157,9 +2327,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.34.0"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
@ -2170,30 +2340,30 @@ dependencies = [
[[package]]
name = "windows_aarch64_msvc"
version = "0.34.0"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_i686_gnu"
version = "0.34.0"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_msvc"
version = "0.34.0"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_x86_64_gnu"
version = "0.34.0"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.34.0"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"

View file

@ -1,7 +1,7 @@
[package]
name = "pict-rs-proxy"
description = "A simple web frontend for pict-rs"
version = "0.3.1"
version = "0.4.0-alpha.1"
authors = ["asonix <asonix@asonix.dog>"]
license = "AGPL-3.0"
readme = "README.md"
@ -28,6 +28,7 @@ once_cell = "1.4"
opentelemetry = { version = "0.17", features = ["rt-tokio"] }
opentelemetry-otlp = "0.10"
serde = { version = "1.0", features = ["derive"] }
serde_qs = { version = "0.9", features = ["actix4"] }
structopt = "0.3.14"
thiserror = "1.0"
tracing = "0.1"

View file

@ -38,6 +38,7 @@ include!(concat!(env!("OUT_DIR"), "/templates.rs"));
const HOURS: u32 = 60 * 60;
const DAYS: u32 = 24 * HOURS;
// TODO: change structopt use to clap
#[derive(Clone, Debug, StructOpt)]
struct Config {
#[structopt(
@ -86,7 +87,15 @@ struct Config {
impl Config {
fn upstream_upload_url(&self) -> String {
let mut url = self.upstream.clone();
url.set_path("image");
url.set_path("image/backgrounded");
url.to_string()
}
fn upstream_claim_url(&self, upload_id: &str) -> String {
let mut url = self.upstream.clone();
url.set_path("image/backgrounded/claim");
url.set_query(Some(&format!("upload_id={}", upload_id)));
url.to_string()
}
@ -172,6 +181,12 @@ impl Config {
static CONFIG: Lazy<Config> = Lazy::new(Config::from_args);
pub enum UploadResult<'a> {
Image(Image),
UploadId(&'a str),
Error(Error),
}
#[derive(Debug, serde::Deserialize)]
enum FileType {
#[serde(rename = "jpg")]
@ -195,6 +210,40 @@ pub struct Images {
files: Option<Vec<Image>>,
}
#[derive(Debug, serde::Deserialize)]
pub struct Upload {
// This is technically a UUID, but we don't care in this program
upload_id: String,
}
#[derive(Debug, serde::Deserialize)]
pub struct Uploads {
msg: String,
uploads: Option<Vec<Upload>>,
}
#[derive(Debug, Default, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct UploadQuery {
#[serde(default)]
uploads: Vec<String>,
#[serde(default)]
files: Vec<(String, String)>,
}
impl UploadQuery {
fn try_from_uploads(uploads: Uploads) -> Result<Self, String> {
if let Some(uploads) = uploads.uploads {
Ok(UploadQuery {
uploads: uploads.into_iter().map(|u| u.upload_id).collect(),
files: vec![],
})
} else {
Err(uploads.msg)
}
}
}
impl Images {
fn files(&self) -> Option<&[Image]> {
self.files.as_ref().map(|v| v.as_ref())
@ -272,7 +321,7 @@ fn statics(file: &str) -> String {
}
#[derive(Debug)]
struct Error {
pub struct Error {
context: SpanTrace,
kind: ErrorKind,
}
@ -319,8 +368,12 @@ impl ResponseError for Error {
}
}
// TODO: make this error type better (do not forward display impl)
#[derive(Debug, thiserror::Error)]
enum ErrorKind {
#[error("{0}")]
UploadFailed(String),
#[error("{0}")]
Io(#[from] std::io::Error),
@ -329,15 +382,139 @@ enum ErrorKind {
#[error("{0}")]
JsonPayload(#[from] awc::error::JsonPayloadError),
#[error("{0}")]
Query(#[from] serde_qs::Error),
#[error("{0}")]
Canceled(#[from] actix_rt::task::JoinError),
}
#[tracing::instrument(name = "Upload")]
#[tracing::instrument(name = "Upload Page")]
async fn index() -> Result<HttpResponse, Error> {
render(HttpResponse::Ok(), |cursor| {
self::templates::index(cursor, "/upload", "images[]")
})
}
#[tracing::instrument(name = "List Uploads", skip(client))]
async fn list_uploads(
query: serde_qs::actix::QsQuery<UploadQuery>,
client: web::Data<Client>,
) -> Result<HttpResponse, Error> {
let query = query.into_inner();
let mut upload_handles = Vec::new();
let mut details_handles = Vec::new();
for upload_id in &query.uploads {
let claim_url = CONFIG.upstream_claim_url(upload_id.as_str());
let client = client.clone();
upload_handles.push(actix_rt::spawn(async move {
let mut res = client.get(claim_url).send().await?;
if res.status() == 204 {
return Ok(None) as Result<Option<Image>, Error>;
}
let result = res.json::<Images>().await?;
match result.files {
Some(files) if files.len() == 1 => Ok(files.into_iter().next()),
Some(_) => Err(ErrorKind::UploadFailed("Bad response".into()).into()),
None => Err(ErrorKind::UploadFailed(result.msg).into()),
}
}));
}
for (file, delete_token) in &query.files {
let details_url = CONFIG.upstream_details_url(file);
let file = file.clone();
let delete_token = delete_token.clone();
let client = client.clone();
details_handles.push(actix_rt::spawn(async move {
let mut res = client.get(details_url).send().await?;
let details = res.json::<Details>().await?;
Ok(Image {
file,
delete_token,
details,
})
}))
}
let mut results = Vec::new();
let mut any_incomplete = false;
for handle in details_handles {
let res = handle.await.map_err(Error::from).and_then(|res| res);
match res {
Ok(image) => {
results.push(UploadResult::Image(image));
}
Err(e) => {
results.push(UploadResult::Error(e));
}
}
}
for (handle, upload_id) in upload_handles.into_iter().zip(&query.uploads) {
let res = handle.await.map_err(Error::from).and_then(|res| res);
match res {
Ok(Some(image)) => {
results.push(UploadResult::Image(image));
}
Ok(None) => {
any_incomplete = true;
results.push(UploadResult::UploadId(upload_id));
}
Err(e) => {
results.push(UploadResult::Error(e));
}
}
}
if any_incomplete {
let new_query =
results
.into_iter()
.fold(UploadQuery::default(), |mut query, res| match res {
UploadResult::Image(img) => {
query.files.push((img.file, img.delete_token));
query
}
UploadResult::UploadId(id) => {
query.uploads.push(id.to_owned());
query
}
_ => query,
});
if new_query != query {
let query = serde_qs::to_string(&new_query)?;
return Ok(HttpResponse::SeeOther()
.insert_header((LOCATION, format!("/upload?{}", query)))
.finish());
}
return render(HttpResponse::Ok(), |cursor| {
self::templates::uploads(cursor)
});
}
render(HttpResponse::Ok(), |cursor| {
self::templates::finished_uploads(cursor, results)
})
}
#[tracing::instrument(name = "Upload", skip(req, body, client))]
async fn upload(
req: HttpRequest,
@ -354,11 +531,15 @@ async fn upload(
let mut res = client_request.send_stream(body).await?;
let images = res.json::<Images>().await?;
let uploads = res.json::<Uploads>().await?;
render(HttpResponse::build(res.status()), |cursor| {
self::templates::images(cursor, images)
})
let query = UploadQuery::try_from_uploads(uploads).map_err(ErrorKind::UploadFailed)?;
let query = serde_qs::to_string(&query)?;
Ok(HttpResponse::SeeOther()
.insert_header((LOCATION, format!("/upload?{}", query)))
.finish())
}
const THUMBNAIL_SIZES: &[u64] = &[40, 50, 80, 100, 200, 400, 800, 1200];
@ -713,7 +894,11 @@ async fn main() -> Result<(), anyhow::Error> {
.app_data(web::Data::new(client))
.wrap(TracingLogger::default())
.service(web::resource("/").route(web::get().to(index)))
.service(web::resource("/upload").route(web::post().to(upload)))
.service(
web::resource("/upload")
.route(web::post().to(upload))
.route(web::get().to(list_uploads)),
)
.service(web::resource("/image/{filename}").route(web::get().to(full_res)))
.service(web::resource("/thumbnails").route(web::get().to(thumbs)))
.service(web::resource("/view/{size}/{filename}").route(web::get().to(view)))

11
static/uploads.js Normal file
View file

@ -0,0 +1,11 @@
(function() {
function reloadOnComplete() {
if (document.readyState === 'complete') {
// Do not use window.reload() because it's bugged on firefox
window.location.href = window.location.href;
}
}
document.addEventListener('readystatechange', reloadOnComplete);
reloadOnComplete();
})()

View file

@ -4,24 +4,24 @@
@(image: &Image)
@:layout_html("Confirm Delete", Some(&format!("Delete {} from pict-rs", image.filename())), {
<title>Confirm Delete</title>
<link rel="stylesheet" href="@crate::statics(images_css.name)" type="text/css" />
<title>Confirm Delete</title>
<link rel="stylesheet" href="@crate::statics(images_css.name)" type="text/css" />
}, {
<section>
<article>
<h3>Are you sure you want to delete @image.filename()?</h3>
</article>
<article>
<div class="imagebox">
<picture>
<source type="image/webp" srcset="@image.thumb(800, FileType::Webp)" />
<img src="@image.thumb(800, FileType::Jpg)" alt="@image.filename()" title="@image.filename()" />
</picture>
</div>
<p>
<a href="@image.confirm_delete()">Delete @image.filename()</a>
</p>
</article>
@:return_home_html()
</section>
<section>
<article>
<h3>Are you sure you want to delete @image.filename()?</h3>
</article>
<article>
<div class="imagebox">
<picture>
<source type="image/webp" srcset="@image.thumb(800, FileType::Webp)" />
<img src="@image.thumb(800, FileType::Jpg)" alt="@image.filename()" title="@image.filename()" />
</picture>
</div>
<p>
<a href="@image.confirm_delete()">Delete @image.filename()</a>
</p>
</article>
@:return_home_html()
</section>
})

View file

@ -3,10 +3,10 @@
@(filename: &str)
@:layout_html(&format!("Deleted {}", filename), None, {}, {
<section>
<article>
<h3>Deleted @filename</h3>
</article>
@:return_home_html()
</section>
<section>
<article>
<h3>Deleted @filename</h3>
</article>
@:return_home_html()
</section>
})

View file

@ -3,13 +3,13 @@
@(msg: &str)
@:layout_html("Error", None, {}, {
<section>
<article>
<h3>There was an error processing your request</h3>
</article>
<article>
<p>@msg</p>
</article>
@:return_home_html()
</section>
<section>
<article>
<h3>There was an error processing your request</h3>
</article>
<article>
<p>@msg</p>
</article>
@:return_home_html()
</section>
})

View file

@ -0,0 +1,63 @@
@use super::{layout_html, return_home_html, statics::images_css};
@use crate::{UploadResult, FileType};
@(results: Vec<UploadResult>)
@:layout_html("Upload Complete!", None, {
<link rel="stylesheet" href="@crate::statics(images_css.name)" type="text/css" />
}, {
<section>
<article>
<h3>Your images have been uploaded</h3>
</article>
<article>
<p class="subtitle">Do not lose these links</p>
</article>
<ul>
@for result in results {
<li>
<article>
@match result {
UploadResult::Image(image) => {
<div class="imagebox">
<picture>
<source type="image/webp" srcset="@image.thumb(800, FileType::Webp)" />
<img src="@image.thumb(800, FileType::Jpg)" alt="@image.filename()" title="@image.filename()" />
</picture>
</div>
<p>
Link:<br />
<a href="@image.view(None)" target="_blank" rel="noopener noreferrer">
@image.view(None)
</a>
</p>
<p>
Thumbnails:<br />
<a href="@image.thumbnails()" target="_blank" rel="noopener noreferrer">
@image.thumbnails()
</a>
</p>
<p>
Delete link:<br />
<a href="@image.delete()" target="_blank" rel="noopener noreferrer">
@image.delete()
</a>
</p>
}
UploadResult::Error(error) => {
<p>
Error:<br />
@error.to_string()
</p>
}
UploadResult::UploadId(_) => {
<p>Wating...</p>
}
}
</article>
</li>
}
</ul>
@:return_home_html()
</section>
})

View file

@ -4,68 +4,56 @@
@(images: Images)
@:layout_html(images.message(), None, {
<link rel="stylesheet" href="@crate::statics(images_css.name)" type="text/css" />
<link rel="stylesheet" href="@crate::statics(images_css.name)" type="text/css" />
}, {
<section>
@if let Some(images) = images.files() {
<article>
<h3>Your images have been uploaded</h3>
</article>
<article>
<p class="subtitle">Do not lose these links</p>
</article>
<ul>
@for image in images {
<li>
<article>
<div class="imagebox">
<picture>
<source type="image/webp" srcset="@image.thumb(800, FileType::Webp)" />
<img src="@image.thumb(800, FileType::Jpg)" alt="@image.filename()" title="@image.filename()" />
</picture>
</div>
<p>
Link:<br />
<a
href="@image.view(None)"
target="_blank"
rel="noopener noreferrer"
>
@image.view(None)
</a>
</p>
<p>
Thumbnails:<br />
<a
href="@image.thumbnails()"
target="_blank"
rel="noopener noreferrer"
>
@image.thumbnails()
</a>
</p>
<p>
Delete link:<br />
<a
href="@image.delete()"
target="_blank"
rel="noopener noreferrer"
>
@image.delete()
</a>
</p>
</article>
</li>
}
</ul>
} else {
<article>
<h3>There was an error uploading your images</h3>
</article>
<article>
<p>@images.msg()</p>
</article>
}
@:return_home_html()
</section>
<section>
@if let Some(images) = images.files() {
<article>
<h3>Your images have been uploaded</h3>
</article>
<article>
<p class="subtitle">Do not lose these links</p>
</article>
<ul>
@for image in images {
<li>
<article>
<div class="imagebox">
<picture>
<source type="image/webp" srcset="@image.thumb(800, FileType::Webp)" />
<img src="@image.thumb(800, FileType::Jpg)" alt="@image.filename()" title="@image.filename()" />
</picture>
</div>
<p>
Link:<br />
<a href="@image.view(None)" target="_blank" rel="noopener noreferrer">
@image.view(None)
</a>
</p>
<p>
Thumbnails:<br />
<a href="@image.thumbnails()" target="_blank" rel="noopener noreferrer">
@image.thumbnails()
</a>
</p>
<p>
Delete link:<br />
<a href="@image.delete()" target="_blank" rel="noopener noreferrer">
@image.delete()
</a>
</p>
</article>
</li>
}
</ul>
} else {
<article>
<h3>There was an error uploading your images</h3>
</article>
<article>
<p>@images.msg()</p>
</article>
}
@:return_home_html()
</section>
})

View file

@ -3,37 +3,35 @@
@(endpoint: &str, name: &str)
@:layout_html("Upload Images", None, {
<link rel="stylesheet" href="@crate::statics(form_css.name)" type="text/css" />
<script src="@crate::statics(form_js.name)" type="text/javascript"></script>
<link rel="stylesheet" href="@crate::statics(form_css.name)" type="text/css" />
<script src="@crate::statics(form_js.name)" type="text/javascript"></script>
}, {
<section>
<form method="post" action="@endpoint" enctype="multipart/form-data">
<article>
<div class="legend">
<h3><legend>Upload Images</legend></h3>
</div>
</article>
<article>
<label for="@name">Chose up to ten images to upload (PNG, JPG, GIF, WEBP, MP4)</label>
<div class="file-upload">
<div class="button plain">
<span id="file-upload-text">Select Files</span>
<input
id="file-upload-input"
type="file"
name="@name"
accept="image/png,image/gif,image/jpeg,image/webp,video/mp4,video/quicktime,.jpg,.jpeg,.png,.gif,.webp,.m4v,.mp4"
multiple
/>
</div>
</div>
</article>
<article>
<div class="button submit">
<span>Upload</span>
<button>Upload</button>
</div>
</article>
</form>
</section>
<section>
<form method="post" action="@endpoint" enctype="multipart/form-data">
<article>
<div class="legend">
<h3>
<legend>Upload Images</legend>
</h3>
</div>
</article>
<article>
<label for="@name">Chose up to ten images to upload (PNG, JPG, GIF, WEBP, MP4)</label>
<div class="file-upload">
<div class="button plain">
<span id="file-upload-text">Select Files</span>
<input id="file-upload-input" type="file" name="@name"
accept="image/png,image/gif,image/jpeg,image/webp,video/mp4,video/quicktime,.jpg,.jpeg,.png,.gif,.webp,.m4v,.mp4"
multiple />
</div>
</div>
</article>
<article>
<div class="button submit">
<span>Upload</span>
<button>Upload</button>
</div>
</article>
</form>
</section>
})

View file

@ -2,26 +2,31 @@
@(title: &str, description: Option<&str>, head: Content, body: Content)
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>@title</title>
<link rel="stylesheet" href="@crate::statics(layout_css.name)" type="text/css" />
<meta property="og:title" content="@title" />
@if let Some(description) = description {
<meta property="og:description" content="@description" />
} else {
<meta property="og:description" content="Upload and share image files" />
}
<meta property="og:type" content="website" />
<link rel="shortcut icon" type="image/png" href="@crate::statics(favicon_ico.name)">
@:head()
</head>
<body>
<div class="title"><h1>pict-rs</h1></div>
@:body()
</body>
</html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>@title</title>
<link rel="stylesheet" href="@crate::statics(layout_css.name)" type="text/css" />
<meta property="og:title" content="@title" />
@if let Some(description) = description {
<meta property="og:description" content="@description" />
} else {
<meta property="og:description" content="Upload and share image files" />
}
<meta property="og:type" content="website" />
<link rel="shortcut icon" type="image/png" href="@crate::statics(favicon_ico.name)">
@:head()
</head>
<body>
<div class="title">
<h1>pict-rs</h1>
</div>
@:body()
</body>
</html>

View file

@ -3,15 +3,15 @@
@()
@:layout_html("Not Found", None, {
<link rel="stylesheet" href="@crate::statics(not_found_css.name)" type="text/css" />
<link rel="stylesheet" href="@crate::statics(not_found_css.name)" type="text/css" />
}, {
<section>
<article>
<h3>Oops!</h3>
</article>
<article>
<p>The page you are looking for could not be found</p>
</article>
@:return_home_html()
</section>
<section>
<article>
<h3>Oops!</h3>
</article>
<article>
<p>The page you are looking for could not be found</p>
</article>
@:return_home_html()
</section>
})

View file

@ -1,5 +1,5 @@
@()
<article>
<p><a href="/">Return Home</a></p>
<p><a href="/">Return Home</a></p>
</article>

View file

@ -4,42 +4,38 @@
@(image: Image, sizes: &[u64])
@:layout_html("Thumbnails", Some(&format!("Thumbnails for {}", image.filename())), {
<meta property="og:image" content="@image.link()" />
<meta property="og:url" content="@image.link()" />
<meta property="og:image:alt" content="Image: @image.filename()" />
<link rel="stylesheet" href="@crate::statics(images_css.name)" type="text/css" />
<meta property="og:image" content="@image.link()" />
<meta property="og:url" content="@image.link()" />
<meta property="og:image:alt" content="Image: @image.filename()" />
<link rel="stylesheet" href="@crate::statics(images_css.name)" type="text/css" />
}, {
<section>
<article>
<h3>Here are your thumbnails</h3>
</article>
<ul>
<li>
<article>
<p>Original File:<br /><a href="@image.view(None)">@image.view(None)</a></p>
</article>
</li>
@for size in sizes {
<li>
<article>
<picture>
<source type="image/webp" srcset="@image.thumb(*size, FileType::Webp)" />
<img src="@image.thumb(*size, FileType::Jpg)" alt="@image.filename()" title="@image.filename()" />
</picture>
<p>@size x @size</p>
<p>
<a
href="@image.view(Some(*size))"
target="_blank"
rel="noopener noreferrer"
>
@image.view(Some(*size))
</a>
</p>
</article>
</li>
}
</ul>
@:return_home_html()
</section>
<section>
<article>
<h3>Here are your thumbnails</h3>
</article>
<ul>
<li>
<article>
<p>Original File:<br /><a href="@image.view(None)">@image.view(None)</a></p>
</article>
</li>
@for size in sizes {
<li>
<article>
<picture>
<source type="image/webp" srcset="@image.thumb(*size, FileType::Webp)" />
<img src="@image.thumb(*size, FileType::Jpg)" alt="@image.filename()" title="@image.filename()" />
</picture>
<p>@size x @size</p>
<p>
<a href="@image.view(Some(*size))" target="_blank" rel="noopener noreferrer">
@image.view(Some(*size))
</a>
</p>
</article>
</li>
}
</ul>
@:return_home_html()
</section>
})

14
templates/uploads.rs.html Normal file
View file

@ -0,0 +1,14 @@
@use super::{layout_html, return_home_html, statics::uploads_js};
@()
@:layout_html("Waiting for uploads...", None, {
<script src="@crate::statics(uploads_js.name)" type="text/javascript"></script>
}, {
<section>
<article>
<h3>Your images are being uploaded, please refresh in a few seconds...</h3>
</article>
@:return_home_html()
</section>
})

View file

@ -3,46 +3,39 @@
@(image: Image, size: Option<u64>)
@:layout_html(&format!("Image: {}", image.filename()), Some("An image hosted on pict-rs"), {
<link rel="stylesheet" href="@crate::statics(images_css.name)" type="text/css" />
@if let Some(size) = size {
<meta property="og:image" content="@image.thumb(size, FileType::Jpg)" />
<meta property="og:url" content="@image.view(Some(size))" />
<meta property="og:image:type" content="image/jpg" />
} else {
<meta property="og:image" content="@image.link()" />
<meta property="og:url" content="@image.view(None)" />
}
<meta property="og:image:alt" content="Image: @image.filename()" />
}, {
<section>
<article>
<div>
@if let Some(size) = size {
<picture>
<source type="image/webp" srcset="@image.thumb(size, FileType::Webp)" />
<img src="@image.thumb(size, FileType::Jpg)" alt="@image.filename()" title="@image.filename()" />
</picture>
<p><a href="@image.thumb(size, FileType::Jpg)">Direct Link</a></p>
} else {
@if image.is_video() {
<video
src="@image.link()"
alt="@image.filename()"
title="@image.filename()"
type="@image.mime()"
autoplay
muted
loop
>
</video>
} else {
<img src="@image.link()" alt="@image.filename()" title="@image.filename()" />
}
<p><a href="@image.link()">Direct Link</a></p>
}
</div>
</article>
@:return_home_html()
</section>
})
@:layout_html(&format!("Image: {}", image.filename()), Some("An image hosted on pict-rs"), {
<link rel="stylesheet" href="@crate::statics(images_css.name)" type="text/css" />
@if let Some(size) = size {
<meta property="og:image" content="@image.thumb(size, FileType::Jpg)" />
<meta property="og:url" content="@image.view(Some(size))" />
<meta property="og:image:type" content="image/jpg" />
} else {
<meta property="og:image" content="@image.link()" />
<meta property="og:url" content="@image.view(None)" />
}
<meta property="og:image:alt" content="Image: @image.filename()" />
}, {
<section>
<article>
<div>
@if let Some(size) = size {
<picture>
<source type="image/webp" srcset="@image.thumb(size, FileType::Webp)" />
<img src="@image.thumb(size, FileType::Jpg)" alt="@image.filename()" title="@image.filename()" />
</picture>
<p><a href="@image.thumb(size, FileType::Jpg)">Direct Link</a></p>
} else {
@if image.is_video() {
<video src="@image.link()" alt="@image.filename()" title="@image.filename()" type="@image.mime()" autoplay muted
loop>
</video>
} else {
<img src="@image.link()" alt="@image.filename()" title="@image.filename()" />
}
<p><a href="@image.link()">Direct Link</a></p>
}
</div>
</article>
@:return_home_html()
</section>
})