├── .github └── workflows │ └── release.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── get_keys ├── Cargo.toml └── src │ └── main.rs ├── mpv-livetweet.lua └── twitter ├── Cargo.toml └── src └── main.rs /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | workflow_dispatch: 4 | push: 5 | tags: 6 | - v*.*.* 7 | 8 | jobs: 9 | build: 10 | strategy: 11 | matrix: 12 | include: 13 | - os: ubuntu-latest 14 | copy_artifacts: cp target/release/get_keys target/release/twitter mpv-livetweet.lua dist 15 | artifact_name: build_linux 16 | - os: macos-latest 17 | copy_artifacts: cp target/release/get_keys target/release/twitter mpv-livetweet.lua dist 18 | artifact_name: build_macos 19 | - os: windows-latest 20 | copy_artifacts: cp target/release/get_keys.exe,target/release/twitter.exe,mpv-livetweet.lua dist 21 | artifact_name: build_windows 22 | 23 | runs-on: ${{ matrix.os }} 24 | 25 | environment: Twitter 26 | 27 | steps: 28 | - name: Checkout 29 | uses: actions/checkout@v2 30 | 31 | - name: Install Rust toolchain 32 | uses: actions-rs/toolchain@v1 33 | with: 34 | toolchain: stable 35 | 36 | - name: Build 37 | uses: actions-rs/cargo@v1 38 | env: 39 | CONSUMER_KEY: ${{ secrets.CONSUMER_KEY }} 40 | CONSUMER_SECRET: ${{ secrets.CONSUMER_SECRET }} 41 | with: 42 | command: build 43 | args: --release 44 | 45 | - name: Create dist directory 46 | run: mkdir dist 47 | 48 | - name: Copy artifacts to dist 49 | run: ${{ matrix.copy_artifacts }} 50 | 51 | - name: Upload release zip 52 | uses: actions/upload-artifact@v2 53 | with: 54 | name: ${{ matrix.artifact_name }} 55 | path: dist/* 56 | 57 | release: 58 | needs: build 59 | runs-on: ubuntu-latest 60 | steps: 61 | - uses: actions/download-artifact@v2 62 | 63 | - name: Zip windows 64 | run: zip ../mpv-livetweet_windows.zip * 65 | working-directory: build_windows 66 | 67 | - name: Zip linux 68 | run: zip ../mpv-livetweet_linux.zip * 69 | working-directory: build_linux 70 | 71 | - name: Zip macos 72 | run: zip ../mpv-livetweet_macos.zip * 73 | working-directory: build_macos 74 | 75 | - name: Release 76 | uses: softprops/action-gh-release@v1 77 | env: 78 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 79 | with: 80 | files: | 81 | mpv-livetweet_windows.zip 82 | mpv-livetweet_linux.zip 83 | mpv-livetweet_macos.zip 84 | 85 | # build_linux: 86 | # runs-on: ubuntu-latest 87 | # steps: 88 | # - name: Checkout 89 | # uses: actions/checkout@v2 90 | 91 | # - name: Install Rust toolchain 92 | # uses: actions-rs/toolchain@v1 93 | # with: 94 | # toolchain: stable 95 | 96 | # - name: Build 97 | # uses: actions-rs/cargo@v1 98 | # env: 99 | # CONSUMER_KEY: ${{ secrets.CONSUMER_KEY }} 100 | # CONSUMER_SECRET: ${{ secrets.CONSUMER_SECRET }} 101 | # with: 102 | # command: build 103 | # args: --release 104 | 105 | # - name: Create release zip 106 | # run: mkdir dist && cp target/release/get_keys target/release/twitter mpv-livetweet.lua dist && cd dist && zip mpv-livetweet_v1.0.1_linux.zip * 107 | 108 | # - name: Upload release zip 109 | # uses: actions/upload-artifact@v2 110 | # with: 111 | # name: build_linux 112 | # path: dist/mpv-livetweet_v1.0.1_linux.zip 113 | 114 | # build_macos: 115 | # runs-on: macos-latest 116 | # steps: 117 | # - name: Checkout 118 | # uses: actions/checkout@v2 119 | 120 | # - name: Install Rust toolchain 121 | # uses: actions-rs/toolchain@v1 122 | # with: 123 | # toolchain: stable 124 | 125 | # - name: Build 126 | # uses: actions-rs/cargo@v1 127 | # env: 128 | # CONSUMER_KEY: ${{ secrets.CONSUMER_KEY }} 129 | # CONSUMER_SECRET: ${{ secrets.CONSUMER_SECRET }} 130 | # with: 131 | # command: build 132 | # args: --release 133 | 134 | # - name: Create release zip 135 | # run: mkdir dist && cp target/release/get_keys target/release/twitter mpv-livetweet.lua dist && cd dist && zip mpv-livetweet_v1.0.1_macos.zip * 136 | 137 | # - name: Upload release zip 138 | # uses: actions/upload-artifact@v2 139 | # with: 140 | # name: build_macos 141 | # path: dist/mpv-livetweet_v1.0.1_macos.zip 142 | 143 | # build_windows: 144 | # runs-on: windows-latest 145 | # steps: 146 | # - name: Checkout 147 | # uses: actions/checkout@v2 148 | 149 | # - name: Install Rust toolchain 150 | # uses: actions-rs/toolchain@v1 151 | # with: 152 | # toolchain: stable 153 | 154 | # - name: Build 155 | # uses: actions-rs/cargo@v1 156 | # env: 157 | # CONSUMER_KEY: ${{ secrets.CONSUMER_KEY }} 158 | # CONSUMER_SECRET: ${{ secrets.CONSUMER_SECRET }} 159 | # with: 160 | # command: build 161 | # args: --release 162 | 163 | # - name: Create release zip 164 | # run: mkdir dist ; cp target\release\get_keys.exe,target\release\twitter.exe,mpv-livetweet.lua dist ; cd dist ; 7z a mpv-livetweet_v1.0.1_windows.zip * 165 | 166 | # - name: Upload release zip 167 | # uses: actions/upload-artifact@v2 168 | # with: 169 | # name: build_windows 170 | # path: dist\mpv-livetweet_v1.0.1_windows.zip 171 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | dist/ 3 | *.zip 4 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aho-corasick" 5 | version = "0.7.18" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 8 | dependencies = [ 9 | "memchr", 10 | ] 11 | 12 | [[package]] 13 | name = "atty" 14 | version = "0.2.14" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 17 | dependencies = [ 18 | "hermit-abi", 19 | "libc", 20 | "winapi", 21 | ] 22 | 23 | [[package]] 24 | name = "autocfg" 25 | version = "1.0.1" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 28 | 29 | [[package]] 30 | name = "base64" 31 | version = "0.13.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 34 | 35 | [[package]] 36 | name = "bitflags" 37 | version = "1.2.1" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 40 | 41 | [[package]] 42 | name = "block-buffer" 43 | version = "0.9.0" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" 46 | dependencies = [ 47 | "generic-array", 48 | ] 49 | 50 | [[package]] 51 | name = "bumpalo" 52 | version = "3.7.0" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" 55 | 56 | [[package]] 57 | name = "bytes" 58 | version = "1.0.1" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" 61 | 62 | [[package]] 63 | name = "cc" 64 | version = "1.0.68" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" 67 | 68 | [[package]] 69 | name = "cfg-if" 70 | version = "1.0.0" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 73 | 74 | [[package]] 75 | name = "chrono" 76 | version = "0.4.19" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" 79 | dependencies = [ 80 | "libc", 81 | "num-integer", 82 | "num-traits", 83 | "serde", 84 | "time", 85 | "winapi", 86 | ] 87 | 88 | [[package]] 89 | name = "clap" 90 | version = "3.0.0-beta.2" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "4bd1061998a501ee7d4b6d449020df3266ca3124b941ec56cf2005c3779ca142" 93 | dependencies = [ 94 | "atty", 95 | "bitflags", 96 | "clap_derive", 97 | "indexmap", 98 | "lazy_static", 99 | "os_str_bytes", 100 | "strsim", 101 | "termcolor", 102 | "textwrap", 103 | "unicode-width", 104 | "vec_map", 105 | ] 106 | 107 | [[package]] 108 | name = "clap_derive" 109 | version = "3.0.0-beta.2" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "370f715b81112975b1b69db93e0b56ea4cd4e5002ac43b2da8474106a54096a1" 112 | dependencies = [ 113 | "heck", 114 | "proc-macro-error", 115 | "proc-macro2", 116 | "quote", 117 | "syn", 118 | ] 119 | 120 | [[package]] 121 | name = "convert_case" 122 | version = "0.4.0" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" 125 | 126 | [[package]] 127 | name = "core-foundation" 128 | version = "0.9.1" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" 131 | dependencies = [ 132 | "core-foundation-sys", 133 | "libc", 134 | ] 135 | 136 | [[package]] 137 | name = "core-foundation-sys" 138 | version = "0.8.2" 139 | source = "registry+https://github.com/rust-lang/crates.io-index" 140 | checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" 141 | 142 | [[package]] 143 | name = "cpufeatures" 144 | version = "0.1.5" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef" 147 | dependencies = [ 148 | "libc", 149 | ] 150 | 151 | [[package]] 152 | name = "crypto-mac" 153 | version = "0.10.0" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" 156 | dependencies = [ 157 | "generic-array", 158 | "subtle", 159 | ] 160 | 161 | [[package]] 162 | name = "derive_more" 163 | version = "0.99.14" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "5cc7b9cef1e351660e5443924e4f43ab25fbbed3e9a5f052df3677deb4d6b320" 166 | dependencies = [ 167 | "convert_case", 168 | "proc-macro2", 169 | "quote", 170 | "syn", 171 | ] 172 | 173 | [[package]] 174 | name = "digest" 175 | version = "0.9.0" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" 178 | dependencies = [ 179 | "generic-array", 180 | ] 181 | 182 | [[package]] 183 | name = "egg-mode" 184 | version = "0.15.0" 185 | source = "git+https://github.com/egg-mode-rs/egg-mode?rev=6b81073eba9#6b81073eba9c3b123ca0e80bdb5ef61d1758f131" 186 | dependencies = [ 187 | "base64", 188 | "chrono", 189 | "derive_more", 190 | "futures", 191 | "hmac", 192 | "hyper", 193 | "hyper-tls", 194 | "lazy_static", 195 | "mime", 196 | "native-tls", 197 | "percent-encoding", 198 | "rand", 199 | "regex", 200 | "serde", 201 | "serde_json", 202 | "sha-1", 203 | "thiserror", 204 | "tokio", 205 | "url", 206 | ] 207 | 208 | [[package]] 209 | name = "fnv" 210 | version = "1.0.7" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 213 | 214 | [[package]] 215 | name = "foreign-types" 216 | version = "0.3.2" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 219 | dependencies = [ 220 | "foreign-types-shared", 221 | ] 222 | 223 | [[package]] 224 | name = "foreign-types-shared" 225 | version = "0.1.1" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 228 | 229 | [[package]] 230 | name = "form_urlencoded" 231 | version = "1.0.1" 232 | source = "registry+https://github.com/rust-lang/crates.io-index" 233 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" 234 | dependencies = [ 235 | "matches", 236 | "percent-encoding", 237 | ] 238 | 239 | [[package]] 240 | name = "futures" 241 | version = "0.3.15" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "0e7e43a803dae2fa37c1f6a8fe121e1f7bf9548b4dfc0522a42f34145dadfc27" 244 | dependencies = [ 245 | "futures-channel", 246 | "futures-core", 247 | "futures-executor", 248 | "futures-io", 249 | "futures-sink", 250 | "futures-task", 251 | "futures-util", 252 | ] 253 | 254 | [[package]] 255 | name = "futures-channel" 256 | version = "0.3.15" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "e682a68b29a882df0545c143dc3646daefe80ba479bcdede94d5a703de2871e2" 259 | dependencies = [ 260 | "futures-core", 261 | "futures-sink", 262 | ] 263 | 264 | [[package]] 265 | name = "futures-core" 266 | version = "0.3.15" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "0402f765d8a89a26043b889b26ce3c4679d268fa6bb22cd7c6aad98340e179d1" 269 | 270 | [[package]] 271 | name = "futures-executor" 272 | version = "0.3.15" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "badaa6a909fac9e7236d0620a2f57f7664640c56575b71a7552fbd68deafab79" 275 | dependencies = [ 276 | "futures-core", 277 | "futures-task", 278 | "futures-util", 279 | ] 280 | 281 | [[package]] 282 | name = "futures-io" 283 | version = "0.3.15" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "acc499defb3b348f8d8f3f66415835a9131856ff7714bf10dadfc4ec4bdb29a1" 286 | 287 | [[package]] 288 | name = "futures-macro" 289 | version = "0.3.15" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "a4c40298486cdf52cc00cd6d6987892ba502c7656a16a4192a9992b1ccedd121" 292 | dependencies = [ 293 | "autocfg", 294 | "proc-macro-hack", 295 | "proc-macro2", 296 | "quote", 297 | "syn", 298 | ] 299 | 300 | [[package]] 301 | name = "futures-sink" 302 | version = "0.3.15" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "a57bead0ceff0d6dde8f465ecd96c9338121bb7717d3e7b108059531870c4282" 305 | 306 | [[package]] 307 | name = "futures-task" 308 | version = "0.3.15" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "8a16bef9fc1a4dddb5bee51c989e3fbba26569cbb0e31f5b303c184e3dd33dae" 311 | 312 | [[package]] 313 | name = "futures-util" 314 | version = "0.3.15" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "feb5c238d27e2bf94ffdfd27b2c29e3df4a68c4193bb6427384259e2bf191967" 317 | dependencies = [ 318 | "autocfg", 319 | "futures-channel", 320 | "futures-core", 321 | "futures-io", 322 | "futures-macro", 323 | "futures-sink", 324 | "futures-task", 325 | "memchr", 326 | "pin-project-lite", 327 | "pin-utils", 328 | "proc-macro-hack", 329 | "proc-macro-nested", 330 | "slab", 331 | ] 332 | 333 | [[package]] 334 | name = "generic-array" 335 | version = "0.14.4" 336 | source = "registry+https://github.com/rust-lang/crates.io-index" 337 | checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" 338 | dependencies = [ 339 | "typenum", 340 | "version_check", 341 | ] 342 | 343 | [[package]] 344 | name = "get_keys" 345 | version = "1.0.0" 346 | dependencies = [ 347 | "clap", 348 | "egg-mode", 349 | "tokio", 350 | "webbrowser", 351 | ] 352 | 353 | [[package]] 354 | name = "getrandom" 355 | version = "0.2.3" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" 358 | dependencies = [ 359 | "cfg-if", 360 | "libc", 361 | "wasi", 362 | ] 363 | 364 | [[package]] 365 | name = "h2" 366 | version = "0.3.3" 367 | source = "registry+https://github.com/rust-lang/crates.io-index" 368 | checksum = "825343c4eef0b63f541f8903f395dc5beb362a979b5799a84062527ef1e37726" 369 | dependencies = [ 370 | "bytes", 371 | "fnv", 372 | "futures-core", 373 | "futures-sink", 374 | "futures-util", 375 | "http", 376 | "indexmap", 377 | "slab", 378 | "tokio", 379 | "tokio-util", 380 | "tracing", 381 | ] 382 | 383 | [[package]] 384 | name = "hashbrown" 385 | version = "0.11.2" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" 388 | 389 | [[package]] 390 | name = "heck" 391 | version = "0.3.3" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" 394 | dependencies = [ 395 | "unicode-segmentation", 396 | ] 397 | 398 | [[package]] 399 | name = "hermit-abi" 400 | version = "0.1.19" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 403 | dependencies = [ 404 | "libc", 405 | ] 406 | 407 | [[package]] 408 | name = "hmac" 409 | version = "0.10.1" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" 412 | dependencies = [ 413 | "crypto-mac", 414 | "digest", 415 | ] 416 | 417 | [[package]] 418 | name = "http" 419 | version = "0.2.4" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" 422 | dependencies = [ 423 | "bytes", 424 | "fnv", 425 | "itoa", 426 | ] 427 | 428 | [[package]] 429 | name = "http-body" 430 | version = "0.4.2" 431 | source = "registry+https://github.com/rust-lang/crates.io-index" 432 | checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9" 433 | dependencies = [ 434 | "bytes", 435 | "http", 436 | "pin-project-lite", 437 | ] 438 | 439 | [[package]] 440 | name = "httparse" 441 | version = "1.4.1" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68" 444 | 445 | [[package]] 446 | name = "httpdate" 447 | version = "1.0.1" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" 450 | 451 | [[package]] 452 | name = "hyper" 453 | version = "0.14.9" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "07d6baa1b441335f3ce5098ac421fb6547c46dda735ca1bc6d0153c838f9dd83" 456 | dependencies = [ 457 | "bytes", 458 | "futures-channel", 459 | "futures-core", 460 | "futures-util", 461 | "h2", 462 | "http", 463 | "http-body", 464 | "httparse", 465 | "httpdate", 466 | "itoa", 467 | "pin-project-lite", 468 | "socket2", 469 | "tokio", 470 | "tower-service", 471 | "tracing", 472 | "want", 473 | ] 474 | 475 | [[package]] 476 | name = "hyper-tls" 477 | version = "0.5.0" 478 | source = "registry+https://github.com/rust-lang/crates.io-index" 479 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 480 | dependencies = [ 481 | "bytes", 482 | "hyper", 483 | "native-tls", 484 | "tokio", 485 | "tokio-native-tls", 486 | ] 487 | 488 | [[package]] 489 | name = "idna" 490 | version = "0.2.3" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" 493 | dependencies = [ 494 | "matches", 495 | "unicode-bidi", 496 | "unicode-normalization", 497 | ] 498 | 499 | [[package]] 500 | name = "indexmap" 501 | version = "1.7.0" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" 504 | dependencies = [ 505 | "autocfg", 506 | "hashbrown", 507 | ] 508 | 509 | [[package]] 510 | name = "instant" 511 | version = "0.1.9" 512 | source = "registry+https://github.com/rust-lang/crates.io-index" 513 | checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" 514 | dependencies = [ 515 | "cfg-if", 516 | ] 517 | 518 | [[package]] 519 | name = "itoa" 520 | version = "0.4.7" 521 | source = "registry+https://github.com/rust-lang/crates.io-index" 522 | checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" 523 | 524 | [[package]] 525 | name = "js-sys" 526 | version = "0.3.51" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" 529 | dependencies = [ 530 | "wasm-bindgen", 531 | ] 532 | 533 | [[package]] 534 | name = "lazy_static" 535 | version = "1.4.0" 536 | source = "registry+https://github.com/rust-lang/crates.io-index" 537 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 538 | 539 | [[package]] 540 | name = "libc" 541 | version = "0.2.97" 542 | source = "registry+https://github.com/rust-lang/crates.io-index" 543 | checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6" 544 | 545 | [[package]] 546 | name = "lock_api" 547 | version = "0.4.4" 548 | source = "registry+https://github.com/rust-lang/crates.io-index" 549 | checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" 550 | dependencies = [ 551 | "scopeguard", 552 | ] 553 | 554 | [[package]] 555 | name = "log" 556 | version = "0.4.14" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 559 | dependencies = [ 560 | "cfg-if", 561 | ] 562 | 563 | [[package]] 564 | name = "matches" 565 | version = "0.1.8" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" 568 | 569 | [[package]] 570 | name = "memchr" 571 | version = "2.4.0" 572 | source = "registry+https://github.com/rust-lang/crates.io-index" 573 | checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" 574 | 575 | [[package]] 576 | name = "mime" 577 | version = "0.3.16" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 580 | 581 | [[package]] 582 | name = "mio" 583 | version = "0.7.13" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" 586 | dependencies = [ 587 | "libc", 588 | "log", 589 | "miow", 590 | "ntapi", 591 | "winapi", 592 | ] 593 | 594 | [[package]] 595 | name = "miow" 596 | version = "0.3.7" 597 | source = "registry+https://github.com/rust-lang/crates.io-index" 598 | checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" 599 | dependencies = [ 600 | "winapi", 601 | ] 602 | 603 | [[package]] 604 | name = "native-tls" 605 | version = "0.2.7" 606 | source = "registry+https://github.com/rust-lang/crates.io-index" 607 | checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" 608 | dependencies = [ 609 | "lazy_static", 610 | "libc", 611 | "log", 612 | "openssl", 613 | "openssl-probe", 614 | "openssl-sys", 615 | "schannel", 616 | "security-framework", 617 | "security-framework-sys", 618 | "tempfile", 619 | ] 620 | 621 | [[package]] 622 | name = "ntapi" 623 | version = "0.3.6" 624 | source = "registry+https://github.com/rust-lang/crates.io-index" 625 | checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" 626 | dependencies = [ 627 | "winapi", 628 | ] 629 | 630 | [[package]] 631 | name = "num-integer" 632 | version = "0.1.44" 633 | source = "registry+https://github.com/rust-lang/crates.io-index" 634 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 635 | dependencies = [ 636 | "autocfg", 637 | "num-traits", 638 | ] 639 | 640 | [[package]] 641 | name = "num-traits" 642 | version = "0.2.14" 643 | source = "registry+https://github.com/rust-lang/crates.io-index" 644 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 645 | dependencies = [ 646 | "autocfg", 647 | ] 648 | 649 | [[package]] 650 | name = "num_cpus" 651 | version = "1.13.0" 652 | source = "registry+https://github.com/rust-lang/crates.io-index" 653 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 654 | dependencies = [ 655 | "hermit-abi", 656 | "libc", 657 | ] 658 | 659 | [[package]] 660 | name = "once_cell" 661 | version = "1.8.0" 662 | source = "registry+https://github.com/rust-lang/crates.io-index" 663 | checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" 664 | 665 | [[package]] 666 | name = "opaque-debug" 667 | version = "0.3.0" 668 | source = "registry+https://github.com/rust-lang/crates.io-index" 669 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" 670 | 671 | [[package]] 672 | name = "openssl" 673 | version = "0.10.35" 674 | source = "registry+https://github.com/rust-lang/crates.io-index" 675 | checksum = "549430950c79ae24e6d02e0b7404534ecf311d94cc9f861e9e4020187d13d885" 676 | dependencies = [ 677 | "bitflags", 678 | "cfg-if", 679 | "foreign-types", 680 | "libc", 681 | "once_cell", 682 | "openssl-sys", 683 | ] 684 | 685 | [[package]] 686 | name = "openssl-probe" 687 | version = "0.1.4" 688 | source = "registry+https://github.com/rust-lang/crates.io-index" 689 | checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" 690 | 691 | [[package]] 692 | name = "openssl-sys" 693 | version = "0.9.65" 694 | source = "registry+https://github.com/rust-lang/crates.io-index" 695 | checksum = "7a7907e3bfa08bb85105209cdfcb6c63d109f8f6c1ed6ca318fff5c1853fbc1d" 696 | dependencies = [ 697 | "autocfg", 698 | "cc", 699 | "libc", 700 | "pkg-config", 701 | "vcpkg", 702 | ] 703 | 704 | [[package]] 705 | name = "os_str_bytes" 706 | version = "2.4.0" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85" 709 | 710 | [[package]] 711 | name = "parking_lot" 712 | version = "0.11.1" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" 715 | dependencies = [ 716 | "instant", 717 | "lock_api", 718 | "parking_lot_core", 719 | ] 720 | 721 | [[package]] 722 | name = "parking_lot_core" 723 | version = "0.8.3" 724 | source = "registry+https://github.com/rust-lang/crates.io-index" 725 | checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" 726 | dependencies = [ 727 | "cfg-if", 728 | "instant", 729 | "libc", 730 | "redox_syscall", 731 | "smallvec", 732 | "winapi", 733 | ] 734 | 735 | [[package]] 736 | name = "percent-encoding" 737 | version = "2.1.0" 738 | source = "registry+https://github.com/rust-lang/crates.io-index" 739 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 740 | 741 | [[package]] 742 | name = "pin-project-lite" 743 | version = "0.2.7" 744 | source = "registry+https://github.com/rust-lang/crates.io-index" 745 | checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" 746 | 747 | [[package]] 748 | name = "pin-utils" 749 | version = "0.1.0" 750 | source = "registry+https://github.com/rust-lang/crates.io-index" 751 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 752 | 753 | [[package]] 754 | name = "pkg-config" 755 | version = "0.3.19" 756 | source = "registry+https://github.com/rust-lang/crates.io-index" 757 | checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" 758 | 759 | [[package]] 760 | name = "ppv-lite86" 761 | version = "0.2.10" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" 764 | 765 | [[package]] 766 | name = "proc-macro-error" 767 | version = "1.0.4" 768 | source = "registry+https://github.com/rust-lang/crates.io-index" 769 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 770 | dependencies = [ 771 | "proc-macro-error-attr", 772 | "proc-macro2", 773 | "quote", 774 | "syn", 775 | "version_check", 776 | ] 777 | 778 | [[package]] 779 | name = "proc-macro-error-attr" 780 | version = "1.0.4" 781 | source = "registry+https://github.com/rust-lang/crates.io-index" 782 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 783 | dependencies = [ 784 | "proc-macro2", 785 | "quote", 786 | "version_check", 787 | ] 788 | 789 | [[package]] 790 | name = "proc-macro-hack" 791 | version = "0.5.19" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" 794 | 795 | [[package]] 796 | name = "proc-macro-nested" 797 | version = "0.1.7" 798 | source = "registry+https://github.com/rust-lang/crates.io-index" 799 | checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" 800 | 801 | [[package]] 802 | name = "proc-macro2" 803 | version = "1.0.27" 804 | source = "registry+https://github.com/rust-lang/crates.io-index" 805 | checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" 806 | dependencies = [ 807 | "unicode-xid", 808 | ] 809 | 810 | [[package]] 811 | name = "quote" 812 | version = "1.0.9" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" 815 | dependencies = [ 816 | "proc-macro2", 817 | ] 818 | 819 | [[package]] 820 | name = "rand" 821 | version = "0.8.4" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" 824 | dependencies = [ 825 | "libc", 826 | "rand_chacha", 827 | "rand_core", 828 | "rand_hc", 829 | ] 830 | 831 | [[package]] 832 | name = "rand_chacha" 833 | version = "0.3.1" 834 | source = "registry+https://github.com/rust-lang/crates.io-index" 835 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 836 | dependencies = [ 837 | "ppv-lite86", 838 | "rand_core", 839 | ] 840 | 841 | [[package]] 842 | name = "rand_core" 843 | version = "0.6.3" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 846 | dependencies = [ 847 | "getrandom", 848 | ] 849 | 850 | [[package]] 851 | name = "rand_hc" 852 | version = "0.3.1" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" 855 | dependencies = [ 856 | "rand_core", 857 | ] 858 | 859 | [[package]] 860 | name = "redox_syscall" 861 | version = "0.2.9" 862 | source = "registry+https://github.com/rust-lang/crates.io-index" 863 | checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" 864 | dependencies = [ 865 | "bitflags", 866 | ] 867 | 868 | [[package]] 869 | name = "regex" 870 | version = "1.5.4" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" 873 | dependencies = [ 874 | "aho-corasick", 875 | "memchr", 876 | "regex-syntax", 877 | ] 878 | 879 | [[package]] 880 | name = "regex-syntax" 881 | version = "0.6.25" 882 | source = "registry+https://github.com/rust-lang/crates.io-index" 883 | checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" 884 | 885 | [[package]] 886 | name = "remove_dir_all" 887 | version = "0.5.3" 888 | source = "registry+https://github.com/rust-lang/crates.io-index" 889 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 890 | dependencies = [ 891 | "winapi", 892 | ] 893 | 894 | [[package]] 895 | name = "ryu" 896 | version = "1.0.5" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 899 | 900 | [[package]] 901 | name = "schannel" 902 | version = "0.1.19" 903 | source = "registry+https://github.com/rust-lang/crates.io-index" 904 | checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" 905 | dependencies = [ 906 | "lazy_static", 907 | "winapi", 908 | ] 909 | 910 | [[package]] 911 | name = "scopeguard" 912 | version = "1.1.0" 913 | source = "registry+https://github.com/rust-lang/crates.io-index" 914 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 915 | 916 | [[package]] 917 | name = "security-framework" 918 | version = "2.3.1" 919 | source = "registry+https://github.com/rust-lang/crates.io-index" 920 | checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467" 921 | dependencies = [ 922 | "bitflags", 923 | "core-foundation", 924 | "core-foundation-sys", 925 | "libc", 926 | "security-framework-sys", 927 | ] 928 | 929 | [[package]] 930 | name = "security-framework-sys" 931 | version = "2.3.0" 932 | source = "registry+https://github.com/rust-lang/crates.io-index" 933 | checksum = "7e4effb91b4b8b6fb7732e670b6cee160278ff8e6bf485c7805d9e319d76e284" 934 | dependencies = [ 935 | "core-foundation-sys", 936 | "libc", 937 | ] 938 | 939 | [[package]] 940 | name = "serde" 941 | version = "1.0.126" 942 | source = "registry+https://github.com/rust-lang/crates.io-index" 943 | checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" 944 | dependencies = [ 945 | "serde_derive", 946 | ] 947 | 948 | [[package]] 949 | name = "serde_derive" 950 | version = "1.0.126" 951 | source = "registry+https://github.com/rust-lang/crates.io-index" 952 | checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" 953 | dependencies = [ 954 | "proc-macro2", 955 | "quote", 956 | "syn", 957 | ] 958 | 959 | [[package]] 960 | name = "serde_json" 961 | version = "1.0.64" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" 964 | dependencies = [ 965 | "itoa", 966 | "ryu", 967 | "serde", 968 | ] 969 | 970 | [[package]] 971 | name = "sha-1" 972 | version = "0.9.6" 973 | source = "registry+https://github.com/rust-lang/crates.io-index" 974 | checksum = "8c4cfa741c5832d0ef7fab46cabed29c2aae926db0b11bb2069edd8db5e64e16" 975 | dependencies = [ 976 | "block-buffer", 977 | "cfg-if", 978 | "cpufeatures", 979 | "digest", 980 | "opaque-debug", 981 | ] 982 | 983 | [[package]] 984 | name = "signal-hook-registry" 985 | version = "1.4.0" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 988 | dependencies = [ 989 | "libc", 990 | ] 991 | 992 | [[package]] 993 | name = "slab" 994 | version = "0.4.3" 995 | source = "registry+https://github.com/rust-lang/crates.io-index" 996 | checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" 997 | 998 | [[package]] 999 | name = "smallvec" 1000 | version = "1.6.1" 1001 | source = "registry+https://github.com/rust-lang/crates.io-index" 1002 | checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" 1003 | 1004 | [[package]] 1005 | name = "socket2" 1006 | version = "0.4.0" 1007 | source = "registry+https://github.com/rust-lang/crates.io-index" 1008 | checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" 1009 | dependencies = [ 1010 | "libc", 1011 | "winapi", 1012 | ] 1013 | 1014 | [[package]] 1015 | name = "strsim" 1016 | version = "0.10.0" 1017 | source = "registry+https://github.com/rust-lang/crates.io-index" 1018 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 1019 | 1020 | [[package]] 1021 | name = "subtle" 1022 | version = "2.4.0" 1023 | source = "registry+https://github.com/rust-lang/crates.io-index" 1024 | checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" 1025 | 1026 | [[package]] 1027 | name = "syn" 1028 | version = "1.0.73" 1029 | source = "registry+https://github.com/rust-lang/crates.io-index" 1030 | checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" 1031 | dependencies = [ 1032 | "proc-macro2", 1033 | "quote", 1034 | "unicode-xid", 1035 | ] 1036 | 1037 | [[package]] 1038 | name = "tempfile" 1039 | version = "3.2.0" 1040 | source = "registry+https://github.com/rust-lang/crates.io-index" 1041 | checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" 1042 | dependencies = [ 1043 | "cfg-if", 1044 | "libc", 1045 | "rand", 1046 | "redox_syscall", 1047 | "remove_dir_all", 1048 | "winapi", 1049 | ] 1050 | 1051 | [[package]] 1052 | name = "termcolor" 1053 | version = "1.1.2" 1054 | source = "registry+https://github.com/rust-lang/crates.io-index" 1055 | checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" 1056 | dependencies = [ 1057 | "winapi-util", 1058 | ] 1059 | 1060 | [[package]] 1061 | name = "textwrap" 1062 | version = "0.12.1" 1063 | source = "registry+https://github.com/rust-lang/crates.io-index" 1064 | checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789" 1065 | dependencies = [ 1066 | "unicode-width", 1067 | ] 1068 | 1069 | [[package]] 1070 | name = "thiserror" 1071 | version = "1.0.26" 1072 | source = "registry+https://github.com/rust-lang/crates.io-index" 1073 | checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" 1074 | dependencies = [ 1075 | "thiserror-impl", 1076 | ] 1077 | 1078 | [[package]] 1079 | name = "thiserror-impl" 1080 | version = "1.0.26" 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" 1082 | checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" 1083 | dependencies = [ 1084 | "proc-macro2", 1085 | "quote", 1086 | "syn", 1087 | ] 1088 | 1089 | [[package]] 1090 | name = "time" 1091 | version = "0.1.43" 1092 | source = "registry+https://github.com/rust-lang/crates.io-index" 1093 | checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" 1094 | dependencies = [ 1095 | "libc", 1096 | "winapi", 1097 | ] 1098 | 1099 | [[package]] 1100 | name = "tinyvec" 1101 | version = "1.2.0" 1102 | source = "registry+https://github.com/rust-lang/crates.io-index" 1103 | checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" 1104 | dependencies = [ 1105 | "tinyvec_macros", 1106 | ] 1107 | 1108 | [[package]] 1109 | name = "tinyvec_macros" 1110 | version = "0.1.0" 1111 | source = "registry+https://github.com/rust-lang/crates.io-index" 1112 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 1113 | 1114 | [[package]] 1115 | name = "tokio" 1116 | version = "1.8.0" 1117 | source = "registry+https://github.com/rust-lang/crates.io-index" 1118 | checksum = "570c2eb13b3ab38208130eccd41be92520388791207fde783bda7c1e8ace28d4" 1119 | dependencies = [ 1120 | "autocfg", 1121 | "bytes", 1122 | "libc", 1123 | "memchr", 1124 | "mio", 1125 | "num_cpus", 1126 | "once_cell", 1127 | "parking_lot", 1128 | "pin-project-lite", 1129 | "signal-hook-registry", 1130 | "tokio-macros", 1131 | "winapi", 1132 | ] 1133 | 1134 | [[package]] 1135 | name = "tokio-macros" 1136 | version = "1.2.0" 1137 | source = "registry+https://github.com/rust-lang/crates.io-index" 1138 | checksum = "c49e3df43841dafb86046472506755d8501c5615673955f6aa17181125d13c37" 1139 | dependencies = [ 1140 | "proc-macro2", 1141 | "quote", 1142 | "syn", 1143 | ] 1144 | 1145 | [[package]] 1146 | name = "tokio-native-tls" 1147 | version = "0.3.0" 1148 | source = "registry+https://github.com/rust-lang/crates.io-index" 1149 | checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" 1150 | dependencies = [ 1151 | "native-tls", 1152 | "tokio", 1153 | ] 1154 | 1155 | [[package]] 1156 | name = "tokio-util" 1157 | version = "0.6.7" 1158 | source = "registry+https://github.com/rust-lang/crates.io-index" 1159 | checksum = "1caa0b0c8d94a049db56b5acf8cba99dc0623aab1b26d5b5f5e2d945846b3592" 1160 | dependencies = [ 1161 | "bytes", 1162 | "futures-core", 1163 | "futures-sink", 1164 | "log", 1165 | "pin-project-lite", 1166 | "tokio", 1167 | ] 1168 | 1169 | [[package]] 1170 | name = "tower-service" 1171 | version = "0.3.1" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" 1174 | 1175 | [[package]] 1176 | name = "tracing" 1177 | version = "0.1.26" 1178 | source = "registry+https://github.com/rust-lang/crates.io-index" 1179 | checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" 1180 | dependencies = [ 1181 | "cfg-if", 1182 | "pin-project-lite", 1183 | "tracing-core", 1184 | ] 1185 | 1186 | [[package]] 1187 | name = "tracing-core" 1188 | version = "0.1.18" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052" 1191 | dependencies = [ 1192 | "lazy_static", 1193 | ] 1194 | 1195 | [[package]] 1196 | name = "try-lock" 1197 | version = "0.2.3" 1198 | source = "registry+https://github.com/rust-lang/crates.io-index" 1199 | checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" 1200 | 1201 | [[package]] 1202 | name = "twitter" 1203 | version = "1.0.0" 1204 | dependencies = [ 1205 | "clap", 1206 | "egg-mode", 1207 | "futures", 1208 | "serde", 1209 | "serde_json", 1210 | "tokio", 1211 | ] 1212 | 1213 | [[package]] 1214 | name = "typenum" 1215 | version = "1.13.0" 1216 | source = "registry+https://github.com/rust-lang/crates.io-index" 1217 | checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" 1218 | 1219 | [[package]] 1220 | name = "unicode-bidi" 1221 | version = "0.3.5" 1222 | source = "registry+https://github.com/rust-lang/crates.io-index" 1223 | checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" 1224 | dependencies = [ 1225 | "matches", 1226 | ] 1227 | 1228 | [[package]] 1229 | name = "unicode-normalization" 1230 | version = "0.1.19" 1231 | source = "registry+https://github.com/rust-lang/crates.io-index" 1232 | checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" 1233 | dependencies = [ 1234 | "tinyvec", 1235 | ] 1236 | 1237 | [[package]] 1238 | name = "unicode-segmentation" 1239 | version = "1.8.0" 1240 | source = "registry+https://github.com/rust-lang/crates.io-index" 1241 | checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" 1242 | 1243 | [[package]] 1244 | name = "unicode-width" 1245 | version = "0.1.8" 1246 | source = "registry+https://github.com/rust-lang/crates.io-index" 1247 | checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" 1248 | 1249 | [[package]] 1250 | name = "unicode-xid" 1251 | version = "0.2.2" 1252 | source = "registry+https://github.com/rust-lang/crates.io-index" 1253 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 1254 | 1255 | [[package]] 1256 | name = "url" 1257 | version = "2.2.2" 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" 1259 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" 1260 | dependencies = [ 1261 | "form_urlencoded", 1262 | "idna", 1263 | "matches", 1264 | "percent-encoding", 1265 | ] 1266 | 1267 | [[package]] 1268 | name = "vcpkg" 1269 | version = "0.2.15" 1270 | source = "registry+https://github.com/rust-lang/crates.io-index" 1271 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 1272 | 1273 | [[package]] 1274 | name = "vec_map" 1275 | version = "0.8.2" 1276 | source = "registry+https://github.com/rust-lang/crates.io-index" 1277 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 1278 | 1279 | [[package]] 1280 | name = "version_check" 1281 | version = "0.9.3" 1282 | source = "registry+https://github.com/rust-lang/crates.io-index" 1283 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 1284 | 1285 | [[package]] 1286 | name = "want" 1287 | version = "0.3.0" 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" 1289 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 1290 | dependencies = [ 1291 | "log", 1292 | "try-lock", 1293 | ] 1294 | 1295 | [[package]] 1296 | name = "wasi" 1297 | version = "0.10.2+wasi-snapshot-preview1" 1298 | source = "registry+https://github.com/rust-lang/crates.io-index" 1299 | checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" 1300 | 1301 | [[package]] 1302 | name = "wasm-bindgen" 1303 | version = "0.2.74" 1304 | source = "registry+https://github.com/rust-lang/crates.io-index" 1305 | checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" 1306 | dependencies = [ 1307 | "cfg-if", 1308 | "wasm-bindgen-macro", 1309 | ] 1310 | 1311 | [[package]] 1312 | name = "wasm-bindgen-backend" 1313 | version = "0.2.74" 1314 | source = "registry+https://github.com/rust-lang/crates.io-index" 1315 | checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" 1316 | dependencies = [ 1317 | "bumpalo", 1318 | "lazy_static", 1319 | "log", 1320 | "proc-macro2", 1321 | "quote", 1322 | "syn", 1323 | "wasm-bindgen-shared", 1324 | ] 1325 | 1326 | [[package]] 1327 | name = "wasm-bindgen-macro" 1328 | version = "0.2.74" 1329 | source = "registry+https://github.com/rust-lang/crates.io-index" 1330 | checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" 1331 | dependencies = [ 1332 | "quote", 1333 | "wasm-bindgen-macro-support", 1334 | ] 1335 | 1336 | [[package]] 1337 | name = "wasm-bindgen-macro-support" 1338 | version = "0.2.74" 1339 | source = "registry+https://github.com/rust-lang/crates.io-index" 1340 | checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" 1341 | dependencies = [ 1342 | "proc-macro2", 1343 | "quote", 1344 | "syn", 1345 | "wasm-bindgen-backend", 1346 | "wasm-bindgen-shared", 1347 | ] 1348 | 1349 | [[package]] 1350 | name = "wasm-bindgen-shared" 1351 | version = "0.2.74" 1352 | source = "registry+https://github.com/rust-lang/crates.io-index" 1353 | checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" 1354 | 1355 | [[package]] 1356 | name = "web-sys" 1357 | version = "0.3.51" 1358 | source = "registry+https://github.com/rust-lang/crates.io-index" 1359 | checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" 1360 | dependencies = [ 1361 | "js-sys", 1362 | "wasm-bindgen", 1363 | ] 1364 | 1365 | [[package]] 1366 | name = "webbrowser" 1367 | version = "0.5.5" 1368 | source = "registry+https://github.com/rust-lang/crates.io-index" 1369 | checksum = "ecad156490d6b620308ed411cfee90d280b3cbd13e189ea0d3fada8acc89158a" 1370 | dependencies = [ 1371 | "web-sys", 1372 | "widestring", 1373 | "winapi", 1374 | ] 1375 | 1376 | [[package]] 1377 | name = "widestring" 1378 | version = "0.4.3" 1379 | source = "registry+https://github.com/rust-lang/crates.io-index" 1380 | checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" 1381 | 1382 | [[package]] 1383 | name = "winapi" 1384 | version = "0.3.9" 1385 | source = "registry+https://github.com/rust-lang/crates.io-index" 1386 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1387 | dependencies = [ 1388 | "winapi-i686-pc-windows-gnu", 1389 | "winapi-x86_64-pc-windows-gnu", 1390 | ] 1391 | 1392 | [[package]] 1393 | name = "winapi-i686-pc-windows-gnu" 1394 | version = "0.4.0" 1395 | source = "registry+https://github.com/rust-lang/crates.io-index" 1396 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1397 | 1398 | [[package]] 1399 | name = "winapi-util" 1400 | version = "0.1.5" 1401 | source = "registry+https://github.com/rust-lang/crates.io-index" 1402 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 1403 | dependencies = [ 1404 | "winapi", 1405 | ] 1406 | 1407 | [[package]] 1408 | name = "winapi-x86_64-pc-windows-gnu" 1409 | version = "0.4.0" 1410 | source = "registry+https://github.com/rust-lang/crates.io-index" 1411 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1412 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["get_keys", "twitter"] 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2016 steenuil 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mpv-livetweet 2 | 3 | Be that dick who tweets screenshots of their favourite anime spoiling everyone **without even having to leave your player!** 4 | 5 | > _"whoa, integrated tweeting in movie players. The relentless march of progress"_ - **[@jons520](https://twitter.com/jons520/status/611668022902697984)** 6 | 7 | > _"lol straight to twitter, your followers probably hate you"_ - **[ChrisK2](https://github.com/ChrisK2)** 8 | 9 | > _"you're creating a monster"_ - **Cidoku** 10 | 11 | ### Features 12 | 13 | - Text adding 14 | - Multi-screenshot drifting 15 | - Annie-May hashtag retrieving 16 | 17 | ## Usage 18 | 19 | Create your config using the `get_keys` binary. A browser window will open and you'll get a code after clicking Authorize. Write the code into the terminal and a file called `mpv-livetweet.conf` will be created. 20 | 21 | Create a folder called `script-opts` in your mpv config folder (the one containing `mpv.conf`) and move the `mpv-livetweet.conf` file into it. 22 | 23 | Copy the `twitter` binary somewhere and copy its path. 24 | 25 | Open `mpv-livetweet.conf` and configure the path to `curl` and to the `twitter` binary. 26 | 27 | ``` 28 | # On Windows 10 curl_path is C:\Windows\SysWOW64\curl.exe 29 | curl_path=/path/to/curl 30 | twitter_path=/path/to/twitter/binary 31 | ``` 32 | 33 | Copy `mpv-livetweet.lua` to the `scripts` folder in your mpv config folder. 34 | 35 | Download [`user-input.lua`](https://raw.githubusercontent.com/CogentRedTester/mpv-user-input/master/user-input.lua) and save it to the `scripts` folder in your mpv config folder. 36 | 37 | The script tries to fetch the hashtag of the anime you're currently watching with the AniList API and appends it to the tweet text. If you don't want it to be fetched, set the `fetch_hashtag` option to `no` in the config file. 38 | 39 | ``` 40 | fetch_hashtag=no 41 | ``` 42 | 43 | By default the script sends tweets as a reply to the last tweet it sent during the same session. You can clear the last tweet ID by exiting the player, using the keybind, or you can disable this functionality by setting the `as_reply` option to `no` in the config file. 44 | 45 | ``` 46 | as_reply=no 47 | ``` 48 | 49 | ## Commands 50 | 51 | | Shortcut | When queue is empty | With screenshots in queue | 52 | | --------- | ------------------------------ | ------------------------- | 53 | | **Alt+s** | Queue a screenshot | Queue a screenshot | 54 | | **Alt+t** | Take a screenshot and tweet it | Tweet queued screenshots | 55 | | **Alt+c** | - | Delete queued screenshots | 56 | | **Alt+x** | Clear the last tweet ID | Clear the last tweet ID | 57 | 58 | The keybinds can be changed in the config file. 59 | 60 | ``` 61 | keybind_queue_screenshot=Alt+s 62 | keybind_tweet=Alt+t 63 | keybind_cancel=Alt+c 64 | keybind_clear_reply=Alt+x 65 | ``` 66 | 67 | To increase the font size of the tweet input (which is really tiny by default), create a file called `user-input.conf` in the `script-opts` folder and set the `font_size` option to your preferred size. The default is `16`. 68 | 69 | ``` 70 | font_size=24 71 | ``` 72 | 73 | ### From source 74 | 75 | Acquire a consumer API key and secret from a twitter app, either from an existing one or by creating your own on https://developer.twitter.com/en/apps. 76 | 77 | Compile the `twitter` and `get_keys` crates with Rust with the CONSUMER_KEY and CONSUMER_SECRET env variables set to the tokens you acquired. 78 | 79 | ``` 80 | CONSUMER_KEY=foo CONSUMER_SECRET=bar cargo build --release 81 | ``` 82 | 83 | Or on Powershell: 84 | 85 | ``` 86 | $ENV:CONSUMER_KEY="foo"; $ENV:CONSUMER_SECRET="bar"; cargo build --release 87 | ``` 88 | 89 | --- 90 | 91 | Excessive use of the script might cause butthurt and follower loss. Use responsibly and in small doses. 92 | -------------------------------------------------------------------------------- /get_keys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["steinuil "] 3 | edition = "2018" 4 | name = "get_keys" 5 | version = "1.0.0" 6 | 7 | [dependencies] 8 | clap = "3.0.0-beta.2" 9 | egg-mode = {git = "https://github.com/egg-mode-rs/egg-mode", rev = "6b81073eba9"} 10 | tokio = {version = "1.8", features = ["full"]} 11 | webbrowser = "0.5" 12 | -------------------------------------------------------------------------------- /get_keys/src/main.rs: -------------------------------------------------------------------------------- 1 | use clap::Clap; 2 | use tokio::io::AsyncBufReadExt; 3 | 4 | #[derive(Clap)] 5 | struct Config { 6 | #[clap(long, default_value = "mpv-livetweet.conf")] 7 | out_file: String, 8 | } 9 | 10 | #[tokio::main] 11 | async fn main() { 12 | let config = Config::parse(); 13 | 14 | let consumer_token = 15 | egg_mode::KeyPair::new(std::env!("CONSUMER_KEY"), std::env!("CONSUMER_SECRET")); 16 | let request_token = egg_mode::auth::request_token(&consumer_token, "oob") 17 | .await 18 | .unwrap(); 19 | let auth_url = egg_mode::auth::authorize_url(&request_token); 20 | 21 | if let Err(_) = webbrowser::open(&auth_url) { 22 | println!("Go to this URL on your browser:"); 23 | println!("{}", &auth_url); 24 | } 25 | 26 | let mut verifier = String::new(); 27 | 28 | println!("Enter the pin:"); 29 | 30 | tokio::io::BufReader::new(tokio::io::stdin()) 31 | .read_line(&mut verifier) 32 | .await 33 | .unwrap(); 34 | 35 | let (token, _, _) = egg_mode::auth::access_token(consumer_token, &request_token, &verifier) 36 | .await 37 | .unwrap(); 38 | 39 | let (consumer_token, access_token) = match token { 40 | egg_mode::auth::Token::Bearer(_) => unreachable!(), 41 | egg_mode::auth::Token::Access { consumer, access } => (consumer, access), 42 | }; 43 | 44 | let mpv_livetweet_conf = format!( 45 | "consumer_key={}\nconsumer_secret={}\naccess_token_key={}\naccess_token_secret={}\n", 46 | consumer_token.key, consumer_token.secret, access_token.key, access_token.secret 47 | ); 48 | 49 | tokio::fs::write(&config.out_file, mpv_livetweet_conf) 50 | .await 51 | .unwrap(); 52 | 53 | println!("Tokens saved to {}", config.out_file); 54 | } 55 | -------------------------------------------------------------------------------- /mpv-livetweet.lua: -------------------------------------------------------------------------------- 1 | local mp = require("mp") 2 | local mp_options = require("mp.options") 3 | local utils = require("mp.utils") 4 | 5 | local options = { 6 | keybind_queue_screenshot = "Alt+s", 7 | keybind_tweet = "Alt+t", 8 | keybind_cancel = "Alt+c", 9 | keybind_clear_reply = "Alt+x", 10 | fetch_hashtag = true, 11 | as_reply = true, 12 | curl_path = "", 13 | twitter_path = "", 14 | consumer_key = "", 15 | consumer_secret = "", 16 | access_token_key = "", 17 | access_token_secret = "", 18 | } 19 | 20 | mp_options.read_options(options, "mpv-livetweet") 21 | 22 | -- Utils 23 | 24 | local function trim(str) 25 | str = str:gsub('^%s+', '') 26 | str = str:gsub('%s+$', '') 27 | return str 28 | end 29 | 30 | local function escape(str) 31 | str = str:gsub('\\', '\\\\') 32 | str = str:gsub('"', '\\"') 33 | if str:len() > 0 then 34 | return str 35 | else 36 | -- Whatever shell is used on Windows doesn't like empty string arguments, apparently 37 | return " " 38 | end 39 | end 40 | 41 | -- Get tweet input 42 | 43 | local USER_INPUT_COUNTER = 1 44 | 45 | -- sends a request to ask the user for input using formatted options provided 46 | -- creates a script message to recieve the response and call fn 47 | local function get_user_input(fn, options) 48 | options = options or {} 49 | local name = mp.get_script_name() 50 | local response_string = name.."/__user_input_request/"..USER_INPUT_COUNTER 51 | USER_INPUT_COUNTER = USER_INPUT_COUNTER + 1 52 | 53 | -- create a callback for user-input to respond to 54 | mp.register_script_message(response_string, function(input, err) 55 | mp.unregister_script_message(response_string) 56 | fn(err == "" and input or nil, err) 57 | end) 58 | 59 | -- send the input command 60 | mp.commandv("script-message-to", "user_input", "request-user-input", 61 | response_string, 62 | name .. '/' .. (options.id or ""), -- id code for the request 63 | "["..(options.source or name).."] "..(options.request_text or options.text or ("requesting user input:")), 64 | options.default_input or "", 65 | options.queueable and "1" or "", 66 | options.replace and "1" or "" 67 | ) 68 | end 69 | 70 | local function system(args) 71 | local cmd = io.popen(args, "r") 72 | local body = cmd:read('*a') 73 | cmd:close() 74 | return body 75 | end 76 | 77 | -- Fetch hashtag from AniList 78 | 79 | local SCREENSHOT_QUEUE = {} 80 | local SCREENSHOT_LIMIT = 4 81 | 82 | local function approximate_show_name() 83 | local patterns_to_remove = { 84 | "%.%a+$", -- extension 85 | "%b[]", -- anything between brackets 86 | "%b()", -- anything between parenthesis 87 | "%d%d%a?%d?", -- episode number and version 88 | "[sS]pecial%a?" 89 | } 90 | local patterns_to_clear = { '_', '[^a-zA-Z0-9]', '%s+' } 91 | 92 | local query = mp.get_property("filename") 93 | 94 | for _, pattern in ipairs(patterns_to_remove) do 95 | query = query:gsub(pattern, '') 96 | end 97 | for _, pattern in ipairs(patterns_to_clear) do 98 | query = query:gsub(pattern, ' ') 99 | end 100 | 101 | return trim(query) 102 | end 103 | 104 | local HASHTAG_QUERY = 'query ($name: String) { Media(search: $name, type: ANIME) { hashtag } }' 105 | 106 | local HASHTAGS_CACHE = {} 107 | 108 | local function get_show_hashtag() 109 | local query = approximate_show_name() 110 | 111 | if HASHTAGS_CACHE[query] then 112 | return HASHTAGS_CACHE[query] 113 | end 114 | 115 | local body = utils.format_json({ 116 | query = HASHTAG_QUERY, 117 | variables = { name = query }, 118 | }) 119 | 120 | local response = utils.parse_json(system( 121 | options.curl_path .. 122 | " -s" .. 123 | " -X POST" .. 124 | ' -H "Content-Type: application/json"' .. 125 | ' -H "Accept: application/json"' .. 126 | ' --data "' .. escape(body) .. '"' .. 127 | " https://graphql.anilist.co/" 128 | )) 129 | 130 | local hashtag = 131 | response 132 | and response.data 133 | and response.data.Media 134 | and response.data.Media.hashtag 135 | 136 | if hashtag ~= nil then 137 | HASHTAGS_CACHE[query] = hashtag 138 | end 139 | 140 | return hashtag 141 | end 142 | 143 | -- Handle screenshot files 144 | 145 | local function file_exists(name) 146 | local f = io.open(name, "r") 147 | if f == nil then return false end 148 | f:close() 149 | return true 150 | end 151 | 152 | local function queue_screenshot() 153 | if #SCREENSHOT_QUEUE >= SCREENSHOT_LIMIT then 154 | mp.osd_message("Queue full, screenshot not taken") 155 | return 156 | end 157 | 158 | local dir = 159 | os.getenv("TMPDIR") or 160 | os.getenv("TEMP") or 161 | os.getenv("HOME") or 162 | os.getenv("USERPROFILE") or 163 | "" 164 | 165 | local shot = utils.join_path( 166 | dir, 167 | "mpv-livetweet-screenshot-" .. tostring(os.time()) .. ".jpg" 168 | ) 169 | if file_exists(shot) then 170 | mp.commandv("File already exists, screenshot not taken") 171 | return 172 | end 173 | 174 | SCREENSHOT_QUEUE[#SCREENSHOT_QUEUE + 1] = shot 175 | 176 | mp.commandv("screenshot_to_file", shot, "subtitles") 177 | mp.osd_message("Queued screenshot " .. tostring(#SCREENSHOT_QUEUE) .. " of 4") 178 | end 179 | 180 | local function delete_queued_screenshots() 181 | for _, shot in ipairs(SCREENSHOT_QUEUE) do 182 | os.remove(shot) 183 | end 184 | SCREENSHOT_QUEUE = {} 185 | end 186 | 187 | mp.register_event("shutdown", delete_queued_screenshots) 188 | 189 | -- Tweet 190 | 191 | local LAST_TWEET_ID = nil 192 | 193 | local function clear_reply() 194 | if options.as_reply then 195 | mp.osd_message("The next tweet will not be a reply") 196 | LAST_TWEET_ID = nil 197 | end 198 | end 199 | 200 | local function send_tweet(text) 201 | local cmd = options.twitter_path .. 202 | " --consumer-key " .. options.consumer_key .. 203 | " --consumer-secret " .. options.consumer_secret .. 204 | " --access-token-key " .. options.access_token_key .. 205 | " --access-token-secret " .. options.access_token_secret .. 206 | ' --status "' .. escape(text) .. '"' 207 | 208 | if options.as_reply and LAST_TWEET_ID ~= nil then 209 | cmd = cmd .. " --reply-to " .. tostring(LAST_TWEET_ID) 210 | end 211 | 212 | for _, filename in ipairs(SCREENSHOT_QUEUE) do 213 | cmd = cmd .. ' --file "' .. escape(filename) .. '"' 214 | end 215 | 216 | local result = utils.parse_json(system(cmd)) 217 | 218 | if not result then print(cmd) end 219 | 220 | return result or { type = "Failure", error = "Couldn't read the screenshot files" } 221 | end 222 | 223 | local function tweet() 224 | local hashtag = options.fetch_hashtag and get_show_hashtag() or nil 225 | 226 | if #SCREENSHOT_QUEUE == 0 then 227 | queue_screenshot() 228 | end 229 | 230 | local input_text = "Tweeting with " .. tostring(#SCREENSHOT_QUEUE) .. " screenshots" 231 | if options.as_reply and LAST_TWEET_ID ~= nil then 232 | input_text = input_text .. " replying to tweet ID " .. tostring(LAST_TWEET_ID) 233 | end 234 | 235 | get_user_input( 236 | function(text) 237 | if text ~= nil then 238 | local result = send_tweet(trim(text)) 239 | 240 | if result.type == "Success" then 241 | delete_queued_screenshots() 242 | LAST_TWEET_ID = result.id 243 | mp.osd_message("Tweet posted to " .. result.url) 244 | else 245 | mp.osd_message("Error: " .. result.error) 246 | end 247 | end 248 | end, 249 | { 250 | text = input_text, 251 | default_input = hashtag and (' ' .. hashtag) 252 | } 253 | ) 254 | end 255 | 256 | -- Cancel 257 | 258 | local function cancel() 259 | if #SCREENSHOT_QUEUE == 0 then return end 260 | mp.osd_message("Deleting queued screenshots") 261 | delete_queued_screenshots() 262 | end 263 | 264 | -- Register keybindings 265 | 266 | mp.add_key_binding(options.keybind_queue_screenshot, queue_screenshot) 267 | mp.add_key_binding(options.keybind_tweet, tweet) 268 | mp.add_key_binding(options.keybind_cancel, cancel) 269 | mp.add_key_binding(options.keybind_clear_reply, clear_reply) 270 | -------------------------------------------------------------------------------- /twitter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["steinuil "] 3 | edition = "2018" 4 | name = "twitter" 5 | version = "1.0.0" 6 | 7 | [dependencies] 8 | clap = "3.0.0-beta.2" 9 | egg-mode = {git = "https://github.com/egg-mode-rs/egg-mode", rev = "6b81073eba9"} 10 | futures = "0.3" 11 | serde = "1.0" 12 | serde_json = "1.0" 13 | tokio = {version = "1.8", features = ["full"]} 14 | -------------------------------------------------------------------------------- /twitter/src/main.rs: -------------------------------------------------------------------------------- 1 | use clap::Clap; 2 | use serde::Serialize; 3 | 4 | #[derive(Clap)] 5 | struct Config { 6 | #[clap(long)] 7 | consumer_key: String, 8 | 9 | #[clap(long)] 10 | consumer_secret: String, 11 | 12 | #[clap(long)] 13 | access_token_key: String, 14 | 15 | #[clap(long)] 16 | access_token_secret: String, 17 | 18 | #[clap(long)] 19 | status: String, 20 | 21 | #[clap(long, multiple = true)] 22 | file: Vec, 23 | 24 | #[clap(long)] 25 | reply_to: Option, 26 | } 27 | 28 | #[derive(Serialize)] 29 | #[serde(tag = "type")] 30 | enum TweetResult { 31 | Success { id: String, url: String }, 32 | Failure { error: String }, 33 | } 34 | 35 | async fn send_tweet(config: Config) -> Result { 36 | let token = egg_mode::Token::Access { 37 | consumer: egg_mode::KeyPair::new(config.consumer_key, config.consumer_secret), 38 | access: egg_mode::KeyPair::new(config.access_token_key, config.access_token_secret), 39 | }; 40 | 41 | let media_handles = futures::future::try_join_all(config.file.iter().map(|filename| { 42 | let token = token.clone(); 43 | async move { 44 | let buf = tokio::fs::read(&filename).await?; 45 | egg_mode::media::upload_media(&buf, &egg_mode::media::media_types::image_jpg(), &token) 46 | .await 47 | } 48 | })) 49 | .await 50 | .unwrap(); 51 | 52 | let mut draft = egg_mode::tweet::DraftTweet::new(config.status); 53 | 54 | draft.in_reply_to = config.reply_to; 55 | 56 | for handle in media_handles { 57 | draft.add_media(handle.id); 58 | } 59 | 60 | let tweet = draft.send(&token).await.unwrap().response; 61 | 62 | Ok(tweet) 63 | } 64 | 65 | #[tokio::main] 66 | async fn main() { 67 | let config = Config::parse(); 68 | 69 | let result = match send_tweet(config).await { 70 | Ok(tweet) => TweetResult::Success { 71 | id: tweet.id.to_string(), 72 | url: format!( 73 | "https://twitter.com/{}/status/{}", 74 | tweet.user.unwrap().screen_name, 75 | tweet.id 76 | ), 77 | }, 78 | Err(error) => TweetResult::Failure { 79 | error: error.to_string(), 80 | }, 81 | }; 82 | 83 | print!("{}", serde_json::to_string(&result).unwrap()) 84 | } 85 | --------------------------------------------------------------------------------