Add cli & lib crates
This commit is contained in:
@ -1,3 +1,5 @@
|
|||||||
Dockerfile
|
Dockerfile
|
||||||
target
|
target
|
||||||
|
*/target
|
||||||
database
|
database
|
||||||
|
.git
|
||||||
|
|||||||
518
Cargo.lock
generated
518
Cargo.lock
generated
@ -1,7 +1,5 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
version = "0.14.1"
|
version = "0.14.1"
|
||||||
@ -80,6 +78,15 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_term"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.50"
|
version = "0.1.50"
|
||||||
@ -259,6 +266,21 @@ dependencies = [
|
|||||||
"generic-array 0.14.4",
|
"generic-array 0.14.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "2.33.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term",
|
||||||
|
"atty",
|
||||||
|
"bitflags",
|
||||||
|
"strsim",
|
||||||
|
"textwrap",
|
||||||
|
"unicode-width",
|
||||||
|
"vec_map",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const_fn"
|
name = "const_fn"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
@ -288,6 +310,22 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpuid-bool"
|
name = "cpuid-bool"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
@ -454,6 +492,19 @@ dependencies = [
|
|||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
|
||||||
|
dependencies = [
|
||||||
|
"atty",
|
||||||
|
"humantime",
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
"termcolor",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "failure"
|
name = "failure"
|
||||||
version = "0.1.8"
|
version = "0.1.8"
|
||||||
@ -514,6 +565,31 @@ version = "1.0.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
|
dependencies = [
|
||||||
|
"foreign-types-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "foreign-types-shared"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "fs2"
|
name = "fs2"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
@ -753,7 +829,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"pest",
|
"pest",
|
||||||
"pest_derive",
|
"pest_derive",
|
||||||
"quick-error",
|
"quick-error 2.0.0",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
@ -764,6 +840,15 @@ version = "0.9.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-segmentation",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.18"
|
version = "0.1.18"
|
||||||
@ -827,6 +912,15 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9"
|
checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
|
||||||
|
dependencies = [
|
||||||
|
"quick-error 1.2.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.14.6"
|
version = "0.14.6"
|
||||||
@ -851,6 +945,30 @@ dependencies = [
|
|||||||
"want",
|
"want",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper-tls"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"hyper",
|
||||||
|
"native-tls",
|
||||||
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.6.2"
|
version = "1.6.2"
|
||||||
@ -906,12 +1024,27 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ipnet"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.50"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kernel32-sys"
|
name = "kernel32-sys"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@ -977,6 +1110,12 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matches"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.3.4"
|
version = "2.3.4"
|
||||||
@ -1092,6 +1231,24 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "native-tls"
|
||||||
|
version = "0.2.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"openssl",
|
||||||
|
"openssl-probe",
|
||||||
|
"openssl-sys",
|
||||||
|
"schannel",
|
||||||
|
"security-framework",
|
||||||
|
"security-framework-sys",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "net2"
|
name = "net2"
|
||||||
version = "0.2.37"
|
version = "0.2.37"
|
||||||
@ -1192,6 +1349,39 @@ version = "0.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl"
|
||||||
|
version = "0.10.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"foreign-types",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"openssl-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-probe"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "openssl-sys"
|
||||||
|
version = "0.9.61"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"vcpkg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
@ -1321,6 +1511,12 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pkg-config"
|
||||||
|
version = "0.3.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polyval"
|
name = "polyval"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
@ -1338,6 +1534,16 @@ version = "0.2.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pretty_env_logger"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d"
|
||||||
|
dependencies = [
|
||||||
|
"env_logger",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error"
|
name = "proc-macro-error"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
@ -1396,6 +1602,12 @@ dependencies = [
|
|||||||
"yansi",
|
"yansi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-error"
|
||||||
|
version = "1.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-error"
|
name = "quick-error"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
@ -1506,6 +1718,41 @@ dependencies = [
|
|||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reqwest"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2296f2fac53979e8ccbc4a1136b25dcefd37be9ed7e4a1f6b05a6029c84ff124"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"bytes",
|
||||||
|
"encoding_rs",
|
||||||
|
"futures-core",
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"http-body",
|
||||||
|
"hyper",
|
||||||
|
"hyper-tls",
|
||||||
|
"ipnet",
|
||||||
|
"js-sys",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"mime",
|
||||||
|
"native-tls",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project-lite",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_urlencoded",
|
||||||
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
|
"url",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"web-sys",
|
||||||
|
"winreg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rocket"
|
name = "rocket"
|
||||||
version = "0.5.0-dev"
|
version = "0.5.0-dev"
|
||||||
@ -1634,6 +1881,16 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schannel"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scoped-tls"
|
name = "scoped-tls"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -1646,6 +1903,29 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3670b1d2fdf6084d192bc71ead7aabe6c06aa2ea3fbd9cc3ac111fa5c2b1bd84"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"core-foundation",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"security-framework-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework-sys"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3676258fd3cfe2c9a0ec99ce3038798d847ce3e4bb17746373eb9f0f1ac16339"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -1710,6 +1990,18 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_urlencoded"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
|
||||||
|
dependencies = [
|
||||||
|
"form_urlencoded",
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha-1"
|
name = "sha-1"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
@ -1865,7 +2157,7 @@ checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stl"
|
name = "stl"
|
||||||
version = "2.4.0"
|
version = "2.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -1881,10 +2173,69 @@ dependencies = [
|
|||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sled",
|
"sled",
|
||||||
|
"stl_lib",
|
||||||
"tokio",
|
"tokio",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stl_cli"
|
||||||
|
version = "2.5.0"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"futures",
|
||||||
|
"log",
|
||||||
|
"notify",
|
||||||
|
"pretty_env_logger",
|
||||||
|
"reqwest",
|
||||||
|
"serde",
|
||||||
|
"stl_lib",
|
||||||
|
"structopt",
|
||||||
|
"syscalls",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stl_lib"
|
||||||
|
version = "2.5.0"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"serde",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "structopt"
|
||||||
|
version = "0.3.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"lazy_static",
|
||||||
|
"structopt-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "structopt-derive"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro-error",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.4.0"
|
version = "2.4.0"
|
||||||
@ -1914,6 +2265,15 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syscalls"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ad4126c98e506c5c2ada914b40c17b57a99f7d7044e35ff631a3504effb28e4"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.2.0"
|
version = "3.2.0"
|
||||||
@ -1928,6 +2288,44 @@ dependencies = [
|
|||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textwrap"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.1.43"
|
version = "0.1.43"
|
||||||
@ -1976,6 +2374,21 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec_macros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyvec_macros"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@ -2006,6 +2419,16 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-native-tls"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
|
||||||
|
dependencies = [
|
||||||
|
"native-tls",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.6.6"
|
version = "0.6.6"
|
||||||
@ -2108,6 +2531,36 @@ version = "0.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c"
|
checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-bidi"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0"
|
||||||
|
dependencies = [
|
||||||
|
"matches",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-normalization"
|
||||||
|
version = "0.1.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef"
|
||||||
|
dependencies = [
|
||||||
|
"tinyvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-segmentation"
|
||||||
|
version = "1.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@ -2124,6 +2577,18 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "url"
|
||||||
|
version = "2.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b"
|
||||||
|
dependencies = [
|
||||||
|
"form_urlencoded",
|
||||||
|
"idna",
|
||||||
|
"matches",
|
||||||
|
"percent-encoding",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "0.8.2"
|
version = "0.8.2"
|
||||||
@ -2134,6 +2599,18 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vcpkg"
|
||||||
|
version = "0.2.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cbdbff6266a24120518560b5dc983096efb98462e51d0d68169895b237be3e5d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vec_map"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.3"
|
version = "0.9.3"
|
||||||
@ -2174,6 +2651,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
|
checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"wasm-bindgen-macro",
|
"wasm-bindgen-macro",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2192,6 +2671,18 @@ dependencies = [
|
|||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-futures"
|
||||||
|
version = "0.4.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "81b8b767af23de6ac18bf2168b690bed2902743ddf0fb39252e36f9e2bfc63ea"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.73"
|
version = "0.2.73"
|
||||||
@ -2221,6 +2712,16 @@ version = "0.2.73"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
|
checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-sys"
|
||||||
|
version = "0.3.50"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
@ -2264,6 +2765,15 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winreg"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ws2_32-sys"
|
name = "ws2_32-sys"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
|||||||
44
Cargo.toml
44
Cargo.toml
@ -1,38 +1,6 @@
|
|||||||
[package]
|
[workspace]
|
||||||
name = "stl"
|
members = [
|
||||||
description = "studielogg aka scuffed toggl"
|
"server",
|
||||||
version = "2.4.0"
|
"cli",
|
||||||
authors = ["Joakim Hulthe <joakim@hulthe.net>"]
|
"lib",
|
||||||
license = "MPL-2.0"
|
]
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
dotenv = "0.13.0"
|
|
||||||
serde = "1"
|
|
||||||
serde_json = "1"
|
|
||||||
serde_derive = "1"
|
|
||||||
log = "0.4.8"
|
|
||||||
futures = "0.3"
|
|
||||||
chrono = { version = "0.4", features = ["serde"] }
|
|
||||||
sled = "0.34"
|
|
||||||
semver = "0.11"
|
|
||||||
uuid = { version = "0.8", features = ["serde", "v4"] }
|
|
||||||
duplicate = "0.2"
|
|
||||||
bincode = "1"
|
|
||||||
handlebars = "3"
|
|
||||||
|
|
||||||
[dependencies.tokio]
|
|
||||||
version = "1"
|
|
||||||
features = ["sync", "time"]
|
|
||||||
|
|
||||||
[dependencies.rocket]
|
|
||||||
#version = "0.4"
|
|
||||||
git = "https://github.com/SergioBenitez/Rocket"
|
|
||||||
branch = "master"
|
|
||||||
features = ["secrets"]
|
|
||||||
|
|
||||||
[dependencies.rocket_contrib]
|
|
||||||
#version = "0.4"
|
|
||||||
git = "https://github.com/SergioBenitez/Rocket"
|
|
||||||
branch = "master"
|
|
||||||
features = ["handlebars_templates", "uuid"]
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
###################
|
###################
|
||||||
### BUILD STAGE ###
|
### BUILD STAGE ###
|
||||||
###################
|
###################
|
||||||
FROM rust:1.47 as build_stage
|
FROM rust:1.51 as build_stage
|
||||||
|
|
||||||
# Install build dependencies
|
# Install build dependencies
|
||||||
RUN rustup target add x86_64-unknown-linux-musl
|
RUN rustup target add x86_64-unknown-linux-musl
|
||||||
@ -9,7 +9,9 @@ RUN rustup target add x86_64-unknown-linux-musl
|
|||||||
# Build project
|
# Build project
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY . .
|
COPY . .
|
||||||
|
WORKDIR /app/server
|
||||||
RUN cargo build --release --target x86_64-unknown-linux-musl
|
RUN cargo build --release --target x86_64-unknown-linux-musl
|
||||||
|
WORKDIR /app
|
||||||
RUN strip target/x86_64-unknown-linux-musl/release/stl
|
RUN strip target/x86_64-unknown-linux-musl/release/stl
|
||||||
|
|
||||||
########################
|
########################
|
||||||
@ -29,8 +31,8 @@ VOLUME "/database"
|
|||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
# Copy static files
|
# Copy static files
|
||||||
COPY templates templates
|
COPY server/templates templates
|
||||||
COPY static static
|
COPY server/static static
|
||||||
|
|
||||||
# Copy application binary
|
# Copy application binary
|
||||||
COPY --from=build_stage /app/target/x86_64-unknown-linux-musl/release/stl stl
|
COPY --from=build_stage /app/target/x86_64-unknown-linux-musl/release/stl stl
|
||||||
|
|||||||
1
cli/.gitignore
vendored
Normal file
1
cli/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
1711
cli/Cargo.lock
generated
Normal file
1711
cli/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
36
cli/Cargo.toml
Normal file
36
cli/Cargo.toml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
[package]
|
||||||
|
name = "stl_cli"
|
||||||
|
version = "2.5.0"
|
||||||
|
authors = ["Joakim Hulthe <joakim@hulthe.net>"]
|
||||||
|
license = "MPL-2.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "stl"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
thiserror = "1.0.24"
|
||||||
|
notify = "4.0.16"
|
||||||
|
log = "0.4.14"
|
||||||
|
pretty_env_logger = "0.4.0"
|
||||||
|
uuid = { version = "0.8", features = ["serde", "v4"] }
|
||||||
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
structopt = "0.3.21"
|
||||||
|
syscalls = { version = "0.3", default-features = false }
|
||||||
|
futures = "0.3"
|
||||||
|
|
||||||
|
[dependencies.stl_lib]
|
||||||
|
path = "../lib"
|
||||||
|
|
||||||
|
[dependencies.serde]
|
||||||
|
version = "1"
|
||||||
|
features = ["derive"]
|
||||||
|
|
||||||
|
[dependencies.reqwest]
|
||||||
|
version = "0.11.3"
|
||||||
|
features = ["json"]
|
||||||
|
|
||||||
|
[dependencies.tokio]
|
||||||
|
version = "1.5.0"
|
||||||
|
features = ["fs", "rt", "rt-multi-thread", "macros"]
|
||||||
0
cli/src/api.rs
Normal file
0
cli/src/api.rs
Normal file
161
cli/src/daemon.rs
Normal file
161
cli/src/daemon.rs
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
use crate::util::proxy_channel;
|
||||||
|
use crate::DaemonOpt;
|
||||||
|
use crate::Error;
|
||||||
|
use futures::poll;
|
||||||
|
use futures::task::Poll;
|
||||||
|
use notify::{INotifyWatcher, Op, RecursiveMode, Watcher};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::mpsc;
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
use stl_lib::api::url;
|
||||||
|
use stl_lib::v2::trees::category;
|
||||||
|
use tokio::fs;
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
use tokio::task::{spawn, JoinHandle};
|
||||||
|
|
||||||
|
pub fn run(opt: DaemonOpt) -> Result<(), Error> {
|
||||||
|
let opt: &'static DaemonOpt = Box::leak(Box::new(opt));
|
||||||
|
|
||||||
|
let rt = Runtime::new()?;
|
||||||
|
rt.block_on(async {
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
|
info!("creating output file");
|
||||||
|
fs::write(&opt.file, b"").await?;
|
||||||
|
|
||||||
|
let mut watcher = INotifyWatcher::new_raw(tx).unwrap();
|
||||||
|
watcher
|
||||||
|
.watch(&opt.file, RecursiveMode::NonRecursive)
|
||||||
|
.expect("failed to watch file");
|
||||||
|
|
||||||
|
update_category_list(opt).await?;
|
||||||
|
let mut last_update = Instant::now();
|
||||||
|
|
||||||
|
let mut wfe: JoinHandle<_> = spawn(wait_for_event(opt));
|
||||||
|
|
||||||
|
let mut rx = proxy_channel(rx);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let event = match rx.recv().await {
|
||||||
|
Some(event) => event,
|
||||||
|
None => return Err(Error::ChannelClosed),
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!("event op {:?}", event.op);
|
||||||
|
|
||||||
|
match event.op {
|
||||||
|
Ok(Op::CHMOD) => { /* YEESSS */ }
|
||||||
|
_ => continue,
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("CHMOD event detected");
|
||||||
|
|
||||||
|
let update_categories;
|
||||||
|
let restart_wfe;
|
||||||
|
|
||||||
|
match poll!(&mut wfe) {
|
||||||
|
Poll::Ready(Ok(Ok(_wfe))) => {
|
||||||
|
restart_wfe = true;
|
||||||
|
update_categories = Some(true);
|
||||||
|
}
|
||||||
|
Poll::Ready(Ok(Err(e))) => {
|
||||||
|
error!("error waiting for event (falling back to timing): {}", e);
|
||||||
|
restart_wfe = false;
|
||||||
|
update_categories = None;
|
||||||
|
}
|
||||||
|
Poll::Ready(Err(_)) => {
|
||||||
|
restart_wfe = false;
|
||||||
|
update_categories = None;
|
||||||
|
}
|
||||||
|
Poll::Pending => {
|
||||||
|
restart_wfe = false;
|
||||||
|
update_categories = Some(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let elapsed = last_update.elapsed();
|
||||||
|
let update_categories =
|
||||||
|
update_categories.unwrap_or_else(|| elapsed > Duration::from_secs(opt.poll_delay));
|
||||||
|
|
||||||
|
if update_categories {
|
||||||
|
update_category_list(opt).await?;
|
||||||
|
last_update = Instant::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
if update_categories || restart_wfe {
|
||||||
|
wfe = spawn(wait_for_event(opt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct WaitForEvent {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
timeout: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn wait_for_event(opt: &DaemonOpt) -> Result<WaitForEvent, Error> {
|
||||||
|
info!("calling wait_for_event");
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let wfe: WaitForEvent = client
|
||||||
|
.get(format!(
|
||||||
|
"{}{}?timeout={}",
|
||||||
|
&opt.api_uri,
|
||||||
|
url::WAIT_FOR_EVENT,
|
||||||
|
opt.poll_delay
|
||||||
|
))
|
||||||
|
.header("Cookie", &opt.cookie)
|
||||||
|
.send()
|
||||||
|
.await?
|
||||||
|
.json()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(wfe)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn update_category_list(opt: &DaemonOpt) -> Result<(), Error> {
|
||||||
|
let categories = get_active_categories(opt).await?;
|
||||||
|
|
||||||
|
info!("writing output file");
|
||||||
|
let data = categories.join("|");
|
||||||
|
let data = if data.is_empty() {
|
||||||
|
b"--"
|
||||||
|
} else {
|
||||||
|
data.as_bytes()
|
||||||
|
};
|
||||||
|
|
||||||
|
fs::write(&opt.file, data).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_active_categories(opt: &DaemonOpt) -> Result<Vec<String>, Error> {
|
||||||
|
info!("downloading category list");
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let response = client
|
||||||
|
.get(format!("{}{}", &opt.api_uri, url::SESSIONS))
|
||||||
|
.header("Cookie", &opt.cookie)
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let categories: HashMap<category::K, category::V> = response.json().await?;
|
||||||
|
|
||||||
|
// sort by the longest running log
|
||||||
|
let mut categories: Vec<category::V> = categories.into_iter().map(|(_, v)| v).collect();
|
||||||
|
categories.sort_by_key(|c| (c.started));
|
||||||
|
|
||||||
|
Ok(categories
|
||||||
|
.into_iter()
|
||||||
|
.inspect(|category| {
|
||||||
|
info!(
|
||||||
|
" name={} active={}",
|
||||||
|
category.name,
|
||||||
|
category.started.is_some()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.filter(|category| category.started.is_some())
|
||||||
|
.map(|category| category.name)
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
80
cli/src/main.rs
Normal file
80
cli/src/main.rs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
|
||||||
|
pub mod daemon;
|
||||||
|
pub mod stat;
|
||||||
|
pub mod util;
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use structopt::StructOpt;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("request error {0:?}")]
|
||||||
|
Request(#[from] reqwest::Error),
|
||||||
|
|
||||||
|
#[error("input/output error")]
|
||||||
|
IO(#[from] tokio::io::Error),
|
||||||
|
|
||||||
|
#[error("notify channel closed")]
|
||||||
|
ChannelClosed,
|
||||||
|
|
||||||
|
#[error("syscall error, code = {error_code}")]
|
||||||
|
SysCall { error_code: i64 },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
pub enum Opt {
|
||||||
|
/// Launch the daemon
|
||||||
|
Daemon(DaemonOpt),
|
||||||
|
|
||||||
|
/// touch the stat file if it exists
|
||||||
|
/// otherwise exit with status code 1
|
||||||
|
Stat(StatOpt),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
pub struct DaemonOpt {
|
||||||
|
/// The path to the output file
|
||||||
|
#[structopt(short, long)]
|
||||||
|
file: PathBuf,
|
||||||
|
|
||||||
|
/// The server uri
|
||||||
|
#[structopt(short, long, default_value = "https://stl.nubo.sh")]
|
||||||
|
api_uri: String,
|
||||||
|
|
||||||
|
/// The amount of time to wait between polls
|
||||||
|
#[structopt(short = "d", long, default_value = "30")]
|
||||||
|
poll_delay: u64,
|
||||||
|
|
||||||
|
/// The authorization cookie for the server
|
||||||
|
#[structopt(short, long)]
|
||||||
|
cookie: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(StructOpt)]
|
||||||
|
pub struct StatOpt {
|
||||||
|
#[structopt(short, long)]
|
||||||
|
file: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
pretty_env_logger::init();
|
||||||
|
|
||||||
|
let opt = Opt::from_args();
|
||||||
|
|
||||||
|
let result = match opt {
|
||||||
|
Opt::Daemon(opt) => daemon::run(opt),
|
||||||
|
Opt::Stat(opt) => stat::run(&opt),
|
||||||
|
};
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
error!("{}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("stld starting");
|
||||||
|
}
|
||||||
34
cli/src/stat.rs
Normal file
34
cli/src/stat.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::{Error, StatOpt};
|
||||||
|
use std::fs;
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
|
use std::process::exit;
|
||||||
|
use syscalls::syscall;
|
||||||
|
|
||||||
|
pub fn run(opt: &StatOpt) -> Result<(), Error> {
|
||||||
|
let file = match fs::OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.read(false)
|
||||||
|
.create(false)
|
||||||
|
.open(&opt.file)
|
||||||
|
{
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(_) => exit(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
let fd: i32 = file.as_raw_fd();
|
||||||
|
|
||||||
|
let result: i64 = unsafe {
|
||||||
|
// update file mtime (to trigger inotify) in the daemon
|
||||||
|
//
|
||||||
|
// SAFETY:
|
||||||
|
// - fd is a valid file descriptor, since it was created using a File
|
||||||
|
// - passing NULL to all other parameters is valid according to `man 2 utimensat`
|
||||||
|
syscall!(SYS_utimensat, fd, 0, 0, 0)
|
||||||
|
}
|
||||||
|
.map_err(|error_code| Error::SysCall { error_code })?;
|
||||||
|
|
||||||
|
// 0 should be the only possible return value, since error cases are handled by the result
|
||||||
|
assert_eq!(result, 0);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
24
cli/src/util.rs
Normal file
24
cli/src/util.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use std::sync::mpsc as std_mpsc;
|
||||||
|
use tokio::sync::mpsc as tokio_mpsc;
|
||||||
|
use tokio::task;
|
||||||
|
|
||||||
|
pub fn proxy_channel<T>(std_rx: std_mpsc::Receiver<T>) -> tokio_mpsc::Receiver<T>
|
||||||
|
where
|
||||||
|
T: 'static + Send + Sync,
|
||||||
|
{
|
||||||
|
let (tx, tokio_rx) = tokio_mpsc::channel(255);
|
||||||
|
|
||||||
|
task::spawn_blocking(move || loop {
|
||||||
|
let msg = match std_rx.recv() {
|
||||||
|
Ok(msg) => msg,
|
||||||
|
Err(_) => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
match tx.blocking_send(msg) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(_) => return,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
tokio_rx
|
||||||
|
}
|
||||||
13
lib/Cargo.toml
Normal file
13
lib/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "stl_lib"
|
||||||
|
version = "2.5.0"
|
||||||
|
authors = ["Joakim Hulthe <joakim@hulthe.net>"]
|
||||||
|
license = "MPL-2.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
uuid = { version = "0.8", features = ["serde", "v4"] }
|
||||||
|
|
||||||
4
lib/src/api.rs
Normal file
4
lib/src/api.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
pub mod url {
|
||||||
|
pub const SESSIONS: &str = "/api/sessions";
|
||||||
|
pub const WAIT_FOR_EVENT: &str = "/api/wait_for_event";
|
||||||
|
}
|
||||||
27
lib/src/category.rs
Normal file
27
lib/src/category.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use chrono::{DateTime, Local};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub type CategoryKey = Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Category {
|
||||||
|
/// The name of the category
|
||||||
|
pub name: String,
|
||||||
|
|
||||||
|
/// The description of the category
|
||||||
|
pub description: Option<String>,
|
||||||
|
|
||||||
|
/// The HTML color of the category in the rendered view
|
||||||
|
pub color: String,
|
||||||
|
|
||||||
|
/// If the session is not active, this will be None
|
||||||
|
pub started: Option<DateTime<Local>>,
|
||||||
|
|
||||||
|
/// The parent category of this category
|
||||||
|
/// If none, the category has no parent
|
||||||
|
pub parent: Option<CategoryKey>,
|
||||||
|
|
||||||
|
/// Whether the item has been "deleted", e.g. it shoudn't be shown in the view
|
||||||
|
pub deleted: bool,
|
||||||
|
}
|
||||||
3
lib/src/lib.rs
Normal file
3
lib/src/lib.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod api;
|
||||||
|
pub mod v2;
|
||||||
|
pub mod wfe;
|
||||||
63
lib/src/v2.rs
Normal file
63
lib/src/v2.rs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
pub(self) use chrono::{DateTime, Local};
|
||||||
|
pub(self) use serde::{Deserialize, Serialize};
|
||||||
|
pub(self) use uuid::Uuid;
|
||||||
|
|
||||||
|
/// Stuff in the default namespace
|
||||||
|
pub mod global {}
|
||||||
|
|
||||||
|
pub mod trees {
|
||||||
|
pub mod category {
|
||||||
|
use super::super::*;
|
||||||
|
|
||||||
|
pub const NAME: &str = "CATEGORIES";
|
||||||
|
|
||||||
|
pub type K = Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct V {
|
||||||
|
/// The name of the category
|
||||||
|
pub name: String,
|
||||||
|
|
||||||
|
/// The description of the category
|
||||||
|
pub description: Option<String>,
|
||||||
|
|
||||||
|
/// The HTML color of the category in the rendered view
|
||||||
|
pub color: String,
|
||||||
|
|
||||||
|
/// If the session is not active, this will be None
|
||||||
|
pub started: Option<DateTime<Local>>,
|
||||||
|
|
||||||
|
/// The parent category of this category
|
||||||
|
/// If none, the category has no parent
|
||||||
|
pub parent: Option<K>,
|
||||||
|
|
||||||
|
// FIXME: this field is currently not used
|
||||||
|
/// Whether the item has been "deleted", e.g. it shoudn't be shown in the view
|
||||||
|
pub deleted: bool,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod session {
|
||||||
|
use super::super::*;
|
||||||
|
|
||||||
|
pub const NAME: &str = "SESSIONS";
|
||||||
|
|
||||||
|
pub type K = Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct V {
|
||||||
|
/// The UUID of the category to which this session belongs
|
||||||
|
pub category: trees::category::K,
|
||||||
|
|
||||||
|
/// The time when this session was started
|
||||||
|
pub started: DateTime<Local>,
|
||||||
|
|
||||||
|
/// The time when this session was ended
|
||||||
|
pub ended: DateTime<Local>,
|
||||||
|
|
||||||
|
// FIXME: this field is currently not used
|
||||||
|
/// Whether the item has been "deleted", e.g. it shoudn't be shown in the view
|
||||||
|
pub deleted: bool,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
6
lib/src/wfe.rs
Normal file
6
lib/src/wfe.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct WaitForEvent {
|
||||||
|
pub timeout: bool,
|
||||||
|
}
|
||||||
2281
server/Cargo.lock
generated
Normal file
2281
server/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
41
server/Cargo.toml
Normal file
41
server/Cargo.toml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
[package]
|
||||||
|
name = "stl"
|
||||||
|
description = "studielogg aka scuffed toggl"
|
||||||
|
version = "2.5.0"
|
||||||
|
authors = ["Joakim Hulthe <joakim@hulthe.net>"]
|
||||||
|
license = "MPL-2.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
dotenv = "0.13.0"
|
||||||
|
serde = "1"
|
||||||
|
serde_json = "1"
|
||||||
|
serde_derive = "1"
|
||||||
|
log = "0.4.8"
|
||||||
|
futures = "0.3"
|
||||||
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
|
sled = "0.34"
|
||||||
|
semver = "0.11"
|
||||||
|
uuid = { version = "0.8", features = ["serde", "v4"] }
|
||||||
|
duplicate = "0.2"
|
||||||
|
bincode = "1"
|
||||||
|
handlebars = "3"
|
||||||
|
|
||||||
|
[dependencies.stl_lib]
|
||||||
|
path = "../lib"
|
||||||
|
|
||||||
|
[dependencies.tokio]
|
||||||
|
version = "1"
|
||||||
|
features = ["sync", "time"]
|
||||||
|
|
||||||
|
[dependencies.rocket]
|
||||||
|
#version = "0.4"
|
||||||
|
git = "https://github.com/SergioBenitez/Rocket"
|
||||||
|
branch = "master"
|
||||||
|
features = ["secrets"]
|
||||||
|
|
||||||
|
[dependencies.rocket_contrib]
|
||||||
|
#version = "0.4"
|
||||||
|
git = "https://github.com/SergioBenitez/Rocket"
|
||||||
|
branch = "master"
|
||||||
|
features = ["handlebars_templates", "uuid"]
|
||||||
4
server/database/conf
Normal file
4
server/database/conf
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
segment_size: 524288
|
||||||
|
use_compression: false
|
||||||
|
version: 0.34
|
||||||
|
vQ<>
|
||||||
BIN
server/database/db
Normal file
BIN
server/database/db
Normal file
Binary file not shown.
BIN
server/database/snap.0000000000014880
Normal file
BIN
server/database/snap.0000000000014880
Normal file
Binary file not shown.
@ -12,7 +12,7 @@ pub fn migrate(db: &mut Db) -> Result<(), MigrationError> {
|
|||||||
|
|
||||||
// Open old & new trees
|
// Open old & new trees
|
||||||
let v1_past_sessions = db.open_tree(v1::trees::past_sessions::NAME)?;
|
let v1_past_sessions = db.open_tree(v1::trees::past_sessions::NAME)?;
|
||||||
let v2_sessions = db.open_tree(v2::trees::sessions::NAME)?;
|
let v2_sessions = db.open_tree(v2::trees::session::NAME)?;
|
||||||
|
|
||||||
// Iterate over old tree
|
// Iterate over old tree
|
||||||
for r in v1_past_sessions.iter() {
|
for r in v1_past_sessions.iter() {
|
||||||
@ -26,7 +26,7 @@ pub fn migrate(db: &mut Db) -> Result<(), MigrationError> {
|
|||||||
} = deserialize(&v)?;
|
} = deserialize(&v)?;
|
||||||
|
|
||||||
// Convert to new value
|
// Convert to new value
|
||||||
let v2_value = v2::trees::sessions::V {
|
let v2_value = v2::trees::session::V {
|
||||||
category,
|
category,
|
||||||
started: DateTime::<Utc>::from_utc(started, Utc).into(),
|
started: DateTime::<Utc>::from_utc(started, Utc).into(),
|
||||||
ended: DateTime::<Utc>::from_utc(ended, Utc).into(),
|
ended: DateTime::<Utc>::from_utc(ended, Utc).into(),
|
||||||
@ -59,7 +59,7 @@ pub fn migrate(db: &mut Db) -> Result<(), MigrationError> {
|
|||||||
} = deserialize(&v)?;
|
} = deserialize(&v)?;
|
||||||
|
|
||||||
// Convert to new value
|
// Convert to new value
|
||||||
let v2_value = v2::trees::categories::V {
|
let v2_value = v2::trees::category::V {
|
||||||
name,
|
name,
|
||||||
description: None,
|
description: None,
|
||||||
color,
|
color,
|
||||||
@ -1,7 +1,7 @@
|
|||||||
pub mod unversioned;
|
pub mod unversioned;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod v1;
|
pub mod v1;
|
||||||
pub mod v2;
|
pub use stl_lib::v2;
|
||||||
|
|
||||||
pub mod migrations;
|
pub mod migrations;
|
||||||
|
|
||||||
@ -1,12 +1,12 @@
|
|||||||
use crate::database::latest::trees::categories;
|
use crate::database::latest::trees::category;
|
||||||
use crate::status_json::StatusJson;
|
use crate::status_json::StatusJson;
|
||||||
use bincode::{deserialize, serialize};
|
use bincode::{deserialize, serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub fn get_category(
|
pub fn get_category(
|
||||||
tree: &sled::Tree,
|
tree: &sled::Tree,
|
||||||
key: &categories::K,
|
key: &category::K,
|
||||||
) -> Result<Option<categories::V>, StatusJson> {
|
) -> Result<Option<category::V>, StatusJson> {
|
||||||
Ok(match tree.get(serialize(key)?)? {
|
Ok(match tree.get(serialize(key)?)? {
|
||||||
Some(raw) => Some(deserialize(&raw)?),
|
Some(raw) => Some(deserialize(&raw)?),
|
||||||
None => None,
|
None => None,
|
||||||
@ -15,7 +15,7 @@ pub fn get_category(
|
|||||||
|
|
||||||
pub fn get_all_categories(
|
pub fn get_all_categories(
|
||||||
tree: &sled::Tree,
|
tree: &sled::Tree,
|
||||||
) -> Result<HashMap<categories::K, categories::V>, StatusJson> {
|
) -> Result<HashMap<category::K, category::V>, StatusJson> {
|
||||||
Ok(tree
|
Ok(tree
|
||||||
.iter()
|
.iter()
|
||||||
.map(|result| {
|
.map(|result| {
|
||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::auth::Authorized;
|
use crate::auth::Authorized;
|
||||||
use crate::database::latest::trees::{categories, sessions};
|
use crate::database::latest::trees::{category, session};
|
||||||
use crate::database::util::category::get_all_categories;
|
use crate::database::util::category::get_all_categories;
|
||||||
use crate::routes::pages;
|
use crate::routes::pages;
|
||||||
use crate::status_json::StatusJson;
|
use crate::status_json::StatusJson;
|
||||||
@ -12,16 +12,16 @@ use rocket::response::Redirect;
|
|||||||
use rocket::{get, post, uri, State};
|
use rocket::{get, post, uri, State};
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use rocket_contrib::uuid::Uuid;
|
use rocket_contrib::uuid::Uuid;
|
||||||
use serde::Serialize;
|
|
||||||
use sled::Transactional;
|
use sled::Transactional;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use stl_lib::wfe::WaitForEvent;
|
||||||
|
|
||||||
#[get("/sessions")]
|
#[get("/sessions")]
|
||||||
pub fn get_sessions(
|
pub fn get_sessions(
|
||||||
_auth: Authorized,
|
_auth: Authorized,
|
||||||
db: State<'_, sled::Db>,
|
db: State<'_, sled::Db>,
|
||||||
) -> Result<Json<HashMap<categories::K, categories::V>>, StatusJson> {
|
) -> Result<Json<HashMap<category::K, category::V>>, StatusJson> {
|
||||||
let categories_tree = db.open_tree(categories::NAME)?;
|
let categories_tree = db.open_tree(category::NAME)?;
|
||||||
Ok(Json(get_all_categories(&categories_tree)?))
|
Ok(Json(get_all_categories(&categories_tree)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,10 +39,10 @@ pub fn create_category(
|
|||||||
) -> Result<StatusJson, StatusJson> {
|
) -> Result<StatusJson, StatusJson> {
|
||||||
let category = category.into_inner();
|
let category = category.into_inner();
|
||||||
|
|
||||||
let categories_tree = db.open_tree(categories::NAME)?;
|
let categories_tree = db.open_tree(category::NAME)?;
|
||||||
categories_tree.insert(
|
categories_tree.insert(
|
||||||
serialize(&uuid::Uuid::new_v4())?,
|
serialize(&uuid::Uuid::new_v4())?,
|
||||||
serialize(&categories::V {
|
serialize(&category::V {
|
||||||
name: category.name,
|
name: category.name,
|
||||||
description: None,
|
description: None,
|
||||||
color: category.color,
|
color: category.color,
|
||||||
@ -65,13 +65,13 @@ pub fn bump_session(
|
|||||||
let duration = Duration::minutes(minutes);
|
let duration = Duration::minutes(minutes);
|
||||||
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?);
|
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?);
|
||||||
|
|
||||||
let categories_tree = db.open_tree(categories::NAME)?;
|
let categories_tree = db.open_tree(category::NAME)?;
|
||||||
|
|
||||||
Ok((&categories_tree).transaction(|tx_categories| {
|
Ok((&categories_tree).transaction(|tx_categories| {
|
||||||
match tx_categories.get(&category_uuid_s)? {
|
match tx_categories.get(&category_uuid_s)? {
|
||||||
None => return Ok(Err(Status::NotFound.into())),
|
None => return Ok(Err(Status::NotFound.into())),
|
||||||
Some(data) => {
|
Some(data) => {
|
||||||
let mut category: categories::V = deserialize(&data).unwrap();
|
let mut category: category::V = deserialize(&data).unwrap();
|
||||||
match category.started.as_mut() {
|
match category.started.as_mut() {
|
||||||
Some(started) => {
|
Some(started) => {
|
||||||
if let Some(new_started) = started.checked_sub_signed(duration) {
|
if let Some(new_started) = started.checked_sub_signed(duration) {
|
||||||
@ -127,15 +127,15 @@ pub fn toggle_category_session(
|
|||||||
) -> Result<StatusJson, StatusJson> {
|
) -> Result<StatusJson, StatusJson> {
|
||||||
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?);
|
let category_uuid_s = sled::IVec::from(serialize(&category_uuid.into_inner())?);
|
||||||
|
|
||||||
let categories_tree = db.open_tree(categories::NAME)?;
|
let categories_tree = db.open_tree(category::NAME)?;
|
||||||
let sessions_tree = db.open_tree(sessions::NAME)?;
|
let sessions_tree = db.open_tree(session::NAME)?;
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
(&categories_tree, &sessions_tree).transaction(|(tx_categories, tx_sessions)| {
|
(&categories_tree, &sessions_tree).transaction(|(tx_categories, tx_sessions)| {
|
||||||
match tx_categories.get(&category_uuid_s)? {
|
match tx_categories.get(&category_uuid_s)? {
|
||||||
None => return Ok(Err(Status::NotFound)),
|
None => return Ok(Err(Status::NotFound)),
|
||||||
Some(data) => {
|
Some(data) => {
|
||||||
let mut category: categories::V = deserialize(&data).unwrap();
|
let mut category: category::V = deserialize(&data).unwrap();
|
||||||
let now = Local::now();
|
let now = Local::now();
|
||||||
|
|
||||||
match (set_active, category.started.take()) {
|
match (set_active, category.started.take()) {
|
||||||
@ -144,7 +144,7 @@ pub fn toggle_category_session(
|
|||||||
let duration = now - started;
|
let duration = now - started;
|
||||||
if duration > Duration::minutes(5) {
|
if duration > Duration::minutes(5) {
|
||||||
let session_uuid = serialize(&uuid::Uuid::new_v4()).unwrap();
|
let session_uuid = serialize(&uuid::Uuid::new_v4()).unwrap();
|
||||||
let session = sessions::V {
|
let session = session::V {
|
||||||
category: category_uuid.into_inner(),
|
category: category_uuid.into_inner(),
|
||||||
started,
|
started,
|
||||||
ended: now,
|
ended: now,
|
||||||
@ -189,7 +189,7 @@ pub fn edit_session(
|
|||||||
) -> Result<Redirect, StatusJson> {
|
) -> Result<Redirect, StatusJson> {
|
||||||
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?);
|
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?);
|
||||||
|
|
||||||
let session = sessions::V {
|
let session = session::V {
|
||||||
category: session.category.into_inner(),
|
category: session.category.into_inner(),
|
||||||
started: Local
|
started: Local
|
||||||
.from_local_datetime(&NaiveDateTime::parse_from_str(
|
.from_local_datetime(&NaiveDateTime::parse_from_str(
|
||||||
@ -213,7 +213,7 @@ pub fn edit_session(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
db.open_tree(sessions::NAME)?
|
db.open_tree(session::NAME)?
|
||||||
.insert(session_uuid_s, serialize(&session)?)?;
|
.insert(session_uuid_s, serialize(&session)?)?;
|
||||||
|
|
||||||
// FIXME: Uuid does not implement FromUriParam for some reason... File an issue?
|
// FIXME: Uuid does not implement FromUriParam for some reason... File an issue?
|
||||||
@ -229,7 +229,7 @@ pub fn delete_session(
|
|||||||
) -> Result<Redirect, StatusJson> {
|
) -> Result<Redirect, StatusJson> {
|
||||||
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?);
|
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?);
|
||||||
|
|
||||||
let sessions_tree = db.open_tree(sessions::NAME)?;
|
let sessions_tree = db.open_tree(session::NAME)?;
|
||||||
|
|
||||||
match sessions_tree.remove(session_uuid_s)? {
|
match sessions_tree.remove(session_uuid_s)? {
|
||||||
Some(_) => Ok(Redirect::to(uri!(pages::history))),
|
Some(_) => Ok(Redirect::to(uri!(pages::history))),
|
||||||
@ -241,18 +241,13 @@ pub fn delete_session(
|
|||||||
// match tx_sessions.get(&session_uuid_s)? {
|
// match tx_sessions.get(&session_uuid_s)? {
|
||||||
// None => return Ok(Err(Status::NotFound)),
|
// None => return Ok(Err(Status::NotFound)),
|
||||||
// Some(data) => {
|
// Some(data) => {
|
||||||
// let mut session: sessions::V = deserialize(&data).unwrap();
|
// let mut session: session::V = deserialize(&data).unwrap();
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// Ok(Ok(Redirect::to(uri!(pages::history))))
|
// Ok(Ok(Redirect::to(uri!(pages::history))))
|
||||||
// })??)
|
// })??)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
pub struct WaitForEvent {
|
|
||||||
timeout: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/wait_for_event?<timeout>")]
|
#[get("/wait_for_event?<timeout>")]
|
||||||
pub async fn wait_for_event(
|
pub async fn wait_for_event(
|
||||||
_auth: Authorized,
|
_auth: Authorized,
|
||||||
@ -1,7 +1,7 @@
|
|||||||
pub mod stats;
|
pub mod stats;
|
||||||
|
|
||||||
use crate::auth::Authorized;
|
use crate::auth::Authorized;
|
||||||
use crate::database::latest::trees::{categories, sessions};
|
use crate::database::latest::trees::{category, session};
|
||||||
use crate::status_json::StatusJson;
|
use crate::status_json::StatusJson;
|
||||||
use bincode::{deserialize, serialize};
|
use bincode::{deserialize, serialize};
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
@ -16,10 +16,10 @@ use std::time::Duration;
|
|||||||
pub fn index(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, StatusJson> {
|
pub fn index(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, StatusJson> {
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct TemplateContext {
|
struct TemplateContext {
|
||||||
categories: Vec<(uuid::Uuid, categories::V)>,
|
categories: Vec<(category::K, category::V)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let categories_tree = db.open_tree(categories::NAME)?;
|
let categories_tree = db.open_tree(category::NAME)?;
|
||||||
|
|
||||||
let context = TemplateContext {
|
let context = TemplateContext {
|
||||||
categories: categories_tree
|
categories: categories_tree
|
||||||
@ -41,13 +41,13 @@ pub fn session_edit(
|
|||||||
) -> Result<Template, StatusJson> {
|
) -> Result<Template, StatusJson> {
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct SessionPageContext {
|
struct SessionPageContext {
|
||||||
session: sessions::V,
|
session: session::V,
|
||||||
session_id: uuid::Uuid,
|
session_id: uuid::Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?);
|
let session_uuid_s = sled::IVec::from(serialize(&session_uuid.into_inner())?);
|
||||||
|
|
||||||
let sessions_tree = db.open_tree(sessions::NAME)?;
|
let sessions_tree = db.open_tree(session::NAME)?;
|
||||||
match sessions_tree.get(session_uuid_s)? {
|
match sessions_tree.get(session_uuid_s)? {
|
||||||
None => Err(Status::NotFound)?,
|
None => Err(Status::NotFound)?,
|
||||||
Some(data) => {
|
Some(data) => {
|
||||||
@ -65,8 +65,8 @@ pub fn session_edit(
|
|||||||
pub fn history(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, StatusJson> {
|
pub fn history(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, StatusJson> {
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct HistoryEntryContext {
|
struct HistoryEntryContext {
|
||||||
category: categories::V,
|
category: category::V,
|
||||||
session: sessions::V,
|
session: session::V,
|
||||||
session_id: uuid::Uuid,
|
session_id: uuid::Uuid,
|
||||||
duration: Duration,
|
duration: Duration,
|
||||||
}
|
}
|
||||||
@ -76,17 +76,17 @@ pub fn history(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template, S
|
|||||||
entries: Vec<HistoryEntryContext>,
|
entries: Vec<HistoryEntryContext>,
|
||||||
}
|
}
|
||||||
|
|
||||||
let categories_tree = db.open_tree(categories::NAME)?;
|
let categories_tree = db.open_tree(category::NAME)?;
|
||||||
let sessions_tree = db.open_tree(sessions::NAME)?;
|
let sessions_tree = db.open_tree(session::NAME)?;
|
||||||
|
|
||||||
let categories: HashMap<categories::K, categories::V> = categories_tree
|
let categories: HashMap<category::K, category::V> = categories_tree
|
||||||
.iter()
|
.iter()
|
||||||
.map(|result| {
|
.map(|result| {
|
||||||
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
|
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
|
||||||
})
|
})
|
||||||
.collect::<Result<Result<_, _>, _>>()??;
|
.collect::<Result<Result<_, _>, _>>()??;
|
||||||
|
|
||||||
let sessions: HashMap<sessions::K, sessions::V> = sessions_tree
|
let sessions: HashMap<session::K, session::V> = sessions_tree
|
||||||
.iter()
|
.iter()
|
||||||
.map(|result| {
|
.map(|result| {
|
||||||
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
|
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
|
||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::auth::Authorized;
|
use crate::auth::Authorized;
|
||||||
use crate::database::latest::trees::{categories, sessions};
|
use crate::database::latest::trees::{category, session};
|
||||||
use crate::database::util::category::get_category;
|
use crate::database::util::category::get_category;
|
||||||
use crate::status_json::StatusJson;
|
use crate::status_json::StatusJson;
|
||||||
use bincode::deserialize;
|
use bincode::deserialize;
|
||||||
@ -14,8 +14,8 @@ use std::collections::{BTreeMap, HashMap};
|
|||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
struct CategoryStatsContext {
|
struct CategoryStatsContext {
|
||||||
category_id: categories::K,
|
category_id: category::K,
|
||||||
category: categories::V,
|
category: category::V,
|
||||||
|
|
||||||
last_session_start: Option<DateTime<Local>>,
|
last_session_start: Option<DateTime<Local>>,
|
||||||
secs_last_session: u64,
|
secs_last_session: u64,
|
||||||
@ -26,7 +26,7 @@ struct CategoryStatsContext {
|
|||||||
bars: Vec<(u32, f64, f64)>,
|
bars: Vec<(u32, f64, f64)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sum_sessions<'a>(iter: impl IntoIterator<Item = &'a sessions::V>) -> u64 {
|
fn sum_sessions<'a>(iter: impl IntoIterator<Item = &'a session::V>) -> u64 {
|
||||||
iter.into_iter()
|
iter.into_iter()
|
||||||
.map(|session| session.ended - session.started)
|
.map(|session| session.ended - session.started)
|
||||||
.map(|duration| duration.num_seconds() as u64)
|
.map(|duration| duration.num_seconds() as u64)
|
||||||
@ -39,13 +39,13 @@ pub fn single_stats(
|
|||||||
category_uuid: Uuid,
|
category_uuid: Uuid,
|
||||||
db: State<'_, sled::Db>,
|
db: State<'_, sled::Db>,
|
||||||
) -> Result<Template, StatusJson> {
|
) -> Result<Template, StatusJson> {
|
||||||
let categories_tree = db.open_tree(categories::NAME)?;
|
let categories_tree = db.open_tree(category::NAME)?;
|
||||||
let sessions_tree = db.open_tree(sessions::NAME)?;
|
let sessions_tree = db.open_tree(session::NAME)?;
|
||||||
|
|
||||||
let category: categories::V =
|
let category: category::V =
|
||||||
get_category(&categories_tree, &category_uuid)?.ok_or(Status::NotFound)?;
|
get_category(&categories_tree, &category_uuid)?.ok_or(Status::NotFound)?;
|
||||||
|
|
||||||
let sessions: HashMap<sessions::K, sessions::V> = sessions_tree
|
let sessions: HashMap<session::K, session::V> = sessions_tree
|
||||||
.iter()
|
.iter()
|
||||||
.map(|result| {
|
.map(|result| {
|
||||||
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
|
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
|
||||||
@ -114,17 +114,17 @@ pub fn all_stats(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template,
|
|||||||
|
|
||||||
let now = Local::now();
|
let now = Local::now();
|
||||||
|
|
||||||
let categories_tree = db.open_tree(categories::NAME)?;
|
let categories_tree = db.open_tree(category::NAME)?;
|
||||||
let sessions_tree = db.open_tree(sessions::NAME)?;
|
let sessions_tree = db.open_tree(session::NAME)?;
|
||||||
|
|
||||||
let categories: HashMap<categories::K, categories::V> = categories_tree
|
let categories: HashMap<category::K, category::V> = categories_tree
|
||||||
.iter()
|
.iter()
|
||||||
.map(|result| {
|
.map(|result| {
|
||||||
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
|
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
|
||||||
})
|
})
|
||||||
.collect::<Result<Result<_, _>, _>>()??;
|
.collect::<Result<Result<_, _>, _>>()??;
|
||||||
|
|
||||||
let sessions: HashMap<sessions::K, sessions::V> = sessions_tree
|
let sessions: HashMap<session::K, session::V> = sessions_tree
|
||||||
.iter()
|
.iter()
|
||||||
.map(|result| {
|
.map(|result| {
|
||||||
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
|
result.map(|(k, v)| deserialize(&k).and_then(|k| deserialize(&v).map(|v| (k, v))))
|
||||||
@ -193,7 +193,7 @@ pub fn all_stats(_auth: Authorized, db: State<'_, sled::Db>) -> Result<Template,
|
|||||||
|
|
||||||
fn compute_percentage_per_hour<'a, I>(sessions: I) -> BTreeMap<u32, f64>
|
fn compute_percentage_per_hour<'a, I>(sessions: I) -> BTreeMap<u32, f64>
|
||||||
where
|
where
|
||||||
I: Iterator<Item = &'a sessions::V>,
|
I: Iterator<Item = &'a session::V>,
|
||||||
{
|
{
|
||||||
let mut stats_per_hour = BTreeMap::new();
|
let mut stats_per_hour = BTreeMap::new();
|
||||||
for session in sessions {
|
for session in sessions {
|
||||||
@ -282,7 +282,7 @@ mod test {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
sessions::V {
|
session::V {
|
||||||
category: Default::default(),
|
category: Default::default(),
|
||||||
deleted: false,
|
deleted: false,
|
||||||
started: set_hm(today, h1, m1),
|
started: set_hm(today, h1, m1),
|
||||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Reference in New Issue
Block a user