forked from natto1784/yamaf
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
fa60934d60
|
|||
|
6fe202b1d1
|
|||
|
0566e6709c
|
|||
|
1516480216
|
|||
|
63a0268695
|
|||
|
fad5ee8a30
|
234
Cargo.lock
generated
234
Cargo.lock
generated
@@ -2,6 +2,15 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android_system_properties"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atomic-waker"
|
name = "atomic-waker"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
@@ -9,10 +18,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum"
|
name = "autocfg"
|
||||||
version = "0.8.6"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a18ed336352031311f4e0b4dd2ff392d4fbb370777c9d18d7fc9d7359f73871"
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "axum"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum-core",
|
"axum-core",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -68,10 +83,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bumpalo"
|
||||||
version = "1.10.1"
|
version = "3.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.2.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36"
|
||||||
|
dependencies = [
|
||||||
|
"find-msvc-tools",
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@@ -79,6 +110,25 @@ version = "1.0.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
|
||||||
|
dependencies = [
|
||||||
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
|
"num-traits",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.35"
|
version = "0.8.35"
|
||||||
@@ -88,6 +138,12 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "find-msvc-tools"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@@ -215,9 +271,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "1.7.0"
|
version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e"
|
checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-waker",
|
"atomic-waker",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -236,9 +292,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-util"
|
name = "hyper-util"
|
||||||
version = "0.1.17"
|
version = "0.1.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8"
|
checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -250,12 +306,46 @@ dependencies = [
|
|||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone"
|
||||||
|
version = "0.1.64"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
|
||||||
|
dependencies = [
|
||||||
|
"android_system_properties",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"iana-time-zone-haiku",
|
||||||
|
"js-sys",
|
||||||
|
"log",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone-haiku"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.82"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.177"
|
version = "0.2.177"
|
||||||
@@ -333,6 +423,15 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.21.3"
|
version = "1.21.3"
|
||||||
@@ -451,6 +550,12 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.20"
|
version = "1.0.20"
|
||||||
@@ -528,6 +633,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.6"
|
version = "1.4.6"
|
||||||
@@ -567,9 +678,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.109"
|
version = "2.0.110"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2f17c7e013e88258aa9543dcbe81aca68a667a9ac37cd69c9fbc07858bfe0e2f"
|
checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -704,12 +815,110 @@ dependencies = [
|
|||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.105"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"rustversion",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.105"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.105"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.105"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.62.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||||
|
dependencies = [
|
||||||
|
"windows-implement",
|
||||||
|
"windows-interface",
|
||||||
|
"windows-link",
|
||||||
|
"windows-result",
|
||||||
|
"windows-strings",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-implement"
|
||||||
|
version = "0.60.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-interface"
|
||||||
|
version = "0.59.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-link"
|
name = "windows-link"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-result"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-strings"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.60.2"
|
version = "0.60.2"
|
||||||
@@ -804,6 +1013,7 @@ name = "yamaf"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
|
"chrono",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
"rand",
|
"rand",
|
||||||
|
|||||||
@@ -7,8 +7,12 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = { version = "0.8.6", features = ["multipart"] }
|
axum = { version = "0.8.6", features = ["multipart"] }
|
||||||
|
chrono = "*"
|
||||||
futures-util = "0.3.31"
|
futures-util = "0.3.31"
|
||||||
mime_guess= "*"
|
mime_guess= "*"
|
||||||
rand = "*"
|
rand = "*"
|
||||||
tokio = { version = "1.48.0", features = ["full"] }
|
tokio = { version = "1.48.0", features = ["full"] }
|
||||||
tokio-util = { version = "0.7.17", features = ["io"] }
|
tokio-util = { version = "0.7.17", features = ["io"] }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
cleanup = []
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@@ -1,5 +1,5 @@
|
|||||||
Marvel Rivals License Revision 2
|
Marvel Rivals License Revision 2
|
||||||
(c) Author, year
|
(c) Amneesh Singh, 2025
|
||||||
|
|
||||||
Permission to use, copy, distribute, sell, or modify the compiled binaries,
|
Permission to use, copy, distribute, sell, or modify the compiled binaries,
|
||||||
source code, and documentation (the "Software") is granted only to individuals
|
source code, and documentation (the "Software") is granted only to individuals
|
||||||
|
|||||||
3
LISENCE
3
LISENCE
@@ -1,3 +0,0 @@
|
|||||||
Zomato License (v1.0)
|
|
||||||
You may fork, taste, and remix this code — but don’t serve it without credit.
|
|
||||||
All bugs come with complimentary fries 🍟.
|
|
||||||
15
README.org
15
README.org
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
* Yet Another Mid Ahh Filehost
|
* Yet Another Mid Ahh Filehost
|
||||||
|
|
||||||
adasdad
|
|
||||||
- YAMAF is a yet another mid ahh filehost for personal use.
|
- YAMAF is a yet another mid ahh filehost for personal use.
|
||||||
- It is extremely simple and minimal and might break under niche circumstances like uploading many huge files.
|
- It is extremely simple and minimal and might break under niche circumstances like uploading many huge files.
|
||||||
- It uses axum unlike its predecessors[fn:1][fn:2], both of which were written in rust some time ago now.
|
- It uses axum unlike its predecessors[fn:1][fn:2], both of which were written in rust some time ago now.
|
||||||
@@ -19,7 +18,19 @@ adasdad
|
|||||||
| EXTERNAL_HOST | User facing domain name, used to return accessible URLs | ${INTERNAL_HOST} |
|
| EXTERNAL_HOST | User facing domain name, used to return accessible URLs | ${INTERNAL_HOST} |
|
||||||
| EXTERNAL_HAS_TLS | URLs in html have https if set, otherwise http | - |
|
| EXTERNAL_HAS_TLS | URLs in html have https if set, otherwise http | - |
|
||||||
| MAX_FILES | This does not actually limit the number of files, and used to calculate bodysize | 10 |
|
| MAX_FILES | This does not actually limit the number of files, and used to calculate bodysize | 10 |
|
||||||
| MAX_FILESIZE_MB | Determines the max filesize possible, used to return failure and calculate bodysize | 100M |
|
| MAX_FILESIZE_MB | Determines the max filesize possible, used to return failure and calculate bodysize | 100M |
|
||||||
|
| MIN_FILEDAYS | Minimum number of days for file retention | 30 days |
|
||||||
|
| MAX_FILEDAYS | Maximum number of days for file retention | 365 days |
|
||||||
|
|
||||||
|
** Retention
|
||||||
|
|
||||||
|
File retention is as per the following formula
|
||||||
|
|
||||||
|
#+begin_src text
|
||||||
|
retention = min_days + (max_days - min_days) * (1 - file_size / max_size) ^ e
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Cleanup happens everyday when midnight (IST) has passed
|
||||||
|
|
||||||
|
|
||||||
[fn:1] https://git.weirdnatto.in/natto1784/simple-filehost/
|
[fn:1] https://git.weirdnatto.in/natto1784/simple-filehost/
|
||||||
|
|||||||
11
flake.nix
11
flake.nix
@@ -47,17 +47,14 @@
|
|||||||
|
|
||||||
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
|
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
|
||||||
|
|
||||||
yamaf = craneLib.buildPackage (
|
yamaf = pkgs.callPackage ./nix/yamaf.nix {
|
||||||
commonArgs
|
inherit craneLib lib src;
|
||||||
// {
|
};
|
||||||
inherit cargoArtifacts;
|
|
||||||
doCheck = false;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
packages = {
|
packages = {
|
||||||
inherit yamaf;
|
inherit yamaf;
|
||||||
|
yamaf-all = yamaf.override { withCleanup = true; };
|
||||||
default = yamaf;
|
default = yamaf;
|
||||||
image = pkgs.dockerTools.buildImage {
|
image = pkgs.dockerTools.buildImage {
|
||||||
name = "yamaf";
|
name = "yamaf";
|
||||||
|
|||||||
3
lIS2
3
lIS2
@@ -1,3 +0,0 @@
|
|||||||
Zomato License (v1.0)
|
|
||||||
You may fork, taste, and remix this code — but don’t serve it without credit.
|
|
||||||
All bugs come with complimentary fries 🍟.
|
|
||||||
15
nix/yamaf.nix
Normal file
15
nix/yamaf.nix
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
craneLib,
|
||||||
|
lib,
|
||||||
|
src,
|
||||||
|
withCleanup ? false,
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
cargoArtifacts = craneLib.buildDepsOnly { inherit src; };
|
||||||
|
in
|
||||||
|
craneLib.buildPackage {
|
||||||
|
inherit cargoArtifacts src;
|
||||||
|
doCheck = false;
|
||||||
|
|
||||||
|
cargoExtraArgs = lib.optionalString withCleanup "--features cleanup";
|
||||||
|
}
|
||||||
110
src/index.html
110
src/index.html
@@ -1,89 +1,23 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>{{TITLE}}</title>
|
<title>{{TITLE}}</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-family: sans-serif;
|
|
||||||
max-width: 800px;
|
|
||||||
margin: 40px auto;
|
|
||||||
padding: 0 20px;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 1.8rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
display: block;
|
|
||||||
background: #f3f3f3;
|
|
||||||
padding: 0.5rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
margin: 0.75rem 0;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
form {
|
|
||||||
margin-top: 1rem;
|
|
||||||
padding: 1rem;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
border-radius: 6px;
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
margin-top: 1rem;
|
|
||||||
background: #007bff;
|
|
||||||
color: #fff;
|
|
||||||
border: none;
|
|
||||||
padding: 0.6rem 1.2rem;
|
|
||||||
border-radius: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:hover {
|
|
||||||
background: #0056b3;
|
|
||||||
}
|
|
||||||
|
|
||||||
#progress-container {
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-container {
|
|
||||||
position: relative;
|
|
||||||
padding-bottom: 56.25%;
|
|
||||||
height: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-top: 2rem;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-container iframe {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1>{{TITLE}}</h1>
|
<h1>{{TITLE}}</h1>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Use curl to upload:
|
Use curl to upload:
|
||||||
<code>curl -F file=@"[file]" {{USER_URL}}</code>
|
<br>
|
||||||
|
<code>
|
||||||
|
curl -F file=@"[file]" {{USER_URL}}
|
||||||
|
</code>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
If key is enabled then a field "key" will be required.
|
If key is enabled then a field "key" will be required.
|
||||||
<br />
|
<br>
|
||||||
Make sure the key is the first field in the multipart before any files.
|
Make sure the key is the first field in the multipart before any files.
|
||||||
|
<br>
|
||||||
<code>
|
<code>
|
||||||
curl -F "key=[key]" -F file=@"[file]" -F file=@"[file2]" {{USER_URL}}
|
curl -F "key=[key]" -F file=@"[file]" -F file=@"[file2]" {{USER_URL}}
|
||||||
</code>
|
</code>
|
||||||
@@ -91,21 +25,21 @@
|
|||||||
|
|
||||||
<form method="post" enctype="multipart/form-data">
|
<form method="post" enctype="multipart/form-data">
|
||||||
{{KEY_FIELD}}
|
{{KEY_FIELD}}
|
||||||
<input type="file" name="file" multiple />
|
<input type="file" name="file" multiple>
|
||||||
<br />
|
<br>
|
||||||
<button type="submit">Upload</button>
|
<button type="submit">Upload</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div id="progress-container"></div>
|
<!-- CLEANUP_START -->
|
||||||
|
<h4>Cleanup</h4>
|
||||||
|
File retention is as per the following formula
|
||||||
|
<pre><code>
|
||||||
|
max_size = {{MAX_SIZE}} // in megabytes
|
||||||
|
max_days = {{MAX_DAYS}}
|
||||||
|
min_days = {{MIN_DAYS}}
|
||||||
|
retention = min_days + (max_days - min_days) * (1 - file_size / max_size) ^ e
|
||||||
|
</code></pre>
|
||||||
|
Cleanup happens everyday when midnight (IST) has passed
|
||||||
|
<!-- CLEANUP_END -->
|
||||||
|
|
||||||
<div class="video-container">
|
|
||||||
<iframe
|
|
||||||
src="https://www.youtube.com/embed/WjzbSvnQ7SU?autoplay=1&mute=1&loop=1&playlist=WjzbSvnQ7SU"
|
|
||||||
title="Brainrot Video"
|
|
||||||
frameborder="0"
|
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
||||||
allowfullscreen
|
|
||||||
></iframe>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
257
src/main.rs
257
src/main.rs
@@ -6,11 +6,10 @@ use axum::{
|
|||||||
response::{Html, IntoResponse, Response},
|
response::{Html, IntoResponse, Response},
|
||||||
routing::get,
|
routing::get,
|
||||||
};
|
};
|
||||||
|
|
||||||
use rand::{Rng, distr::Alphanumeric};
|
use rand::{Rng, distr::Alphanumeric};
|
||||||
use std::{env, net::SocketAddr, sync::LazyLock};
|
use std::{env, net::SocketAddr, sync::LazyLock};
|
||||||
use std::{env::VarError, path::PathBuf};
|
use std::{env::VarError, path::PathBuf};
|
||||||
use tokio::fs::File;
|
use tokio::fs;
|
||||||
use tokio_util::io::ReaderStream;
|
use tokio_util::io::ReaderStream;
|
||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
@@ -23,12 +22,14 @@ struct Config {
|
|||||||
external_protocol: &'static str,
|
external_protocol: &'static str,
|
||||||
max_filesize: usize,
|
max_filesize: usize,
|
||||||
max_bodysize: usize,
|
max_bodysize: usize,
|
||||||
|
min_filedays: usize,
|
||||||
|
max_filedays: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
static CONFIG: LazyLock<Config> = LazyLock::new(|| {
|
static CONFIG: LazyLock<Config> = LazyLock::new(|| {
|
||||||
let root_dir = env::var("ROOT_DIR").unwrap_or_else(|_| "/var/files".to_string());
|
let root_dir = env::var("ROOT_DIR").unwrap_or_else(|_| "/var/files".to_string());
|
||||||
let key = env::var("KEY");
|
let key = env::var("KEY");
|
||||||
let title = env::var("TITLE").unwrap_or_else(|_| "Simpler Filehost".to_string());
|
let title = env::var("TITLE").unwrap_or_else(|_| "Yet Another Mid Ahh Filehost".to_string());
|
||||||
|
|
||||||
let internal_host = env::var("INTERNAL_HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
|
let internal_host = env::var("INTERNAL_HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
|
||||||
let internal_port = env::var("INTERNAL_PORT")
|
let internal_port = env::var("INTERNAL_PORT")
|
||||||
@@ -54,6 +55,18 @@ static CONFIG: LazyLock<Config> = LazyLock::new(|| {
|
|||||||
<< 20;
|
<< 20;
|
||||||
let max_bodysize = max_files * max_filesize * 2;
|
let max_bodysize = max_files * max_filesize * 2;
|
||||||
|
|
||||||
|
let min_filedays = env::var("MIN_FILEDAYS")
|
||||||
|
.ok()
|
||||||
|
.and_then(|x| x.parse().ok())
|
||||||
|
.unwrap_or(30);
|
||||||
|
|
||||||
|
let max_filedays = env::var("MAX_FILEDAYS")
|
||||||
|
.ok()
|
||||||
|
.and_then(|x| x.parse().ok())
|
||||||
|
.unwrap_or(365);
|
||||||
|
|
||||||
|
assert!(max_filedays >= min_filedays);
|
||||||
|
|
||||||
Config {
|
Config {
|
||||||
root_dir,
|
root_dir,
|
||||||
key,
|
key,
|
||||||
@@ -64,6 +77,8 @@ static CONFIG: LazyLock<Config> = LazyLock::new(|| {
|
|||||||
external_protocol,
|
external_protocol,
|
||||||
max_filesize,
|
max_filesize,
|
||||||
max_bodysize,
|
max_bodysize,
|
||||||
|
min_filedays,
|
||||||
|
max_filedays,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -86,6 +101,35 @@ async fn main() {
|
|||||||
addr, CONFIG.root_dir
|
addr, CONFIG.root_dir
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* cleanup cronjob */
|
||||||
|
#[cfg(feature = "cleanup")]
|
||||||
|
tokio::spawn(async move {
|
||||||
|
use chrono::{Local, NaiveDate};
|
||||||
|
|
||||||
|
let mut last_cleanup_day: NaiveDate = Local::now().date_naive();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
use tokio::time::{Duration, sleep};
|
||||||
|
|
||||||
|
/* every 30 minutes */
|
||||||
|
sleep(Duration::from_secs(30 * 60)).await;
|
||||||
|
|
||||||
|
let now = Local::now();
|
||||||
|
let today = now.date_naive();
|
||||||
|
|
||||||
|
/* if the date changed, midnight has passed */
|
||||||
|
if today > last_cleanup_day {
|
||||||
|
println!("attempting cleanup at {}", now.to_string());
|
||||||
|
if let Err(e) = cleanup_directory().await {
|
||||||
|
eprintln!("cleanup failed: {}", e);
|
||||||
|
} else {
|
||||||
|
println!("cleanup succeeded!");
|
||||||
|
last_cleanup_day = today;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
axum::serve(listener, app).await.unwrap();
|
axum::serve(listener, app).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +152,19 @@ static INDEX_HTML: LazyLock<String> = LazyLock::new(|| {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if cfg!(feature = "cleanup") {
|
||||||
|
html = html
|
||||||
|
.replace("{{MAX_SIZE}}", &(CONFIG.max_filesize >> 20).to_string())
|
||||||
|
.replace("{{MAX_DAYS}}", &CONFIG.max_filedays.to_string())
|
||||||
|
.replace("{{MIN_DAYS}}", &CONFIG.min_filedays.to_string());
|
||||||
|
} else {
|
||||||
|
if let Some(start) = html.find("<!-- CLEANUP_START -->") {
|
||||||
|
if let Some(end) = html.find("<!-- CLEANUP_END -->") {
|
||||||
|
html.replace_range(start..end + "<!-- CLEANUP_END -->".len(), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
html
|
html
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -153,10 +210,7 @@ fn clean_filename(filename: &str) -> String {
|
|||||||
let mut prev_dash = false;
|
let mut prev_dash = false;
|
||||||
|
|
||||||
for c in filename.to_lowercase().chars() {
|
for c in filename.to_lowercase().chars() {
|
||||||
if c.is_ascii_alphanumeric() {
|
if c.is_ascii_alphanumeric() || c == '.' {
|
||||||
slug.push(c);
|
|
||||||
prev_dash = false;
|
|
||||||
} else if c == '.' {
|
|
||||||
slug.push(c);
|
slug.push(c);
|
||||||
prev_dash = false;
|
prev_dash = false;
|
||||||
} else if !prev_dash {
|
} else if !prev_dash {
|
||||||
@@ -168,81 +222,94 @@ fn clean_filename(filename: &str) -> String {
|
|||||||
slug.trim_matches('-').to_string()
|
slug.trim_matches('-').to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn upload(mut payload: Multipart) -> Result<impl IntoResponse, YamafError> {
|
async fn upload(
|
||||||
|
headers: HeaderMap,
|
||||||
|
mut payload: Multipart,
|
||||||
|
) -> Result<impl IntoResponse, YamafError> {
|
||||||
let mut responses = Vec::new();
|
let mut responses = Vec::new();
|
||||||
let mut found_key = false;
|
|
||||||
|
let wants_html = headers
|
||||||
|
.get("accept")
|
||||||
|
.and_then(|h| h.to_str().ok())
|
||||||
|
.map(|a| a.contains("text/html"))
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if let Ok(ref key) = CONFIG.key {
|
||||||
|
if let Some(field) = payload.next_field().await.unwrap() {
|
||||||
|
if field.name() == Some("key") {
|
||||||
|
let bytes = field
|
||||||
|
.bytes()
|
||||||
|
.await
|
||||||
|
.map_err(|e| YamafError::BadRequest(format!("Error reading key: {e}")))?;
|
||||||
|
|
||||||
|
let s = String::from_utf8(bytes.to_vec())
|
||||||
|
.map_err(|_| YamafError::InternalError("Invalid key format".into()))?;
|
||||||
|
|
||||||
|
if s != *key {
|
||||||
|
return Err(YamafError::BadRequest("Wrong key".into()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(YamafError::BadRequest("Missing key".into()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(YamafError::BadRequest("Missing key".into()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while let Some(mut field) = payload.next_field().await.unwrap() {
|
while let Some(mut field) = payload.next_field().await.unwrap() {
|
||||||
match field.name() {
|
if field.name() == Some("file") {
|
||||||
Some("key") => {
|
let filename = field
|
||||||
if let Ok(ref key) = CONFIG.key {
|
.file_name()
|
||||||
let bytes = field
|
.map_or(format!("{}-upload", random(10)), |filename| {
|
||||||
.bytes()
|
format!("{}-{}", random(4), clean_filename(filename))
|
||||||
.await
|
});
|
||||||
.map_err(|e| YamafError::BadRequest(format!("Error reading key: {e}")))?;
|
|
||||||
|
|
||||||
let s = String::from_utf8(bytes.to_vec())
|
let save_path = std::path::Path::new(&CONFIG.root_dir).join(&filename);
|
||||||
.map_err(|_| YamafError::InternalError("Invalid key format".into()))?;
|
|
||||||
|
|
||||||
if s != *key {
|
let mut file = fs::File::create(&save_path)
|
||||||
return Err(YamafError::BadRequest("Wrong key".into()));
|
.await
|
||||||
}
|
.map_err(|_| YamafError::InternalError("Internal i/o error".into()))?;
|
||||||
|
|
||||||
found_key = true;
|
let mut written: usize = 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some("file") => {
|
while let Some(chunk) = field
|
||||||
if CONFIG.key.is_ok() && found_key == false {
|
.chunk()
|
||||||
return Err(YamafError::BadRequest("Missing key".into()));
|
.await
|
||||||
|
.map_err(|err| YamafError::InternalError(err.to_string()))?
|
||||||
|
{
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
|
written = written
|
||||||
|
.checked_add(chunk.len())
|
||||||
|
.ok_or_else(|| YamafError::BadRequest("File too large".into()))?;
|
||||||
|
|
||||||
|
if written > CONFIG.max_filesize {
|
||||||
|
_ = fs::remove_file(&save_path).await;
|
||||||
|
|
||||||
|
return Err(YamafError::FileTooBig(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
let filename = field
|
file.write_all(&chunk)
|
||||||
.file_name()
|
|
||||||
.map_or(format!("{}-upload", random(10)), |filename| {
|
|
||||||
format!("{}-{}", random(4), clean_filename(filename))
|
|
||||||
});
|
|
||||||
|
|
||||||
let save_path = std::path::Path::new(&CONFIG.root_dir).join(&filename);
|
|
||||||
|
|
||||||
let mut file = File::create(&save_path)
|
|
||||||
.await
|
.await
|
||||||
.map_err(|_| YamafError::InternalError("Internal i/o error".into()))?;
|
.map_err(|_| YamafError::InternalError("Internal i/o error".into()))?;
|
||||||
|
|
||||||
let mut written: usize = 0;
|
|
||||||
|
|
||||||
while let Some(chunk) = field
|
|
||||||
.chunk()
|
|
||||||
.await
|
|
||||||
.map_err(|err| YamafError::InternalError(err.to_string()))?
|
|
||||||
{
|
|
||||||
use tokio::io::AsyncWriteExt;
|
|
||||||
|
|
||||||
written = written
|
|
||||||
.checked_add(chunk.len())
|
|
||||||
.ok_or_else(|| YamafError::BadRequest("File too large".into()))?;
|
|
||||||
|
|
||||||
if written > CONFIG.max_filesize {
|
|
||||||
_ = tokio::fs::remove_file(&save_path).await;
|
|
||||||
|
|
||||||
return Err(YamafError::FileTooBig(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
file.write_all(&chunk)
|
|
||||||
.await
|
|
||||||
.map_err(|_| YamafError::InternalError("Internal i/o error".into()))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
responses.push(format!(
|
|
||||||
r#"<a href="{proto}://{host}/{file}">{proto}://{host}/{file}</a> (size ~ {size:.2}k)"#,
|
|
||||||
proto = CONFIG.external_protocol,
|
|
||||||
host = CONFIG.external_host,
|
|
||||||
file = filename,
|
|
||||||
size = written as f64 / 1024 as f64
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
None | Some(_) => {}
|
let url = format!(
|
||||||
|
"{proto}://{host}/{file}",
|
||||||
|
proto = CONFIG.external_protocol,
|
||||||
|
host = CONFIG.external_host,
|
||||||
|
file = filename,
|
||||||
|
);
|
||||||
|
|
||||||
|
if wants_html {
|
||||||
|
responses.push(format!(
|
||||||
|
r#"<a href="{url}">{url}</a> (size ~ {size:.2}k)"#,
|
||||||
|
url = url,
|
||||||
|
size = written as f64 / 1024.0,
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
responses.push(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,20 +317,24 @@ async fn upload(mut payload: Multipart) -> Result<impl IntoResponse, YamafError>
|
|||||||
return Err(YamafError::BadRequest("No files uploaded".into()));
|
return Err(YamafError::BadRequest("No files uploaded".into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Html(format!(
|
if wants_html {
|
||||||
"Here are your file(s):<br>{}",
|
Ok(Html(format!(
|
||||||
responses.join("<br>")
|
"Here are your file(s):<br>{}",
|
||||||
))
|
responses.join("<br>")
|
||||||
.into_response())
|
))
|
||||||
|
.into_response())
|
||||||
|
} else {
|
||||||
|
Ok(responses.join("\n").into_response())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn serve_file(Path(filename): Path<String>) -> Result<impl IntoResponse, YamafError> {
|
async fn serve_file(Path(filename): Path<String>) -> Result<impl IntoResponse, YamafError> {
|
||||||
let path = PathBuf::from(&CONFIG.root_dir).join(&filename);
|
let path = PathBuf::from(&CONFIG.root_dir).join(&filename);
|
||||||
|
|
||||||
let metadata = tokio::fs::metadata(&path)
|
let metadata = fs::metadata(&path)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| YamafError::FileNotFound)?;
|
.map_err(|_| YamafError::FileNotFound)?;
|
||||||
let file = File::open(&path)
|
let file = fs::File::open(&path)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| YamafError::FileNotFound)?;
|
.map_err(|_| YamafError::FileNotFound)?;
|
||||||
let mime = mime_guess::from_path(&path).first_or_octet_stream();
|
let mime = mime_guess::from_path(&path).first_or_octet_stream();
|
||||||
@@ -289,3 +360,37 @@ async fn serve_file(Path(filename): Path<String>) -> Result<impl IntoResponse, Y
|
|||||||
|
|
||||||
Ok((StatusCode::OK, headers, body).into_response())
|
Ok((StatusCode::OK, headers, body).into_response())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "cleanup")]
|
||||||
|
async fn cleanup_directory() -> Result<(), std::io::Error> {
|
||||||
|
let dir = std::path::Path::new(&CONFIG.root_dir);
|
||||||
|
let mut entries = fs::read_dir(dir).await?;
|
||||||
|
|
||||||
|
while let Some(entry) = entries.next_entry().await? {
|
||||||
|
use std::os::unix::fs::MetadataExt;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
let path = entry.path();
|
||||||
|
let meta = entry.metadata().await?;
|
||||||
|
let modified = meta.modified().unwrap_or(SystemTime::UNIX_EPOCH);
|
||||||
|
let age = SystemTime::now()
|
||||||
|
.duration_since(modified)
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
/* min_days + (max_days - min_days) * (1 - size/max_size)^e */
|
||||||
|
let retention = (CONFIG.min_filedays as f64
|
||||||
|
+ (CONFIG.max_filedays - CONFIG.min_filedays) as f64
|
||||||
|
* (1.0 - (meta.size() as f64 / CONFIG.max_filesize as f64))
|
||||||
|
.powf(std::f64::consts::E))
|
||||||
|
* 24.0
|
||||||
|
* 60.0
|
||||||
|
* 60.0;
|
||||||
|
|
||||||
|
if meta.is_file() && age.as_secs_f64() > retention {
|
||||||
|
fs::remove_file(&path).await?;
|
||||||
|
println!("Deleted {:?}", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user