├── .dockerignore ├── .github └── workflows │ ├── build-image.yml │ └── check-rust.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Dockerfile ├── LICENSE ├── README.md ├── renovate.json ├── sailfish.toml └── src ├── api ├── common.rs ├── error.rs ├── index.rs ├── mod.rs ├── schema.graphql ├── watching.graphql ├── watching.rs └── watching.svg ├── config.rs └── main.rs /.dockerignore: -------------------------------------------------------------------------------- 1 | .github/ 2 | Dockerfile 3 | .dockerignore 4 | .gitignore 5 | target/ 6 | renovate.json 7 | README.md 8 | LICENSE 9 | -------------------------------------------------------------------------------- /.github/workflows/build-image.yml: -------------------------------------------------------------------------------- 1 | name: 'Build Image' 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - '**.md' 7 | branches-ignore: 8 | - 'renovate/**' 9 | 10 | release: 11 | types: 12 | - published 13 | 14 | workflow_dispatch: 15 | 16 | permissions: 17 | contents: read 18 | packages: write 19 | actions: read 20 | security-events: write 21 | 22 | jobs: 23 | build: 24 | uses: SlashNephy/.github/.github/workflows/docker-build.yml@master 25 | with: 26 | image-name: ghcr.io/slashnephy/annict-profile-card 27 | image-platforms: linux/amd64 28 | -------------------------------------------------------------------------------- /.github/workflows/check-rust.yml: -------------------------------------------------------------------------------- 1 | name: 'Check' 2 | 3 | on: 4 | pull_request: 5 | types: 6 | - opened 7 | - synchronize 8 | 9 | workflow_dispatch: 10 | 11 | jobs: 12 | build: 13 | uses: SlashNephy/.github/.github/workflows/cargo-run.yml@master 14 | permissions: 15 | contents: 'read' 16 | with: 17 | command: 'build' 18 | args: '--release' 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | target/* 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "actix-codec" 7 | version = "0.5.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe" 10 | dependencies = [ 11 | "bitflags", 12 | "bytes", 13 | "futures-core", 14 | "futures-sink", 15 | "log", 16 | "memchr", 17 | "pin-project-lite", 18 | "tokio", 19 | "tokio-util", 20 | ] 21 | 22 | [[package]] 23 | name = "actix-cors" 24 | version = "0.6.2" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "02a0adcaabb68f1dfe8880cb3c5f049261c68f5d69ce06b6f3a930f31710838e" 27 | dependencies = [ 28 | "actix-utils", 29 | "actix-web", 30 | "derive_more", 31 | "futures-util", 32 | "log", 33 | "once_cell", 34 | "smallvec", 35 | ] 36 | 37 | [[package]] 38 | name = "actix-http" 39 | version = "3.2.1" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "6f9ffb6db08c1c3a1f4aef540f1a63193adc73c4fbd40b75a95fc8c5258f6e51" 42 | dependencies = [ 43 | "actix-codec", 44 | "actix-rt", 45 | "actix-service", 46 | "actix-tls", 47 | "actix-utils", 48 | "ahash", 49 | "base64", 50 | "bitflags", 51 | "brotli", 52 | "bytes", 53 | "bytestring", 54 | "derive_more", 55 | "encoding_rs", 56 | "flate2", 57 | "futures-core", 58 | "h2", 59 | "http", 60 | "httparse", 61 | "httpdate", 62 | "itoa 1.0.3", 63 | "language-tags", 64 | "local-channel", 65 | "mime", 66 | "percent-encoding", 67 | "pin-project-lite", 68 | "rand", 69 | "sha1", 70 | "smallvec", 71 | "tracing", 72 | "zstd", 73 | ] 74 | 75 | [[package]] 76 | name = "actix-macros" 77 | version = "0.2.3" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" 80 | dependencies = [ 81 | "quote", 82 | "syn", 83 | ] 84 | 85 | [[package]] 86 | name = "actix-router" 87 | version = "0.5.0" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "eb60846b52c118f2f04a56cc90880a274271c489b2498623d58176f8ca21fa80" 90 | dependencies = [ 91 | "bytestring", 92 | "firestorm", 93 | "http", 94 | "log", 95 | "regex", 96 | "serde", 97 | ] 98 | 99 | [[package]] 100 | name = "actix-rt" 101 | version = "2.7.0" 102 | source = "registry+https://github.com/rust-lang/crates.io-index" 103 | checksum = "7ea16c295198e958ef31930a6ef37d0fb64e9ca3b6116e6b93a8bdae96ee1000" 104 | dependencies = [ 105 | "futures-core", 106 | "tokio", 107 | ] 108 | 109 | [[package]] 110 | name = "actix-server" 111 | version = "2.1.1" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "0da34f8e659ea1b077bb4637948b815cd3768ad5a188fdcd74ff4d84240cd824" 114 | dependencies = [ 115 | "actix-rt", 116 | "actix-service", 117 | "actix-utils", 118 | "futures-core", 119 | "futures-util", 120 | "mio", 121 | "num_cpus", 122 | "socket2", 123 | "tokio", 124 | "tracing", 125 | ] 126 | 127 | [[package]] 128 | name = "actix-service" 129 | version = "2.0.0" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "77f5f9d66a8730d0fae62c26f3424f5751e5518086628a40b7ab6fca4a705034" 132 | dependencies = [ 133 | "futures-core", 134 | "paste", 135 | "pin-project-lite", 136 | ] 137 | 138 | [[package]] 139 | name = "actix-tls" 140 | version = "3.0.3" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "9fde0cf292f7cdc7f070803cb9a0d45c018441321a78b1042ffbbb81ec333297" 143 | dependencies = [ 144 | "actix-codec", 145 | "actix-rt", 146 | "actix-service", 147 | "actix-utils", 148 | "futures-core", 149 | "http", 150 | "log", 151 | "openssl", 152 | "pin-project-lite", 153 | "tokio-openssl", 154 | "tokio-util", 155 | ] 156 | 157 | [[package]] 158 | name = "actix-utils" 159 | version = "3.0.0" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "e491cbaac2e7fc788dfff99ff48ef317e23b3cf63dbaf7aaab6418f40f92aa94" 162 | dependencies = [ 163 | "local-waker", 164 | "pin-project-lite", 165 | ] 166 | 167 | [[package]] 168 | name = "actix-web" 169 | version = "4.1.0" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "a27e8fe9ba4ae613c21f677c2cfaf0696c3744030c6f485b34634e502d6bb379" 172 | dependencies = [ 173 | "actix-codec", 174 | "actix-http", 175 | "actix-macros", 176 | "actix-router", 177 | "actix-rt", 178 | "actix-server", 179 | "actix-service", 180 | "actix-tls", 181 | "actix-utils", 182 | "actix-web-codegen", 183 | "ahash", 184 | "bytes", 185 | "bytestring", 186 | "cfg-if", 187 | "cookie", 188 | "derive_more", 189 | "encoding_rs", 190 | "futures-core", 191 | "futures-util", 192 | "itoa 1.0.3", 193 | "language-tags", 194 | "log", 195 | "mime", 196 | "once_cell", 197 | "pin-project-lite", 198 | "regex", 199 | "serde", 200 | "serde_json", 201 | "serde_urlencoded", 202 | "smallvec", 203 | "socket2", 204 | "time 0.3.13", 205 | "url", 206 | ] 207 | 208 | [[package]] 209 | name = "actix-web-codegen" 210 | version = "4.0.1" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "5f270541caec49c15673b0af0e9a00143421ad4f118d2df7edcb68b627632f56" 213 | dependencies = [ 214 | "actix-router", 215 | "proc-macro2", 216 | "quote", 217 | "syn", 218 | ] 219 | 220 | [[package]] 221 | name = "adler" 222 | version = "1.0.2" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 225 | 226 | [[package]] 227 | name = "ahash" 228 | version = "0.7.4" 229 | source = "registry+https://github.com/rust-lang/crates.io-index" 230 | checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" 231 | dependencies = [ 232 | "getrandom", 233 | "once_cell", 234 | "version_check", 235 | ] 236 | 237 | [[package]] 238 | name = "aho-corasick" 239 | version = "0.7.18" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 242 | dependencies = [ 243 | "memchr", 244 | ] 245 | 246 | [[package]] 247 | name = "alloc-no-stdlib" 248 | version = "2.0.3" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "35ef4730490ad1c4eae5c4325b2a95f521d023e5c885853ff7aca0a6a1631db3" 251 | 252 | [[package]] 253 | name = "alloc-stdlib" 254 | version = "0.2.1" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "697ed7edc0f1711de49ce108c541623a0af97c6c60b2f6e2b65229847ac843c2" 257 | dependencies = [ 258 | "alloc-no-stdlib", 259 | ] 260 | 261 | [[package]] 262 | name = "android_system_properties" 263 | version = "0.1.4" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "d7ed72e1635e121ca3e79420540282af22da58be50de153d36f81ddc6b83aa9e" 266 | dependencies = [ 267 | "libc", 268 | ] 269 | 270 | [[package]] 271 | name = "annict-profile-card" 272 | version = "0.0.1" 273 | dependencies = [ 274 | "actix-cors", 275 | "actix-web", 276 | "awc", 277 | "base64", 278 | "chrono", 279 | "chrono-tz", 280 | "env_logger", 281 | "envy", 282 | "futures", 283 | "graphql_client", 284 | "log", 285 | "openssl-probe", 286 | "sailfish", 287 | "serde", 288 | "serde_json", 289 | "thiserror", 290 | ] 291 | 292 | [[package]] 293 | name = "ascii" 294 | version = "0.9.3" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" 297 | 298 | [[package]] 299 | name = "atty" 300 | version = "0.2.14" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 303 | dependencies = [ 304 | "hermit-abi", 305 | "libc", 306 | "winapi", 307 | ] 308 | 309 | [[package]] 310 | name = "autocfg" 311 | version = "1.1.0" 312 | source = "registry+https://github.com/rust-lang/crates.io-index" 313 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 314 | 315 | [[package]] 316 | name = "awc" 317 | version = "3.0.0" 318 | source = "registry+https://github.com/rust-lang/crates.io-index" 319 | checksum = "65c60c44fbf3c8cee365e86b97d706e513b733c4eeb16437b45b88d2fffe889a" 320 | dependencies = [ 321 | "actix-codec", 322 | "actix-http", 323 | "actix-rt", 324 | "actix-service", 325 | "actix-tls", 326 | "actix-utils", 327 | "ahash", 328 | "base64", 329 | "bytes", 330 | "cfg-if", 331 | "cookie", 332 | "derive_more", 333 | "futures-core", 334 | "futures-util", 335 | "h2", 336 | "http", 337 | "itoa 1.0.3", 338 | "log", 339 | "mime", 340 | "percent-encoding", 341 | "pin-project-lite", 342 | "rand", 343 | "serde", 344 | "serde_json", 345 | "serde_urlencoded", 346 | "tokio", 347 | ] 348 | 349 | [[package]] 350 | name = "base64" 351 | version = "0.13.0" 352 | source = "registry+https://github.com/rust-lang/crates.io-index" 353 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 354 | 355 | [[package]] 356 | name = "bitflags" 357 | version = "1.2.1" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 360 | 361 | [[package]] 362 | name = "block-buffer" 363 | version = "0.10.2" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" 366 | dependencies = [ 367 | "generic-array", 368 | ] 369 | 370 | [[package]] 371 | name = "brotli" 372 | version = "3.3.4" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" 375 | dependencies = [ 376 | "alloc-no-stdlib", 377 | "alloc-stdlib", 378 | "brotli-decompressor", 379 | ] 380 | 381 | [[package]] 382 | name = "brotli-decompressor" 383 | version = "2.3.2" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" 386 | dependencies = [ 387 | "alloc-no-stdlib", 388 | "alloc-stdlib", 389 | ] 390 | 391 | [[package]] 392 | name = "bumpalo" 393 | version = "3.6.1" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" 396 | 397 | [[package]] 398 | name = "byteorder" 399 | version = "1.4.3" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 402 | 403 | [[package]] 404 | name = "bytes" 405 | version = "1.0.1" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" 408 | 409 | [[package]] 410 | name = "bytestring" 411 | version = "1.0.0" 412 | source = "registry+https://github.com/rust-lang/crates.io-index" 413 | checksum = "90706ba19e97b90786e19dc0d5e2abd80008d99d4c0c5d1ad0b5e72cec7c494d" 414 | dependencies = [ 415 | "bytes", 416 | ] 417 | 418 | [[package]] 419 | name = "cc" 420 | version = "1.0.67" 421 | source = "registry+https://github.com/rust-lang/crates.io-index" 422 | checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" 423 | dependencies = [ 424 | "jobserver", 425 | ] 426 | 427 | [[package]] 428 | name = "cfg-if" 429 | version = "1.0.0" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 432 | 433 | [[package]] 434 | name = "chrono" 435 | version = "0.4.22" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" 438 | dependencies = [ 439 | "iana-time-zone", 440 | "js-sys", 441 | "num-integer", 442 | "num-traits", 443 | "time 0.1.44", 444 | "wasm-bindgen", 445 | "winapi", 446 | ] 447 | 448 | [[package]] 449 | name = "chrono-tz" 450 | version = "0.6.3" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "29c39203181991a7dd4343b8005bd804e7a9a37afb8ac070e43771e8c820bbde" 453 | dependencies = [ 454 | "chrono", 455 | "chrono-tz-build", 456 | "phf", 457 | ] 458 | 459 | [[package]] 460 | name = "chrono-tz-build" 461 | version = "0.0.3" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "6f509c3a87b33437b05e2458750a0700e5bdd6956176773e6c7d6dd15a283a0c" 464 | dependencies = [ 465 | "parse-zoneinfo", 466 | "phf", 467 | "phf_codegen", 468 | ] 469 | 470 | [[package]] 471 | name = "combine" 472 | version = "3.8.1" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" 475 | dependencies = [ 476 | "ascii", 477 | "byteorder", 478 | "either", 479 | "memchr", 480 | "unreachable", 481 | ] 482 | 483 | [[package]] 484 | name = "convert_case" 485 | version = "0.4.0" 486 | source = "registry+https://github.com/rust-lang/crates.io-index" 487 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" 488 | 489 | [[package]] 490 | name = "cookie" 491 | version = "0.16.0" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05" 494 | dependencies = [ 495 | "percent-encoding", 496 | "time 0.3.13", 497 | "version_check", 498 | ] 499 | 500 | [[package]] 501 | name = "core-foundation-sys" 502 | version = "0.8.3" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 505 | 506 | [[package]] 507 | name = "cpufeatures" 508 | version = "0.2.2" 509 | source = "registry+https://github.com/rust-lang/crates.io-index" 510 | checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" 511 | dependencies = [ 512 | "libc", 513 | ] 514 | 515 | [[package]] 516 | name = "crc32fast" 517 | version = "1.2.1" 518 | source = "registry+https://github.com/rust-lang/crates.io-index" 519 | checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" 520 | dependencies = [ 521 | "cfg-if", 522 | ] 523 | 524 | [[package]] 525 | name = "crypto-common" 526 | version = "0.1.6" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 529 | dependencies = [ 530 | "generic-array", 531 | "typenum", 532 | ] 533 | 534 | [[package]] 535 | name = "derive_more" 536 | version = "0.99.13" 537 | source = "registry+https://github.com/rust-lang/crates.io-index" 538 | checksum = "f82b1b72f1263f214c0f823371768776c4f5841b942c9883aa8e5ec584fd0ba6" 539 | dependencies = [ 540 | "convert_case", 541 | "proc-macro2", 542 | "quote", 543 | "syn", 544 | ] 545 | 546 | [[package]] 547 | name = "digest" 548 | version = "0.10.3" 549 | source = "registry+https://github.com/rust-lang/crates.io-index" 550 | checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" 551 | dependencies = [ 552 | "block-buffer", 553 | "crypto-common", 554 | ] 555 | 556 | [[package]] 557 | name = "either" 558 | version = "1.6.1" 559 | source = "registry+https://github.com/rust-lang/crates.io-index" 560 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" 561 | 562 | [[package]] 563 | name = "encoding_rs" 564 | version = "0.8.28" 565 | source = "registry+https://github.com/rust-lang/crates.io-index" 566 | checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" 567 | dependencies = [ 568 | "cfg-if", 569 | ] 570 | 571 | [[package]] 572 | name = "env_logger" 573 | version = "0.9.0" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" 576 | dependencies = [ 577 | "atty", 578 | "humantime", 579 | "log", 580 | "regex", 581 | "termcolor", 582 | ] 583 | 584 | [[package]] 585 | name = "envy" 586 | version = "0.4.2" 587 | source = "registry+https://github.com/rust-lang/crates.io-index" 588 | checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" 589 | dependencies = [ 590 | "serde", 591 | ] 592 | 593 | [[package]] 594 | name = "filetime" 595 | version = "0.2.14" 596 | source = "registry+https://github.com/rust-lang/crates.io-index" 597 | checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" 598 | dependencies = [ 599 | "cfg-if", 600 | "libc", 601 | "redox_syscall", 602 | "winapi", 603 | ] 604 | 605 | [[package]] 606 | name = "firestorm" 607 | version = "0.5.1" 608 | source = "registry+https://github.com/rust-lang/crates.io-index" 609 | checksum = "2c5f6c2c942da57e2aaaa84b8a521489486f14e75e7fa91dab70aba913975f98" 610 | 611 | [[package]] 612 | name = "flate2" 613 | version = "1.0.20" 614 | source = "registry+https://github.com/rust-lang/crates.io-index" 615 | checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" 616 | dependencies = [ 617 | "cfg-if", 618 | "crc32fast", 619 | "libc", 620 | "miniz_oxide", 621 | ] 622 | 623 | [[package]] 624 | name = "fnv" 625 | version = "1.0.7" 626 | source = "registry+https://github.com/rust-lang/crates.io-index" 627 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 628 | 629 | [[package]] 630 | name = "foreign-types" 631 | version = "0.3.2" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 634 | dependencies = [ 635 | "foreign-types-shared", 636 | ] 637 | 638 | [[package]] 639 | name = "foreign-types-shared" 640 | version = "0.1.1" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 643 | 644 | [[package]] 645 | name = "form_urlencoded" 646 | version = "1.0.1" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" 649 | dependencies = [ 650 | "matches", 651 | "percent-encoding", 652 | ] 653 | 654 | [[package]] 655 | name = "futures" 656 | version = "0.3.21" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" 659 | dependencies = [ 660 | "futures-channel", 661 | "futures-core", 662 | "futures-executor", 663 | "futures-io", 664 | "futures-sink", 665 | "futures-task", 666 | "futures-util", 667 | ] 668 | 669 | [[package]] 670 | name = "futures-channel" 671 | version = "0.3.21" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" 674 | dependencies = [ 675 | "futures-core", 676 | "futures-sink", 677 | ] 678 | 679 | [[package]] 680 | name = "futures-core" 681 | version = "0.3.21" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" 684 | 685 | [[package]] 686 | name = "futures-executor" 687 | version = "0.3.21" 688 | source = "registry+https://github.com/rust-lang/crates.io-index" 689 | checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" 690 | dependencies = [ 691 | "futures-core", 692 | "futures-task", 693 | "futures-util", 694 | ] 695 | 696 | [[package]] 697 | name = "futures-io" 698 | version = "0.3.21" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" 701 | 702 | [[package]] 703 | name = "futures-macro" 704 | version = "0.3.21" 705 | source = "registry+https://github.com/rust-lang/crates.io-index" 706 | checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" 707 | dependencies = [ 708 | "proc-macro2", 709 | "quote", 710 | "syn", 711 | ] 712 | 713 | [[package]] 714 | name = "futures-sink" 715 | version = "0.3.21" 716 | source = "registry+https://github.com/rust-lang/crates.io-index" 717 | checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" 718 | 719 | [[package]] 720 | name = "futures-task" 721 | version = "0.3.21" 722 | source = "registry+https://github.com/rust-lang/crates.io-index" 723 | checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" 724 | 725 | [[package]] 726 | name = "futures-util" 727 | version = "0.3.21" 728 | source = "registry+https://github.com/rust-lang/crates.io-index" 729 | checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" 730 | dependencies = [ 731 | "futures-channel", 732 | "futures-core", 733 | "futures-io", 734 | "futures-macro", 735 | "futures-sink", 736 | "futures-task", 737 | "memchr", 738 | "pin-project-lite", 739 | "pin-utils", 740 | "slab", 741 | ] 742 | 743 | [[package]] 744 | name = "generic-array" 745 | version = "0.14.4" 746 | source = "registry+https://github.com/rust-lang/crates.io-index" 747 | checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" 748 | dependencies = [ 749 | "typenum", 750 | "version_check", 751 | ] 752 | 753 | [[package]] 754 | name = "getrandom" 755 | version = "0.2.3" 756 | source = "registry+https://github.com/rust-lang/crates.io-index" 757 | checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" 758 | dependencies = [ 759 | "cfg-if", 760 | "libc", 761 | "wasi 0.10.0+wasi-snapshot-preview1", 762 | ] 763 | 764 | [[package]] 765 | name = "graphql-introspection-query" 766 | version = "0.2.0" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | checksum = "7f2a4732cf5140bd6c082434494f785a19cfb566ab07d1382c3671f5812fed6d" 769 | dependencies = [ 770 | "serde", 771 | ] 772 | 773 | [[package]] 774 | name = "graphql-parser" 775 | version = "0.4.0" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "d2ebc8013b4426d5b81a4364c419a95ed0b404af2b82e2457de52d9348f0e474" 778 | dependencies = [ 779 | "combine", 780 | "thiserror", 781 | ] 782 | 783 | [[package]] 784 | name = "graphql_client" 785 | version = "0.11.0" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | checksum = "7fc16d75d169fddb720d8f1c7aed6413e329e1584079b9734ff07266a193f5bc" 788 | dependencies = [ 789 | "graphql_query_derive", 790 | "serde", 791 | "serde_json", 792 | ] 793 | 794 | [[package]] 795 | name = "graphql_client_codegen" 796 | version = "0.11.0" 797 | source = "registry+https://github.com/rust-lang/crates.io-index" 798 | checksum = "f290ecfa3bea3e8a157899dc8a1d96ee7dd6405c18c8ddd213fc58939d18a0e9" 799 | dependencies = [ 800 | "graphql-introspection-query", 801 | "graphql-parser", 802 | "heck", 803 | "lazy_static", 804 | "proc-macro2", 805 | "quote", 806 | "serde", 807 | "serde_json", 808 | "syn", 809 | ] 810 | 811 | [[package]] 812 | name = "graphql_query_derive" 813 | version = "0.11.0" 814 | source = "registry+https://github.com/rust-lang/crates.io-index" 815 | checksum = "a755cc59cda2641ea3037b4f9f7ef40471c329f55c1fa2db6fa0bb7ae6c1f7ce" 816 | dependencies = [ 817 | "graphql_client_codegen", 818 | "proc-macro2", 819 | "syn", 820 | ] 821 | 822 | [[package]] 823 | name = "h2" 824 | version = "0.3.13" 825 | source = "registry+https://github.com/rust-lang/crates.io-index" 826 | checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" 827 | dependencies = [ 828 | "bytes", 829 | "fnv", 830 | "futures-core", 831 | "futures-sink", 832 | "futures-util", 833 | "http", 834 | "indexmap", 835 | "slab", 836 | "tokio", 837 | "tokio-util", 838 | "tracing", 839 | ] 840 | 841 | [[package]] 842 | name = "hashbrown" 843 | version = "0.9.1" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" 846 | 847 | [[package]] 848 | name = "heck" 849 | version = "0.4.0" 850 | source = "registry+https://github.com/rust-lang/crates.io-index" 851 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" 852 | 853 | [[package]] 854 | name = "hermit-abi" 855 | version = "0.1.18" 856 | source = "registry+https://github.com/rust-lang/crates.io-index" 857 | checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" 858 | dependencies = [ 859 | "libc", 860 | ] 861 | 862 | [[package]] 863 | name = "home" 864 | version = "0.5.3" 865 | source = "registry+https://github.com/rust-lang/crates.io-index" 866 | checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654" 867 | dependencies = [ 868 | "winapi", 869 | ] 870 | 871 | [[package]] 872 | name = "http" 873 | version = "0.2.8" 874 | source = "registry+https://github.com/rust-lang/crates.io-index" 875 | checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" 876 | dependencies = [ 877 | "bytes", 878 | "fnv", 879 | "itoa 1.0.3", 880 | ] 881 | 882 | [[package]] 883 | name = "httparse" 884 | version = "1.7.1" 885 | source = "registry+https://github.com/rust-lang/crates.io-index" 886 | checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" 887 | 888 | [[package]] 889 | name = "httpdate" 890 | version = "1.0.2" 891 | source = "registry+https://github.com/rust-lang/crates.io-index" 892 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" 893 | 894 | [[package]] 895 | name = "humantime" 896 | version = "2.1.0" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" 899 | 900 | [[package]] 901 | name = "iana-time-zone" 902 | version = "0.1.44" 903 | source = "registry+https://github.com/rust-lang/crates.io-index" 904 | checksum = "808cf7d67cf4a22adc5be66e75ebdf769b3f2ea032041437a7061f97a63dad4b" 905 | dependencies = [ 906 | "android_system_properties", 907 | "core-foundation-sys", 908 | "js-sys", 909 | "wasm-bindgen", 910 | "winapi", 911 | ] 912 | 913 | [[package]] 914 | name = "idna" 915 | version = "0.2.2" 916 | source = "registry+https://github.com/rust-lang/crates.io-index" 917 | checksum = "89829a5d69c23d348314a7ac337fe39173b61149a9864deabd260983aed48c21" 918 | dependencies = [ 919 | "matches", 920 | "unicode-bidi", 921 | "unicode-normalization", 922 | ] 923 | 924 | [[package]] 925 | name = "indexmap" 926 | version = "1.6.2" 927 | source = "registry+https://github.com/rust-lang/crates.io-index" 928 | checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" 929 | dependencies = [ 930 | "autocfg", 931 | "hashbrown", 932 | ] 933 | 934 | [[package]] 935 | name = "itoa" 936 | version = "0.4.7" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" 939 | 940 | [[package]] 941 | name = "itoa" 942 | version = "1.0.3" 943 | source = "registry+https://github.com/rust-lang/crates.io-index" 944 | checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" 945 | 946 | [[package]] 947 | name = "itoap" 948 | version = "1.0.1" 949 | source = "registry+https://github.com/rust-lang/crates.io-index" 950 | checksum = "9028f49264629065d057f340a86acb84867925865f73bbf8d47b4d149a7e88b8" 951 | 952 | [[package]] 953 | name = "jobserver" 954 | version = "0.1.22" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd" 957 | dependencies = [ 958 | "libc", 959 | ] 960 | 961 | [[package]] 962 | name = "js-sys" 963 | version = "0.3.59" 964 | source = "registry+https://github.com/rust-lang/crates.io-index" 965 | checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" 966 | dependencies = [ 967 | "wasm-bindgen", 968 | ] 969 | 970 | [[package]] 971 | name = "language-tags" 972 | version = "0.3.2" 973 | source = "registry+https://github.com/rust-lang/crates.io-index" 974 | checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" 975 | 976 | [[package]] 977 | name = "lazy_static" 978 | version = "1.4.0" 979 | source = "registry+https://github.com/rust-lang/crates.io-index" 980 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 981 | 982 | [[package]] 983 | name = "libc" 984 | version = "0.2.131" 985 | source = "registry+https://github.com/rust-lang/crates.io-index" 986 | checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40" 987 | 988 | [[package]] 989 | name = "local-channel" 990 | version = "0.1.2" 991 | source = "registry+https://github.com/rust-lang/crates.io-index" 992 | checksum = "6246c68cf195087205a0512559c97e15eaf95198bf0e206d662092cdcb03fe9f" 993 | dependencies = [ 994 | "futures-core", 995 | "futures-sink", 996 | "futures-util", 997 | "local-waker", 998 | ] 999 | 1000 | [[package]] 1001 | name = "local-waker" 1002 | version = "0.1.1" 1003 | source = "registry+https://github.com/rust-lang/crates.io-index" 1004 | checksum = "84f9a2d3e27ce99ce2c3aad0b09b1a7b916293ea9b2bf624c13fe646fadd8da4" 1005 | 1006 | [[package]] 1007 | name = "lock_api" 1008 | version = "0.4.7" 1009 | source = "registry+https://github.com/rust-lang/crates.io-index" 1010 | checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" 1011 | dependencies = [ 1012 | "autocfg", 1013 | "scopeguard", 1014 | ] 1015 | 1016 | [[package]] 1017 | name = "log" 1018 | version = "0.4.17" 1019 | source = "registry+https://github.com/rust-lang/crates.io-index" 1020 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 1021 | dependencies = [ 1022 | "cfg-if", 1023 | ] 1024 | 1025 | [[package]] 1026 | name = "matches" 1027 | version = "0.1.8" 1028 | source = "registry+https://github.com/rust-lang/crates.io-index" 1029 | checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" 1030 | 1031 | [[package]] 1032 | name = "memchr" 1033 | version = "2.5.0" 1034 | source = "registry+https://github.com/rust-lang/crates.io-index" 1035 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 1036 | 1037 | [[package]] 1038 | name = "mime" 1039 | version = "0.3.16" 1040 | source = "registry+https://github.com/rust-lang/crates.io-index" 1041 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 1042 | 1043 | [[package]] 1044 | name = "miniz_oxide" 1045 | version = "0.4.4" 1046 | source = "registry+https://github.com/rust-lang/crates.io-index" 1047 | checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" 1048 | dependencies = [ 1049 | "adler", 1050 | "autocfg", 1051 | ] 1052 | 1053 | [[package]] 1054 | name = "mio" 1055 | version = "0.8.4" 1056 | source = "registry+https://github.com/rust-lang/crates.io-index" 1057 | checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" 1058 | dependencies = [ 1059 | "libc", 1060 | "log", 1061 | "wasi 0.11.0+wasi-snapshot-preview1", 1062 | "windows-sys", 1063 | ] 1064 | 1065 | [[package]] 1066 | name = "num-integer" 1067 | version = "0.1.44" 1068 | source = "registry+https://github.com/rust-lang/crates.io-index" 1069 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 1070 | dependencies = [ 1071 | "autocfg", 1072 | "num-traits", 1073 | ] 1074 | 1075 | [[package]] 1076 | name = "num-traits" 1077 | version = "0.2.14" 1078 | source = "registry+https://github.com/rust-lang/crates.io-index" 1079 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 1080 | dependencies = [ 1081 | "autocfg", 1082 | ] 1083 | 1084 | [[package]] 1085 | name = "num_cpus" 1086 | version = "1.13.0" 1087 | source = "registry+https://github.com/rust-lang/crates.io-index" 1088 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 1089 | dependencies = [ 1090 | "hermit-abi", 1091 | "libc", 1092 | ] 1093 | 1094 | [[package]] 1095 | name = "num_threads" 1096 | version = "0.1.6" 1097 | source = "registry+https://github.com/rust-lang/crates.io-index" 1098 | checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" 1099 | dependencies = [ 1100 | "libc", 1101 | ] 1102 | 1103 | [[package]] 1104 | name = "once_cell" 1105 | version = "1.13.0" 1106 | source = "registry+https://github.com/rust-lang/crates.io-index" 1107 | checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" 1108 | 1109 | [[package]] 1110 | name = "openssl" 1111 | version = "0.10.33" 1112 | source = "registry+https://github.com/rust-lang/crates.io-index" 1113 | checksum = "a61075b62a23fef5a29815de7536d940aa35ce96d18ce0cc5076272db678a577" 1114 | dependencies = [ 1115 | "bitflags", 1116 | "cfg-if", 1117 | "foreign-types", 1118 | "libc", 1119 | "once_cell", 1120 | "openssl-sys", 1121 | ] 1122 | 1123 | [[package]] 1124 | name = "openssl-probe" 1125 | version = "0.1.5" 1126 | source = "registry+https://github.com/rust-lang/crates.io-index" 1127 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" 1128 | 1129 | [[package]] 1130 | name = "openssl-sys" 1131 | version = "0.9.61" 1132 | source = "registry+https://github.com/rust-lang/crates.io-index" 1133 | checksum = "313752393519e876837e09e1fa183ddef0be7735868dced3196f4472d536277f" 1134 | dependencies = [ 1135 | "autocfg", 1136 | "cc", 1137 | "libc", 1138 | "pkg-config", 1139 | "vcpkg", 1140 | ] 1141 | 1142 | [[package]] 1143 | name = "parking_lot" 1144 | version = "0.12.1" 1145 | source = "registry+https://github.com/rust-lang/crates.io-index" 1146 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 1147 | dependencies = [ 1148 | "lock_api", 1149 | "parking_lot_core", 1150 | ] 1151 | 1152 | [[package]] 1153 | name = "parking_lot_core" 1154 | version = "0.9.3" 1155 | source = "registry+https://github.com/rust-lang/crates.io-index" 1156 | checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" 1157 | dependencies = [ 1158 | "cfg-if", 1159 | "libc", 1160 | "redox_syscall", 1161 | "smallvec", 1162 | "windows-sys", 1163 | ] 1164 | 1165 | [[package]] 1166 | name = "parse-zoneinfo" 1167 | version = "0.3.0" 1168 | source = "registry+https://github.com/rust-lang/crates.io-index" 1169 | checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" 1170 | dependencies = [ 1171 | "regex", 1172 | ] 1173 | 1174 | [[package]] 1175 | name = "paste" 1176 | version = "1.0.5" 1177 | source = "registry+https://github.com/rust-lang/crates.io-index" 1178 | checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" 1179 | 1180 | [[package]] 1181 | name = "percent-encoding" 1182 | version = "2.1.0" 1183 | source = "registry+https://github.com/rust-lang/crates.io-index" 1184 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 1185 | 1186 | [[package]] 1187 | name = "phf" 1188 | version = "0.11.1" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" 1191 | dependencies = [ 1192 | "phf_shared", 1193 | ] 1194 | 1195 | [[package]] 1196 | name = "phf_codegen" 1197 | version = "0.11.1" 1198 | source = "registry+https://github.com/rust-lang/crates.io-index" 1199 | checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770" 1200 | dependencies = [ 1201 | "phf_generator", 1202 | "phf_shared", 1203 | ] 1204 | 1205 | [[package]] 1206 | name = "phf_generator" 1207 | version = "0.11.1" 1208 | source = "registry+https://github.com/rust-lang/crates.io-index" 1209 | checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" 1210 | dependencies = [ 1211 | "phf_shared", 1212 | "rand", 1213 | ] 1214 | 1215 | [[package]] 1216 | name = "phf_shared" 1217 | version = "0.11.1" 1218 | source = "registry+https://github.com/rust-lang/crates.io-index" 1219 | checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" 1220 | dependencies = [ 1221 | "siphasher", 1222 | "uncased", 1223 | ] 1224 | 1225 | [[package]] 1226 | name = "pin-project-lite" 1227 | version = "0.2.9" 1228 | source = "registry+https://github.com/rust-lang/crates.io-index" 1229 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 1230 | 1231 | [[package]] 1232 | name = "pin-utils" 1233 | version = "0.1.0" 1234 | source = "registry+https://github.com/rust-lang/crates.io-index" 1235 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1236 | 1237 | [[package]] 1238 | name = "pkg-config" 1239 | version = "0.3.19" 1240 | source = "registry+https://github.com/rust-lang/crates.io-index" 1241 | checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" 1242 | 1243 | [[package]] 1244 | name = "ppv-lite86" 1245 | version = "0.2.10" 1246 | source = "registry+https://github.com/rust-lang/crates.io-index" 1247 | checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" 1248 | 1249 | [[package]] 1250 | name = "proc-macro2" 1251 | version = "1.0.36" 1252 | source = "registry+https://github.com/rust-lang/crates.io-index" 1253 | checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" 1254 | dependencies = [ 1255 | "unicode-xid", 1256 | ] 1257 | 1258 | [[package]] 1259 | name = "quote" 1260 | version = "1.0.9" 1261 | source = "registry+https://github.com/rust-lang/crates.io-index" 1262 | checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" 1263 | dependencies = [ 1264 | "proc-macro2", 1265 | ] 1266 | 1267 | [[package]] 1268 | name = "rand" 1269 | version = "0.8.4" 1270 | source = "registry+https://github.com/rust-lang/crates.io-index" 1271 | checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" 1272 | dependencies = [ 1273 | "libc", 1274 | "rand_chacha", 1275 | "rand_core", 1276 | "rand_hc", 1277 | ] 1278 | 1279 | [[package]] 1280 | name = "rand_chacha" 1281 | version = "0.3.1" 1282 | source = "registry+https://github.com/rust-lang/crates.io-index" 1283 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1284 | dependencies = [ 1285 | "ppv-lite86", 1286 | "rand_core", 1287 | ] 1288 | 1289 | [[package]] 1290 | name = "rand_core" 1291 | version = "0.6.3" 1292 | source = "registry+https://github.com/rust-lang/crates.io-index" 1293 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 1294 | dependencies = [ 1295 | "getrandom", 1296 | ] 1297 | 1298 | [[package]] 1299 | name = "rand_hc" 1300 | version = "0.3.1" 1301 | source = "registry+https://github.com/rust-lang/crates.io-index" 1302 | checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" 1303 | dependencies = [ 1304 | "rand_core", 1305 | ] 1306 | 1307 | [[package]] 1308 | name = "redox_syscall" 1309 | version = "0.2.16" 1310 | source = "registry+https://github.com/rust-lang/crates.io-index" 1311 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 1312 | dependencies = [ 1313 | "bitflags", 1314 | ] 1315 | 1316 | [[package]] 1317 | name = "regex" 1318 | version = "1.6.0" 1319 | source = "registry+https://github.com/rust-lang/crates.io-index" 1320 | checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" 1321 | dependencies = [ 1322 | "aho-corasick", 1323 | "memchr", 1324 | "regex-syntax", 1325 | ] 1326 | 1327 | [[package]] 1328 | name = "regex-syntax" 1329 | version = "0.6.27" 1330 | source = "registry+https://github.com/rust-lang/crates.io-index" 1331 | checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" 1332 | 1333 | [[package]] 1334 | name = "ryu" 1335 | version = "1.0.5" 1336 | source = "registry+https://github.com/rust-lang/crates.io-index" 1337 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 1338 | 1339 | [[package]] 1340 | name = "sailfish" 1341 | version = "0.4.0" 1342 | source = "registry+https://github.com/rust-lang/crates.io-index" 1343 | checksum = "948a7edfc2f03d7c58a097dda25ed29440a72e8528894a6e182fe9171195fed1" 1344 | dependencies = [ 1345 | "itoap", 1346 | "ryu", 1347 | "sailfish-macros", 1348 | "version_check", 1349 | ] 1350 | 1351 | [[package]] 1352 | name = "sailfish-compiler" 1353 | version = "0.4.0" 1354 | source = "registry+https://github.com/rust-lang/crates.io-index" 1355 | checksum = "3f0a01133d6ce146020e6416ac6a823f813f1cbb30ff77548b4fa20749524947" 1356 | dependencies = [ 1357 | "filetime", 1358 | "home", 1359 | "memchr", 1360 | "proc-macro2", 1361 | "quote", 1362 | "serde", 1363 | "syn", 1364 | "toml", 1365 | ] 1366 | 1367 | [[package]] 1368 | name = "sailfish-macros" 1369 | version = "0.4.0" 1370 | source = "registry+https://github.com/rust-lang/crates.io-index" 1371 | checksum = "86326c1f1dce0b316e0a47071f683b185417dc64e1a704380b5c706b09e871b1" 1372 | dependencies = [ 1373 | "proc-macro2", 1374 | "sailfish-compiler", 1375 | ] 1376 | 1377 | [[package]] 1378 | name = "scopeguard" 1379 | version = "1.1.0" 1380 | source = "registry+https://github.com/rust-lang/crates.io-index" 1381 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1382 | 1383 | [[package]] 1384 | name = "serde" 1385 | version = "1.0.143" 1386 | source = "registry+https://github.com/rust-lang/crates.io-index" 1387 | checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" 1388 | dependencies = [ 1389 | "serde_derive", 1390 | ] 1391 | 1392 | [[package]] 1393 | name = "serde_derive" 1394 | version = "1.0.143" 1395 | source = "registry+https://github.com/rust-lang/crates.io-index" 1396 | checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" 1397 | dependencies = [ 1398 | "proc-macro2", 1399 | "quote", 1400 | "syn", 1401 | ] 1402 | 1403 | [[package]] 1404 | name = "serde_json" 1405 | version = "1.0.83" 1406 | source = "registry+https://github.com/rust-lang/crates.io-index" 1407 | checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" 1408 | dependencies = [ 1409 | "itoa 1.0.3", 1410 | "ryu", 1411 | "serde", 1412 | ] 1413 | 1414 | [[package]] 1415 | name = "serde_urlencoded" 1416 | version = "0.7.0" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" 1419 | dependencies = [ 1420 | "form_urlencoded", 1421 | "itoa 0.4.7", 1422 | "ryu", 1423 | "serde", 1424 | ] 1425 | 1426 | [[package]] 1427 | name = "sha1" 1428 | version = "0.10.1" 1429 | source = "registry+https://github.com/rust-lang/crates.io-index" 1430 | checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f" 1431 | dependencies = [ 1432 | "cfg-if", 1433 | "cpufeatures", 1434 | "digest", 1435 | ] 1436 | 1437 | [[package]] 1438 | name = "signal-hook-registry" 1439 | version = "1.3.0" 1440 | source = "registry+https://github.com/rust-lang/crates.io-index" 1441 | checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6" 1442 | dependencies = [ 1443 | "libc", 1444 | ] 1445 | 1446 | [[package]] 1447 | name = "siphasher" 1448 | version = "0.3.10" 1449 | source = "registry+https://github.com/rust-lang/crates.io-index" 1450 | checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" 1451 | 1452 | [[package]] 1453 | name = "slab" 1454 | version = "0.4.2" 1455 | source = "registry+https://github.com/rust-lang/crates.io-index" 1456 | checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 1457 | 1458 | [[package]] 1459 | name = "smallvec" 1460 | version = "1.6.1" 1461 | source = "registry+https://github.com/rust-lang/crates.io-index" 1462 | checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" 1463 | 1464 | [[package]] 1465 | name = "socket2" 1466 | version = "0.4.4" 1467 | source = "registry+https://github.com/rust-lang/crates.io-index" 1468 | checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" 1469 | dependencies = [ 1470 | "libc", 1471 | "winapi", 1472 | ] 1473 | 1474 | [[package]] 1475 | name = "syn" 1476 | version = "1.0.94" 1477 | source = "registry+https://github.com/rust-lang/crates.io-index" 1478 | checksum = "a07e33e919ebcd69113d5be0e4d70c5707004ff45188910106854f38b960df4a" 1479 | dependencies = [ 1480 | "proc-macro2", 1481 | "quote", 1482 | "unicode-xid", 1483 | ] 1484 | 1485 | [[package]] 1486 | name = "termcolor" 1487 | version = "1.1.2" 1488 | source = "registry+https://github.com/rust-lang/crates.io-index" 1489 | checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" 1490 | dependencies = [ 1491 | "winapi-util", 1492 | ] 1493 | 1494 | [[package]] 1495 | name = "thiserror" 1496 | version = "1.0.32" 1497 | source = "registry+https://github.com/rust-lang/crates.io-index" 1498 | checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" 1499 | dependencies = [ 1500 | "thiserror-impl", 1501 | ] 1502 | 1503 | [[package]] 1504 | name = "thiserror-impl" 1505 | version = "1.0.32" 1506 | source = "registry+https://github.com/rust-lang/crates.io-index" 1507 | checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" 1508 | dependencies = [ 1509 | "proc-macro2", 1510 | "quote", 1511 | "syn", 1512 | ] 1513 | 1514 | [[package]] 1515 | name = "time" 1516 | version = "0.1.44" 1517 | source = "registry+https://github.com/rust-lang/crates.io-index" 1518 | checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" 1519 | dependencies = [ 1520 | "libc", 1521 | "wasi 0.10.0+wasi-snapshot-preview1", 1522 | "winapi", 1523 | ] 1524 | 1525 | [[package]] 1526 | name = "time" 1527 | version = "0.3.13" 1528 | source = "registry+https://github.com/rust-lang/crates.io-index" 1529 | checksum = "db76ff9fa4b1458b3c7f077f3ff9887394058460d21e634355b273aaf11eea45" 1530 | dependencies = [ 1531 | "itoa 1.0.3", 1532 | "libc", 1533 | "num_threads", 1534 | "time-macros", 1535 | ] 1536 | 1537 | [[package]] 1538 | name = "time-macros" 1539 | version = "0.2.4" 1540 | source = "registry+https://github.com/rust-lang/crates.io-index" 1541 | checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792" 1542 | 1543 | [[package]] 1544 | name = "tinyvec" 1545 | version = "1.2.0" 1546 | source = "registry+https://github.com/rust-lang/crates.io-index" 1547 | checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" 1548 | dependencies = [ 1549 | "tinyvec_macros", 1550 | ] 1551 | 1552 | [[package]] 1553 | name = "tinyvec_macros" 1554 | version = "0.1.0" 1555 | source = "registry+https://github.com/rust-lang/crates.io-index" 1556 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 1557 | 1558 | [[package]] 1559 | name = "tokio" 1560 | version = "1.20.1" 1561 | source = "registry+https://github.com/rust-lang/crates.io-index" 1562 | checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" 1563 | dependencies = [ 1564 | "autocfg", 1565 | "bytes", 1566 | "libc", 1567 | "memchr", 1568 | "mio", 1569 | "once_cell", 1570 | "parking_lot", 1571 | "pin-project-lite", 1572 | "signal-hook-registry", 1573 | "socket2", 1574 | "winapi", 1575 | ] 1576 | 1577 | [[package]] 1578 | name = "tokio-openssl" 1579 | version = "0.6.2" 1580 | source = "registry+https://github.com/rust-lang/crates.io-index" 1581 | checksum = "f24cddc8445a4dc8359cdd9e91c19d544fc95f672e32afe8945852b9381a09fe" 1582 | dependencies = [ 1583 | "futures", 1584 | "openssl", 1585 | "openssl-sys", 1586 | "tokio", 1587 | ] 1588 | 1589 | [[package]] 1590 | name = "tokio-util" 1591 | version = "0.7.3" 1592 | source = "registry+https://github.com/rust-lang/crates.io-index" 1593 | checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" 1594 | dependencies = [ 1595 | "bytes", 1596 | "futures-core", 1597 | "futures-sink", 1598 | "pin-project-lite", 1599 | "tokio", 1600 | "tracing", 1601 | ] 1602 | 1603 | [[package]] 1604 | name = "toml" 1605 | version = "0.5.9" 1606 | source = "registry+https://github.com/rust-lang/crates.io-index" 1607 | checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" 1608 | dependencies = [ 1609 | "serde", 1610 | ] 1611 | 1612 | [[package]] 1613 | name = "tracing" 1614 | version = "0.1.36" 1615 | source = "registry+https://github.com/rust-lang/crates.io-index" 1616 | checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" 1617 | dependencies = [ 1618 | "cfg-if", 1619 | "log", 1620 | "pin-project-lite", 1621 | "tracing-core", 1622 | ] 1623 | 1624 | [[package]] 1625 | name = "tracing-core" 1626 | version = "0.1.29" 1627 | source = "registry+https://github.com/rust-lang/crates.io-index" 1628 | checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" 1629 | dependencies = [ 1630 | "once_cell", 1631 | ] 1632 | 1633 | [[package]] 1634 | name = "typenum" 1635 | version = "1.15.0" 1636 | source = "registry+https://github.com/rust-lang/crates.io-index" 1637 | checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" 1638 | 1639 | [[package]] 1640 | name = "uncased" 1641 | version = "0.9.7" 1642 | source = "registry+https://github.com/rust-lang/crates.io-index" 1643 | checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" 1644 | dependencies = [ 1645 | "version_check", 1646 | ] 1647 | 1648 | [[package]] 1649 | name = "unicode-bidi" 1650 | version = "0.3.5" 1651 | source = "registry+https://github.com/rust-lang/crates.io-index" 1652 | checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" 1653 | dependencies = [ 1654 | "matches", 1655 | ] 1656 | 1657 | [[package]] 1658 | name = "unicode-normalization" 1659 | version = "0.1.17" 1660 | source = "registry+https://github.com/rust-lang/crates.io-index" 1661 | checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" 1662 | dependencies = [ 1663 | "tinyvec", 1664 | ] 1665 | 1666 | [[package]] 1667 | name = "unicode-xid" 1668 | version = "0.2.1" 1669 | source = "registry+https://github.com/rust-lang/crates.io-index" 1670 | checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" 1671 | 1672 | [[package]] 1673 | name = "unreachable" 1674 | version = "1.0.0" 1675 | source = "registry+https://github.com/rust-lang/crates.io-index" 1676 | checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" 1677 | dependencies = [ 1678 | "void", 1679 | ] 1680 | 1681 | [[package]] 1682 | name = "url" 1683 | version = "2.2.1" 1684 | source = "registry+https://github.com/rust-lang/crates.io-index" 1685 | checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" 1686 | dependencies = [ 1687 | "form_urlencoded", 1688 | "idna", 1689 | "matches", 1690 | "percent-encoding", 1691 | ] 1692 | 1693 | [[package]] 1694 | name = "vcpkg" 1695 | version = "0.2.11" 1696 | source = "registry+https://github.com/rust-lang/crates.io-index" 1697 | checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" 1698 | 1699 | [[package]] 1700 | name = "version_check" 1701 | version = "0.9.3" 1702 | source = "registry+https://github.com/rust-lang/crates.io-index" 1703 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 1704 | 1705 | [[package]] 1706 | name = "void" 1707 | version = "1.0.2" 1708 | source = "registry+https://github.com/rust-lang/crates.io-index" 1709 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 1710 | 1711 | [[package]] 1712 | name = "wasi" 1713 | version = "0.10.0+wasi-snapshot-preview1" 1714 | source = "registry+https://github.com/rust-lang/crates.io-index" 1715 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 1716 | 1717 | [[package]] 1718 | name = "wasi" 1719 | version = "0.11.0+wasi-snapshot-preview1" 1720 | source = "registry+https://github.com/rust-lang/crates.io-index" 1721 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1722 | 1723 | [[package]] 1724 | name = "wasm-bindgen" 1725 | version = "0.2.82" 1726 | source = "registry+https://github.com/rust-lang/crates.io-index" 1727 | checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" 1728 | dependencies = [ 1729 | "cfg-if", 1730 | "wasm-bindgen-macro", 1731 | ] 1732 | 1733 | [[package]] 1734 | name = "wasm-bindgen-backend" 1735 | version = "0.2.82" 1736 | source = "registry+https://github.com/rust-lang/crates.io-index" 1737 | checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" 1738 | dependencies = [ 1739 | "bumpalo", 1740 | "log", 1741 | "once_cell", 1742 | "proc-macro2", 1743 | "quote", 1744 | "syn", 1745 | "wasm-bindgen-shared", 1746 | ] 1747 | 1748 | [[package]] 1749 | name = "wasm-bindgen-macro" 1750 | version = "0.2.82" 1751 | source = "registry+https://github.com/rust-lang/crates.io-index" 1752 | checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" 1753 | dependencies = [ 1754 | "quote", 1755 | "wasm-bindgen-macro-support", 1756 | ] 1757 | 1758 | [[package]] 1759 | name = "wasm-bindgen-macro-support" 1760 | version = "0.2.82" 1761 | source = "registry+https://github.com/rust-lang/crates.io-index" 1762 | checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" 1763 | dependencies = [ 1764 | "proc-macro2", 1765 | "quote", 1766 | "syn", 1767 | "wasm-bindgen-backend", 1768 | "wasm-bindgen-shared", 1769 | ] 1770 | 1771 | [[package]] 1772 | name = "wasm-bindgen-shared" 1773 | version = "0.2.82" 1774 | source = "registry+https://github.com/rust-lang/crates.io-index" 1775 | checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" 1776 | 1777 | [[package]] 1778 | name = "winapi" 1779 | version = "0.3.9" 1780 | source = "registry+https://github.com/rust-lang/crates.io-index" 1781 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1782 | dependencies = [ 1783 | "winapi-i686-pc-windows-gnu", 1784 | "winapi-x86_64-pc-windows-gnu", 1785 | ] 1786 | 1787 | [[package]] 1788 | name = "winapi-i686-pc-windows-gnu" 1789 | version = "0.4.0" 1790 | source = "registry+https://github.com/rust-lang/crates.io-index" 1791 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1792 | 1793 | [[package]] 1794 | name = "winapi-util" 1795 | version = "0.1.5" 1796 | source = "registry+https://github.com/rust-lang/crates.io-index" 1797 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 1798 | dependencies = [ 1799 | "winapi", 1800 | ] 1801 | 1802 | [[package]] 1803 | name = "winapi-x86_64-pc-windows-gnu" 1804 | version = "0.4.0" 1805 | source = "registry+https://github.com/rust-lang/crates.io-index" 1806 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1807 | 1808 | [[package]] 1809 | name = "windows-sys" 1810 | version = "0.36.1" 1811 | source = "registry+https://github.com/rust-lang/crates.io-index" 1812 | checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" 1813 | dependencies = [ 1814 | "windows_aarch64_msvc", 1815 | "windows_i686_gnu", 1816 | "windows_i686_msvc", 1817 | "windows_x86_64_gnu", 1818 | "windows_x86_64_msvc", 1819 | ] 1820 | 1821 | [[package]] 1822 | name = "windows_aarch64_msvc" 1823 | version = "0.36.1" 1824 | source = "registry+https://github.com/rust-lang/crates.io-index" 1825 | checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" 1826 | 1827 | [[package]] 1828 | name = "windows_i686_gnu" 1829 | version = "0.36.1" 1830 | source = "registry+https://github.com/rust-lang/crates.io-index" 1831 | checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" 1832 | 1833 | [[package]] 1834 | name = "windows_i686_msvc" 1835 | version = "0.36.1" 1836 | source = "registry+https://github.com/rust-lang/crates.io-index" 1837 | checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" 1838 | 1839 | [[package]] 1840 | name = "windows_x86_64_gnu" 1841 | version = "0.36.1" 1842 | source = "registry+https://github.com/rust-lang/crates.io-index" 1843 | checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" 1844 | 1845 | [[package]] 1846 | name = "windows_x86_64_msvc" 1847 | version = "0.36.1" 1848 | source = "registry+https://github.com/rust-lang/crates.io-index" 1849 | checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" 1850 | 1851 | [[package]] 1852 | name = "zstd" 1853 | version = "0.11.2+zstd.1.5.2" 1854 | source = "registry+https://github.com/rust-lang/crates.io-index" 1855 | checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" 1856 | dependencies = [ 1857 | "zstd-safe", 1858 | ] 1859 | 1860 | [[package]] 1861 | name = "zstd-safe" 1862 | version = "5.0.2+zstd.1.5.2" 1863 | source = "registry+https://github.com/rust-lang/crates.io-index" 1864 | checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" 1865 | dependencies = [ 1866 | "libc", 1867 | "zstd-sys", 1868 | ] 1869 | 1870 | [[package]] 1871 | name = "zstd-sys" 1872 | version = "2.0.1+zstd.1.5.2" 1873 | source = "registry+https://github.com/rust-lang/crates.io-index" 1874 | checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" 1875 | dependencies = [ 1876 | "cc", 1877 | "libc", 1878 | ] 1879 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "annict-profile-card" 3 | # description = "" 4 | version = "0.0.1" 5 | authors = ["Nep "] 6 | edition = "2018" 7 | license = "MIT" 8 | publish = false 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | actix-web = { version = "4.1.0", features = ["openssl"] } 14 | awc = "3.0.0" 15 | actix-cors = "0.6.2" 16 | graphql_client = "0.11.0" 17 | serde = { version = "1.0.143", features = ["derive"] } 18 | serde_json = "1.0.83" 19 | sailfish = "0.4.0" 20 | futures = "0.3.21" 21 | thiserror = "1.0.32" 22 | base64 = "0.13.0" 23 | openssl-probe = "0.1.5" 24 | envy = "0.4.2" 25 | env_logger = "0.9.0" 26 | log = "0.4.17" 27 | chrono = "0.4.22" 28 | chrono-tz = "0.6.3" 29 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM lukemathwalker/cargo-chef:0.1.38-rust-1.62.0-bullseye AS chef 2 | WORKDIR /app 3 | 4 | FROM chef AS recipe 5 | COPY ./ /app/ 6 | RUN cargo chef prepare --recipe-path recipe.json 7 | 8 | FROM chef AS build 9 | # Build dependencies 10 | COPY --from=recipe /app/recipe.json ./ 11 | RUN cargo chef cook --release --recipe-path recipe.json 12 | # Build application 13 | COPY ./ /app/ 14 | RUN cargo build --release --offline --workspace --verbose \ 15 | && strip target/release/annict-profile-card 16 | 17 | FROM --platform=$TARGETPLATFORM debian:11.3-slim AS runtime 18 | COPY --from=build /app/target/release/annict-profile-card / 19 | ENTRYPOINT [ "/annict-profile-card" ] 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Nep 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # annict-profile-card 2 | 🔭 Annict の視聴状況などを SVG 画像として出力する API サーバ (WIP) 3 | 4 | Annict [GraphQL API](https://developers.annict.jp/graphql-api) を使用しています。 5 | 6 | [![GitHub release (latest by date)](https://img.shields.io/github/v/release/SlashNephy/annict-profile-card)](https://github.com/SlashNephy/annict-profile-card/releases) 7 | [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/SlashNephy/annict-profile-card/Build%20Image)](https://github.com/SlashNephy/annict-profile-card/actions/workflows/build-image.yml) 8 | [![license](https://img.shields.io/github/license/SlashNephy/annict-profile-card)](https://github.com/SlashNephy/annict-profile-card/blob/master/LICENSE) 9 | [![issues](https://img.shields.io/github/issues/SlashNephy/annict-profile-card)](https://github.com/SlashNephy/annict-profile-card/issues) 10 | [![pull requests](https://img.shields.io/github/issues-pr/SlashNephy/annict-profile-card)](https://github.com/SlashNephy/annict-profile-card/pulls) 11 | 12 | ## Docker 13 | 14 | `docker-compose.yml` 15 | 16 | ```yaml 17 | version: '3.8' 18 | 19 | services: 20 | server: 21 | container_name: annict-profile-card 22 | image: ghcr.io/slashnephy/annict-profile-card:master 23 | restart: always 24 | ports: 25 | - 8080:8080/tcp 26 | environment: 27 | ANNICT_TOKEN: xxx # https://annict.jp/settings/tokens/new で発行できます 28 | RUST_LOG: info,annict_profile_card=debug 29 | ``` 30 | 31 | ### GET /watching/{username} 32 | 33 | 今期視聴しているアニメ一覧を返します。表示される作品は Annict 上で「見てる」を設定したものが対象です。 34 | 35 | |クエリパラメータ|デフォルト値|説明| 36 | |---|:---:|---| 37 | |`season`|**現在のシーズン**|表示するシーズンを `2021-summer` という形式で指定します。`all` を指定した場合, すべてのシーズンが対象です。| 38 | |`bg_color`|`1a1b27`|背景の色を hex で指定します。| 39 | |`header_color`|`70a5fd`|ヘッダーの色を hex で指定します。| 40 | |`text_color`|`d6e3e1`|文字の色を hex で指定します。| 41 | |`icon_color`|`bf91f3`|アイコンの色を hex で指定します。| 42 | |`title_color`|`38bdae`|タイトルの色を hex で指定します。| 43 | |`limit_works`|`10`| 表示する作品数を指定します。 | 44 | |`limit_images`|`3`| 表示する作品のアイキャッチ画像の数を指定します。 | 45 | |`sort`|`satisfaction`| 作品一覧をソートする方法を指定します。
`satisfaction` の場合, 満足度 % の値で降順にソートします。
`watcher` の場合, 視聴者数の数で降順にソートします。 | 46 | |`order`|`desc`| ソートする方向を指定します。
`desc` の場合は降順で, `asc` の場合は昇順になります。| 47 | |`expose_image_url`|`false`| `true` の場合, SVG 画像内に埋め込まれる画像を外部 URL で埋め込みます。
`false` の場合, Base64 エンコードされた画像が埋め込まれます。 | 48 | 49 | ![image](https://user-images.githubusercontent.com/7302150/153339724-98ebbd59-038e-4abe-89d2-d2ebf6eabb18.png) 50 | 51 | ## Known Issue 52 | 53 | - GitHub 上に貼り付ける場合 `expose_image_url=false` が必要 54 | GitHub などのサイトに貼り付ける場合には CORS の関係で画像は Base64 エンコードして埋め込む必要があります。 55 | 56 | - GitHub 上では作品のアイキャッチ画像が表示できない 57 | GitHub では SVG 画像の長さ制限?があるようでエンコードしても表示できません。`limit_images=0` でアイキャッチ画像を無効化できます。 58 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "github>SlashNephy/.github:renovate-config" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /sailfish.toml: -------------------------------------------------------------------------------- 1 | template_dirs = ["src/api"] 2 | 3 | [optimizations] 4 | rm_whitespace = true 5 | -------------------------------------------------------------------------------- /src/api/common.rs: -------------------------------------------------------------------------------- 1 | use awc::middleware::Redirect; 2 | use awc::Client as HttpClient; 3 | use chrono::{Datelike, Local}; 4 | use graphql_client::{GraphQLQuery, Response}; 5 | use log::*; 6 | use std::time::Duration; 7 | 8 | use crate::api::error::ApiError; 9 | use crate::config; 10 | use log::Level::Trace; 11 | 12 | const ANNICT_GRAPHQL_ENDPOINT: &str = "https://api.annict.com/graphql"; 13 | const USER_AGENT: &str = "annict-profile-card (+https://github.com/SlashNephy/annict-profile-card)"; 14 | 15 | pub async fn perform_query( 16 | variables: Q::Variables, 17 | ) -> Result { 18 | let request_body = Q::build_query(variables); 19 | 20 | if log_enabled!(Trace) { 21 | trace!( 22 | "Request: {:#?}", 23 | serde_json::to_value(&request_body).unwrap() 24 | ); 25 | } 26 | 27 | let config = config::load(); 28 | let client = HttpClient::default(); 29 | 30 | let mut response_body = client 31 | .post(ANNICT_GRAPHQL_ENDPOINT) 32 | .bearer_auth(config.annict_token) 33 | .append_header(("User-Agent", USER_AGENT)) 34 | .timeout(Duration::from_secs(15)) 35 | .send_json(&request_body) 36 | .await 37 | .map_err(|e| ApiError::AnnictGraphQLRequestError(e))?; 38 | 39 | if log_enabled!(Trace) { 40 | trace!("Response Header: {:#?}", &response_body); 41 | } 42 | 43 | let response: Response = response_body 44 | .json() 45 | .await 46 | .map_err(|e| ApiError::AnnictGraphQLResponseParseError(e))?; 47 | 48 | if let Some(errors) = response.errors { 49 | let text = errors 50 | .into_iter() 51 | .map(|x| x.to_string()) 52 | .collect::>() 53 | .join("\n"); 54 | 55 | return Err(ApiError::AnnictGraphQLResponseError(text)); 56 | } 57 | 58 | Ok(response.data.unwrap()) 59 | } 60 | 61 | pub async fn encode_image(url: String) -> Result { 62 | let client = HttpClient::builder().wrap(Redirect::new()).finish(); 63 | let image = client 64 | .get(url) 65 | .append_header(("User-Agent", USER_AGENT)) 66 | .timeout(Duration::from_secs(15)) 67 | .send() 68 | .await 69 | .map_err(|e| ApiError::ImageRequestError(e))? 70 | .body() 71 | .limit(3_145_728) // 3 MB 72 | .await 73 | .map_err(|e| ApiError::ImageReadBodyError(e))?; 74 | 75 | let data = base64::encode(image); 76 | Ok(format!("data:image/png;base64,{}", data)) 77 | } 78 | 79 | pub fn get_current_season() -> String { 80 | let now = Local::today(); 81 | let year = now.year(); 82 | let season = match now.month() { 83 | 1..=3 => "winter", 84 | 4..=6 => "spring", 85 | 7..=9 => "summer", 86 | 10..=12 => "autumn", 87 | _ => panic!("Invalid month"), 88 | }; 89 | 90 | format!("{}-{}", year, season) 91 | } 92 | -------------------------------------------------------------------------------- /src/api/error.rs: -------------------------------------------------------------------------------- 1 | use awc::error::{JsonPayloadError, PayloadError, SendRequestError}; 2 | use thiserror::Error; 3 | 4 | #[derive(Debug, Error)] 5 | pub enum ApiError { 6 | #[error("failed to request GraphQL query: {0}")] 7 | AnnictGraphQLRequestError(SendRequestError), 8 | #[error("failed to parse GraphQL response: {0}")] 9 | AnnictGraphQLResponseParseError(JsonPayloadError), 10 | #[error("an error returned from GraphQL server: {0}")] 11 | AnnictGraphQLResponseError(String), 12 | 13 | #[error("failed to get image: {0}")] 14 | ImageRequestError(SendRequestError), 15 | #[error("failed to read image body: {0}")] 16 | ImageReadBodyError(PayloadError), 17 | } 18 | -------------------------------------------------------------------------------- /src/api/index.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{HttpResponse, Responder}; 2 | 3 | #[actix_web::get("/")] 4 | pub async fn get_index() -> impl Responder { 5 | HttpResponse::PermanentRedirect() 6 | .append_header(( 7 | "Location", 8 | "https://github.com/SlashNephy/annict-profile-card", 9 | )) 10 | .finish() 11 | } 12 | -------------------------------------------------------------------------------- /src/api/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod common; 2 | pub mod error; 3 | pub mod index; 4 | pub mod watching; 5 | -------------------------------------------------------------------------------- /src/api/schema.graphql: -------------------------------------------------------------------------------- 1 | schema { 2 | query: Query 3 | mutation: Mutation 4 | } 5 | 6 | "Directs the executor to include this field or fragment only when the `if` argument is true" 7 | directive @include( 8 | "Included when true." 9 | if: Boolean! 10 | ) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT 11 | "Directs the executor to skip this field or fragment when the `if`'argument is true." 12 | directive @skip( 13 | "Skipped when true." 14 | if: Boolean! 15 | ) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT 16 | "Marks the field or enum value as deprecated" 17 | directive @deprecated( 18 | "The reason for the deprecation" 19 | reason: String = "No longer supported" 20 | ) on FIELD_DEFINITION | ENUM_VALUE 21 | "Exposes a URL that specifies the behaviour of this scalar." 22 | directive @specifiedBy( 23 | "The URL that specifies the behaviour of this scalar." 24 | url: String! 25 | ) on SCALAR 26 | "An object with an ID." 27 | interface Node { 28 | "ID of the object." 29 | id: ID! 30 | } 31 | union ActivityItem = MultipleRecord | Record | Review | Status 32 | union StaffResourceItem = Organization | Person 33 | type Activity implements Node { 34 | annictId: Int! 35 | "ID of the object." 36 | id: ID! 37 | user: User! 38 | } 39 | "The connection type for Activity." 40 | type ActivityConnection { 41 | "A list of edges." 42 | edges: [ActivityEdge] 43 | "A list of nodes." 44 | nodes: [Activity] 45 | "Information to aid in pagination." 46 | pageInfo: PageInfo! 47 | } 48 | "An edge in a connection." 49 | type ActivityEdge { 50 | action: ActivityAction! 51 | annictId: Int! 52 | "A cursor for use in pagination." 53 | cursor: String! 54 | node: ActivityItem 55 | user: User! 56 | } 57 | type Cast implements Node { 58 | annictId: Int! 59 | character: Character! 60 | id: ID! 61 | name: String! 62 | nameEn: String! 63 | person: Person! 64 | sortNumber: Int! 65 | work: Work! 66 | } 67 | "The connection type for Cast." 68 | type CastConnection { 69 | "A list of edges." 70 | edges: [CastEdge] 71 | "A list of nodes." 72 | nodes: [Cast] 73 | "Information to aid in pagination." 74 | pageInfo: PageInfo! 75 | } 76 | "An edge in a connection." 77 | type CastEdge { 78 | "A cursor for use in pagination." 79 | cursor: String! 80 | "The item at the end of the edge." 81 | node: Cast 82 | } 83 | type Channel implements Node { 84 | annictId: Int! 85 | channelGroup: ChannelGroup! 86 | id: ID! 87 | name: String! 88 | programs( 89 | "Returns the elements in the list that come after the specified cursor." 90 | after: String, 91 | "Returns the elements in the list that come before the specified cursor." 92 | before: String, 93 | "Returns the first _n_ elements from the list." 94 | first: Int, 95 | "Returns the last _n_ elements from the list." 96 | last: Int 97 | ): ProgramConnection 98 | published: Boolean! 99 | scChid: Int! 100 | } 101 | "The connection type for Channel." 102 | type ChannelConnection { 103 | "A list of edges." 104 | edges: [ChannelEdge] 105 | "A list of nodes." 106 | nodes: [Channel] 107 | "Information to aid in pagination." 108 | pageInfo: PageInfo! 109 | } 110 | "An edge in a connection." 111 | type ChannelEdge { 112 | "A cursor for use in pagination." 113 | cursor: String! 114 | "The item at the end of the edge." 115 | node: Channel 116 | } 117 | type ChannelGroup implements Node { 118 | annictId: Int! 119 | channels( 120 | "Returns the elements in the list that come after the specified cursor." 121 | after: String, 122 | "Returns the elements in the list that come before the specified cursor." 123 | before: String, 124 | "Returns the first _n_ elements from the list." 125 | first: Int, 126 | "Returns the last _n_ elements from the list." 127 | last: Int 128 | ): ChannelConnection 129 | id: ID! 130 | name: String! 131 | sortNumber: Int! 132 | } 133 | type Character implements Node { 134 | age: String! 135 | ageEn: String! 136 | annictId: Int! 137 | birthday: String! 138 | birthdayEn: String! 139 | bloodType: String! 140 | bloodTypeEn: String! 141 | description: String! 142 | descriptionEn: String! 143 | descriptionSource: String! 144 | descriptionSourceEn: String! 145 | favoriteCharactersCount: Int! 146 | height: String! 147 | heightEn: String! 148 | id: ID! 149 | name: String! 150 | nameEn: String! 151 | nameKana: String! 152 | nationality: String! 153 | nationalityEn: String! 154 | nickname: String! 155 | nicknameEn: String! 156 | occupation: String! 157 | occupationEn: String! 158 | series: Series! 159 | weight: String! 160 | weightEn: String! 161 | } 162 | "The connection type for Character." 163 | type CharacterConnection { 164 | "A list of edges." 165 | edges: [CharacterEdge] 166 | "A list of nodes." 167 | nodes: [Character] 168 | "Information to aid in pagination." 169 | pageInfo: PageInfo! 170 | } 171 | "An edge in a connection." 172 | type CharacterEdge { 173 | "A cursor for use in pagination." 174 | cursor: String! 175 | "The item at the end of the edge." 176 | node: Character 177 | } 178 | "Autogenerated return type of CreateRecord" 179 | type CreateRecordPayload { 180 | "A unique identifier for the client performing the mutation." 181 | clientMutationId: String 182 | record: Record 183 | } 184 | "Autogenerated return type of CreateReview" 185 | type CreateReviewPayload { 186 | "A unique identifier for the client performing the mutation." 187 | clientMutationId: String 188 | review: Review 189 | } 190 | "Autogenerated return type of DeleteRecord" 191 | type DeleteRecordPayload { 192 | "A unique identifier for the client performing the mutation." 193 | clientMutationId: String 194 | episode: Episode 195 | } 196 | "Autogenerated return type of DeleteReview" 197 | type DeleteReviewPayload { 198 | "A unique identifier for the client performing the mutation." 199 | clientMutationId: String 200 | work: Work 201 | } 202 | "An episode of a work" 203 | type Episode implements Node { 204 | annictId: Int! 205 | id: ID! 206 | nextEpisode: Episode 207 | number: Int 208 | numberText: String 209 | prevEpisode: Episode 210 | recordCommentsCount: Int! 211 | records( 212 | "Returns the elements in the list that come after the specified cursor." 213 | after: String, 214 | "Returns the elements in the list that come before the specified cursor." 215 | before: String, 216 | "Returns the first _n_ elements from the list." 217 | first: Int, 218 | hasComment: Boolean, 219 | "Returns the last _n_ elements from the list." 220 | last: Int, 221 | orderBy: RecordOrder 222 | ): RecordConnection 223 | recordsCount: Int! 224 | satisfactionRate: Float 225 | sortNumber: Int! 226 | title: String 227 | viewerDidTrack: Boolean! 228 | viewerRecordsCount: Int! 229 | work: Work! 230 | } 231 | "The connection type for Episode." 232 | type EpisodeConnection { 233 | "A list of edges." 234 | edges: [EpisodeEdge] 235 | "A list of nodes." 236 | nodes: [Episode] 237 | "Information to aid in pagination." 238 | pageInfo: PageInfo! 239 | } 240 | "An edge in a connection." 241 | type EpisodeEdge { 242 | "A cursor for use in pagination." 243 | cursor: String! 244 | "The item at the end of the edge." 245 | node: Episode 246 | } 247 | type MultipleRecord implements Node { 248 | annictId: Int! 249 | createdAt: DateTime! 250 | id: ID! 251 | records( 252 | "Returns the elements in the list that come after the specified cursor." 253 | after: String, 254 | "Returns the elements in the list that come before the specified cursor." 255 | before: String, 256 | "Returns the first _n_ elements from the list." 257 | first: Int, 258 | "Returns the last _n_ elements from the list." 259 | last: Int 260 | ): RecordConnection 261 | user: User! 262 | work: Work! 263 | } 264 | type Mutation { 265 | createRecord(input: CreateRecordInput!): CreateRecordPayload 266 | createReview(input: CreateReviewInput!): CreateReviewPayload 267 | deleteRecord(input: DeleteRecordInput!): DeleteRecordPayload 268 | deleteReview(input: DeleteReviewInput!): DeleteReviewPayload 269 | updateRecord(input: UpdateRecordInput!): UpdateRecordPayload 270 | updateReview(input: UpdateReviewInput!): UpdateReviewPayload 271 | updateStatus(input: UpdateStatusInput!): UpdateStatusPayload 272 | } 273 | type Organization implements Node { 274 | annictId: Int! 275 | favoriteOrganizationsCount: Int! 276 | id: ID! 277 | name: String! 278 | nameEn: String! 279 | nameKana: String! 280 | staffsCount: Int! 281 | twitterUsername: String! 282 | twitterUsernameEn: String! 283 | url: String! 284 | urlEn: String! 285 | wikipediaUrl: String! 286 | wikipediaUrlEn: String! 287 | } 288 | "The connection type for Organization." 289 | type OrganizationConnection { 290 | "A list of edges." 291 | edges: [OrganizationEdge] 292 | "A list of nodes." 293 | nodes: [Organization] 294 | "Information to aid in pagination." 295 | pageInfo: PageInfo! 296 | } 297 | "An edge in a connection." 298 | type OrganizationEdge { 299 | "A cursor for use in pagination." 300 | cursor: String! 301 | "The item at the end of the edge." 302 | node: Organization 303 | } 304 | "Information about pagination in a connection." 305 | type PageInfo { 306 | "When paginating forwards, the cursor to continue." 307 | endCursor: String 308 | "When paginating forwards, are there more items?" 309 | hasNextPage: Boolean! 310 | "When paginating backwards, are there more items?" 311 | hasPreviousPage: Boolean! 312 | "When paginating backwards, the cursor to continue." 313 | startCursor: String 314 | } 315 | type Person implements Node { 316 | annictId: Int! 317 | birthday: String! 318 | bloodType: String! 319 | castsCount: Int! 320 | favoritePeopleCount: Int! 321 | genderText: String! 322 | height: String! 323 | id: ID! 324 | name: String! 325 | nameEn: String! 326 | nameKana: String! 327 | nickname: String! 328 | nicknameEn: String! 329 | prefecture: Prefecture! 330 | staffsCount: Int! 331 | twitterUsername: String! 332 | twitterUsernameEn: String! 333 | url: String! 334 | urlEn: String! 335 | wikipediaUrl: String! 336 | wikipediaUrlEn: String! 337 | } 338 | "The connection type for Person." 339 | type PersonConnection { 340 | "A list of edges." 341 | edges: [PersonEdge] 342 | "A list of nodes." 343 | nodes: [Person] 344 | "Information to aid in pagination." 345 | pageInfo: PageInfo! 346 | } 347 | "An edge in a connection." 348 | type PersonEdge { 349 | "A cursor for use in pagination." 350 | cursor: String! 351 | "The item at the end of the edge." 352 | node: Person 353 | } 354 | type Prefecture implements Node { 355 | annictId: Int! 356 | id: ID! 357 | name: String! 358 | } 359 | type Program implements Node { 360 | annictId: Int! 361 | channel: Channel! 362 | episode: Episode! 363 | id: ID! 364 | rebroadcast: Boolean! 365 | scPid: Int 366 | startedAt: DateTime! 367 | state: ProgramState! 368 | work: Work! 369 | } 370 | "The connection type for Program." 371 | type ProgramConnection { 372 | "A list of edges." 373 | edges: [ProgramEdge] 374 | "A list of nodes." 375 | nodes: [Program] 376 | "Information to aid in pagination." 377 | pageInfo: PageInfo! 378 | } 379 | "An edge in a connection." 380 | type ProgramEdge { 381 | "A cursor for use in pagination." 382 | cursor: String! 383 | "The item at the end of the edge." 384 | node: Program 385 | } 386 | type Query { 387 | "Fetches an object given its ID." 388 | node( 389 | "ID of the object." 390 | id: ID! 391 | ): Node 392 | "Fetches a list of objects given a list of IDs." 393 | nodes( 394 | "IDs of the objects." 395 | ids: [ID!]! 396 | ): [Node]! 397 | searchCharacters( 398 | "Returns the elements in the list that come after the specified cursor." 399 | after: String, 400 | annictIds: [Int!], 401 | "Returns the elements in the list that come before the specified cursor." 402 | before: String, 403 | "Returns the first _n_ elements from the list." 404 | first: Int, 405 | "Returns the last _n_ elements from the list." 406 | last: Int, 407 | names: [String!], 408 | orderBy: CharacterOrder 409 | ): CharacterConnection 410 | searchEpisodes( 411 | "Returns the elements in the list that come after the specified cursor." 412 | after: String, 413 | annictIds: [Int!], 414 | "Returns the elements in the list that come before the specified cursor." 415 | before: String, 416 | "Returns the first _n_ elements from the list." 417 | first: Int, 418 | "Returns the last _n_ elements from the list." 419 | last: Int, 420 | orderBy: EpisodeOrder 421 | ): EpisodeConnection 422 | searchOrganizations( 423 | "Returns the elements in the list that come after the specified cursor." 424 | after: String, 425 | annictIds: [Int!], 426 | "Returns the elements in the list that come before the specified cursor." 427 | before: String, 428 | "Returns the first _n_ elements from the list." 429 | first: Int, 430 | "Returns the last _n_ elements from the list." 431 | last: Int, 432 | names: [String!], 433 | orderBy: OrganizationOrder 434 | ): OrganizationConnection 435 | searchPeople( 436 | "Returns the elements in the list that come after the specified cursor." 437 | after: String, 438 | annictIds: [Int!], 439 | "Returns the elements in the list that come before the specified cursor." 440 | before: String, 441 | "Returns the first _n_ elements from the list." 442 | first: Int, 443 | "Returns the last _n_ elements from the list." 444 | last: Int, 445 | names: [String!], 446 | orderBy: PersonOrder 447 | ): PersonConnection 448 | searchWorks( 449 | "Returns the elements in the list that come after the specified cursor." 450 | after: String, 451 | annictIds: [Int!], 452 | "Returns the elements in the list that come before the specified cursor." 453 | before: String, 454 | "Returns the first _n_ elements from the list." 455 | first: Int, 456 | "Returns the last _n_ elements from the list." 457 | last: Int, 458 | orderBy: WorkOrder, 459 | seasons: [String!], 460 | titles: [String!] 461 | ): WorkConnection 462 | user(username: String!): User 463 | viewer: User 464 | } 465 | type Record implements Node { 466 | annictId: Int! 467 | comment: String 468 | commentsCount: Int! 469 | createdAt: DateTime! 470 | episode: Episode! 471 | facebookClickCount: Int! 472 | id: ID! 473 | likesCount: Int! 474 | modified: Boolean! 475 | rating: Float 476 | ratingState: RatingState 477 | twitterClickCount: Int! 478 | updatedAt: DateTime! 479 | user: User! 480 | work: Work! 481 | } 482 | "The connection type for Record." 483 | type RecordConnection { 484 | "A list of edges." 485 | edges: [RecordEdge] 486 | "A list of nodes." 487 | nodes: [Record] 488 | "Information to aid in pagination." 489 | pageInfo: PageInfo! 490 | } 491 | "An edge in a connection." 492 | type RecordEdge { 493 | "A cursor for use in pagination." 494 | cursor: String! 495 | "The item at the end of the edge." 496 | node: Record 497 | } 498 | type Review implements Node { 499 | annictId: Int! 500 | body: String! 501 | createdAt: DateTime! 502 | id: ID! 503 | impressionsCount: Int! 504 | likesCount: Int! 505 | modifiedAt: DateTime 506 | ratingAnimationState: RatingState 507 | ratingCharacterState: RatingState 508 | ratingMusicState: RatingState 509 | ratingOverallState: RatingState 510 | ratingStoryState: RatingState 511 | title: String 512 | updatedAt: DateTime! 513 | user: User! 514 | work: Work! 515 | } 516 | "The connection type for Review." 517 | type ReviewConnection { 518 | "A list of edges." 519 | edges: [ReviewEdge] 520 | "A list of nodes." 521 | nodes: [Review] 522 | "Information to aid in pagination." 523 | pageInfo: PageInfo! 524 | } 525 | "An edge in a connection." 526 | type ReviewEdge { 527 | "A cursor for use in pagination." 528 | cursor: String! 529 | "The item at the end of the edge." 530 | node: Review 531 | } 532 | type Series implements Node { 533 | annictId: Int! 534 | id: ID! 535 | name: String! 536 | nameEn: String! 537 | nameRo: String! 538 | works( 539 | "Returns the elements in the list that come after the specified cursor." 540 | after: String, 541 | "Returns the elements in the list that come before the specified cursor." 542 | before: String, 543 | "Returns the first _n_ elements from the list." 544 | first: Int, 545 | "Returns the last _n_ elements from the list." 546 | last: Int, 547 | orderBy: SeriesWorkOrder 548 | ): SeriesWorkConnection 549 | } 550 | "The connection type for Series." 551 | type SeriesConnection { 552 | "A list of edges." 553 | edges: [SeriesEdge] 554 | "A list of nodes." 555 | nodes: [Series] 556 | "Information to aid in pagination." 557 | pageInfo: PageInfo! 558 | } 559 | "An edge in a connection." 560 | type SeriesEdge { 561 | "A cursor for use in pagination." 562 | cursor: String! 563 | "The item at the end of the edge." 564 | node: Series 565 | } 566 | "The connection type for Work." 567 | type SeriesWorkConnection { 568 | "A list of edges." 569 | edges: [SeriesWorkEdge] 570 | "A list of nodes." 571 | nodes: [Work] 572 | "Information to aid in pagination." 573 | pageInfo: PageInfo! 574 | } 575 | "An edge in a connection." 576 | type SeriesWorkEdge { 577 | "A cursor for use in pagination." 578 | cursor: String! 579 | node: Work! 580 | summary: String 581 | summaryEn: String 582 | } 583 | type Staff implements Node { 584 | annictId: Int! 585 | id: ID! 586 | name: String! 587 | nameEn: String! 588 | resource: StaffResourceItem! 589 | roleOther: String! 590 | roleOtherEn: String! 591 | roleText: String! 592 | sortNumber: Int! 593 | work: Work! 594 | } 595 | "The connection type for Staff." 596 | type StaffConnection { 597 | "A list of edges." 598 | edges: [StaffEdge] 599 | "A list of nodes." 600 | nodes: [Staff] 601 | "Information to aid in pagination." 602 | pageInfo: PageInfo! 603 | } 604 | "An edge in a connection." 605 | type StaffEdge { 606 | "A cursor for use in pagination." 607 | cursor: String! 608 | "The item at the end of the edge." 609 | node: Staff 610 | } 611 | type Status implements Node { 612 | annictId: Int! 613 | createdAt: DateTime! 614 | id: ID! 615 | likesCount: Int! 616 | state: StatusState! 617 | user: User! 618 | work: Work! 619 | } 620 | "Autogenerated return type of UpdateRecord" 621 | type UpdateRecordPayload { 622 | "A unique identifier for the client performing the mutation." 623 | clientMutationId: String 624 | record: Record 625 | } 626 | "Autogenerated return type of UpdateReview" 627 | type UpdateReviewPayload { 628 | "A unique identifier for the client performing the mutation." 629 | clientMutationId: String 630 | review: Review 631 | } 632 | "Autogenerated return type of UpdateStatus" 633 | type UpdateStatusPayload { 634 | "A unique identifier for the client performing the mutation." 635 | clientMutationId: String 636 | work: Work 637 | } 638 | type User implements Node { 639 | activities( 640 | "Returns the elements in the list that come after the specified cursor." 641 | after: String, 642 | "Returns the elements in the list that come before the specified cursor." 643 | before: String, 644 | "Returns the first _n_ elements from the list." 645 | first: Int, 646 | "Returns the last _n_ elements from the list." 647 | last: Int, 648 | orderBy: ActivityOrder 649 | ): ActivityConnection 650 | annictId: Int! 651 | avatarUrl: String 652 | backgroundImageUrl: String 653 | createdAt: DateTime! 654 | description: String! 655 | email: String 656 | followers( 657 | "Returns the elements in the list that come after the specified cursor." 658 | after: String, 659 | "Returns the elements in the list that come before the specified cursor." 660 | before: String, 661 | "Returns the first _n_ elements from the list." 662 | first: Int, 663 | "Returns the last _n_ elements from the list." 664 | last: Int 665 | ): UserConnection 666 | followersCount: Int! 667 | following( 668 | "Returns the elements in the list that come after the specified cursor." 669 | after: String, 670 | "Returns the elements in the list that come before the specified cursor." 671 | before: String, 672 | "Returns the first _n_ elements from the list." 673 | first: Int, 674 | "Returns the last _n_ elements from the list." 675 | last: Int 676 | ): UserConnection 677 | followingActivities( 678 | "Returns the elements in the list that come after the specified cursor." 679 | after: String, 680 | "Returns the elements in the list that come before the specified cursor." 681 | before: String, 682 | "Returns the first _n_ elements from the list." 683 | first: Int, 684 | "Returns the last _n_ elements from the list." 685 | last: Int, 686 | orderBy: ActivityOrder 687 | ): ActivityConnection 688 | followingsCount: Int! 689 | id: ID! 690 | name: String! 691 | notificationsCount: Int 692 | onHoldCount: Int! 693 | programs( 694 | "Returns the elements in the list that come after the specified cursor." 695 | after: String, 696 | "Returns the elements in the list that come before the specified cursor." 697 | before: String, 698 | "Returns the first _n_ elements from the list." 699 | first: Int, 700 | "Returns the last _n_ elements from the list." 701 | last: Int, 702 | orderBy: ProgramOrder, 703 | unwatched: Boolean 704 | ): ProgramConnection 705 | records( 706 | "Returns the elements in the list that come after the specified cursor." 707 | after: String, 708 | "Returns the elements in the list that come before the specified cursor." 709 | before: String, 710 | "Returns the first _n_ elements from the list." 711 | first: Int, 712 | hasComment: Boolean, 713 | "Returns the last _n_ elements from the list." 714 | last: Int, 715 | orderBy: RecordOrder 716 | ): RecordConnection 717 | recordsCount: Int! 718 | stopWatchingCount: Int! 719 | url: String 720 | username: String! 721 | viewerCanFollow: Boolean! 722 | viewerIsFollowing: Boolean! 723 | wannaWatchCount: Int! 724 | watchedCount: Int! 725 | watchingCount: Int! 726 | works( 727 | "Returns the elements in the list that come after the specified cursor." 728 | after: String, 729 | annictIds: [Int!], 730 | "Returns the elements in the list that come before the specified cursor." 731 | before: String, 732 | "Returns the first _n_ elements from the list." 733 | first: Int, 734 | "Returns the last _n_ elements from the list." 735 | last: Int, 736 | orderBy: WorkOrder, 737 | seasons: [String!], 738 | state: StatusState, 739 | titles: [String!] 740 | ): WorkConnection 741 | } 742 | "The connection type for User." 743 | type UserConnection { 744 | "A list of edges." 745 | edges: [UserEdge] 746 | "A list of nodes." 747 | nodes: [User] 748 | "Information to aid in pagination." 749 | pageInfo: PageInfo! 750 | } 751 | "An edge in a connection." 752 | type UserEdge { 753 | "A cursor for use in pagination." 754 | cursor: String! 755 | "The item at the end of the edge." 756 | node: User 757 | } 758 | "An anime title" 759 | type Work implements Node { 760 | annictId: Int! 761 | casts( 762 | "Returns the elements in the list that come after the specified cursor." 763 | after: String, 764 | "Returns the elements in the list that come before the specified cursor." 765 | before: String, 766 | "Returns the first _n_ elements from the list." 767 | first: Int, 768 | "Returns the last _n_ elements from the list." 769 | last: Int, 770 | orderBy: CastOrder 771 | ): CastConnection 772 | episodes( 773 | "Returns the elements in the list that come after the specified cursor." 774 | after: String, 775 | "Returns the elements in the list that come before the specified cursor." 776 | before: String, 777 | "Returns the first _n_ elements from the list." 778 | first: Int, 779 | "Returns the last _n_ elements from the list." 780 | last: Int, 781 | orderBy: EpisodeOrder 782 | ): EpisodeConnection 783 | episodesCount: Int! 784 | id: ID! 785 | image: WorkImage 786 | malAnimeId: String 787 | media: Media! 788 | noEpisodes: Boolean! 789 | officialSiteUrl: String 790 | officialSiteUrlEn: String 791 | programs( 792 | "Returns the elements in the list that come after the specified cursor." 793 | after: String, 794 | "Returns the elements in the list that come before the specified cursor." 795 | before: String, 796 | "Returns the first _n_ elements from the list." 797 | first: Int, 798 | "Returns the last _n_ elements from the list." 799 | last: Int, 800 | orderBy: ProgramOrder 801 | ): ProgramConnection 802 | reviews( 803 | "Returns the elements in the list that come after the specified cursor." 804 | after: String, 805 | "Returns the elements in the list that come before the specified cursor." 806 | before: String, 807 | "Returns the first _n_ elements from the list." 808 | first: Int, 809 | hasBody: Boolean, 810 | "Returns the last _n_ elements from the list." 811 | last: Int, 812 | orderBy: ReviewOrder 813 | ): ReviewConnection 814 | reviewsCount: Int! 815 | satisfactionRate: Float 816 | seasonName: SeasonName 817 | seasonYear: Int 818 | seriesList( 819 | "Returns the elements in the list that come after the specified cursor." 820 | after: String, 821 | "Returns the elements in the list that come before the specified cursor." 822 | before: String, 823 | "Returns the first _n_ elements from the list." 824 | first: Int, 825 | "Returns the last _n_ elements from the list." 826 | last: Int 827 | ): SeriesConnection 828 | staffs( 829 | "Returns the elements in the list that come after the specified cursor." 830 | after: String, 831 | "Returns the elements in the list that come before the specified cursor." 832 | before: String, 833 | "Returns the first _n_ elements from the list." 834 | first: Int, 835 | "Returns the last _n_ elements from the list." 836 | last: Int, 837 | orderBy: StaffOrder 838 | ): StaffConnection 839 | syobocalTid: Int 840 | title: String! 841 | titleEn: String 842 | titleKana: String 843 | titleRo: String 844 | twitterHashtag: String 845 | twitterUsername: String 846 | viewerStatusState: StatusState 847 | watchersCount: Int! 848 | wikipediaUrl: String 849 | wikipediaUrlEn: String 850 | } 851 | "The connection type for Work." 852 | type WorkConnection { 853 | "A list of edges." 854 | edges: [WorkEdge] 855 | "A list of nodes." 856 | nodes: [Work] 857 | "Information to aid in pagination." 858 | pageInfo: PageInfo! 859 | } 860 | "An edge in a connection." 861 | type WorkEdge { 862 | "A cursor for use in pagination." 863 | cursor: String! 864 | "The item at the end of the edge." 865 | node: Work 866 | } 867 | type WorkImage implements Node { 868 | annictId: Int 869 | facebookOgImageUrl: String 870 | id: ID! 871 | internalUrl(size: String!): String 872 | recommendedImageUrl: String 873 | twitterAvatarUrl: String 874 | twitterBiggerAvatarUrl: String 875 | twitterMiniAvatarUrl: String 876 | twitterNormalAvatarUrl: String 877 | work: Work 878 | } 879 | enum ActivityAction { 880 | CREATE 881 | } 882 | enum ActivityOrderField { 883 | CREATED_AT 884 | } 885 | enum CastOrderField { 886 | CREATED_AT 887 | SORT_NUMBER 888 | } 889 | enum CharacterOrderField { 890 | CREATED_AT 891 | FAVORITE_CHARACTERS_COUNT 892 | } 893 | enum EpisodeOrderField { 894 | CREATED_AT 895 | SORT_NUMBER 896 | } 897 | "Media of anime" 898 | enum Media { 899 | MOVIE 900 | OTHER 901 | OVA 902 | TV 903 | WEB 904 | } 905 | enum OrderDirection { 906 | ASC 907 | DESC 908 | } 909 | enum OrganizationOrderField { 910 | CREATED_AT 911 | FAVORITE_ORGANIZATIONS_COUNT 912 | } 913 | enum PersonOrderField { 914 | CREATED_AT 915 | FAVORITE_PEOPLE_COUNT 916 | } 917 | enum ProgramOrderField { 918 | STARTED_AT 919 | } 920 | enum ProgramState { 921 | HIDDEN 922 | PUBLISHED 923 | } 924 | enum RatingState { 925 | AVERAGE 926 | BAD 927 | GOOD 928 | GREAT 929 | } 930 | enum RecordOrderField { 931 | CREATED_AT 932 | LIKES_COUNT 933 | } 934 | enum ReviewOrderField { 935 | CREATED_AT 936 | LIKES_COUNT 937 | } 938 | "Season name" 939 | enum SeasonName { 940 | AUTUMN 941 | SPRING 942 | SUMMER 943 | WINTER 944 | } 945 | enum SeriesWorkOrderField { 946 | SEASON 947 | } 948 | enum StaffOrderField { 949 | CREATED_AT 950 | SORT_NUMBER 951 | } 952 | enum StatusState { 953 | NO_STATE 954 | ON_HOLD 955 | STOP_WATCHING 956 | WANNA_WATCH 957 | WATCHED 958 | WATCHING 959 | } 960 | enum WorkOrderField { 961 | CREATED_AT 962 | SEASON 963 | WATCHERS_COUNT 964 | } 965 | "DateTime" 966 | scalar DateTime 967 | input ActivityOrder { 968 | direction: OrderDirection! 969 | field: ActivityOrderField! 970 | } 971 | input CastOrder { 972 | direction: OrderDirection! 973 | field: CastOrderField! 974 | } 975 | input CharacterOrder { 976 | direction: OrderDirection! 977 | field: CharacterOrderField! 978 | } 979 | "Autogenerated input type of CreateRecord" 980 | input CreateRecordInput { 981 | "A unique identifier for the client performing the mutation." 982 | clientMutationId: String 983 | comment: String 984 | episodeId: ID! 985 | ratingState: RatingState 986 | shareFacebook: Boolean 987 | shareTwitter: Boolean 988 | } 989 | "Autogenerated input type of CreateReview" 990 | input CreateReviewInput { 991 | body: String! 992 | "A unique identifier for the client performing the mutation." 993 | clientMutationId: String 994 | ratingAnimationState: RatingState 995 | ratingCharacterState: RatingState 996 | ratingMusicState: RatingState 997 | ratingOverallState: RatingState 998 | ratingStoryState: RatingState 999 | shareFacebook: Boolean 1000 | shareTwitter: Boolean 1001 | title: String 1002 | workId: ID! 1003 | } 1004 | "Autogenerated input type of DeleteRecord" 1005 | input DeleteRecordInput { 1006 | "A unique identifier for the client performing the mutation." 1007 | clientMutationId: String 1008 | recordId: ID! 1009 | } 1010 | "Autogenerated input type of DeleteReview" 1011 | input DeleteReviewInput { 1012 | "A unique identifier for the client performing the mutation." 1013 | clientMutationId: String 1014 | reviewId: ID! 1015 | } 1016 | input EpisodeOrder { 1017 | direction: OrderDirection! 1018 | field: EpisodeOrderField! 1019 | } 1020 | input OrganizationOrder { 1021 | direction: OrderDirection! 1022 | field: OrganizationOrderField! 1023 | } 1024 | input PersonOrder { 1025 | direction: OrderDirection! 1026 | field: PersonOrderField! 1027 | } 1028 | input ProgramOrder { 1029 | direction: OrderDirection! 1030 | field: ProgramOrderField! 1031 | } 1032 | input RecordOrder { 1033 | direction: OrderDirection! 1034 | field: RecordOrderField! 1035 | } 1036 | input ReviewOrder { 1037 | direction: OrderDirection! 1038 | field: ReviewOrderField! 1039 | } 1040 | input SeriesWorkOrder { 1041 | direction: OrderDirection! 1042 | field: SeriesWorkOrderField! 1043 | } 1044 | input StaffOrder { 1045 | direction: OrderDirection! 1046 | field: StaffOrderField! 1047 | } 1048 | "Autogenerated input type of UpdateRecord" 1049 | input UpdateRecordInput { 1050 | "A unique identifier for the client performing the mutation." 1051 | clientMutationId: String 1052 | comment: String 1053 | ratingState: RatingState 1054 | recordId: ID! 1055 | shareFacebook: Boolean 1056 | shareTwitter: Boolean 1057 | } 1058 | "Autogenerated input type of UpdateReview" 1059 | input UpdateReviewInput { 1060 | body: String! 1061 | "A unique identifier for the client performing the mutation." 1062 | clientMutationId: String 1063 | ratingAnimationState: RatingState! 1064 | ratingCharacterState: RatingState! 1065 | ratingMusicState: RatingState! 1066 | ratingOverallState: RatingState! 1067 | ratingStoryState: RatingState! 1068 | reviewId: ID! 1069 | shareFacebook: Boolean 1070 | shareTwitter: Boolean 1071 | title: String 1072 | } 1073 | "Autogenerated input type of UpdateStatus" 1074 | input UpdateStatusInput { 1075 | "A unique identifier for the client performing the mutation." 1076 | clientMutationId: String 1077 | state: StatusState! 1078 | workId: ID! 1079 | } 1080 | input WorkOrder { 1081 | direction: OrderDirection! 1082 | field: WorkOrderField! 1083 | } 1084 | -------------------------------------------------------------------------------- /src/api/watching.graphql: -------------------------------------------------------------------------------- 1 | query WatchingQuery( 2 | $username: String!, 3 | $state: StatusState!, 4 | $seasons: [String!]!, 5 | $orderBy: WorkOrder! 6 | ) { 7 | user(username: $username) { 8 | name 9 | username 10 | avatarUrl 11 | 12 | works( 13 | orderBy: $orderBy, 14 | seasons: $seasons, 15 | state: $state, 16 | ) { 17 | nodes { 18 | title 19 | image { 20 | recommendedImageUrl 21 | } 22 | satisfactionRate 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/api/watching.rs: -------------------------------------------------------------------------------- 1 | use actix_web::error::ErrorInternalServerError; 2 | use actix_web::web::{Path, Query}; 3 | use actix_web::HttpResponse; 4 | use futures::future::join_all; 5 | use graphql_client::GraphQLQuery; 6 | use log::*; 7 | use sailfish::TemplateOnce; 8 | use serde::Deserialize; 9 | 10 | use super::common; 11 | use actix_web::http::header::{CacheControl, CacheDirective}; 12 | use log::Level::Trace; 13 | use watching_query::*; 14 | 15 | #[derive(GraphQLQuery)] 16 | #[graphql( 17 | schema_path = "src/api/schema.graphql", 18 | query_path = "src/api/watching.graphql", 19 | response_derives = "Debug" 20 | )] 21 | struct WatchingQuery; 22 | 23 | #[derive(Deserialize, Debug, Clone)] 24 | pub struct WatchingParameter { 25 | #[serde(default)] 26 | season: Option, 27 | #[serde(default = "default_bg_color")] 28 | bg_color: String, 29 | #[serde(default = "default_header_color")] 30 | header_color: String, 31 | #[serde(default = "default_text_color")] 32 | text_color: String, 33 | #[serde(default = "default_icon_color")] 34 | icon_color: String, 35 | #[serde(default = "default_title_color")] 36 | title_color: String, 37 | #[serde(default = "default_limit_works")] 38 | limit_works: usize, 39 | #[serde(default = "default_limit_images")] 40 | limit_images: usize, 41 | #[serde(default)] 42 | sort: SortKey, 43 | #[serde(default)] 44 | order: SortOrder, 45 | #[serde(default)] 46 | expose_image_url: bool, 47 | } 48 | 49 | fn default_bg_color() -> String { 50 | String::from("1a1b27") 51 | } 52 | fn default_header_color() -> String { 53 | String::from("70a5fd") 54 | } 55 | fn default_text_color() -> String { 56 | String::from("d6e3e1") 57 | } 58 | fn default_icon_color() -> String { 59 | String::from("bf91f3") 60 | } 61 | fn default_title_color() -> String { 62 | String::from("38bdae") 63 | } 64 | fn default_limit_works() -> usize { 65 | 10 66 | } 67 | fn default_limit_images() -> usize { 68 | 3 69 | } 70 | 71 | #[derive(Deserialize, PartialEq, Debug, Clone)] 72 | enum SortKey { 73 | #[serde(alias = "watcher")] 74 | WatchersCount, 75 | #[serde(alias = "satisfaction")] 76 | SatisfactionRate, 77 | } 78 | 79 | impl Default for SortKey { 80 | fn default() -> Self { 81 | SortKey::SatisfactionRate 82 | } 83 | } 84 | 85 | #[derive(Deserialize, PartialEq, Debug, Clone)] 86 | enum SortOrder { 87 | #[serde(alias = "desc")] 88 | Descending, 89 | #[serde(alias = "asc")] 90 | Ascending, 91 | } 92 | 93 | impl Default for SortOrder { 94 | fn default() -> Self { 95 | SortOrder::Descending 96 | } 97 | } 98 | 99 | #[derive(TemplateOnce)] 100 | #[template(path = "watching.svg")] 101 | struct WatchingSvgTemplate { 102 | query: Query, 103 | name: String, 104 | username: String, 105 | avatar_uri: String, 106 | works: Vec, 107 | works_count: usize, 108 | image_uris: Vec, 109 | } 110 | 111 | #[actix_web::get("/watching/{username}")] 112 | pub async fn get_watching( 113 | path: Path, 114 | query: Query, 115 | ) -> actix_web::Result { 116 | let username = path.into_inner(); 117 | let data = common::perform_query::(Variables { 118 | username, 119 | state: StatusState::WATCHING, 120 | order_by: WorkOrder { 121 | direction: match query.order.clone() { 122 | SortOrder::Ascending => OrderDirection::ASC, 123 | SortOrder::Descending => OrderDirection::DESC, 124 | }, 125 | field: WorkOrderField::WATCHERS_COUNT, 126 | }, 127 | seasons: match query.season.as_deref() { 128 | Some("all") => vec![], 129 | Some(value) => vec![String::from(value)], 130 | None => vec![common::get_current_season()], 131 | }, 132 | }) 133 | .await 134 | .map_err(|e| ErrorInternalServerError(e))?; 135 | 136 | if log_enabled!(Trace) { 137 | trace!("Query: {:#?}", &query); 138 | trace!("Response: {:#?}", &data); 139 | } 140 | 141 | // ユーザオブジェクト 142 | let user: WatchingQueryUser = match data.user { 143 | Some(user) => user, 144 | None => return Ok(HttpResponse::NotFound().finish()), 145 | }; 146 | 147 | // プロフィール画像 148 | let original_avatar_url = user.avatar_url.unwrap(); 149 | let avatar_uri = match query.expose_image_url { 150 | true => original_avatar_url, 151 | false => { 152 | // base64 エンコードする 153 | match common::encode_image(original_avatar_url).await { 154 | Ok(uri) => uri, 155 | Err(e) => { 156 | warn!("An error occurred while encode_image: {:#?}", e); 157 | String::from("data:image/png;base64,") 158 | } 159 | } 160 | } 161 | }; 162 | 163 | // 作品のベクトル 164 | let original_works: Vec = user 165 | .works 166 | .unwrap() 167 | .nodes 168 | .unwrap() 169 | .into_iter() 170 | .filter_map(|x| x) 171 | .collect(); 172 | let works_count = original_works.len(); 173 | let mut works: Vec = original_works; 174 | // 満足度の降順でソート 175 | if query.sort == SortKey::SatisfactionRate { 176 | works.sort_unstable_by(|x, y| { 177 | let rate_x: f64 = x.satisfaction_rate.unwrap_or(0.0); 178 | let rate_y: f64 = y.satisfaction_rate.unwrap_or(0.0); 179 | 180 | match &query.order { 181 | SortOrder::Ascending => rate_x.partial_cmp(&rate_y).unwrap(), 182 | SortOrder::Descending => rate_y.partial_cmp(&rate_x).unwrap(), 183 | } 184 | }); 185 | } 186 | // limit_works 個に制限 187 | works = works.into_iter().take(query.limit_works).collect(); 188 | 189 | // 作品のアイキャッチ画像のベクトル 190 | let original_image_uris: Vec = (&works) 191 | .into_iter() 192 | .filter_map(|x| x.image.as_ref()) 193 | .filter_map(|x| x.recommended_image_url.as_ref()) 194 | .map(|x| x.to_owned()) 195 | .take(query.limit_images) 196 | .collect(); 197 | let image_uris = match query.expose_image_url { 198 | true => original_image_uris, 199 | false => { 200 | // 並列に base64 エンコードする 201 | let job = join_all( 202 | original_image_uris 203 | .into_iter() 204 | .map(|x| common::encode_image(x)), 205 | ); 206 | 207 | job.await 208 | .into_iter() 209 | .map(|x| { 210 | match x { 211 | Ok(uri) => uri, 212 | // 失敗したら空画像に差し替える 213 | Err(e) => { 214 | warn!("An error occurred while encode_image: {:#?}", e); 215 | String::from("data:image/png;base64,") 216 | } 217 | } 218 | }) 219 | .collect() 220 | } 221 | }; 222 | 223 | let svg = WatchingSvgTemplate { 224 | query, 225 | name: user.name, 226 | username: user.username, 227 | avatar_uri, 228 | works, 229 | works_count, 230 | image_uris, 231 | } 232 | .render_once() 233 | .map_err(|e| ErrorInternalServerError(e))?; 234 | 235 | let mut builder = HttpResponse::Ok(); 236 | builder.content_type("image/svg+xml"); 237 | builder.insert_header(CacheControl(vec![ 238 | CacheDirective::Public, 239 | CacheDirective::MaxAge(7200), 240 | ])); 241 | let response = builder.body(svg); 242 | 243 | Ok(response) 244 | } 245 | -------------------------------------------------------------------------------- /src/api/watching.svg: -------------------------------------------------------------------------------- 1 | 2 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | <%= *name %> @<%= *username %> 56 | 57 | 58 | 今期視聴中: <%= works_count %> 作品 59 | 60 | 61 | 62 | 63 | 64 | 65 | <% for (i, work) in works.iter().enumerate() { %> 66 | 67 | 68 | 69 | 70 | 71 | 72 | <%= work.title %> 73 | 74 | 75 | <% } %> 76 | 77 | 78 | 79 | 80 | <% for (i, image_uri) in image_uris.iter().enumerate() { %> 81 | 82 | 83 | 84 | <% } %> 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | 3 | #[derive(Deserialize, Debug)] 4 | pub struct Config { 5 | #[serde(default = "default_http_addr")] 6 | pub http_addr: String, 7 | pub annict_token: String, 8 | } 9 | 10 | fn default_http_addr() -> String { 11 | "0.0.0.0:8080".to_string() 12 | } 13 | 14 | pub fn load() -> Config { 15 | envy::from_env().unwrap_or_else(|_| panic!("failed to load env")) 16 | } 17 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use actix_cors::Cors; 2 | use actix_web::{middleware, App, HttpServer}; 3 | use env_logger; 4 | use log::*; 5 | 6 | mod api; 7 | mod config; 8 | 9 | #[actix_web::main] 10 | async fn main() -> std::io::Result<()> { 11 | env_logger::init(); 12 | 13 | openssl_probe::init_ssl_cert_env_vars(); 14 | 15 | let config = config::load(); 16 | info!("HTTP Server is listening for {}", config.http_addr); 17 | 18 | HttpServer::new(|| { 19 | let cors = Cors::default() 20 | .allow_any_origin() 21 | .allowed_methods(vec!["GET"]) 22 | .allow_any_header() 23 | .max_age(3600); 24 | 25 | App::new() 26 | .wrap(cors) 27 | .wrap(middleware::Logger::default()) 28 | .service(api::index::get_index) 29 | .service(api::watching::get_watching) 30 | }) 31 | .bind(config.http_addr)? 32 | .run() 33 | .await 34 | } 35 | --------------------------------------------------------------------------------