This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

Convert from Python to Rust

+3006 -359
+2599
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 = "adler2" 7 + version = "2.0.1" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" 10 + 11 + [[package]] 12 + name = "aho-corasick" 13 + version = "1.1.4" 14 + source = "registry+https://github.com/rust-lang/crates.io-index" 15 + checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" 16 + dependencies = [ 17 + "memchr", 18 + ] 19 + 20 + [[package]] 21 + name = "allocator-api2" 22 + version = "0.2.21" 23 + source = "registry+https://github.com/rust-lang/crates.io-index" 24 + checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" 25 + 26 + [[package]] 27 + name = "android_system_properties" 28 + version = "0.1.5" 29 + source = "registry+https://github.com/rust-lang/crates.io-index" 30 + checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 31 + dependencies = [ 32 + "libc", 33 + ] 34 + 35 + [[package]] 36 + name = "anyhow" 37 + version = "1.0.102" 38 + source = "registry+https://github.com/rust-lang/crates.io-index" 39 + checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" 40 + 41 + [[package]] 42 + name = "async-compression" 43 + version = "0.4.42" 44 + source = "registry+https://github.com/rust-lang/crates.io-index" 45 + checksum = "e79b3f8a79cccc2898f31920fc69f304859b3bd567490f75ebf51ae1c792a9ac" 46 + dependencies = [ 47 + "compression-codecs", 48 + "compression-core", 49 + "pin-project-lite", 50 + "tokio", 51 + ] 52 + 53 + [[package]] 54 + name = "async-lock" 55 + version = "3.4.2" 56 + source = "registry+https://github.com/rust-lang/crates.io-index" 57 + checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" 58 + dependencies = [ 59 + "event-listener", 60 + "event-listener-strategy", 61 + "pin-project-lite", 62 + ] 63 + 64 + [[package]] 65 + name = "atomic-waker" 66 + version = "1.1.2" 67 + source = "registry+https://github.com/rust-lang/crates.io-index" 68 + checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 69 + 70 + [[package]] 71 + name = "atrium-api" 72 + version = "0.25.8" 73 + source = "registry+https://github.com/rust-lang/crates.io-index" 74 + checksum = "e04c38c6bfc922a7950a13ad52f8d21bee77020b90e822364c7ec8625c4cd403" 75 + dependencies = [ 76 + "atrium-common", 77 + "atrium-xrpc", 78 + "chrono", 79 + "http", 80 + "ipld-core", 81 + "langtag", 82 + "regex", 83 + "serde", 84 + "serde_bytes", 85 + "serde_json", 86 + "thiserror 1.0.69", 87 + "tokio", 88 + "trait-variant", 89 + ] 90 + 91 + [[package]] 92 + name = "atrium-common" 93 + version = "0.1.4" 94 + source = "registry+https://github.com/rust-lang/crates.io-index" 95 + checksum = "98466259d2e6189ddf3439b96432d5303668b4d51c2a78996934d981065550f3" 96 + dependencies = [ 97 + "dashmap", 98 + "lru", 99 + "moka", 100 + "thiserror 1.0.69", 101 + "tokio", 102 + "trait-variant", 103 + "web-time", 104 + ] 105 + 106 + [[package]] 107 + name = "atrium-xrpc" 108 + version = "0.12.4" 109 + source = "registry+https://github.com/rust-lang/crates.io-index" 110 + checksum = "944b35cc08732d40ddbb3356be9e38d11aed4b4c40c33f5b0f235e0650eff296" 111 + dependencies = [ 112 + "http", 113 + "serde", 114 + "serde_html_form", 115 + "serde_json", 116 + "thiserror 1.0.69", 117 + "trait-variant", 118 + ] 119 + 120 + [[package]] 121 + name = "atrium-xrpc-client" 122 + version = "0.5.15" 123 + source = "registry+https://github.com/rust-lang/crates.io-index" 124 + checksum = "d9d1c0ebd71047b85ccfcad936ded56179af24beb60239ab590c549d2325e679" 125 + dependencies = [ 126 + "atrium-xrpc", 127 + "reqwest", 128 + ] 129 + 130 + [[package]] 131 + name = "autocfg" 132 + version = "1.5.1" 133 + source = "registry+https://github.com/rust-lang/crates.io-index" 134 + checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" 135 + 136 + [[package]] 137 + name = "base-x" 138 + version = "0.2.11" 139 + source = "registry+https://github.com/rust-lang/crates.io-index" 140 + checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" 141 + 142 + [[package]] 143 + name = "base256emoji" 144 + version = "1.0.2" 145 + source = "registry+https://github.com/rust-lang/crates.io-index" 146 + checksum = "b5e9430d9a245a77c92176e649af6e275f20839a48389859d1661e9a128d077c" 147 + dependencies = [ 148 + "const-str", 149 + "match-lookup", 150 + ] 151 + 152 + [[package]] 153 + name = "base64" 154 + version = "0.22.1" 155 + source = "registry+https://github.com/rust-lang/crates.io-index" 156 + checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 157 + 158 + [[package]] 159 + name = "bitflags" 160 + version = "2.13.0" 161 + source = "registry+https://github.com/rust-lang/crates.io-index" 162 + checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" 163 + 164 + [[package]] 165 + name = "bluesky-avatar-updater" 166 + version = "0.1.0" 167 + dependencies = [ 168 + "anyhow", 169 + "atrium-api", 170 + "bsky-sdk", 171 + "bytes", 172 + "chrono", 173 + "cid", 174 + "dotenvy", 175 + "infer", 176 + "reqwest", 177 + "serde", 178 + "serde_json", 179 + "tokio", 180 + "tracing", 181 + "tracing-appender", 182 + "tracing-subscriber", 183 + "url", 184 + ] 185 + 186 + [[package]] 187 + name = "bsky-sdk" 188 + version = "0.1.24" 189 + source = "registry+https://github.com/rust-lang/crates.io-index" 190 + checksum = "0e3bc207e44975454fd3339789a8137161cccd73ef9414e52f7e9f95e4cb0a9a" 191 + dependencies = [ 192 + "anyhow", 193 + "atrium-api", 194 + "atrium-xrpc-client", 195 + "chrono", 196 + "psl", 197 + "regex", 198 + "serde", 199 + "serde_json", 200 + "thiserror 1.0.69", 201 + "trait-variant", 202 + "unicode-segmentation", 203 + ] 204 + 205 + [[package]] 206 + name = "bumpalo" 207 + version = "3.20.3" 208 + source = "registry+https://github.com/rust-lang/crates.io-index" 209 + checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" 210 + 211 + [[package]] 212 + name = "byteorder" 213 + version = "1.5.0" 214 + source = "registry+https://github.com/rust-lang/crates.io-index" 215 + checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 216 + 217 + [[package]] 218 + name = "bytes" 219 + version = "1.11.1" 220 + source = "registry+https://github.com/rust-lang/crates.io-index" 221 + checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" 222 + 223 + [[package]] 224 + name = "cc" 225 + version = "1.2.64" 226 + source = "registry+https://github.com/rust-lang/crates.io-index" 227 + checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f" 228 + dependencies = [ 229 + "find-msvc-tools", 230 + "shlex", 231 + ] 232 + 233 + [[package]] 234 + name = "cfb" 235 + version = "0.7.3" 236 + source = "registry+https://github.com/rust-lang/crates.io-index" 237 + checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" 238 + dependencies = [ 239 + "byteorder", 240 + "fnv", 241 + "uuid", 242 + ] 243 + 244 + [[package]] 245 + name = "cfg-if" 246 + version = "1.0.4" 247 + source = "registry+https://github.com/rust-lang/crates.io-index" 248 + checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" 249 + 250 + [[package]] 251 + name = "chrono" 252 + version = "0.4.45" 253 + source = "registry+https://github.com/rust-lang/crates.io-index" 254 + checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" 255 + dependencies = [ 256 + "iana-time-zone", 257 + "js-sys", 258 + "num-traits", 259 + "serde", 260 + "wasm-bindgen", 261 + "windows-link", 262 + ] 263 + 264 + [[package]] 265 + name = "cid" 266 + version = "0.11.3" 267 + source = "registry+https://github.com/rust-lang/crates.io-index" 268 + checksum = "21a304f95f84d169a6f31c4d0a30d784643aaa0bbc9c1e449a2c23e963ec4971" 269 + dependencies = [ 270 + "multibase", 271 + "multihash", 272 + "serde", 273 + "serde_bytes", 274 + "unsigned-varint", 275 + ] 276 + 277 + [[package]] 278 + name = "compression-codecs" 279 + version = "0.4.38" 280 + source = "registry+https://github.com/rust-lang/crates.io-index" 281 + checksum = "ce2548391e9c1929c21bf6aa2680af86fe4c1b33e6cea9ac1cfeec0bd11218cf" 282 + dependencies = [ 283 + "compression-core", 284 + "flate2", 285 + "memchr", 286 + ] 287 + 288 + [[package]] 289 + name = "compression-core" 290 + version = "0.4.32" 291 + source = "registry+https://github.com/rust-lang/crates.io-index" 292 + checksum = "cc14f565cf027a105f7a44ccf9e5b424348421a1d8952a8fc9d499d313107789" 293 + 294 + [[package]] 295 + name = "concurrent-queue" 296 + version = "2.5.0" 297 + source = "registry+https://github.com/rust-lang/crates.io-index" 298 + checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" 299 + dependencies = [ 300 + "crossbeam-utils", 301 + ] 302 + 303 + [[package]] 304 + name = "const-str" 305 + version = "0.4.3" 306 + source = "registry+https://github.com/rust-lang/crates.io-index" 307 + checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3" 308 + 309 + [[package]] 310 + name = "core-foundation" 311 + version = "0.9.4" 312 + source = "registry+https://github.com/rust-lang/crates.io-index" 313 + checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 314 + dependencies = [ 315 + "core-foundation-sys", 316 + "libc", 317 + ] 318 + 319 + [[package]] 320 + name = "core-foundation" 321 + version = "0.10.1" 322 + source = "registry+https://github.com/rust-lang/crates.io-index" 323 + checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" 324 + dependencies = [ 325 + "core-foundation-sys", 326 + "libc", 327 + ] 328 + 329 + [[package]] 330 + name = "core-foundation-sys" 331 + version = "0.8.7" 332 + source = "registry+https://github.com/rust-lang/crates.io-index" 333 + checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 334 + 335 + [[package]] 336 + name = "crc32fast" 337 + version = "1.5.0" 338 + source = "registry+https://github.com/rust-lang/crates.io-index" 339 + checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" 340 + dependencies = [ 341 + "cfg-if", 342 + ] 343 + 344 + [[package]] 345 + name = "crossbeam-channel" 346 + version = "0.5.15" 347 + source = "registry+https://github.com/rust-lang/crates.io-index" 348 + checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" 349 + dependencies = [ 350 + "crossbeam-utils", 351 + ] 352 + 353 + [[package]] 354 + name = "crossbeam-epoch" 355 + version = "0.9.18" 356 + source = "registry+https://github.com/rust-lang/crates.io-index" 357 + checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 358 + dependencies = [ 359 + "crossbeam-utils", 360 + ] 361 + 362 + [[package]] 363 + name = "crossbeam-utils" 364 + version = "0.8.21" 365 + source = "registry+https://github.com/rust-lang/crates.io-index" 366 + checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 367 + 368 + [[package]] 369 + name = "dashmap" 370 + version = "6.2.1" 371 + source = "registry+https://github.com/rust-lang/crates.io-index" 372 + checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" 373 + dependencies = [ 374 + "cfg-if", 375 + "crossbeam-utils", 376 + "hashbrown 0.14.5", 377 + "lock_api", 378 + "once_cell", 379 + "parking_lot_core", 380 + ] 381 + 382 + [[package]] 383 + name = "data-encoding" 384 + version = "2.11.0" 385 + source = "registry+https://github.com/rust-lang/crates.io-index" 386 + checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" 387 + 388 + [[package]] 389 + name = "data-encoding-macro" 390 + version = "0.1.20" 391 + source = "registry+https://github.com/rust-lang/crates.io-index" 392 + checksum = "3259c913752a86488b501ed8680446a5ed2d5aeac6e596cb23ba3800768ea32c" 393 + dependencies = [ 394 + "data-encoding", 395 + "data-encoding-macro-internal", 396 + ] 397 + 398 + [[package]] 399 + name = "data-encoding-macro-internal" 400 + version = "0.1.18" 401 + source = "registry+https://github.com/rust-lang/crates.io-index" 402 + checksum = "ccc2776f0c61eca1ca32528f85548abd1a4be8fb53d1b21c013e4f18da1e7090" 403 + dependencies = [ 404 + "data-encoding", 405 + "syn", 406 + ] 407 + 408 + [[package]] 409 + name = "deranged" 410 + version = "0.5.8" 411 + source = "registry+https://github.com/rust-lang/crates.io-index" 412 + checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" 413 + 414 + [[package]] 415 + name = "displaydoc" 416 + version = "0.2.6" 417 + source = "registry+https://github.com/rust-lang/crates.io-index" 418 + checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" 419 + dependencies = [ 420 + "proc-macro2", 421 + "quote", 422 + "syn", 423 + ] 424 + 425 + [[package]] 426 + name = "dotenvy" 427 + version = "0.15.7" 428 + source = "registry+https://github.com/rust-lang/crates.io-index" 429 + checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" 430 + 431 + [[package]] 432 + name = "encoding_rs" 433 + version = "0.8.35" 434 + source = "registry+https://github.com/rust-lang/crates.io-index" 435 + checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 436 + dependencies = [ 437 + "cfg-if", 438 + ] 439 + 440 + [[package]] 441 + name = "equivalent" 442 + version = "1.0.2" 443 + source = "registry+https://github.com/rust-lang/crates.io-index" 444 + checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 445 + 446 + [[package]] 447 + name = "errno" 448 + version = "0.3.14" 449 + source = "registry+https://github.com/rust-lang/crates.io-index" 450 + checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" 451 + dependencies = [ 452 + "libc", 453 + "windows-sys 0.61.2", 454 + ] 455 + 456 + [[package]] 457 + name = "event-listener" 458 + version = "5.4.1" 459 + source = "registry+https://github.com/rust-lang/crates.io-index" 460 + checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" 461 + dependencies = [ 462 + "concurrent-queue", 463 + "parking", 464 + "pin-project-lite", 465 + ] 466 + 467 + [[package]] 468 + name = "event-listener-strategy" 469 + version = "0.5.4" 470 + source = "registry+https://github.com/rust-lang/crates.io-index" 471 + checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" 472 + dependencies = [ 473 + "event-listener", 474 + "pin-project-lite", 475 + ] 476 + 477 + [[package]] 478 + name = "fastrand" 479 + version = "2.4.1" 480 + source = "registry+https://github.com/rust-lang/crates.io-index" 481 + checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" 482 + 483 + [[package]] 484 + name = "find-msvc-tools" 485 + version = "0.1.9" 486 + source = "registry+https://github.com/rust-lang/crates.io-index" 487 + checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" 488 + 489 + [[package]] 490 + name = "flate2" 491 + version = "1.1.9" 492 + source = "registry+https://github.com/rust-lang/crates.io-index" 493 + checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" 494 + dependencies = [ 495 + "crc32fast", 496 + "miniz_oxide", 497 + ] 498 + 499 + [[package]] 500 + name = "fnv" 501 + version = "1.0.7" 502 + source = "registry+https://github.com/rust-lang/crates.io-index" 503 + checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 504 + 505 + [[package]] 506 + name = "foldhash" 507 + version = "0.1.5" 508 + source = "registry+https://github.com/rust-lang/crates.io-index" 509 + checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" 510 + 511 + [[package]] 512 + name = "foldhash" 513 + version = "0.2.0" 514 + source = "registry+https://github.com/rust-lang/crates.io-index" 515 + checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" 516 + 517 + [[package]] 518 + name = "foreign-types" 519 + version = "0.3.2" 520 + source = "registry+https://github.com/rust-lang/crates.io-index" 521 + checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 522 + dependencies = [ 523 + "foreign-types-shared", 524 + ] 525 + 526 + [[package]] 527 + name = "foreign-types-shared" 528 + version = "0.1.1" 529 + source = "registry+https://github.com/rust-lang/crates.io-index" 530 + checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 531 + 532 + [[package]] 533 + name = "form_urlencoded" 534 + version = "1.2.2" 535 + source = "registry+https://github.com/rust-lang/crates.io-index" 536 + checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" 537 + dependencies = [ 538 + "percent-encoding", 539 + ] 540 + 541 + [[package]] 542 + name = "futures-channel" 543 + version = "0.3.32" 544 + source = "registry+https://github.com/rust-lang/crates.io-index" 545 + checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" 546 + dependencies = [ 547 + "futures-core", 548 + ] 549 + 550 + [[package]] 551 + name = "futures-core" 552 + version = "0.3.32" 553 + source = "registry+https://github.com/rust-lang/crates.io-index" 554 + checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" 555 + 556 + [[package]] 557 + name = "futures-macro" 558 + version = "0.3.32" 559 + source = "registry+https://github.com/rust-lang/crates.io-index" 560 + checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" 561 + dependencies = [ 562 + "proc-macro2", 563 + "quote", 564 + "syn", 565 + ] 566 + 567 + [[package]] 568 + name = "futures-sink" 569 + version = "0.3.32" 570 + source = "registry+https://github.com/rust-lang/crates.io-index" 571 + checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" 572 + 573 + [[package]] 574 + name = "futures-task" 575 + version = "0.3.32" 576 + source = "registry+https://github.com/rust-lang/crates.io-index" 577 + checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" 578 + 579 + [[package]] 580 + name = "futures-util" 581 + version = "0.3.32" 582 + source = "registry+https://github.com/rust-lang/crates.io-index" 583 + checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" 584 + dependencies = [ 585 + "futures-core", 586 + "futures-macro", 587 + "futures-task", 588 + "pin-project-lite", 589 + "slab", 590 + ] 591 + 592 + [[package]] 593 + name = "getrandom" 594 + version = "0.2.17" 595 + source = "registry+https://github.com/rust-lang/crates.io-index" 596 + checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" 597 + dependencies = [ 598 + "cfg-if", 599 + "libc", 600 + "wasi", 601 + ] 602 + 603 + [[package]] 604 + name = "getrandom" 605 + version = "0.4.2" 606 + source = "registry+https://github.com/rust-lang/crates.io-index" 607 + checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" 608 + dependencies = [ 609 + "cfg-if", 610 + "libc", 611 + "r-efi", 612 + "wasip2", 613 + "wasip3", 614 + ] 615 + 616 + [[package]] 617 + name = "h2" 618 + version = "0.4.14" 619 + source = "registry+https://github.com/rust-lang/crates.io-index" 620 + checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" 621 + dependencies = [ 622 + "atomic-waker", 623 + "bytes", 624 + "fnv", 625 + "futures-core", 626 + "futures-sink", 627 + "http", 628 + "indexmap", 629 + "slab", 630 + "tokio", 631 + "tokio-util", 632 + "tracing", 633 + ] 634 + 635 + [[package]] 636 + name = "hashbrown" 637 + version = "0.14.5" 638 + source = "registry+https://github.com/rust-lang/crates.io-index" 639 + checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 640 + 641 + [[package]] 642 + name = "hashbrown" 643 + version = "0.15.5" 644 + source = "registry+https://github.com/rust-lang/crates.io-index" 645 + checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" 646 + dependencies = [ 647 + "foldhash 0.1.5", 648 + ] 649 + 650 + [[package]] 651 + name = "hashbrown" 652 + version = "0.16.1" 653 + source = "registry+https://github.com/rust-lang/crates.io-index" 654 + checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" 655 + dependencies = [ 656 + "allocator-api2", 657 + "equivalent", 658 + "foldhash 0.2.0", 659 + ] 660 + 661 + [[package]] 662 + name = "hashbrown" 663 + version = "0.17.1" 664 + source = "registry+https://github.com/rust-lang/crates.io-index" 665 + checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" 666 + 667 + [[package]] 668 + name = "heck" 669 + version = "0.5.0" 670 + source = "registry+https://github.com/rust-lang/crates.io-index" 671 + checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 672 + 673 + [[package]] 674 + name = "http" 675 + version = "1.4.2" 676 + source = "registry+https://github.com/rust-lang/crates.io-index" 677 + checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" 678 + dependencies = [ 679 + "bytes", 680 + "itoa", 681 + ] 682 + 683 + [[package]] 684 + name = "http-body" 685 + version = "1.0.1" 686 + source = "registry+https://github.com/rust-lang/crates.io-index" 687 + checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 688 + dependencies = [ 689 + "bytes", 690 + "http", 691 + ] 692 + 693 + [[package]] 694 + name = "http-body-util" 695 + version = "0.1.3" 696 + source = "registry+https://github.com/rust-lang/crates.io-index" 697 + checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 698 + dependencies = [ 699 + "bytes", 700 + "futures-core", 701 + "http", 702 + "http-body", 703 + "pin-project-lite", 704 + ] 705 + 706 + [[package]] 707 + name = "httparse" 708 + version = "1.10.1" 709 + source = "registry+https://github.com/rust-lang/crates.io-index" 710 + checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 711 + 712 + [[package]] 713 + name = "hyper" 714 + version = "1.10.1" 715 + source = "registry+https://github.com/rust-lang/crates.io-index" 716 + checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" 717 + dependencies = [ 718 + "atomic-waker", 719 + "bytes", 720 + "futures-channel", 721 + "futures-core", 722 + "h2", 723 + "http", 724 + "http-body", 725 + "httparse", 726 + "itoa", 727 + "pin-project-lite", 728 + "smallvec", 729 + "tokio", 730 + "want", 731 + ] 732 + 733 + [[package]] 734 + name = "hyper-rustls" 735 + version = "0.27.9" 736 + source = "registry+https://github.com/rust-lang/crates.io-index" 737 + checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" 738 + dependencies = [ 739 + "http", 740 + "hyper", 741 + "hyper-util", 742 + "rustls", 743 + "tokio", 744 + "tokio-rustls", 745 + "tower-service", 746 + ] 747 + 748 + [[package]] 749 + name = "hyper-tls" 750 + version = "0.6.0" 751 + source = "registry+https://github.com/rust-lang/crates.io-index" 752 + checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" 753 + dependencies = [ 754 + "bytes", 755 + "http-body-util", 756 + "hyper", 757 + "hyper-util", 758 + "native-tls", 759 + "tokio", 760 + "tokio-native-tls", 761 + "tower-service", 762 + ] 763 + 764 + [[package]] 765 + name = "hyper-util" 766 + version = "0.1.20" 767 + source = "registry+https://github.com/rust-lang/crates.io-index" 768 + checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" 769 + dependencies = [ 770 + "base64", 771 + "bytes", 772 + "futures-channel", 773 + "futures-util", 774 + "http", 775 + "http-body", 776 + "hyper", 777 + "ipnet", 778 + "libc", 779 + "percent-encoding", 780 + "pin-project-lite", 781 + "socket2", 782 + "system-configuration", 783 + "tokio", 784 + "tower-service", 785 + "tracing", 786 + "windows-registry", 787 + ] 788 + 789 + [[package]] 790 + name = "iana-time-zone" 791 + version = "0.1.65" 792 + source = "registry+https://github.com/rust-lang/crates.io-index" 793 + checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" 794 + dependencies = [ 795 + "android_system_properties", 796 + "core-foundation-sys", 797 + "iana-time-zone-haiku", 798 + "js-sys", 799 + "log", 800 + "wasm-bindgen", 801 + "windows-core", 802 + ] 803 + 804 + [[package]] 805 + name = "iana-time-zone-haiku" 806 + version = "0.1.2" 807 + source = "registry+https://github.com/rust-lang/crates.io-index" 808 + checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 809 + dependencies = [ 810 + "cc", 811 + ] 812 + 813 + [[package]] 814 + name = "icu_collections" 815 + version = "2.2.0" 816 + source = "registry+https://github.com/rust-lang/crates.io-index" 817 + checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" 818 + dependencies = [ 819 + "displaydoc", 820 + "potential_utf", 821 + "utf8_iter", 822 + "yoke", 823 + "zerofrom", 824 + "zerovec", 825 + ] 826 + 827 + [[package]] 828 + name = "icu_locale_core" 829 + version = "2.2.0" 830 + source = "registry+https://github.com/rust-lang/crates.io-index" 831 + checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" 832 + dependencies = [ 833 + "displaydoc", 834 + "litemap", 835 + "tinystr", 836 + "writeable", 837 + "zerovec", 838 + ] 839 + 840 + [[package]] 841 + name = "icu_normalizer" 842 + version = "2.2.0" 843 + source = "registry+https://github.com/rust-lang/crates.io-index" 844 + checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" 845 + dependencies = [ 846 + "icu_collections", 847 + "icu_normalizer_data", 848 + "icu_properties", 849 + "icu_provider", 850 + "smallvec", 851 + "zerovec", 852 + ] 853 + 854 + [[package]] 855 + name = "icu_normalizer_data" 856 + version = "2.2.0" 857 + source = "registry+https://github.com/rust-lang/crates.io-index" 858 + checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" 859 + 860 + [[package]] 861 + name = "icu_properties" 862 + version = "2.2.0" 863 + source = "registry+https://github.com/rust-lang/crates.io-index" 864 + checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" 865 + dependencies = [ 866 + "icu_collections", 867 + "icu_locale_core", 868 + "icu_properties_data", 869 + "icu_provider", 870 + "zerotrie", 871 + "zerovec", 872 + ] 873 + 874 + [[package]] 875 + name = "icu_properties_data" 876 + version = "2.2.0" 877 + source = "registry+https://github.com/rust-lang/crates.io-index" 878 + checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" 879 + 880 + [[package]] 881 + name = "icu_provider" 882 + version = "2.2.0" 883 + source = "registry+https://github.com/rust-lang/crates.io-index" 884 + checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" 885 + dependencies = [ 886 + "displaydoc", 887 + "icu_locale_core", 888 + "writeable", 889 + "yoke", 890 + "zerofrom", 891 + "zerotrie", 892 + "zerovec", 893 + ] 894 + 895 + [[package]] 896 + name = "id-arena" 897 + version = "2.3.0" 898 + source = "registry+https://github.com/rust-lang/crates.io-index" 899 + checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" 900 + 901 + [[package]] 902 + name = "idna" 903 + version = "1.1.0" 904 + source = "registry+https://github.com/rust-lang/crates.io-index" 905 + checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" 906 + dependencies = [ 907 + "idna_adapter", 908 + "smallvec", 909 + "utf8_iter", 910 + ] 911 + 912 + [[package]] 913 + name = "idna_adapter" 914 + version = "1.2.2" 915 + source = "registry+https://github.com/rust-lang/crates.io-index" 916 + checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" 917 + dependencies = [ 918 + "icu_normalizer", 919 + "icu_properties", 920 + ] 921 + 922 + [[package]] 923 + name = "indexmap" 924 + version = "2.14.0" 925 + source = "registry+https://github.com/rust-lang/crates.io-index" 926 + checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" 927 + dependencies = [ 928 + "equivalent", 929 + "hashbrown 0.17.1", 930 + "serde", 931 + "serde_core", 932 + ] 933 + 934 + [[package]] 935 + name = "infer" 936 + version = "0.19.0" 937 + source = "registry+https://github.com/rust-lang/crates.io-index" 938 + checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" 939 + dependencies = [ 940 + "cfb", 941 + ] 942 + 943 + [[package]] 944 + name = "ipld-core" 945 + version = "0.4.3" 946 + source = "registry+https://github.com/rust-lang/crates.io-index" 947 + checksum = "090f624976d72f0b0bb71b86d58dc16c15e069193067cb3a3a09d655246cbbda" 948 + dependencies = [ 949 + "cid", 950 + "serde", 951 + "serde_bytes", 952 + ] 953 + 954 + [[package]] 955 + name = "ipnet" 956 + version = "2.12.0" 957 + source = "registry+https://github.com/rust-lang/crates.io-index" 958 + checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" 959 + 960 + [[package]] 961 + name = "itoa" 962 + version = "1.0.18" 963 + source = "registry+https://github.com/rust-lang/crates.io-index" 964 + checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" 965 + 966 + [[package]] 967 + name = "js-sys" 968 + version = "0.3.102" 969 + source = "registry+https://github.com/rust-lang/crates.io-index" 970 + checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31" 971 + dependencies = [ 972 + "cfg-if", 973 + "futures-util", 974 + "wasm-bindgen", 975 + ] 976 + 977 + [[package]] 978 + name = "langtag" 979 + version = "0.3.4" 980 + source = "registry+https://github.com/rust-lang/crates.io-index" 981 + checksum = "ed60c85f254d6ae8450cec15eedd921efbc4d1bdf6fcf6202b9a58b403f6f805" 982 + dependencies = [ 983 + "serde", 984 + ] 985 + 986 + [[package]] 987 + name = "lazy_static" 988 + version = "1.5.0" 989 + source = "registry+https://github.com/rust-lang/crates.io-index" 990 + checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 991 + 992 + [[package]] 993 + name = "leb128fmt" 994 + version = "0.1.0" 995 + source = "registry+https://github.com/rust-lang/crates.io-index" 996 + checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" 997 + 998 + [[package]] 999 + name = "libc" 1000 + version = "0.2.186" 1001 + source = "registry+https://github.com/rust-lang/crates.io-index" 1002 + checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" 1003 + 1004 + [[package]] 1005 + name = "linux-raw-sys" 1006 + version = "0.12.1" 1007 + source = "registry+https://github.com/rust-lang/crates.io-index" 1008 + checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" 1009 + 1010 + [[package]] 1011 + name = "litemap" 1012 + version = "0.8.2" 1013 + source = "registry+https://github.com/rust-lang/crates.io-index" 1014 + checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" 1015 + 1016 + [[package]] 1017 + name = "lock_api" 1018 + version = "0.4.14" 1019 + source = "registry+https://github.com/rust-lang/crates.io-index" 1020 + checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" 1021 + dependencies = [ 1022 + "scopeguard", 1023 + ] 1024 + 1025 + [[package]] 1026 + name = "log" 1027 + version = "0.4.32" 1028 + source = "registry+https://github.com/rust-lang/crates.io-index" 1029 + checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" 1030 + 1031 + [[package]] 1032 + name = "lru" 1033 + version = "0.16.4" 1034 + source = "registry+https://github.com/rust-lang/crates.io-index" 1035 + checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" 1036 + dependencies = [ 1037 + "hashbrown 0.16.1", 1038 + ] 1039 + 1040 + [[package]] 1041 + name = "match-lookup" 1042 + version = "0.1.2" 1043 + source = "registry+https://github.com/rust-lang/crates.io-index" 1044 + checksum = "757aee279b8bdbb9f9e676796fd459e4207a1f986e87886700abf589f5abf771" 1045 + dependencies = [ 1046 + "proc-macro2", 1047 + "quote", 1048 + "syn", 1049 + ] 1050 + 1051 + [[package]] 1052 + name = "matchers" 1053 + version = "0.2.0" 1054 + source = "registry+https://github.com/rust-lang/crates.io-index" 1055 + checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" 1056 + dependencies = [ 1057 + "regex-automata", 1058 + ] 1059 + 1060 + [[package]] 1061 + name = "memchr" 1062 + version = "2.8.2" 1063 + source = "registry+https://github.com/rust-lang/crates.io-index" 1064 + checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" 1065 + 1066 + [[package]] 1067 + name = "mime" 1068 + version = "0.3.17" 1069 + source = "registry+https://github.com/rust-lang/crates.io-index" 1070 + checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1071 + 1072 + [[package]] 1073 + name = "miniz_oxide" 1074 + version = "0.8.9" 1075 + source = "registry+https://github.com/rust-lang/crates.io-index" 1076 + checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" 1077 + dependencies = [ 1078 + "adler2", 1079 + "simd-adler32", 1080 + ] 1081 + 1082 + [[package]] 1083 + name = "mio" 1084 + version = "1.2.1" 1085 + source = "registry+https://github.com/rust-lang/crates.io-index" 1086 + checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" 1087 + dependencies = [ 1088 + "libc", 1089 + "wasi", 1090 + "windows-sys 0.61.2", 1091 + ] 1092 + 1093 + [[package]] 1094 + name = "moka" 1095 + version = "0.12.15" 1096 + source = "registry+https://github.com/rust-lang/crates.io-index" 1097 + checksum = "957228ad12042ee839f93c8f257b62b4c0ab5eaae1d4fa60de53b27c9d7c5046" 1098 + dependencies = [ 1099 + "async-lock", 1100 + "crossbeam-channel", 1101 + "crossbeam-epoch", 1102 + "crossbeam-utils", 1103 + "equivalent", 1104 + "event-listener", 1105 + "futures-util", 1106 + "parking_lot", 1107 + "portable-atomic", 1108 + "smallvec", 1109 + "tagptr", 1110 + "uuid", 1111 + ] 1112 + 1113 + [[package]] 1114 + name = "multibase" 1115 + version = "0.9.2" 1116 + source = "registry+https://github.com/rust-lang/crates.io-index" 1117 + checksum = "8694bb4835f452b0e3bb06dbebb1d6fc5385b6ca1caf2e55fd165c042390ec77" 1118 + dependencies = [ 1119 + "base-x", 1120 + "base256emoji", 1121 + "data-encoding", 1122 + "data-encoding-macro", 1123 + ] 1124 + 1125 + [[package]] 1126 + name = "multihash" 1127 + version = "0.19.5" 1128 + source = "registry+https://github.com/rust-lang/crates.io-index" 1129 + checksum = "577c63b00ad74d57e8c9aa870b5fccebf2fd64a308a5aee9f1bb88e4aea19447" 1130 + dependencies = [ 1131 + "serde", 1132 + "unsigned-varint", 1133 + ] 1134 + 1135 + [[package]] 1136 + name = "native-tls" 1137 + version = "0.2.18" 1138 + source = "registry+https://github.com/rust-lang/crates.io-index" 1139 + checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" 1140 + dependencies = [ 1141 + "libc", 1142 + "log", 1143 + "openssl", 1144 + "openssl-probe", 1145 + "openssl-sys", 1146 + "schannel", 1147 + "security-framework", 1148 + "security-framework-sys", 1149 + "tempfile", 1150 + ] 1151 + 1152 + [[package]] 1153 + name = "nu-ansi-term" 1154 + version = "0.50.3" 1155 + source = "registry+https://github.com/rust-lang/crates.io-index" 1156 + checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" 1157 + dependencies = [ 1158 + "windows-sys 0.61.2", 1159 + ] 1160 + 1161 + [[package]] 1162 + name = "num-conv" 1163 + version = "0.2.2" 1164 + source = "registry+https://github.com/rust-lang/crates.io-index" 1165 + checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" 1166 + 1167 + [[package]] 1168 + name = "num-traits" 1169 + version = "0.2.19" 1170 + source = "registry+https://github.com/rust-lang/crates.io-index" 1171 + checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 1172 + dependencies = [ 1173 + "autocfg", 1174 + ] 1175 + 1176 + [[package]] 1177 + name = "once_cell" 1178 + version = "1.21.4" 1179 + source = "registry+https://github.com/rust-lang/crates.io-index" 1180 + checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" 1181 + 1182 + [[package]] 1183 + name = "openssl" 1184 + version = "0.10.81" 1185 + source = "registry+https://github.com/rust-lang/crates.io-index" 1186 + checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" 1187 + dependencies = [ 1188 + "bitflags", 1189 + "cfg-if", 1190 + "foreign-types", 1191 + "libc", 1192 + "openssl-macros", 1193 + "openssl-sys", 1194 + ] 1195 + 1196 + [[package]] 1197 + name = "openssl-macros" 1198 + version = "0.1.1" 1199 + source = "registry+https://github.com/rust-lang/crates.io-index" 1200 + checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1201 + dependencies = [ 1202 + "proc-macro2", 1203 + "quote", 1204 + "syn", 1205 + ] 1206 + 1207 + [[package]] 1208 + name = "openssl-probe" 1209 + version = "0.2.1" 1210 + source = "registry+https://github.com/rust-lang/crates.io-index" 1211 + checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" 1212 + 1213 + [[package]] 1214 + name = "openssl-sys" 1215 + version = "0.9.117" 1216 + source = "registry+https://github.com/rust-lang/crates.io-index" 1217 + checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" 1218 + dependencies = [ 1219 + "cc", 1220 + "libc", 1221 + "pkg-config", 1222 + "vcpkg", 1223 + ] 1224 + 1225 + [[package]] 1226 + name = "parking" 1227 + version = "2.2.1" 1228 + source = "registry+https://github.com/rust-lang/crates.io-index" 1229 + checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" 1230 + 1231 + [[package]] 1232 + name = "parking_lot" 1233 + version = "0.12.5" 1234 + source = "registry+https://github.com/rust-lang/crates.io-index" 1235 + checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" 1236 + dependencies = [ 1237 + "lock_api", 1238 + "parking_lot_core", 1239 + ] 1240 + 1241 + [[package]] 1242 + name = "parking_lot_core" 1243 + version = "0.9.12" 1244 + source = "registry+https://github.com/rust-lang/crates.io-index" 1245 + checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" 1246 + dependencies = [ 1247 + "cfg-if", 1248 + "libc", 1249 + "redox_syscall", 1250 + "smallvec", 1251 + "windows-link", 1252 + ] 1253 + 1254 + [[package]] 1255 + name = "percent-encoding" 1256 + version = "2.3.2" 1257 + source = "registry+https://github.com/rust-lang/crates.io-index" 1258 + checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" 1259 + 1260 + [[package]] 1261 + name = "pin-project-lite" 1262 + version = "0.2.17" 1263 + source = "registry+https://github.com/rust-lang/crates.io-index" 1264 + checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" 1265 + 1266 + [[package]] 1267 + name = "pkg-config" 1268 + version = "0.3.33" 1269 + source = "registry+https://github.com/rust-lang/crates.io-index" 1270 + checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" 1271 + 1272 + [[package]] 1273 + name = "portable-atomic" 1274 + version = "1.13.1" 1275 + source = "registry+https://github.com/rust-lang/crates.io-index" 1276 + checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" 1277 + 1278 + [[package]] 1279 + name = "potential_utf" 1280 + version = "0.1.5" 1281 + source = "registry+https://github.com/rust-lang/crates.io-index" 1282 + checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" 1283 + dependencies = [ 1284 + "zerovec", 1285 + ] 1286 + 1287 + [[package]] 1288 + name = "powerfmt" 1289 + version = "0.2.0" 1290 + source = "registry+https://github.com/rust-lang/crates.io-index" 1291 + checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 1292 + 1293 + [[package]] 1294 + name = "prettyplease" 1295 + version = "0.2.37" 1296 + source = "registry+https://github.com/rust-lang/crates.io-index" 1297 + checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" 1298 + dependencies = [ 1299 + "proc-macro2", 1300 + "syn", 1301 + ] 1302 + 1303 + [[package]] 1304 + name = "proc-macro2" 1305 + version = "1.0.106" 1306 + source = "registry+https://github.com/rust-lang/crates.io-index" 1307 + checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" 1308 + dependencies = [ 1309 + "unicode-ident", 1310 + ] 1311 + 1312 + [[package]] 1313 + name = "psl" 1314 + version = "2.1.213" 1315 + source = "registry+https://github.com/rust-lang/crates.io-index" 1316 + checksum = "04e78830163eebdf905adb55ba26ba9b3ba554b08bd84c2fbe3b643c8addf22c" 1317 + dependencies = [ 1318 + "psl-types", 1319 + ] 1320 + 1321 + [[package]] 1322 + name = "psl-types" 1323 + version = "2.0.11" 1324 + source = "registry+https://github.com/rust-lang/crates.io-index" 1325 + checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" 1326 + 1327 + [[package]] 1328 + name = "quote" 1329 + version = "1.0.45" 1330 + source = "registry+https://github.com/rust-lang/crates.io-index" 1331 + checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" 1332 + dependencies = [ 1333 + "proc-macro2", 1334 + ] 1335 + 1336 + [[package]] 1337 + name = "r-efi" 1338 + version = "6.0.0" 1339 + source = "registry+https://github.com/rust-lang/crates.io-index" 1340 + checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" 1341 + 1342 + [[package]] 1343 + name = "redox_syscall" 1344 + version = "0.5.18" 1345 + source = "registry+https://github.com/rust-lang/crates.io-index" 1346 + checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" 1347 + dependencies = [ 1348 + "bitflags", 1349 + ] 1350 + 1351 + [[package]] 1352 + name = "regex" 1353 + version = "1.12.4" 1354 + source = "registry+https://github.com/rust-lang/crates.io-index" 1355 + checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" 1356 + dependencies = [ 1357 + "aho-corasick", 1358 + "memchr", 1359 + "regex-automata", 1360 + "regex-syntax", 1361 + ] 1362 + 1363 + [[package]] 1364 + name = "regex-automata" 1365 + version = "0.4.14" 1366 + source = "registry+https://github.com/rust-lang/crates.io-index" 1367 + checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" 1368 + dependencies = [ 1369 + "aho-corasick", 1370 + "memchr", 1371 + "regex-syntax", 1372 + ] 1373 + 1374 + [[package]] 1375 + name = "regex-syntax" 1376 + version = "0.8.11" 1377 + source = "registry+https://github.com/rust-lang/crates.io-index" 1378 + checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" 1379 + 1380 + [[package]] 1381 + name = "reqwest" 1382 + version = "0.12.28" 1383 + source = "registry+https://github.com/rust-lang/crates.io-index" 1384 + checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" 1385 + dependencies = [ 1386 + "base64", 1387 + "bytes", 1388 + "encoding_rs", 1389 + "futures-core", 1390 + "h2", 1391 + "http", 1392 + "http-body", 1393 + "http-body-util", 1394 + "hyper", 1395 + "hyper-rustls", 1396 + "hyper-tls", 1397 + "hyper-util", 1398 + "js-sys", 1399 + "log", 1400 + "mime", 1401 + "native-tls", 1402 + "percent-encoding", 1403 + "pin-project-lite", 1404 + "rustls-pki-types", 1405 + "serde", 1406 + "serde_json", 1407 + "serde_urlencoded", 1408 + "sync_wrapper", 1409 + "tokio", 1410 + "tokio-native-tls", 1411 + "tower", 1412 + "tower-http", 1413 + "tower-service", 1414 + "url", 1415 + "wasm-bindgen", 1416 + "wasm-bindgen-futures", 1417 + "web-sys", 1418 + ] 1419 + 1420 + [[package]] 1421 + name = "ring" 1422 + version = "0.17.14" 1423 + source = "registry+https://github.com/rust-lang/crates.io-index" 1424 + checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" 1425 + dependencies = [ 1426 + "cc", 1427 + "cfg-if", 1428 + "getrandom 0.2.17", 1429 + "libc", 1430 + "untrusted", 1431 + "windows-sys 0.52.0", 1432 + ] 1433 + 1434 + [[package]] 1435 + name = "rustix" 1436 + version = "1.1.4" 1437 + source = "registry+https://github.com/rust-lang/crates.io-index" 1438 + checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" 1439 + dependencies = [ 1440 + "bitflags", 1441 + "errno", 1442 + "libc", 1443 + "linux-raw-sys", 1444 + "windows-sys 0.61.2", 1445 + ] 1446 + 1447 + [[package]] 1448 + name = "rustls" 1449 + version = "0.23.40" 1450 + source = "registry+https://github.com/rust-lang/crates.io-index" 1451 + checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" 1452 + dependencies = [ 1453 + "once_cell", 1454 + "rustls-pki-types", 1455 + "rustls-webpki", 1456 + "subtle", 1457 + "zeroize", 1458 + ] 1459 + 1460 + [[package]] 1461 + name = "rustls-pki-types" 1462 + version = "1.14.1" 1463 + source = "registry+https://github.com/rust-lang/crates.io-index" 1464 + checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" 1465 + dependencies = [ 1466 + "zeroize", 1467 + ] 1468 + 1469 + [[package]] 1470 + name = "rustls-webpki" 1471 + version = "0.103.13" 1472 + source = "registry+https://github.com/rust-lang/crates.io-index" 1473 + checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" 1474 + dependencies = [ 1475 + "ring", 1476 + "rustls-pki-types", 1477 + "untrusted", 1478 + ] 1479 + 1480 + [[package]] 1481 + name = "rustversion" 1482 + version = "1.0.22" 1483 + source = "registry+https://github.com/rust-lang/crates.io-index" 1484 + checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" 1485 + 1486 + [[package]] 1487 + name = "ryu" 1488 + version = "1.0.23" 1489 + source = "registry+https://github.com/rust-lang/crates.io-index" 1490 + checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" 1491 + 1492 + [[package]] 1493 + name = "schannel" 1494 + version = "0.1.29" 1495 + source = "registry+https://github.com/rust-lang/crates.io-index" 1496 + checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" 1497 + dependencies = [ 1498 + "windows-sys 0.61.2", 1499 + ] 1500 + 1501 + [[package]] 1502 + name = "scopeguard" 1503 + version = "1.2.0" 1504 + source = "registry+https://github.com/rust-lang/crates.io-index" 1505 + checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1506 + 1507 + [[package]] 1508 + name = "security-framework" 1509 + version = "3.7.0" 1510 + source = "registry+https://github.com/rust-lang/crates.io-index" 1511 + checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" 1512 + dependencies = [ 1513 + "bitflags", 1514 + "core-foundation 0.10.1", 1515 + "core-foundation-sys", 1516 + "libc", 1517 + "security-framework-sys", 1518 + ] 1519 + 1520 + [[package]] 1521 + name = "security-framework-sys" 1522 + version = "2.17.0" 1523 + source = "registry+https://github.com/rust-lang/crates.io-index" 1524 + checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" 1525 + dependencies = [ 1526 + "core-foundation-sys", 1527 + "libc", 1528 + ] 1529 + 1530 + [[package]] 1531 + name = "semver" 1532 + version = "1.0.28" 1533 + source = "registry+https://github.com/rust-lang/crates.io-index" 1534 + checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" 1535 + 1536 + [[package]] 1537 + name = "serde" 1538 + version = "1.0.228" 1539 + source = "registry+https://github.com/rust-lang/crates.io-index" 1540 + checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" 1541 + dependencies = [ 1542 + "serde_core", 1543 + "serde_derive", 1544 + ] 1545 + 1546 + [[package]] 1547 + name = "serde_bytes" 1548 + version = "0.11.19" 1549 + source = "registry+https://github.com/rust-lang/crates.io-index" 1550 + checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8" 1551 + dependencies = [ 1552 + "serde", 1553 + "serde_core", 1554 + ] 1555 + 1556 + [[package]] 1557 + name = "serde_core" 1558 + version = "1.0.228" 1559 + source = "registry+https://github.com/rust-lang/crates.io-index" 1560 + checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" 1561 + dependencies = [ 1562 + "serde_derive", 1563 + ] 1564 + 1565 + [[package]] 1566 + name = "serde_derive" 1567 + version = "1.0.228" 1568 + source = "registry+https://github.com/rust-lang/crates.io-index" 1569 + checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" 1570 + dependencies = [ 1571 + "proc-macro2", 1572 + "quote", 1573 + "syn", 1574 + ] 1575 + 1576 + [[package]] 1577 + name = "serde_html_form" 1578 + version = "0.2.8" 1579 + source = "registry+https://github.com/rust-lang/crates.io-index" 1580 + checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f" 1581 + dependencies = [ 1582 + "form_urlencoded", 1583 + "indexmap", 1584 + "itoa", 1585 + "ryu", 1586 + "serde_core", 1587 + ] 1588 + 1589 + [[package]] 1590 + name = "serde_json" 1591 + version = "1.0.150" 1592 + source = "registry+https://github.com/rust-lang/crates.io-index" 1593 + checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" 1594 + dependencies = [ 1595 + "itoa", 1596 + "memchr", 1597 + "serde", 1598 + "serde_core", 1599 + "zmij", 1600 + ] 1601 + 1602 + [[package]] 1603 + name = "serde_urlencoded" 1604 + version = "0.7.1" 1605 + source = "registry+https://github.com/rust-lang/crates.io-index" 1606 + checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1607 + dependencies = [ 1608 + "form_urlencoded", 1609 + "itoa", 1610 + "ryu", 1611 + "serde", 1612 + ] 1613 + 1614 + [[package]] 1615 + name = "sharded-slab" 1616 + version = "0.1.7" 1617 + source = "registry+https://github.com/rust-lang/crates.io-index" 1618 + checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 1619 + dependencies = [ 1620 + "lazy_static", 1621 + ] 1622 + 1623 + [[package]] 1624 + name = "shlex" 1625 + version = "2.0.1" 1626 + source = "registry+https://github.com/rust-lang/crates.io-index" 1627 + checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" 1628 + 1629 + [[package]] 1630 + name = "signal-hook-registry" 1631 + version = "1.4.8" 1632 + source = "registry+https://github.com/rust-lang/crates.io-index" 1633 + checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" 1634 + dependencies = [ 1635 + "errno", 1636 + "libc", 1637 + ] 1638 + 1639 + [[package]] 1640 + name = "simd-adler32" 1641 + version = "0.3.9" 1642 + source = "registry+https://github.com/rust-lang/crates.io-index" 1643 + checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" 1644 + 1645 + [[package]] 1646 + name = "slab" 1647 + version = "0.4.12" 1648 + source = "registry+https://github.com/rust-lang/crates.io-index" 1649 + checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" 1650 + 1651 + [[package]] 1652 + name = "smallvec" 1653 + version = "1.15.2" 1654 + source = "registry+https://github.com/rust-lang/crates.io-index" 1655 + checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" 1656 + 1657 + [[package]] 1658 + name = "socket2" 1659 + version = "0.6.4" 1660 + source = "registry+https://github.com/rust-lang/crates.io-index" 1661 + checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" 1662 + dependencies = [ 1663 + "libc", 1664 + "windows-sys 0.61.2", 1665 + ] 1666 + 1667 + [[package]] 1668 + name = "stable_deref_trait" 1669 + version = "1.2.1" 1670 + source = "registry+https://github.com/rust-lang/crates.io-index" 1671 + checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" 1672 + 1673 + [[package]] 1674 + name = "subtle" 1675 + version = "2.6.1" 1676 + source = "registry+https://github.com/rust-lang/crates.io-index" 1677 + checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 1678 + 1679 + [[package]] 1680 + name = "symlink" 1681 + version = "0.1.0" 1682 + source = "registry+https://github.com/rust-lang/crates.io-index" 1683 + checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" 1684 + 1685 + [[package]] 1686 + name = "syn" 1687 + version = "2.0.117" 1688 + source = "registry+https://github.com/rust-lang/crates.io-index" 1689 + checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" 1690 + dependencies = [ 1691 + "proc-macro2", 1692 + "quote", 1693 + "unicode-ident", 1694 + ] 1695 + 1696 + [[package]] 1697 + name = "sync_wrapper" 1698 + version = "1.0.2" 1699 + source = "registry+https://github.com/rust-lang/crates.io-index" 1700 + checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 1701 + dependencies = [ 1702 + "futures-core", 1703 + ] 1704 + 1705 + [[package]] 1706 + name = "synstructure" 1707 + version = "0.13.2" 1708 + source = "registry+https://github.com/rust-lang/crates.io-index" 1709 + checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" 1710 + dependencies = [ 1711 + "proc-macro2", 1712 + "quote", 1713 + "syn", 1714 + ] 1715 + 1716 + [[package]] 1717 + name = "system-configuration" 1718 + version = "0.7.0" 1719 + source = "registry+https://github.com/rust-lang/crates.io-index" 1720 + checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" 1721 + dependencies = [ 1722 + "bitflags", 1723 + "core-foundation 0.9.4", 1724 + "system-configuration-sys", 1725 + ] 1726 + 1727 + [[package]] 1728 + name = "system-configuration-sys" 1729 + version = "0.6.0" 1730 + source = "registry+https://github.com/rust-lang/crates.io-index" 1731 + checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" 1732 + dependencies = [ 1733 + "core-foundation-sys", 1734 + "libc", 1735 + ] 1736 + 1737 + [[package]] 1738 + name = "tagptr" 1739 + version = "0.2.0" 1740 + source = "registry+https://github.com/rust-lang/crates.io-index" 1741 + checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" 1742 + 1743 + [[package]] 1744 + name = "tempfile" 1745 + version = "3.27.0" 1746 + source = "registry+https://github.com/rust-lang/crates.io-index" 1747 + checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" 1748 + dependencies = [ 1749 + "fastrand", 1750 + "getrandom 0.4.2", 1751 + "once_cell", 1752 + "rustix", 1753 + "windows-sys 0.61.2", 1754 + ] 1755 + 1756 + [[package]] 1757 + name = "thiserror" 1758 + version = "1.0.69" 1759 + source = "registry+https://github.com/rust-lang/crates.io-index" 1760 + checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 1761 + dependencies = [ 1762 + "thiserror-impl 1.0.69", 1763 + ] 1764 + 1765 + [[package]] 1766 + name = "thiserror" 1767 + version = "2.0.18" 1768 + source = "registry+https://github.com/rust-lang/crates.io-index" 1769 + checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" 1770 + dependencies = [ 1771 + "thiserror-impl 2.0.18", 1772 + ] 1773 + 1774 + [[package]] 1775 + name = "thiserror-impl" 1776 + version = "1.0.69" 1777 + source = "registry+https://github.com/rust-lang/crates.io-index" 1778 + checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 1779 + dependencies = [ 1780 + "proc-macro2", 1781 + "quote", 1782 + "syn", 1783 + ] 1784 + 1785 + [[package]] 1786 + name = "thiserror-impl" 1787 + version = "2.0.18" 1788 + source = "registry+https://github.com/rust-lang/crates.io-index" 1789 + checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" 1790 + dependencies = [ 1791 + "proc-macro2", 1792 + "quote", 1793 + "syn", 1794 + ] 1795 + 1796 + [[package]] 1797 + name = "thread_local" 1798 + version = "1.1.9" 1799 + source = "registry+https://github.com/rust-lang/crates.io-index" 1800 + checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" 1801 + dependencies = [ 1802 + "cfg-if", 1803 + ] 1804 + 1805 + [[package]] 1806 + name = "time" 1807 + version = "0.3.49" 1808 + source = "registry+https://github.com/rust-lang/crates.io-index" 1809 + checksum = "711a53c2d47bbd818258c498c8dbfe186a2526c631495cfe7e078567f86b8469" 1810 + dependencies = [ 1811 + "deranged", 1812 + "num-conv", 1813 + "powerfmt", 1814 + "serde_core", 1815 + "time-core", 1816 + "time-macros", 1817 + ] 1818 + 1819 + [[package]] 1820 + name = "time-core" 1821 + version = "0.1.9" 1822 + source = "registry+https://github.com/rust-lang/crates.io-index" 1823 + checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" 1824 + 1825 + [[package]] 1826 + name = "time-macros" 1827 + version = "0.2.29" 1828 + source = "registry+https://github.com/rust-lang/crates.io-index" 1829 + checksum = "71c652a3727a9cbb9a02f707f530b618ce00d0ccd762009c8c23bd191df3c17d" 1830 + dependencies = [ 1831 + "num-conv", 1832 + "time-core", 1833 + ] 1834 + 1835 + [[package]] 1836 + name = "tinystr" 1837 + version = "0.8.3" 1838 + source = "registry+https://github.com/rust-lang/crates.io-index" 1839 + checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" 1840 + dependencies = [ 1841 + "displaydoc", 1842 + "zerovec", 1843 + ] 1844 + 1845 + [[package]] 1846 + name = "tokio" 1847 + version = "1.52.3" 1848 + source = "registry+https://github.com/rust-lang/crates.io-index" 1849 + checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" 1850 + dependencies = [ 1851 + "bytes", 1852 + "libc", 1853 + "mio", 1854 + "parking_lot", 1855 + "pin-project-lite", 1856 + "signal-hook-registry", 1857 + "socket2", 1858 + "tokio-macros", 1859 + "windows-sys 0.61.2", 1860 + ] 1861 + 1862 + [[package]] 1863 + name = "tokio-macros" 1864 + version = "2.7.0" 1865 + source = "registry+https://github.com/rust-lang/crates.io-index" 1866 + checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" 1867 + dependencies = [ 1868 + "proc-macro2", 1869 + "quote", 1870 + "syn", 1871 + ] 1872 + 1873 + [[package]] 1874 + name = "tokio-native-tls" 1875 + version = "0.3.1" 1876 + source = "registry+https://github.com/rust-lang/crates.io-index" 1877 + checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 1878 + dependencies = [ 1879 + "native-tls", 1880 + "tokio", 1881 + ] 1882 + 1883 + [[package]] 1884 + name = "tokio-rustls" 1885 + version = "0.26.4" 1886 + source = "registry+https://github.com/rust-lang/crates.io-index" 1887 + checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" 1888 + dependencies = [ 1889 + "rustls", 1890 + "tokio", 1891 + ] 1892 + 1893 + [[package]] 1894 + name = "tokio-util" 1895 + version = "0.7.18" 1896 + source = "registry+https://github.com/rust-lang/crates.io-index" 1897 + checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" 1898 + dependencies = [ 1899 + "bytes", 1900 + "futures-core", 1901 + "futures-sink", 1902 + "pin-project-lite", 1903 + "tokio", 1904 + ] 1905 + 1906 + [[package]] 1907 + name = "tower" 1908 + version = "0.5.3" 1909 + source = "registry+https://github.com/rust-lang/crates.io-index" 1910 + checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" 1911 + dependencies = [ 1912 + "futures-core", 1913 + "futures-util", 1914 + "pin-project-lite", 1915 + "sync_wrapper", 1916 + "tokio", 1917 + "tower-layer", 1918 + "tower-service", 1919 + ] 1920 + 1921 + [[package]] 1922 + name = "tower-http" 1923 + version = "0.6.11" 1924 + source = "registry+https://github.com/rust-lang/crates.io-index" 1925 + checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" 1926 + dependencies = [ 1927 + "async-compression", 1928 + "bitflags", 1929 + "bytes", 1930 + "futures-core", 1931 + "futures-util", 1932 + "http", 1933 + "http-body", 1934 + "http-body-util", 1935 + "pin-project-lite", 1936 + "tokio", 1937 + "tokio-util", 1938 + "tower", 1939 + "tower-layer", 1940 + "tower-service", 1941 + "url", 1942 + ] 1943 + 1944 + [[package]] 1945 + name = "tower-layer" 1946 + version = "0.3.3" 1947 + source = "registry+https://github.com/rust-lang/crates.io-index" 1948 + checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 1949 + 1950 + [[package]] 1951 + name = "tower-service" 1952 + version = "0.3.3" 1953 + source = "registry+https://github.com/rust-lang/crates.io-index" 1954 + checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 1955 + 1956 + [[package]] 1957 + name = "tracing" 1958 + version = "0.1.44" 1959 + source = "registry+https://github.com/rust-lang/crates.io-index" 1960 + checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" 1961 + dependencies = [ 1962 + "pin-project-lite", 1963 + "tracing-attributes", 1964 + "tracing-core", 1965 + ] 1966 + 1967 + [[package]] 1968 + name = "tracing-appender" 1969 + version = "0.2.5" 1970 + source = "registry+https://github.com/rust-lang/crates.io-index" 1971 + checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" 1972 + dependencies = [ 1973 + "crossbeam-channel", 1974 + "symlink", 1975 + "thiserror 2.0.18", 1976 + "time", 1977 + "tracing-subscriber", 1978 + ] 1979 + 1980 + [[package]] 1981 + name = "tracing-attributes" 1982 + version = "0.1.31" 1983 + source = "registry+https://github.com/rust-lang/crates.io-index" 1984 + checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" 1985 + dependencies = [ 1986 + "proc-macro2", 1987 + "quote", 1988 + "syn", 1989 + ] 1990 + 1991 + [[package]] 1992 + name = "tracing-core" 1993 + version = "0.1.36" 1994 + source = "registry+https://github.com/rust-lang/crates.io-index" 1995 + checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" 1996 + dependencies = [ 1997 + "once_cell", 1998 + "valuable", 1999 + ] 2000 + 2001 + [[package]] 2002 + name = "tracing-log" 2003 + version = "0.2.0" 2004 + source = "registry+https://github.com/rust-lang/crates.io-index" 2005 + checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 2006 + dependencies = [ 2007 + "log", 2008 + "once_cell", 2009 + "tracing-core", 2010 + ] 2011 + 2012 + [[package]] 2013 + name = "tracing-subscriber" 2014 + version = "0.3.23" 2015 + source = "registry+https://github.com/rust-lang/crates.io-index" 2016 + checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" 2017 + dependencies = [ 2018 + "matchers", 2019 + "nu-ansi-term", 2020 + "once_cell", 2021 + "regex-automata", 2022 + "sharded-slab", 2023 + "smallvec", 2024 + "thread_local", 2025 + "tracing", 2026 + "tracing-core", 2027 + "tracing-log", 2028 + ] 2029 + 2030 + [[package]] 2031 + name = "trait-variant" 2032 + version = "0.1.2" 2033 + source = "registry+https://github.com/rust-lang/crates.io-index" 2034 + checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7" 2035 + dependencies = [ 2036 + "proc-macro2", 2037 + "quote", 2038 + "syn", 2039 + ] 2040 + 2041 + [[package]] 2042 + name = "try-lock" 2043 + version = "0.2.5" 2044 + source = "registry+https://github.com/rust-lang/crates.io-index" 2045 + checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 2046 + 2047 + [[package]] 2048 + name = "unicode-ident" 2049 + version = "1.0.24" 2050 + source = "registry+https://github.com/rust-lang/crates.io-index" 2051 + checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" 2052 + 2053 + [[package]] 2054 + name = "unicode-segmentation" 2055 + version = "1.13.3" 2056 + source = "registry+https://github.com/rust-lang/crates.io-index" 2057 + checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" 2058 + 2059 + [[package]] 2060 + name = "unicode-xid" 2061 + version = "0.2.6" 2062 + source = "registry+https://github.com/rust-lang/crates.io-index" 2063 + checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 2064 + 2065 + [[package]] 2066 + name = "unsigned-varint" 2067 + version = "0.8.0" 2068 + source = "registry+https://github.com/rust-lang/crates.io-index" 2069 + checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06" 2070 + 2071 + [[package]] 2072 + name = "untrusted" 2073 + version = "0.9.0" 2074 + source = "registry+https://github.com/rust-lang/crates.io-index" 2075 + checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 2076 + 2077 + [[package]] 2078 + name = "url" 2079 + version = "2.5.8" 2080 + source = "registry+https://github.com/rust-lang/crates.io-index" 2081 + checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" 2082 + dependencies = [ 2083 + "form_urlencoded", 2084 + "idna", 2085 + "percent-encoding", 2086 + "serde", 2087 + ] 2088 + 2089 + [[package]] 2090 + name = "utf8_iter" 2091 + version = "1.0.4" 2092 + source = "registry+https://github.com/rust-lang/crates.io-index" 2093 + checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 2094 + 2095 + [[package]] 2096 + name = "uuid" 2097 + version = "1.23.3" 2098 + source = "registry+https://github.com/rust-lang/crates.io-index" 2099 + checksum = "144d6b123cef80b301b8f72a9e2ca4370ddec21950d0a103dd22c437006d2db7" 2100 + dependencies = [ 2101 + "getrandom 0.4.2", 2102 + "js-sys", 2103 + "wasm-bindgen", 2104 + ] 2105 + 2106 + [[package]] 2107 + name = "valuable" 2108 + version = "0.1.1" 2109 + source = "registry+https://github.com/rust-lang/crates.io-index" 2110 + checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" 2111 + 2112 + [[package]] 2113 + name = "vcpkg" 2114 + version = "0.2.15" 2115 + source = "registry+https://github.com/rust-lang/crates.io-index" 2116 + checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2117 + 2118 + [[package]] 2119 + name = "want" 2120 + version = "0.3.1" 2121 + source = "registry+https://github.com/rust-lang/crates.io-index" 2122 + checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 2123 + dependencies = [ 2124 + "try-lock", 2125 + ] 2126 + 2127 + [[package]] 2128 + name = "wasi" 2129 + version = "0.11.1+wasi-snapshot-preview1" 2130 + source = "registry+https://github.com/rust-lang/crates.io-index" 2131 + checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 2132 + 2133 + [[package]] 2134 + name = "wasip2" 2135 + version = "1.0.4+wasi-0.2.12" 2136 + source = "registry+https://github.com/rust-lang/crates.io-index" 2137 + checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" 2138 + dependencies = [ 2139 + "wit-bindgen 0.57.1", 2140 + ] 2141 + 2142 + [[package]] 2143 + name = "wasip3" 2144 + version = "0.4.0+wasi-0.3.0-rc-2026-01-06" 2145 + source = "registry+https://github.com/rust-lang/crates.io-index" 2146 + checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" 2147 + dependencies = [ 2148 + "wit-bindgen 0.51.0", 2149 + ] 2150 + 2151 + [[package]] 2152 + name = "wasm-bindgen" 2153 + version = "0.2.125" 2154 + source = "registry+https://github.com/rust-lang/crates.io-index" 2155 + checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a" 2156 + dependencies = [ 2157 + "cfg-if", 2158 + "once_cell", 2159 + "rustversion", 2160 + "wasm-bindgen-macro", 2161 + "wasm-bindgen-shared", 2162 + ] 2163 + 2164 + [[package]] 2165 + name = "wasm-bindgen-futures" 2166 + version = "0.4.75" 2167 + source = "registry+https://github.com/rust-lang/crates.io-index" 2168 + checksum = "503b14d284f2c8dac03b819967e155ea753f573586193b2b2c95990cb5d69280" 2169 + dependencies = [ 2170 + "js-sys", 2171 + "wasm-bindgen", 2172 + ] 2173 + 2174 + [[package]] 2175 + name = "wasm-bindgen-macro" 2176 + version = "0.2.125" 2177 + source = "registry+https://github.com/rust-lang/crates.io-index" 2178 + checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d" 2179 + dependencies = [ 2180 + "quote", 2181 + "wasm-bindgen-macro-support", 2182 + ] 2183 + 2184 + [[package]] 2185 + name = "wasm-bindgen-macro-support" 2186 + version = "0.2.125" 2187 + source = "registry+https://github.com/rust-lang/crates.io-index" 2188 + checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd" 2189 + dependencies = [ 2190 + "bumpalo", 2191 + "proc-macro2", 2192 + "quote", 2193 + "syn", 2194 + "wasm-bindgen-shared", 2195 + ] 2196 + 2197 + [[package]] 2198 + name = "wasm-bindgen-shared" 2199 + version = "0.2.125" 2200 + source = "registry+https://github.com/rust-lang/crates.io-index" 2201 + checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f" 2202 + dependencies = [ 2203 + "unicode-ident", 2204 + ] 2205 + 2206 + [[package]] 2207 + name = "wasm-encoder" 2208 + version = "0.244.0" 2209 + source = "registry+https://github.com/rust-lang/crates.io-index" 2210 + checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" 2211 + dependencies = [ 2212 + "leb128fmt", 2213 + "wasmparser", 2214 + ] 2215 + 2216 + [[package]] 2217 + name = "wasm-metadata" 2218 + version = "0.244.0" 2219 + source = "registry+https://github.com/rust-lang/crates.io-index" 2220 + checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" 2221 + dependencies = [ 2222 + "anyhow", 2223 + "indexmap", 2224 + "wasm-encoder", 2225 + "wasmparser", 2226 + ] 2227 + 2228 + [[package]] 2229 + name = "wasmparser" 2230 + version = "0.244.0" 2231 + source = "registry+https://github.com/rust-lang/crates.io-index" 2232 + checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" 2233 + dependencies = [ 2234 + "bitflags", 2235 + "hashbrown 0.15.5", 2236 + "indexmap", 2237 + "semver", 2238 + ] 2239 + 2240 + [[package]] 2241 + name = "web-sys" 2242 + version = "0.3.102" 2243 + source = "registry+https://github.com/rust-lang/crates.io-index" 2244 + checksum = "a6430a72df5eb332242960fe84b3002a241163998241eb596d4f739b9757061d" 2245 + dependencies = [ 2246 + "js-sys", 2247 + "wasm-bindgen", 2248 + ] 2249 + 2250 + [[package]] 2251 + name = "web-time" 2252 + version = "1.1.0" 2253 + source = "registry+https://github.com/rust-lang/crates.io-index" 2254 + checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 2255 + dependencies = [ 2256 + "js-sys", 2257 + "wasm-bindgen", 2258 + ] 2259 + 2260 + [[package]] 2261 + name = "windows-core" 2262 + version = "0.62.2" 2263 + source = "registry+https://github.com/rust-lang/crates.io-index" 2264 + checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" 2265 + dependencies = [ 2266 + "windows-implement", 2267 + "windows-interface", 2268 + "windows-link", 2269 + "windows-result", 2270 + "windows-strings", 2271 + ] 2272 + 2273 + [[package]] 2274 + name = "windows-implement" 2275 + version = "0.60.2" 2276 + source = "registry+https://github.com/rust-lang/crates.io-index" 2277 + checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" 2278 + dependencies = [ 2279 + "proc-macro2", 2280 + "quote", 2281 + "syn", 2282 + ] 2283 + 2284 + [[package]] 2285 + name = "windows-interface" 2286 + version = "0.59.3" 2287 + source = "registry+https://github.com/rust-lang/crates.io-index" 2288 + checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" 2289 + dependencies = [ 2290 + "proc-macro2", 2291 + "quote", 2292 + "syn", 2293 + ] 2294 + 2295 + [[package]] 2296 + name = "windows-link" 2297 + version = "0.2.1" 2298 + source = "registry+https://github.com/rust-lang/crates.io-index" 2299 + checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 2300 + 2301 + [[package]] 2302 + name = "windows-registry" 2303 + version = "0.6.1" 2304 + source = "registry+https://github.com/rust-lang/crates.io-index" 2305 + checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" 2306 + dependencies = [ 2307 + "windows-link", 2308 + "windows-result", 2309 + "windows-strings", 2310 + ] 2311 + 2312 + [[package]] 2313 + name = "windows-result" 2314 + version = "0.4.1" 2315 + source = "registry+https://github.com/rust-lang/crates.io-index" 2316 + checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" 2317 + dependencies = [ 2318 + "windows-link", 2319 + ] 2320 + 2321 + [[package]] 2322 + name = "windows-strings" 2323 + version = "0.5.1" 2324 + source = "registry+https://github.com/rust-lang/crates.io-index" 2325 + checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" 2326 + dependencies = [ 2327 + "windows-link", 2328 + ] 2329 + 2330 + [[package]] 2331 + name = "windows-sys" 2332 + version = "0.52.0" 2333 + source = "registry+https://github.com/rust-lang/crates.io-index" 2334 + checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 2335 + dependencies = [ 2336 + "windows-targets", 2337 + ] 2338 + 2339 + [[package]] 2340 + name = "windows-sys" 2341 + version = "0.61.2" 2342 + source = "registry+https://github.com/rust-lang/crates.io-index" 2343 + checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 2344 + dependencies = [ 2345 + "windows-link", 2346 + ] 2347 + 2348 + [[package]] 2349 + name = "windows-targets" 2350 + version = "0.52.6" 2351 + source = "registry+https://github.com/rust-lang/crates.io-index" 2352 + checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 2353 + dependencies = [ 2354 + "windows_aarch64_gnullvm", 2355 + "windows_aarch64_msvc", 2356 + "windows_i686_gnu", 2357 + "windows_i686_gnullvm", 2358 + "windows_i686_msvc", 2359 + "windows_x86_64_gnu", 2360 + "windows_x86_64_gnullvm", 2361 + "windows_x86_64_msvc", 2362 + ] 2363 + 2364 + [[package]] 2365 + name = "windows_aarch64_gnullvm" 2366 + version = "0.52.6" 2367 + source = "registry+https://github.com/rust-lang/crates.io-index" 2368 + checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 2369 + 2370 + [[package]] 2371 + name = "windows_aarch64_msvc" 2372 + version = "0.52.6" 2373 + source = "registry+https://github.com/rust-lang/crates.io-index" 2374 + checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2375 + 2376 + [[package]] 2377 + name = "windows_i686_gnu" 2378 + version = "0.52.6" 2379 + source = "registry+https://github.com/rust-lang/crates.io-index" 2380 + checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 2381 + 2382 + [[package]] 2383 + name = "windows_i686_gnullvm" 2384 + version = "0.52.6" 2385 + source = "registry+https://github.com/rust-lang/crates.io-index" 2386 + checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 2387 + 2388 + [[package]] 2389 + name = "windows_i686_msvc" 2390 + version = "0.52.6" 2391 + source = "registry+https://github.com/rust-lang/crates.io-index" 2392 + checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 2393 + 2394 + [[package]] 2395 + name = "windows_x86_64_gnu" 2396 + version = "0.52.6" 2397 + source = "registry+https://github.com/rust-lang/crates.io-index" 2398 + checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 2399 + 2400 + [[package]] 2401 + name = "windows_x86_64_gnullvm" 2402 + version = "0.52.6" 2403 + source = "registry+https://github.com/rust-lang/crates.io-index" 2404 + checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 2405 + 2406 + [[package]] 2407 + name = "windows_x86_64_msvc" 2408 + version = "0.52.6" 2409 + source = "registry+https://github.com/rust-lang/crates.io-index" 2410 + checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 2411 + 2412 + [[package]] 2413 + name = "wit-bindgen" 2414 + version = "0.51.0" 2415 + source = "registry+https://github.com/rust-lang/crates.io-index" 2416 + checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" 2417 + dependencies = [ 2418 + "wit-bindgen-rust-macro", 2419 + ] 2420 + 2421 + [[package]] 2422 + name = "wit-bindgen" 2423 + version = "0.57.1" 2424 + source = "registry+https://github.com/rust-lang/crates.io-index" 2425 + checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" 2426 + 2427 + [[package]] 2428 + name = "wit-bindgen-core" 2429 + version = "0.51.0" 2430 + source = "registry+https://github.com/rust-lang/crates.io-index" 2431 + checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" 2432 + dependencies = [ 2433 + "anyhow", 2434 + "heck", 2435 + "wit-parser", 2436 + ] 2437 + 2438 + [[package]] 2439 + name = "wit-bindgen-rust" 2440 + version = "0.51.0" 2441 + source = "registry+https://github.com/rust-lang/crates.io-index" 2442 + checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" 2443 + dependencies = [ 2444 + "anyhow", 2445 + "heck", 2446 + "indexmap", 2447 + "prettyplease", 2448 + "syn", 2449 + "wasm-metadata", 2450 + "wit-bindgen-core", 2451 + "wit-component", 2452 + ] 2453 + 2454 + [[package]] 2455 + name = "wit-bindgen-rust-macro" 2456 + version = "0.51.0" 2457 + source = "registry+https://github.com/rust-lang/crates.io-index" 2458 + checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" 2459 + dependencies = [ 2460 + "anyhow", 2461 + "prettyplease", 2462 + "proc-macro2", 2463 + "quote", 2464 + "syn", 2465 + "wit-bindgen-core", 2466 + "wit-bindgen-rust", 2467 + ] 2468 + 2469 + [[package]] 2470 + name = "wit-component" 2471 + version = "0.244.0" 2472 + source = "registry+https://github.com/rust-lang/crates.io-index" 2473 + checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" 2474 + dependencies = [ 2475 + "anyhow", 2476 + "bitflags", 2477 + "indexmap", 2478 + "log", 2479 + "serde", 2480 + "serde_derive", 2481 + "serde_json", 2482 + "wasm-encoder", 2483 + "wasm-metadata", 2484 + "wasmparser", 2485 + "wit-parser", 2486 + ] 2487 + 2488 + [[package]] 2489 + name = "wit-parser" 2490 + version = "0.244.0" 2491 + source = "registry+https://github.com/rust-lang/crates.io-index" 2492 + checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" 2493 + dependencies = [ 2494 + "anyhow", 2495 + "id-arena", 2496 + "indexmap", 2497 + "log", 2498 + "semver", 2499 + "serde", 2500 + "serde_derive", 2501 + "serde_json", 2502 + "unicode-xid", 2503 + "wasmparser", 2504 + ] 2505 + 2506 + [[package]] 2507 + name = "writeable" 2508 + version = "0.6.3" 2509 + source = "registry+https://github.com/rust-lang/crates.io-index" 2510 + checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" 2511 + 2512 + [[package]] 2513 + name = "yoke" 2514 + version = "0.8.3" 2515 + source = "registry+https://github.com/rust-lang/crates.io-index" 2516 + checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" 2517 + dependencies = [ 2518 + "stable_deref_trait", 2519 + "yoke-derive", 2520 + "zerofrom", 2521 + ] 2522 + 2523 + [[package]] 2524 + name = "yoke-derive" 2525 + version = "0.8.2" 2526 + source = "registry+https://github.com/rust-lang/crates.io-index" 2527 + checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" 2528 + dependencies = [ 2529 + "proc-macro2", 2530 + "quote", 2531 + "syn", 2532 + "synstructure", 2533 + ] 2534 + 2535 + [[package]] 2536 + name = "zerofrom" 2537 + version = "0.1.8" 2538 + source = "registry+https://github.com/rust-lang/crates.io-index" 2539 + checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" 2540 + dependencies = [ 2541 + "zerofrom-derive", 2542 + ] 2543 + 2544 + [[package]] 2545 + name = "zerofrom-derive" 2546 + version = "0.1.7" 2547 + source = "registry+https://github.com/rust-lang/crates.io-index" 2548 + checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" 2549 + dependencies = [ 2550 + "proc-macro2", 2551 + "quote", 2552 + "syn", 2553 + "synstructure", 2554 + ] 2555 + 2556 + [[package]] 2557 + name = "zeroize" 2558 + version = "1.9.0" 2559 + source = "registry+https://github.com/rust-lang/crates.io-index" 2560 + checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" 2561 + 2562 + [[package]] 2563 + name = "zerotrie" 2564 + version = "0.2.4" 2565 + source = "registry+https://github.com/rust-lang/crates.io-index" 2566 + checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" 2567 + dependencies = [ 2568 + "displaydoc", 2569 + "yoke", 2570 + "zerofrom", 2571 + ] 2572 + 2573 + [[package]] 2574 + name = "zerovec" 2575 + version = "0.11.6" 2576 + source = "registry+https://github.com/rust-lang/crates.io-index" 2577 + checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" 2578 + dependencies = [ 2579 + "yoke", 2580 + "zerofrom", 2581 + "zerovec-derive", 2582 + ] 2583 + 2584 + [[package]] 2585 + name = "zerovec-derive" 2586 + version = "0.11.3" 2587 + source = "registry+https://github.com/rust-lang/crates.io-index" 2588 + checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" 2589 + dependencies = [ 2590 + "proc-macro2", 2591 + "quote", 2592 + "syn", 2593 + ] 2594 + 2595 + [[package]] 2596 + name = "zmij" 2597 + version = "1.0.21" 2598 + source = "registry+https://github.com/rust-lang/crates.io-index" 2599 + checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
+22
Cargo.toml
··· 1 + [package] 2 + name = "bluesky-avatar-updater" 3 + version = "0.1.0" 4 + edition = "2021" 5 + 6 + [dependencies] 7 + tokio = { version = "1.37.0", features = ["full"] } 8 + reqwest = { version = "0.12.4", features = ["json"] } 9 + serde = { version = "1.0.201", features = ["derive"] } 10 + serde_json = "1.0.117" 11 + anyhow = "1.0.86" 12 + tracing = "0.1.40" 13 + tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } 14 + tracing-appender = "0.2.3" 15 + dotenvy = "0.15.7" 16 + bsky-sdk = "0.1.24" 17 + atrium-api = "0.25.8" 18 + chrono = "0.4.38" 19 + infer = "0.19.0" 20 + url = "2.5.0" 21 + bytes = "1.6.0" 22 + cid = "0.11.3"
+33 -48
README.md
··· 1 1 # Bluesky Avatar Updater 2 2 3 - **_This repository is available on [GitHub](https://github.com/ewanc26/bluesky-avatar-updater) and [Tangled](https://tangled.sh/did:plc:ofrbh253gwicbkc5nktqepol/bluesky-avatar-updater). GitHub is the primary version, and the Tangled version is a mirror._** 3 + [![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/) 4 4 5 - ## Overview 5 + A Rust tool to automatically rotate your Bluesky profile avatar and banner every hour. 6 6 7 - This repository contains a Python script that updates a Bluesky profile avatar, and optionally a banner, based on the current hour. It looks up blob CIDs in `assets/cids.json`, fetches the blobs from the configured endpoint, and updates the profile record through the AT Protocol. 7 + ## Features 8 8 9 - The script also performs a health check against the endpoint, writes logs to `logs/update.log`, rotates logs every 14 days with up to 5 backups, removes old logs older than 30 days at startup, and installs an hourly cron job so the update runs automatically. 10 - 11 - This project was inspired by [@dame.is](https://bsky.app/profile/dame.is)'s blog post ['How I made an automated dynamic avatar for my Bluesky profile'](https://dame.is/blog/how-i-made-an-automated-dynamic-avatar-for-my-bluesky-profile). 12 - 13 - > 🧶 Also available on [Tangled](https://tangled.org/ewancroft.uk/bluesky-avatar-updater) 9 + - **Automated Rotation**: Automatically updates your profile assets every hour. 10 + - **Environment Support**: Loads configuration from `.env` files. 11 + - **Logging**: Robust file logging with 14-day rotation. 12 + - **Cron Integration**: Self-installs as an hourly cron job for persistent updates. 13 + - **Asset Mapping**: Supports detailed hourly CID mapping for both avatar and banner. 14 14 15 15 ## Requirements 16 16 17 - - Python 3.6 or later 18 - - A virtual environment 19 - - Python packages from `requirements.txt` 20 - - A valid Bluesky account with app password access 21 - - A working AT Protocol endpoint that serves the blobs referenced in `cids.json` 17 + To run this project, you will need the following: 22 18 23 - Install the Python dependencies with: 24 - 25 - ```bash 26 - pip install -r requirements.txt 27 - ``` 19 + - Rust 1.85+ (Cargo) 28 20 29 - ## Setup 21 + ## Installation 30 22 31 23 1. Clone the repository: 32 24 ··· 35 27 cd bluesky-avatar-updater 36 28 ``` 37 29 38 - 2. Create and activate a virtual environment: 30 + 2. Build the project: 39 31 40 32 ```bash 41 - python3 -m venv .venv 42 - source .venv/bin/activate 33 + cargo build --release 43 34 ``` 44 35 45 - 3. Create `assets/.env` with: 36 + 3. Create a `.env` file in the `assets/` directory (or the root) and add your environment variables: 46 37 47 - ```env 48 - ENDPOINT=your_endpoint 49 - HANDLE=your_handle 38 + ```plaintext 39 + ENDPOINT=https://bsky.social 40 + HANDLE=your_handle.bsky.social 50 41 PASSWORD=your_app_password 51 - DID=your_did 42 + DID=did:plc:your_did 52 43 UPDATE_BANNER=false 53 44 ``` 54 45 ··· 66 57 67 58 ## Usage 68 59 69 - Run the updater from the repository root while the virtual environment is active: 60 + Run the updater from the repository root: 70 61 71 62 ```bash 72 - python -u ./src/main.py 63 + cargo run --release 73 64 ``` 74 65 75 66 On start-up, the script will: 76 67 77 - 1. Verify that it is running inside a virtual environment 78 - 2. Load `assets/.env` 79 - 3. Confirm the endpoint is healthy 80 - 4. Read the CID mapping from `assets/cids.json` 81 - 5. Select the avatar CID for the current hour 82 - 6. Log in to Bluesky and update the profile record 83 - 7. Ensure an hourly cron job exists for future runs 84 - 85 - ## Notes 86 - 87 - - `UPDATE_BANNER=true` enables banner updates when a banner CID is present for the current hour. 88 - - The endpoint value is normalised to HTTPS if necessary. 89 - - The script expects the endpoint to support `/_health` and `com.atproto.sync.getBlob`. 68 + 1. Load configuration and environment variables. 69 + 2. Confirm the endpoint is healthy. 70 + 3. Read the CID mapping from `assets/cids.json`. 71 + 4. Select the avatar/banner CID for the current hour. 72 + 5. Log in to Bluesky and update the profile record. 73 + 6. Ensure an hourly cron job exists for future runs. 90 74 91 - ## Troubleshooting 75 + ## File Structure 92 76 93 - - If the script exits immediately, double-check that the virtual environment is active. 94 - - If authentication fails, confirm the handle and app password are correct. 95 - - If blob fetching fails, make sure the endpoint can access the DID/CID pair in `cids.json`. 96 - - If cron does not install, verify that `python-crontab` is available in the virtual environment. 77 + - `src/main.rs`: Main orchestration. 78 + - `src/bsky.rs`: Bluesky API and blob handling. 79 + - `src/cron.rs`: Cron job management. 80 + - `src/utils.rs`: Utility functions and environment validation. 81 + - `assets/cids.json`: Mapping of hours to avatar and banner CIDs. 97 82 98 83 ## License 99 84 100 - This project is released under the MIT License. Please refer to the [LICENSE](./LICENSE) file for full details. 85 + This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. 101 86 102 87 ## ☕ Support 103 88
-5
requirements.txt
··· 1 - python-dotenv 2 - atproto 3 - requests 4 - python-magic 5 - python-crontab
+33
src/bsky.rs
··· 1 + use atrium_api::types::{Blob, CidLink}; 2 + use anyhow::{Result, anyhow}; 3 + use reqwest::Client; 4 + use tracing::{info, debug}; 5 + use bytes::Bytes; 6 + use std::str::FromStr; 7 + 8 + pub async fn fetch_blob(did: &str, cid: &str, endpoint: &str) -> Result<Bytes> { 9 + let url = format!("{}/xrpc/com.atproto.sync.getBlob?did={}&cid={}", endpoint.trim_end_matches('/'), did, cid); 10 + let client = Client::new(); 11 + let response = client.get(&url).timeout(std::time::Duration::from_secs(5)).send().await?; 12 + response.error_for_status_ref()?; 13 + let content = response.bytes().await?; 14 + info!("Fetched blob {} successfully.", cid); 15 + Ok(content) 16 + } 17 + 18 + pub async fn get_blob_metadata(cid: &str, did: &str, endpoint: &str) -> Result<Blob> { 19 + info!("Retrieving metadata for blob {}.", cid); 20 + let blob_data = fetch_blob(did, cid, endpoint).await?; 21 + 22 + let kind = infer::get(&blob_data).ok_or_else(|| anyhow!("Could not infer mime type for blob {}", cid))?; 23 + let mime_type = kind.mime_type().to_string(); 24 + let size = blob_data.len(); 25 + 26 + debug!("Blob metadata: MIME Type - {}, Size - {}", mime_type, size); 27 + 28 + Ok(Blob { 29 + r#ref: CidLink(cid::Cid::from_str(cid).map_err(|e| anyhow!("{:?}", e))?), 30 + mime_type, 31 + size, 32 + }) 33 + }
+66
src/cron.rs
··· 1 + use std::process::Command; 2 + use std::env; 3 + use std::io::Write; 4 + use tracing::{info, error}; 5 + 6 + pub fn setup_cron_job() { 7 + let current_exe = match env::current_exe() { 8 + Ok(path) => path, 9 + Err(e) => { 10 + error!("Failed to get current exe path: {}", e); 11 + return; 12 + } 13 + }; 14 + let current_exe_str = current_exe.to_str().expect("Failed to convert path to string"); 15 + 16 + // Command to check if cron job exists 17 + let output = Command::new("crontab") 18 + .arg("-l") 19 + .output(); 20 + 21 + let cron_list = match output { 22 + Ok(out) if out.status.success() => String::from_utf8_lossy(&out.stdout).to_string(), 23 + _ => String::new(), 24 + }; 25 + 26 + if cron_list.contains(current_exe_str) { 27 + info!("Cron job already exists."); 28 + return; 29 + } 30 + 31 + let new_job = format!("0 * * * * {}", current_exe_str); 32 + let mut new_cron = cron_list; 33 + if !new_cron.is_empty() && !new_cron.ends_with('\n') { 34 + new_cron.push('\n'); 35 + } 36 + new_cron.push_str(&new_job); 37 + new_cron.push('\n'); 38 + 39 + let child = Command::new("crontab") 40 + .arg("-") 41 + .stdin(std::process::Stdio::piped()) 42 + .spawn(); 43 + 44 + match child { 45 + Ok(mut child) => { 46 + let mut stdin = child.stdin.take().expect("Failed to open stdin"); 47 + if let Err(e) = stdin.write_all(new_cron.as_bytes()) { 48 + error!("Failed to write to crontab stdin: {}", e); 49 + return; 50 + } 51 + drop(stdin); 52 + 53 + match child.wait() { 54 + Ok(status) => { 55 + if status.success() { 56 + info!("Cron job has been set up to run every hour."); 57 + } else { 58 + error!("Failed to set up cron job (crontab exited with error)."); 59 + } 60 + } 61 + Err(e) => error!("Failed to wait on crontab process: {}", e), 62 + } 63 + } 64 + Err(e) => error!("Failed to spawn crontab process: {}", e), 65 + } 66 + }
-306
src/main.py
··· 1 - import os 2 - import json 3 - import logging 4 - import requests 5 - import magic 6 - from datetime import datetime 7 - from dotenv import load_dotenv 8 - from atproto import Client, models 9 - from atproto.exceptions import BadRequestError 10 - import sys 11 - from crontab import CronTab 12 - from logging.handlers import TimedRotatingFileHandler 13 - import glob 14 - import time 15 - 16 - # Ensure the script is run inside a virtual environment 17 - if not hasattr(sys, 'real_prefix') and not (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix): 18 - print("Error: This script must be run inside a virtual environment.") 19 - sys.exit(1) 20 - else: 21 - logging.info("Virtual environment detected.") 22 - 23 - # Define the paths 24 - BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) 25 - ASSETS_DIR = os.path.join(BASE_DIR, "assets") 26 - ENV_PATH = os.path.join(ASSETS_DIR, ".env") 27 - JSON_PATH = os.path.join(ASSETS_DIR, "cids.json") 28 - SCRIPT_PATH = os.path.abspath(__file__) 29 - 30 - # Define the log file directory and log file path 31 - log_dir = os.path.join(BASE_DIR, "logs") 32 - if not os.path.exists(log_dir): 33 - os.makedirs(log_dir) 34 - 35 - def cleanup_old_logs(log_directory, days=30): 36 - """Deletes log files older than the specified number of days.""" 37 - cutoff = time.time() - (days * 86400) # Convert days to seconds 38 - for log_file in glob.glob(os.path.join(log_directory, "update.log")): 39 - if os.path.isfile(log_file) and os.path.getmtime(log_file) < cutoff: 40 - os.remove(log_file) 41 - print(f"Deleted old log: {log_file}") 42 - 43 - # Cleanup logs older than 30 days before setting up new logging 44 - cleanup_old_logs(log_dir, days=30) 45 - 46 - # Use a fixed log file name for the current log; TimedRotatingFileHandler will manage rotations. 47 - log_file_path = os.path.join(log_dir, "update.log") 48 - 49 - # Configure logging to both console and file with bi-weekly rotation 50 - console_handler = logging.StreamHandler() 51 - console_handler.setLevel(logging.INFO) # Show only INFO and higher levels on console 52 - 53 - # Create a timed rotating file handler (rotate every 14 days, keep up to 5 backups) 54 - file_handler = TimedRotatingFileHandler( 55 - log_file_path, 56 - when="D", # 'D' stands for days 57 - interval=14, # Rotate every 14 days 58 - backupCount=5 59 - ) 60 - file_handler.setLevel(logging.INFO) # Save all logs to file 61 - 62 - formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s") 63 - console_handler.setFormatter(formatter) 64 - file_handler.setFormatter(formatter) 65 - 66 - # Root logger setup 67 - logger = logging.getLogger() 68 - logger.setLevel(logging.INFO) # Set the root logger level to INFO 69 - 70 - # Remove default handlers (to prevent duplication) 71 - for handler in logger.handlers[:]: 72 - logger.removeHandler(handler) 73 - 74 - # Add the custom handlers 75 - logger.addHandler(console_handler) 76 - logger.addHandler(file_handler) 77 - 78 - # Suppress httpx logging (this stops httpx internal logs) 79 - logging.getLogger("httpx").setLevel(logging.WARNING) # Suppress INFO and DEBUG logs from httpx 80 - 81 - def ensure_https(url): 82 - """Ensure the URL starts with https://.""" 83 - if not url.startswith("http://") and not url.startswith("https://"): 84 - return "https://" + url 85 - if url.startswith("http://"): 86 - return "https://" + url[7:] 87 - return url 88 - 89 - def is_endpoint_alive(url): 90 - """Check if the provided endpoint is alive by making a health check request.""" 91 - health_url = f"{url.rstrip('/')}/xrpc/_health" 92 - try: 93 - response = requests.get(health_url, timeout=5) 94 - if response.status_code == 200: 95 - logger.info(f"Endpoint {url} is alive and healthy.") 96 - return True 97 - else: 98 - logger.warning(f"Endpoint {url} is not responding correctly: {response.status_code}") 99 - return False 100 - except requests.RequestException as e: 101 - logger.error(f"Health check failed for {health_url}: {e}") 102 - return False 103 - 104 - def fetch_blob(did, cid, endpoint): 105 - """Fetch the blob from the endpoint.""" 106 - url = f"{endpoint}/xrpc/com.atproto.sync.getBlob?did={did}&cid={cid}" 107 - try: 108 - response = requests.get(url, timeout=5) 109 - response.raise_for_status() 110 - logger.info(f"Fetched blob {cid} successfully.") 111 - return response.content 112 - except requests.RequestException as e: 113 - logger.error(f"Failed to fetch blob {cid} for DID {did}: {e}") 114 - return None 115 - 116 - def get_blob_metadata(cid, did, endpoint): 117 - """Get the metadata for the blob.""" 118 - try: 119 - logger.info(f"Retrieving metadata for blob {cid}.") 120 - blob_data = fetch_blob(did, cid, endpoint) 121 - if blob_data is None: 122 - return None 123 - 124 - mime = magic.Magic(mime=True) 125 - mime_type = mime.from_buffer(blob_data) 126 - size = len(blob_data) 127 - 128 - logger.debug(f"Blob metadata: MIME Type - {mime_type}, Size - {size}") 129 - return { 130 - "$type": "blob", 131 - "ref": {"$link": cid}, 132 - "mimeType": mime_type, 133 - "size": size, 134 - } 135 - except Exception as e: 136 - logger.error(f"Error retrieving metadata for blob {cid}: {e}") 137 - return None 138 - 139 - def validate_environment_variables(): 140 - """Validate environment variables and return a dictionary of values.""" 141 - endpoint = os.getenv("ENDPOINT") 142 - handle = os.getenv("HANDLE") 143 - password = os.getenv("PASSWORD") 144 - did = os.getenv("DID") 145 - update_banner = os.getenv("UPDATE_BANNER", "false").lower() == "true" 146 - 147 - if not all([endpoint, handle, password, did]): 148 - logger.error("Missing environment variables. Ensure ENDPOINT, HANDLE, PASSWORD, and DID are set in .env file.") 149 - return None 150 - return { 151 - "endpoint": endpoint, 152 - "handle": handle, 153 - "password": password, 154 - "did": did, 155 - "update_banner": update_banner 156 - } 157 - 158 - def setup_cron_job(): 159 - """Set up the cron job to run every hour.""" 160 - # Get the path to the virtual environment's Python interpreter 161 - venv_python = os.path.join(BASE_DIR, ".venv", "bin", "python3") 162 - 163 - # Check if the cron job already exists 164 - cron = CronTab(user=True) 165 - job_exists = False 166 - for job in cron: 167 - if SCRIPT_PATH in job.command: 168 - job_exists = True 169 - break 170 - 171 - if not job_exists: 172 - # Set up the cron job to run every hour (top of the hour) 173 - cron_command = f"{venv_python} {SCRIPT_PATH}" 174 - job = cron.new(command=cron_command, comment="Avatar update script") 175 - job.minute.on(0) # Run at the start of every hour 176 - cron.write() 177 - logger.info("Cron job has been set up to run every hour within the virtual environment.") 178 - else: 179 - logger.info("Cron job already exists.") 180 - 181 - def main(): 182 - """Main function to run the avatar and banner update process.""" 183 - # Set up the cron job (only once) 184 - try: 185 - setup_cron_job() 186 - except Exception as e: 187 - logger.error(f"Error setting cron job: {e}") 188 - pass 189 - 190 - logger.info("Script started.") 191 - logger.info("Starting update process...") 192 - 193 - # Load environment variables from the .env file 194 - if os.path.exists(ENV_PATH): 195 - load_dotenv(ENV_PATH) 196 - logger.info(f"Loaded environment from {ENV_PATH}") 197 - else: 198 - logger.error(f"Missing .env file at {ENV_PATH}") 199 - return 200 - 201 - env_vars = validate_environment_variables() 202 - if not env_vars: 203 - return 204 - 205 - # Ensure endpoint URL is correct and alive 206 - endpoint = ensure_https(env_vars["endpoint"]) 207 - if not is_endpoint_alive(endpoint): 208 - logger.error(f"Endpoint {endpoint} is not responding.") 209 - return 210 - 211 - # Load the CID mapping from the JSON file 212 - try: 213 - with open(JSON_PATH, "r") as f: 214 - blob_dict = json.load(f) 215 - logger.info(f"Loaded blob CIDs from {JSON_PATH}.") 216 - except Exception as e: 217 - logger.error(f"Error loading cids.json from {JSON_PATH}: {e}") 218 - return 219 - 220 - # Determine the blob CIDs for the current hour from the modified structure 221 - current_hour = datetime.now().strftime("%H") 222 - logger.info(f"Current hour: {current_hour}") 223 - 224 - current_entry = blob_dict.get(current_hour) 225 - if not current_entry: 226 - logger.warning(f"No entry found for hour {current_hour} in cids.json") 227 - return 228 - 229 - new_avatar_cid = current_entry.get("avatar") 230 - new_banner_cid = current_entry.get("banner") if env_vars["update_banner"] else None 231 - 232 - if not new_avatar_cid: 233 - logger.warning(f"No avatar CID found for hour {current_hour}") 234 - return 235 - 236 - logger.info(f"Selected avatar CID: {new_avatar_cid}") 237 - if env_vars["update_banner"]: 238 - if new_banner_cid: 239 - logger.info(f"Selected banner CID: {new_banner_cid}") 240 - else: 241 - logger.warning(f"UPDATE_BANNER is enabled, but no banner CID found for hour {current_hour}") 242 - 243 - # Authenticate with the endpoint 244 - client = Client(endpoint) 245 - try: 246 - client.login(env_vars["handle"], env_vars["password"]) 247 - logger.info("Authentication successful.") 248 - except Exception as e: 249 - logger.error(f"Authentication failed: {e}") 250 - return 251 - 252 - # Fetch the current profile and update it with the new avatar (and optionally banner) 253 - try: 254 - current_profile_record = client.app.bsky.actor.profile.get( 255 - client.me.did, "self" 256 - ) 257 - current_profile = current_profile_record.value 258 - swap_record_cid = current_profile_record.cid 259 - logger.info("Current profile record fetched successfully.") 260 - except BadRequestError: 261 - current_profile = swap_record_cid = None 262 - logger.warning("Failed to fetch current profile record.") 263 - 264 - old_description = current_profile.description if current_profile else None 265 - old_display_name = current_profile.display_name if current_profile else None 266 - old_banner = current_profile.banner if current_profile else None 267 - 268 - avatar_metadata = get_blob_metadata(new_avatar_cid, env_vars["did"], endpoint) 269 - if avatar_metadata is None: 270 - logger.error(f"Could not retrieve metadata for avatar blob CID: {new_avatar_cid}") 271 - return 272 - 273 - banner_metadata = None 274 - if env_vars["update_banner"] and new_banner_cid: 275 - banner_metadata = get_blob_metadata(new_banner_cid, env_vars["did"], endpoint) 276 - if banner_metadata is None: 277 - logger.warning(f"Could not retrieve metadata for banner blob CID: {new_banner_cid}") 278 - banner_metadata = old_banner 279 - else: 280 - banner_metadata = old_banner 281 - 282 - # Update the profile with the new avatar and optionally the new banner 283 - try: 284 - client.com.atproto.repo.put_record( 285 - models.ComAtprotoRepoPutRecord.Data( 286 - collection=models.ids.AppBskyActorProfile, 287 - repo=client.me.did, 288 - rkey="self", 289 - swap_record=swap_record_cid, 290 - record=models.AppBskyActorProfile.Record( 291 - avatar=avatar_metadata, 292 - banner=banner_metadata, 293 - description=old_description, 294 - display_name=old_display_name, 295 - ), 296 - ) 297 - ) 298 - if env_vars["update_banner"] and new_banner_cid: 299 - logger.info(f"Profile updated successfully with avatar CID {new_avatar_cid} and banner CID {new_banner_cid}") 300 - else: 301 - logger.info(f"Profile updated successfully with avatar CID: {new_avatar_cid}") 302 - except Exception as e: 303 - logger.error(f"Failed to update profile record: {e}") 304 - 305 - if __name__ == "__main__": 306 - main()
+191
src/main.rs
··· 1 + mod bsky; 2 + mod cron; 3 + mod utils; 4 + 5 + use anyhow::{Result, Context, anyhow}; 6 + use bsky_sdk::BskyAgent; 7 + use bsky_sdk::agent::config::Config; 8 + use chrono::Local; 9 + use dotenvy::dotenv; 10 + use serde::{Deserialize, Serialize}; 11 + use std::collections::HashMap; 12 + use std::env; 13 + use std::fs; 14 + use tracing::{info, error, warn}; 15 + use tracing_subscriber::{fmt, prelude::*, EnvFilter}; 16 + use atrium_api::app::bsky::actor::profile::{Record, RecordData}; 17 + use atrium_api::types::{BlobRef, TypedBlobRef, Unknown}; 18 + 19 + #[derive(Serialize, Deserialize, Debug)] 20 + struct HourEntry { 21 + avatar: String, 22 + banner: Option<String>, 23 + } 24 + 25 + #[tokio::main] 26 + async fn main() -> Result<()> { 27 + // Define the paths 28 + let base_dir = env::current_dir()?; 29 + let assets_dir = base_dir.join("assets"); 30 + let json_path = assets_dir.join("cids.json"); 31 + let log_dir = base_dir.join("logs"); 32 + 33 + if !log_dir.exists() { 34 + fs::create_dir_all(&log_dir)?; 35 + } 36 + 37 + // Set up tracing 38 + let file_appender = tracing_appender::rolling::daily(&log_dir, "update.log"); 39 + let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender); 40 + 41 + let filter = EnvFilter::try_from_default_env() 42 + .unwrap_or_else(|_| EnvFilter::new("info")); 43 + 44 + tracing_subscriber::registry() 45 + .with(filter) 46 + .with(fmt::layer().with_writer(std::io::stdout)) 47 + .with(fmt::layer().with_writer(non_blocking).with_ansi(false)) 48 + .init(); 49 + 50 + info!("Script started."); 51 + 52 + // Setup cron job 53 + cron::setup_cron_job(); 54 + 55 + // Load environment variables 56 + dotenv().ok(); 57 + // Also try loading from assets/.env if it exists (per original script) 58 + let env_path = assets_dir.join(".env"); 59 + if env_path.exists() { 60 + dotenvy::from_path(&env_path).ok(); 61 + info!("Loaded environment from {:?}", env_path); 62 + } 63 + 64 + let env_vars = match utils::validate_environment_variables() { 65 + Some(v) => v, 66 + None => return Ok(()), 67 + }; 68 + 69 + let endpoint = utils::ensure_https(&env_vars.endpoint); 70 + if !utils::is_endpoint_alive(&endpoint).await { 71 + error!("Endpoint {} is not responding.", endpoint); 72 + return Ok(()); 73 + } 74 + 75 + // Load CID mapping 76 + let blob_dict: HashMap<String, HourEntry> = if json_path.exists() { 77 + let content = fs::read_to_string(&json_path)?; 78 + serde_json::from_str(&content).context("Failed to parse cids.json")? 79 + } else { 80 + error!("Missing cids.json at {:?}", json_path); 81 + return Ok(()); 82 + }; 83 + 84 + let current_hour = Local::now().format("%H").to_string(); 85 + info!("Current hour: {}", current_hour); 86 + 87 + let current_entry = match blob_dict.get(&current_hour) { 88 + Some(entry) => entry, 89 + None => { 90 + warn!("No entry found for hour {} in cids.json", current_hour); 91 + return Ok(()); 92 + } 93 + }; 94 + 95 + let new_avatar_cid = &current_entry.avatar; 96 + let new_banner_cid = current_entry.banner.as_ref(); 97 + 98 + info!("Selected avatar CID: {}", new_avatar_cid); 99 + if env_vars.update_banner { 100 + if let Some(bcid) = new_banner_cid { 101 + info!("Selected banner CID: {}", bcid); 102 + } 103 + } 104 + 105 + // Authenticate 106 + let agent = BskyAgent::builder() 107 + .config(Config { 108 + endpoint: endpoint.clone(), 109 + ..Default::default() 110 + }) 111 + .build() 112 + .await?; 113 + 114 + agent.login(env_vars.handle.clone(), env_vars.password.clone()).await?; 115 + info!("Authentication successful."); 116 + 117 + // Fetch current profile 118 + let me = agent.api.com.atproto.repo.get_record( 119 + atrium_api::com::atproto::repo::get_record::ParametersData { 120 + collection: "app.bsky.actor.profile".parse().map_err(|e| anyhow!("{:?}", e))?, 121 + repo: env_vars.did.clone().parse().map_err(|e| anyhow!("{:?}", e))?, 122 + rkey: "self".parse().map_err(|e| anyhow!("{:?}", e))?, 123 + cid: None, 124 + }.into() 125 + ).await; 126 + 127 + let (mut current_record_data, swap_record_cid) = match me { 128 + Ok(output) => { 129 + let record = serde_json::from_value::<Record>(serde_json::to_value(&output.data.value)?)?; 130 + (record.data, output.data.cid) 131 + } 132 + Err(e) => { 133 + warn!("Failed to fetch current profile record: {:?}", e); 134 + // Default empty record data 135 + (RecordData { 136 + avatar: None, 137 + banner: None, 138 + created_at: None, 139 + description: None, 140 + display_name: None, 141 + joined_via_starter_pack: None, 142 + labels: None, 143 + pinned_post: None, 144 + pronouns: None, 145 + website: None, 146 + }, None) 147 + } 148 + }; 149 + 150 + // Update avatar 151 + match bsky::get_blob_metadata(new_avatar_cid, &env_vars.did, &endpoint).await { 152 + Ok(blob) => { 153 + current_record_data.avatar = Some(BlobRef::Typed(TypedBlobRef::Blob(blob))); 154 + } 155 + Err(e) => { 156 + error!("Could not retrieve metadata for avatar blob CID: {}. Error: {:?}", new_avatar_cid, e); 157 + return Ok(()); 158 + } 159 + } 160 + 161 + // Update banner if needed 162 + if env_vars.update_banner { 163 + if let Some(bcid) = new_banner_cid { 164 + match bsky::get_blob_metadata(bcid, &env_vars.did, &endpoint).await { 165 + Ok(blob) => { 166 + current_record_data.banner = Some(BlobRef::Typed(TypedBlobRef::Blob(blob))); 167 + } 168 + Err(e) => { 169 + warn!("Could not retrieve metadata for banner blob CID: {}. Error: {:?}", bcid, e); 170 + } 171 + } 172 + } 173 + } 174 + 175 + // Put record back 176 + agent.api.com.atproto.repo.put_record( 177 + atrium_api::com::atproto::repo::put_record::InputData { 178 + collection: "app.bsky.actor.profile".parse().map_err(|e| anyhow!("{:?}", e))?, 179 + repo: env_vars.did.parse().map_err(|e| anyhow!("{:?}", e))?, 180 + rkey: "self".parse().map_err(|e| anyhow!("{:?}", e))?, 181 + record: serde_json::from_value::<Unknown>(serde_json::to_value(current_record_data)?)?, 182 + swap_record: swap_record_cid, 183 + validate: None, 184 + swap_commit: None, 185 + }.into() 186 + ).await?; 187 + 188 + info!("Profile updated successfully."); 189 + 190 + Ok(()) 191 + }
+62
src/utils.rs
··· 1 + use reqwest::Client; 2 + use tracing::{info, warn, error}; 3 + use std::env; 4 + 5 + pub fn ensure_https(url: &str) -> String { 6 + if !url.starts_with("http://") && !url.starts_with("https://") { 7 + return format!("https://{}", url); 8 + } 9 + if let Some(stripped) = url.strip_prefix("http://") { 10 + return format!("https://{}", stripped); 11 + } 12 + url.to_string() 13 + } 14 + 15 + pub async fn is_endpoint_alive(url: &str) -> bool { 16 + let health_url = format!("{}/xrpc/_health", url.trim_end_matches('/')); 17 + let client = Client::new(); 18 + match client.get(&health_url).timeout(std::time::Duration::from_secs(5)).send().await { 19 + Ok(response) => { 20 + if response.status().is_success() { 21 + info!("Endpoint {} is alive and healthy.", url); 22 + true 23 + } else { 24 + warn!("Endpoint {} is not responding correctly: {}", url, response.status()); 25 + false 26 + } 27 + } 28 + Err(e) => { 29 + error!("Health check failed for {}: {}", health_url, e); 30 + false 31 + } 32 + } 33 + } 34 + 35 + pub struct EnvVars { 36 + pub endpoint: String, 37 + pub handle: String, 38 + pub password: String, 39 + pub did: String, 40 + pub update_banner: bool, 41 + } 42 + 43 + pub fn validate_environment_variables() -> Option<EnvVars> { 44 + let endpoint = env::var("ENDPOINT").ok(); 45 + let handle = env::var("HANDLE").ok(); 46 + let password = env::var("PASSWORD").ok(); 47 + let did = env::var("DID").ok(); 48 + let update_banner = env::var("UPDATE_BANNER").unwrap_or_else(|_| "false".to_string()).to_lowercase() == "true"; 49 + 50 + if let (Some(endpoint), Some(handle), Some(password), Some(did)) = (endpoint, handle, password, did) { 51 + Some(EnvVars { 52 + endpoint, 53 + handle, 54 + password, 55 + did, 56 + update_banner, 57 + }) 58 + } else { 59 + error!("Missing environment variables. Ensure ENDPOINT, HANDLE, PASSWORD, and DID are set."); 60 + None 61 + } 62 + }