├── .devcontainer └── devcontainer.json ├── .github └── workflows │ └── release.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── rustfmt.toml └── src ├── discord.rs ├── lib.rs ├── main.rs ├── provider ├── avtrdb.rs ├── cache.rs ├── mod.rs ├── paw.rs ├── prelude.rs ├── vrcdb.rs ├── vrcds.rs └── vrcwb.rs └── vrchat.rs /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/rust 3 | { 4 | "name": "Rust", 5 | "image": "mcr.microsoft.com/devcontainers/rust:1-1-bookworm" 6 | } 7 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | on: 2 | release: 3 | types: [created] 4 | 5 | jobs: 6 | release: 7 | env: 8 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 9 | 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | include: 14 | - name: Windows 15 | target: i686-pc-windows-msvc 16 | runner: windows-latest 17 | 18 | - name: Linux 19 | target: x86_64-unknown-linux-gnu 20 | runner: ubuntu-latest 21 | 22 | name: ${{ matrix.name }} 23 | runs-on: ${{ matrix.runner }} 24 | steps: 25 | - name: Fetch Repository 26 | uses: actions/checkout@v3 27 | 28 | - name: Update Rust Toolchain 29 | run: rustup update stable 30 | 31 | - name: Add Rust Target 32 | run: rustup target add ${{ matrix.target }} 33 | 34 | - name: Build Release Binary 35 | run: cargo build --release --target ${{ matrix.target }} 36 | 37 | - name: Upload Release Binary (Windows) 38 | if: ${{ matrix.runner == 'windows-latest' }} 39 | run: gh release upload ${{ github.ref_name }} ./target/${{ matrix.target }}/release/vrc-log.exe --clobber 40 | 41 | - name: Upload Release Binary (Linux) 42 | if: ${{ matrix.runner == 'ubuntu-latest' }} 43 | run: gh release upload ${{ github.ref_name }} ./target/${{ matrix.target }}/release/vrc-log --clobber 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .vscode/ 3 | target/ 4 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.24.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler2" 16 | version = "2.0.0" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 19 | 20 | [[package]] 21 | name = "ahash" 22 | version = "0.8.12" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" 25 | dependencies = [ 26 | "cfg-if", 27 | "once_cell", 28 | "version_check", 29 | "zerocopy", 30 | ] 31 | 32 | [[package]] 33 | name = "aho-corasick" 34 | version = "1.1.3" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 37 | dependencies = [ 38 | "memchr", 39 | ] 40 | 41 | [[package]] 42 | name = "allocator-api2" 43 | version = "0.2.21" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" 46 | 47 | [[package]] 48 | name = "android-tzdata" 49 | version = "0.1.1" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 52 | 53 | [[package]] 54 | name = "android_system_properties" 55 | version = "0.1.5" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 58 | dependencies = [ 59 | "libc", 60 | ] 61 | 62 | [[package]] 63 | name = "anyhow" 64 | version = "1.0.98" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" 67 | 68 | [[package]] 69 | name = "async-trait" 70 | version = "0.1.88" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" 73 | dependencies = [ 74 | "proc-macro2", 75 | "quote", 76 | "syn", 77 | ] 78 | 79 | [[package]] 80 | name = "atomic-waker" 81 | version = "1.1.2" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 84 | 85 | [[package]] 86 | name = "autocfg" 87 | version = "1.4.0" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 90 | 91 | [[package]] 92 | name = "backtrace" 93 | version = "0.3.75" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" 96 | dependencies = [ 97 | "addr2line", 98 | "cfg-if", 99 | "libc", 100 | "miniz_oxide", 101 | "object", 102 | "rustc-demangle", 103 | "windows-targets", 104 | ] 105 | 106 | [[package]] 107 | name = "base64" 108 | version = "0.22.1" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 111 | 112 | [[package]] 113 | name = "bitflags" 114 | version = "1.3.2" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 117 | 118 | [[package]] 119 | name = "bitflags" 120 | version = "2.9.1" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" 123 | 124 | [[package]] 125 | name = "bumpalo" 126 | version = "3.18.1" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" 129 | 130 | [[package]] 131 | name = "byteorder" 132 | version = "1.5.0" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 135 | 136 | [[package]] 137 | name = "bytes" 138 | version = "1.10.1" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 141 | 142 | [[package]] 143 | name = "cached" 144 | version = "0.55.1" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "b0839c297f8783316fcca9d90344424e968395413f0662a5481f79c6648bbc14" 147 | dependencies = [ 148 | "ahash", 149 | "cached_proc_macro", 150 | "cached_proc_macro_types", 151 | "hashbrown 0.14.5", 152 | "once_cell", 153 | "thiserror", 154 | "web-time", 155 | ] 156 | 157 | [[package]] 158 | name = "cached_proc_macro" 159 | version = "0.24.0" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "673992d934f0711b68ebb3e1b79cdc4be31634b37c98f26867ced0438ca5c603" 162 | dependencies = [ 163 | "darling", 164 | "proc-macro2", 165 | "quote", 166 | "syn", 167 | ] 168 | 169 | [[package]] 170 | name = "cached_proc_macro_types" 171 | version = "0.1.1" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" 174 | 175 | [[package]] 176 | name = "cc" 177 | version = "1.2.26" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" 180 | dependencies = [ 181 | "shlex", 182 | ] 183 | 184 | [[package]] 185 | name = "cfg-if" 186 | version = "1.0.0" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 189 | 190 | [[package]] 191 | name = "cfg_aliases" 192 | version = "0.2.1" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 195 | 196 | [[package]] 197 | name = "chrono" 198 | version = "0.4.41" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" 201 | dependencies = [ 202 | "android-tzdata", 203 | "iana-time-zone", 204 | "js-sys", 205 | "num-traits", 206 | "wasm-bindgen", 207 | "windows-link", 208 | ] 209 | 210 | [[package]] 211 | name = "colored" 212 | version = "3.0.0" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" 215 | dependencies = [ 216 | "windows-sys 0.59.0", 217 | ] 218 | 219 | [[package]] 220 | name = "convert_case" 221 | version = "0.7.1" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" 224 | dependencies = [ 225 | "unicode-segmentation", 226 | ] 227 | 228 | [[package]] 229 | name = "core-foundation" 230 | version = "0.9.4" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 233 | dependencies = [ 234 | "core-foundation-sys", 235 | "libc", 236 | ] 237 | 238 | [[package]] 239 | name = "core-foundation-sys" 240 | version = "0.8.7" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 243 | 244 | [[package]] 245 | name = "crossbeam" 246 | version = "0.8.4" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" 249 | dependencies = [ 250 | "crossbeam-channel", 251 | "crossbeam-deque", 252 | "crossbeam-epoch", 253 | "crossbeam-queue", 254 | "crossbeam-utils", 255 | ] 256 | 257 | [[package]] 258 | name = "crossbeam-channel" 259 | version = "0.5.15" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" 262 | dependencies = [ 263 | "crossbeam-utils", 264 | ] 265 | 266 | [[package]] 267 | name = "crossbeam-deque" 268 | version = "0.8.6" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 271 | dependencies = [ 272 | "crossbeam-epoch", 273 | "crossbeam-utils", 274 | ] 275 | 276 | [[package]] 277 | name = "crossbeam-epoch" 278 | version = "0.9.18" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 281 | dependencies = [ 282 | "crossbeam-utils", 283 | ] 284 | 285 | [[package]] 286 | name = "crossbeam-queue" 287 | version = "0.3.12" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" 290 | dependencies = [ 291 | "crossbeam-utils", 292 | ] 293 | 294 | [[package]] 295 | name = "crossbeam-utils" 296 | version = "0.8.21" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 299 | 300 | [[package]] 301 | name = "crossterm" 302 | version = "0.29.0" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" 305 | dependencies = [ 306 | "bitflags 2.9.1", 307 | "crossterm_winapi", 308 | "derive_more", 309 | "document-features", 310 | "mio", 311 | "parking_lot", 312 | "rustix", 313 | "signal-hook", 314 | "signal-hook-mio", 315 | "winapi", 316 | ] 317 | 318 | [[package]] 319 | name = "crossterm_winapi" 320 | version = "0.9.1" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" 323 | dependencies = [ 324 | "winapi", 325 | ] 326 | 327 | [[package]] 328 | name = "darling" 329 | version = "0.20.11" 330 | source = "registry+https://github.com/rust-lang/crates.io-index" 331 | checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" 332 | dependencies = [ 333 | "darling_core", 334 | "darling_macro", 335 | ] 336 | 337 | [[package]] 338 | name = "darling_core" 339 | version = "0.20.11" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" 342 | dependencies = [ 343 | "fnv", 344 | "ident_case", 345 | "proc-macro2", 346 | "quote", 347 | "strsim", 348 | "syn", 349 | ] 350 | 351 | [[package]] 352 | name = "darling_macro" 353 | version = "0.20.11" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" 356 | dependencies = [ 357 | "darling_core", 358 | "quote", 359 | "syn", 360 | ] 361 | 362 | [[package]] 363 | name = "deranged" 364 | version = "0.4.0" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" 367 | dependencies = [ 368 | "powerfmt", 369 | ] 370 | 371 | [[package]] 372 | name = "derive_more" 373 | version = "2.0.1" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" 376 | dependencies = [ 377 | "derive_more-impl", 378 | ] 379 | 380 | [[package]] 381 | name = "derive_more-impl" 382 | version = "2.0.1" 383 | source = "registry+https://github.com/rust-lang/crates.io-index" 384 | checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" 385 | dependencies = [ 386 | "convert_case", 387 | "proc-macro2", 388 | "quote", 389 | "syn", 390 | ] 391 | 392 | [[package]] 393 | name = "discord-presence" 394 | version = "1.6.0" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | checksum = "f91d7c2fc01ffdc327e2b66d65dd59b8bd3f31a17e88811ce0540412fa0b84c1" 397 | dependencies = [ 398 | "byteorder", 399 | "bytes", 400 | "cfg-if", 401 | "crossbeam-channel", 402 | "log", 403 | "num-derive", 404 | "num-traits", 405 | "parking_lot", 406 | "paste", 407 | "quork", 408 | "serde", 409 | "serde_json", 410 | "thiserror", 411 | "uuid", 412 | ] 413 | 414 | [[package]] 415 | name = "displaydoc" 416 | version = "0.2.5" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 419 | dependencies = [ 420 | "proc-macro2", 421 | "quote", 422 | "syn", 423 | ] 424 | 425 | [[package]] 426 | name = "document-features" 427 | version = "0.2.11" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" 430 | dependencies = [ 431 | "litrs", 432 | ] 433 | 434 | [[package]] 435 | name = "encoding_rs" 436 | version = "0.8.35" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 439 | dependencies = [ 440 | "cfg-if", 441 | ] 442 | 443 | [[package]] 444 | name = "equivalent" 445 | version = "1.0.2" 446 | source = "registry+https://github.com/rust-lang/crates.io-index" 447 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 448 | 449 | [[package]] 450 | name = "errno" 451 | version = "0.3.12" 452 | source = "registry+https://github.com/rust-lang/crates.io-index" 453 | checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" 454 | dependencies = [ 455 | "libc", 456 | "windows-sys 0.59.0", 457 | ] 458 | 459 | [[package]] 460 | name = "fallible-iterator" 461 | version = "0.3.0" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" 464 | 465 | [[package]] 466 | name = "fallible-streaming-iterator" 467 | version = "0.1.9" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" 470 | 471 | [[package]] 472 | name = "fastrand" 473 | version = "2.3.0" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 476 | 477 | [[package]] 478 | name = "filetime" 479 | version = "0.2.25" 480 | source = "registry+https://github.com/rust-lang/crates.io-index" 481 | checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" 482 | dependencies = [ 483 | "cfg-if", 484 | "libc", 485 | "libredox", 486 | "windows-sys 0.59.0", 487 | ] 488 | 489 | [[package]] 490 | name = "fnv" 491 | version = "1.0.7" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 494 | 495 | [[package]] 496 | name = "foldhash" 497 | version = "0.1.5" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" 500 | 501 | [[package]] 502 | name = "foreign-types" 503 | version = "0.3.2" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 506 | dependencies = [ 507 | "foreign-types-shared", 508 | ] 509 | 510 | [[package]] 511 | name = "foreign-types-shared" 512 | version = "0.1.1" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 515 | 516 | [[package]] 517 | name = "form_urlencoded" 518 | version = "1.2.1" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 521 | dependencies = [ 522 | "percent-encoding", 523 | ] 524 | 525 | [[package]] 526 | name = "fsevent-sys" 527 | version = "4.1.0" 528 | source = "registry+https://github.com/rust-lang/crates.io-index" 529 | checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" 530 | dependencies = [ 531 | "libc", 532 | ] 533 | 534 | [[package]] 535 | name = "futures" 536 | version = "0.3.31" 537 | source = "registry+https://github.com/rust-lang/crates.io-index" 538 | checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" 539 | dependencies = [ 540 | "futures-channel", 541 | "futures-core", 542 | "futures-executor", 543 | "futures-io", 544 | "futures-sink", 545 | "futures-task", 546 | "futures-util", 547 | ] 548 | 549 | [[package]] 550 | name = "futures-channel" 551 | version = "0.3.31" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 554 | dependencies = [ 555 | "futures-core", 556 | "futures-sink", 557 | ] 558 | 559 | [[package]] 560 | name = "futures-core" 561 | version = "0.3.31" 562 | source = "registry+https://github.com/rust-lang/crates.io-index" 563 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 564 | 565 | [[package]] 566 | name = "futures-executor" 567 | version = "0.3.31" 568 | source = "registry+https://github.com/rust-lang/crates.io-index" 569 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 570 | dependencies = [ 571 | "futures-core", 572 | "futures-task", 573 | "futures-util", 574 | ] 575 | 576 | [[package]] 577 | name = "futures-io" 578 | version = "0.3.31" 579 | source = "registry+https://github.com/rust-lang/crates.io-index" 580 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 581 | 582 | [[package]] 583 | name = "futures-macro" 584 | version = "0.3.31" 585 | source = "registry+https://github.com/rust-lang/crates.io-index" 586 | checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 587 | dependencies = [ 588 | "proc-macro2", 589 | "quote", 590 | "syn", 591 | ] 592 | 593 | [[package]] 594 | name = "futures-sink" 595 | version = "0.3.31" 596 | source = "registry+https://github.com/rust-lang/crates.io-index" 597 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 598 | 599 | [[package]] 600 | name = "futures-task" 601 | version = "0.3.31" 602 | source = "registry+https://github.com/rust-lang/crates.io-index" 603 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 604 | 605 | [[package]] 606 | name = "futures-util" 607 | version = "0.3.31" 608 | source = "registry+https://github.com/rust-lang/crates.io-index" 609 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 610 | dependencies = [ 611 | "futures-channel", 612 | "futures-core", 613 | "futures-io", 614 | "futures-macro", 615 | "futures-sink", 616 | "futures-task", 617 | "memchr", 618 | "pin-project-lite", 619 | "pin-utils", 620 | "slab", 621 | ] 622 | 623 | [[package]] 624 | name = "getrandom" 625 | version = "0.2.16" 626 | source = "registry+https://github.com/rust-lang/crates.io-index" 627 | checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 628 | dependencies = [ 629 | "cfg-if", 630 | "libc", 631 | "wasi 0.11.0+wasi-snapshot-preview1", 632 | ] 633 | 634 | [[package]] 635 | name = "getrandom" 636 | version = "0.3.3" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" 639 | dependencies = [ 640 | "cfg-if", 641 | "libc", 642 | "r-efi", 643 | "wasi 0.14.2+wasi-0.2.4", 644 | ] 645 | 646 | [[package]] 647 | name = "gimli" 648 | version = "0.31.1" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 651 | 652 | [[package]] 653 | name = "h2" 654 | version = "0.4.10" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" 657 | dependencies = [ 658 | "atomic-waker", 659 | "bytes", 660 | "fnv", 661 | "futures-core", 662 | "futures-sink", 663 | "http", 664 | "indexmap", 665 | "slab", 666 | "tokio", 667 | "tokio-util", 668 | "tracing", 669 | ] 670 | 671 | [[package]] 672 | name = "hashbrown" 673 | version = "0.14.5" 674 | source = "registry+https://github.com/rust-lang/crates.io-index" 675 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 676 | dependencies = [ 677 | "ahash", 678 | "allocator-api2", 679 | ] 680 | 681 | [[package]] 682 | name = "hashbrown" 683 | version = "0.15.3" 684 | source = "registry+https://github.com/rust-lang/crates.io-index" 685 | checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" 686 | dependencies = [ 687 | "foldhash", 688 | ] 689 | 690 | [[package]] 691 | name = "hashlink" 692 | version = "0.10.0" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" 695 | dependencies = [ 696 | "hashbrown 0.15.3", 697 | ] 698 | 699 | [[package]] 700 | name = "heck" 701 | version = "0.5.0" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 704 | 705 | [[package]] 706 | name = "http" 707 | version = "1.3.1" 708 | source = "registry+https://github.com/rust-lang/crates.io-index" 709 | checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 710 | dependencies = [ 711 | "bytes", 712 | "fnv", 713 | "itoa", 714 | ] 715 | 716 | [[package]] 717 | name = "http-body" 718 | version = "1.0.1" 719 | source = "registry+https://github.com/rust-lang/crates.io-index" 720 | checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 721 | dependencies = [ 722 | "bytes", 723 | "http", 724 | ] 725 | 726 | [[package]] 727 | name = "http-body-util" 728 | version = "0.1.3" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 731 | dependencies = [ 732 | "bytes", 733 | "futures-core", 734 | "http", 735 | "http-body", 736 | "pin-project-lite", 737 | ] 738 | 739 | [[package]] 740 | name = "httparse" 741 | version = "1.10.1" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 744 | 745 | [[package]] 746 | name = "hyper" 747 | version = "1.6.0" 748 | source = "registry+https://github.com/rust-lang/crates.io-index" 749 | checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" 750 | dependencies = [ 751 | "bytes", 752 | "futures-channel", 753 | "futures-util", 754 | "h2", 755 | "http", 756 | "http-body", 757 | "httparse", 758 | "itoa", 759 | "pin-project-lite", 760 | "smallvec", 761 | "tokio", 762 | "want", 763 | ] 764 | 765 | [[package]] 766 | name = "hyper-rustls" 767 | version = "0.27.7" 768 | source = "registry+https://github.com/rust-lang/crates.io-index" 769 | checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" 770 | dependencies = [ 771 | "http", 772 | "hyper", 773 | "hyper-util", 774 | "rustls", 775 | "rustls-pki-types", 776 | "tokio", 777 | "tokio-rustls", 778 | "tower-service", 779 | ] 780 | 781 | [[package]] 782 | name = "hyper-tls" 783 | version = "0.6.0" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" 786 | dependencies = [ 787 | "bytes", 788 | "http-body-util", 789 | "hyper", 790 | "hyper-util", 791 | "native-tls", 792 | "tokio", 793 | "tokio-native-tls", 794 | "tower-service", 795 | ] 796 | 797 | [[package]] 798 | name = "hyper-util" 799 | version = "0.1.14" 800 | source = "registry+https://github.com/rust-lang/crates.io-index" 801 | checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" 802 | dependencies = [ 803 | "base64", 804 | "bytes", 805 | "futures-channel", 806 | "futures-core", 807 | "futures-util", 808 | "http", 809 | "http-body", 810 | "hyper", 811 | "ipnet", 812 | "libc", 813 | "percent-encoding", 814 | "pin-project-lite", 815 | "socket2", 816 | "system-configuration", 817 | "tokio", 818 | "tower-service", 819 | "tracing", 820 | "windows-registry", 821 | ] 822 | 823 | [[package]] 824 | name = "iana-time-zone" 825 | version = "0.1.63" 826 | source = "registry+https://github.com/rust-lang/crates.io-index" 827 | checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" 828 | dependencies = [ 829 | "android_system_properties", 830 | "core-foundation-sys", 831 | "iana-time-zone-haiku", 832 | "js-sys", 833 | "log", 834 | "wasm-bindgen", 835 | "windows-core", 836 | ] 837 | 838 | [[package]] 839 | name = "iana-time-zone-haiku" 840 | version = "0.1.2" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 843 | dependencies = [ 844 | "cc", 845 | ] 846 | 847 | [[package]] 848 | name = "icu_collections" 849 | version = "2.0.0" 850 | source = "registry+https://github.com/rust-lang/crates.io-index" 851 | checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" 852 | dependencies = [ 853 | "displaydoc", 854 | "potential_utf", 855 | "yoke", 856 | "zerofrom", 857 | "zerovec", 858 | ] 859 | 860 | [[package]] 861 | name = "icu_locale_core" 862 | version = "2.0.0" 863 | source = "registry+https://github.com/rust-lang/crates.io-index" 864 | checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" 865 | dependencies = [ 866 | "displaydoc", 867 | "litemap", 868 | "tinystr", 869 | "writeable", 870 | "zerovec", 871 | ] 872 | 873 | [[package]] 874 | name = "icu_normalizer" 875 | version = "2.0.0" 876 | source = "registry+https://github.com/rust-lang/crates.io-index" 877 | checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" 878 | dependencies = [ 879 | "displaydoc", 880 | "icu_collections", 881 | "icu_normalizer_data", 882 | "icu_properties", 883 | "icu_provider", 884 | "smallvec", 885 | "zerovec", 886 | ] 887 | 888 | [[package]] 889 | name = "icu_normalizer_data" 890 | version = "2.0.0" 891 | source = "registry+https://github.com/rust-lang/crates.io-index" 892 | checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" 893 | 894 | [[package]] 895 | name = "icu_properties" 896 | version = "2.0.1" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" 899 | dependencies = [ 900 | "displaydoc", 901 | "icu_collections", 902 | "icu_locale_core", 903 | "icu_properties_data", 904 | "icu_provider", 905 | "potential_utf", 906 | "zerotrie", 907 | "zerovec", 908 | ] 909 | 910 | [[package]] 911 | name = "icu_properties_data" 912 | version = "2.0.1" 913 | source = "registry+https://github.com/rust-lang/crates.io-index" 914 | checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" 915 | 916 | [[package]] 917 | name = "icu_provider" 918 | version = "2.0.0" 919 | source = "registry+https://github.com/rust-lang/crates.io-index" 920 | checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" 921 | dependencies = [ 922 | "displaydoc", 923 | "icu_locale_core", 924 | "stable_deref_trait", 925 | "tinystr", 926 | "writeable", 927 | "yoke", 928 | "zerofrom", 929 | "zerotrie", 930 | "zerovec", 931 | ] 932 | 933 | [[package]] 934 | name = "ident_case" 935 | version = "1.0.1" 936 | source = "registry+https://github.com/rust-lang/crates.io-index" 937 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 938 | 939 | [[package]] 940 | name = "idna" 941 | version = "1.0.3" 942 | source = "registry+https://github.com/rust-lang/crates.io-index" 943 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 944 | dependencies = [ 945 | "idna_adapter", 946 | "smallvec", 947 | "utf8_iter", 948 | ] 949 | 950 | [[package]] 951 | name = "idna_adapter" 952 | version = "1.2.1" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" 955 | dependencies = [ 956 | "icu_normalizer", 957 | "icu_properties", 958 | ] 959 | 960 | [[package]] 961 | name = "indexmap" 962 | version = "2.9.0" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" 965 | dependencies = [ 966 | "equivalent", 967 | "hashbrown 0.15.3", 968 | ] 969 | 970 | [[package]] 971 | name = "inotify" 972 | version = "0.11.0" 973 | source = "registry+https://github.com/rust-lang/crates.io-index" 974 | checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" 975 | dependencies = [ 976 | "bitflags 2.9.1", 977 | "inotify-sys", 978 | "libc", 979 | ] 980 | 981 | [[package]] 982 | name = "inotify-sys" 983 | version = "0.1.5" 984 | source = "registry+https://github.com/rust-lang/crates.io-index" 985 | checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" 986 | dependencies = [ 987 | "libc", 988 | ] 989 | 990 | [[package]] 991 | name = "ipnet" 992 | version = "2.11.0" 993 | source = "registry+https://github.com/rust-lang/crates.io-index" 994 | checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 995 | 996 | [[package]] 997 | name = "iri-string" 998 | version = "0.7.8" 999 | source = "registry+https://github.com/rust-lang/crates.io-index" 1000 | checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" 1001 | dependencies = [ 1002 | "memchr", 1003 | "serde", 1004 | ] 1005 | 1006 | [[package]] 1007 | name = "itoa" 1008 | version = "1.0.15" 1009 | source = "registry+https://github.com/rust-lang/crates.io-index" 1010 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 1011 | 1012 | [[package]] 1013 | name = "js-sys" 1014 | version = "0.3.77" 1015 | source = "registry+https://github.com/rust-lang/crates.io-index" 1016 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 1017 | dependencies = [ 1018 | "once_cell", 1019 | "wasm-bindgen", 1020 | ] 1021 | 1022 | [[package]] 1023 | name = "kqueue" 1024 | version = "1.1.1" 1025 | source = "registry+https://github.com/rust-lang/crates.io-index" 1026 | checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" 1027 | dependencies = [ 1028 | "kqueue-sys", 1029 | "libc", 1030 | ] 1031 | 1032 | [[package]] 1033 | name = "kqueue-sys" 1034 | version = "1.0.4" 1035 | source = "registry+https://github.com/rust-lang/crates.io-index" 1036 | checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" 1037 | dependencies = [ 1038 | "bitflags 1.3.2", 1039 | "libc", 1040 | ] 1041 | 1042 | [[package]] 1043 | name = "lazy-regex" 1044 | version = "3.4.1" 1045 | source = "registry+https://github.com/rust-lang/crates.io-index" 1046 | checksum = "60c7310b93682b36b98fa7ea4de998d3463ccbebd94d935d6b48ba5b6ffa7126" 1047 | dependencies = [ 1048 | "lazy-regex-proc_macros", 1049 | "once_cell", 1050 | "regex", 1051 | ] 1052 | 1053 | [[package]] 1054 | name = "lazy-regex-proc_macros" 1055 | version = "3.4.1" 1056 | source = "registry+https://github.com/rust-lang/crates.io-index" 1057 | checksum = "4ba01db5ef81e17eb10a5e0f2109d1b3a3e29bac3070fdbd7d156bf7dbd206a1" 1058 | dependencies = [ 1059 | "proc-macro2", 1060 | "quote", 1061 | "regex", 1062 | "syn", 1063 | ] 1064 | 1065 | [[package]] 1066 | name = "lazy_static" 1067 | version = "1.5.0" 1068 | source = "registry+https://github.com/rust-lang/crates.io-index" 1069 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 1070 | 1071 | [[package]] 1072 | name = "libc" 1073 | version = "0.2.172" 1074 | source = "registry+https://github.com/rust-lang/crates.io-index" 1075 | checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" 1076 | 1077 | [[package]] 1078 | name = "libredox" 1079 | version = "0.1.3" 1080 | source = "registry+https://github.com/rust-lang/crates.io-index" 1081 | checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" 1082 | dependencies = [ 1083 | "bitflags 2.9.1", 1084 | "libc", 1085 | "redox_syscall", 1086 | ] 1087 | 1088 | [[package]] 1089 | name = "libsqlite3-sys" 1090 | version = "0.34.0" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "91632f3b4fb6bd1d72aa3d78f41ffecfcf2b1a6648d8c241dbe7dbfaf4875e15" 1093 | dependencies = [ 1094 | "cc", 1095 | "pkg-config", 1096 | "vcpkg", 1097 | ] 1098 | 1099 | [[package]] 1100 | name = "linux-raw-sys" 1101 | version = "0.9.4" 1102 | source = "registry+https://github.com/rust-lang/crates.io-index" 1103 | checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" 1104 | 1105 | [[package]] 1106 | name = "litemap" 1107 | version = "0.8.0" 1108 | source = "registry+https://github.com/rust-lang/crates.io-index" 1109 | checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" 1110 | 1111 | [[package]] 1112 | name = "litrs" 1113 | version = "0.4.1" 1114 | source = "registry+https://github.com/rust-lang/crates.io-index" 1115 | checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" 1116 | 1117 | [[package]] 1118 | name = "lock_api" 1119 | version = "0.4.13" 1120 | source = "registry+https://github.com/rust-lang/crates.io-index" 1121 | checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" 1122 | dependencies = [ 1123 | "autocfg", 1124 | "scopeguard", 1125 | ] 1126 | 1127 | [[package]] 1128 | name = "log" 1129 | version = "0.4.27" 1130 | source = "registry+https://github.com/rust-lang/crates.io-index" 1131 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 1132 | 1133 | [[package]] 1134 | name = "matchers" 1135 | version = "0.1.0" 1136 | source = "registry+https://github.com/rust-lang/crates.io-index" 1137 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 1138 | dependencies = [ 1139 | "regex-automata 0.1.10", 1140 | ] 1141 | 1142 | [[package]] 1143 | name = "memchr" 1144 | version = "2.7.4" 1145 | source = "registry+https://github.com/rust-lang/crates.io-index" 1146 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 1147 | 1148 | [[package]] 1149 | name = "mime" 1150 | version = "0.3.17" 1151 | source = "registry+https://github.com/rust-lang/crates.io-index" 1152 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1153 | 1154 | [[package]] 1155 | name = "miniz_oxide" 1156 | version = "0.8.8" 1157 | source = "registry+https://github.com/rust-lang/crates.io-index" 1158 | checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" 1159 | dependencies = [ 1160 | "adler2", 1161 | ] 1162 | 1163 | [[package]] 1164 | name = "mio" 1165 | version = "1.0.4" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" 1168 | dependencies = [ 1169 | "libc", 1170 | "log", 1171 | "wasi 0.11.0+wasi-snapshot-preview1", 1172 | "windows-sys 0.59.0", 1173 | ] 1174 | 1175 | [[package]] 1176 | name = "native-tls" 1177 | version = "0.2.14" 1178 | source = "registry+https://github.com/rust-lang/crates.io-index" 1179 | checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" 1180 | dependencies = [ 1181 | "libc", 1182 | "log", 1183 | "openssl", 1184 | "openssl-probe", 1185 | "openssl-sys", 1186 | "schannel", 1187 | "security-framework", 1188 | "security-framework-sys", 1189 | "tempfile", 1190 | ] 1191 | 1192 | [[package]] 1193 | name = "nix" 1194 | version = "0.29.0" 1195 | source = "registry+https://github.com/rust-lang/crates.io-index" 1196 | checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" 1197 | dependencies = [ 1198 | "bitflags 2.9.1", 1199 | "cfg-if", 1200 | "cfg_aliases", 1201 | "libc", 1202 | ] 1203 | 1204 | [[package]] 1205 | name = "notify" 1206 | version = "8.0.0" 1207 | source = "registry+https://github.com/rust-lang/crates.io-index" 1208 | checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" 1209 | dependencies = [ 1210 | "bitflags 2.9.1", 1211 | "filetime", 1212 | "fsevent-sys", 1213 | "inotify", 1214 | "kqueue", 1215 | "libc", 1216 | "log", 1217 | "mio", 1218 | "notify-types", 1219 | "walkdir", 1220 | "windows-sys 0.59.0", 1221 | ] 1222 | 1223 | [[package]] 1224 | name = "notify-types" 1225 | version = "2.0.0" 1226 | source = "registry+https://github.com/rust-lang/crates.io-index" 1227 | checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" 1228 | 1229 | [[package]] 1230 | name = "nu-ansi-term" 1231 | version = "0.46.0" 1232 | source = "registry+https://github.com/rust-lang/crates.io-index" 1233 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 1234 | dependencies = [ 1235 | "overload", 1236 | "winapi", 1237 | ] 1238 | 1239 | [[package]] 1240 | name = "num-conv" 1241 | version = "0.1.0" 1242 | source = "registry+https://github.com/rust-lang/crates.io-index" 1243 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 1244 | 1245 | [[package]] 1246 | name = "num-derive" 1247 | version = "0.4.2" 1248 | source = "registry+https://github.com/rust-lang/crates.io-index" 1249 | checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" 1250 | dependencies = [ 1251 | "proc-macro2", 1252 | "quote", 1253 | "syn", 1254 | ] 1255 | 1256 | [[package]] 1257 | name = "num-traits" 1258 | version = "0.2.19" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1261 | dependencies = [ 1262 | "autocfg", 1263 | ] 1264 | 1265 | [[package]] 1266 | name = "object" 1267 | version = "0.36.7" 1268 | source = "registry+https://github.com/rust-lang/crates.io-index" 1269 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 1270 | dependencies = [ 1271 | "memchr", 1272 | ] 1273 | 1274 | [[package]] 1275 | name = "once_cell" 1276 | version = "1.21.3" 1277 | source = "registry+https://github.com/rust-lang/crates.io-index" 1278 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 1279 | 1280 | [[package]] 1281 | name = "openssl" 1282 | version = "0.10.73" 1283 | source = "registry+https://github.com/rust-lang/crates.io-index" 1284 | checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" 1285 | dependencies = [ 1286 | "bitflags 2.9.1", 1287 | "cfg-if", 1288 | "foreign-types", 1289 | "libc", 1290 | "once_cell", 1291 | "openssl-macros", 1292 | "openssl-sys", 1293 | ] 1294 | 1295 | [[package]] 1296 | name = "openssl-macros" 1297 | version = "0.1.1" 1298 | source = "registry+https://github.com/rust-lang/crates.io-index" 1299 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1300 | dependencies = [ 1301 | "proc-macro2", 1302 | "quote", 1303 | "syn", 1304 | ] 1305 | 1306 | [[package]] 1307 | name = "openssl-probe" 1308 | version = "0.1.6" 1309 | source = "registry+https://github.com/rust-lang/crates.io-index" 1310 | checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" 1311 | 1312 | [[package]] 1313 | name = "openssl-sys" 1314 | version = "0.9.109" 1315 | source = "registry+https://github.com/rust-lang/crates.io-index" 1316 | checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" 1317 | dependencies = [ 1318 | "cc", 1319 | "libc", 1320 | "pkg-config", 1321 | "vcpkg", 1322 | ] 1323 | 1324 | [[package]] 1325 | name = "overload" 1326 | version = "0.1.1" 1327 | source = "registry+https://github.com/rust-lang/crates.io-index" 1328 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 1329 | 1330 | [[package]] 1331 | name = "parking_lot" 1332 | version = "0.12.4" 1333 | source = "registry+https://github.com/rust-lang/crates.io-index" 1334 | checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" 1335 | dependencies = [ 1336 | "lock_api", 1337 | "parking_lot_core", 1338 | ] 1339 | 1340 | [[package]] 1341 | name = "parking_lot_core" 1342 | version = "0.9.11" 1343 | source = "registry+https://github.com/rust-lang/crates.io-index" 1344 | checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" 1345 | dependencies = [ 1346 | "cfg-if", 1347 | "libc", 1348 | "redox_syscall", 1349 | "smallvec", 1350 | "windows-targets", 1351 | ] 1352 | 1353 | [[package]] 1354 | name = "paste" 1355 | version = "1.0.15" 1356 | source = "registry+https://github.com/rust-lang/crates.io-index" 1357 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 1358 | 1359 | [[package]] 1360 | name = "percent-encoding" 1361 | version = "2.3.1" 1362 | source = "registry+https://github.com/rust-lang/crates.io-index" 1363 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 1364 | 1365 | [[package]] 1366 | name = "pin-project-lite" 1367 | version = "0.2.16" 1368 | source = "registry+https://github.com/rust-lang/crates.io-index" 1369 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 1370 | 1371 | [[package]] 1372 | name = "pin-utils" 1373 | version = "0.1.0" 1374 | source = "registry+https://github.com/rust-lang/crates.io-index" 1375 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1376 | 1377 | [[package]] 1378 | name = "pkg-config" 1379 | version = "0.3.32" 1380 | source = "registry+https://github.com/rust-lang/crates.io-index" 1381 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 1382 | 1383 | [[package]] 1384 | name = "potential_utf" 1385 | version = "0.1.2" 1386 | source = "registry+https://github.com/rust-lang/crates.io-index" 1387 | checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" 1388 | dependencies = [ 1389 | "zerovec", 1390 | ] 1391 | 1392 | [[package]] 1393 | name = "powerfmt" 1394 | version = "0.2.0" 1395 | source = "registry+https://github.com/rust-lang/crates.io-index" 1396 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 1397 | 1398 | [[package]] 1399 | name = "proc-macro-crate" 1400 | version = "3.3.0" 1401 | source = "registry+https://github.com/rust-lang/crates.io-index" 1402 | checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" 1403 | dependencies = [ 1404 | "toml_edit", 1405 | ] 1406 | 1407 | [[package]] 1408 | name = "proc-macro-error-attr2" 1409 | version = "2.0.0" 1410 | source = "registry+https://github.com/rust-lang/crates.io-index" 1411 | checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" 1412 | dependencies = [ 1413 | "proc-macro2", 1414 | "quote", 1415 | ] 1416 | 1417 | [[package]] 1418 | name = "proc-macro-error2" 1419 | version = "2.0.1" 1420 | source = "registry+https://github.com/rust-lang/crates.io-index" 1421 | checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" 1422 | dependencies = [ 1423 | "proc-macro-error-attr2", 1424 | "proc-macro2", 1425 | "quote", 1426 | "syn", 1427 | ] 1428 | 1429 | [[package]] 1430 | name = "proc-macro2" 1431 | version = "1.0.95" 1432 | source = "registry+https://github.com/rust-lang/crates.io-index" 1433 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 1434 | dependencies = [ 1435 | "unicode-ident", 1436 | ] 1437 | 1438 | [[package]] 1439 | name = "quork" 1440 | version = "0.9.0" 1441 | source = "registry+https://github.com/rust-lang/crates.io-index" 1442 | checksum = "6bd9640e0addc098a3481fd53bdc23970e5dd0edf6b349403aa680fb576c8f83" 1443 | dependencies = [ 1444 | "cfg-if", 1445 | "nix", 1446 | "quork-proc", 1447 | "thiserror", 1448 | "windows-sys 0.59.0", 1449 | ] 1450 | 1451 | [[package]] 1452 | name = "quork-proc" 1453 | version = "0.5.0" 1454 | source = "registry+https://github.com/rust-lang/crates.io-index" 1455 | checksum = "860d36740d9412e39fff90f57010e9870b15c2b48e5325295a6f5a824a480439" 1456 | dependencies = [ 1457 | "proc-macro-crate", 1458 | "proc-macro-error2", 1459 | "proc-macro2", 1460 | "quote", 1461 | "syn", 1462 | ] 1463 | 1464 | [[package]] 1465 | name = "quote" 1466 | version = "1.0.40" 1467 | source = "registry+https://github.com/rust-lang/crates.io-index" 1468 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 1469 | dependencies = [ 1470 | "proc-macro2", 1471 | ] 1472 | 1473 | [[package]] 1474 | name = "r-efi" 1475 | version = "5.2.0" 1476 | source = "registry+https://github.com/rust-lang/crates.io-index" 1477 | checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" 1478 | 1479 | [[package]] 1480 | name = "redox_syscall" 1481 | version = "0.5.12" 1482 | source = "registry+https://github.com/rust-lang/crates.io-index" 1483 | checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" 1484 | dependencies = [ 1485 | "bitflags 2.9.1", 1486 | ] 1487 | 1488 | [[package]] 1489 | name = "regex" 1490 | version = "1.11.1" 1491 | source = "registry+https://github.com/rust-lang/crates.io-index" 1492 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 1493 | dependencies = [ 1494 | "aho-corasick", 1495 | "memchr", 1496 | "regex-automata 0.4.9", 1497 | "regex-syntax 0.8.5", 1498 | ] 1499 | 1500 | [[package]] 1501 | name = "regex-automata" 1502 | version = "0.1.10" 1503 | source = "registry+https://github.com/rust-lang/crates.io-index" 1504 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 1505 | dependencies = [ 1506 | "regex-syntax 0.6.29", 1507 | ] 1508 | 1509 | [[package]] 1510 | name = "regex-automata" 1511 | version = "0.4.9" 1512 | source = "registry+https://github.com/rust-lang/crates.io-index" 1513 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 1514 | dependencies = [ 1515 | "aho-corasick", 1516 | "memchr", 1517 | "regex-syntax 0.8.5", 1518 | ] 1519 | 1520 | [[package]] 1521 | name = "regex-syntax" 1522 | version = "0.6.29" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" 1525 | 1526 | [[package]] 1527 | name = "regex-syntax" 1528 | version = "0.8.5" 1529 | source = "registry+https://github.com/rust-lang/crates.io-index" 1530 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 1531 | 1532 | [[package]] 1533 | name = "reqwest" 1534 | version = "0.12.19" 1535 | source = "registry+https://github.com/rust-lang/crates.io-index" 1536 | checksum = "a2f8e5513d63f2e5b386eb5106dc67eaf3f84e95258e210489136b8b92ad6119" 1537 | dependencies = [ 1538 | "base64", 1539 | "bytes", 1540 | "encoding_rs", 1541 | "futures-core", 1542 | "h2", 1543 | "http", 1544 | "http-body", 1545 | "http-body-util", 1546 | "hyper", 1547 | "hyper-rustls", 1548 | "hyper-tls", 1549 | "hyper-util", 1550 | "ipnet", 1551 | "js-sys", 1552 | "log", 1553 | "mime", 1554 | "native-tls", 1555 | "once_cell", 1556 | "percent-encoding", 1557 | "pin-project-lite", 1558 | "rustls-pki-types", 1559 | "serde", 1560 | "serde_json", 1561 | "serde_urlencoded", 1562 | "sync_wrapper", 1563 | "tokio", 1564 | "tokio-native-tls", 1565 | "tower", 1566 | "tower-http", 1567 | "tower-service", 1568 | "url", 1569 | "wasm-bindgen", 1570 | "wasm-bindgen-futures", 1571 | "web-sys", 1572 | ] 1573 | 1574 | [[package]] 1575 | name = "ring" 1576 | version = "0.17.14" 1577 | source = "registry+https://github.com/rust-lang/crates.io-index" 1578 | checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" 1579 | dependencies = [ 1580 | "cc", 1581 | "cfg-if", 1582 | "getrandom 0.2.16", 1583 | "libc", 1584 | "untrusted", 1585 | "windows-sys 0.52.0", 1586 | ] 1587 | 1588 | [[package]] 1589 | name = "rusqlite" 1590 | version = "0.36.0" 1591 | source = "registry+https://github.com/rust-lang/crates.io-index" 1592 | checksum = "3de23c3319433716cf134eed225fe9986bc24f63bed9be9f20c329029e672dc7" 1593 | dependencies = [ 1594 | "bitflags 2.9.1", 1595 | "fallible-iterator", 1596 | "fallible-streaming-iterator", 1597 | "hashlink", 1598 | "libsqlite3-sys", 1599 | "smallvec", 1600 | ] 1601 | 1602 | [[package]] 1603 | name = "rustc-demangle" 1604 | version = "0.1.24" 1605 | source = "registry+https://github.com/rust-lang/crates.io-index" 1606 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 1607 | 1608 | [[package]] 1609 | name = "rustix" 1610 | version = "1.0.7" 1611 | source = "registry+https://github.com/rust-lang/crates.io-index" 1612 | checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" 1613 | dependencies = [ 1614 | "bitflags 2.9.1", 1615 | "errno", 1616 | "libc", 1617 | "linux-raw-sys", 1618 | "windows-sys 0.59.0", 1619 | ] 1620 | 1621 | [[package]] 1622 | name = "rustls" 1623 | version = "0.23.27" 1624 | source = "registry+https://github.com/rust-lang/crates.io-index" 1625 | checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" 1626 | dependencies = [ 1627 | "once_cell", 1628 | "rustls-pki-types", 1629 | "rustls-webpki", 1630 | "subtle", 1631 | "zeroize", 1632 | ] 1633 | 1634 | [[package]] 1635 | name = "rustls-pki-types" 1636 | version = "1.12.0" 1637 | source = "registry+https://github.com/rust-lang/crates.io-index" 1638 | checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" 1639 | dependencies = [ 1640 | "zeroize", 1641 | ] 1642 | 1643 | [[package]] 1644 | name = "rustls-webpki" 1645 | version = "0.103.3" 1646 | source = "registry+https://github.com/rust-lang/crates.io-index" 1647 | checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" 1648 | dependencies = [ 1649 | "ring", 1650 | "rustls-pki-types", 1651 | "untrusted", 1652 | ] 1653 | 1654 | [[package]] 1655 | name = "rustversion" 1656 | version = "1.0.21" 1657 | source = "registry+https://github.com/rust-lang/crates.io-index" 1658 | checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" 1659 | 1660 | [[package]] 1661 | name = "ryu" 1662 | version = "1.0.20" 1663 | source = "registry+https://github.com/rust-lang/crates.io-index" 1664 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 1665 | 1666 | [[package]] 1667 | name = "same-file" 1668 | version = "1.0.6" 1669 | source = "registry+https://github.com/rust-lang/crates.io-index" 1670 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 1671 | dependencies = [ 1672 | "winapi-util", 1673 | ] 1674 | 1675 | [[package]] 1676 | name = "schannel" 1677 | version = "0.1.27" 1678 | source = "registry+https://github.com/rust-lang/crates.io-index" 1679 | checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" 1680 | dependencies = [ 1681 | "windows-sys 0.59.0", 1682 | ] 1683 | 1684 | [[package]] 1685 | name = "scopeguard" 1686 | version = "1.2.0" 1687 | source = "registry+https://github.com/rust-lang/crates.io-index" 1688 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1689 | 1690 | [[package]] 1691 | name = "security-framework" 1692 | version = "2.11.1" 1693 | source = "registry+https://github.com/rust-lang/crates.io-index" 1694 | checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 1695 | dependencies = [ 1696 | "bitflags 2.9.1", 1697 | "core-foundation", 1698 | "core-foundation-sys", 1699 | "libc", 1700 | "security-framework-sys", 1701 | ] 1702 | 1703 | [[package]] 1704 | name = "security-framework-sys" 1705 | version = "2.14.0" 1706 | source = "registry+https://github.com/rust-lang/crates.io-index" 1707 | checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" 1708 | dependencies = [ 1709 | "core-foundation-sys", 1710 | "libc", 1711 | ] 1712 | 1713 | [[package]] 1714 | name = "serde" 1715 | version = "1.0.219" 1716 | source = "registry+https://github.com/rust-lang/crates.io-index" 1717 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 1718 | dependencies = [ 1719 | "serde_derive", 1720 | ] 1721 | 1722 | [[package]] 1723 | name = "serde_derive" 1724 | version = "1.0.219" 1725 | source = "registry+https://github.com/rust-lang/crates.io-index" 1726 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 1727 | dependencies = [ 1728 | "proc-macro2", 1729 | "quote", 1730 | "syn", 1731 | ] 1732 | 1733 | [[package]] 1734 | name = "serde_json" 1735 | version = "1.0.140" 1736 | source = "registry+https://github.com/rust-lang/crates.io-index" 1737 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 1738 | dependencies = [ 1739 | "itoa", 1740 | "memchr", 1741 | "ryu", 1742 | "serde", 1743 | ] 1744 | 1745 | [[package]] 1746 | name = "serde_urlencoded" 1747 | version = "0.7.1" 1748 | source = "registry+https://github.com/rust-lang/crates.io-index" 1749 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1750 | dependencies = [ 1751 | "form_urlencoded", 1752 | "itoa", 1753 | "ryu", 1754 | "serde", 1755 | ] 1756 | 1757 | [[package]] 1758 | name = "sharded-slab" 1759 | version = "0.1.7" 1760 | source = "registry+https://github.com/rust-lang/crates.io-index" 1761 | checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 1762 | dependencies = [ 1763 | "lazy_static", 1764 | ] 1765 | 1766 | [[package]] 1767 | name = "shlex" 1768 | version = "1.3.0" 1769 | source = "registry+https://github.com/rust-lang/crates.io-index" 1770 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1771 | 1772 | [[package]] 1773 | name = "signal-hook" 1774 | version = "0.3.18" 1775 | source = "registry+https://github.com/rust-lang/crates.io-index" 1776 | checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" 1777 | dependencies = [ 1778 | "libc", 1779 | "signal-hook-registry", 1780 | ] 1781 | 1782 | [[package]] 1783 | name = "signal-hook-mio" 1784 | version = "0.2.4" 1785 | source = "registry+https://github.com/rust-lang/crates.io-index" 1786 | checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" 1787 | dependencies = [ 1788 | "libc", 1789 | "mio", 1790 | "signal-hook", 1791 | ] 1792 | 1793 | [[package]] 1794 | name = "signal-hook-registry" 1795 | version = "1.4.5" 1796 | source = "registry+https://github.com/rust-lang/crates.io-index" 1797 | checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" 1798 | dependencies = [ 1799 | "libc", 1800 | ] 1801 | 1802 | [[package]] 1803 | name = "slab" 1804 | version = "0.4.9" 1805 | source = "registry+https://github.com/rust-lang/crates.io-index" 1806 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1807 | dependencies = [ 1808 | "autocfg", 1809 | ] 1810 | 1811 | [[package]] 1812 | name = "smallvec" 1813 | version = "1.15.1" 1814 | source = "registry+https://github.com/rust-lang/crates.io-index" 1815 | checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 1816 | 1817 | [[package]] 1818 | name = "socket2" 1819 | version = "0.5.10" 1820 | source = "registry+https://github.com/rust-lang/crates.io-index" 1821 | checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" 1822 | dependencies = [ 1823 | "libc", 1824 | "windows-sys 0.52.0", 1825 | ] 1826 | 1827 | [[package]] 1828 | name = "stable_deref_trait" 1829 | version = "1.2.0" 1830 | source = "registry+https://github.com/rust-lang/crates.io-index" 1831 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 1832 | 1833 | [[package]] 1834 | name = "strsim" 1835 | version = "0.11.1" 1836 | source = "registry+https://github.com/rust-lang/crates.io-index" 1837 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 1838 | 1839 | [[package]] 1840 | name = "strum" 1841 | version = "0.27.1" 1842 | source = "registry+https://github.com/rust-lang/crates.io-index" 1843 | checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" 1844 | dependencies = [ 1845 | "strum_macros", 1846 | ] 1847 | 1848 | [[package]] 1849 | name = "strum_macros" 1850 | version = "0.27.1" 1851 | source = "registry+https://github.com/rust-lang/crates.io-index" 1852 | checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" 1853 | dependencies = [ 1854 | "heck", 1855 | "proc-macro2", 1856 | "quote", 1857 | "rustversion", 1858 | "syn", 1859 | ] 1860 | 1861 | [[package]] 1862 | name = "subtle" 1863 | version = "2.6.1" 1864 | source = "registry+https://github.com/rust-lang/crates.io-index" 1865 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 1866 | 1867 | [[package]] 1868 | name = "syn" 1869 | version = "2.0.101" 1870 | source = "registry+https://github.com/rust-lang/crates.io-index" 1871 | checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 1872 | dependencies = [ 1873 | "proc-macro2", 1874 | "quote", 1875 | "unicode-ident", 1876 | ] 1877 | 1878 | [[package]] 1879 | name = "sync_wrapper" 1880 | version = "1.0.2" 1881 | source = "registry+https://github.com/rust-lang/crates.io-index" 1882 | checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 1883 | dependencies = [ 1884 | "futures-core", 1885 | ] 1886 | 1887 | [[package]] 1888 | name = "synstructure" 1889 | version = "0.13.2" 1890 | source = "registry+https://github.com/rust-lang/crates.io-index" 1891 | checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" 1892 | dependencies = [ 1893 | "proc-macro2", 1894 | "quote", 1895 | "syn", 1896 | ] 1897 | 1898 | [[package]] 1899 | name = "system-configuration" 1900 | version = "0.6.1" 1901 | source = "registry+https://github.com/rust-lang/crates.io-index" 1902 | checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" 1903 | dependencies = [ 1904 | "bitflags 2.9.1", 1905 | "core-foundation", 1906 | "system-configuration-sys", 1907 | ] 1908 | 1909 | [[package]] 1910 | name = "system-configuration-sys" 1911 | version = "0.6.0" 1912 | source = "registry+https://github.com/rust-lang/crates.io-index" 1913 | checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" 1914 | dependencies = [ 1915 | "core-foundation-sys", 1916 | "libc", 1917 | ] 1918 | 1919 | [[package]] 1920 | name = "tempfile" 1921 | version = "3.20.0" 1922 | source = "registry+https://github.com/rust-lang/crates.io-index" 1923 | checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" 1924 | dependencies = [ 1925 | "fastrand", 1926 | "getrandom 0.3.3", 1927 | "once_cell", 1928 | "rustix", 1929 | "windows-sys 0.59.0", 1930 | ] 1931 | 1932 | [[package]] 1933 | name = "terminal-link" 1934 | version = "0.1.0" 1935 | source = "registry+https://github.com/rust-lang/crates.io-index" 1936 | checksum = "253bcead4f3aa96243b0f8fa46f9010e87ca23bd5d0c723d474ff1d2417bbdf8" 1937 | 1938 | [[package]] 1939 | name = "thiserror" 1940 | version = "2.0.12" 1941 | source = "registry+https://github.com/rust-lang/crates.io-index" 1942 | checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 1943 | dependencies = [ 1944 | "thiserror-impl", 1945 | ] 1946 | 1947 | [[package]] 1948 | name = "thiserror-impl" 1949 | version = "2.0.12" 1950 | source = "registry+https://github.com/rust-lang/crates.io-index" 1951 | checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 1952 | dependencies = [ 1953 | "proc-macro2", 1954 | "quote", 1955 | "syn", 1956 | ] 1957 | 1958 | [[package]] 1959 | name = "thread_local" 1960 | version = "1.1.8" 1961 | source = "registry+https://github.com/rust-lang/crates.io-index" 1962 | checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" 1963 | dependencies = [ 1964 | "cfg-if", 1965 | "once_cell", 1966 | ] 1967 | 1968 | [[package]] 1969 | name = "time" 1970 | version = "0.3.41" 1971 | source = "registry+https://github.com/rust-lang/crates.io-index" 1972 | checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" 1973 | dependencies = [ 1974 | "deranged", 1975 | "itoa", 1976 | "num-conv", 1977 | "powerfmt", 1978 | "serde", 1979 | "time-core", 1980 | "time-macros", 1981 | ] 1982 | 1983 | [[package]] 1984 | name = "time-core" 1985 | version = "0.1.4" 1986 | source = "registry+https://github.com/rust-lang/crates.io-index" 1987 | checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" 1988 | 1989 | [[package]] 1990 | name = "time-macros" 1991 | version = "0.2.22" 1992 | source = "registry+https://github.com/rust-lang/crates.io-index" 1993 | checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" 1994 | dependencies = [ 1995 | "num-conv", 1996 | "time-core", 1997 | ] 1998 | 1999 | [[package]] 2000 | name = "tinystr" 2001 | version = "0.8.1" 2002 | source = "registry+https://github.com/rust-lang/crates.io-index" 2003 | checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" 2004 | dependencies = [ 2005 | "displaydoc", 2006 | "zerovec", 2007 | ] 2008 | 2009 | [[package]] 2010 | name = "tokio" 2011 | version = "1.45.1" 2012 | source = "registry+https://github.com/rust-lang/crates.io-index" 2013 | checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" 2014 | dependencies = [ 2015 | "backtrace", 2016 | "bytes", 2017 | "libc", 2018 | "mio", 2019 | "parking_lot", 2020 | "pin-project-lite", 2021 | "signal-hook-registry", 2022 | "socket2", 2023 | "tokio-macros", 2024 | "windows-sys 0.52.0", 2025 | ] 2026 | 2027 | [[package]] 2028 | name = "tokio-macros" 2029 | version = "2.5.0" 2030 | source = "registry+https://github.com/rust-lang/crates.io-index" 2031 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 2032 | dependencies = [ 2033 | "proc-macro2", 2034 | "quote", 2035 | "syn", 2036 | ] 2037 | 2038 | [[package]] 2039 | name = "tokio-native-tls" 2040 | version = "0.3.1" 2041 | source = "registry+https://github.com/rust-lang/crates.io-index" 2042 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 2043 | dependencies = [ 2044 | "native-tls", 2045 | "tokio", 2046 | ] 2047 | 2048 | [[package]] 2049 | name = "tokio-rusqlite-new" 2050 | version = "0.10.0" 2051 | source = "registry+https://github.com/rust-lang/crates.io-index" 2052 | checksum = "1d5e39e7c825b55770bb03865ed55ab2cce6984c3dc6255f2d914a798cd84766" 2053 | dependencies = [ 2054 | "crossbeam-channel", 2055 | "rusqlite", 2056 | "tokio", 2057 | ] 2058 | 2059 | [[package]] 2060 | name = "tokio-rustls" 2061 | version = "0.26.2" 2062 | source = "registry+https://github.com/rust-lang/crates.io-index" 2063 | checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" 2064 | dependencies = [ 2065 | "rustls", 2066 | "tokio", 2067 | ] 2068 | 2069 | [[package]] 2070 | name = "tokio-util" 2071 | version = "0.7.15" 2072 | source = "registry+https://github.com/rust-lang/crates.io-index" 2073 | checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" 2074 | dependencies = [ 2075 | "bytes", 2076 | "futures-core", 2077 | "futures-sink", 2078 | "pin-project-lite", 2079 | "tokio", 2080 | ] 2081 | 2082 | [[package]] 2083 | name = "toml_datetime" 2084 | version = "0.6.11" 2085 | source = "registry+https://github.com/rust-lang/crates.io-index" 2086 | checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" 2087 | 2088 | [[package]] 2089 | name = "toml_edit" 2090 | version = "0.22.27" 2091 | source = "registry+https://github.com/rust-lang/crates.io-index" 2092 | checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" 2093 | dependencies = [ 2094 | "indexmap", 2095 | "toml_datetime", 2096 | "winnow", 2097 | ] 2098 | 2099 | [[package]] 2100 | name = "tower" 2101 | version = "0.5.2" 2102 | source = "registry+https://github.com/rust-lang/crates.io-index" 2103 | checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 2104 | dependencies = [ 2105 | "futures-core", 2106 | "futures-util", 2107 | "pin-project-lite", 2108 | "sync_wrapper", 2109 | "tokio", 2110 | "tower-layer", 2111 | "tower-service", 2112 | ] 2113 | 2114 | [[package]] 2115 | name = "tower-http" 2116 | version = "0.6.6" 2117 | source = "registry+https://github.com/rust-lang/crates.io-index" 2118 | checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" 2119 | dependencies = [ 2120 | "bitflags 2.9.1", 2121 | "bytes", 2122 | "futures-util", 2123 | "http", 2124 | "http-body", 2125 | "iri-string", 2126 | "pin-project-lite", 2127 | "tower", 2128 | "tower-layer", 2129 | "tower-service", 2130 | ] 2131 | 2132 | [[package]] 2133 | name = "tower-layer" 2134 | version = "0.3.3" 2135 | source = "registry+https://github.com/rust-lang/crates.io-index" 2136 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 2137 | 2138 | [[package]] 2139 | name = "tower-service" 2140 | version = "0.3.3" 2141 | source = "registry+https://github.com/rust-lang/crates.io-index" 2142 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 2143 | 2144 | [[package]] 2145 | name = "tracing" 2146 | version = "0.1.41" 2147 | source = "registry+https://github.com/rust-lang/crates.io-index" 2148 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 2149 | dependencies = [ 2150 | "pin-project-lite", 2151 | "tracing-attributes", 2152 | "tracing-core", 2153 | ] 2154 | 2155 | [[package]] 2156 | name = "tracing-attributes" 2157 | version = "0.1.29" 2158 | source = "registry+https://github.com/rust-lang/crates.io-index" 2159 | checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" 2160 | dependencies = [ 2161 | "proc-macro2", 2162 | "quote", 2163 | "syn", 2164 | ] 2165 | 2166 | [[package]] 2167 | name = "tracing-core" 2168 | version = "0.1.34" 2169 | source = "registry+https://github.com/rust-lang/crates.io-index" 2170 | checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" 2171 | dependencies = [ 2172 | "once_cell", 2173 | "valuable", 2174 | ] 2175 | 2176 | [[package]] 2177 | name = "tracing-log" 2178 | version = "0.2.0" 2179 | source = "registry+https://github.com/rust-lang/crates.io-index" 2180 | checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 2181 | dependencies = [ 2182 | "log", 2183 | "once_cell", 2184 | "tracing-core", 2185 | ] 2186 | 2187 | [[package]] 2188 | name = "tracing-subscriber" 2189 | version = "0.3.19" 2190 | source = "registry+https://github.com/rust-lang/crates.io-index" 2191 | checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" 2192 | dependencies = [ 2193 | "matchers", 2194 | "nu-ansi-term", 2195 | "once_cell", 2196 | "regex", 2197 | "sharded-slab", 2198 | "smallvec", 2199 | "thread_local", 2200 | "time", 2201 | "tracing", 2202 | "tracing-core", 2203 | "tracing-log", 2204 | ] 2205 | 2206 | [[package]] 2207 | name = "try-lock" 2208 | version = "0.2.5" 2209 | source = "registry+https://github.com/rust-lang/crates.io-index" 2210 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 2211 | 2212 | [[package]] 2213 | name = "unicode-ident" 2214 | version = "1.0.18" 2215 | source = "registry+https://github.com/rust-lang/crates.io-index" 2216 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 2217 | 2218 | [[package]] 2219 | name = "unicode-segmentation" 2220 | version = "1.12.0" 2221 | source = "registry+https://github.com/rust-lang/crates.io-index" 2222 | checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" 2223 | 2224 | [[package]] 2225 | name = "untrusted" 2226 | version = "0.9.0" 2227 | source = "registry+https://github.com/rust-lang/crates.io-index" 2228 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 2229 | 2230 | [[package]] 2231 | name = "url" 2232 | version = "2.5.4" 2233 | source = "registry+https://github.com/rust-lang/crates.io-index" 2234 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 2235 | dependencies = [ 2236 | "form_urlencoded", 2237 | "idna", 2238 | "percent-encoding", 2239 | ] 2240 | 2241 | [[package]] 2242 | name = "utf8_iter" 2243 | version = "1.0.4" 2244 | source = "registry+https://github.com/rust-lang/crates.io-index" 2245 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 2246 | 2247 | [[package]] 2248 | name = "uuid" 2249 | version = "1.17.0" 2250 | source = "registry+https://github.com/rust-lang/crates.io-index" 2251 | checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" 2252 | dependencies = [ 2253 | "getrandom 0.3.3", 2254 | "js-sys", 2255 | "wasm-bindgen", 2256 | ] 2257 | 2258 | [[package]] 2259 | name = "valuable" 2260 | version = "0.1.1" 2261 | source = "registry+https://github.com/rust-lang/crates.io-index" 2262 | checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" 2263 | 2264 | [[package]] 2265 | name = "vcpkg" 2266 | version = "0.2.15" 2267 | source = "registry+https://github.com/rust-lang/crates.io-index" 2268 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2269 | 2270 | [[package]] 2271 | name = "version_check" 2272 | version = "0.9.5" 2273 | source = "registry+https://github.com/rust-lang/crates.io-index" 2274 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 2275 | 2276 | [[package]] 2277 | name = "vrc-log" 2278 | version = "0.12.2" 2279 | dependencies = [ 2280 | "anyhow", 2281 | "async-trait", 2282 | "cached", 2283 | "chrono", 2284 | "colored", 2285 | "crossbeam", 2286 | "crossterm", 2287 | "discord-presence", 2288 | "futures", 2289 | "lazy-regex", 2290 | "notify", 2291 | "parking_lot", 2292 | "reqwest", 2293 | "serde", 2294 | "serde_json", 2295 | "strum", 2296 | "terminal-link", 2297 | "time", 2298 | "tokio", 2299 | "tokio-rusqlite-new", 2300 | "tracing", 2301 | "tracing-subscriber", 2302 | ] 2303 | 2304 | [[package]] 2305 | name = "walkdir" 2306 | version = "2.5.0" 2307 | source = "registry+https://github.com/rust-lang/crates.io-index" 2308 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 2309 | dependencies = [ 2310 | "same-file", 2311 | "winapi-util", 2312 | ] 2313 | 2314 | [[package]] 2315 | name = "want" 2316 | version = "0.3.1" 2317 | source = "registry+https://github.com/rust-lang/crates.io-index" 2318 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 2319 | dependencies = [ 2320 | "try-lock", 2321 | ] 2322 | 2323 | [[package]] 2324 | name = "wasi" 2325 | version = "0.11.0+wasi-snapshot-preview1" 2326 | source = "registry+https://github.com/rust-lang/crates.io-index" 2327 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 2328 | 2329 | [[package]] 2330 | name = "wasi" 2331 | version = "0.14.2+wasi-0.2.4" 2332 | source = "registry+https://github.com/rust-lang/crates.io-index" 2333 | checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 2334 | dependencies = [ 2335 | "wit-bindgen-rt", 2336 | ] 2337 | 2338 | [[package]] 2339 | name = "wasm-bindgen" 2340 | version = "0.2.100" 2341 | source = "registry+https://github.com/rust-lang/crates.io-index" 2342 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 2343 | dependencies = [ 2344 | "cfg-if", 2345 | "once_cell", 2346 | "rustversion", 2347 | "wasm-bindgen-macro", 2348 | ] 2349 | 2350 | [[package]] 2351 | name = "wasm-bindgen-backend" 2352 | version = "0.2.100" 2353 | source = "registry+https://github.com/rust-lang/crates.io-index" 2354 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 2355 | dependencies = [ 2356 | "bumpalo", 2357 | "log", 2358 | "proc-macro2", 2359 | "quote", 2360 | "syn", 2361 | "wasm-bindgen-shared", 2362 | ] 2363 | 2364 | [[package]] 2365 | name = "wasm-bindgen-futures" 2366 | version = "0.4.50" 2367 | source = "registry+https://github.com/rust-lang/crates.io-index" 2368 | checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 2369 | dependencies = [ 2370 | "cfg-if", 2371 | "js-sys", 2372 | "once_cell", 2373 | "wasm-bindgen", 2374 | "web-sys", 2375 | ] 2376 | 2377 | [[package]] 2378 | name = "wasm-bindgen-macro" 2379 | version = "0.2.100" 2380 | source = "registry+https://github.com/rust-lang/crates.io-index" 2381 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 2382 | dependencies = [ 2383 | "quote", 2384 | "wasm-bindgen-macro-support", 2385 | ] 2386 | 2387 | [[package]] 2388 | name = "wasm-bindgen-macro-support" 2389 | version = "0.2.100" 2390 | source = "registry+https://github.com/rust-lang/crates.io-index" 2391 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 2392 | dependencies = [ 2393 | "proc-macro2", 2394 | "quote", 2395 | "syn", 2396 | "wasm-bindgen-backend", 2397 | "wasm-bindgen-shared", 2398 | ] 2399 | 2400 | [[package]] 2401 | name = "wasm-bindgen-shared" 2402 | version = "0.2.100" 2403 | source = "registry+https://github.com/rust-lang/crates.io-index" 2404 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 2405 | dependencies = [ 2406 | "unicode-ident", 2407 | ] 2408 | 2409 | [[package]] 2410 | name = "web-sys" 2411 | version = "0.3.77" 2412 | source = "registry+https://github.com/rust-lang/crates.io-index" 2413 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 2414 | dependencies = [ 2415 | "js-sys", 2416 | "wasm-bindgen", 2417 | ] 2418 | 2419 | [[package]] 2420 | name = "web-time" 2421 | version = "1.1.0" 2422 | source = "registry+https://github.com/rust-lang/crates.io-index" 2423 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 2424 | dependencies = [ 2425 | "js-sys", 2426 | "wasm-bindgen", 2427 | ] 2428 | 2429 | [[package]] 2430 | name = "winapi" 2431 | version = "0.3.9" 2432 | source = "registry+https://github.com/rust-lang/crates.io-index" 2433 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2434 | dependencies = [ 2435 | "winapi-i686-pc-windows-gnu", 2436 | "winapi-x86_64-pc-windows-gnu", 2437 | ] 2438 | 2439 | [[package]] 2440 | name = "winapi-i686-pc-windows-gnu" 2441 | version = "0.4.0" 2442 | source = "registry+https://github.com/rust-lang/crates.io-index" 2443 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2444 | 2445 | [[package]] 2446 | name = "winapi-util" 2447 | version = "0.1.9" 2448 | source = "registry+https://github.com/rust-lang/crates.io-index" 2449 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 2450 | dependencies = [ 2451 | "windows-sys 0.59.0", 2452 | ] 2453 | 2454 | [[package]] 2455 | name = "winapi-x86_64-pc-windows-gnu" 2456 | version = "0.4.0" 2457 | source = "registry+https://github.com/rust-lang/crates.io-index" 2458 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2459 | 2460 | [[package]] 2461 | name = "windows-core" 2462 | version = "0.61.2" 2463 | source = "registry+https://github.com/rust-lang/crates.io-index" 2464 | checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" 2465 | dependencies = [ 2466 | "windows-implement", 2467 | "windows-interface", 2468 | "windows-link", 2469 | "windows-result", 2470 | "windows-strings", 2471 | ] 2472 | 2473 | [[package]] 2474 | name = "windows-implement" 2475 | version = "0.60.0" 2476 | source = "registry+https://github.com/rust-lang/crates.io-index" 2477 | checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" 2478 | dependencies = [ 2479 | "proc-macro2", 2480 | "quote", 2481 | "syn", 2482 | ] 2483 | 2484 | [[package]] 2485 | name = "windows-interface" 2486 | version = "0.59.1" 2487 | source = "registry+https://github.com/rust-lang/crates.io-index" 2488 | checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" 2489 | dependencies = [ 2490 | "proc-macro2", 2491 | "quote", 2492 | "syn", 2493 | ] 2494 | 2495 | [[package]] 2496 | name = "windows-link" 2497 | version = "0.1.1" 2498 | source = "registry+https://github.com/rust-lang/crates.io-index" 2499 | checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" 2500 | 2501 | [[package]] 2502 | name = "windows-registry" 2503 | version = "0.5.2" 2504 | source = "registry+https://github.com/rust-lang/crates.io-index" 2505 | checksum = "b3bab093bdd303a1240bb99b8aba8ea8a69ee19d34c9e2ef9594e708a4878820" 2506 | dependencies = [ 2507 | "windows-link", 2508 | "windows-result", 2509 | "windows-strings", 2510 | ] 2511 | 2512 | [[package]] 2513 | name = "windows-result" 2514 | version = "0.3.4" 2515 | source = "registry+https://github.com/rust-lang/crates.io-index" 2516 | checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" 2517 | dependencies = [ 2518 | "windows-link", 2519 | ] 2520 | 2521 | [[package]] 2522 | name = "windows-strings" 2523 | version = "0.4.2" 2524 | source = "registry+https://github.com/rust-lang/crates.io-index" 2525 | checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" 2526 | dependencies = [ 2527 | "windows-link", 2528 | ] 2529 | 2530 | [[package]] 2531 | name = "windows-sys" 2532 | version = "0.52.0" 2533 | source = "registry+https://github.com/rust-lang/crates.io-index" 2534 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 2535 | dependencies = [ 2536 | "windows-targets", 2537 | ] 2538 | 2539 | [[package]] 2540 | name = "windows-sys" 2541 | version = "0.59.0" 2542 | source = "registry+https://github.com/rust-lang/crates.io-index" 2543 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 2544 | dependencies = [ 2545 | "windows-targets", 2546 | ] 2547 | 2548 | [[package]] 2549 | name = "windows-targets" 2550 | version = "0.52.6" 2551 | source = "registry+https://github.com/rust-lang/crates.io-index" 2552 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 2553 | dependencies = [ 2554 | "windows_aarch64_gnullvm", 2555 | "windows_aarch64_msvc", 2556 | "windows_i686_gnu", 2557 | "windows_i686_gnullvm", 2558 | "windows_i686_msvc", 2559 | "windows_x86_64_gnu", 2560 | "windows_x86_64_gnullvm", 2561 | "windows_x86_64_msvc", 2562 | ] 2563 | 2564 | [[package]] 2565 | name = "windows_aarch64_gnullvm" 2566 | version = "0.52.6" 2567 | source = "registry+https://github.com/rust-lang/crates.io-index" 2568 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 2569 | 2570 | [[package]] 2571 | name = "windows_aarch64_msvc" 2572 | version = "0.52.6" 2573 | source = "registry+https://github.com/rust-lang/crates.io-index" 2574 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2575 | 2576 | [[package]] 2577 | name = "windows_i686_gnu" 2578 | version = "0.52.6" 2579 | source = "registry+https://github.com/rust-lang/crates.io-index" 2580 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 2581 | 2582 | [[package]] 2583 | name = "windows_i686_gnullvm" 2584 | version = "0.52.6" 2585 | source = "registry+https://github.com/rust-lang/crates.io-index" 2586 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 2587 | 2588 | [[package]] 2589 | name = "windows_i686_msvc" 2590 | version = "0.52.6" 2591 | source = "registry+https://github.com/rust-lang/crates.io-index" 2592 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 2593 | 2594 | [[package]] 2595 | name = "windows_x86_64_gnu" 2596 | version = "0.52.6" 2597 | source = "registry+https://github.com/rust-lang/crates.io-index" 2598 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 2599 | 2600 | [[package]] 2601 | name = "windows_x86_64_gnullvm" 2602 | version = "0.52.6" 2603 | source = "registry+https://github.com/rust-lang/crates.io-index" 2604 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 2605 | 2606 | [[package]] 2607 | name = "windows_x86_64_msvc" 2608 | version = "0.52.6" 2609 | source = "registry+https://github.com/rust-lang/crates.io-index" 2610 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 2611 | 2612 | [[package]] 2613 | name = "winnow" 2614 | version = "0.7.10" 2615 | source = "registry+https://github.com/rust-lang/crates.io-index" 2616 | checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" 2617 | dependencies = [ 2618 | "memchr", 2619 | ] 2620 | 2621 | [[package]] 2622 | name = "wit-bindgen-rt" 2623 | version = "0.39.0" 2624 | source = "registry+https://github.com/rust-lang/crates.io-index" 2625 | checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 2626 | dependencies = [ 2627 | "bitflags 2.9.1", 2628 | ] 2629 | 2630 | [[package]] 2631 | name = "writeable" 2632 | version = "0.6.1" 2633 | source = "registry+https://github.com/rust-lang/crates.io-index" 2634 | checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" 2635 | 2636 | [[package]] 2637 | name = "yoke" 2638 | version = "0.8.0" 2639 | source = "registry+https://github.com/rust-lang/crates.io-index" 2640 | checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" 2641 | dependencies = [ 2642 | "serde", 2643 | "stable_deref_trait", 2644 | "yoke-derive", 2645 | "zerofrom", 2646 | ] 2647 | 2648 | [[package]] 2649 | name = "yoke-derive" 2650 | version = "0.8.0" 2651 | source = "registry+https://github.com/rust-lang/crates.io-index" 2652 | checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" 2653 | dependencies = [ 2654 | "proc-macro2", 2655 | "quote", 2656 | "syn", 2657 | "synstructure", 2658 | ] 2659 | 2660 | [[package]] 2661 | name = "zerocopy" 2662 | version = "0.8.25" 2663 | source = "registry+https://github.com/rust-lang/crates.io-index" 2664 | checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" 2665 | dependencies = [ 2666 | "zerocopy-derive", 2667 | ] 2668 | 2669 | [[package]] 2670 | name = "zerocopy-derive" 2671 | version = "0.8.25" 2672 | source = "registry+https://github.com/rust-lang/crates.io-index" 2673 | checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" 2674 | dependencies = [ 2675 | "proc-macro2", 2676 | "quote", 2677 | "syn", 2678 | ] 2679 | 2680 | [[package]] 2681 | name = "zerofrom" 2682 | version = "0.1.6" 2683 | source = "registry+https://github.com/rust-lang/crates.io-index" 2684 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" 2685 | dependencies = [ 2686 | "zerofrom-derive", 2687 | ] 2688 | 2689 | [[package]] 2690 | name = "zerofrom-derive" 2691 | version = "0.1.6" 2692 | source = "registry+https://github.com/rust-lang/crates.io-index" 2693 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" 2694 | dependencies = [ 2695 | "proc-macro2", 2696 | "quote", 2697 | "syn", 2698 | "synstructure", 2699 | ] 2700 | 2701 | [[package]] 2702 | name = "zeroize" 2703 | version = "1.8.1" 2704 | source = "registry+https://github.com/rust-lang/crates.io-index" 2705 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 2706 | 2707 | [[package]] 2708 | name = "zerotrie" 2709 | version = "0.2.2" 2710 | source = "registry+https://github.com/rust-lang/crates.io-index" 2711 | checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" 2712 | dependencies = [ 2713 | "displaydoc", 2714 | "yoke", 2715 | "zerofrom", 2716 | ] 2717 | 2718 | [[package]] 2719 | name = "zerovec" 2720 | version = "0.11.2" 2721 | source = "registry+https://github.com/rust-lang/crates.io-index" 2722 | checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" 2723 | dependencies = [ 2724 | "yoke", 2725 | "zerofrom", 2726 | "zerovec-derive", 2727 | ] 2728 | 2729 | [[package]] 2730 | name = "zerovec-derive" 2731 | version = "0.11.1" 2732 | source = "registry+https://github.com/rust-lang/crates.io-index" 2733 | checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" 2734 | dependencies = [ 2735 | "proc-macro2", 2736 | "quote", 2737 | "syn", 2738 | ] 2739 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vrc-log" 3 | version = "0.12.2" 4 | authors = ["Shayne Hartford "] 5 | edition = "2021" 6 | description = "VRChat Local Avatar ID Logger" 7 | readme = "README.md" 8 | homepage = "https://git.shaybox.com/vrc-log/releases/latest" 9 | repository = "https://github.com/ShayBox/VRC-LOG" 10 | license = "MIT" 11 | keywords = ["vrchat", "local", "cache", "avatar", "logger"] 12 | categories = ["config", "database", "filesystem", "games", "parsing"] 13 | 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [dependencies] 17 | anyhow = "1" 18 | async-trait = "0.1" 19 | cached = { version = "0.55", optional = true } 20 | chrono = "0.4" 21 | colored = "3" 22 | crossbeam = "0.8" 23 | crossterm = { version = "0.29", optional = true } 24 | discord-presence = { version = "1", optional = true } 25 | futures = "0.3" 26 | lazy-regex = "3" 27 | notify = "8" 28 | parking_lot = "0.12" 29 | reqwest = { version = "0.12", features = ["json"], optional = true } 30 | serde = { version = "1", features = ["derive"] } 31 | serde_json = "1" 32 | strum = { version = "0.27", features = ["derive"] } 33 | terminal-link = "0.1" 34 | time = { version = "0.3", features = ["macros"] } 35 | tokio = { version = "1", features = ["full"] } 36 | tokio-rusqlite-new = { version = "0.10", features = ["bundled"], optional = true } 37 | tracing = "0.1" 38 | tracing-subscriber = { version = "0.3", features = ["env-filter", "time"] } 39 | 40 | [features] 41 | default = ["cache", "avtrdb", "vrcdb", "vrcds", "vrcwb", "paw", "title"] 42 | 43 | # VRChat Avatar Database Providers 44 | cache = ["dep:tokio-rusqlite-new"] 45 | avtrdb = ["dep:reqwest", "discord"] 46 | vrcdb = ["dep:reqwest", "discord"] 47 | vrcds = ["dep:reqwest", "discord"] 48 | vrcwb = ["dep:reqwest", "discord"] 49 | paw = ["dep:reqwest"] 50 | 51 | discord = ["dep:discord-presence", "dep:cached"] 52 | title = ["dep:crossterm"] 53 | 54 | # https://github.com/johnthagen/min-sized-rust 55 | [profile.release] 56 | strip = true # Automatically strip symbols from the binary. 57 | opt-level = "z" # Optimize for size. 58 | lto = true 59 | codegen-units = 1 60 | panic = "abort" 61 | 62 | [lints.clippy] 63 | pedantic = { level = "warn", priority = -1 } 64 | nursery = { level = "warn", priority = -1 } 65 | cargo = { level = "warn", priority = -1 } 66 | multiple_crate_versions = "allow" 67 | similar_names = "allow" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Shayne Hartford 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Discord 4 | 5 | 6 | Downloads 7 | 8 |
9 | 10 | # VRC-LOG 11 | 12 | VRChat Local Avatar ID Logger 13 | 14 | ## Important Notice 15 | 16 | This project does **NOT** rip or steal avatars, and does **NOT** break the VRChat Terms of Service. 17 | It just scans your local logs and analytics files for avatar IDs and sends them to avatar search providers. 18 | If you don't want your avatars searchable you can request the providers below to blacklist them. 19 | 20 | I **DO NOT** work with search providers that don't allow blacklisting, such as YAAS (part of the SAARs ripper project) 21 | 22 | ## Cache Encryption 23 | 24 | VRChat recently added local avatar cache encryption, which broke the logger, and rippers :) 25 | I've updated the logger to use the Amplitude Analytics file, which only contains data when switching worlds. 26 | You should take a look at this file for the short time it contains data before uploading, it contains **A LOT 27 | ** of data... 28 | 29 | **You can also add `--enable-sdk-log-levels` to your launch options to get more avatars more quickly.** 30 | 31 | ### VRCX Auto-Launch 32 | 33 | This program prints [VRCX] avatar links when a new (to you) avatars get discovered. 34 | You can place a **shortcut** to this program within the [VRCX] Auto-Launch Folder (Settings > Advanced) 35 | 36 | ### Steam Launch Options (Headless) 37 | 38 | Place the file in the VRChat directory or `PATH` and set your launch options 39 | `vrc-log(.exe) %command%` 40 | 41 | ### Supported Avatar Database Providers 42 | 43 | - [avtrDB - Avatar Search] - [Discord](https://discord.gg/ZxB6w2hGfU) / [VRCX](https://api.avtrdb.com/v1/avatar/search/vrcx) / [Web](https://avtrdb.com) 44 | - [VRCDB - Avatar Search] - [Discord](https://discord.gg/q427ecnUvj) / [VRCX](https://vrcx.vrcdb.com/avatars/Avatar/VRCX) / [Web](https://vrcdb.com) / [World](https://vrchat.com/home/world/wrld_1146f625-5d42-40f5-bfe7-06a7664e2796) 45 | - [VRCDS - Project Dark Star] - [Discord](https://discord.gg/QT4uatfU8h) / [VRCX](https://avtr.nekosunevr.co.uk/vrcx_search) / [Web](https://avtr.nekosunevr.co.uk) 46 | - [VRCWB - World Balancer] - [Discord](https://discord.gg/Uw7aAShdsp) / [VRCX](https://avatar.worldbalancer.com/vrcx_search.php) / [Web](https://avatar.worldbalancer.com/search.php) 47 | - [PAW - Puppy's Avatar World] - [Discord](https://discord.gg/zHhs4nQYxX) / [VRCX](https://paw-api.amelia.fun/vrcx_search) / [Web](https://paw.amelia.fun) 48 | 49 | #### Unsupported Avatar Database Providers 50 | 51 | - ~~VRCDB - Ravenwood~~ - Shutdown 52 | - ~~[Just H Party]~~ - Can't submit avatars 53 | - ~~[Prismic's Avatar Search]~~ - Can't submit avatars 54 | 55 | Additional contributions welcome, please open an issue, pull request, or join Discord. 56 | 57 | [avtrDB - Avatar Search]: https://avtrdb.com 58 | 59 | [Just H Party]: https://avtr.just-h.party 60 | 61 | [Prismic's Avatar Search]: https://vrchat.com/home/world/wrld_57514404-7f4e-4aee-a50a-57f55d3084bf 62 | 63 | [VRCDB - Avatar Search]: https://sites.smokes-hub.de 64 | 65 | [VRCDS - Project Dark Star]: https://avtr.nekosunevr.co.uk 66 | 67 | [VRCWB - World Balancer]: https://avatar.worldbalancer.com 68 | 69 | [VRCX]: https://github.com/vrcx-team/VRCX?tab=readme-ov-file#--vrcx 70 | 71 | [PAW - Puppy's Avatar World]: https://paw.amelia.fun -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | enum_discrim_align_threshold = 10 2 | group_imports = "StdExternalCrate" 3 | imports_granularity = "Crate" 4 | imports_layout = "HorizontalVertical" 5 | struct_field_align_threshold = 10 6 | -------------------------------------------------------------------------------- /src/discord.rs: -------------------------------------------------------------------------------- 1 | use std::{sync::Arc, time::Duration}; 2 | 3 | use cached::proc_macro::once; 4 | use discord_presence::{ 5 | models::{EventData, PartialUser}, 6 | Client, 7 | }; 8 | use parking_lot::Mutex; 9 | 10 | pub const CLIENT_ID: u64 = 1_137_885_877_918_502_923; 11 | pub const DEVELOPER_ID: &str = "358558305997684739"; 12 | 13 | pub struct Discord { 14 | pub client: Client, 15 | pub user: Arc>>, 16 | } 17 | 18 | impl Discord { 19 | fn start() -> Self { 20 | let mut discord = Self { 21 | client: Client::new(CLIENT_ID), 22 | user: Arc::default(), 23 | }; 24 | 25 | let user = discord.user.clone(); 26 | discord 27 | .client 28 | .on_ready(move |ctx| { 29 | if let EventData::Ready(event) = ctx.event { 30 | *user.lock() = event.user; 31 | } 32 | }) 33 | .persist(); 34 | 35 | discord.client.start(); 36 | discord 37 | } 38 | } 39 | 40 | #[once(option = true, sync_writes = true)] 41 | pub fn get_user_id() -> Option { 42 | if let Ok(user_id) = std::env::var("DISCORD") { 43 | /* TODO: Validate User ID (Snowflake) - Regex? */ 44 | return Some(user_id); 45 | } 46 | 47 | let discord = Discord::start(); 48 | std::thread::sleep(Duration::from_secs(5)); 49 | discord.client.shutdown().ok()?; 50 | 51 | if let Some(user) = discord.user.lock().as_ref() { 52 | if let Some(user_id) = &user.id { 53 | if user_id != "1045800378228281345" { 54 | if let Some(username) = &user.username { 55 | info!("[Discord] Authenticated as {username}"); 56 | } 57 | 58 | return Some(user_id.clone()); 59 | } 60 | 61 | warn!("Vesktop & arRPC doesn't support fetching user info"); 62 | warn!("You can supply the 'DISCORD' env variable manually"); 63 | warn!("The User ID will default to the developer: ShayBox"); 64 | } 65 | } else { 66 | warn!("Error: Discord RPC Connection Failed\n"); 67 | warn!("This may be due to one of the following reasons:"); 68 | warn!("1. Discord is not running on your system."); 69 | warn!("2. VRC-LOG was restarted too quickly.\n"); 70 | warn!("The User ID will default to the developer: ShayBox"); 71 | } 72 | 73 | Some(String::from(DEVELOPER_ID)) 74 | } 75 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate tracing; 3 | 4 | use std::{ 5 | collections::VecDeque, 6 | env::Args, 7 | fs::File, 8 | io::{BufRead, BufReader, Error}, 9 | path::{Path, PathBuf}, 10 | process::{Command, Stdio}, 11 | sync::LazyLock, 12 | time::Duration, 13 | }; 14 | 15 | use anyhow::{bail, Result}; 16 | use chrono::Local; 17 | use colored::{Color, Colorize}; 18 | use crossbeam::channel::{Receiver, Sender}; 19 | use lazy_regex::{lazy_regex, regex_replace_all, Lazy, Regex}; 20 | use notify::{Config, Event, PollWatcher, RecursiveMode, Watcher}; 21 | use parking_lot::RwLock; 22 | use terminal_link::Link; 23 | 24 | use crate::provider::{prelude::*, Provider, Type}; 25 | 26 | #[cfg(feature = "discord")] 27 | pub mod discord; 28 | pub mod provider; 29 | pub mod vrchat; 30 | 31 | pub const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); 32 | pub const CARGO_PKG_HOMEPAGE: &str = env!("CARGO_PKG_HOMEPAGE"); 33 | pub const USER_AGENT: &str = concat!( 34 | "VRC-LOG/", 35 | env!("CARGO_PKG_VERSION"), 36 | " shaybox@shaybox.com" 37 | ); 38 | 39 | #[must_use] 40 | pub fn get_local_time() -> String { 41 | Local::now().format("%Y-%m-%d %H:%M:%S").to_string() 42 | } 43 | 44 | /// # Errors 45 | /// Will return `Err` if it couldn't get the GitHub repository. 46 | pub async fn check_for_updates() -> reqwest::Result { 47 | let response = reqwest::get(CARGO_PKG_HOMEPAGE).await?; 48 | if let Some(mut segments) = response.url().path_segments() { 49 | if let Some(remote_version) = segments.next_back() { 50 | return Ok(remote_version > CARGO_PKG_VERSION); 51 | } 52 | } 53 | 54 | Ok(false) 55 | } 56 | 57 | /// # Errors 58 | /// Will return `Err` if `PollWatcher::watch` errors 59 | pub fn watch>(tx: Sender, path: P) -> notify::Result { 60 | let tx_clone = tx.clone(); 61 | let mut watcher = PollWatcher::with_initial_scan( 62 | move |watch_event: notify::Result| { 63 | if let Ok(event) = watch_event { 64 | for path in event.paths { 65 | if !path.ends_with(".log") { 66 | let _ = tx.send(path); 67 | } 68 | } 69 | } 70 | }, 71 | Config::default() 72 | .with_compare_contents(true) 73 | .with_poll_interval(Duration::from_secs(1)), 74 | move |scan_event: notify::Result| { 75 | if let Ok(path) = scan_event { 76 | if !path.ends_with(".log") { 77 | let _ = tx_clone.send(path); 78 | } 79 | } 80 | }, 81 | )?; 82 | 83 | watcher.watch(path.as_ref(), RecursiveMode::NonRecursive)?; 84 | 85 | Ok(watcher) 86 | } 87 | 88 | /// Steam Game Launch Options: `.../vrc-log(.exe) %command%` 89 | /// 90 | /// # Errors 91 | /// Will return `Err` if `Command::spawn` errors 92 | /// # Panics 93 | /// Will panic if `Child::wait` panics 94 | pub fn launch_game(args: Args) -> Result<()> { 95 | let args = args.collect::>(); 96 | if args.len() > 1 { 97 | let mut child = Command::new(&args[1]) 98 | .args(args.iter().skip(2)) 99 | .stderr(Stdio::null()) 100 | .stdout(Stdio::null()) 101 | .spawn()?; 102 | 103 | std::thread::spawn(move || { 104 | child.wait().unwrap(); 105 | std::process::exit(0); 106 | }); 107 | } 108 | 109 | Ok(()) 110 | } 111 | 112 | /// # Errors 113 | /// Will return `Err` if `Sqlite::new` or `Provider::send_avatar_id` errors 114 | pub async fn process_avatars((_tx, rx): (Sender, Receiver)) -> Result<()> { 115 | #[cfg(feature = "cache")] 116 | let cache = Cache::new().await?; 117 | 118 | #[cfg(feature = "avtrdb")] 119 | let avtrdb = AvtrDB::default(); 120 | 121 | #[cfg(feature = "vrcdb")] 122 | let vrcdb = VrcDB::default(); 123 | 124 | #[cfg(feature = "vrcds")] 125 | let vrcds = VrcDS::default(); 126 | 127 | #[cfg(feature = "vrcwb")] 128 | let vrcwb = VrcWB::default(); 129 | 130 | #[cfg(feature = "paw")] 131 | let paw = Paw::default(); 132 | 133 | let providers = VecDeque::from([ 134 | #[cfg(feature = "avtrdb")] 135 | Type::AVTRDB(&avtrdb), 136 | #[cfg(feature = "vrcdb")] 137 | Type::VRCDB(&vrcdb), 138 | #[cfg(feature = "vrcds")] 139 | Type::VRCDS(&vrcds), 140 | #[cfg(feature = "vrcwb")] 141 | Type::VRCWB(&vrcwb), 142 | #[cfg(feature = "paw")] 143 | Type::PAW(&paw), 144 | ]); 145 | 146 | while let Ok(path) = rx.recv() { 147 | for avatar_id in parse_avatar_ids(&path) { 148 | #[cfg(feature = "cache")] // Avatar already in cache 149 | if !cache.check_avatar_id(&avatar_id).await? { 150 | continue; 151 | } 152 | 153 | #[cfg(feature = "cache")] // Don't send to cache if sending failed 154 | let mut send_to_cache = true; 155 | 156 | print_colorized(&avatar_id); 157 | 158 | // Collect all provider futures for this avatar_id 159 | let futures = providers 160 | .iter() 161 | .map(|provider| provider.send_avatar_id(&avatar_id)); 162 | let results = futures::future::join_all(futures).await; 163 | 164 | for (provider, result) in providers.iter().zip(results) { 165 | match result { 166 | Ok(unique) => { 167 | if unique { 168 | info!("^ Successfully Submitted to {provider}"); 169 | } 170 | } 171 | Err(error) => { 172 | #[cfg(feature = "cache")] 173 | { 174 | send_to_cache = false; 175 | } 176 | error!("^ Failed to submit to {provider}: {error}"); 177 | } 178 | } 179 | } 180 | 181 | #[cfg(feature = "cache")] 182 | if send_to_cache { 183 | cache.send_avatar_id(&avatar_id).await?; 184 | } 185 | } 186 | } 187 | 188 | bail!("Channel Closed") 189 | } 190 | 191 | /// # Errors 192 | /// Will return `Err` if `std::fs::canonicalize` errors 193 | /// 194 | /// # Panics 195 | /// Will panic if an environment variable doesn't exist 196 | pub fn parse_path_env(path: &str) -> Result { 197 | let path = regex_replace_all!(r"(?:\$|%)(\w+)%?", path, |_, env| { 198 | std::env::var(env).unwrap_or_else(|_| panic!("Environment Variable not found: {env}")) 199 | }); 200 | 201 | std::fs::canonicalize(path.as_ref()) 202 | } 203 | 204 | #[must_use] 205 | pub fn parse_avatar_ids(path: &PathBuf) -> Vec { 206 | static RE: Lazy = lazy_regex!(r"avtr_\w{8}-\w{4}-\w{4}-\w{4}-\w{12}"); 207 | 208 | let Ok(file) = File::open(path) else { 209 | return Vec::new(); // Directory 210 | }; 211 | 212 | let mut reader = BufReader::new(file); 213 | let mut avatar_ids = Vec::new(); 214 | let mut buf = Vec::new(); 215 | 216 | while reader.read_until(b'\n', &mut buf).unwrap_or(0) > 0 { 217 | let line = String::from_utf8_lossy(&buf); 218 | for mat in RE.find_iter(&line) { 219 | avatar_ids.push(mat.as_str().to_string()); 220 | } 221 | buf.clear(); 222 | } 223 | 224 | avatar_ids 225 | } 226 | 227 | /// # Print with colorized rainbow rows for separation 228 | pub fn print_colorized(avatar_id: &str) { 229 | static INDEX: LazyLock> = LazyLock::new(|| RwLock::new(0)); 230 | static COLORS: LazyLock<[Color; 12]> = LazyLock::new(|| { 231 | [ 232 | Color::Red, 233 | Color::BrightRed, 234 | Color::Yellow, 235 | Color::BrightYellow, 236 | Color::Green, 237 | Color::BrightGreen, 238 | Color::Blue, 239 | Color::BrightBlue, 240 | Color::Cyan, 241 | Color::BrightCyan, 242 | Color::Magenta, 243 | Color::BrightMagenta, 244 | ] 245 | }); 246 | 247 | let index = *INDEX.read(); 248 | let color = COLORS[index]; 249 | *INDEX.write() = (index + 1) % COLORS.len(); 250 | 251 | let text = format!("vrcx://avatar/{avatar_id}"); 252 | let link = Link::new(&text, &text).to_string().color(color); 253 | info!("{link}"); 254 | } 255 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate tracing; 3 | 4 | use std::sync::OnceLock; 5 | 6 | use anyhow::Result; 7 | use chrono::{Local, Offset}; 8 | #[cfg(feature = "title")] 9 | use crossterm::{execute, terminal::SetTitle}; 10 | use notify::PollWatcher; 11 | use terminal_link::Link; 12 | use time::{macros::format_description, UtcOffset}; 13 | use tracing::level_filters::LevelFilter; 14 | use tracing_subscriber::{fmt::time::OffsetTime, EnvFilter}; 15 | use vrc_log::{ 16 | vrchat::{VRCHAT_AMP_PATH, VRCHAT_LOW_PATH}, 17 | CARGO_PKG_HOMEPAGE, 18 | }; 19 | 20 | /* Watchers will stop working if they get dropped. */ 21 | static WATCHERS: OnceLock> = OnceLock::new(); 22 | 23 | #[tokio::main] 24 | async fn main() -> Result<()> { 25 | #[cfg(feature = "title")] 26 | execute!(std::io::stdout(), SetTitle("VRC-LOG"))?; 27 | 28 | /* Debugging: RUST_LOG=vrc_log=debug */ 29 | tracing_subscriber::fmt() 30 | .with_env_filter( 31 | EnvFilter::builder() 32 | .with_default_directive(LevelFilter::INFO.into()) 33 | .from_env_lossy(), 34 | ) 35 | .with_target(false) 36 | .with_timer(OffsetTime::new( 37 | UtcOffset::from_whole_seconds(Local::now().offset().fix().local_minus_utc())?, 38 | format_description!("[hour repr:12]:[minute]:[second] [period]"), 39 | )) 40 | .init(); 41 | 42 | if vrc_log::check_for_updates().await? { 43 | let text = "An update is available"; 44 | let link = Link::new(text, CARGO_PKG_HOMEPAGE); 45 | info!("{link}"); 46 | } 47 | 48 | let args = std::env::args(); 49 | let (tx, rx) = crossbeam::channel::unbounded(); 50 | let _ = WATCHERS.set(vec![ 51 | vrc_log::watch(tx.clone(), VRCHAT_AMP_PATH.as_path())?, 52 | vrc_log::watch(tx.clone(), VRCHAT_LOW_PATH.as_path())?, 53 | ]); 54 | 55 | vrc_log::launch_game(args)?; 56 | vrc_log::process_avatars((tx, rx)).await 57 | } 58 | -------------------------------------------------------------------------------- /src/provider/avtrdb.rs: -------------------------------------------------------------------------------- 1 | use std::{time::Duration, vec}; 2 | 3 | use anyhow::{bail, Result}; 4 | use async_trait::async_trait; 5 | use reqwest::{Client, StatusCode, Url}; 6 | use serde::{Deserialize, Serialize}; 7 | 8 | use crate::{ 9 | provider::{Provider, Type}, 10 | USER_AGENT, 11 | }; 12 | 13 | const URL: &str = "https://api.avtrdb.com/v2/"; 14 | 15 | pub struct AvtrDB { 16 | attribution: Option, 17 | client: Client, 18 | url: Url, 19 | } 20 | 21 | impl AvtrDB { 22 | #[must_use] 23 | pub fn new(attribution: Option, url: Url) -> Self { 24 | Self { 25 | attribution, 26 | url, 27 | ..Default::default() 28 | } 29 | } 30 | } 31 | 32 | impl Default for AvtrDB { 33 | fn default() -> Self { 34 | // Only alphanumeric strings up to 30 characters or nothing are allowed. 35 | // if these conditions are not met, the given avatars will not be ingested. 36 | let attribution = std::env::var("AVTRDB_ATTRIBUTION") 37 | .ok() 38 | .or_else(crate::discord::get_user_id); 39 | 40 | Self { 41 | attribution, 42 | url: Url::parse(URL).expect("Failed to parse URL"), 43 | client: Client::builder() 44 | .timeout(Duration::from_secs(10)) 45 | .user_agent(USER_AGENT) 46 | .build() 47 | .unwrap(), 48 | } 49 | } 50 | } 51 | 52 | #[derive(Debug, Serialize)] 53 | struct AvtrDBRequest { 54 | avatar_ids: Vec, 55 | attribution: Option, 56 | } 57 | 58 | #[derive(Debug, Deserialize)] 59 | struct AvtrDBResponse { 60 | valid_avatar_ids: u64, 61 | } 62 | 63 | #[derive(Debug, Deserialize)] 64 | struct AvtrDBSearchResponse { 65 | avatars: Vec, 66 | } 67 | 68 | #[async_trait] 69 | impl Provider for AvtrDB { 70 | async fn check_avatar_id(&self, avatar_id: &str) -> Result { 71 | let name = Type::AVTRDB(self); 72 | let mut url = self.url.join("avatar/search")?; 73 | url.set_query(Some(format!("query={avatar_id}").as_str())); 74 | 75 | let response = self.client.get(url).send().await?; 76 | let status = response.status(); 77 | let text = response.text().await?; 78 | debug!("[{name}] {status} | {text}"); 79 | 80 | if status != StatusCode::OK { 81 | bail!("[{name}] Failed to check avatar: {status} | {text}"); 82 | } 83 | 84 | let data = serde_json::from_str::(&text)?; 85 | 86 | Ok(data.avatars.len() == 1) 87 | } 88 | 89 | // The API supports batching, but this interface does not 90 | // FIXME: adapt ProviderTrait to support batching 91 | async fn send_avatar_id(&self, avatar_id: &str) -> Result { 92 | let name = Type::AVTRDB(self); 93 | let request = AvtrDBRequest { 94 | avatar_ids: vec![avatar_id.to_string()], 95 | attribution: self.attribution.clone(), 96 | }; 97 | 98 | debug!("[{name}] Sending {:#?}", serde_json::to_string(&request)?); 99 | 100 | let response = self 101 | .client 102 | .post(self.url.join("avatar/ingest")?) 103 | .json(&request) 104 | .timeout(Duration::from_secs(3)) 105 | .send() 106 | .await?; 107 | 108 | let status = response.status(); 109 | let text = response.text().await?; 110 | let data = serde_json::from_str::(&text)?; 111 | debug!("[{name}] {status} | {text}"); 112 | 113 | let unique = match status { 114 | StatusCode::OK => data.valid_avatar_ids == 1, 115 | StatusCode::TOO_MANY_REQUESTS => { 116 | warn!("[{name}] 429 Rate Limit, trying again in 10 seconds"); 117 | tokio::time::sleep(Duration::from_secs(10)).await; 118 | Box::pin(self.send_avatar_id(avatar_id)).await? 119 | } 120 | _ => bail!("[{name}] Unknown Error: {status} | {text}"), 121 | }; 122 | 123 | Ok(unique) 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/provider/cache.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use async_trait::async_trait; 3 | use tokio_rusqlite_new::{Connection, Error}; 4 | 5 | use crate::{provider::Provider, vrchat::VRCHAT_LOW_PATH}; 6 | 7 | pub struct Cache { 8 | connection: Connection, 9 | } 10 | 11 | impl Cache { 12 | /// # Errors 13 | /// Will return `Err` if `sqlite::open` errors 14 | pub async fn new() -> Result { 15 | let path = VRCHAT_LOW_PATH.join("avatars.sqlite"); 16 | let connection = Connection::open(path).await?; 17 | 18 | connection 19 | .call(|connection| { 20 | let query = "CREATE TABLE avatars ( 21 | id TEXT PRIMARY KEY, 22 | created_at DATETIME DEFAULT CURRENT_TIMESTAMP, 23 | updated_at DATETIME DEFAULT CURRENT_TIMESTAMP 24 | )"; 25 | 26 | // Create the table if it doesn't exist 27 | if connection.execute(query, []).is_err() { 28 | // Ensure `created_at` and `updated_at` columns exist 29 | let mut statement = connection.prepare("PRAGMA table_info(avatars)")?; 30 | let columns = statement 31 | .query_map([], |row| row.get::<_, String>(1))? 32 | .collect::, _>>()?; 33 | 34 | if !columns.contains(&"created_at".to_string()) { 35 | #[rustfmt::skip] 36 | connection.execute(" 37 | ALTER TABLE avatars 38 | ADD COLUMN created_at DATETIME 39 | ", [])?; 40 | } 41 | 42 | #[rustfmt::skip] 43 | connection.execute(" 44 | UPDATE avatars 45 | SET created_at = CURRENT_TIMESTAMP 46 | WHERE created_at IS NULL 47 | ", [])?; 48 | 49 | if !columns.contains(&"updated_at".to_string()) { 50 | #[rustfmt::skip] 51 | connection.execute(" 52 | ALTER TABLE avatars 53 | ADD COLUMN updated_at DATETIME 54 | ", [])?; 55 | } 56 | 57 | #[rustfmt::skip] // Prevent a large burst after updating 58 | connection.execute(" 59 | UPDATE avatars 60 | SET updated_at = datetime('now', '-31 days') 61 | WHERE updated_at IS NULL 62 | ", [])?; 63 | 64 | // Print cache statistics 65 | if let Ok(mut statement) = connection.prepare("SELECT COUNT(*) FROM avatars") { 66 | if let Ok(count) = statement.query_row([], |row| row.get::<_, i64>(0)) { 67 | info!("{} Cached Avatars", count); 68 | } 69 | } 70 | } 71 | 72 | Ok::<(), Error>(()) 73 | }) 74 | .await?; 75 | 76 | Ok(Self { connection }) 77 | } 78 | } 79 | 80 | #[async_trait] 81 | impl Provider for Cache { 82 | async fn check_avatar_id(&self, avatar_id: &str) -> Result { 83 | let id = avatar_id.to_string(); 84 | let query = " 85 | SELECT 1 FROM avatars 86 | WHERE id = (?) AND updated_at >= datetime('now', '-30 days') 87 | LIMIT 1 88 | "; 89 | 90 | let is_ok = self 91 | .connection 92 | .call(move |c| Ok::(c.execute(query, [id]).is_ok())) 93 | .await?; 94 | 95 | Ok(is_ok) 96 | } 97 | 98 | async fn send_avatar_id(&self, avatar_id: &str) -> Result { 99 | let id = avatar_id.to_string(); 100 | let query = " 101 | INSERT INTO avatars (id, created_at, updated_at) 102 | VALUES (?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) 103 | ON CONFLICT (id) DO UPDATE SET updated_at = CURRENT_TIMESTAMP 104 | "; 105 | 106 | let is_ok = self 107 | .connection 108 | .call(move |c| Ok::(c.execute(query, [id]).is_ok())) 109 | .await?; 110 | 111 | Ok(is_ok) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/provider/mod.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use async_trait::async_trait; 3 | use strum::Display; 4 | 5 | use crate::provider::prelude::*; 6 | 7 | #[cfg(feature = "avtrdb")] 8 | pub mod avtrdb; 9 | #[cfg(feature = "cache")] 10 | pub mod cache; 11 | #[cfg(feature = "vrcdb")] 12 | pub mod vrcdb; 13 | #[cfg(feature = "vrcds")] 14 | pub mod vrcds; 15 | #[cfg(feature = "vrcwb")] 16 | pub mod vrcwb; 17 | #[cfg(feature = "paw")] 18 | pub mod paw; 19 | 20 | pub mod prelude; 21 | 22 | #[derive(Display)] 23 | pub enum Type<'a> { 24 | #[cfg(feature = "cache")] 25 | CACHE(&'a Cache), 26 | #[cfg(feature = "avtrdb")] 27 | #[strum(to_string = "avtrDB - Avatar Search")] 28 | AVTRDB(&'a AvtrDB), 29 | #[cfg(feature = "vrcdb")] 30 | #[strum(to_string = "VRCDB - Avatar Search")] 31 | VRCDB(&'a VrcDB), 32 | #[cfg(feature = "vrcds")] 33 | #[strum(to_string = "VRCDS - Project Dark Star")] 34 | VRCDS(&'a VrcDS), 35 | #[cfg(feature = "vrcwb")] 36 | #[strum(to_string = "VRCWB - World Balancer")] 37 | VRCWB(&'a VrcWB), 38 | #[cfg(feature = "paw")] 39 | #[strum(to_string = "PAW - Puppy's Avatar World")] 40 | PAW(&'a Paw), 41 | } 42 | 43 | #[async_trait] 44 | pub trait Provider { 45 | /// # Check if the avatar ID is unique or not. 46 | /// True: New/Unique | False: Duplicate/Existing. 47 | /// 48 | /// # Errors 49 | /// Will return `Err` if anything errors 50 | async fn check_avatar_id(&self, avatar_id: &str) -> Result; 51 | 52 | /// # Send avatar ID to the provider 53 | /// True: New/Unique | False: Duplicate/Existing. 54 | /// 55 | /// # Errors 56 | /// Will return `Err` if anything errors 57 | async fn send_avatar_id(&self, avatar_id: &str) -> Result; 58 | } 59 | 60 | #[async_trait] 61 | impl Provider for Type<'_> { 62 | async fn check_avatar_id(&self, avatar_id: &str) -> Result { 63 | match self { 64 | #[cfg(feature = "cache")] 65 | Type::CACHE(p) => p.check_avatar_id(avatar_id).await, 66 | _ => Ok(true), 67 | } 68 | } 69 | 70 | async fn send_avatar_id(&self, avatar_id: &str) -> Result { 71 | match self { 72 | #[cfg(feature = "cache")] 73 | Type::CACHE(p) => p.send_avatar_id(avatar_id).await, 74 | #[cfg(feature = "avtrdb")] 75 | Type::AVTRDB(p) => p.send_avatar_id(avatar_id).await, 76 | #[cfg(feature = "vrcdb")] 77 | Type::VRCDB(p) => p.send_avatar_id(avatar_id).await, 78 | #[cfg(feature = "vrcds")] 79 | Type::VRCDS(p) => p.send_avatar_id(avatar_id).await, 80 | #[cfg(feature = "vrcwb")] 81 | Type::VRCWB(p) => p.send_avatar_id(avatar_id).await, 82 | #[cfg(feature = "paw")] 83 | Type::PAW(p) => p.send_avatar_id(avatar_id).await, 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/provider/paw.rs: -------------------------------------------------------------------------------- 1 | use std::{time::Duration}; 2 | 3 | use anyhow::{bail, Result}; 4 | use async_trait::async_trait; 5 | use reqwest::{Client, StatusCode}; 6 | use serde::Deserialize; 7 | 8 | use crate::{ 9 | provider::{Provider, Type}, 10 | USER_AGENT, 11 | }; 12 | 13 | const URL: &str = "https://paw-api.amelia.fun/update"; 14 | const AVATAR_URL: &str = "https://paw-api.amelia.fun/avatar"; 15 | 16 | pub struct Paw { 17 | client: Client, 18 | } 19 | 20 | impl Default for Paw { 21 | fn default() -> Self { 22 | Self { 23 | client: Client::default(), 24 | } 25 | } 26 | } 27 | 28 | #[derive(Debug, Deserialize)] 29 | struct PawResponse { 30 | success: bool, 31 | code: u16, 32 | result: Option, 33 | avatar: Option, 34 | } 35 | 36 | #[async_trait] 37 | impl Provider for Paw { 38 | async fn check_avatar_id(&self, _avatar_id: &str) -> Result { 39 | let name = Type::PAW(self); 40 | let response = self 41 | .client 42 | .get(AVATAR_URL) 43 | .header("User-Agent", USER_AGENT) 44 | .query(&[("avatarId", _avatar_id)]) 45 | .timeout(Duration::from_secs(3)) 46 | .send() 47 | .await?; 48 | 49 | let status = response.status(); 50 | let text = response.text().await?; 51 | debug!("[{name}] {status} | {text}"); 52 | 53 | if status != StatusCode::OK { 54 | bail!("[{name}] Failed to check avatar: {status} | {text}"); 55 | } 56 | 57 | let data = serde_json::from_str::(&text)?; 58 | 59 | Ok(data.success && data.code == 200 && data.result.is_some()) 60 | } 61 | 62 | async fn send_avatar_id(&self, avatar_id: &str) -> Result { 63 | let name = Type::PAW(self); 64 | let response = self 65 | .client 66 | .post(URL) 67 | .header("User-Agent", USER_AGENT) 68 | .query(&[("avatarId", avatar_id)]) 69 | .timeout(Duration::from_secs(3)) 70 | .send() 71 | .await?; 72 | 73 | let status = response.status(); 74 | let text = response.text().await?; 75 | debug!("[{name}] {status} | {text}"); 76 | 77 | let unique = match status { 78 | StatusCode::OK => { 79 | let data = serde_json::from_str::(&text)?; 80 | 81 | !matches!(data.avatar.as_ref(), Some(avatar) if !avatar.is_null() && !(avatar.is_array() && avatar.as_array().unwrap().is_empty())) 82 | }, 83 | StatusCode::TOO_MANY_REQUESTS => { 84 | warn!("[{name}] 429 Rate Limit, Please Wait 10 seconds..."); 85 | tokio::time::sleep(Duration::from_secs(10)).await; 86 | Box::pin(self.send_avatar_id(avatar_id)).await? 87 | } 88 | _ => bail!("[{name}] {status} | {text}"), 89 | }; 90 | 91 | Ok(unique) 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/provider/prelude.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "avtrdb")] 2 | pub use super::avtrdb::AvtrDB; 3 | #[cfg(feature = "cache")] 4 | pub use super::cache::Cache; 5 | #[cfg(feature = "vrcdb")] 6 | pub use super::vrcdb::VrcDB; 7 | #[cfg(feature = "vrcds")] 8 | pub use super::vrcds::VrcDS; 9 | #[cfg(feature = "vrcwb")] 10 | pub use super::vrcwb::VrcWB; 11 | #[cfg(feature = "paw")] 12 | pub use super::paw::Paw; -------------------------------------------------------------------------------- /src/provider/vrcdb.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, time::Duration}; 2 | 3 | use anyhow::{bail, Result}; 4 | use async_trait::async_trait; 5 | use reqwest::{Client, StatusCode}; 6 | 7 | use crate::{ 8 | provider::{Provider, Type}, 9 | USER_AGENT, 10 | }; 11 | 12 | const URL: &str = "https://search.bs002.de/api/Avatar/putavatar"; 13 | 14 | pub struct VrcDB { 15 | client: Client, 16 | userid: String, 17 | } 18 | 19 | impl Default for VrcDB { 20 | fn default() -> Self { 21 | Self { 22 | client: Client::default(), 23 | userid: crate::discord::get_user_id().unwrap(), 24 | } 25 | } 26 | } 27 | 28 | #[async_trait] 29 | impl Provider for VrcDB { 30 | async fn check_avatar_id(&self, _avatar_id: &str) -> Result { 31 | bail!("Unsupported/Unused") 32 | } 33 | 34 | async fn send_avatar_id(&self, avatar_id: &str) -> Result { 35 | let name = Type::VRCDB(self); 36 | let response = self 37 | .client 38 | .put(URL) 39 | .header("User-Agent", USER_AGENT) 40 | .json(&HashMap::from([ 41 | ("id", avatar_id), 42 | ("userid", &self.userid), 43 | ])) 44 | .timeout(Duration::from_secs(3)) 45 | .send() 46 | .await?; 47 | 48 | let status = response.status(); 49 | let text = response.text().await?; 50 | debug!("[{name}] {status} | {text}"); 51 | 52 | let unique = match status { 53 | StatusCode::OK => false, 54 | StatusCode::NOT_FOUND => true, 55 | StatusCode::TOO_MANY_REQUESTS => { 56 | warn!("[{name}] 429 Rate Limit, Please Wait 1 Minute..."); 57 | tokio::time::sleep(Duration::from_secs(60)).await; 58 | Box::pin(self.send_avatar_id(avatar_id)).await? 59 | } 60 | StatusCode::INTERNAL_SERVER_ERROR => { 61 | info!("^ Pending in Queue: {name}"); 62 | debug!("New Avatars can take up to a day to be processed"); 63 | true 64 | } 65 | _ => bail!("[{name}] {status} | {text}"), 66 | }; 67 | 68 | Ok(unique) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/provider/vrcds.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, time::Duration}; 2 | 3 | use anyhow::{bail, Result}; 4 | use async_trait::async_trait; 5 | use reqwest::{Client, StatusCode}; 6 | 7 | use crate::{ 8 | provider::{Provider, Type}, 9 | USER_AGENT, 10 | }; 11 | 12 | const URL: &str = "https://avtr.nekosunevr.co.uk/v1/vrchat/avatars/store/putavatarExternal"; 13 | 14 | pub struct VrcDS { 15 | client: Client, 16 | userid: String, 17 | } 18 | 19 | impl Default for VrcDS { 20 | fn default() -> Self { 21 | Self { 22 | client: Client::default(), 23 | userid: crate::discord::get_user_id().unwrap(), 24 | } 25 | } 26 | } 27 | 28 | #[async_trait] 29 | impl Provider for VrcDS { 30 | async fn check_avatar_id(&self, _avatar_id: &str) -> Result { 31 | bail!("Unsupported/Unused") 32 | } 33 | 34 | async fn send_avatar_id(&self, avatar_id: &str) -> Result { 35 | let name = Type::VRCDS(self); 36 | let response = match self 37 | .client 38 | .post(URL) 39 | .header("User-Agent", USER_AGENT) 40 | .json(&HashMap::from([ 41 | ("id", avatar_id), 42 | ("userid", &self.userid), 43 | ])) 44 | .timeout(Duration::from_secs(3)) 45 | .send() 46 | .await 47 | { 48 | Ok(response) => response, 49 | Err(error) => { 50 | // Ignore for cache purposes, it goes offline too often. 51 | // TODO: Remove when API is more stable. 52 | warn!("[{name}] {error}"); 53 | return Ok(false); 54 | } 55 | }; 56 | 57 | let status = response.status(); 58 | let text = response.text().await?; 59 | debug!("[{name}] {status} | {text}"); 60 | 61 | let unique = match status { 62 | StatusCode::OK => false, 63 | StatusCode::NOT_FOUND => true, 64 | _ => bail!("[{name}] {status} | {text}"), 65 | }; 66 | 67 | Ok(unique) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/provider/vrcwb.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, time::Duration}; 2 | 3 | use anyhow::{bail, Result}; 4 | use async_trait::async_trait; 5 | use reqwest::{Client, StatusCode}; 6 | 7 | use crate::{ 8 | provider::{Provider, Type}, 9 | USER_AGENT, 10 | }; 11 | 12 | const URL: &str = "https://avatar.worldbalancer.com/v1/vrchat/avatars/store/putavatarExternal"; 13 | 14 | pub struct VrcWB { 15 | client: Client, 16 | userid: String, 17 | } 18 | 19 | impl Default for VrcWB { 20 | fn default() -> Self { 21 | Self { 22 | client: Client::default(), 23 | userid: crate::discord::get_user_id().unwrap(), 24 | } 25 | } 26 | } 27 | 28 | #[async_trait] 29 | impl Provider for VrcWB { 30 | async fn check_avatar_id(&self, _avatar_id: &str) -> Result { 31 | bail!("Unsupported/Unused") 32 | } 33 | 34 | async fn send_avatar_id(&self, avatar_id: &str) -> Result { 35 | let name = Type::VRCWB(self); 36 | let response = self 37 | .client 38 | .post(URL) 39 | .header("User-Agent", USER_AGENT) 40 | .json(&HashMap::from([ 41 | ("id", avatar_id), 42 | ("userid", &self.userid), 43 | ])) 44 | .timeout(Duration::from_secs(3)) 45 | .send() 46 | .await?; 47 | 48 | let status = response.status(); 49 | let text = response.text().await?; 50 | debug!("[{name}] {status} | {text}"); 51 | 52 | let unique = match status { 53 | StatusCode::OK => false, 54 | StatusCode::NOT_FOUND => true, 55 | StatusCode::TOO_MANY_REQUESTS => { 56 | warn!("[{name}] 429 Rate Limit, Please Wait 1 Minute..."); 57 | tokio::time::sleep(Duration::from_secs(60)).await; 58 | Box::pin(self.send_avatar_id(avatar_id)).await? 59 | } 60 | _ => bail!("[{name}] {status} | {text}"), 61 | }; 62 | 63 | Ok(unique) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/vrchat.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | fs::File, 3 | io::{Error, Read, Seek}, 4 | path::PathBuf, 5 | sync::LazyLock, 6 | }; 7 | 8 | use anyhow::Context; 9 | use serde::{Deserialize, Deserializer, Serialize}; 10 | 11 | #[cfg(target_os = "windows")] 12 | const AMP_PATH: &str = "%Temp%\\VRChat\\VRChat\\amplitude.cache"; 13 | 14 | #[cfg(target_os = "linux")] 15 | const AMP_PATH: &str = "$HOME/.local/share/Steam/steamapps/compatdata/438100/pfx/drive_c/users/steamuser/Temp/VRChat/VRChat/amplitude.cache"; 16 | 17 | #[cfg(target_os = "windows")] 18 | const LOW_PATH: &str = "%AppData%\\..\\LocalLow\\VRChat\\VRChat"; 19 | 20 | #[cfg(target_os = "linux")] 21 | const LOW_PATH: &str = "$HOME/.local/share/Steam/steamapps/compatdata/438100/pfx/drive_c/users/steamuser/AppData/LocalLow/VRChat/VRChat"; 22 | 23 | pub static VRCHAT_AMP_PATH: LazyLock = 24 | LazyLock::new(|| crate::parse_path_env(AMP_PATH).expect("Failed to parse amplitude path")); 25 | 26 | /// This is a static path and cannot be changed (without symlinks) 27 | pub static VRCHAT_LOW_PATH: LazyLock = 28 | LazyLock::new(|| crate::parse_path_env(LOW_PATH).expect("Failed to parse local low path")); 29 | 30 | #[derive(Clone, Debug, Deserialize, Serialize)] 31 | pub struct VRChat { 32 | /// This is actually the path to the cache parent directory 33 | /// `VRChat` doesn't allow you to change the cache directory name 34 | /// The `Cache-WindowsPlayer` path is appended during deserialization below 35 | /// Because this is how `VRChat` does it, it must not be in the config file 36 | #[serde(deserialize_with = "deserialize")] 37 | pub cache_directory: PathBuf, 38 | } 39 | 40 | /// Try to deserialize the `VRChat` `config.json` `cache_directory`, `parse_path_env`, and append `Cache-WindowsPlayer` 41 | /// 42 | /// # Errors 43 | /// Will return `Err` if `crate::parse_path_env` errors 44 | pub fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result { 45 | let haystack = String::deserialize(deserializer)?; 46 | let path = crate::parse_path_env(&haystack) 47 | .context("Failed to parse the default path") 48 | .map_err(serde::de::Error::custom)? 49 | .join("Cache-WindowsPlayer"); 50 | 51 | Ok(path) 52 | } 53 | 54 | impl VRChat { 55 | #[must_use] 56 | pub fn get_path() -> PathBuf { 57 | VRCHAT_LOW_PATH.join("config.json") 58 | } 59 | 60 | /// Try to load the `VRChat` `config.json` file for the `cache_directory` field 61 | /// 62 | /// # Errors 63 | /// Will return `Err` if `File::open`, `File::read_to_string`, or `File::rewind` errors 64 | pub fn load() -> Result { 65 | let path = Self::get_path(); 66 | let mut file = File::options() 67 | .read(true) 68 | .write(true) 69 | .create(true) 70 | .truncate(false) 71 | .open(path)?; 72 | 73 | let mut text = String::new(); 74 | file.read_to_string(&mut text)?; 75 | file.rewind()?; 76 | 77 | // Fallback to default below if config fails to deserialize 78 | serde_json::from_str(&text).map_or_else(|_| Ok(Self::default()), Ok) 79 | } 80 | } 81 | 82 | impl Default for VRChat { 83 | fn default() -> Self { 84 | Self { 85 | cache_directory: VRCHAT_LOW_PATH.join("Cache-WindowsPlayer"), 86 | } 87 | } 88 | } 89 | --------------------------------------------------------------------------------