diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..0358936
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,755 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
+dependencies = [
+ "anstyle",
+ "once_cell_polyfill",
+ "windows-sys",
+]
+
+[[package]]
+name = "array-init"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc"
+
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
+[[package]]
+name = "binrw"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d4bca59c20d6f40c2cc0802afbe1e788b89096f61bdf7aeea6bf00f10c2909b"
+dependencies = [
+ "array-init",
+ "binrw_derive",
+ "bytemuck",
+]
+
+[[package]]
+name = "binrw_derive"
+version = "0.14.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8ba42866ce5bced2645bfa15e97eef2c62d2bdb530510538de8dd3d04efff3c"
+dependencies = [
+ "either",
+ "owo-colors",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
+
+[[package]]
+name = "bytemuck"
+version = "1.23.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677"
+
+[[package]]
+name = "cc"
+version = "1.2.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f"
+dependencies = [
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
+
+[[package]]
+name = "chrono"
+version = "0.4.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "wasm-bindgen",
+ "windows-link",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
+[[package]]
+name = "crc16"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "338089f42c427b86394a5ee60ff321da23a5c89c9d89514c829687b26359fcff"
+
+[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
+[[package]]
+name = "glob"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.63"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
+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 = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
+name = "js-sys"
+version = "0.3.77"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.175"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
+
+[[package]]
+name = "log"
+version = "0.4.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
+
+[[package]]
+name = "maple"
+version = "0.1.0"
+dependencies = [
+ "rekordcrate",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
+
+[[package]]
+name = "modular-bitfield"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74"
+dependencies = [
+ "modular-bitfield-impl",
+ "static_assertions",
+]
+
+[[package]]
+name = "modular-bitfield-impl"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[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.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "once_cell_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
+
+[[package]]
+name = "owo-colors"
+version = "3.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
+
+[[package]]
+name = "parse-display"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "287d8d3ebdce117b8539f59411e4ed9ec226e0a4153c7f55495c6070d68e6f72"
+dependencies = [
+ "parse-display-derive",
+ "regex",
+ "regex-syntax",
+]
+
+[[package]]
+name = "parse-display-derive"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fc048687be30d79502dea2f623d052f3a074012c6eac41726b7ab17213616b1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "regex",
+ "regex-syntax",
+ "structmeta",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.101"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quick-xml"
+version = "0.37.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "rekordcrate"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18888593c45eb477d87e28f6c226598bc1286d54a7f67d87cee25d73707bf915"
+dependencies = [
+ "binrw",
+ "chrono",
+ "clap",
+ "crc16",
+ "glob",
+ "modular-bitfield",
+ "parse-display",
+ "quick-xml",
+ "serde",
+ "thiserror",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "serde"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "structmeta"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e1575d8d40908d70f6fd05537266b90ae71b15dbbe7a8b7dffa2b759306d329"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "structmeta-derive",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "structmeta-derive"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "152a0b65a590ff6c3da95cabe2353ee04e6167c896b28e3b14478c2636c922fc"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
+dependencies = [
+ "bumpalo",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.100"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.61.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-link",
+ "windows-result",
+ "windows-strings",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.59.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "windows-link"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
+
+[[package]]
+name = "windows-result"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.53.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
+dependencies = [
+ "windows-link",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
diff --git a/Cargo.toml b/Cargo.toml
index 80ed476..15033fe 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,3 +4,4 @@ version = "0.1.0"
edition = "2024"
[dependencies]
+rekordcrate = "0.3.0"
diff --git a/TODO.md b/TODO.md
index 20d87d3..9201e40 100755
--- a/TODO.md
+++ b/TODO.md
@@ -1,4 +1,4 @@
-[ ] download playlist
-[ ] store everything by artist - album
+[x] download playlist
+[x] store everything by artist - album
[ ] convert flac to mp3
[ ] link files into playlist folders
diff --git a/compose.yaml b/compose.yaml
index e915510..4d26579 100644
--- a/compose.yaml
+++ b/compose.yaml
@@ -1,13 +1,17 @@
services:
slskd:
- image: slskd/slskd
+ image: registry.ntwl.xyz/slskd
+ build:
+ context: .
+ dockerfile: slskd.Dockerfile
+ env_file: .env
ports:
- "5030:5030"
- "5031:5031"
- "50300:50300"
volumes:
- - ./data/slskd:/app/data
- - ./etc/slskd.yml:/app/slskd.yml
+ - ./data/slskd:/data
+ - ./etc/:/app/etc/
maple:
image: registry.ntwl.xyz/maple
@@ -17,7 +21,6 @@ services:
env_file: .env
volumes:
- ./data/maple:/data
- - ./src:/app/src/
- ./etc/:/app/etc/
diff --git a/etc/run_maple.sh b/etc/run_maple.sh
index 77bc854..0d4a94b 100644
--- a/etc/run_maple.sh
+++ b/etc/run_maple.sh
@@ -5,10 +5,14 @@ set -uxe
SLDL_CONF_DIR="/root/.config/sldl/"
SLDL_CONF="$SLDL_CONF_DIR/sldl.conf"
+directories() {
+ mkdir -p $SLDL_CONF_DIR
+ mkdir -p /data/_metadata
+}
+
configure() {
cd /app
- mkdir -p $SLDL_CONF_DIR
envsubst < /app/etc/sldl.tpl.conf > $SLDL_CONF
echo "--------------------------------------------------------------"
@@ -18,10 +22,11 @@ configure() {
}
start() {
- sleep 100000
+ # sleep 100000
}
main() {
+ directories
configure
start
}
diff --git a/etc/run_slskd.sh b/etc/run_slskd.sh
index 1a8a247..1a50407 100644
--- a/etc/run_slskd.sh
+++ b/etc/run_slskd.sh
@@ -2,7 +2,7 @@
set -uxe
-SLDL_CONF_DIR="/slskd/"
+SLDL_CONF_DIR="/app/"
SLDL_CONF="$SLDL_CONF_DIR/slskd.yml"
configure() {
@@ -17,6 +17,12 @@ configure() {
echo "--------------------------------------------------------------"
}
+directories() {
+ mkdir -p /data/downloads
+ mkdir -p /data/incomplete
+ mkdir -p /data/shared
+}
+
run() {
cd /slskd
/usr/bin/tini -- ./start.sh
@@ -24,6 +30,7 @@ run() {
main() {
configure
+ directories
run
}
diff --git a/etc/sldl.tpl.conf b/etc/sldl.tpl.conf
index 828a096..2b76dd3 100644
--- a/etc/sldl.tpl.conf
+++ b/etc/sldl.tpl.conf
@@ -1,14 +1,17 @@
path = "/data"
+index-path = "/data/_metadata/index.sldl.csv"
username = "${SLDL_USER}"
password = "${SLDL_PASS}"
-name-format = "{albumartist(/)album(/)track( )title|(missing-tags/)slsk-foldername(/)slsk-filename}"
-# name-format = "{item-name}/{artist( - )title|filename}"
-
-fast-search = true
-interactive = false
-concurrent-downloads = 4
+name-format = "{artist(/)album(/)track( )title|(_missing_tags/)slsk-foldername(/)slsk-filename}"
pref-format = "flac,mp3"
pref-min-bitrate = 200
pref-max-bitrate = 2500
+
+strict-conditions = true
+fast-search = true
+interactive = false
+no-progress = true
+concurrent-downloads = 4
+
diff --git a/etc/slskd.tpl.yml b/etc/slskd.tpl.yml
index 93f0647..8de7733 100755
--- a/etc/slskd.tpl.yml
+++ b/etc/slskd.tpl.yml
@@ -39,12 +39,12 @@
# permissions:
# file:
# mode: ~ # not for Windows, chmod syntax, e.g. 644, 777. can't escalate beyond umask
-# directories:
-# incomplete: ~
-# downloads: ~
+directories:
+ incomplete: /data/incomplete
+ downloads: /data/downloads
shares:
directories:
- - /app/shared
+ - /data/shared
# filters:
# - \.ini$
# - Thumbs.db$
@@ -177,9 +177,9 @@ web:
# disk: false
# no_color: false
# loki: ~
-# metrics:
-# enabled: false
-# url: /metrics
+metrics:
+ enabled: false
+ url: /metrics
# authentication:
# disabled: false
# username: slskd
diff --git a/etc/slskd.yml b/etc/slskd.yml
deleted file mode 100644
index 729e8d0..0000000
--- a/etc/slskd.yml
+++ /dev/null
@@ -1,302 +0,0 @@
-# debug: false
-# headless: false
-# remote_configuration: false
-# remote_file_management: false
-# instance_name: default
-# flags:
-# no_logo: false
-# no_start: false
-# no_config_watch: false
-# no_connect: false
-# no_share_scan: false
-# force_share_scan: false
-# force_migrations: false
-# no_version_check: false
-# log_sql: false
-# experimental: false
-# volatile: false
-# case_sensitive_reg_ex: false
-# legacy_windows_tcp_keepalive: false
-# optimistic_relay_file_info: false
-# relay:
-# enabled: false
-# mode: controller # controller (default), agent, or debug (for local development)
-# # controller config is required when running in 'agent' mode
-# # this specifies the relay controller that will be controlling this agent
-# controller:
-# address: https://some.site.com:5000
-# ignore_certificate_errors: false
-# api_key:
-# secret:
-# downloads: false
-# # agent config is optional when running in 'controller' mode
-# # this specifies all of the agents capable of connecting
-# agents:
-# my_agent:
-# instance_name: my_agent # make sure the top-level instance_name of the agent matches!
-# secret:
-# cidr: 0.0.0.0/0,::/0
-# permissions:
-# file:
-# mode: ~ # not for Windows, chmod syntax, e.g. 644, 777. can't escalate beyond umask
-# directories:
-# incomplete: ~
-# downloads: ~
-shares:
- directories:
- - /app/shared
-# filters:
-# - \.ini$
-# - Thumbs.db$
-# - \.DS_Store$
-# cache:
-# storage_mode: memory
-# workers: 16
-# retention: ~ # retain indefinitely (do not automatically re-scan)
-# rooms:
-# - ~
-# global:
-# upload:
-# slots: 20
-# speed_limit: 1000 # in kibibytes
-# limits:
-# queued:
-# files: 500
-# megabytes: 5000
-# daily:
-# files: 1000
-# megabytes: 10000
-# failures: 200
-# weekly:
-# files: 5000
-# megabytes: 50000
-# failures: 1000
-# download:
-# slots: 500
-# speed_limit: 1000
-# groups:
-# default:
-# upload:
-# priority: 500
-# strategy: roundrobin
-# slots: 10
-# limits:
-# queued:
-# files: 150
-# megabytes: 1500
-# daily: ~ # no daily limits (weekly still apply)
-# weekly:
-# files: 1500
-# megabytes: 15000
-# failures: 150
-# leechers:
-# thresholds:
-# files: 1
-# directories: 1
-# upload:
-# priority: 999
-# strategy: roundrobin
-# slots: 1
-# speed_limit: 100
-# limits:
-# queued:
-# files: 15
-# megabytes: 150
-# daily:
-# files: 30
-# megabytes: 300
-# failures: 10
-# weekly:
-# files: 150
-# megabytes: 1500
-# failures: 30
-# blacklisted:
-# members:
-# -
-# cidrs:
-# -
-# user_defined:
-# my_buddies:
-# upload:
-# priority: 250
-# strategy: firstinfirstout
-# slots: 10
-# limits:
-# queued:
-# files: 1000 # override global default
-# members:
-# - alice
-# - bob
-# blacklist:
-# enabled: true
-# file:
-# filters:
-# search:
-# request:
-# - ^.{1,2}$
-web:
- port: 5030
- https:
- disabled: false
- port: 5031
- force: false
- certificate:
- pfx: ~
- password: ~
- url_base: /
- content_path: wwwroot
- logging: false
- authentication:
- disabled: false
- username: ${SLSKD_WEB_USER}
- password: ${SLSKD_WEB_PASS}
-# jwt:
-# key: ~
-# ttl: 604800000
-# api_keys:
-# my_api_key:
-# key:
-# role: readonly # readonly, readwrite, administrator
-# cidr: 0.0.0.0/0,::/0
-# retention:
-# search: 10080 # 7 days, in minutes
-# transfers:
-# upload:
-# succeeded: 1440 # 1 day, in minutes
-# errored: 30
-# cancelled: 5
-# download:
-# succeeded: 1440 # 1 day, in minutes
-# errored: 20160 # 2 weeks, in minutes
-# cancelled: 5
-# files:
-# complete: 20160 # 2 weeks, in minutes
-# incomplete: 43200 # 30 days, in minutes
-# logs: 180 # days
-# logger:
-# disk: false
-# no_color: false
-# loki: ~
-# metrics:
-# enabled: false
-# url: /metrics
-# authentication:
-# disabled: false
-# username: slskd
-# password: slskd
-# feature:
-# swagger: false
-soulseek:
- address: vps.slsknet.org
- port: 2271
- username: ntwl
- password: "ninety nonsense nights"
-# description: |
-# A slskd user. https://github.com/slskd/slskd
-# picture: path/to/slsk-profile-picture.jpg
-# listen_ip_address: 0.0.0.0
-# listen_port: 50300
-# diagnostic_level: Info
-# distributed_network:
-# disabled: false
-# disable_children: false
-# child_limit: 25
-# logging: false
-# connection:
-# timeout:
-# connect: 10000
-# inactivity: 15000
-# buffer:
-# read: 16384
-# write: 16384
-# transfer: 262144
-# write_queue: 250
-# proxy:
-# enabled: false
-# address: ~
-# port: ~
-# username: ~
-# password: ~
-# integration:
-# webhooks:
-# my_webhook:
-# on:
-# - DownloadFileComplete
-# call:
-# url: https://192.168.1.42:8080/slskd_webhook
-# headers:
-# - name: X-API-Key
-# value: foobar1234
-# - name: Authorization
-# value: Bearer eyJ...ssw5c
-# - name: User-Agent
-# value: slskd/0.0
-# ignore_certificate_errors: false
-# timeout: 5000 # in milliseconds
-# retry:
-# attempts: 3
-# scripts:
-# run_command_with_linux_system_shell: # automatically uses the executable defined in $SHELL
-# on:
-# - DownloadFileComplete
-# run:
-# command: 'echo "$SLSKD_SCRIPT_DATA" >> linux_system_shell.txt'
-# run_with_sh:
-# on:
-# - DownloadFileComplete
-# run:
-# executable: /bin/sh
-# args: '-c "echo $SLSKD_SCRIPT_DATA >> linux_sh.txt"'
-# run_with_sh_and_args_list:
-# on:
-# - DownloadFileComplete
-# run:
-# executable: /bin/sh
-# arglist:
-# - -c
-# - echo $SLSKD_SCRIPT_DATA >> linux_sh_and_args_list.txt
-# run_command_with_windows_system_shell: # automatically uses cmd.exe (included with all Windows installs)
-# on:
-# - DownloadFileComplete
-# run:
-# command: 'echo "%SLSKD_SCRIPT_DATA%" >> windows_system_shell.txt'
-# run_with_windows_cmd:
-# on:
-# - DownloadFileComplete
-# run:
-# executable: cmd.exe
-# args: '/c "echo "%SLSKD_SCRIPT_DATA%" >> windows_cmd.txt"'
-# run_with_windows_git_bash:
-# on:
-# - DownloadFileComplete
-# run:
-# executable: C:\Program Files\Git\bin\bash.exe
-# args: '-c "echo "$SLSKD_SCRIPT_DATA" >> windows_git_bash.txt"'
-# run_with_windows_cmd_and_args_list:
-# on:
-# - DownloadFileComplete
-# run:
-# executable: cmd.exe
-# arglist:
-# - /c
-# - 'echo "%SLSKD_SCRIPT_DATA%" >> windows_cmd_and_args_list.txt'
-# ftp:
-# enabled: false
-# address: ~
-# port: ~
-# username: ~
-# password: ~
-# remote_path: /
-# encryption_mode: auto
-# ignore_certificate_errors: false
-# overwrite_existing: true
-# connection_timeout: 5000
-# retry_attempts: 3
-# pushbullet:
-# enabled: false
-# access_token: ~
-# notification_prefix: "From slskd:"
-# notify_on_private_message: true
-# notify_on_room_mention: true
-# retry_attempts: 3
-# cooldown_time: 900000
\ No newline at end of file
diff --git a/justfile b/justfile
index 2c1fb1a..a9d6a5a 100644
--- a/justfile
+++ b/justfile
@@ -1,5 +1,11 @@
set dotenv-load
+ctr := "maple"
+bin := "bash"
+
+ls:
+ just --list
+
up:
docker compose -f compose.yaml up --remove-orphans
@@ -9,13 +15,13 @@ down:
build:
docker compose -f compose.yaml build
-run CTR:
- docker compose -f compose.yaml run {{CTR}} bash
+run:
+ docker compose -f compose.yaml run {{ctr}} {{bin}}
-exec CTR:
- docker compose -f compose.yaml exec {{CTR}} bash
+exec:
+ docker compose -f compose.yaml exec {{ctr}} {{bin}}
-dl TRG:
+dl trg:
docker compose -f compose.yaml run \
--remove-orphans \
- maple -- sldl {{TRG}}
+ maple -- sldl {{trg}}
diff --git a/slskd.Dockerfile b/slskd.Dockerfile
index a952c23..766bdbb 100644
--- a/slskd.Dockerfile
+++ b/slskd.Dockerfile
@@ -1,5 +1,6 @@
FROM slskd/slskd
-RUN apk add envsubst
+RUN apt-get update
+RUN apt-get install -y gettext-base
ENTRYPOINT ["bash", "/app/etc/run_slskd.sh"]
\ No newline at end of file