Start repository:

Currently has the ability to open, thumbnail, encrypt, and upload single images, but still needs better UX and output, as well as the ability to generate index files
This commit is contained in:
Emi Simpson 2022-08-11 20:00:13 -04:00
commit 8c4336709b
Signed by: Emi
GPG key ID: A12F2C2FFDC3D847
8 changed files with 1178 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

870
Cargo.lock generated Normal file
View file

@ -0,0 +1,870 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "adler32"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]]
name = "aead"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
dependencies = [
"generic-array",
]
[[package]]
name = "aes"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
"opaque-debug",
]
[[package]]
name = "aes-gcm"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
dependencies = [
"aead",
"aes",
"cipher",
"ctr",
"ghash",
"subtle",
]
[[package]]
name = "argh"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7e7e4aa7e40747e023c0761dafcb42333a9517575bbf1241747f68dd3177a62"
dependencies = [
"argh_derive",
"argh_shared",
]
[[package]]
name = "argh_derive"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69f2bd7ff6ed6414f4e5521bd509bae46454bbd513801767ced3f21a751ab4bc"
dependencies = [
"argh_shared",
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "argh_shared"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47253b98986dafc7a3e1cf3259194f1f47ac61abb57a57f46ec09e48d004ecda"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "aviary-cli"
version = "0.1.0"
dependencies = [
"argh",
"argh_derive",
"base64",
"blurhash",
"image",
"iota-crypto",
"itertools",
"mime",
"ureq",
"webp",
]
[[package]]
name = "base64"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
dependencies = [
"generic-array",
]
[[package]]
name = "block-modes"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e"
dependencies = [
"block-padding",
"cipher",
]
[[package]]
name = "block-padding"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
[[package]]
name = "blurhash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8671e4c8bf59f8784aa27fe4c8e152f2a45dfeb91a52d114e5d104a451494bb4"
[[package]]
name = "bumpalo"
version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
[[package]]
name = "bytemuck"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
dependencies = [
"jobserver",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chunked_transfer"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
[[package]]
name = "cipher"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
dependencies = [
"generic-array",
]
[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "cpufeatures"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "ctr"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea"
dependencies = [
"cipher",
]
[[package]]
name = "deflate"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f"
dependencies = [
"adler32",
]
[[package]]
name = "digest"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
name = "either"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
[[package]]
name = "flate2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "form_urlencoded"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
dependencies = [
"matches",
"percent-encoding",
]
[[package]]
name = "generic-array"
version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [
"cfg-if",
"js-sys",
"libc",
"wasi",
"wasm-bindgen",
]
[[package]]
name = "ghash"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
dependencies = [
"opaque-debug",
"polyval",
]
[[package]]
name = "gif"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06"
dependencies = [
"color_quant",
"weezl",
]
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]]
name = "idna"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "image"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e30ca2ecf7666107ff827a8e481de6a132a9b687ed3bb20bb1c144a36c00964"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"gif",
"jpeg-decoder",
"num-rational",
"num-traits",
"png",
"scoped_threadpool",
"tiff",
]
[[package]]
name = "iota-crypto"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "538b238fbd6fa732f526f6401656fa6a366598b9fe1ca35185e47f3978369707"
dependencies = [
"aead",
"aes",
"aes-gcm",
"block-modes",
"digest",
"generic-array",
"getrandom",
"hmac",
"sha2",
"subtle",
]
[[package]]
name = "itertools"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
dependencies = [
"either",
]
[[package]]
name = "jobserver"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa"
dependencies = [
"libc",
]
[[package]]
name = "jpeg-decoder"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b"
[[package]]
name = "js-sys"
version = "0.3.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.129"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64de3cc433455c14174d42e554d4027ee631c4d046d43e3ecc6efc4636cdc7a7"
[[package]]
name = "libwebp-sys"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439fd1885aa28937e7edcd68d2e793cb4a22f8733460d2519fbafd2b215672bf"
dependencies = [
"cc",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
[[package]]
name = "matches"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "mime"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "miniz_oxide"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
dependencies = [
"adler",
]
[[package]]
name = "num-integer"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "percent-encoding"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "png"
version = "0.17.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba"
dependencies = [
"bitflags",
"crc32fast",
"deflate",
"miniz_oxide",
]
[[package]]
name = "polyval"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug",
"universal-hash",
]
[[package]]
name = "proc-macro2"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
"winapi",
]
[[package]]
name = "rustls"
version = "0.20.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033"
dependencies = [
"log",
"ring",
"sct",
"webpki",
]
[[package]]
name = "scoped_threadpool"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
[[package]]
name = "sct"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "sha2"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tiff"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7259662e32d1e219321eb309d5f9d898b779769d81b76e762c07c8e5d38fcb65"
dependencies = [
"flate2",
"jpeg-decoder",
"weezl",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "typenum"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]]
name = "unicode-bidi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]]
name = "unicode-ident"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
[[package]]
name = "unicode-normalization"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
[[package]]
name = "universal-hash"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05"
dependencies = [
"generic-array",
"subtle",
]
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "ureq"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97acb4c28a254fd7a4aeec976c46a7fa404eac4d7c134b30c75144846d7cb8f"
dependencies = [
"base64",
"chunked_transfer",
"log",
"once_cell",
"rustls",
"url",
"webpki",
"webpki-roots",
]
[[package]]
name = "url"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
dependencies = [
"form_urlencoded",
"idna",
"matches",
"percent-encoding",
]
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a"
[[package]]
name = "web-sys"
version = "0.3.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webp"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf022f821f166079a407d000ab57e84de020e66ffbbf4edde999bc7d6e371cae"
dependencies = [
"image",
"libwebp-sys",
]
[[package]]
name = "webpki"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "webpki-roots"
version = "0.22.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf"
dependencies = [
"webpki",
]
[[package]]
name = "weezl"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

29
Cargo.toml Normal file
View file

@ -0,0 +1,29 @@
[package]
name = "aviary-cli"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
argh = "0.1.8"
argh_derive = "0.1.8"
webp = "0.2.2"
itertools = "0.10.3"
blurhash = "0.1.1"
base64 = "0.13.0"
mime = "0.3.16"
[dependencies.iota-crypto]
version = "0.13.0"
features = ["aes", "random"]
[dependencies.ureq]
version = "2.5.0"
default-features = false
features = ["tls"]
[dependencies.image]
version = "0.24.3"
default-features = false
features = ["gif", "jpeg", "ico", "png", "tiff", "webp", "bmp", "hdr"]

26
src/crypto.rs Normal file
View file

@ -0,0 +1,26 @@
use crypto::ciphers::{
aes_gcm::Aes256Gcm,
traits::Aead,
};
use crypto::utils::rand;
const NONCE: [u8; 12] = [0xd0, 0xc3, 0x75, 0x56, 0x58, 0xc1, 0x7e, 0x5f, 0xd6, 0xcc, 0xb6, 0x76];
pub fn encrypt(key: &[u8; 32], plaintext: &[u8]) -> Vec<u8> {
let mut result = vec![0; plaintext.len() + 16];
let (cyphertext, tag) = result.split_at_mut(plaintext.len());
Aes256Gcm::try_encrypt(
key,
&NONCE,
&[],
plaintext,
cyphertext,
tag).expect("Unexpected cryptography error");
result
}
pub fn make_key() -> [u8; 32] {
let mut result = [0; 32];
rand::fill(&mut result).expect("Unexpected error generating random data");
result
}

190
src/main.rs Normal file
View file

@ -0,0 +1,190 @@
mod parse;
mod crypto;
mod upload;
mod thumbnailing;
use std::borrow::Cow;
use std::io::{self, ErrorKind, Read};
use std::fs::File;
use std::path::{PathBuf, Path};
use itertools::{Itertools, Either};
#[derive(Debug)]
enum AviaryError {
/// One of the files passed by the user simply did not exist
///
/// The attached path is the file which didn't exist
///
/// Handling: Halt execution before any upload begins and alert the user of any
/// missing files.
FileDNE(PathBuf),
/// The program lacks permission to read one of the images provided by the user
///
/// Handling: Halt execution before any upload begins and alert the user of the issue
ReadPermissionDenied(PathBuf),
/// There was an issue reading data from the disk
///
/// Handling: Halt execution immediately and alert the user
StreamReadError(PathBuf, io::Error),
/// One or more of the images wasn't correctly encoded
///
/// Handling: Halt execution immediately and ask the user if they're sure the
/// provided file is an image.
ImageFormatError(PathBuf),
/// The server is currently having some difficulties
///
/// Represents a 5XX or 4XX error, as well as any transport error that doesn't seem
/// like it could stem from a network issue.
///
/// Handling: Halt execution and alert the user that the server isn't working at the
/// minute, and ask them to try a different server or try again.
ServerError(String),
/// Couldn't connect to the server
///
/// Indicates that there was some network error which prevented the client from
/// reaching the server.
///
/// Handling: Halt execution and ask the user to check that their computer is
/// connected to the internet, and is not having any DNS issues.
ConnectionError(String),
/// The server URL provided by the user was invalid
///
/// Handling: Halt execution and alert the user that the server url they provided was
/// invalid, including a couple examples
BadServerParameter,
}
fn trim_url<'a>(base_url: &str, url: &'a str) -> Option<&'a str> {
if url.starts_with(base_url) {
let shortened = url
.trim()
.trim_start_matches(base_url)
.trim_matches('/')
.trim_end_matches(".bin");
if shortened.len() > 50 {
None
} else {
Some(shortened)
}
} else {
None
}
}
fn main() {
let args: parse::Args = argh::from_env();
let (files, errors): (Vec<_>, Vec<_>) = args.images.iter()
.map(Path::new)
.map(|path| File::open(path)
.map(|file| (path, file))
.map_err(|e| match e.kind() {
ErrorKind::NotFound => AviaryError::FileDNE(path.to_owned()),
ErrorKind::PermissionDenied => AviaryError::ReadPermissionDenied(path.to_owned()),
_ => panic!(
"Received an error kind that should be impossible for {}: {:?}",
path.display(),
e
)
}
))
.partition_result();
if !errors.is_empty() {
println!("[FATAL] The was a problem accessing some of the files you provided!");
let (nonexistant, noread): (Vec<_>, Vec<_>) = errors.iter()
.partition_map(|e| match e {
AviaryError::FileDNE(path) => Either::Left(path),
AviaryError::ReadPermissionDenied(path) => Either::Right(path),
other => panic!("This error should not be possible! {other:?}")
});
if !nonexistant.is_empty() {
println!("\nWe didn't see any files at the following locations:");
nonexistant.iter().for_each(|path| println!("{}", path.display()));
}
if !noread.is_empty() {
println!("\nWe found these files, but didn't have permission to open them:");
noread.iter().for_each(|path| println!("{}", path.display()));
}
} else {
let agent = upload::get_agent();
let full_server = if args.server.starts_with("http") {
Cow::Borrowed(&args.server)
} else {
Cow::Owned(format!("https://{}", args.server))
};
let upload_records = files.into_iter()
.map(|(path, mut file)|
(|| {
let mut buff = Vec::with_capacity(file.metadata()?.len() as usize);
file.read_to_end(&mut buff)?;
Ok((path, buff))
})().map_err(|e| AviaryError::StreamReadError(path.to_owned(), e))
)
.map(|r| r.and_then(|(path, raw_dat)| {
let (thumbnail, blurhash) = thumbnailing::thumbnail(&raw_dat)
.map_err(|_| AviaryError::ImageFormatError(path.to_owned()))?;
Ok((raw_dat, thumbnail, blurhash))
}))
.map_ok(|(raw_dat, thumbnail, blurhash)| {
let key = crypto::make_key();
(
key,
crypto::encrypt(&key, &raw_dat),
crypto::encrypt(&key, &thumbnail),
blurhash
)
})
.map(|r| r.and_then(|(key, full_img, thumb, blurhash)|
upload::put_data(&agent, &*full_server, &thumb)
.and_then(|thumb_url|
upload::put_data(&agent, &*full_server, &full_img)
.map(|full_url| (key, full_url, thumb_url, blurhash)))
.map_err(|err| match err {
ureq::Error::Status(code, msg) => AviaryError::ServerError(
format!("Error code {} received from server: {}", code,
msg.into_string().unwrap_or(String::new()))),
ureq::Error::Transport(transport) => match transport.kind() {
ureq::ErrorKind::InvalidUrl =>
AviaryError::BadServerParameter,
ureq::ErrorKind::Dns =>
AviaryError::ConnectionError(
format!("DNS issue: {}", transport.message().unwrap_or(""))),
ureq::ErrorKind::Io =>
AviaryError::ConnectionError(
format!("IO issue: {}", transport.message().unwrap_or(""))),
ureq::ErrorKind::ConnectionFailed =>
AviaryError::ConnectionError(
format!("Connection issue: {}", transport.message().unwrap_or(""))),
ureq::ErrorKind::TooManyRedirects =>
AviaryError::ServerError("Too many redirects".to_owned()),
ureq::ErrorKind::BadHeader =>
AviaryError::ServerError("Invalid header from server".to_owned()),
ureq::ErrorKind::BadStatus =>
AviaryError::ServerError("Invalid status from server".to_owned()),
unk => panic!("Unexpected transport error kind {unk}:\n{transport}")
},
})
))
.map(|r| r.and_then(|(key, full_url, thumb_url, blurhash)| {
let full_trimmed = trim_url(&*full_server, &full_url);
let thmb_trimmed = trim_url(&*full_server, &thumb_url);
if let (Some(full_url), Some(thmb_url)) = (full_trimmed, thmb_trimmed) {
Ok((key, full_url.to_owned(), thmb_url.to_owned(), blurhash))
} else {
Err(AviaryError::ServerError(format!("Received bad response from server: {}", full_url)))
}
}))
.collect::<Result<Vec<_>, _>>()
.unwrap();
upload_records.into_iter()
.for_each(|(key, full_url, thumb_url, blurhash)|
println!("{}, {}, {}, {}", base64::encode(key), full_url, thumb_url, blurhash))
}
}

17
src/parse.rs Normal file
View file

@ -0,0 +1,17 @@
use argh_derive::FromArgs;
#[derive(FromArgs)]
/// Create Aviary galleries
pub struct Args {
/// the title of the gallery
#[argh(option, short = 't')]
pub title: Option<String>,
/// the null pointer server to use
#[argh(option, short = 's', default = "\"envs.sh\".to_owned()")]
pub server: String,
/// A list of image files to post
#[argh(positional)]
pub images: Vec<String>,
}

25
src/thumbnailing.rs Normal file
View file

@ -0,0 +1,25 @@
use std::io::Cursor;
use image::{io::Reader, DynamicImage, ImageResult};
use webp::{Encoder, WebPMemory};
pub fn thumbnail(bytes: &[u8]) -> ImageResult<(WebPMemory, String)> {
let original_image = Reader::new(Cursor::new(bytes))
.with_guessed_format().expect("IO errors impossible with Cursor")
.decode()?;
let new_dimm = u32::min(original_image.height(), original_image.width());
let crop_x = (original_image.width() - new_dimm) / 2;
let crop_y = (original_image.height() - new_dimm) / 2;
let cropped = original_image.crop_imm(crop_x, crop_y, new_dimm, new_dimm);
let scaled = if new_dimm < 400 {
cropped
} else {
original_image.thumbnail_exact(400, 400)
}.into_rgba8();
let blurhash = blurhash::encode(4, 4, 400, 400, scaled.as_raw());
Ok((
Encoder::from_image(&DynamicImage::ImageRgba8(scaled))
.expect("Unexpected difficulty interpretting thumbnail")
.encode(50.0),
blurhash
))
}

20
src/upload.rs Normal file
View file

@ -0,0 +1,20 @@
use std::io::Read;
use ureq::{Agent, AgentBuilder};
const DATA_HEADER: &'static [u8] = b"--FuckLiterallyAllCops\r\nContent-Disposition: form-data; name=\"file\"; filename=\"pigeon.bin\"\r\nContent-Type: application/octet-stream\r\n\r\n";
const DATA_FOOTER: &'static [u8] = b"\x00\r\n--FuckLiterallyAllCops--\r\n";
pub fn get_agent() -> Agent {
AgentBuilder::new()
.max_idle_connections(3)
.redirects(2)
.user_agent("aviary-cli/0.0.1")
.build()
}
pub fn put_data(agent: &Agent, server: &str, data: &[u8]) -> Result<String, ureq::Error> {
Ok(agent.post(server)
.set("Content-Type", "multipart/form-data; boundary=FuckLiterallyAllCops")
.send(DATA_HEADER.chain(data).chain(DATA_FOOTER))?.into_string()?)
}