prototype
This commit is contained in:
parent
7d5e336868
commit
b8c05c3b26
766
Cargo.lock
generated
766
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 = "askama"
|
name = "askama"
|
||||||
version = "0.16.0"
|
version = "0.16.0"
|
||||||
@ -52,7 +61,71 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
"winnow",
|
"winnow 1.0.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic-waker"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "axum"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90"
|
||||||
|
dependencies = [
|
||||||
|
"axum-core",
|
||||||
|
"bytes",
|
||||||
|
"form_urlencoded",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper",
|
||||||
|
"hyper-util",
|
||||||
|
"itoa",
|
||||||
|
"matchit",
|
||||||
|
"memchr",
|
||||||
|
"mime",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project-lite",
|
||||||
|
"serde_core",
|
||||||
|
"serde_json",
|
||||||
|
"serde_path_to_error",
|
||||||
|
"serde_urlencoded",
|
||||||
|
"sync_wrapper",
|
||||||
|
"tokio",
|
||||||
|
"tower",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "axum-core"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"http-body-util",
|
||||||
|
"mime",
|
||||||
|
"pin-project-lite",
|
||||||
|
"sync_wrapper",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -64,30 +137,367 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.20.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "1.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.2.63"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
|
||||||
|
dependencies = [
|
||||||
|
"find-msvc-tools",
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
|
||||||
|
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]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "find-msvc-tools"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "form_urlencoded"
|
||||||
|
version = "1.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
|
||||||
|
dependencies = [
|
||||||
|
"percent-encoding",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-channel"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"pin-project-lite",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.17.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http"
|
||||||
|
version = "1.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"itoa",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http-body"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"http",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http-body-util"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httparse"
|
||||||
|
version = "1.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "httpdate"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper"
|
||||||
|
version = "1.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498"
|
||||||
|
dependencies = [
|
||||||
|
"atomic-waker",
|
||||||
|
"bytes",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"httparse",
|
||||||
|
"httpdate",
|
||||||
|
"itoa",
|
||||||
|
"pin-project-lite",
|
||||||
|
"smallvec",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper-util"
|
||||||
|
version = "0.1.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"hyper",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone"
|
||||||
|
version = "0.1.65"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
|
||||||
|
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]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.99"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"futures-util",
|
||||||
|
"once_cell",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.186"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matchit"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.8.1"
|
version = "2.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
|
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime"
|
||||||
|
version = "0.3.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.21.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.2"
|
version = "2.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.106"
|
version = "1.0.106"
|
||||||
@ -106,12 +516,39 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
version = "2.1.2"
|
version = "2.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
|
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.228"
|
version = "1.0.228"
|
||||||
@ -119,6 +556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_core",
|
"serde_core",
|
||||||
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -154,6 +592,76 @@ dependencies = [
|
|||||||
"zmij",
|
"zmij",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_path_to_error"
|
||||||
|
version = "0.1.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"serde",
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_urlencoded"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
|
||||||
|
dependencies = [
|
||||||
|
"form_urlencoded",
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
|
||||||
|
dependencies = [
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.15.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "socket2"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.117"
|
version = "2.0.117"
|
||||||
@ -165,11 +673,139 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sync_wrapper"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thek4n-ru"
|
name = "thek4n-ru"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama",
|
"askama",
|
||||||
|
"axum",
|
||||||
|
"chrono",
|
||||||
|
"serde",
|
||||||
|
"tokio",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio"
|
||||||
|
version = "1.52.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"parking_lot",
|
||||||
|
"pin-project-lite",
|
||||||
|
"signal-hook-registry",
|
||||||
|
"socket2",
|
||||||
|
"tokio-macros",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "2.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.8.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.22.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_write",
|
||||||
|
"winnow 0.7.15",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_write"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"pin-project-lite",
|
||||||
|
"sync_wrapper",
|
||||||
|
"tokio",
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-layer"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-service"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing"
|
||||||
|
version = "0.1.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-core"
|
||||||
|
version = "0.1.36"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -178,6 +814,134 @@ version = "1.0.24"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.1+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.122"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"rustversion",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.122"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.122"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.122"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437"
|
||||||
|
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]]
|
||||||
|
name = "windows-link"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
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]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.61.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.7.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
|
|||||||
@ -6,3 +6,8 @@ authors = ["Vladislav Kan <thek4n@yandex.ru>"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
askama = "0.16.0"
|
askama = "0.16.0"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
toml = "0.8"
|
||||||
|
axum = "0.8"
|
||||||
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
chrono = "0.4"
|
||||||
|
|||||||
12
TODO.md
Normal file
12
TODO.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# ToDo list
|
||||||
|
* [ ] Сделать в embed шаблоны
|
||||||
|
* [ ] Сделать автоматическую локализацию по ip или заголовкам http `Accept-Language`
|
||||||
|
* [X] Сделать локализацию по параметру `/?lang=en`
|
||||||
|
* [X] Сделать авто выбор верстки в зависимости от User-Agent
|
||||||
|
* [ ] Сделать стили и засунуть их в embed (с уникальным хешем в имени)
|
||||||
|
* [ ] Сделать скрипты и засунуть их в embed (с уникальным хешем в имени)
|
||||||
|
* [ ] Отрефачить
|
||||||
|
* [ ] Сделать определение хоста по которому был запрос и засунуть его в
|
||||||
|
аргумент `build_html_template()`
|
||||||
|
* [x] Сделать текущий год на клиенте или сервере (решить) (на сервере
|
||||||
|
предпочтительно, чтобы им нельзя было манипулировать на клиенте)
|
||||||
@ -1,9 +1,11 @@
|
|||||||
[page]
|
[page]
|
||||||
title = "Hi, I'm Vlad"
|
title.en = "Hi, I'm Vlad"
|
||||||
|
title.ru = "Владислав Кан"
|
||||||
meta_title = "thek4n"
|
meta_title = "thek4n"
|
||||||
meta_description = "thek4n - developer"
|
meta_description = "thek4n - developer"
|
||||||
description = "Developer"
|
description.en = "Developer"
|
||||||
copyright_author = "thek4n"
|
description.ru = "Разработчик"
|
||||||
|
copyright_author = "Vladislav Kan <thek4n@yandex.ru>"
|
||||||
|
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
@ -16,7 +18,7 @@ title = "english"
|
|||||||
|
|
||||||
[[languages]]
|
[[languages]]
|
||||||
key = "ru"
|
key = "ru"
|
||||||
title = "russian"
|
title = "русский"
|
||||||
|
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
@ -26,11 +28,11 @@ title = "russian"
|
|||||||
title.en = "About Me"
|
title.en = "About Me"
|
||||||
title.ru = "Обо Мне"
|
title.ru = "Обо Мне"
|
||||||
text.en = '''
|
text.en = '''
|
||||||
|
About me text...
|
||||||
'''
|
'''
|
||||||
|
|
||||||
text.ru = '''
|
text.ru = '''
|
||||||
|
Обо мне текст...
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
@ -55,9 +57,57 @@ copied_title.en = "Copied!"
|
|||||||
copied_title.ru = "Скопировано!"
|
copied_title.ru = "Скопировано!"
|
||||||
|
|
||||||
value = '''
|
value = '''
|
||||||
asdfasdf
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
asdfasdf
|
|
||||||
asdfasdf
|
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
|
||||||
|
=h906
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
440
src/main.rs
440
src/main.rs
@ -1,5 +1,89 @@
|
|||||||
use askama::Template;
|
use askama::Template;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
|
use axum::{
|
||||||
|
http::header::{USER_AGENT, ACCEPT},
|
||||||
|
response::{Html, IntoResponse},
|
||||||
|
routing::get,
|
||||||
|
extract::Query,
|
||||||
|
Router,
|
||||||
|
http::HeaderMap,
|
||||||
|
};
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use chrono::Datelike;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
struct Config {
|
||||||
|
page: PageConfig,
|
||||||
|
languages: Vec<LanguageConfig>,
|
||||||
|
projects: Option<Vec<ProjectConfig>>,
|
||||||
|
contacts: Option<Vec<ContactConfig>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
struct PageConfig {
|
||||||
|
title: HashMap<String, String>, // теперь HashMap
|
||||||
|
meta_title: String,
|
||||||
|
meta_description: String,
|
||||||
|
description: HashMap<String, String>, // теперь HashMap
|
||||||
|
copyright_author: String,
|
||||||
|
aboutme: Option<AboutMeConfig>,
|
||||||
|
gpg: Option<GPGConfig>,
|
||||||
|
projects: Option<ProjectsSectionConfig>,
|
||||||
|
contacts: Option<ContactsSectionConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
struct AboutMeConfig {
|
||||||
|
title: HashMap<String, String>,
|
||||||
|
text: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
struct GPGConfig {
|
||||||
|
title: HashMap<String, String>,
|
||||||
|
url: String,
|
||||||
|
url_title: String,
|
||||||
|
showkey_title: HashMap<String, String>,
|
||||||
|
availat_title: HashMap<String, String>,
|
||||||
|
copy_title: HashMap<String, String>,
|
||||||
|
value: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
struct ProjectsSectionConfig {
|
||||||
|
title: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
struct ContactsSectionConfig {
|
||||||
|
title: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
struct ProjectConfig {
|
||||||
|
title: String,
|
||||||
|
url: String,
|
||||||
|
source_url: String,
|
||||||
|
source_url_title: String,
|
||||||
|
description: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
struct ContactConfig {
|
||||||
|
site_name: HashMap<String, String>,
|
||||||
|
title: String,
|
||||||
|
url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
struct LanguageConfig {
|
||||||
|
key: String,
|
||||||
|
title: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Template structures matching the HTML
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "html_index.jinja2")]
|
#[template(path = "html_index.jinja2")]
|
||||||
struct HtmlPageTemplate<'a> {
|
struct HtmlPageTemplate<'a> {
|
||||||
@ -23,25 +107,26 @@ struct TextPageTemplate<'a> {
|
|||||||
description: &'a str,
|
description: &'a str,
|
||||||
copyright_author: &'a str,
|
copyright_author: &'a str,
|
||||||
base_url: &'a str,
|
base_url: &'a str,
|
||||||
meta: PageMeta<'a>,
|
|
||||||
year: &'a str,
|
year: &'a str,
|
||||||
aboutme_section: AboutMeSection<'a>,
|
aboutme_section: AboutMeSection<'a>,
|
||||||
gpg_section: GPGSection<'a>,
|
gpg_section: GPGSection<'a>,
|
||||||
contacts_section: ContactsSection<'a>,
|
contacts_section: ContactsSection<'a>,
|
||||||
projects_section: ProjectsSection<'a>,
|
projects_section: ProjectsSection<'a>,
|
||||||
languages: Vec<Language<'a>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
struct PageMeta<'a> {
|
struct PageMeta<'a> {
|
||||||
title: &'a str,
|
title: &'a str,
|
||||||
description: &'a str,
|
description: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
struct AboutMeSection<'a> {
|
struct AboutMeSection<'a> {
|
||||||
title: &'a str,
|
title: &'a str,
|
||||||
text: &'a str,
|
text: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
struct GPGSection<'a> {
|
struct GPGSection<'a> {
|
||||||
title: &'a str,
|
title: &'a str,
|
||||||
availat_title: &'a str,
|
availat_title: &'a str,
|
||||||
@ -52,22 +137,26 @@ struct GPGSection<'a> {
|
|||||||
value: &'a str,
|
value: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct ContactsSection<'a> {
|
struct ContactsSection<'a> {
|
||||||
title: &'a str,
|
title: &'a str,
|
||||||
contacts: Vec<Contact<'a>>,
|
contacts: Vec<Contact<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct Contact<'a> {
|
struct Contact<'a> {
|
||||||
site_name: &'a str,
|
site_name: &'a str,
|
||||||
url: &'a str,
|
url: &'a str,
|
||||||
title: &'a str,
|
title: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct ProjectsSection<'a> {
|
struct ProjectsSection<'a> {
|
||||||
title: &'a str,
|
title: &'a str,
|
||||||
projects: Vec<Project<'a>>,
|
projects: Vec<Project<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct Project<'a> {
|
struct Project<'a> {
|
||||||
title: &'a str,
|
title: &'a str,
|
||||||
url: &'a str,
|
url: &'a str,
|
||||||
@ -76,76 +165,291 @@ struct Project<'a> {
|
|||||||
description: &'a str,
|
description: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct Language<'a> {
|
struct Language<'a> {
|
||||||
key: &'a str,
|
key: &'a str,
|
||||||
current: bool,
|
current: bool,
|
||||||
value: &'a str,
|
value: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn load_config(path: &str) -> Result<Config, Box<dyn std::error::Error>> {
|
||||||
let meta = PageMeta{
|
let contents = fs::read_to_string(path)?;
|
||||||
title: "thek4n",
|
let config: Config = toml::from_str(&contents)?;
|
||||||
description: "thek4n - developer",
|
Ok(config)
|
||||||
};
|
}
|
||||||
|
|
||||||
let aboutme_section = AboutMeSection{
|
fn build_aboutme_section<'a>(config: &'a Config, lang_key: &'a str) -> AboutMeSection<'a> {
|
||||||
title: "About Me",
|
AboutMeSection {
|
||||||
text: "About me text",
|
title: config
|
||||||
};
|
.page
|
||||||
|
.aboutme
|
||||||
let gpg_section = GPGSection{
|
.as_ref()
|
||||||
title: "GPG Key",
|
.and_then(|a| a.title.get(lang_key))
|
||||||
availat_title: "Available at",
|
.map(|s| s.as_str())
|
||||||
url: "/gpgkey.txt",
|
.unwrap_or(""),
|
||||||
url_title: "thek4n.ru/gpgkey.txt",
|
text: config
|
||||||
showkey_title: "Show key",
|
.page
|
||||||
copy_title: "Copy",
|
.aboutme
|
||||||
value: "key....",
|
.as_ref()
|
||||||
};
|
.and_then(|a| a.text.get(lang_key))
|
||||||
|
.map(|s| s.as_str())
|
||||||
let contacts = vec![Contact{
|
.unwrap_or(""),
|
||||||
site_name: "Telegram",
|
}
|
||||||
url: "https://t.me/thek4n",
|
}
|
||||||
title: "@thek4n",
|
|
||||||
}];
|
fn build_gpg_section<'a>(config: &'a Config, lang_key: &'a str) -> GPGSection<'a> {
|
||||||
|
let gpg_config = config.page.gpg.as_ref().unwrap();
|
||||||
let contacts_section = ContactsSection{
|
GPGSection {
|
||||||
title: "Contacts",
|
title: gpg_config.title.get(lang_key).map(|s| s.as_str()).unwrap_or(""),
|
||||||
contacts,
|
availat_title: gpg_config
|
||||||
};
|
.availat_title
|
||||||
|
.get(lang_key)
|
||||||
let projects = vec![Project{
|
.map(|s| s.as_str())
|
||||||
title: "project",
|
.unwrap_or(""),
|
||||||
url: "https://paste.thek4n.ru",
|
url: &gpg_config.url,
|
||||||
source_url: "https://gitea.thek4n.ru/thek4n/paste.thek4n.ru",
|
url_title: &gpg_config.url_title,
|
||||||
source_url_title: "thek4n/paste.thek4n.ru",
|
showkey_title: gpg_config
|
||||||
description: "copy/paste service",
|
.showkey_title
|
||||||
}];
|
.get(lang_key)
|
||||||
|
.map(|s| s.as_str())
|
||||||
let projects_section = ProjectsSection{
|
.unwrap_or(""),
|
||||||
title: "Projects",
|
copy_title: gpg_config
|
||||||
projects,
|
.copy_title
|
||||||
};
|
.get(lang_key)
|
||||||
|
.map(|s| s.as_str())
|
||||||
let languages = vec![Language{
|
.unwrap_or(""),
|
||||||
key: "en",
|
value: &gpg_config.value,
|
||||||
current: true,
|
}
|
||||||
value: "English",
|
}
|
||||||
}];
|
|
||||||
|
fn build_contacts_section<'a>(config: &'a Config, lang_key: &'a str) -> ContactsSection<'a> {
|
||||||
let index = TextPageTemplate{
|
let contacts_config = config.page.contacts.as_ref().unwrap();
|
||||||
title: "TheK4n",
|
let contacts: Vec<Contact<'a>> = config
|
||||||
description: "Developer",
|
.contacts
|
||||||
copyright_author: "Vladislav Kan <thek4n@yandex.ru>",
|
.as_ref()
|
||||||
base_url: "https://thek4n.ru",
|
.unwrap()
|
||||||
meta,
|
.iter()
|
||||||
year: "2026", // todo: get current year
|
.map(|contact| Contact {
|
||||||
aboutme_section,
|
site_name: contact
|
||||||
gpg_section,
|
.site_name
|
||||||
projects_section,
|
.get(lang_key)
|
||||||
contacts_section,
|
.map(|s| s.as_str())
|
||||||
languages,
|
.unwrap_or(""),
|
||||||
};
|
url: &contact.url,
|
||||||
|
title: &contact.title,
|
||||||
println!("{}", index.render().unwrap());
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
ContactsSection {
|
||||||
|
title: contacts_config
|
||||||
|
.title
|
||||||
|
.get(lang_key)
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(""),
|
||||||
|
contacts,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_projects_section<'a>(config: &'a Config, lang_key: &'a str) -> ProjectsSection<'a> {
|
||||||
|
let projects_config = config.page.projects.as_ref().unwrap();
|
||||||
|
let projects: Vec<Project<'a>> = config
|
||||||
|
.projects
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|project| Project {
|
||||||
|
title: &project.title,
|
||||||
|
url: &project.url,
|
||||||
|
source_url: &project.source_url,
|
||||||
|
source_url_title: &project.source_url_title,
|
||||||
|
description: project
|
||||||
|
.description
|
||||||
|
.get(lang_key)
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(""),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
ProjectsSection {
|
||||||
|
title: projects_config
|
||||||
|
.title
|
||||||
|
.get(lang_key)
|
||||||
|
.map(|s| s.as_str())
|
||||||
|
.unwrap_or(""),
|
||||||
|
projects,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_languages<'a>(config: &'a Config, lang_key: &'a str) -> Vec<Language<'a>> {
|
||||||
|
config
|
||||||
|
.languages
|
||||||
|
.iter()
|
||||||
|
.map(|lang| Language {
|
||||||
|
key: &lang.key,
|
||||||
|
current: lang.key == lang_key,
|
||||||
|
value: &lang.title,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_html_template<'a>(
|
||||||
|
config: &'a Config,
|
||||||
|
lang_key: &'a str,
|
||||||
|
base_url: &'a str,
|
||||||
|
year: &'a str,
|
||||||
|
) -> HtmlPageTemplate<'a> {
|
||||||
|
let meta = PageMeta {
|
||||||
|
title: &config.page.meta_title,
|
||||||
|
description: &config.page.meta_description,
|
||||||
|
};
|
||||||
|
|
||||||
|
HtmlPageTemplate {
|
||||||
|
title: config.page.title.get(lang_key).map(|s| s.as_str()).unwrap_or(""),
|
||||||
|
description: config.page.description.get(lang_key).map(|s| s.as_str()).unwrap_or(""),
|
||||||
|
copyright_author: &config.page.copyright_author,
|
||||||
|
base_url,
|
||||||
|
meta,
|
||||||
|
year,
|
||||||
|
aboutme: build_aboutme_section(config, lang_key),
|
||||||
|
gpg_section: build_gpg_section(config, lang_key),
|
||||||
|
contacts_section: build_contacts_section(config, lang_key),
|
||||||
|
projects_section: build_projects_section(config, lang_key),
|
||||||
|
languages: build_languages(config, lang_key),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_text_template<'a>(
|
||||||
|
config: &'a Config,
|
||||||
|
lang_key: &'a str,
|
||||||
|
base_url: &'a str,
|
||||||
|
year: &'a str,
|
||||||
|
) -> TextPageTemplate<'a> {
|
||||||
|
TextPageTemplate {
|
||||||
|
title: config.page.title.get(lang_key).map(|s| s.as_str()).unwrap_or(""),
|
||||||
|
description: config.page.description.get(lang_key).map(|s| s.as_str()).unwrap_or(""),
|
||||||
|
copyright_author: &config.page.copyright_author,
|
||||||
|
base_url,
|
||||||
|
year,
|
||||||
|
aboutme_section: build_aboutme_section(config, lang_key),
|
||||||
|
gpg_section: build_gpg_section(config, lang_key),
|
||||||
|
contacts_section: build_contacts_section(config, lang_key),
|
||||||
|
projects_section: build_projects_section(config, lang_key),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
enum ClientType {
|
||||||
|
Browser,
|
||||||
|
CliLike, // curl, wget, httpie и т.д.
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn detect_client_type(headers: &HeaderMap) -> ClientType {
|
||||||
|
let user_agent = headers
|
||||||
|
.get(USER_AGENT)
|
||||||
|
.and_then(|v| v.to_str().ok())
|
||||||
|
.unwrap_or("");
|
||||||
|
|
||||||
|
let user_agent_lower = user_agent.to_lowercase();
|
||||||
|
|
||||||
|
// Проверка Accept header
|
||||||
|
let accept = headers
|
||||||
|
.get(ACCEPT)
|
||||||
|
.and_then(|v| v.to_str().ok())
|
||||||
|
.unwrap_or("");
|
||||||
|
|
||||||
|
let accept_lower = accept.to_lowercase();
|
||||||
|
|
||||||
|
// CLI утилиты обычно имеют простой Accept или не имеют его вовсе
|
||||||
|
let is_likely_cli = accept_lower.is_empty()
|
||||||
|
|| accept_lower == "*/*"
|
||||||
|
|| accept_lower == "application/json"
|
||||||
|
|| accept_lower == "text/plain";
|
||||||
|
|
||||||
|
// Браузеры всегда запрашивают text/html в первую очередь
|
||||||
|
let is_likely_browser = accept_lower.contains("text/html")
|
||||||
|
&& (accept_lower.contains("application/xhtml+xml")
|
||||||
|
|| accept_lower.contains("application/xml")
|
||||||
|
|| accept_lower.contains("*/*"));
|
||||||
|
|
||||||
|
// Комбинированная проверка: User-Agent + Accept
|
||||||
|
if user_agent_lower.contains("curl")
|
||||||
|
|| user_agent_lower.contains("wget")
|
||||||
|
|| user_agent_lower.contains("httpie")
|
||||||
|
|| user_agent_lower.contains("python-requests")
|
||||||
|
|| user_agent_lower.contains("go-http-client")
|
||||||
|
|| (is_likely_cli && !user_agent_lower.contains("mozilla/"))
|
||||||
|
{
|
||||||
|
return ClientType::CliLike;
|
||||||
|
}
|
||||||
|
|
||||||
|
if user_agent_lower.contains("mozilla/")
|
||||||
|
&& (user_agent_lower.contains("chrome")
|
||||||
|
|| user_agent_lower.contains("safari")
|
||||||
|
|| user_agent_lower.contains("firefox")
|
||||||
|
|| user_agent_lower.contains("edg"))
|
||||||
|
&& is_likely_browser
|
||||||
|
{
|
||||||
|
return ClientType::Browser;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback с использованием только Accept header
|
||||||
|
if is_likely_browser {
|
||||||
|
ClientType::Browser
|
||||||
|
} else if is_likely_cli {
|
||||||
|
ClientType::CliLike
|
||||||
|
} else {
|
||||||
|
ClientType::Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct RootParams {
|
||||||
|
pub lang: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn root_handler(
|
||||||
|
headers: HeaderMap,
|
||||||
|
Query(params): Query<RootParams>
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
let query_lang = params.lang.unwrap_or("en".to_string());
|
||||||
|
|
||||||
|
let config = load_config("docs/config_example.toml").unwrap();
|
||||||
|
|
||||||
|
let lang_exists = config.languages.iter().any(|lang_config| lang_config.key == query_lang);
|
||||||
|
|
||||||
|
let lang = if lang_exists {
|
||||||
|
query_lang.as_str()
|
||||||
|
} else {
|
||||||
|
"en"
|
||||||
|
};
|
||||||
|
|
||||||
|
let year = chrono::Utc::now().year().to_string();
|
||||||
|
|
||||||
|
match detect_client_type(&headers) {
|
||||||
|
ClientType::Browser => {
|
||||||
|
Html(build_html_template(&config, lang, "https://thek4n.ru", year.as_str())
|
||||||
|
.render()
|
||||||
|
.unwrap())
|
||||||
|
.into_response()
|
||||||
|
}
|
||||||
|
ClientType::CliLike | ClientType::Unknown => {
|
||||||
|
format!("{}\n", build_text_template(&config, lang, "https://thek4n.ru", year.as_str())).into_response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let app = Router::new()
|
||||||
|
.route("/", get(root_handler));
|
||||||
|
|
||||||
|
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
||||||
|
|
||||||
|
axum::serve(
|
||||||
|
tokio::net::TcpListener::bind(addr).await.unwrap(),
|
||||||
|
app,
|
||||||
|
)
|
||||||
|
.await.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,8 +27,7 @@
|
|||||||
<h1>{{ projects_section.title }}</h1>
|
<h1>{{ projects_section.title }}</h1>
|
||||||
{% for project in projects_section.projects %}
|
{% for project in projects_section.projects %}
|
||||||
<p>
|
<p>
|
||||||
<span><a href="{{ project.url }}">{{ project.title }}</a></span>
|
<span><a href="{{ project.url }}">{{ project.title }}</a></span>:
|
||||||
:
|
|
||||||
<span><a href="{{ project.source_url }}">{{ project.source_url_title }}</a></span>
|
<span><a href="{{ project.source_url }}">{{ project.source_url_title }}</a></span>
|
||||||
<span><small class="muted">({{ project.description }})</small>
|
<span><small class="muted">({{ project.description }})</small>
|
||||||
</p>
|
</p>
|
||||||
@ -54,7 +53,9 @@
|
|||||||
{{ gpg_section.showkey_title }}
|
{{ gpg_section.showkey_title }}
|
||||||
<a id="copy-gpg" class="copy-link" href="#" onclick="copyGPGKey()">{{ gpg_section.copy_title }}</a>
|
<a id="copy-gpg" class="copy-link" href="#" onclick="copyGPGKey()">{{ gpg_section.copy_title }}</a>
|
||||||
</span>
|
</span>
|
||||||
{{ gpg_section.value }}
|
<code>
|
||||||
|
{{ gpg_section.value|linebreaksbr }}
|
||||||
|
</code>
|
||||||
</summary>
|
</summary>
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user