Compare commits
10 Commits
d3c3592e67
...
125091c76d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
125091c76d | ||
|
|
1943b5b1f6 | ||
|
|
c4860b812b | ||
|
|
be2e430fcc | ||
|
|
f23c92628d | ||
|
|
d35372b20a | ||
|
|
5ad0135deb | ||
|
|
19a0d53624 | ||
|
|
7670e6f3ae | ||
|
|
789a3566bf |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1 +1,6 @@
|
||||
/target
|
||||
|
||||
/*.txt
|
||||
|
||||
/players.redb
|
||||
/players.json
|
||||
|
||||
465
Cargo.lock
generated
465
Cargo.lock
generated
@@ -97,6 +97,26 @@ dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
|
||||
dependencies = [
|
||||
"bincode_derive",
|
||||
"serde",
|
||||
"unty",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bincode_derive"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
|
||||
dependencies = [
|
||||
"virtue",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.1"
|
||||
@@ -203,13 +223,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "713c6293af093c202ad318e8f7bdc1de1a36d7a793bb77f7fc6bd6f1788659a9"
|
||||
dependencies = [
|
||||
"compio-buf",
|
||||
"compio-dispatcher",
|
||||
"compio-driver",
|
||||
"compio-fs",
|
||||
"compio-io",
|
||||
"compio-log",
|
||||
"compio-macros",
|
||||
"compio-net",
|
||||
"compio-process",
|
||||
"compio-quic",
|
||||
"compio-runtime",
|
||||
"compio-signal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -223,6 +247,18 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compio-dispatcher"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cdf8c613be826be410d8744ab30acc49cc5134a78e2aa25efae9efa44bed6a7"
|
||||
dependencies = [
|
||||
"compio-driver",
|
||||
"compio-runtime",
|
||||
"flume",
|
||||
"futures-channel",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compio-driver"
|
||||
version = "0.8.1"
|
||||
@@ -237,10 +273,13 @@ dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-queue",
|
||||
"futures-util",
|
||||
"io-uring",
|
||||
"io_uring_buf_ring",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"paste",
|
||||
"polling",
|
||||
"slab",
|
||||
"socket2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
@@ -314,6 +353,43 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compio-process"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3867cfe7b23eaae89ff815aba4fdde61cb6fd55f81fd368128300c6b7e645016"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compio-buf",
|
||||
"compio-driver",
|
||||
"compio-io",
|
||||
"compio-runtime",
|
||||
"futures-util",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compio-quic"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f107e044329f1e171930801b09bfc6e764c5e171e45c7a3e382f98561da619a"
|
||||
dependencies = [
|
||||
"cfg_aliases",
|
||||
"compio-buf",
|
||||
"compio-io",
|
||||
"compio-log",
|
||||
"compio-net",
|
||||
"compio-runtime",
|
||||
"flume",
|
||||
"futures-util",
|
||||
"libc",
|
||||
"quinn-proto",
|
||||
"rustc-hash",
|
||||
"rustls",
|
||||
"thiserror 2.0.12",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compio-runtime"
|
||||
version = "0.8.1"
|
||||
@@ -330,10 +406,27 @@ dependencies = [
|
||||
"libc",
|
||||
"once_cell",
|
||||
"scoped-tls",
|
||||
"slab",
|
||||
"socket2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compio-signal"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03d2931880b03b33d4df7d2b8a008e93731366d185358c7442fc8d24d5f9c1bd"
|
||||
dependencies = [
|
||||
"compio-buf",
|
||||
"compio-driver",
|
||||
"compio-runtime",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"os_pipe",
|
||||
"slab",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "2.5.0"
|
||||
@@ -407,6 +500,16 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46f93780a459b7d656ef7f071fe699c4d3d2cb201c4b24d085b6ddc505276e73"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curl"
|
||||
version = "0.4.48"
|
||||
@@ -493,6 +596,18 @@ dependencies = [
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flume"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"nanorand",
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.31"
|
||||
@@ -562,6 +677,33 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasi 0.14.2+wasi-0.2.4",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
@@ -651,6 +793,28 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io_uring_buf_ring"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a8867874ff5758b47c1dac069e6e86541432f9da8be9111c5e94154134f07d0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"io-uring",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.16"
|
||||
@@ -718,6 +882,12 @@ version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "lru-slab"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
|
||||
|
||||
[[package]]
|
||||
name = "md5"
|
||||
version = "0.8.0"
|
||||
@@ -745,6 +915,38 @@ dependencies = [
|
||||
"adler2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanorand"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||
dependencies = [
|
||||
"getrandom 0.2.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
@@ -986,6 +1188,15 @@ dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "3.3.0"
|
||||
@@ -1004,6 +1215,26 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn-proto"
|
||||
version = "0.11.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"getrandom 0.3.3",
|
||||
"lru-slab",
|
||||
"rand",
|
||||
"ring",
|
||||
"rustc-hash",
|
||||
"rustls-pki-types",
|
||||
"slab",
|
||||
"thiserror 2.0.12",
|
||||
"tinyvec",
|
||||
"tracing",
|
||||
"web-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
@@ -1013,6 +1244,50 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "5.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||
dependencies = [
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
|
||||
dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redb"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fef838cd981b5c46e9e91e20e4623e43b29b5c251eb245b34da0cbd2da09ab27"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ref-cast"
|
||||
version = "1.0.24"
|
||||
@@ -1033,12 +1308,32 @@ dependencies = [
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom 0.2.16",
|
||||
"libc",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
@@ -1061,6 +1356,40 @@ dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
|
||||
dependencies = [
|
||||
"web-time",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.21"
|
||||
@@ -1099,9 +1428,11 @@ name = "sdgb-api"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"bincode",
|
||||
"cbc",
|
||||
"chrono",
|
||||
"cipher",
|
||||
"compio",
|
||||
"digest",
|
||||
"flate2",
|
||||
"hmac-sha256",
|
||||
@@ -1110,7 +1441,9 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"snafu",
|
||||
"spdlog-rs",
|
||||
"strum 0.27.2",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1118,13 +1451,17 @@ name = "sdgb-cli"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"compio",
|
||||
"ctrlc",
|
||||
"futures-util",
|
||||
"nyquest-preset",
|
||||
"palc",
|
||||
"redb",
|
||||
"sdgb-api",
|
||||
"serde_json",
|
||||
"snafu",
|
||||
"spdlog-rs",
|
||||
"strum 0.27.2",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1308,6 +1645,12 @@ dependencies = [
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
@@ -1370,6 +1713,47 @@ dependencies = [
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec_macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.47.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"io-uring",
|
||||
"libc",
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
"tokio-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.11"
|
||||
@@ -1402,6 +1786,9 @@ name = "tracing-core"
|
||||
version = "0.1.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
@@ -1415,6 +1802,18 @@ version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "unty"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
@@ -1427,6 +1826,27 @@ version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "virtue"
|
||||
version = "0.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.14.2+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
|
||||
dependencies = [
|
||||
"wit-bindgen-rt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.100"
|
||||
@@ -1485,6 +1905,16 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-time"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "1.2.0"
|
||||
@@ -1788,3 +2218,38 @@ checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rt"
|
||||
version = "0.39.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
|
||||
|
||||
@@ -3,11 +3,18 @@ members = ["sdgb-api", "sdgb-cli"]
|
||||
resolver = "3"
|
||||
|
||||
[workspace.dependencies]
|
||||
sdgb-api = { path = "./sdgb-api" }
|
||||
sdgb-api = { path = "./sdgb-api", default-features = false }
|
||||
|
||||
spdlog-rs = { version = "0.4.3", default-features = false, features = [
|
||||
"level-debug",
|
||||
"release-level-info",
|
||||
] }
|
||||
|
||||
snafu = { version = "0.8.6", features = ["backtrace", "rust_1_81"] }
|
||||
serde_json = "1.0.141"
|
||||
strum = { version = "0.27.2", features = ["derive"] }
|
||||
tokio = { version = "1", features = ["rt-multi-thread"] }
|
||||
compio = { version = "0.15.0", features = ["runtime"] }
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
@@ -5,10 +5,19 @@ edition = "2024"
|
||||
|
||||
license = "GPL-3.0"
|
||||
|
||||
[features]
|
||||
default = ["compio", "bincode"]
|
||||
compio = ["dep:compio"]
|
||||
tokio = ["dep:tokio"]
|
||||
bincode = ["dep:bincode"]
|
||||
|
||||
[dependencies]
|
||||
snafu = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
strum = {workspace = true}
|
||||
strum = { workspace = true }
|
||||
tokio = { workspace = true, optional = true }
|
||||
compio = { workspace = true, optional = true }
|
||||
spdlog-rs = { workspace = true }
|
||||
|
||||
# hashing
|
||||
digest = "0.10.7"
|
||||
@@ -26,6 +35,7 @@ serde = { version = "1.0.219", features = ["derive"] }
|
||||
|
||||
# compression / encryption
|
||||
flate2 = "1.1.2"
|
||||
cbc = "0.1.2"
|
||||
cbc = { version = "0.1.2", features = ["alloc"] }
|
||||
aes = "0.8.4"
|
||||
cipher = { version = "0.4.4", features = ["block-padding"] }
|
||||
bincode = { version = "2.0.1", optional = true }
|
||||
|
||||
22
sdgb-api/benches/enc_dec.rs
Normal file
22
sdgb-api/benches/enc_dec.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
#![feature(test)]
|
||||
extern crate test;
|
||||
|
||||
use sdgb_api::title::{MaiVersionExt, Sdgb1_50};
|
||||
|
||||
#[bench]
|
||||
pub fn sdgb_150_enc_short(b: &mut test::Bencher) {
|
||||
b.iter(|| _ = Sdgb1_50::encode(b"Hello world"));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn sdgb_150_enc_4k(b: &mut test::Bencher) {
|
||||
let data = [1u8; 4096];
|
||||
b.iter(|| _ = Sdgb1_50::encode(data));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn sdgb_150_dec_4k(b: &mut test::Bencher) {
|
||||
let data = [1u8; 4096];
|
||||
let enc_data = Sdgb1_50::encode(data).unwrap();
|
||||
b.iter(|| _ = Sdgb1_50::decode(enc_data.clone()));
|
||||
}
|
||||
@@ -3,24 +3,36 @@ use snafu::Snafu;
|
||||
|
||||
#[derive(Debug, Snafu)]
|
||||
pub enum ApiError {
|
||||
JoinError,
|
||||
|
||||
#[snafu(display("api returned nothing!"))]
|
||||
EmptyResponse,
|
||||
#[snafu(display("encrypt data: {error}"))]
|
||||
Pad { error: PadError },
|
||||
Pad {
|
||||
error: PadError,
|
||||
},
|
||||
#[snafu(display("decrypt data: {error}"))]
|
||||
Unpad { error: UnpadError },
|
||||
Unpad {
|
||||
error: UnpadError,
|
||||
},
|
||||
|
||||
#[snafu(display("io error: {source}"))]
|
||||
#[snafu(context(false))]
|
||||
IO { source: std::io::Error },
|
||||
IO {
|
||||
source: std::io::Error,
|
||||
},
|
||||
|
||||
#[snafu(display("json error: {source}"))]
|
||||
#[snafu(context(false))]
|
||||
JSON { source: serde_json::Error },
|
||||
JSON {
|
||||
source: serde_json::Error,
|
||||
},
|
||||
|
||||
#[snafu(display("request error: {source}"))]
|
||||
#[snafu(context(false))]
|
||||
Request { source: nyquest::Error },
|
||||
Request {
|
||||
source: nyquest::Error,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<UnpadError> for ApiError {
|
||||
|
||||
@@ -4,3 +4,5 @@ pub mod title;
|
||||
|
||||
mod error;
|
||||
pub use error::ApiError;
|
||||
|
||||
pub use bincode;
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
use std::io::{Read, Write as _};
|
||||
use std::io::Write as _;
|
||||
|
||||
use aes::cipher::{
|
||||
BlockDecryptMut, BlockEncryptMut, BlockSizeUser, KeyIvInit, block_padding::Pkcs7,
|
||||
};
|
||||
|
||||
use digest::generic_array::GenericArray;
|
||||
use flate2::write::ZlibEncoder;
|
||||
use flate2::{Compression, read::ZlibDecoder};
|
||||
use flate2::Compression;
|
||||
use flate2::write::{ZlibDecoder, ZlibEncoder};
|
||||
use spdlog::debug;
|
||||
|
||||
use crate::error::ApiError;
|
||||
use crate::title::{MaiVersion, MaiVersionExt, Sdgb1_40, Sdgb1_50};
|
||||
|
||||
impl MaiVersionExt for Sdgb1_40 {
|
||||
fn decode(mut data: impl AsMut<[u8]>) -> Result<Vec<u8>, ApiError> {
|
||||
let mut decompressed = decompress(data.as_mut());
|
||||
fn decode(data: impl AsRef<[u8]>) -> Result<Vec<u8>, ApiError> {
|
||||
let mut decompressed = decompress(data.as_ref());
|
||||
if decompressed.is_empty() {
|
||||
return Err(ApiError::EmptyResponse);
|
||||
}
|
||||
@@ -41,14 +41,20 @@ impl MaiVersionExt for Sdgb1_40 {
|
||||
}
|
||||
|
||||
impl MaiVersionExt for Sdgb1_50 {
|
||||
fn decode(mut data: impl AsMut<[u8]>) -> Result<Vec<u8>, ApiError> {
|
||||
if data.as_mut().is_empty() {
|
||||
fn decode(data: impl AsRef<[u8]>) -> Result<Vec<u8>, ApiError> {
|
||||
let mut data = data.as_ref().to_vec();
|
||||
if data.is_empty() {
|
||||
return Err(ApiError::EmptyResponse);
|
||||
}
|
||||
|
||||
let decrypted = decrypt(&mut data, Self::AES_KEY, Self::AES_IV)?;
|
||||
let decompressed = decompress(decrypted);
|
||||
Ok(decompressed)
|
||||
if data.len() % 16 != 0 {
|
||||
let pad = 16 - (data.len() % 16);
|
||||
data.resize(data.len() + pad, pad as _);
|
||||
}
|
||||
|
||||
debug!("data size: {}", data.len());
|
||||
let decrypted = decrypt_vec(&data, Self::AES_KEY, Self::AES_IV)?;
|
||||
Ok(decompress(decrypted))
|
||||
}
|
||||
|
||||
fn encode(data: impl AsRef<[u8]>) -> Result<Vec<u8>, ApiError> {
|
||||
@@ -72,8 +78,9 @@ fn compress(data: impl AsRef<[u8]>) -> Result<Vec<u8>, ApiError> {
|
||||
|
||||
fn decompress(data: impl AsRef<[u8]>) -> Vec<u8> {
|
||||
let mut buf = Vec::with_capacity(data.as_ref().len() * 2);
|
||||
let mut decode = ZlibDecoder::new(data.as_ref());
|
||||
_ = decode.read_to_end(&mut buf);
|
||||
let mut decode = ZlibDecoder::new(&mut buf);
|
||||
_ = decode.write_all(data.as_ref());
|
||||
_ = decode.finish();
|
||||
buf
|
||||
}
|
||||
|
||||
@@ -104,6 +111,13 @@ fn decrypt<'ct>(
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn decrypt_vec(data: impl AsRef<[u8]>, key: &[u8; 32], iv: &[u8; 16]) -> Result<Vec<u8>, ApiError> {
|
||||
let key = GenericArray::from_slice(key);
|
||||
let iv = GenericArray::from_slice(iv);
|
||||
let decryptor = Aes256CbcDec::new(key, iv);
|
||||
Ok(decryptor.decrypt_padded_vec_mut::<Pkcs7>(data.as_ref())?)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod _tests {
|
||||
|
||||
@@ -148,4 +162,62 @@ mod _tests {
|
||||
assert_eq!(enc, data);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// FIXME: user data decryption
|
||||
#[test]
|
||||
fn test_user_data_dec() -> Result<(), ApiError> {
|
||||
let data = [
|
||||
112, 133, 192, 229, 116, 195, 219, 220, 56, 176, 98, 148, 246, 73, 179, 157, 181, 251,
|
||||
9, 7, 190, 113, 101, 8, 144, 58, 23, 196, 16, 176, 78, 96, 106, 53, 191, 118, 86, 247,
|
||||
50, 250, 168, 155, 164, 108, 7, 152, 251, 123, 186, 121, 113, 41, 104, 79, 29, 71, 47,
|
||||
228, 214, 97, 223, 29, 27, 163, 159, 113, 82, 45, 29, 41, 176, 246, 33, 235, 22, 202,
|
||||
1, 61, 133, 126, 8, 20, 9, 214, 153, 11, 203, 207, 5, 195, 129, 172, 70, 81, 58, 156,
|
||||
240, 87, 203, 137, 110, 183, 245, 177, 210, 63, 231, 136, 82, 97, 201, 184, 236, 117,
|
||||
89, 85, 22, 29, 2, 238, 250, 148, 158, 151, 139, 179, 9, 42, 47, 220, 88, 137, 135,
|
||||
139, 57, 35, 0, 50, 123, 133, 103, 15, 87, 86, 208, 203, 235, 153, 214, 87, 236, 46,
|
||||
78, 50, 72, 50, 8, 46, 30, 242, 44, 184, 72, 118, 51, 120, 99, 158, 247, 255, 168, 181,
|
||||
119, 156, 214, 143, 253, 185, 21, 76, 117, 201, 38, 38, 79, 171, 8, 251, 90, 53, 59,
|
||||
89, 30, 136, 69, 168, 57, 34, 115, 145, 159, 110, 182, 5, 126, 208, 202, 216, 92, 200,
|
||||
168, 63, 114, 119, 129, 38, 139, 189, 101, 215, 102, 76, 29, 228, 219, 46, 79, 166,
|
||||
127, 194, 60, 183, 169, 167, 210, 120, 77, 219, 58, 16, 231, 233, 189, 66, 215, 202,
|
||||
28, 209, 59, 192, 141, 91, 65, 17, 187, 88, 189, 149, 139, 48, 237, 152, 161, 87, 120,
|
||||
99, 2, 50, 12, 120, 179, 50, 235, 255, 223, 162, 216, 84, 13, 135, 196, 131, 121, 97,
|
||||
171, 106, 240, 189, 112, 92, 41, 59, 204, 24, 72, 91, 14, 220, 249, 10, 166, 4, 254,
|
||||
183, 194, 227, 53, 163, 35, 165, 253, 149, 83, 253, 191, 138, 236, 208, 146, 242, 31,
|
||||
185, 152, 226, 100, 191, 2, 2, 82, 101, 141, 31, 71, 106, 2, 83, 1, 231, 140, 20, 16,
|
||||
156, 171, 108, 109, 14, 93, 168, 203, 50, 20, 21, 142, 135, 97, 7, 80, 61, 110, 76,
|
||||
152, 106, 231, 100, 78, 187, 28, 39, 191, 10, 206, 78, 127, 79, 247, 192, 164, 51, 237,
|
||||
9, 63, 201, 7, 27, 81, 243, 88, 30, 244, 205, 57, 14, 126, 60, 61, 173, 21, 84, 15,
|
||||
105, 38, 239, 249, 82, 202, 245, 219, 88, 195, 112, 113, 40, 60, 76, 10, 243, 232, 52,
|
||||
27, 0, 84, 247, 85, 140, 99, 140, 165, 145, 140, 96, 55, 0, 174, 155, 241, 166, 252,
|
||||
150, 87, 106, 42, 58, 33, 154, 222, 83, 69, 172, 226, 216, 108, 115, 203, 38, 133, 43,
|
||||
171, 172, 78, 142, 70, 78, 186, 146, 24, 126, 203, 106, 221, 144, 17, 32, 42, 186, 125,
|
||||
134, 186, 174, 214, 137, 212, 234, 202, 79, 241, 28, 222, 98, 83, 76, 254, 90, 210, 12,
|
||||
141, 40, 191, 123, 143, 170, 154, 39, 137, 222, 224, 241, 61, 136, 184, 104, 106, 209,
|
||||
184, 128, 30, 95, 36, 250, 163, 47, 82, 19, 121, 123, 134, 142, 31, 170, 23, 148, 20,
|
||||
80, 157, 252, 103, 192, 204, 229, 10, 66, 84, 49, 21, 197, 110, 208, 202, 124, 217,
|
||||
117, 19, 190, 241, 154, 178, 83, 37, 175, 209, 52, 228, 219, 137, 238, 146, 111, 228,
|
||||
254, 89, 219, 49, 85, 30, 214, 162, 234, 138, 122, 9, 93, 164, 133, 136, 160, 75, 118,
|
||||
87, 14, 170, 92, 109, 244, 40, 234, 40, 216, 72, 207, 81, 161, 252, 252, 0, 38, 206,
|
||||
123, 212, 93, 252, 225, 205, 16, 5, 197, 59, 93, 100, 56, 93, 125, 214, 150, 133, 208,
|
||||
12, 0, 226, 246, 94, 62, 235, 164, 48, 134, 205, 77, 14, 107, 162, 60, 23, 150, 47,
|
||||
198, 5, 214, 125, 12, 150, 63, 128, 95, 237, 209, 55, 5, 11, 59, 187, 0, 254, 180, 226,
|
||||
126, 88, 87, 172, 38, 169, 27, 25, 92, 204, 24, 103, 78, 226, 65, 163, 114, 16, 202,
|
||||
31, 160, 182, 100, 226, 15, 64, 5, 71, 117, 237, 31, 145, 250, 97, 105, 103, 67, 243,
|
||||
2, 208, 60, 72, 16, 199, 57, 170, 99, 151, 62, 100, 53, 23, 45, 123, 225, 170, 149, 65,
|
||||
26, 142, 240, 82, 214, 88, 93, 100, 158, 84, 42, 5, 112, 165, 194, 1, 160, 149, 103,
|
||||
238, 63, 75, 3, 134, 113, 197, 251, 251, 90, 34, 184, 248, 214, 183, 168, 135, 4, 169,
|
||||
134, 194, 106, 83, 108, 176, 26, 159, 80, 143, 105, 111, 53, 4, 1, 240, 44, 240, 149,
|
||||
118, 189, 208, 190, 235, 145, 166, 163, 231, 158, 219, 221, 208, 61, 158, 132, 39, 75,
|
||||
235, 36, 199, 169, 34, 119, 150, 223, 74, 5, 107, 123, 132, 116, 97, 241, 53, 43, 238,
|
||||
115, 189, 195, 124, 127, 172, 5, 109, 112, 149, 190, 19, 202, 253, 171, 53, 105, 123,
|
||||
173, 50, 50, 145, 56, 232, 13, 169, 47, 60, 112, 35, 100, 205, 35, 142, 5, 198, 235,
|
||||
206, 112, 145, 99, 21, 214, 1, 184, 57, 125, 87, 245, 204, 162, 167, 124, 18, 154, 49,
|
||||
25, 144, 181, 58, 184, 212, 59, 252, 72, 167, 228, 60, 118, 113, 65, 50, 150, 235, 163,
|
||||
121, 215, 82, 91, 100, 78, 54, 199, 238, 93, 21, 21, 29, 215, 18, 201, 205, 106, 211,
|
||||
78, 141, 155,
|
||||
];
|
||||
let _ = Sdgb1_50::decode(data)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,5 +59,9 @@ mod _test {
|
||||
Sdgb1_50::api_hash(APIMethod::GetUserPreviewApi),
|
||||
"004cf848f96d393a5f2720101e30b93d"
|
||||
);
|
||||
assert_eq!(
|
||||
Sdgb1_50::api_hash(APIMethod::GetUserDataApi),
|
||||
"3af1e5b298bb5b7379c94934b2e038c5"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ use nyquest::{
|
||||
header::{ACCEPT_ENCODING, CONTENT_ENCODING, EXPECT, USER_AGENT},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use spdlog::debug;
|
||||
|
||||
pub trait MaiVersion {
|
||||
const AES_KEY: &[u8; 32];
|
||||
@@ -24,7 +25,7 @@ pub trait MaiVersion {
|
||||
|
||||
pub trait MaiVersionExt: MaiVersion {
|
||||
fn encode(data: impl AsRef<[u8]>) -> Result<Vec<u8>, ApiError>;
|
||||
fn decode(data: impl AsMut<[u8]>) -> Result<Vec<u8>, ApiError>;
|
||||
fn decode(data: impl AsRef<[u8]>) -> Result<Vec<u8>, ApiError>;
|
||||
|
||||
fn api_hash(api: APIMethod) -> String {
|
||||
let api_name: &str = api.into();
|
||||
@@ -37,11 +38,7 @@ pub trait MaiVersionExt: MaiVersion {
|
||||
format!("{digest:x}")
|
||||
}
|
||||
|
||||
fn api_request<D>(
|
||||
api: APIMethod,
|
||||
agent_extra: impl Display,
|
||||
data: D,
|
||||
) -> Result<Request, ApiError>
|
||||
fn api_call<D>(api: APIMethod, agent_extra: impl Display, data: D) -> Result<Request, ApiError>
|
||||
where
|
||||
D: Serialize,
|
||||
{
|
||||
@@ -66,16 +63,28 @@ pub trait MaiVersionExt: MaiVersion {
|
||||
fn request_raw<D>(
|
||||
client: &AsyncClient,
|
||||
api: APIMethod,
|
||||
agent_extra: impl Display,
|
||||
agent_extra: impl Display + Send + 'static,
|
||||
data: D,
|
||||
) -> impl Future<Output = Result<Vec<u8>, ApiError>>
|
||||
where
|
||||
D: Serialize,
|
||||
D: Serialize + Send + 'static,
|
||||
{
|
||||
#[cfg(feature = "compio")]
|
||||
use compio::runtime::spawn_blocking;
|
||||
#[cfg(feature = "tokio")]
|
||||
use tokio::task::spawn_blocking;
|
||||
|
||||
async {
|
||||
let req = Self::api_request(api, agent_extra, data)?;
|
||||
let req = spawn_blocking(move || Self::api_call(api, agent_extra, data))
|
||||
.await
|
||||
.map_err(|_| ApiError::JoinError)??;
|
||||
let data = client.request(req).await?.bytes().await?;
|
||||
let decoded = Self::decode(data)?;
|
||||
|
||||
debug!("received: {data:?}");
|
||||
|
||||
let decoded = spawn_blocking(move || Self::decode(data))
|
||||
.await
|
||||
.map_err(|_| ApiError::JoinError)??;
|
||||
Ok(decoded)
|
||||
}
|
||||
}
|
||||
@@ -83,11 +92,11 @@ pub trait MaiVersionExt: MaiVersion {
|
||||
fn request<D, R>(
|
||||
client: &AsyncClient,
|
||||
api: APIMethod,
|
||||
agent_extra: impl Display,
|
||||
agent_extra: impl Display + Send + 'static,
|
||||
data: D,
|
||||
) -> impl Future<Output = Result<R, ApiError>>
|
||||
where
|
||||
D: Serialize,
|
||||
D: Serialize + Send + 'static,
|
||||
R: for<'a> Deserialize<'a>,
|
||||
{
|
||||
async {
|
||||
|
||||
153
sdgb-api/src/title/model/get_user_data_api/mod.rs
Normal file
153
sdgb-api/src/title/model/get_user_data_api/mod.rs
Normal file
@@ -0,0 +1,153 @@
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GetUserDataApi {
|
||||
pub user_id: u32,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GetUserDataApiResp {
|
||||
pub user_id: u32,
|
||||
pub user_data: UserData,
|
||||
pub ban_state: u32,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UserData {
|
||||
/// your username, in full-width character
|
||||
pub user_name: String,
|
||||
/// should be `1`
|
||||
pub is_net_member: i64,
|
||||
/// maimile, 舞里程
|
||||
pub point: i64,
|
||||
/// 总获取过舞里程
|
||||
pub total_point: i64,
|
||||
/// DX RATING
|
||||
pub player_rating: i64,
|
||||
pub music_rating: i64,
|
||||
/// B35
|
||||
pub player_old_rating: i64,
|
||||
/// B15
|
||||
pub player_new_rating: i64,
|
||||
/// highest total dx rating
|
||||
pub highest_rating: i64,
|
||||
pub grade_rating: i64,
|
||||
/// 级别认定
|
||||
pub grade_rank: i64,
|
||||
/// 段位认定
|
||||
pub course_rank: i64,
|
||||
/// 友人对战段位
|
||||
pub class_rank: i64,
|
||||
pub nameplate_id: i64,
|
||||
pub frame_id: i64,
|
||||
pub icon_id: i64,
|
||||
pub trophy_id: i64,
|
||||
pub plate_id: i64,
|
||||
pub title_id: i64,
|
||||
pub partner_id: i64,
|
||||
pub chara_slot: Vec<i64>,
|
||||
pub chara_lock_slot: Vec<i64>,
|
||||
pub content_bit: i64,
|
||||
pub select_map_id: i64,
|
||||
/// 总游玩次数
|
||||
pub play_count: i64,
|
||||
/// 当前版本游玩次数
|
||||
pub current_play_count: i64,
|
||||
pub play_vs_count: i64,
|
||||
pub play_sync_count: i64,
|
||||
pub win_count: i64,
|
||||
pub help_count: i64,
|
||||
pub combo_count: i64,
|
||||
/// 总 DX 分数
|
||||
pub total_deluxscore: i64,
|
||||
/// 绿 DX 分数
|
||||
pub total_basic_deluxscore: i64,
|
||||
/// 黄 DX 分数
|
||||
pub total_advanced_deluxscore: i64,
|
||||
/// 红 DX 分数
|
||||
pub total_expert_deluxscore: i64,
|
||||
/// 紫 DX 分数
|
||||
pub total_master_deluxscore: i64,
|
||||
/// 白 DX 分数
|
||||
pub total_re_master_deluxscore: i64,
|
||||
/// 总 Sync
|
||||
pub total_sync: i64,
|
||||
pub total_basic_sync: i64,
|
||||
pub total_advanced_sync: i64,
|
||||
pub total_expert_sync: i64,
|
||||
pub total_master_sync: i64,
|
||||
pub total_re_master_sync: i64,
|
||||
pub total_achievement: i64,
|
||||
pub total_basic_achievement: i64,
|
||||
pub total_advanced_achievement: i64,
|
||||
pub total_expert_achievement: i64,
|
||||
pub total_master_achievement: i64,
|
||||
pub total_re_master_achievement: i64,
|
||||
pub event_watched_date: String,
|
||||
/// 最后游玩ROM版本
|
||||
pub last_rom_version: String,
|
||||
/// 最后游玩数据版本
|
||||
pub last_data_version: String,
|
||||
/// 上次登陆日期
|
||||
pub last_login_date: String,
|
||||
/// 上次游玩结束日期
|
||||
pub last_play_date: String,
|
||||
/// 上次双人登陆日期
|
||||
pub last_pair_login_date: String,
|
||||
/// 上次免费游玩日期
|
||||
pub last_trial_play_date: String,
|
||||
pub last_play_credit: i64,
|
||||
pub last_play_mode: i64,
|
||||
|
||||
/// 上次游玩位置 ID
|
||||
pub last_place_id: i64,
|
||||
/// 上次游玩位置
|
||||
pub last_place_name: Option<String>,
|
||||
|
||||
pub last_all_net_id: i64,
|
||||
/// 上次游玩地区 ID
|
||||
pub last_region_id: i64,
|
||||
/// 上次游玩地区
|
||||
pub last_region_name: String,
|
||||
pub last_country_code: String,
|
||||
#[serde(rename = "lastSelectEMoney")]
|
||||
pub last_select_emoney: i64,
|
||||
/// 上次功能票
|
||||
pub last_select_ticket: i64,
|
||||
/// 上次挑战段位
|
||||
pub last_select_course: i64,
|
||||
/// 上次段位计数
|
||||
pub last_count_course: i64,
|
||||
pub first_game_id: String,
|
||||
/// 首次游玩游戏版本
|
||||
pub first_rom_version: String,
|
||||
/// 首次游玩数据版本
|
||||
pub first_data_version: String,
|
||||
/// 首次游玩
|
||||
pub first_play_date: String,
|
||||
pub compatible_cm_version: String,
|
||||
/// 总觉醒数
|
||||
pub total_awake: i64,
|
||||
pub daily_bonus_date: String,
|
||||
pub daily_course_bonus_date: String,
|
||||
pub map_stock: i64,
|
||||
pub rename_credit: i64,
|
||||
pub friend_regist_skip: i64,
|
||||
pub cm_last_emoney_credit: i64,
|
||||
pub cm_last_emoney_brand: i64,
|
||||
|
||||
/// 访问密码(国区无)
|
||||
pub access_code: Option<String>,
|
||||
/// 好友代码(国区无)
|
||||
pub friend_code: Option<u32>,
|
||||
/// 上次游玩 ID
|
||||
pub last_game_id: Option<u32>,
|
||||
/// 上次登入狗号
|
||||
pub last_client_id: Option<String>,
|
||||
/// 时间戳
|
||||
pub date_time: Option<u64>,
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use bincode::{Decode, Encode};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -8,10 +9,10 @@ pub struct GetUserPreviewApi {
|
||||
pub user_id: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GetUserPreviewApiResp {
|
||||
pub user_id: i64,
|
||||
pub user_id: u32,
|
||||
pub user_name: String,
|
||||
pub is_login: bool,
|
||||
pub last_rom_version: String,
|
||||
|
||||
@@ -6,3 +6,9 @@ pub use get_user_preview_api::{GetUserPreviewApi, GetUserPreviewApiResp};
|
||||
|
||||
mod user_logout_api;
|
||||
pub use user_logout_api::{UserLogoutApi, UserLogoutApiResp};
|
||||
|
||||
mod user_login_api;
|
||||
pub use user_login_api::{UserLoginApi, UserLoginApiResp};
|
||||
|
||||
mod get_user_data_api;
|
||||
pub use get_user_data_api::{GetUserDataApi, GetUserDataApiResp};
|
||||
|
||||
54
sdgb-api/src/title/model/user_login_api/mod.rs
Normal file
54
sdgb-api/src/title/model/user_login_api/mod.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UserLoginApi {
|
||||
pub user_id: u32,
|
||||
pub region_id: u32,
|
||||
pub date_time: u64,
|
||||
pub acsess_code: String,
|
||||
pub place_id: String,
|
||||
pub client_id: String,
|
||||
/// set to `false` is fine
|
||||
pub is_continue: bool,
|
||||
/// fixed to 0
|
||||
pub generic_flag: u8,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UserLoginApiResp {
|
||||
/// - `1`: success
|
||||
/// - `100`: logged
|
||||
/// - `102`: QRCode expired
|
||||
pub return_code: i32,
|
||||
/// format: yyyy-mm-dd HH:MM:SS
|
||||
pub last_login_date: Option<String>,
|
||||
pub login_count: Option<u64>,
|
||||
pub consecutive_login_count: Option<u64>,
|
||||
/// needed for some operation
|
||||
pub login_id: Option<u64>,
|
||||
}
|
||||
|
||||
impl UserLoginApi {
|
||||
pub fn new(user_id: u32) -> Self {
|
||||
let date_time = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map(|t| t.as_secs())
|
||||
.unwrap_or_default();
|
||||
|
||||
// 爱玩星球焦作解放店
|
||||
UserLoginApi {
|
||||
user_id,
|
||||
date_time,
|
||||
region_id: 13,
|
||||
acsess_code: "".to_owned(),
|
||||
place_id: 3223.to_string(),
|
||||
is_continue: false,
|
||||
generic_flag: 0,
|
||||
client_id: "A63E01E6170".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,20 +5,27 @@ edition = "2024"
|
||||
authors = ["mokurin000"]
|
||||
description = "CLI tool for SDGB protocol"
|
||||
|
||||
[features]
|
||||
default = ["compio", "cache"]
|
||||
|
||||
compio = ["dep:compio", "sdgb-api/compio"]
|
||||
tokio = ["dep:tokio", "sdgb-api/tokio"]
|
||||
|
||||
cache = ["dep:redb"]
|
||||
|
||||
[dependencies]
|
||||
sdgb-api = { workspace = true, features = ["bincode"] }
|
||||
spdlog-rs = { workspace = true }
|
||||
|
||||
snafu = { workspace = true }
|
||||
sdgb-api = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
strum = { workspace = true }
|
||||
tokio = { workspace = true, features = ["macros"], optional = true }
|
||||
compio = { workspace = true, features = ["macros"], optional = true }
|
||||
|
||||
nyquest-preset = { version = "0.2.0", features = ["async"] }
|
||||
compio = { version = "0.15.0", default-features = false, features = [
|
||||
"runtime",
|
||||
"macros",
|
||||
] }
|
||||
|
||||
palc = { version = "0.0.1", features = ["derive"] }
|
||||
spdlog-rs = { version = "0.4.3", default-features = false, features = [
|
||||
"level-info",
|
||||
"release-level-info",
|
||||
] }
|
||||
futures-util = "0.3.31"
|
||||
redb = { version = "2.6.1", optional = true }
|
||||
ctrlc = { version = "3.4.7", features = ["termination"] }
|
||||
|
||||
25
sdgb-cli/src/cache/mod.rs
vendored
Normal file
25
sdgb-cli/src/cache/mod.rs
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use redb::{Table, TableDefinition, WriteTransaction};
|
||||
|
||||
static DATABASE: LazyLock<redb::Database> = LazyLock::new(|| {
|
||||
redb::Database::builder()
|
||||
.create("players.redb")
|
||||
.expect("failed to open database")
|
||||
});
|
||||
const DIFINITION: TableDefinition<'_, u32, Vec<u8>> = redb::TableDefinition::new("players");
|
||||
|
||||
pub fn write_txn() -> Result<WriteTransaction, redb::Error> {
|
||||
Ok(DATABASE.begin_write()?)
|
||||
}
|
||||
|
||||
pub fn open_table(write: &WriteTransaction) -> Result<Table<'_, u32, Vec<u8>>, redb::Error> {
|
||||
Ok(write.open_table(DIFINITION)?)
|
||||
}
|
||||
|
||||
pub fn init_db() -> Result<(), redb::Error> {
|
||||
let write_txn = DATABASE.begin_write()?;
|
||||
write_txn.open_table(DIFINITION)?;
|
||||
write_txn.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -36,6 +36,13 @@ pub enum Commands {
|
||||
#[arg(short, long)]
|
||||
user_id: u32,
|
||||
},
|
||||
Userdata {
|
||||
#[arg(short, long)]
|
||||
user_id: u32,
|
||||
},
|
||||
|
||||
ListAllUser,
|
||||
|
||||
Logout {
|
||||
#[arg(short, long)]
|
||||
user_id: u32,
|
||||
|
||||
@@ -1,30 +1,58 @@
|
||||
use std::{
|
||||
fs::OpenOptions,
|
||||
io::{self, BufRead},
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
|
||||
use futures_util::StreamExt;
|
||||
use nyquest_preset::nyquest::ClientBuilder;
|
||||
use palc::Parser;
|
||||
use spdlog::{Level, LevelFilter::MoreSevereEqual};
|
||||
|
||||
use sdgb_api::{
|
||||
ApiError,
|
||||
all_net::QRCode,
|
||||
auth_lite::{SDGB, SDHJ, delivery_raw},
|
||||
title::{
|
||||
MaiVersionExt, Sdgb1_40, Sdgb1_50,
|
||||
methods::APIMethod,
|
||||
model::{
|
||||
GetUserPreviewApi, GetUserPreviewApiResp, Ping, PingResp, UserLogoutApi,
|
||||
UserLogoutApiResp,
|
||||
GetUserDataApi, GetUserDataApiResp, GetUserPreviewApi, GetUserPreviewApiResp, Ping,
|
||||
PingResp, UserLoginApi, UserLoginApiResp, UserLogoutApi, UserLogoutApiResp,
|
||||
},
|
||||
},
|
||||
};
|
||||
use spdlog::{error, info};
|
||||
use spdlog::{error, info, warn};
|
||||
|
||||
use crate::commands::Cli;
|
||||
|
||||
#[cfg(feature = "cache")]
|
||||
mod cache;
|
||||
mod commands;
|
||||
|
||||
#[compio::main]
|
||||
static EARLY_QUIT: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[cfg_attr(feature = "compio", compio::main)]
|
||||
#[cfg_attr(feature = "tokio", tokio::main)]
|
||||
async fn main() -> Result<(), Box<dyn snafu::Error>> {
|
||||
nyquest_preset::register();
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
spdlog::default_logger().set_level_filter(MoreSevereEqual(Level::Debug));
|
||||
} else {
|
||||
spdlog::default_logger().set_level_filter(MoreSevereEqual(Level::Info));
|
||||
}
|
||||
|
||||
ctrlc::set_handler(|| {
|
||||
warn!("received early-quit request! will abort soon");
|
||||
EARLY_QUIT.store(true, Ordering::Relaxed);
|
||||
})?;
|
||||
|
||||
let cmd = <Cli as Parser>::parse();
|
||||
|
||||
let client = ClientBuilder::default().build_async().await?;
|
||||
|
||||
// TODO: refactor via enum_dispatch
|
||||
match cmd.command {
|
||||
commands::Commands::Logout { user_id } => {
|
||||
let logout: UserLogoutApiResp = Sdgb1_50::request(
|
||||
@@ -78,6 +106,173 @@ async fn main() -> Result<(), Box<dyn snafu::Error>> {
|
||||
};
|
||||
println!("{}", String::from_utf8_lossy(&resp));
|
||||
}
|
||||
|
||||
commands::Commands::ListAllUser => {
|
||||
let mut stdin = io::stdin().lock();
|
||||
let mut buf = String::new();
|
||||
let mut user_ids = Vec::new();
|
||||
|
||||
while stdin.read_line(&mut buf).is_ok_and(|size| size != 0) {
|
||||
if buf.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let user_id: u32 = buf.trim().parse()?;
|
||||
buf.clear();
|
||||
user_ids.push(user_id);
|
||||
}
|
||||
|
||||
#[cfg(feature = "cache")]
|
||||
let _ = cache::init_db();
|
||||
#[cfg(feature = "cache")]
|
||||
let write = cache::write_txn()?;
|
||||
#[cfg(feature = "cache")]
|
||||
let config = sdgb_api::bincode::config::Configuration::<
|
||||
sdgb_api::bincode::config::LittleEndian,
|
||||
>::default()
|
||||
.with_no_limit();
|
||||
|
||||
let players = futures_util::stream::iter(user_ids)
|
||||
.map(async |user_id| {
|
||||
if EARLY_QUIT.load(Ordering::Relaxed) {
|
||||
return Err("early skip due to ctrl-c")?;
|
||||
}
|
||||
|
||||
#[cfg(feature = "cache")]
|
||||
{
|
||||
use redb::ReadableTable;
|
||||
use sdgb_api::bincode::borrow_decode_from_slice;
|
||||
|
||||
let cache_table = cache::open_table(&write)?;
|
||||
let data = cache_table.get(user_id)?;
|
||||
if let Some(data) = data {
|
||||
let decoded: (GetUserPreviewApiResp, _) =
|
||||
borrow_decode_from_slice(&data.value(), config)?;
|
||||
|
||||
return Ok(decoded.0);
|
||||
}
|
||||
}
|
||||
|
||||
let resp = Sdgb1_50::request::<_, GetUserPreviewApiResp>(
|
||||
&client,
|
||||
APIMethod::GetUserPreviewApi,
|
||||
user_id,
|
||||
GetUserPreviewApi { user_id },
|
||||
)
|
||||
.await;
|
||||
|
||||
match &resp {
|
||||
Ok(resp) => {
|
||||
info!("preview: {user_id} succeed");
|
||||
|
||||
#[cfg(feature = "cache")]
|
||||
{
|
||||
use sdgb_api::bincode::encode_to_vec;
|
||||
|
||||
if let Ok(mut table) = cache::open_table(&write)
|
||||
&& let Ok(encoded) = encode_to_vec(resp, config)
|
||||
{
|
||||
_ = table.insert(resp.user_id, encoded);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(ApiError::JSON { .. }) => {
|
||||
warn!("account unregistered: {user_id}");
|
||||
}
|
||||
Err(e) => {
|
||||
error!("preview failed: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
Result::<_, Box<dyn snafu::Error>>::Ok(resp?)
|
||||
})
|
||||
.buffer_unordered(20)
|
||||
.filter_map(async |r| r.ok())
|
||||
.collect::<Vec<_>>()
|
||||
.await;
|
||||
|
||||
#[cfg(feature = "cache")]
|
||||
let _ = write.commit();
|
||||
|
||||
let output = OpenOptions::new()
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.create(true)
|
||||
.open("players.json")?;
|
||||
serde_json::to_writer_pretty(output, &players)?;
|
||||
}
|
||||
commands::Commands::Userdata { user_id } => {
|
||||
let login = UserLoginApi::new(user_id);
|
||||
let date_time = login.date_time;
|
||||
let Ok(login_resp): Result<UserLoginApiResp, _> =
|
||||
Sdgb1_50::request(&client, APIMethod::UserLoginApi, user_id, login).await
|
||||
else {
|
||||
let logout_resp: UserLogoutApiResp = Sdgb1_50::request(
|
||||
&client,
|
||||
APIMethod::UserLogoutApi,
|
||||
user_id,
|
||||
UserLogoutApi {
|
||||
user_id,
|
||||
date_time,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
info!("logout: {logout_resp:?}");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
match login_resp.return_code {
|
||||
1 => info!("login succeed"),
|
||||
100 => {
|
||||
error!("user already logged");
|
||||
return Ok(());
|
||||
}
|
||||
102 => {
|
||||
error!("QRCode expired");
|
||||
return Ok(());
|
||||
}
|
||||
103 => {
|
||||
error!("Unregistered userId");
|
||||
return Ok(());
|
||||
}
|
||||
e @ _ => {
|
||||
error!("unknown login error: {e}");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
match Sdgb1_50::request::<_, GetUserDataApiResp>(
|
||||
&client,
|
||||
APIMethod::GetUserDataApi,
|
||||
user_id,
|
||||
GetUserDataApi { user_id },
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(udata) => {
|
||||
info!("{udata:#?}");
|
||||
}
|
||||
Err(e) => {
|
||||
error!("failed to get userdata: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
let logout_resp: UserLogoutApiResp = Sdgb1_50::request(
|
||||
&client,
|
||||
APIMethod::UserLogoutApi,
|
||||
user_id,
|
||||
UserLogoutApi {
|
||||
user_id,
|
||||
date_time,
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
info!("logout: {logout_resp:?}");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user