├── .appveyor ├── linux.yml └── windows.yml ├── .editorconfig ├── .gitignore ├── .rustfmt.toml ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src ├── action.rs ├── builtins.rs └── main.rs /.appveyor/linux.yml: -------------------------------------------------------------------------------- 1 | version: 0.1.{build} 2 | image: Ubuntu2004 3 | platform: x64 4 | clone_depth: 1 5 | branches: 6 | only: 7 | # Release tags 8 | - /^v\d+\.\d+\.\d+.*$/ 9 | - master 10 | - develop 11 | 12 | environment: 13 | PATH: /home/appveyor/.rvm/gems/ruby-2.0.0-p648/bin:/home/appveyor/.rvm/gems/ruby-2.0.0-p648@global/bin:/home/appveyor/.rvm/rubies/ruby-2.0.0-p648/bin:/usr/lib/jvm/java-9-openjdk-amd64/bin:/home/appveyor/.gvm/bin:/home/appveyor/.gvm/bin:/home/appveyor/.nvm/versions/node/v4.9.1/bin:/opt/appveyor/build-agent:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin:/home/appveyor/.dotnet/tools:/home/appveyor/.rvm/bin:/home/appveyor/.rvm/bin:/opt/mssql-tools/bin:/home/appveyor/.cargo/bin 14 | UPLOAD_TOKEN: 15 | secure: A8qR1te5wOhuRo3hrlfcGF6hnBuudYiA8kusdZJQhj8= 16 | 17 | cache: 18 | - /home/appveyor/.cargo 19 | 20 | install: 21 | - sh: curl https://sh.rustup.rs -sSf | sh -s -- -y 22 | - rustc -Vv 23 | - cargo -V 24 | 25 | build_script: 26 | - cargo check 27 | - cargo build --release 28 | 29 | test_script: 30 | - cargo test 31 | 32 | #deploy_script: 33 | #- ps: >- 34 | # if(${env:UPLOAD_TOKEN}) { 35 | # cd /home/appveyor/projects/simplebot/target/release/ 36 | # Compress-Archive -Force -Path ./simple-bot -DestinationPath SimpleBot.zip 37 | # Invoke-RestMethod -Uri "https://splamy.de/api/nightly/simplebot/${env:APPVEYOR_REPO_BRANCH}_linux?filename=SimpleBot.zip&commit=${env:APPVEYOR_REPO_COMMIT}&version=0.1.0" -Headers @{ "Content-Type" = "application/zip"; "Authorization" = "${env:UPLOAD_TOKEN}" } -Method Put -InFile ./SimpleBot.zip 38 | # } 39 | -------------------------------------------------------------------------------- /.appveyor/windows.yml: -------------------------------------------------------------------------------- 1 | version: 0.1.{build} 2 | image: Visual Studio 2022 3 | platform: x64 4 | clone_depth: 1 5 | clone_folder: C:\projects\simple-bot 6 | branches: 7 | only: 8 | # Release tags 9 | - /^v\d+\.\d+\.\d+.*$/ 10 | - master 11 | - develop 12 | 13 | environment: 14 | UPLOAD_TOKEN: 15 | secure: A8qR1te5wOhuRo3hrlfcGF6hnBuudYiA8kusdZJQhj8= 16 | global: 17 | CHANNEL: stable 18 | TARGET: x86_64-pc-windows-msvc 19 | 20 | cache: 21 | - C:\Users\appveyor\.cargo\registry 22 | 23 | install: 24 | - ps: $Env:PATH += ';C:\msys64\usr\bin' 25 | - curl -sSf -o rustup-init.exe https://win.rustup.rs/ 26 | - rustup-init.exe -y --default-host %TARGET% --default-toolchain %CHANNEL% 27 | - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin 28 | - rustc -Vv 29 | - cargo -V 30 | 31 | build_script: 32 | - cargo check 33 | - cargo build --release 34 | 35 | test_script: 36 | - cargo test 37 | 38 | #deploy_script: 39 | #- ps: >- 40 | # if(${env:UPLOAD_TOKEN}) { 41 | # cd([io.path]::combine("${env:APPVEYOR_BUILD_FOLDER}", "target", "release")) 42 | # Compress-Archive -Force -Path simple-bot.exe -DestinationPath SimpleBot.zip 43 | # Invoke-RestMethod -Uri "https://splamy.de/api/nightly/simplebot/${env:APPVEYOR_REPO_BRANCH}_windows?filename=SimpleBot.zip&commit=${env:APPVEYOR_REPO_COMMIT}&version=0.1.0" -Headers @{ "Content-Type" = "application/zip"; "Authorization" = "${env:UPLOAD_TOKEN}" } -Method Put -InFile ./SimpleBot.zip 44 | # } 45 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | indent_style = tab 8 | trim_trailing_whitespace=true 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | private.key 3 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | 3 | hard_tabs = true 4 | fn_single_line = true 5 | format_strings = true 6 | use_try_shorthand = true 7 | where_single_line = true 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | ### Added 9 | - Rate limiting responses: Can be accessed by `rate_limit` in the settings 10 | 11 | ### Changed 12 | - Update tsclientlib 13 | -------------------------------------------------------------------------------- /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 = "aead" 7 | version = "0.5.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" 10 | dependencies = [ 11 | "crypto-common", 12 | "generic-array", 13 | ] 14 | 15 | [[package]] 16 | name = "aes" 17 | version = "0.8.2" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" 20 | dependencies = [ 21 | "cfg-if", 22 | "cipher", 23 | "cpufeatures", 24 | ] 25 | 26 | [[package]] 27 | name = "aho-corasick" 28 | version = "0.7.20" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" 31 | dependencies = [ 32 | "memchr", 33 | ] 34 | 35 | [[package]] 36 | name = "anstream" 37 | version = "0.3.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371" 40 | dependencies = [ 41 | "anstyle", 42 | "anstyle-parse", 43 | "anstyle-query", 44 | "anstyle-wincon", 45 | "colorchoice", 46 | "is-terminal", 47 | "utf8parse", 48 | ] 49 | 50 | [[package]] 51 | name = "anstyle" 52 | version = "1.0.0" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" 55 | 56 | [[package]] 57 | name = "anstyle-parse" 58 | version = "0.2.0" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" 61 | dependencies = [ 62 | "utf8parse", 63 | ] 64 | 65 | [[package]] 66 | name = "anstyle-query" 67 | version = "1.0.0" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" 70 | dependencies = [ 71 | "windows-sys 0.48.0", 72 | ] 73 | 74 | [[package]] 75 | name = "anstyle-wincon" 76 | version = "1.0.0" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd" 79 | dependencies = [ 80 | "anstyle", 81 | "windows-sys 0.48.0", 82 | ] 83 | 84 | [[package]] 85 | name = "anyhow" 86 | version = "1.0.70" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" 89 | 90 | [[package]] 91 | name = "arrayvec" 92 | version = "0.5.2" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" 95 | 96 | [[package]] 97 | name = "async-trait" 98 | version = "0.1.68" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" 101 | dependencies = [ 102 | "proc-macro2", 103 | "quote", 104 | "syn 2.0.15", 105 | ] 106 | 107 | [[package]] 108 | name = "autocfg" 109 | version = "1.1.0" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 112 | 113 | [[package]] 114 | name = "base16ct" 115 | version = "0.1.1" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" 118 | 119 | [[package]] 120 | name = "base64" 121 | version = "0.13.1" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 124 | 125 | [[package]] 126 | name = "base64" 127 | version = "0.21.0" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" 130 | 131 | [[package]] 132 | name = "base64ct" 133 | version = "1.6.0" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" 136 | 137 | [[package]] 138 | name = "bit-vec" 139 | version = "0.6.3" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" 142 | 143 | [[package]] 144 | name = "bitflags" 145 | version = "1.3.2" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 148 | 149 | [[package]] 150 | name = "block-buffer" 151 | version = "0.10.4" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 154 | dependencies = [ 155 | "generic-array", 156 | ] 157 | 158 | [[package]] 159 | name = "bumpalo" 160 | version = "3.12.0" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" 163 | 164 | [[package]] 165 | name = "byteorder" 166 | version = "1.4.3" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 169 | 170 | [[package]] 171 | name = "bytes" 172 | version = "1.4.0" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" 175 | 176 | [[package]] 177 | name = "cc" 178 | version = "1.0.79" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 181 | 182 | [[package]] 183 | name = "cfg-if" 184 | version = "1.0.0" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 187 | 188 | [[package]] 189 | name = "cipher" 190 | version = "0.4.4" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" 193 | dependencies = [ 194 | "crypto-common", 195 | "inout", 196 | ] 197 | 198 | [[package]] 199 | name = "clap" 200 | version = "4.2.2" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "9b802d85aaf3a1cdb02b224ba472ebdea62014fccfcb269b95a4d76443b5ee5a" 203 | dependencies = [ 204 | "clap_builder", 205 | "clap_derive", 206 | "once_cell", 207 | ] 208 | 209 | [[package]] 210 | name = "clap_builder" 211 | version = "4.2.2" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "14a1a858f532119338887a4b8e1af9c60de8249cd7bafd68036a489e261e37b6" 214 | dependencies = [ 215 | "anstream", 216 | "anstyle", 217 | "bitflags", 218 | "clap_lex", 219 | "strsim", 220 | ] 221 | 222 | [[package]] 223 | name = "clap_derive" 224 | version = "4.2.0" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" 227 | dependencies = [ 228 | "heck", 229 | "proc-macro2", 230 | "quote", 231 | "syn 2.0.15", 232 | ] 233 | 234 | [[package]] 235 | name = "clap_lex" 236 | version = "0.4.1" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" 239 | 240 | [[package]] 241 | name = "cmac" 242 | version = "0.7.2" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "8543454e3c3f5126effff9cd44d562af4e31fb8ce1cc0d3dcd8f084515dbc1aa" 245 | dependencies = [ 246 | "cipher", 247 | "dbl", 248 | "digest 0.10.6", 249 | ] 250 | 251 | [[package]] 252 | name = "colorchoice" 253 | version = "1.0.0" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 256 | 257 | [[package]] 258 | name = "const-oid" 259 | version = "0.9.2" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" 262 | 263 | [[package]] 264 | name = "core-foundation" 265 | version = "0.9.3" 266 | source = "registry+https://github.com/rust-lang/crates.io-index" 267 | checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" 268 | dependencies = [ 269 | "core-foundation-sys", 270 | "libc", 271 | ] 272 | 273 | [[package]] 274 | name = "core-foundation-sys" 275 | version = "0.8.4" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" 278 | 279 | [[package]] 280 | name = "cpufeatures" 281 | version = "0.2.6" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" 284 | dependencies = [ 285 | "libc", 286 | ] 287 | 288 | [[package]] 289 | name = "crypto-bigint" 290 | version = "0.4.9" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" 293 | dependencies = [ 294 | "generic-array", 295 | "rand_core", 296 | "subtle", 297 | "zeroize", 298 | ] 299 | 300 | [[package]] 301 | name = "crypto-common" 302 | version = "0.1.6" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 305 | dependencies = [ 306 | "generic-array", 307 | "rand_core", 308 | "typenum", 309 | ] 310 | 311 | [[package]] 312 | name = "csv" 313 | version = "1.2.1" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "0b015497079b9a9d69c02ad25de6c0a6edef051ea6360a327d0bd05802ef64ad" 316 | dependencies = [ 317 | "csv-core", 318 | "itoa", 319 | "ryu", 320 | "serde", 321 | ] 322 | 323 | [[package]] 324 | name = "csv-core" 325 | version = "0.1.10" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" 328 | dependencies = [ 329 | "memchr", 330 | ] 331 | 332 | [[package]] 333 | name = "ctr" 334 | version = "0.9.2" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" 337 | dependencies = [ 338 | "cipher", 339 | ] 340 | 341 | [[package]] 342 | name = "curve25519-dalek-ng" 343 | version = "4.1.1" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "1c359b7249347e46fb28804470d071c921156ad62b3eef5d34e2ba867533dec8" 346 | dependencies = [ 347 | "byteorder", 348 | "digest 0.9.0", 349 | "rand_core", 350 | "subtle-ng", 351 | "zeroize", 352 | ] 353 | 354 | [[package]] 355 | name = "data-encoding" 356 | version = "2.3.3" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" 359 | 360 | [[package]] 361 | name = "dbl" 362 | version = "0.3.2" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "bd2735a791158376708f9347fe8faba9667589d82427ef3aed6794a8981de3d9" 365 | dependencies = [ 366 | "generic-array", 367 | ] 368 | 369 | [[package]] 370 | name = "der" 371 | version = "0.6.1" 372 | source = "registry+https://github.com/rust-lang/crates.io-index" 373 | checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" 374 | dependencies = [ 375 | "const-oid", 376 | "zeroize", 377 | ] 378 | 379 | [[package]] 380 | name = "digest" 381 | version = "0.9.0" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" 384 | dependencies = [ 385 | "generic-array", 386 | ] 387 | 388 | [[package]] 389 | name = "digest" 390 | version = "0.10.6" 391 | source = "registry+https://github.com/rust-lang/crates.io-index" 392 | checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" 393 | dependencies = [ 394 | "block-buffer", 395 | "crypto-common", 396 | "subtle", 397 | ] 398 | 399 | [[package]] 400 | name = "directories-next" 401 | version = "2.0.0" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc" 404 | dependencies = [ 405 | "cfg-if", 406 | "dirs-sys-next", 407 | ] 408 | 409 | [[package]] 410 | name = "dirs-sys-next" 411 | version = "0.1.2" 412 | source = "registry+https://github.com/rust-lang/crates.io-index" 413 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 414 | dependencies = [ 415 | "libc", 416 | "redox_users", 417 | "winapi", 418 | ] 419 | 420 | [[package]] 421 | name = "eax" 422 | version = "0.5.0" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | checksum = "9954fabd903b82b9d7a68f65f97dc96dd9ad368e40ccc907a7c19d53e6bfac28" 425 | dependencies = [ 426 | "aead", 427 | "cipher", 428 | "cmac", 429 | "ctr", 430 | "subtle", 431 | ] 432 | 433 | [[package]] 434 | name = "ecdsa" 435 | version = "0.14.8" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" 438 | dependencies = [ 439 | "der", 440 | "elliptic-curve", 441 | "rfc6979", 442 | "signature", 443 | ] 444 | 445 | [[package]] 446 | name = "either" 447 | version = "1.8.1" 448 | source = "registry+https://github.com/rust-lang/crates.io-index" 449 | checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" 450 | 451 | [[package]] 452 | name = "elliptic-curve" 453 | version = "0.12.3" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" 456 | dependencies = [ 457 | "base16ct", 458 | "crypto-bigint", 459 | "der", 460 | "digest 0.10.6", 461 | "ff", 462 | "generic-array", 463 | "group", 464 | "hkdf", 465 | "pkcs8", 466 | "rand_core", 467 | "sec1", 468 | "subtle", 469 | "zeroize", 470 | ] 471 | 472 | [[package]] 473 | name = "encoding_rs" 474 | version = "0.8.32" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" 477 | dependencies = [ 478 | "cfg-if", 479 | ] 480 | 481 | [[package]] 482 | name = "enum-as-inner" 483 | version = "0.5.1" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" 486 | dependencies = [ 487 | "heck", 488 | "proc-macro2", 489 | "quote", 490 | "syn 1.0.109", 491 | ] 492 | 493 | [[package]] 494 | name = "errno" 495 | version = "0.3.1" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" 498 | dependencies = [ 499 | "errno-dragonfly", 500 | "libc", 501 | "windows-sys 0.48.0", 502 | ] 503 | 504 | [[package]] 505 | name = "errno-dragonfly" 506 | version = "0.1.2" 507 | source = "registry+https://github.com/rust-lang/crates.io-index" 508 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 509 | dependencies = [ 510 | "cc", 511 | "libc", 512 | ] 513 | 514 | [[package]] 515 | name = "fastrand" 516 | version = "1.9.0" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" 519 | dependencies = [ 520 | "instant", 521 | ] 522 | 523 | [[package]] 524 | name = "ff" 525 | version = "0.12.1" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" 528 | dependencies = [ 529 | "rand_core", 530 | "subtle", 531 | ] 532 | 533 | [[package]] 534 | name = "fnv" 535 | version = "1.0.7" 536 | source = "registry+https://github.com/rust-lang/crates.io-index" 537 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 538 | 539 | [[package]] 540 | name = "foreign-types" 541 | version = "0.3.2" 542 | source = "registry+https://github.com/rust-lang/crates.io-index" 543 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 544 | dependencies = [ 545 | "foreign-types-shared", 546 | ] 547 | 548 | [[package]] 549 | name = "foreign-types-shared" 550 | version = "0.1.1" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 553 | 554 | [[package]] 555 | name = "form_urlencoded" 556 | version = "1.1.0" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" 559 | dependencies = [ 560 | "percent-encoding", 561 | ] 562 | 563 | [[package]] 564 | name = "futures" 565 | version = "0.3.28" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" 568 | dependencies = [ 569 | "futures-channel", 570 | "futures-core", 571 | "futures-executor", 572 | "futures-io", 573 | "futures-sink", 574 | "futures-task", 575 | "futures-util", 576 | ] 577 | 578 | [[package]] 579 | name = "futures-channel" 580 | version = "0.3.28" 581 | source = "registry+https://github.com/rust-lang/crates.io-index" 582 | checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" 583 | dependencies = [ 584 | "futures-core", 585 | "futures-sink", 586 | ] 587 | 588 | [[package]] 589 | name = "futures-core" 590 | version = "0.3.28" 591 | source = "registry+https://github.com/rust-lang/crates.io-index" 592 | checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" 593 | 594 | [[package]] 595 | name = "futures-executor" 596 | version = "0.3.28" 597 | source = "registry+https://github.com/rust-lang/crates.io-index" 598 | checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" 599 | dependencies = [ 600 | "futures-core", 601 | "futures-task", 602 | "futures-util", 603 | ] 604 | 605 | [[package]] 606 | name = "futures-io" 607 | version = "0.3.28" 608 | source = "registry+https://github.com/rust-lang/crates.io-index" 609 | checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" 610 | 611 | [[package]] 612 | name = "futures-macro" 613 | version = "0.3.28" 614 | source = "registry+https://github.com/rust-lang/crates.io-index" 615 | checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" 616 | dependencies = [ 617 | "proc-macro2", 618 | "quote", 619 | "syn 2.0.15", 620 | ] 621 | 622 | [[package]] 623 | name = "futures-sink" 624 | version = "0.3.28" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" 627 | 628 | [[package]] 629 | name = "futures-task" 630 | version = "0.3.28" 631 | source = "registry+https://github.com/rust-lang/crates.io-index" 632 | checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" 633 | 634 | [[package]] 635 | name = "futures-util" 636 | version = "0.3.28" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" 639 | dependencies = [ 640 | "futures-channel", 641 | "futures-core", 642 | "futures-io", 643 | "futures-macro", 644 | "futures-sink", 645 | "futures-task", 646 | "memchr", 647 | "pin-project-lite", 648 | "pin-utils", 649 | "slab", 650 | ] 651 | 652 | [[package]] 653 | name = "generic-array" 654 | version = "0.14.7" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 657 | dependencies = [ 658 | "typenum", 659 | "version_check", 660 | ] 661 | 662 | [[package]] 663 | name = "getrandom" 664 | version = "0.2.9" 665 | source = "registry+https://github.com/rust-lang/crates.io-index" 666 | checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" 667 | dependencies = [ 668 | "cfg-if", 669 | "libc", 670 | "wasi", 671 | ] 672 | 673 | [[package]] 674 | name = "git-testament" 675 | version = "0.2.4" 676 | source = "registry+https://github.com/rust-lang/crates.io-index" 677 | checksum = "986bf57c808270f3a0a0652c3bfce0f5d667aa5f5b465616dc697c7f390834b1" 678 | dependencies = [ 679 | "git-testament-derive", 680 | "no-std-compat", 681 | ] 682 | 683 | [[package]] 684 | name = "git-testament-derive" 685 | version = "0.1.14" 686 | source = "registry+https://github.com/rust-lang/crates.io-index" 687 | checksum = "4a782db5866c7ab75f3552dda4cbf34e3e257cc64c963c6ed5af1e12818e8ae6" 688 | dependencies = [ 689 | "log", 690 | "proc-macro2", 691 | "quote", 692 | "syn 1.0.109", 693 | "time", 694 | ] 695 | 696 | [[package]] 697 | name = "group" 698 | version = "0.12.1" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" 701 | dependencies = [ 702 | "ff", 703 | "rand_core", 704 | "subtle", 705 | ] 706 | 707 | [[package]] 708 | name = "h2" 709 | version = "0.3.17" 710 | source = "registry+https://github.com/rust-lang/crates.io-index" 711 | checksum = "66b91535aa35fea1523ad1b86cb6b53c28e0ae566ba4a460f4457e936cad7c6f" 712 | dependencies = [ 713 | "bytes", 714 | "fnv", 715 | "futures-core", 716 | "futures-sink", 717 | "futures-util", 718 | "http", 719 | "indexmap", 720 | "slab", 721 | "tokio", 722 | "tokio-util", 723 | "tracing", 724 | ] 725 | 726 | [[package]] 727 | name = "hashbrown" 728 | version = "0.12.3" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 731 | 732 | [[package]] 733 | name = "heck" 734 | version = "0.4.1" 735 | source = "registry+https://github.com/rust-lang/crates.io-index" 736 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 737 | 738 | [[package]] 739 | name = "hermit-abi" 740 | version = "0.2.6" 741 | source = "registry+https://github.com/rust-lang/crates.io-index" 742 | checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" 743 | dependencies = [ 744 | "libc", 745 | ] 746 | 747 | [[package]] 748 | name = "hermit-abi" 749 | version = "0.3.1" 750 | source = "registry+https://github.com/rust-lang/crates.io-index" 751 | checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" 752 | 753 | [[package]] 754 | name = "hkdf" 755 | version = "0.12.3" 756 | source = "registry+https://github.com/rust-lang/crates.io-index" 757 | checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" 758 | dependencies = [ 759 | "hmac", 760 | ] 761 | 762 | [[package]] 763 | name = "hmac" 764 | version = "0.12.1" 765 | source = "registry+https://github.com/rust-lang/crates.io-index" 766 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 767 | dependencies = [ 768 | "digest 0.10.6", 769 | ] 770 | 771 | [[package]] 772 | name = "hostname" 773 | version = "0.3.1" 774 | source = "registry+https://github.com/rust-lang/crates.io-index" 775 | checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" 776 | dependencies = [ 777 | "libc", 778 | "match_cfg", 779 | "winapi", 780 | ] 781 | 782 | [[package]] 783 | name = "http" 784 | version = "0.2.9" 785 | source = "registry+https://github.com/rust-lang/crates.io-index" 786 | checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" 787 | dependencies = [ 788 | "bytes", 789 | "fnv", 790 | "itoa", 791 | ] 792 | 793 | [[package]] 794 | name = "http-body" 795 | version = "0.4.5" 796 | source = "registry+https://github.com/rust-lang/crates.io-index" 797 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" 798 | dependencies = [ 799 | "bytes", 800 | "http", 801 | "pin-project-lite", 802 | ] 803 | 804 | [[package]] 805 | name = "httparse" 806 | version = "1.8.0" 807 | source = "registry+https://github.com/rust-lang/crates.io-index" 808 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 809 | 810 | [[package]] 811 | name = "httpdate" 812 | version = "1.0.2" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" 815 | 816 | [[package]] 817 | name = "hyper" 818 | version = "0.14.26" 819 | source = "registry+https://github.com/rust-lang/crates.io-index" 820 | checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" 821 | dependencies = [ 822 | "bytes", 823 | "futures-channel", 824 | "futures-core", 825 | "futures-util", 826 | "h2", 827 | "http", 828 | "http-body", 829 | "httparse", 830 | "httpdate", 831 | "itoa", 832 | "pin-project-lite", 833 | "socket2", 834 | "tokio", 835 | "tower-service", 836 | "tracing", 837 | "want", 838 | ] 839 | 840 | [[package]] 841 | name = "hyper-tls" 842 | version = "0.5.0" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 845 | dependencies = [ 846 | "bytes", 847 | "hyper", 848 | "native-tls", 849 | "tokio", 850 | "tokio-native-tls", 851 | ] 852 | 853 | [[package]] 854 | name = "idna" 855 | version = "0.2.3" 856 | source = "registry+https://github.com/rust-lang/crates.io-index" 857 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" 858 | dependencies = [ 859 | "matches", 860 | "unicode-bidi", 861 | "unicode-normalization", 862 | ] 863 | 864 | [[package]] 865 | name = "idna" 866 | version = "0.3.0" 867 | source = "registry+https://github.com/rust-lang/crates.io-index" 868 | checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" 869 | dependencies = [ 870 | "unicode-bidi", 871 | "unicode-normalization", 872 | ] 873 | 874 | [[package]] 875 | name = "indexmap" 876 | version = "1.9.3" 877 | source = "registry+https://github.com/rust-lang/crates.io-index" 878 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 879 | dependencies = [ 880 | "autocfg", 881 | "hashbrown", 882 | ] 883 | 884 | [[package]] 885 | name = "inout" 886 | version = "0.1.3" 887 | source = "registry+https://github.com/rust-lang/crates.io-index" 888 | checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" 889 | dependencies = [ 890 | "generic-array", 891 | ] 892 | 893 | [[package]] 894 | name = "instant" 895 | version = "0.1.12" 896 | source = "registry+https://github.com/rust-lang/crates.io-index" 897 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 898 | dependencies = [ 899 | "cfg-if", 900 | ] 901 | 902 | [[package]] 903 | name = "io-lifetimes" 904 | version = "1.0.10" 905 | source = "registry+https://github.com/rust-lang/crates.io-index" 906 | checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" 907 | dependencies = [ 908 | "hermit-abi 0.3.1", 909 | "libc", 910 | "windows-sys 0.48.0", 911 | ] 912 | 913 | [[package]] 914 | name = "ipconfig" 915 | version = "0.3.1" 916 | source = "registry+https://github.com/rust-lang/crates.io-index" 917 | checksum = "bd302af1b90f2463a98fa5ad469fc212c8e3175a41c3068601bfa2727591c5be" 918 | dependencies = [ 919 | "socket2", 920 | "widestring", 921 | "winapi", 922 | "winreg", 923 | ] 924 | 925 | [[package]] 926 | name = "ipnet" 927 | version = "2.7.2" 928 | source = "registry+https://github.com/rust-lang/crates.io-index" 929 | checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" 930 | 931 | [[package]] 932 | name = "is-terminal" 933 | version = "0.4.7" 934 | source = "registry+https://github.com/rust-lang/crates.io-index" 935 | checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" 936 | dependencies = [ 937 | "hermit-abi 0.3.1", 938 | "io-lifetimes", 939 | "rustix", 940 | "windows-sys 0.48.0", 941 | ] 942 | 943 | [[package]] 944 | name = "itertools" 945 | version = "0.10.5" 946 | source = "registry+https://github.com/rust-lang/crates.io-index" 947 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" 948 | dependencies = [ 949 | "either", 950 | ] 951 | 952 | [[package]] 953 | name = "itoa" 954 | version = "1.0.6" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" 957 | 958 | [[package]] 959 | name = "js-sys" 960 | version = "0.3.61" 961 | source = "registry+https://github.com/rust-lang/crates.io-index" 962 | checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" 963 | dependencies = [ 964 | "wasm-bindgen", 965 | ] 966 | 967 | [[package]] 968 | name = "lazy_static" 969 | version = "1.4.0" 970 | source = "registry+https://github.com/rust-lang/crates.io-index" 971 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 972 | 973 | [[package]] 974 | name = "lexical-core" 975 | version = "0.7.6" 976 | source = "registry+https://github.com/rust-lang/crates.io-index" 977 | checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" 978 | dependencies = [ 979 | "arrayvec", 980 | "bitflags", 981 | "cfg-if", 982 | "ryu", 983 | "static_assertions", 984 | ] 985 | 986 | [[package]] 987 | name = "libc" 988 | version = "0.2.141" 989 | source = "registry+https://github.com/rust-lang/crates.io-index" 990 | checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" 991 | 992 | [[package]] 993 | name = "linked-hash-map" 994 | version = "0.5.6" 995 | source = "registry+https://github.com/rust-lang/crates.io-index" 996 | checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" 997 | 998 | [[package]] 999 | name = "linux-raw-sys" 1000 | version = "0.3.1" 1001 | source = "registry+https://github.com/rust-lang/crates.io-index" 1002 | checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" 1003 | 1004 | [[package]] 1005 | name = "lock_api" 1006 | version = "0.4.9" 1007 | source = "registry+https://github.com/rust-lang/crates.io-index" 1008 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 1009 | dependencies = [ 1010 | "autocfg", 1011 | "scopeguard", 1012 | ] 1013 | 1014 | [[package]] 1015 | name = "log" 1016 | version = "0.4.17" 1017 | source = "registry+https://github.com/rust-lang/crates.io-index" 1018 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 1019 | dependencies = [ 1020 | "cfg-if", 1021 | ] 1022 | 1023 | [[package]] 1024 | name = "lru-cache" 1025 | version = "0.1.2" 1026 | source = "registry+https://github.com/rust-lang/crates.io-index" 1027 | checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" 1028 | dependencies = [ 1029 | "linked-hash-map", 1030 | ] 1031 | 1032 | [[package]] 1033 | name = "match_cfg" 1034 | version = "0.1.0" 1035 | source = "registry+https://github.com/rust-lang/crates.io-index" 1036 | checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" 1037 | 1038 | [[package]] 1039 | name = "matchers" 1040 | version = "0.1.0" 1041 | source = "registry+https://github.com/rust-lang/crates.io-index" 1042 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 1043 | dependencies = [ 1044 | "regex-automata", 1045 | ] 1046 | 1047 | [[package]] 1048 | name = "matches" 1049 | version = "0.1.10" 1050 | source = "registry+https://github.com/rust-lang/crates.io-index" 1051 | checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" 1052 | 1053 | [[package]] 1054 | name = "memchr" 1055 | version = "2.5.0" 1056 | source = "registry+https://github.com/rust-lang/crates.io-index" 1057 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 1058 | 1059 | [[package]] 1060 | name = "mime" 1061 | version = "0.3.17" 1062 | source = "registry+https://github.com/rust-lang/crates.io-index" 1063 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1064 | 1065 | [[package]] 1066 | name = "mio" 1067 | version = "0.8.6" 1068 | source = "registry+https://github.com/rust-lang/crates.io-index" 1069 | checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" 1070 | dependencies = [ 1071 | "libc", 1072 | "log", 1073 | "wasi", 1074 | "windows-sys 0.45.0", 1075 | ] 1076 | 1077 | [[package]] 1078 | name = "native-tls" 1079 | version = "0.2.11" 1080 | source = "registry+https://github.com/rust-lang/crates.io-index" 1081 | checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" 1082 | dependencies = [ 1083 | "lazy_static", 1084 | "libc", 1085 | "log", 1086 | "openssl", 1087 | "openssl-probe", 1088 | "openssl-sys", 1089 | "schannel", 1090 | "security-framework", 1091 | "security-framework-sys", 1092 | "tempfile", 1093 | ] 1094 | 1095 | [[package]] 1096 | name = "no-std-compat" 1097 | version = "0.4.1" 1098 | source = "registry+https://github.com/rust-lang/crates.io-index" 1099 | checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" 1100 | 1101 | [[package]] 1102 | name = "nom" 1103 | version = "5.1.2" 1104 | source = "registry+https://github.com/rust-lang/crates.io-index" 1105 | checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" 1106 | dependencies = [ 1107 | "lexical-core", 1108 | "memchr", 1109 | "version_check", 1110 | ] 1111 | 1112 | [[package]] 1113 | name = "nu-ansi-term" 1114 | version = "0.46.0" 1115 | source = "registry+https://github.com/rust-lang/crates.io-index" 1116 | checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 1117 | dependencies = [ 1118 | "overload", 1119 | "winapi", 1120 | ] 1121 | 1122 | [[package]] 1123 | name = "num-bigint" 1124 | version = "0.4.3" 1125 | source = "registry+https://github.com/rust-lang/crates.io-index" 1126 | checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" 1127 | dependencies = [ 1128 | "autocfg", 1129 | "num-integer", 1130 | "num-traits", 1131 | ] 1132 | 1133 | [[package]] 1134 | name = "num-derive" 1135 | version = "0.3.3" 1136 | source = "registry+https://github.com/rust-lang/crates.io-index" 1137 | checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" 1138 | dependencies = [ 1139 | "proc-macro2", 1140 | "quote", 1141 | "syn 1.0.109", 1142 | ] 1143 | 1144 | [[package]] 1145 | name = "num-integer" 1146 | version = "0.1.45" 1147 | source = "registry+https://github.com/rust-lang/crates.io-index" 1148 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 1149 | dependencies = [ 1150 | "autocfg", 1151 | "num-traits", 1152 | ] 1153 | 1154 | [[package]] 1155 | name = "num-traits" 1156 | version = "0.2.15" 1157 | source = "registry+https://github.com/rust-lang/crates.io-index" 1158 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 1159 | dependencies = [ 1160 | "autocfg", 1161 | ] 1162 | 1163 | [[package]] 1164 | name = "num_cpus" 1165 | version = "1.15.0" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" 1168 | dependencies = [ 1169 | "hermit-abi 0.2.6", 1170 | "libc", 1171 | ] 1172 | 1173 | [[package]] 1174 | name = "omnom" 1175 | version = "3.0.0" 1176 | source = "registry+https://github.com/rust-lang/crates.io-index" 1177 | checksum = "66562a92c66d5937e9d549597c2d3cafe3d2367dd08dc257da730587c2cfc218" 1178 | dependencies = [ 1179 | "memchr", 1180 | ] 1181 | 1182 | [[package]] 1183 | name = "once_cell" 1184 | version = "1.17.1" 1185 | source = "registry+https://github.com/rust-lang/crates.io-index" 1186 | checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" 1187 | 1188 | [[package]] 1189 | name = "openssl" 1190 | version = "0.10.50" 1191 | source = "registry+https://github.com/rust-lang/crates.io-index" 1192 | checksum = "7e30d8bc91859781f0a943411186324d580f2bbeb71b452fe91ae344806af3f1" 1193 | dependencies = [ 1194 | "bitflags", 1195 | "cfg-if", 1196 | "foreign-types", 1197 | "libc", 1198 | "once_cell", 1199 | "openssl-macros", 1200 | "openssl-sys", 1201 | ] 1202 | 1203 | [[package]] 1204 | name = "openssl-macros" 1205 | version = "0.1.1" 1206 | source = "registry+https://github.com/rust-lang/crates.io-index" 1207 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1208 | dependencies = [ 1209 | "proc-macro2", 1210 | "quote", 1211 | "syn 2.0.15", 1212 | ] 1213 | 1214 | [[package]] 1215 | name = "openssl-probe" 1216 | version = "0.1.5" 1217 | source = "registry+https://github.com/rust-lang/crates.io-index" 1218 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" 1219 | 1220 | [[package]] 1221 | name = "openssl-sys" 1222 | version = "0.9.85" 1223 | source = "registry+https://github.com/rust-lang/crates.io-index" 1224 | checksum = "0d3d193fb1488ad46ffe3aaabc912cc931d02ee8518fe2959aea8ef52718b0c0" 1225 | dependencies = [ 1226 | "cc", 1227 | "libc", 1228 | "pkg-config", 1229 | "vcpkg", 1230 | ] 1231 | 1232 | [[package]] 1233 | name = "overload" 1234 | version = "0.1.1" 1235 | source = "registry+https://github.com/rust-lang/crates.io-index" 1236 | checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 1237 | 1238 | [[package]] 1239 | name = "p256" 1240 | version = "0.11.1" 1241 | source = "registry+https://github.com/rust-lang/crates.io-index" 1242 | checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" 1243 | dependencies = [ 1244 | "ecdsa", 1245 | "elliptic-curve", 1246 | "sha2", 1247 | ] 1248 | 1249 | [[package]] 1250 | name = "parking_lot" 1251 | version = "0.12.1" 1252 | source = "registry+https://github.com/rust-lang/crates.io-index" 1253 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 1254 | dependencies = [ 1255 | "lock_api", 1256 | "parking_lot_core", 1257 | ] 1258 | 1259 | [[package]] 1260 | name = "parking_lot_core" 1261 | version = "0.9.7" 1262 | source = "registry+https://github.com/rust-lang/crates.io-index" 1263 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" 1264 | dependencies = [ 1265 | "cfg-if", 1266 | "libc", 1267 | "redox_syscall 0.2.16", 1268 | "smallvec", 1269 | "windows-sys 0.45.0", 1270 | ] 1271 | 1272 | [[package]] 1273 | name = "percent-encoding" 1274 | version = "2.2.0" 1275 | source = "registry+https://github.com/rust-lang/crates.io-index" 1276 | checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" 1277 | 1278 | [[package]] 1279 | name = "pin-project-lite" 1280 | version = "0.2.9" 1281 | source = "registry+https://github.com/rust-lang/crates.io-index" 1282 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 1283 | 1284 | [[package]] 1285 | name = "pin-utils" 1286 | version = "0.1.0" 1287 | source = "registry+https://github.com/rust-lang/crates.io-index" 1288 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1289 | 1290 | [[package]] 1291 | name = "pkcs8" 1292 | version = "0.9.0" 1293 | source = "registry+https://github.com/rust-lang/crates.io-index" 1294 | checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" 1295 | dependencies = [ 1296 | "der", 1297 | "spki", 1298 | ] 1299 | 1300 | [[package]] 1301 | name = "pkg-config" 1302 | version = "0.3.26" 1303 | source = "registry+https://github.com/rust-lang/crates.io-index" 1304 | checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" 1305 | 1306 | [[package]] 1307 | name = "ppv-lite86" 1308 | version = "0.2.17" 1309 | source = "registry+https://github.com/rust-lang/crates.io-index" 1310 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 1311 | 1312 | [[package]] 1313 | name = "proc-macro2" 1314 | version = "1.0.56" 1315 | source = "registry+https://github.com/rust-lang/crates.io-index" 1316 | checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" 1317 | dependencies = [ 1318 | "unicode-ident", 1319 | ] 1320 | 1321 | [[package]] 1322 | name = "quick-error" 1323 | version = "1.2.3" 1324 | source = "registry+https://github.com/rust-lang/crates.io-index" 1325 | checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 1326 | 1327 | [[package]] 1328 | name = "quicklz" 1329 | version = "0.3.1" 1330 | source = "registry+https://github.com/rust-lang/crates.io-index" 1331 | checksum = "750eab265a26a0cd064f2a2b222bf172cc06d7a873e113e5f6d0118cc6e5fbb1" 1332 | dependencies = [ 1333 | "bit-vec", 1334 | "byteorder", 1335 | "thiserror", 1336 | ] 1337 | 1338 | [[package]] 1339 | name = "quote" 1340 | version = "1.0.26" 1341 | source = "registry+https://github.com/rust-lang/crates.io-index" 1342 | checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" 1343 | dependencies = [ 1344 | "proc-macro2", 1345 | ] 1346 | 1347 | [[package]] 1348 | name = "rand" 1349 | version = "0.8.5" 1350 | source = "registry+https://github.com/rust-lang/crates.io-index" 1351 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1352 | dependencies = [ 1353 | "libc", 1354 | "rand_chacha", 1355 | "rand_core", 1356 | ] 1357 | 1358 | [[package]] 1359 | name = "rand_chacha" 1360 | version = "0.3.1" 1361 | source = "registry+https://github.com/rust-lang/crates.io-index" 1362 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1363 | dependencies = [ 1364 | "ppv-lite86", 1365 | "rand_core", 1366 | ] 1367 | 1368 | [[package]] 1369 | name = "rand_core" 1370 | version = "0.6.4" 1371 | source = "registry+https://github.com/rust-lang/crates.io-index" 1372 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1373 | dependencies = [ 1374 | "getrandom", 1375 | ] 1376 | 1377 | [[package]] 1378 | name = "redox_syscall" 1379 | version = "0.2.16" 1380 | source = "registry+https://github.com/rust-lang/crates.io-index" 1381 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 1382 | dependencies = [ 1383 | "bitflags", 1384 | ] 1385 | 1386 | [[package]] 1387 | name = "redox_syscall" 1388 | version = "0.3.5" 1389 | source = "registry+https://github.com/rust-lang/crates.io-index" 1390 | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" 1391 | dependencies = [ 1392 | "bitflags", 1393 | ] 1394 | 1395 | [[package]] 1396 | name = "redox_users" 1397 | version = "0.4.3" 1398 | source = "registry+https://github.com/rust-lang/crates.io-index" 1399 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" 1400 | dependencies = [ 1401 | "getrandom", 1402 | "redox_syscall 0.2.16", 1403 | "thiserror", 1404 | ] 1405 | 1406 | [[package]] 1407 | name = "ref-cast" 1408 | version = "1.0.16" 1409 | source = "registry+https://github.com/rust-lang/crates.io-index" 1410 | checksum = "f43faa91b1c8b36841ee70e97188a869d37ae21759da6846d4be66de5bf7b12c" 1411 | dependencies = [ 1412 | "ref-cast-impl", 1413 | ] 1414 | 1415 | [[package]] 1416 | name = "ref-cast-impl" 1417 | version = "1.0.16" 1418 | source = "registry+https://github.com/rust-lang/crates.io-index" 1419 | checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" 1420 | dependencies = [ 1421 | "proc-macro2", 1422 | "quote", 1423 | "syn 2.0.15", 1424 | ] 1425 | 1426 | [[package]] 1427 | name = "regex" 1428 | version = "1.7.3" 1429 | source = "registry+https://github.com/rust-lang/crates.io-index" 1430 | checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" 1431 | dependencies = [ 1432 | "aho-corasick", 1433 | "memchr", 1434 | "regex-syntax", 1435 | ] 1436 | 1437 | [[package]] 1438 | name = "regex-automata" 1439 | version = "0.1.10" 1440 | source = "registry+https://github.com/rust-lang/crates.io-index" 1441 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 1442 | dependencies = [ 1443 | "regex-syntax", 1444 | ] 1445 | 1446 | [[package]] 1447 | name = "regex-syntax" 1448 | version = "0.6.29" 1449 | source = "registry+https://github.com/rust-lang/crates.io-index" 1450 | checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" 1451 | 1452 | [[package]] 1453 | name = "reqwest" 1454 | version = "0.11.16" 1455 | source = "registry+https://github.com/rust-lang/crates.io-index" 1456 | checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" 1457 | dependencies = [ 1458 | "base64 0.21.0", 1459 | "bytes", 1460 | "encoding_rs", 1461 | "futures-core", 1462 | "futures-util", 1463 | "h2", 1464 | "http", 1465 | "http-body", 1466 | "hyper", 1467 | "hyper-tls", 1468 | "ipnet", 1469 | "js-sys", 1470 | "log", 1471 | "mime", 1472 | "native-tls", 1473 | "once_cell", 1474 | "percent-encoding", 1475 | "pin-project-lite", 1476 | "serde", 1477 | "serde_json", 1478 | "serde_urlencoded", 1479 | "tokio", 1480 | "tokio-native-tls", 1481 | "tower-service", 1482 | "url", 1483 | "wasm-bindgen", 1484 | "wasm-bindgen-futures", 1485 | "web-sys", 1486 | "winreg", 1487 | ] 1488 | 1489 | [[package]] 1490 | name = "resolv-conf" 1491 | version = "0.7.0" 1492 | source = "registry+https://github.com/rust-lang/crates.io-index" 1493 | checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" 1494 | dependencies = [ 1495 | "hostname", 1496 | "quick-error", 1497 | ] 1498 | 1499 | [[package]] 1500 | name = "rfc6979" 1501 | version = "0.3.1" 1502 | source = "registry+https://github.com/rust-lang/crates.io-index" 1503 | checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" 1504 | dependencies = [ 1505 | "crypto-bigint", 1506 | "hmac", 1507 | "zeroize", 1508 | ] 1509 | 1510 | [[package]] 1511 | name = "rustix" 1512 | version = "0.37.11" 1513 | source = "registry+https://github.com/rust-lang/crates.io-index" 1514 | checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" 1515 | dependencies = [ 1516 | "bitflags", 1517 | "errno", 1518 | "io-lifetimes", 1519 | "libc", 1520 | "linux-raw-sys", 1521 | "windows-sys 0.48.0", 1522 | ] 1523 | 1524 | [[package]] 1525 | name = "ryu" 1526 | version = "1.0.13" 1527 | source = "registry+https://github.com/rust-lang/crates.io-index" 1528 | checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" 1529 | 1530 | [[package]] 1531 | name = "schannel" 1532 | version = "0.1.21" 1533 | source = "registry+https://github.com/rust-lang/crates.io-index" 1534 | checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" 1535 | dependencies = [ 1536 | "windows-sys 0.42.0", 1537 | ] 1538 | 1539 | [[package]] 1540 | name = "scopeguard" 1541 | version = "1.1.0" 1542 | source = "registry+https://github.com/rust-lang/crates.io-index" 1543 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1544 | 1545 | [[package]] 1546 | name = "sec1" 1547 | version = "0.3.0" 1548 | source = "registry+https://github.com/rust-lang/crates.io-index" 1549 | checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" 1550 | dependencies = [ 1551 | "base16ct", 1552 | "der", 1553 | "generic-array", 1554 | "pkcs8", 1555 | "subtle", 1556 | "zeroize", 1557 | ] 1558 | 1559 | [[package]] 1560 | name = "security-framework" 1561 | version = "2.8.2" 1562 | source = "registry+https://github.com/rust-lang/crates.io-index" 1563 | checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" 1564 | dependencies = [ 1565 | "bitflags", 1566 | "core-foundation", 1567 | "core-foundation-sys", 1568 | "libc", 1569 | "security-framework-sys", 1570 | ] 1571 | 1572 | [[package]] 1573 | name = "security-framework-sys" 1574 | version = "2.8.0" 1575 | source = "registry+https://github.com/rust-lang/crates.io-index" 1576 | checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" 1577 | dependencies = [ 1578 | "core-foundation-sys", 1579 | "libc", 1580 | ] 1581 | 1582 | [[package]] 1583 | name = "self_cell" 1584 | version = "0.10.2" 1585 | source = "registry+https://github.com/rust-lang/crates.io-index" 1586 | checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" 1587 | 1588 | [[package]] 1589 | name = "serde" 1590 | version = "1.0.160" 1591 | source = "registry+https://github.com/rust-lang/crates.io-index" 1592 | checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" 1593 | dependencies = [ 1594 | "serde_derive", 1595 | ] 1596 | 1597 | [[package]] 1598 | name = "serde_derive" 1599 | version = "1.0.160" 1600 | source = "registry+https://github.com/rust-lang/crates.io-index" 1601 | checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" 1602 | dependencies = [ 1603 | "proc-macro2", 1604 | "quote", 1605 | "syn 2.0.15", 1606 | ] 1607 | 1608 | [[package]] 1609 | name = "serde_json" 1610 | version = "1.0.96" 1611 | source = "registry+https://github.com/rust-lang/crates.io-index" 1612 | checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" 1613 | dependencies = [ 1614 | "itoa", 1615 | "ryu", 1616 | "serde", 1617 | ] 1618 | 1619 | [[package]] 1620 | name = "serde_spanned" 1621 | version = "0.6.1" 1622 | source = "registry+https://github.com/rust-lang/crates.io-index" 1623 | checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" 1624 | dependencies = [ 1625 | "serde", 1626 | ] 1627 | 1628 | [[package]] 1629 | name = "serde_urlencoded" 1630 | version = "0.7.1" 1631 | source = "registry+https://github.com/rust-lang/crates.io-index" 1632 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1633 | dependencies = [ 1634 | "form_urlencoded", 1635 | "itoa", 1636 | "ryu", 1637 | "serde", 1638 | ] 1639 | 1640 | [[package]] 1641 | name = "sha-1" 1642 | version = "0.10.1" 1643 | source = "registry+https://github.com/rust-lang/crates.io-index" 1644 | checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" 1645 | dependencies = [ 1646 | "cfg-if", 1647 | "cpufeatures", 1648 | "digest 0.10.6", 1649 | ] 1650 | 1651 | [[package]] 1652 | name = "sha2" 1653 | version = "0.10.6" 1654 | source = "registry+https://github.com/rust-lang/crates.io-index" 1655 | checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" 1656 | dependencies = [ 1657 | "cfg-if", 1658 | "cpufeatures", 1659 | "digest 0.10.6", 1660 | ] 1661 | 1662 | [[package]] 1663 | name = "sharded-slab" 1664 | version = "0.1.4" 1665 | source = "registry+https://github.com/rust-lang/crates.io-index" 1666 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" 1667 | dependencies = [ 1668 | "lazy_static", 1669 | ] 1670 | 1671 | [[package]] 1672 | name = "signal-hook-registry" 1673 | version = "1.4.1" 1674 | source = "registry+https://github.com/rust-lang/crates.io-index" 1675 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 1676 | dependencies = [ 1677 | "libc", 1678 | ] 1679 | 1680 | [[package]] 1681 | name = "signature" 1682 | version = "1.6.4" 1683 | source = "registry+https://github.com/rust-lang/crates.io-index" 1684 | checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" 1685 | dependencies = [ 1686 | "digest 0.10.6", 1687 | "rand_core", 1688 | ] 1689 | 1690 | [[package]] 1691 | name = "simple-bot" 1692 | version = "0.2.0" 1693 | dependencies = [ 1694 | "anyhow", 1695 | "base64 0.21.0", 1696 | "clap", 1697 | "directories-next", 1698 | "futures", 1699 | "regex", 1700 | "serde", 1701 | "tokio", 1702 | "toml 0.7.3", 1703 | "tracing", 1704 | "tracing-subscriber", 1705 | "tsclientlib", 1706 | "tsproto-types", 1707 | ] 1708 | 1709 | [[package]] 1710 | name = "simple_asn1" 1711 | version = "0.6.2" 1712 | source = "registry+https://github.com/rust-lang/crates.io-index" 1713 | checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" 1714 | dependencies = [ 1715 | "num-bigint", 1716 | "num-traits", 1717 | "thiserror", 1718 | "time", 1719 | ] 1720 | 1721 | [[package]] 1722 | name = "slab" 1723 | version = "0.4.8" 1724 | source = "registry+https://github.com/rust-lang/crates.io-index" 1725 | checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" 1726 | dependencies = [ 1727 | "autocfg", 1728 | ] 1729 | 1730 | [[package]] 1731 | name = "smallvec" 1732 | version = "1.10.0" 1733 | source = "registry+https://github.com/rust-lang/crates.io-index" 1734 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 1735 | 1736 | [[package]] 1737 | name = "socket2" 1738 | version = "0.4.9" 1739 | source = "registry+https://github.com/rust-lang/crates.io-index" 1740 | checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" 1741 | dependencies = [ 1742 | "libc", 1743 | "winapi", 1744 | ] 1745 | 1746 | [[package]] 1747 | name = "spki" 1748 | version = "0.6.0" 1749 | source = "registry+https://github.com/rust-lang/crates.io-index" 1750 | checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" 1751 | dependencies = [ 1752 | "base64ct", 1753 | "der", 1754 | ] 1755 | 1756 | [[package]] 1757 | name = "static_assertions" 1758 | version = "1.1.0" 1759 | source = "registry+https://github.com/rust-lang/crates.io-index" 1760 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 1761 | 1762 | [[package]] 1763 | name = "strsim" 1764 | version = "0.10.0" 1765 | source = "registry+https://github.com/rust-lang/crates.io-index" 1766 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 1767 | 1768 | [[package]] 1769 | name = "subtle" 1770 | version = "2.4.1" 1771 | source = "registry+https://github.com/rust-lang/crates.io-index" 1772 | checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" 1773 | 1774 | [[package]] 1775 | name = "subtle-ng" 1776 | version = "2.5.0" 1777 | source = "registry+https://github.com/rust-lang/crates.io-index" 1778 | checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" 1779 | 1780 | [[package]] 1781 | name = "syn" 1782 | version = "1.0.109" 1783 | source = "registry+https://github.com/rust-lang/crates.io-index" 1784 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1785 | dependencies = [ 1786 | "proc-macro2", 1787 | "quote", 1788 | "unicode-ident", 1789 | ] 1790 | 1791 | [[package]] 1792 | name = "syn" 1793 | version = "2.0.15" 1794 | source = "registry+https://github.com/rust-lang/crates.io-index" 1795 | checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" 1796 | dependencies = [ 1797 | "proc-macro2", 1798 | "quote", 1799 | "unicode-ident", 1800 | ] 1801 | 1802 | [[package]] 1803 | name = "t4rust-derive" 1804 | version = "0.3.0" 1805 | source = "registry+https://github.com/rust-lang/crates.io-index" 1806 | checksum = "b97b5372931346e9152892e48c669674766c75ecd9c00860575706eb43c8a4b1" 1807 | dependencies = [ 1808 | "nom", 1809 | "proc-macro2", 1810 | "quote", 1811 | "syn 1.0.109", 1812 | ] 1813 | 1814 | [[package]] 1815 | name = "tempfile" 1816 | version = "3.5.0" 1817 | source = "registry+https://github.com/rust-lang/crates.io-index" 1818 | checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" 1819 | dependencies = [ 1820 | "cfg-if", 1821 | "fastrand", 1822 | "redox_syscall 0.3.5", 1823 | "rustix", 1824 | "windows-sys 0.45.0", 1825 | ] 1826 | 1827 | [[package]] 1828 | name = "thiserror" 1829 | version = "1.0.40" 1830 | source = "registry+https://github.com/rust-lang/crates.io-index" 1831 | checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" 1832 | dependencies = [ 1833 | "thiserror-impl", 1834 | ] 1835 | 1836 | [[package]] 1837 | name = "thiserror-impl" 1838 | version = "1.0.40" 1839 | source = "registry+https://github.com/rust-lang/crates.io-index" 1840 | checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" 1841 | dependencies = [ 1842 | "proc-macro2", 1843 | "quote", 1844 | "syn 2.0.15", 1845 | ] 1846 | 1847 | [[package]] 1848 | name = "thread_local" 1849 | version = "1.1.7" 1850 | source = "registry+https://github.com/rust-lang/crates.io-index" 1851 | checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" 1852 | dependencies = [ 1853 | "cfg-if", 1854 | "once_cell", 1855 | ] 1856 | 1857 | [[package]] 1858 | name = "time" 1859 | version = "0.3.20" 1860 | source = "registry+https://github.com/rust-lang/crates.io-index" 1861 | checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" 1862 | dependencies = [ 1863 | "itoa", 1864 | "serde", 1865 | "time-core", 1866 | "time-macros", 1867 | ] 1868 | 1869 | [[package]] 1870 | name = "time-core" 1871 | version = "0.1.0" 1872 | source = "registry+https://github.com/rust-lang/crates.io-index" 1873 | checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" 1874 | 1875 | [[package]] 1876 | name = "time-macros" 1877 | version = "0.2.8" 1878 | source = "registry+https://github.com/rust-lang/crates.io-index" 1879 | checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" 1880 | dependencies = [ 1881 | "time-core", 1882 | ] 1883 | 1884 | [[package]] 1885 | name = "tinyvec" 1886 | version = "1.6.0" 1887 | source = "registry+https://github.com/rust-lang/crates.io-index" 1888 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1889 | dependencies = [ 1890 | "tinyvec_macros", 1891 | ] 1892 | 1893 | [[package]] 1894 | name = "tinyvec_macros" 1895 | version = "0.1.1" 1896 | source = "registry+https://github.com/rust-lang/crates.io-index" 1897 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1898 | 1899 | [[package]] 1900 | name = "tokio" 1901 | version = "1.27.0" 1902 | source = "registry+https://github.com/rust-lang/crates.io-index" 1903 | checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" 1904 | dependencies = [ 1905 | "autocfg", 1906 | "bytes", 1907 | "libc", 1908 | "mio", 1909 | "num_cpus", 1910 | "pin-project-lite", 1911 | "signal-hook-registry", 1912 | "socket2", 1913 | "tokio-macros", 1914 | "windows-sys 0.45.0", 1915 | ] 1916 | 1917 | [[package]] 1918 | name = "tokio-macros" 1919 | version = "2.0.0" 1920 | source = "registry+https://github.com/rust-lang/crates.io-index" 1921 | checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" 1922 | dependencies = [ 1923 | "proc-macro2", 1924 | "quote", 1925 | "syn 2.0.15", 1926 | ] 1927 | 1928 | [[package]] 1929 | name = "tokio-native-tls" 1930 | version = "0.3.1" 1931 | source = "registry+https://github.com/rust-lang/crates.io-index" 1932 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 1933 | dependencies = [ 1934 | "native-tls", 1935 | "tokio", 1936 | ] 1937 | 1938 | [[package]] 1939 | name = "tokio-stream" 1940 | version = "0.1.12" 1941 | source = "registry+https://github.com/rust-lang/crates.io-index" 1942 | checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" 1943 | dependencies = [ 1944 | "futures-core", 1945 | "pin-project-lite", 1946 | "tokio", 1947 | ] 1948 | 1949 | [[package]] 1950 | name = "tokio-util" 1951 | version = "0.7.7" 1952 | source = "registry+https://github.com/rust-lang/crates.io-index" 1953 | checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" 1954 | dependencies = [ 1955 | "bytes", 1956 | "futures-core", 1957 | "futures-sink", 1958 | "pin-project-lite", 1959 | "tokio", 1960 | "tracing", 1961 | ] 1962 | 1963 | [[package]] 1964 | name = "toml" 1965 | version = "0.5.11" 1966 | source = "registry+https://github.com/rust-lang/crates.io-index" 1967 | checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" 1968 | dependencies = [ 1969 | "serde", 1970 | ] 1971 | 1972 | [[package]] 1973 | name = "toml" 1974 | version = "0.7.3" 1975 | source = "registry+https://github.com/rust-lang/crates.io-index" 1976 | checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" 1977 | dependencies = [ 1978 | "serde", 1979 | "serde_spanned", 1980 | "toml_datetime", 1981 | "toml_edit", 1982 | ] 1983 | 1984 | [[package]] 1985 | name = "toml_datetime" 1986 | version = "0.6.1" 1987 | source = "registry+https://github.com/rust-lang/crates.io-index" 1988 | checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" 1989 | dependencies = [ 1990 | "serde", 1991 | ] 1992 | 1993 | [[package]] 1994 | name = "toml_edit" 1995 | version = "0.19.8" 1996 | source = "registry+https://github.com/rust-lang/crates.io-index" 1997 | checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" 1998 | dependencies = [ 1999 | "indexmap", 2000 | "serde", 2001 | "serde_spanned", 2002 | "toml_datetime", 2003 | "winnow", 2004 | ] 2005 | 2006 | [[package]] 2007 | name = "tower-service" 2008 | version = "0.3.2" 2009 | source = "registry+https://github.com/rust-lang/crates.io-index" 2010 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 2011 | 2012 | [[package]] 2013 | name = "tracing" 2014 | version = "0.1.37" 2015 | source = "registry+https://github.com/rust-lang/crates.io-index" 2016 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 2017 | dependencies = [ 2018 | "cfg-if", 2019 | "pin-project-lite", 2020 | "tracing-attributes", 2021 | "tracing-core", 2022 | ] 2023 | 2024 | [[package]] 2025 | name = "tracing-attributes" 2026 | version = "0.1.23" 2027 | source = "registry+https://github.com/rust-lang/crates.io-index" 2028 | checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" 2029 | dependencies = [ 2030 | "proc-macro2", 2031 | "quote", 2032 | "syn 1.0.109", 2033 | ] 2034 | 2035 | [[package]] 2036 | name = "tracing-core" 2037 | version = "0.1.30" 2038 | source = "registry+https://github.com/rust-lang/crates.io-index" 2039 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" 2040 | dependencies = [ 2041 | "once_cell", 2042 | "valuable", 2043 | ] 2044 | 2045 | [[package]] 2046 | name = "tracing-log" 2047 | version = "0.1.3" 2048 | source = "registry+https://github.com/rust-lang/crates.io-index" 2049 | checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" 2050 | dependencies = [ 2051 | "lazy_static", 2052 | "log", 2053 | "tracing-core", 2054 | ] 2055 | 2056 | [[package]] 2057 | name = "tracing-subscriber" 2058 | version = "0.3.16" 2059 | source = "registry+https://github.com/rust-lang/crates.io-index" 2060 | checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" 2061 | dependencies = [ 2062 | "matchers", 2063 | "nu-ansi-term", 2064 | "once_cell", 2065 | "regex", 2066 | "sharded-slab", 2067 | "smallvec", 2068 | "thread_local", 2069 | "tracing", 2070 | "tracing-core", 2071 | "tracing-log", 2072 | ] 2073 | 2074 | [[package]] 2075 | name = "trust-dns-proto" 2076 | version = "0.22.0" 2077 | source = "registry+https://github.com/rust-lang/crates.io-index" 2078 | checksum = "4f7f83d1e4a0e4358ac54c5c3681e5d7da5efc5a7a632c90bb6d6669ddd9bc26" 2079 | dependencies = [ 2080 | "async-trait", 2081 | "cfg-if", 2082 | "data-encoding", 2083 | "enum-as-inner", 2084 | "futures-channel", 2085 | "futures-io", 2086 | "futures-util", 2087 | "idna 0.2.3", 2088 | "ipnet", 2089 | "lazy_static", 2090 | "rand", 2091 | "smallvec", 2092 | "thiserror", 2093 | "tinyvec", 2094 | "tokio", 2095 | "tracing", 2096 | "url", 2097 | ] 2098 | 2099 | [[package]] 2100 | name = "trust-dns-resolver" 2101 | version = "0.22.0" 2102 | source = "registry+https://github.com/rust-lang/crates.io-index" 2103 | checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe" 2104 | dependencies = [ 2105 | "cfg-if", 2106 | "futures-util", 2107 | "ipconfig", 2108 | "lazy_static", 2109 | "lru-cache", 2110 | "parking_lot", 2111 | "resolv-conf", 2112 | "smallvec", 2113 | "thiserror", 2114 | "tokio", 2115 | "tracing", 2116 | "trust-dns-proto", 2117 | ] 2118 | 2119 | [[package]] 2120 | name = "try-lock" 2121 | version = "0.2.4" 2122 | source = "registry+https://github.com/rust-lang/crates.io-index" 2123 | checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" 2124 | 2125 | [[package]] 2126 | name = "ts-bookkeeping" 2127 | version = "0.1.0" 2128 | source = "git+https://github.com/ReSpeak/tsclientlib#315f882872771bef6160c7328e56b53f064b7133" 2129 | dependencies = [ 2130 | "base64 0.13.1", 2131 | "heck", 2132 | "itertools", 2133 | "num-derive", 2134 | "num-traits", 2135 | "serde", 2136 | "t4rust-derive", 2137 | "thiserror", 2138 | "time", 2139 | "tracing", 2140 | "tsproto-packets", 2141 | "tsproto-structs", 2142 | "tsproto-types", 2143 | ] 2144 | 2145 | [[package]] 2146 | name = "tsclientlib" 2147 | version = "0.2.0" 2148 | source = "git+https://github.com/ReSpeak/tsclientlib#315f882872771bef6160c7328e56b53f064b7133" 2149 | dependencies = [ 2150 | "base64 0.13.1", 2151 | "futures", 2152 | "git-testament", 2153 | "itertools", 2154 | "num-traits", 2155 | "pin-utils", 2156 | "rand", 2157 | "reqwest", 2158 | "thiserror", 2159 | "time", 2160 | "tokio", 2161 | "tokio-stream", 2162 | "tracing", 2163 | "trust-dns-proto", 2164 | "trust-dns-resolver", 2165 | "ts-bookkeeping", 2166 | "tsproto", 2167 | "tsproto-packets", 2168 | "tsproto-types", 2169 | "url", 2170 | ] 2171 | 2172 | [[package]] 2173 | name = "tsproto" 2174 | version = "0.2.0" 2175 | source = "git+https://github.com/ReSpeak/tsclientlib#315f882872771bef6160c7328e56b53f064b7133" 2176 | dependencies = [ 2177 | "aes", 2178 | "base64 0.13.1", 2179 | "bitflags", 2180 | "curve25519-dalek-ng", 2181 | "eax", 2182 | "futures", 2183 | "generic-array", 2184 | "git-testament", 2185 | "num-bigint", 2186 | "num-derive", 2187 | "num-traits", 2188 | "omnom", 2189 | "pin-project-lite", 2190 | "quicklz", 2191 | "rand", 2192 | "serde", 2193 | "sha-1", 2194 | "sha2", 2195 | "thiserror", 2196 | "time", 2197 | "tokio", 2198 | "tracing", 2199 | "tsproto-packets", 2200 | "tsproto-types", 2201 | ] 2202 | 2203 | [[package]] 2204 | name = "tsproto-packets" 2205 | version = "0.1.0" 2206 | source = "git+https://github.com/ReSpeak/tsclientlib#315f882872771bef6160c7328e56b53f064b7133" 2207 | dependencies = [ 2208 | "base64 0.13.1", 2209 | "bitflags", 2210 | "num-derive", 2211 | "num-traits", 2212 | "omnom", 2213 | "self_cell", 2214 | "serde", 2215 | "thiserror", 2216 | ] 2217 | 2218 | [[package]] 2219 | name = "tsproto-structs" 2220 | version = "0.2.0" 2221 | source = "git+https://github.com/ReSpeak/tsclientlib#315f882872771bef6160c7328e56b53f064b7133" 2222 | dependencies = [ 2223 | "base64 0.13.1", 2224 | "csv", 2225 | "heck", 2226 | "once_cell", 2227 | "serde", 2228 | "toml 0.5.11", 2229 | ] 2230 | 2231 | [[package]] 2232 | name = "tsproto-types" 2233 | version = "0.1.0" 2234 | source = "git+https://github.com/ReSpeak/tsclientlib#315f882872771bef6160c7328e56b53f064b7133" 2235 | dependencies = [ 2236 | "base64 0.13.1", 2237 | "bitflags", 2238 | "curve25519-dalek-ng", 2239 | "elliptic-curve", 2240 | "generic-array", 2241 | "heck", 2242 | "num-bigint", 2243 | "num-derive", 2244 | "num-traits", 2245 | "p256", 2246 | "rand", 2247 | "ref-cast", 2248 | "serde", 2249 | "sha-1", 2250 | "simple_asn1", 2251 | "t4rust-derive", 2252 | "thiserror", 2253 | "time", 2254 | "tsproto-structs", 2255 | ] 2256 | 2257 | [[package]] 2258 | name = "typenum" 2259 | version = "1.16.0" 2260 | source = "registry+https://github.com/rust-lang/crates.io-index" 2261 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 2262 | 2263 | [[package]] 2264 | name = "unicode-bidi" 2265 | version = "0.3.13" 2266 | source = "registry+https://github.com/rust-lang/crates.io-index" 2267 | checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" 2268 | 2269 | [[package]] 2270 | name = "unicode-ident" 2271 | version = "1.0.8" 2272 | source = "registry+https://github.com/rust-lang/crates.io-index" 2273 | checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" 2274 | 2275 | [[package]] 2276 | name = "unicode-normalization" 2277 | version = "0.1.22" 2278 | source = "registry+https://github.com/rust-lang/crates.io-index" 2279 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 2280 | dependencies = [ 2281 | "tinyvec", 2282 | ] 2283 | 2284 | [[package]] 2285 | name = "url" 2286 | version = "2.3.1" 2287 | source = "registry+https://github.com/rust-lang/crates.io-index" 2288 | checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" 2289 | dependencies = [ 2290 | "form_urlencoded", 2291 | "idna 0.3.0", 2292 | "percent-encoding", 2293 | ] 2294 | 2295 | [[package]] 2296 | name = "utf8parse" 2297 | version = "0.2.1" 2298 | source = "registry+https://github.com/rust-lang/crates.io-index" 2299 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 2300 | 2301 | [[package]] 2302 | name = "valuable" 2303 | version = "0.1.0" 2304 | source = "registry+https://github.com/rust-lang/crates.io-index" 2305 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 2306 | 2307 | [[package]] 2308 | name = "vcpkg" 2309 | version = "0.2.15" 2310 | source = "registry+https://github.com/rust-lang/crates.io-index" 2311 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2312 | 2313 | [[package]] 2314 | name = "version_check" 2315 | version = "0.9.4" 2316 | source = "registry+https://github.com/rust-lang/crates.io-index" 2317 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 2318 | 2319 | [[package]] 2320 | name = "want" 2321 | version = "0.3.0" 2322 | source = "registry+https://github.com/rust-lang/crates.io-index" 2323 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 2324 | dependencies = [ 2325 | "log", 2326 | "try-lock", 2327 | ] 2328 | 2329 | [[package]] 2330 | name = "wasi" 2331 | version = "0.11.0+wasi-snapshot-preview1" 2332 | source = "registry+https://github.com/rust-lang/crates.io-index" 2333 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 2334 | 2335 | [[package]] 2336 | name = "wasm-bindgen" 2337 | version = "0.2.84" 2338 | source = "registry+https://github.com/rust-lang/crates.io-index" 2339 | checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" 2340 | dependencies = [ 2341 | "cfg-if", 2342 | "wasm-bindgen-macro", 2343 | ] 2344 | 2345 | [[package]] 2346 | name = "wasm-bindgen-backend" 2347 | version = "0.2.84" 2348 | source = "registry+https://github.com/rust-lang/crates.io-index" 2349 | checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" 2350 | dependencies = [ 2351 | "bumpalo", 2352 | "log", 2353 | "once_cell", 2354 | "proc-macro2", 2355 | "quote", 2356 | "syn 1.0.109", 2357 | "wasm-bindgen-shared", 2358 | ] 2359 | 2360 | [[package]] 2361 | name = "wasm-bindgen-futures" 2362 | version = "0.4.34" 2363 | source = "registry+https://github.com/rust-lang/crates.io-index" 2364 | checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" 2365 | dependencies = [ 2366 | "cfg-if", 2367 | "js-sys", 2368 | "wasm-bindgen", 2369 | "web-sys", 2370 | ] 2371 | 2372 | [[package]] 2373 | name = "wasm-bindgen-macro" 2374 | version = "0.2.84" 2375 | source = "registry+https://github.com/rust-lang/crates.io-index" 2376 | checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" 2377 | dependencies = [ 2378 | "quote", 2379 | "wasm-bindgen-macro-support", 2380 | ] 2381 | 2382 | [[package]] 2383 | name = "wasm-bindgen-macro-support" 2384 | version = "0.2.84" 2385 | source = "registry+https://github.com/rust-lang/crates.io-index" 2386 | checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" 2387 | dependencies = [ 2388 | "proc-macro2", 2389 | "quote", 2390 | "syn 1.0.109", 2391 | "wasm-bindgen-backend", 2392 | "wasm-bindgen-shared", 2393 | ] 2394 | 2395 | [[package]] 2396 | name = "wasm-bindgen-shared" 2397 | version = "0.2.84" 2398 | source = "registry+https://github.com/rust-lang/crates.io-index" 2399 | checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" 2400 | 2401 | [[package]] 2402 | name = "web-sys" 2403 | version = "0.3.61" 2404 | source = "registry+https://github.com/rust-lang/crates.io-index" 2405 | checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" 2406 | dependencies = [ 2407 | "js-sys", 2408 | "wasm-bindgen", 2409 | ] 2410 | 2411 | [[package]] 2412 | name = "widestring" 2413 | version = "0.5.1" 2414 | source = "registry+https://github.com/rust-lang/crates.io-index" 2415 | checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" 2416 | 2417 | [[package]] 2418 | name = "winapi" 2419 | version = "0.3.9" 2420 | source = "registry+https://github.com/rust-lang/crates.io-index" 2421 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2422 | dependencies = [ 2423 | "winapi-i686-pc-windows-gnu", 2424 | "winapi-x86_64-pc-windows-gnu", 2425 | ] 2426 | 2427 | [[package]] 2428 | name = "winapi-i686-pc-windows-gnu" 2429 | version = "0.4.0" 2430 | source = "registry+https://github.com/rust-lang/crates.io-index" 2431 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2432 | 2433 | [[package]] 2434 | name = "winapi-x86_64-pc-windows-gnu" 2435 | version = "0.4.0" 2436 | source = "registry+https://github.com/rust-lang/crates.io-index" 2437 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2438 | 2439 | [[package]] 2440 | name = "windows-sys" 2441 | version = "0.42.0" 2442 | source = "registry+https://github.com/rust-lang/crates.io-index" 2443 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 2444 | dependencies = [ 2445 | "windows_aarch64_gnullvm 0.42.2", 2446 | "windows_aarch64_msvc 0.42.2", 2447 | "windows_i686_gnu 0.42.2", 2448 | "windows_i686_msvc 0.42.2", 2449 | "windows_x86_64_gnu 0.42.2", 2450 | "windows_x86_64_gnullvm 0.42.2", 2451 | "windows_x86_64_msvc 0.42.2", 2452 | ] 2453 | 2454 | [[package]] 2455 | name = "windows-sys" 2456 | version = "0.45.0" 2457 | source = "registry+https://github.com/rust-lang/crates.io-index" 2458 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 2459 | dependencies = [ 2460 | "windows-targets 0.42.2", 2461 | ] 2462 | 2463 | [[package]] 2464 | name = "windows-sys" 2465 | version = "0.48.0" 2466 | source = "registry+https://github.com/rust-lang/crates.io-index" 2467 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 2468 | dependencies = [ 2469 | "windows-targets 0.48.0", 2470 | ] 2471 | 2472 | [[package]] 2473 | name = "windows-targets" 2474 | version = "0.42.2" 2475 | source = "registry+https://github.com/rust-lang/crates.io-index" 2476 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 2477 | dependencies = [ 2478 | "windows_aarch64_gnullvm 0.42.2", 2479 | "windows_aarch64_msvc 0.42.2", 2480 | "windows_i686_gnu 0.42.2", 2481 | "windows_i686_msvc 0.42.2", 2482 | "windows_x86_64_gnu 0.42.2", 2483 | "windows_x86_64_gnullvm 0.42.2", 2484 | "windows_x86_64_msvc 0.42.2", 2485 | ] 2486 | 2487 | [[package]] 2488 | name = "windows-targets" 2489 | version = "0.48.0" 2490 | source = "registry+https://github.com/rust-lang/crates.io-index" 2491 | checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" 2492 | dependencies = [ 2493 | "windows_aarch64_gnullvm 0.48.0", 2494 | "windows_aarch64_msvc 0.48.0", 2495 | "windows_i686_gnu 0.48.0", 2496 | "windows_i686_msvc 0.48.0", 2497 | "windows_x86_64_gnu 0.48.0", 2498 | "windows_x86_64_gnullvm 0.48.0", 2499 | "windows_x86_64_msvc 0.48.0", 2500 | ] 2501 | 2502 | [[package]] 2503 | name = "windows_aarch64_gnullvm" 2504 | version = "0.42.2" 2505 | source = "registry+https://github.com/rust-lang/crates.io-index" 2506 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 2507 | 2508 | [[package]] 2509 | name = "windows_aarch64_gnullvm" 2510 | version = "0.48.0" 2511 | source = "registry+https://github.com/rust-lang/crates.io-index" 2512 | checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" 2513 | 2514 | [[package]] 2515 | name = "windows_aarch64_msvc" 2516 | version = "0.42.2" 2517 | source = "registry+https://github.com/rust-lang/crates.io-index" 2518 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 2519 | 2520 | [[package]] 2521 | name = "windows_aarch64_msvc" 2522 | version = "0.48.0" 2523 | source = "registry+https://github.com/rust-lang/crates.io-index" 2524 | checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" 2525 | 2526 | [[package]] 2527 | name = "windows_i686_gnu" 2528 | version = "0.42.2" 2529 | source = "registry+https://github.com/rust-lang/crates.io-index" 2530 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 2531 | 2532 | [[package]] 2533 | name = "windows_i686_gnu" 2534 | version = "0.48.0" 2535 | source = "registry+https://github.com/rust-lang/crates.io-index" 2536 | checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" 2537 | 2538 | [[package]] 2539 | name = "windows_i686_msvc" 2540 | version = "0.42.2" 2541 | source = "registry+https://github.com/rust-lang/crates.io-index" 2542 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 2543 | 2544 | [[package]] 2545 | name = "windows_i686_msvc" 2546 | version = "0.48.0" 2547 | source = "registry+https://github.com/rust-lang/crates.io-index" 2548 | checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" 2549 | 2550 | [[package]] 2551 | name = "windows_x86_64_gnu" 2552 | version = "0.42.2" 2553 | source = "registry+https://github.com/rust-lang/crates.io-index" 2554 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 2555 | 2556 | [[package]] 2557 | name = "windows_x86_64_gnu" 2558 | version = "0.48.0" 2559 | source = "registry+https://github.com/rust-lang/crates.io-index" 2560 | checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" 2561 | 2562 | [[package]] 2563 | name = "windows_x86_64_gnullvm" 2564 | version = "0.42.2" 2565 | source = "registry+https://github.com/rust-lang/crates.io-index" 2566 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 2567 | 2568 | [[package]] 2569 | name = "windows_x86_64_gnullvm" 2570 | version = "0.48.0" 2571 | source = "registry+https://github.com/rust-lang/crates.io-index" 2572 | checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" 2573 | 2574 | [[package]] 2575 | name = "windows_x86_64_msvc" 2576 | version = "0.42.2" 2577 | source = "registry+https://github.com/rust-lang/crates.io-index" 2578 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 2579 | 2580 | [[package]] 2581 | name = "windows_x86_64_msvc" 2582 | version = "0.48.0" 2583 | source = "registry+https://github.com/rust-lang/crates.io-index" 2584 | checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" 2585 | 2586 | [[package]] 2587 | name = "winnow" 2588 | version = "0.4.1" 2589 | source = "registry+https://github.com/rust-lang/crates.io-index" 2590 | checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" 2591 | dependencies = [ 2592 | "memchr", 2593 | ] 2594 | 2595 | [[package]] 2596 | name = "winreg" 2597 | version = "0.10.1" 2598 | source = "registry+https://github.com/rust-lang/crates.io-index" 2599 | checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" 2600 | dependencies = [ 2601 | "winapi", 2602 | ] 2603 | 2604 | [[package]] 2605 | name = "zeroize" 2606 | version = "1.6.0" 2607 | source = "registry+https://github.com/rust-lang/crates.io-index" 2608 | checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" 2609 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simple-bot" 3 | version = "0.2.0" 4 | authors = ["Flakebi "] 5 | edition = "2021" 6 | 7 | [[bin]] 8 | name = "simple-bot" 9 | 10 | [profile.release] 11 | debug = true 12 | 13 | [dependencies] 14 | anyhow = "1" 15 | base64 = "0.21" 16 | directories-next = "2" 17 | futures = "0.3" 18 | regex = "1" 19 | serde = { version = "1", features = ["derive"] } 20 | clap = { version = "4", features = ["derive"] } 21 | tokio = { version = "1", features = ["signal"] } 22 | toml = "0.7" 23 | tracing = "0.1" 24 | tracing-subscriber = { version = "0.3", features = [ "env-filter" ] } 25 | tsclientlib = { git = "https://github.com/ReSpeak/tsclientlib", default-features = false } 26 | # TODO Needed to load the private key 27 | tsproto-types = { git = "https://github.com/ReSpeak/tsclientlib" } 28 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Sebastian Neubauer 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 | # SimpleBot [![Build status](https://ci.appveyor.com/api/projects/status/p2og3vtd60boblbw/branch/master?svg=true)](https://ci.appveyor.com/project/Flakebi/simplebot/branch/master) 2 | 3 | This is a simple TeamSpeak chat bot. It connects as a usual client and responds to some messages. The bot originally was built to test and showcase the capabilities of the [tsclientlib](https://github.com/ReSpeak/tsclientlib) library, though it developed into a more sophisticated and usable bot. 4 | 5 | ## Dependencies 6 | - [OpenSSL](https://www.openssl.org) 1.1 (not needed on windows) 7 | - [Rust](https://rust-lang.org) (only needed if you want to compile the bot yourself, the preferred installation method is [rustup](https://rustup.rs)), currently the nightly version is needed 8 | 9 | Binary downloads of SimpleBot can be found [here](https://splamy.de/Nightly). 10 | 11 | ## Usage 12 | Use a settings file with `./simple-bot --settings settings.toml` or put it in the configuration directory of your system, which should be 13 | 14 | - Linux: `.config/simple-bot/` 15 | - Windows: `%APPDATA%/ReSpeak/simple-bot/config/` 16 | - macOS: `Library/Preferences/ReSpeak.simple-bot/` 17 | 18 | ## Features 19 | The bot gets triggered by certain words, which then leads to a response. 20 | 21 | These actions can be defined e.g. using the builtin commands. 22 | These can be used in any chat with the bot (you can even poke him with your requests). 23 | ``` 24 | .help 25 | # List all commands 26 | .list 27 | .add on 28 | .del 29 | # Reload the configuration 30 | .reload 31 | # Disconnect the bot 32 | .quit 33 | ``` 34 | 35 | Examples: 36 | ``` 37 | .list 38 | .add Please read the [URL=…]faq[/URL] on question 39 | # Trigger the response 40 | I have a question 41 | # Will not trigger the response 42 | This is questionable. 43 | .del question 44 | ``` 45 | 46 | **Note**: The `trigger` will only match whole words. So in the example before, the response will be triggered on `I have a question` but not on `This is questionable`. 47 | The matching is case sensitive, so `Question` will also not trigger the response. 48 | 49 | ## Configuration 50 | The bot supports a simple configuration in a `settings.toml` file. The default options are 51 | ```toml 52 | # The server to connect to 53 | address = "localhost" 54 | # The channel to connect to 55 | # This can be e.g. 4, "My Channel" or "My Channel/Nested" 56 | channel = "" 57 | # The name of the bot 58 | name = "SimpleBot" 59 | # How many responses can be sent per second 60 | rate_limit = 2 61 | # The prefix for builtin commands 62 | prefix = "." 63 | 64 | # The path to the private key file 65 | key_file = "private.key" 66 | # The file to store dynamically added actions 67 | dynamic_actions = "dynamic.toml" 68 | ``` 69 | 70 | Additionally, more complex behaviour can be defined in the configuration file. 71 | This allows triggers on regular expressions instead of static strings and also gives the ability to execute arbitrary scripts. 72 | The bot will first search for a matching action in the settings, then in the builtins and afterwards in the dynamic actions (the ones which were added with `.add`). 73 | The format is: 74 | ```toml 75 | [[actions.on_message]] 76 | # Trigger 77 | # contains and regex cannot be defined together, though it is ok to define none 78 | # of them which will match every message. 79 | contains = "simple string, like added with .add" 80 | regex = "(?i)e.g. case invariant" 81 | # The way the message is received. 82 | chat = "server|channel|client|poke" 83 | 84 | # Reaction 85 | # At maximum one of the reactions can be defined 86 | # A response of this type is added by the .add builtin command. 87 | response = "plain response" 88 | # Run a script, the arguments will be splitted at spaces and the following 89 | # arguments will be added: 90 | # - Chat mode (server|channel|client|poke) 91 | # - Message 92 | # - Username 93 | # - User uid (optional): This can be used to uniquely identify a user, it will 94 | # not be set when a global server message is received. 95 | command = "python3 ./script.py" 96 | # Run the command in a shell so pipes can be used, etc. The same arguments as 97 | # for commands will be passed, make sure to escape them! 98 | shell = "echo Hi, \"$3\"" 99 | ``` 100 | 101 | If a command is executed and returns `-1` as status code, the action of this command will be skipped and the next matching action will be executed. 102 | This can be used to e.g. allow only certain users to quit the bot: 103 | ```toml 104 | [[actions.on_message]] 105 | regex = "^\\.(del|quit)" 106 | # This is unix specific, on windows this should be another command. 107 | shell = "grep -Fqv \"$4\" whitelist.txt" 108 | ``` 109 | And create a file `whitelist.txt`: 110 | ``` 111 | One uid per line 112 | ``` 113 | 114 | For every incomming message that starts with `.del` or `.quit`, the uid will be searched in the whitelist file. 115 | If the uid is found, `grep` will exit with code `1`, the bot will skip this action and the `.quit` command will be executed. 116 | If the uid is *not* found, `grep` will exit with code `0` and the bot will respond with the command output and not execute `.quit`. As the command output is empty, it will be ignored. 117 | 118 | ## License 119 | Licensed under either of 120 | 121 | * [Apache License, Version 2.0](LICENSE-APACHE) 122 | * [MIT license](LICENSE-MIT) 123 | 124 | at your option. 125 | -------------------------------------------------------------------------------- /src/action.rs: -------------------------------------------------------------------------------- 1 | use std::borrow::Cow; 2 | use std::fmt; 3 | use std::process::Command; 4 | 5 | use anyhow::{bail, Result}; 6 | use base64::{prelude::BASE64_STANDARD, Engine as _}; 7 | use regex::Regex; 8 | use serde::{Deserialize, Serialize}; 9 | use tracing::error; 10 | use tsclientlib::{Connection, MessageTarget, TextMessageTargetMode}; 11 | 12 | use crate::{Bot, Message}; 13 | 14 | #[derive(Clone, Debug, Default, Deserialize, Serialize)] 15 | #[serde(deny_unknown_fields)] 16 | pub struct ActionDefinition { 17 | // Matcher 18 | /// Plain string 19 | pub contains: Option, 20 | /// Regex 21 | pub regex: Option, 22 | /// Check the chat mode for the message: Either `server`, `channel`, 23 | /// `client` or `poke`. 24 | pub chat: Option, 25 | 26 | // Reaction 27 | /// A simple string response. 28 | pub response: Option, 29 | /// Execute program 30 | pub command: Option, 31 | /// Execute command in a shell 32 | pub shell: Option, 33 | } 34 | 35 | #[derive(Default, Debug)] 36 | pub struct ActionList(pub Vec); 37 | 38 | #[derive(Default, Debug)] 39 | pub struct Action { 40 | /// All matchers have to match for the reaction to be executed. 41 | pub matchers: Vec, 42 | /// If empty and this action matches, no action will be executed. 43 | pub reaction: Option, 44 | } 45 | 46 | #[derive(Clone, Debug)] 47 | pub enum Matcher { 48 | Regex(Regex), 49 | /// If this is `None`, it means poke. 50 | Mode(Option), 51 | } 52 | 53 | type ReactionFunction = Box< 54 | dyn for<'a> Fn(&Bot, &mut Connection, &'a Message) -> Option> 55 | + Send 56 | + Sync, 57 | >; 58 | pub enum Reaction { 59 | Plain(String), 60 | Command(String), 61 | Shell(String), 62 | Function(ReactionFunction), 63 | } 64 | 65 | impl fmt::Debug for Reaction { 66 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 67 | match self { 68 | Reaction::Plain(s) => write!(f, "Reaction::Plain({})", s), 69 | Reaction::Command(s) => write!(f, "Reaction::Command({})", s), 70 | Reaction::Shell(s) => write!(f, "Reaction::Shell({})", s), 71 | Reaction::Function(_) => write!(f, "Reaction::Function()"), 72 | } 73 | } 74 | } 75 | 76 | impl ActionDefinition { 77 | pub fn to_action(&self) -> Result { 78 | // Condition 79 | let mut res = Action::default(); 80 | if let Some(contains) = &self.contains { 81 | if let Some(matches) = &self.regex { 82 | bail!( 83 | "An action can only have either contains or matches. This \ 84 | one contains both ({} and {})", 85 | contains, 86 | matches 87 | ); 88 | } 89 | // Only match string at word boundaries 90 | // Add \b only if the first/last character is alphabetix. 91 | let mut regex = regex::escape(contains); 92 | if regex 93 | .chars() 94 | .next() 95 | .map(|c| c.is_alphabetic()) 96 | .unwrap_or(false) 97 | { 98 | regex = format!(r"\b{}", regex); 99 | } 100 | if regex 101 | .chars() 102 | .last() 103 | .map(|c| c.is_alphabetic()) 104 | .unwrap_or(false) 105 | { 106 | regex = format!(r"{}\b", regex); 107 | } 108 | res.matchers.push(Matcher::Regex(Regex::new(®ex)?)); 109 | } else if let Some(matches) = &self.regex { 110 | res.matchers.push(Matcher::Regex(Regex::new(matches)?)); 111 | } 112 | 113 | if let Some(chat) = &self.chat { 114 | let mode = match chat.as_str() { 115 | "server" => Some(TextMessageTargetMode::Server), 116 | "channel" => Some(TextMessageTargetMode::Channel), 117 | "client" => Some(TextMessageTargetMode::Client), 118 | "poke" => None, 119 | s => bail!( 120 | "Chat mode must be server, channel, client or poke. '{}' \ 121 | is not allowed.", 122 | s 123 | ), 124 | }; 125 | res.matchers.push(Matcher::Mode(mode)); 126 | } 127 | 128 | // Reaction 129 | let mut counter = 0; 130 | if let Some(r) = &self.response { 131 | res.reaction = Some(Reaction::Plain(r.to_string())); 132 | counter += 1; 133 | } 134 | if let Some(c) = &self.command { 135 | res.reaction = Some(Reaction::Command(c.to_string())); 136 | counter += 1; 137 | } 138 | if let Some(s) = &self.shell { 139 | res.reaction = Some(Reaction::Shell(s.to_string())); 140 | counter += 1; 141 | } 142 | 143 | if counter > 1 { 144 | bail!("Only one reaction (response, command or shell) is allowed."); 145 | } 146 | 147 | Ok(res) 148 | } 149 | } 150 | 151 | impl Matcher { 152 | pub fn matches(&self, msg: &Message) -> bool { 153 | match self { 154 | Matcher::Regex(r) => r.is_match(msg.message), 155 | Matcher::Mode(m) => match m { 156 | Some(TextMessageTargetMode::Server) => { 157 | matches!(msg.target, MessageTarget::Server) 158 | } 159 | Some(TextMessageTargetMode::Channel) => { 160 | matches!(msg.target, MessageTarget::Channel) 161 | } 162 | Some(TextMessageTargetMode::Client) => { 163 | matches!(msg.target, MessageTarget::Client(_)) 164 | } 165 | Some(TextMessageTargetMode::Unknown) => false, 166 | None => { 167 | matches!(msg.target, MessageTarget::Poke(_)) 168 | } 169 | }, 170 | } 171 | } 172 | } 173 | 174 | impl Reaction { 175 | pub fn get_target(m: &MessageTarget) -> &'static str { 176 | match m { 177 | MessageTarget::Server => "server", 178 | MessageTarget::Channel => "channel", 179 | MessageTarget::Client(_) => "client", 180 | MessageTarget::Poke(_) => "poke", 181 | } 182 | } 183 | 184 | pub fn get_mode(m: &Option) -> &'static str { 185 | match m { 186 | Some(TextMessageTargetMode::Server) => "server", 187 | Some(TextMessageTargetMode::Channel) => "channel", 188 | Some(TextMessageTargetMode::Client) => "client", 189 | Some(TextMessageTargetMode::Unknown) => { 190 | panic!("Unknown TextMessageTargetMode") 191 | } 192 | None => "poke", 193 | } 194 | } 195 | 196 | /// If `None` is returned, the next action should be tested. 197 | pub fn execute<'a>( 198 | &'a self, 199 | bot: &Bot, 200 | con: &mut Connection, 201 | msg: &'a Message, 202 | ) -> Option> { 203 | match self { 204 | Reaction::Plain(s) => Some(Cow::Borrowed(s.as_str())), 205 | Reaction::Command(s) | Reaction::Shell(s) => { 206 | let output; 207 | if let Reaction::Command(_) = self { 208 | // Split arguments at spaces 209 | let mut split = s.split(' '); 210 | let mut cmd = Command::new(split.next().unwrap()); 211 | cmd.args(split) 212 | // Arguments 213 | .arg(Self::get_target(&msg.target)) 214 | .arg(msg.message) 215 | .arg(msg.invoker.name); 216 | if let Some(uid) = &msg.invoker.uid { 217 | cmd.arg(&BASE64_STANDARD.encode(&uid.0)); 218 | } 219 | output = cmd.output(); 220 | } else { 221 | // Shell 222 | #[cfg(target_family = "unix")] 223 | { 224 | let mut cmd = Command::new("sh"); 225 | cmd 226 | .arg("-c") 227 | .arg(s) 228 | // Program name 229 | .arg("sh") 230 | // Arguments 231 | .arg(Self::get_target(&msg.target)) 232 | .arg(msg.message) 233 | .arg(msg.invoker.name); 234 | if let Some(uid) = &msg.invoker.uid { 235 | cmd.arg(&BASE64_STANDARD.encode(&uid.0)); 236 | } 237 | output = cmd.output(); 238 | } 239 | 240 | #[cfg(not(target_family = "unix"))] 241 | { 242 | // Windows is untested 243 | let mut cmd = Command::new("cmd"); 244 | cmd 245 | .arg("/C") 246 | .arg(s) 247 | // Arguments 248 | .arg(Self::get_target(&msg.target)) 249 | .arg(msg.message) 250 | .arg(msg.invoker.name); 251 | if let Some(uid) = &msg.invoker.uid { 252 | cmd.arg(&base64::encode(&uid.0)); 253 | } 254 | output = cmd.output(); 255 | } 256 | } 257 | 258 | let output = match output { 259 | Ok(o) => o, 260 | Err(error) => { 261 | error!(%error, command = s.as_str(), "Failed to execute shell"); 262 | // Don't proceed 263 | return Some("".into()); 264 | } 265 | }; 266 | if !output.status.success() { 267 | // Skip and try next action 268 | return None; 269 | } 270 | 271 | // Try to parse result 272 | let res = match std::str::from_utf8(&output.stdout) { 273 | Ok(r) => r, 274 | Err(error) => { 275 | error!(%error, command = s.as_str(), output = ?output.stdout, "Failed to parse output"); 276 | // Don't proceed 277 | return Some("".into()); 278 | } 279 | }; 280 | 281 | Some(res.to_string().into()) 282 | } 283 | Reaction::Function(f) => f(bot, con, msg), 284 | } 285 | } 286 | } 287 | 288 | impl ActionList { 289 | pub fn handle<'a>( 290 | &'a self, 291 | bot: &Bot, 292 | con: &mut Connection, 293 | msg: &'a Message, 294 | ) -> Option> { 295 | 'actions: for a in &self.0 { 296 | for m in &a.matchers { 297 | if !m.matches(msg) { 298 | continue 'actions; 299 | } 300 | } 301 | 302 | if let Some(a) = &a.reaction { 303 | if let Some(res) = a.execute(bot, con, msg) { 304 | if res == "" { 305 | return None; 306 | } else { 307 | return Some(res); 308 | } 309 | } 310 | } else { 311 | return None; 312 | } 313 | } 314 | None 315 | } 316 | } 317 | -------------------------------------------------------------------------------- /src/builtins.rs: -------------------------------------------------------------------------------- 1 | use std::borrow::Cow; 2 | use std::fmt::Write; 3 | use std::fs; 4 | use std::path::Path; 5 | 6 | use regex::Regex; 7 | use tracing::{debug, error, info}; 8 | use tsclientlib::{Connection, DisconnectOptions}; 9 | 10 | use crate::action::*; 11 | use crate::{ActionFile, Bot, Message}; 12 | 13 | /// Add builtin functions to the end of the action list. 14 | pub fn init(bot: &mut Bot) { 15 | let p = regex::escape(&bot.settings.prefix); 16 | 17 | let help_regex = Regex::new(&format!("^{}help", p)).unwrap(); 18 | add_fun(bot, help_regex, |b, _, _| help(b)); 19 | 20 | let copy_regex = Regex::new(&format!("^{}copy", p)).unwrap(); 21 | add_fun(bot, copy_regex, |_, _, _| copyright()); 22 | 23 | let list_regex = Regex::new(&format!("^{}list", p)).unwrap(); 24 | add_fun(bot, list_regex, move |b, _, m| list(b, m)); 25 | 26 | let add_regex = Regex::new(&format!("^{}add", p)).unwrap(); 27 | let long_add_regex = 28 | Regex::new(&format!("^{}add (?P.*) on (?P.*)$", p)) 29 | .unwrap(); 30 | add_fun(bot, add_regex, move |b, _, m| add(b, &long_add_regex, m)); 31 | 32 | let del_regex = Regex::new(&format!("^{}del", p)).unwrap(); 33 | let long_del_regex = 34 | Regex::new(&format!("^{}del (?P.*)$", p)).unwrap(); 35 | add_fun(bot, del_regex, move |b, _, m| del(b, &long_del_regex, m)); 36 | 37 | let reload_regex = Regex::new(&format!("^{}reload$", p)).unwrap(); 38 | add_fun(bot, reload_regex, move |b, _, _| { 39 | reload(b); 40 | Some("".into()) 41 | }); 42 | 43 | let quit_regex = Regex::new(&format!("^{}quit$", p)).unwrap(); 44 | add_fun(bot, quit_regex, quit); 45 | } 46 | 47 | fn add_fun< 48 | F: for<'a> Fn(&Bot, &mut Connection, &'a Message) -> Option> 49 | + Send 50 | + Sync 51 | + 'static, 52 | >( 53 | bot: &mut Bot, 54 | r: Regex, 55 | f: F, 56 | ) { 57 | bot.actions.0.push(Action { 58 | matchers: vec![Matcher::Regex(r)], 59 | reaction: Some(Reaction::Function(Box::new(f))), 60 | }); 61 | } 62 | 63 | fn add<'a>(bot: &Bot, r: &Regex, msg: &'a Message) -> Option> { 64 | let caps = match r.captures(msg.message) { 65 | Some(r) => r, 66 | None => { 67 | return Some( 68 | format!( 69 | "Usage: {}add on ", 70 | crate::escape_bb(&bot.settings.prefix) 71 | ) 72 | .into(), 73 | ); 74 | } 75 | }; 76 | let response = caps.name("response").unwrap(); 77 | let trigger = caps.name("trigger").unwrap(); 78 | 79 | // Load 80 | let path = Path::new(&bot.settings.dynamic_actions); 81 | let path = if path.is_absolute() { 82 | path.into() 83 | } else { 84 | bot.base_dir.join(path) 85 | }; 86 | let mut dynamic: ActionFile = match fs::read_to_string(&path) { 87 | Ok(s) => match toml::from_str(&s) { 88 | Ok(r) => r, 89 | Err(error) => { 90 | error!(%error, "Failed to parse dynamic actions"); 91 | return Some("Failed".into()); 92 | } 93 | }, 94 | Err(error) => { 95 | debug!(%error, "Dynamic actions not loaded"); 96 | ActionFile::default() 97 | } 98 | }; 99 | 100 | dynamic.on_message.push(ActionDefinition { 101 | contains: Some(trigger.as_str().into()), 102 | regex: None, 103 | chat: None, 104 | 105 | response: Some(response.as_str().into()), 106 | command: None, 107 | shell: None, 108 | }); 109 | 110 | // Save 111 | if let Err(error) = fs::write(&path, toml::to_string(&dynamic).unwrap()) { 112 | error!(%error, "Failed to save dynamic actions"); 113 | return Some("Failed".into()); 114 | } 115 | 116 | reload(bot); 117 | Some("".into()) 118 | } 119 | 120 | /// Remove everything which matches this trigger. 121 | fn del<'a>(bot: &Bot, r: &Regex, msg: &'a Message) -> Option> { 122 | let caps = match r.captures(msg.message) { 123 | Some(r) => r, 124 | None => { 125 | return Some( 126 | format!( 127 | "Usage: {}del ", 128 | crate::escape_bb(&bot.settings.prefix) 129 | ) 130 | .into(), 131 | ); 132 | } 133 | }; 134 | let trigger = caps.name("trigger").unwrap().as_str(); 135 | 136 | // Load 137 | let path = Path::new(&bot.settings.dynamic_actions); 138 | let path = if path.is_absolute() { 139 | path.into() 140 | } else { 141 | bot.base_dir.join(path) 142 | }; 143 | let mut dynamic: ActionFile = match fs::read_to_string(&path) { 144 | Ok(s) => match toml::from_str(&s) { 145 | Ok(r) => r, 146 | Err(error) => { 147 | error!(%error, "Failed to parse dynamic actions"); 148 | return Some("Failed".into()); 149 | } 150 | }, 151 | Err(error) => { 152 | debug!(%error, "Dynamic actions not loaded"); 153 | ActionFile::default() 154 | } 155 | }; 156 | 157 | let mut count = 0; 158 | dynamic.on_message.retain(|a| { 159 | let r = a.contains.as_ref().map(|c| c != trigger).unwrap_or(true); 160 | if !r { 161 | count += 1; 162 | } 163 | r 164 | }); 165 | 166 | // Save 167 | if let Err(error) = fs::write(&path, toml::to_string(&dynamic).unwrap()) { 168 | error!(%error, "Failed to save dynamic actions"); 169 | return Some("Failed".into()); 170 | } 171 | 172 | reload(bot); 173 | if count == 1 { 174 | Some(format!("Removed {} element", count).into()) 175 | } else { 176 | Some(format!("Removed {} elements", count).into()) 177 | } 178 | } 179 | 180 | fn reload(bot: &Bot) { bot.should_reload.set(true); } 181 | 182 | fn quit<'a>( 183 | _: &Bot, 184 | con: &mut Connection, 185 | message: &'a Message, 186 | ) -> Option> { 187 | info!(?message, "Leaving on request"); 188 | // We get no disconnect message here 189 | // Ignore errors on disconnect 190 | let _ = con.disconnect(DisconnectOptions::new()); 191 | Some("".into()) 192 | } 193 | 194 | #[rustfmt::skip] 195 | fn help<'a>(bot: &Bot) -> Option> { 196 | Some( 197 | format!( 198 | "This is a [URL=https://github.com/ReSpeak/SimpleBot]SimpleBot[/URL].\n\ 199 | Use [i]{prefix}add on [/i] to add new actions\n\ 200 | or [i]{prefix}del [/i] to remove them.\n\ 201 | [i]{prefix}list[/i] lists all commands and actions.\n\ 202 | [i]{prefix}quit[/i] disconnects the bot.", 203 | prefix = crate::escape_bb(&bot.settings.prefix) 204 | ) 205 | .into(), 206 | ) 207 | } 208 | 209 | /// Please do not remove this message. It serves the purpose of license and 210 | /// copyright notice, which is required by the MIT and Apache license. 211 | #[rustfmt::skip] 212 | fn copyright() -> Option> { 213 | Some( 214 | "This is a [URL=https://github.com/ReSpeak/SimpleBot]SimpleBot[/URL].\n\ 215 | This software is licensed under MIT and Apache License, Version 2.0.\n\ 216 | See the website for more information.\n\ 217 | © 2018–2023 Flakebi".into(), 218 | ) 219 | } 220 | 221 | fn list<'a>(bot: &Bot, msg: &Message) -> Option> { 222 | let mut page = 0; 223 | if let Some(i) = msg.message.rfind(' ') { 224 | if let Ok(n) = (msg.message[i + 1..]).parse::() { 225 | if n != 0 { 226 | // Start indexing at 1 227 | page = n - 1; 228 | } 229 | } 230 | } 231 | 232 | if page >= bot.list.len() { 233 | page = bot.list.len() - 1; 234 | } 235 | 236 | let page_s = bot.list[page].clone(); 237 | let res = if bot.list.len() > 1 { 238 | format!( 239 | "Page {}/{}, use [i]{}list [/i] to show more.{}", 240 | page + 1, 241 | bot.list.len(), 242 | crate::escape_bb(&bot.settings.prefix), 243 | page_s, //crate::escape_bb(&page_s), 244 | ) 245 | } else { 246 | page_s 247 | }; 248 | 249 | Some(res.into()) 250 | } 251 | 252 | pub fn init_list(bot: &mut Bot) { 253 | let mut matchers = Vec::new(); 254 | for a in &bot.actions.0 { 255 | let mut res = String::new(); 256 | for m in &a.matchers { 257 | match m { 258 | Matcher::Regex(r) => { 259 | let mut r = r.as_str().to_string(); 260 | r = r.replace(&['^', '$'][..], ""); 261 | r = r.replace("\\b", ""); 262 | 263 | r = r.replace("\\\\", "\\"); 264 | r = r.replace("\\.", "."); 265 | res.push_str(&r); 266 | } 267 | Matcher::Mode(m) => { 268 | let _ = write!( 269 | res, 270 | " (only in {} mode)", 271 | Reaction::get_mode(m) 272 | ); 273 | } 274 | } 275 | } 276 | matchers.push(res); 277 | } 278 | matchers.sort_unstable(); 279 | matchers.dedup(); 280 | 281 | // Group lines so thet at maximum 900 chars are on one page 282 | // (there will be additional text later). 283 | let mut res = vec![String::new()]; 284 | for m in matchers { 285 | if res.last().unwrap().len() + m.len() > 900 { 286 | res.push(String::new()); 287 | } 288 | let cur = res.last_mut().unwrap(); 289 | cur.push('\n'); 290 | cur.push_str(&m); 291 | } 292 | 293 | bot.list = res; 294 | } 295 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::cell::Cell; 2 | use std::fs; 3 | use std::path::{Path, PathBuf}; 4 | use std::time::{Duration, Instant}; 5 | 6 | use anyhow::{bail, Result}; 7 | use clap::Parser; 8 | use futures::prelude::*; 9 | use serde::{Deserialize, Serialize}; 10 | use tracing::{debug, error, info, warn}; 11 | use tsclientlib::events::Event; 12 | use tsclientlib::{ 13 | ChannelId, Connection, DisconnectOptions, Identity, InvokerRef, 14 | MessageTarget, OutCommandExt, Reason, StreamItem, 15 | }; 16 | 17 | const SETTINGS_FILENAME: &str = "settings.toml"; 18 | 19 | pub mod action; 20 | pub mod builtins; 21 | 22 | use crate::action::{ActionDefinition, ActionList}; 23 | 24 | #[derive(Parser, Debug)] 25 | #[clap(author, version, about)] 26 | struct Args { 27 | /// The path of the settings file. 28 | #[clap(short, long)] 29 | settings: Option, 30 | 31 | /// Print the content of all packets. 32 | #[clap(short, long, action = clap::ArgAction::Count)] 33 | verbose: u8, 34 | // 0. Print nothing 35 | // 1. Print command string 36 | // 2. Print packets 37 | // 3. Print udp packets 38 | } 39 | 40 | #[derive(Clone, Debug, Default, Deserialize, Serialize)] 41 | #[serde(deny_unknown_fields)] 42 | struct ActionFile { 43 | /// Includes other files. 44 | /// 45 | /// The path is always relative to the current file. Includes will be 46 | /// inserted after the declarations in this file. 47 | #[serde(default = "Vec::new")] 48 | include: Vec, 49 | 50 | // This needs to be second for the toml serialization. 51 | #[serde(default = "Vec::new")] 52 | on_message: Vec, 53 | } 54 | 55 | #[derive(Clone, Debug, Deserialize)] 56 | #[serde(untagged)] 57 | pub enum ChannelDefinition { 58 | Id(u64), 59 | Name(String), 60 | } 61 | 62 | #[derive(Clone, Debug, Deserialize)] 63 | #[serde(deny_unknown_fields)] 64 | pub struct Settings { 65 | /// The file which contains the private key. 66 | /// 67 | /// This will be automatically generated on the first run. 68 | /// 69 | /// # Default 70 | /// `private.key` 71 | #[serde(default = "default_key_file")] 72 | key_file: String, 73 | /// Dynamically added actions. This file will be overwritten automatically. 74 | /// 75 | /// The actions from this file will be added after the normal actions and 76 | /// before the builtins. 77 | /// 78 | /// # Default 79 | /// `dynamic.toml` 80 | #[serde(default = "default_dynamic_actions")] 81 | dynamic_actions: String, 82 | 83 | /// The address of the server to connect to. 84 | /// 85 | /// # Default 86 | /// `localhost` 87 | #[serde(default = "default_address")] 88 | address: String, 89 | /// The channel on the server to connect to. 90 | /// 91 | /// E.g. 4, "My Channel" or "My Channel/Nested" 92 | /// 93 | /// # Default 94 | /// `None` 95 | channel: Option, 96 | /// The name of the bot. 97 | /// 98 | /// # Default 99 | /// `SimpleBot` 100 | #[serde(default = "default_name")] 101 | name: String, 102 | /// The disconnect message of the bot. 103 | /// 104 | /// # Default 105 | /// `Disconnecting` 106 | #[serde(default = "default_disconnect_message")] 107 | disconnect_message: String, 108 | /// How many messages can be sent per second. 109 | /// 110 | /// If this limit is exceeded, incoming messages will be ignored. 111 | /// 112 | /// # Default 113 | /// `2` 114 | #[serde(default = "default_rate_limit")] 115 | rate_limit: u8, 116 | 117 | /// The prefix for builtin commands. 118 | /// 119 | /// # Default 120 | /// `.` 121 | #[serde(default = "default_prefix")] 122 | prefix: String, 123 | 124 | #[serde(default = "Default::default")] 125 | actions: ActionFile, 126 | } 127 | 128 | #[derive(Debug)] 129 | pub struct Bot { 130 | base_dir: PathBuf, 131 | settings_path: PathBuf, 132 | actions: ActionList, 133 | settings: Settings, 134 | rate_limiting: Vec, 135 | /// A cached list of actions 136 | list: Vec, 137 | should_reload: Cell, 138 | } 139 | 140 | #[derive(Clone, Debug)] 141 | pub struct Message<'a> { 142 | target: MessageTarget, 143 | invoker: InvokerRef<'a>, 144 | message: &'a str, 145 | } 146 | 147 | impl Bot { 148 | fn new() -> Self { 149 | Self { 150 | base_dir: PathBuf::new(), 151 | settings_path: PathBuf::new(), 152 | actions: Default::default(), 153 | settings: Default::default(), 154 | rate_limiting: Default::default(), 155 | list: Default::default(), 156 | should_reload: Default::default(), 157 | } 158 | } 159 | } 160 | 161 | impl Default for Settings { 162 | fn default() -> Self { 163 | Self { 164 | key_file: default_key_file(), 165 | dynamic_actions: default_dynamic_actions(), 166 | 167 | address: default_address(), 168 | channel: None, 169 | name: default_name(), 170 | disconnect_message: default_disconnect_message(), 171 | rate_limit: default_rate_limit(), 172 | prefix: default_prefix(), 173 | 174 | actions: Default::default(), 175 | } 176 | } 177 | } 178 | 179 | fn default_key_file() -> String { "private.key".into() } 180 | 181 | fn default_address() -> String { "localhost".into() } 182 | fn default_name() -> String { "SimpleBot".into() } 183 | fn default_disconnect_message() -> String { "Disconnecting".into() } 184 | fn default_rate_limit() -> u8 { 2 } 185 | fn default_prefix() -> String { ".".into() } 186 | fn default_dynamic_actions() -> String { "dynamic.toml".into() } 187 | 188 | #[tokio::main] 189 | async fn main() -> Result<()> { real_main().await } 190 | 191 | async fn real_main() -> Result<()> { 192 | tracing_subscriber::fmt::init(); 193 | // Parse command line options 194 | let args = Args::parse(); 195 | 196 | // Load settings 197 | let settings_path; 198 | let base_dir; 199 | if let Some(settings) = &args.settings { 200 | settings_path = PathBuf::from(settings.to_string()); 201 | base_dir = settings_path 202 | .parent() 203 | .map(|p| p.into()) 204 | .unwrap_or_else(PathBuf::new); 205 | } else { 206 | let proj_dirs = match directories_next::ProjectDirs::from( 207 | "", 208 | "ReSpeak", 209 | "simple-bot", 210 | ) { 211 | Some(r) => r, 212 | None => { 213 | panic!("Failed to get project directory"); 214 | } 215 | }; 216 | base_dir = proj_dirs.config_dir().into(); 217 | settings_path = base_dir.join(SETTINGS_FILENAME); 218 | } 219 | 220 | let mut bot = Bot::new(); 221 | bot.base_dir = base_dir; 222 | bot.settings_path = settings_path; 223 | load_settings(&mut bot)?; 224 | let disconnect_message = bot.settings.disconnect_message.clone(); 225 | 226 | // Load private key 227 | let file = Path::new(&bot.settings.key_file); 228 | let file = if file.is_absolute() { 229 | file.to_path_buf() 230 | } else { 231 | bot.base_dir.join(&bot.settings.key_file) 232 | }; 233 | let private_key = match fs::read(&file) { 234 | Ok(r) => tsproto_types::crypto::EccKeyPrivP256::import(&r)?, 235 | _ => { 236 | // Create new key 237 | let key = tsproto_types::crypto::EccKeyPrivP256::create(); 238 | 239 | // Create directory 240 | if let Err(error) = fs::create_dir_all(&bot.base_dir) { 241 | error!(%error, "Failed to create config dictionary"); 242 | } 243 | // Write to file 244 | if let Err(error) = fs::write(&file, key.to_short()) { 245 | warn!(%error, "file" = ?file.to_str(), "Failed to store the private key, the server \ 246 | identity will not be the same in the next run"); 247 | } 248 | 249 | key 250 | } 251 | }; 252 | let identity = Identity::new(private_key, 0); 253 | 254 | let mut con_config = Connection::build(bot.settings.address.clone()) 255 | .identity(identity) 256 | .name(bot.settings.name.clone()) 257 | .log_commands(args.verbose >= 1) 258 | .log_packets(args.verbose >= 2) 259 | .log_udp_packets(args.verbose >= 3); 260 | 261 | match &bot.settings.channel { 262 | Some(ChannelDefinition::Id(channel)) => { 263 | con_config = con_config.channel_id(ChannelId(*channel)); 264 | } 265 | Some(ChannelDefinition::Name(channel)) => { 266 | con_config = con_config.channel(channel.clone()); 267 | } 268 | _ => {} 269 | } 270 | 271 | // Connect 272 | let mut con = con_config.connect()?; 273 | let r = con 274 | .events() 275 | .try_filter(|e| future::ready(matches!(e, StreamItem::BookEvents(_)))) 276 | .next() 277 | .await; 278 | if let Some(r) = r { 279 | r?; 280 | } 281 | 282 | loop { 283 | let mut events = con.events(); 284 | tokio::select! { 285 | // Wait for ctrl + c 286 | _ = tokio::signal::ctrl_c() => { break; } 287 | // Listen to events 288 | e = events.next() => { 289 | drop(events); 290 | if let Some(e) = e { 291 | if let StreamItem::BookEvents(e) = e? { 292 | handle_event(&mut bot, &mut con, &e); 293 | if bot.should_reload.get() { 294 | bot.should_reload.set(false); 295 | match load_settings(&mut bot) { 296 | Ok(()) => info!("Reloaded successfully"), 297 | Err(error) => error!(%error, "Failed to reload"), 298 | } 299 | } 300 | } 301 | } else { 302 | break; 303 | } 304 | } 305 | } 306 | } 307 | 308 | // Disconnect 309 | con.disconnect( 310 | DisconnectOptions::new() 311 | .reason(Reason::Clientdisconnect) 312 | .message(disconnect_message), 313 | )?; 314 | con.events().for_each(|_| future::ready(())).await; 315 | 316 | Ok(()) 317 | } 318 | 319 | fn load_settings(bot: &mut Bot) -> Result<()> { 320 | // Reload settings 321 | match fs::read_to_string(&bot.settings_path) { 322 | Ok(r) => match toml::from_str(&r) { 323 | Ok(s) => bot.settings = s, 324 | Err(e) => bail!("Failed to parse settings: {}", e), 325 | }, 326 | Err(error) => { 327 | // Only a soft error 328 | warn!(%error, "Failed to read settings, using defaults"); 329 | } 330 | } 331 | 332 | // Reload actions 333 | let mut actions = ActionList::default(); 334 | if let Err(error) = 335 | load_actions(&bot.base_dir, &mut actions, &bot.settings.actions) 336 | { 337 | error!(%error, "Failed to load actions"); 338 | } 339 | 340 | // Load builtins here, otherwise .del will never trigger 341 | bot.actions = actions; 342 | builtins::init(bot); 343 | 344 | // Dynamic actions 345 | let path = Path::new(&bot.settings.dynamic_actions); 346 | let path = if path.is_absolute() { 347 | path.into() 348 | } else { 349 | bot.base_dir.join(path) 350 | }; 351 | let dynamic: ActionFile = match fs::read_to_string(path) { 352 | Ok(s) => toml::from_str(&s)?, 353 | Err(error) => { 354 | debug!(%error, "Dynamic actions not loaded"); 355 | ActionFile::default() 356 | } 357 | }; 358 | if let Err(e) = load_actions(&bot.base_dir, &mut bot.actions, &dynamic) { 359 | bail!("Failed to load dynamic actions: {}", e); 360 | } 361 | builtins::init_list(bot); 362 | debug!(actions = ?bot.actions, "Loaded actions"); 363 | Ok(()) 364 | } 365 | 366 | fn load_actions( 367 | base: &Path, 368 | actions: &mut ActionList, 369 | f: &ActionFile, 370 | ) -> Result<()> { 371 | for a in &f.on_message { 372 | actions.0.push(a.to_action()?); 373 | } 374 | // Handle includes 375 | for i in &f.include { 376 | let path = base.join(i); 377 | let f2: ActionFile = toml::from_str(&fs::read_to_string(&path)?)?; 378 | load_actions(path.parent().unwrap_or(base), actions, &f2)?; 379 | } 380 | 381 | Ok(()) 382 | } 383 | 384 | fn handle_event(bot: &mut Bot, con: &mut Connection, event: &[Event]) { 385 | for e in event { 386 | if let Event::Message { 387 | target, 388 | invoker, 389 | message, 390 | } = e 391 | { 392 | // Ignore messages from ourself 393 | if invoker.id == con.get_state().unwrap().own_client { 394 | continue; 395 | } 396 | // Check rate limiting 397 | { 398 | let rate = &mut bot.rate_limiting; 399 | let now = Instant::now(); 400 | let second = Duration::from_secs(1); 401 | rate.retain(|i| now.duration_since(*i) <= second); 402 | if rate.len() >= bot.settings.rate_limit as usize { 403 | warn!( 404 | ?target, 405 | ?invoker, 406 | message = message.as_str(), 407 | "Ignored message because of rate limiting" 408 | ); 409 | continue; 410 | } 411 | } 412 | 413 | debug!( 414 | ?target, 415 | ?invoker, 416 | message = message.as_str(), 417 | "Got message" 418 | ); 419 | 420 | let msg = Message { 421 | target: *target, 422 | invoker: invoker.as_ref(), 423 | message, 424 | }; 425 | if let Some(response) = bot.actions.handle(bot, con, &msg) { 426 | bot.rate_limiting.push(Instant::now()); 427 | let state = con.get_state().unwrap(); 428 | if let Err(error) = 429 | state.send_message(*target, response.as_ref()).send(con) 430 | { 431 | error!(%error, "Failed to send response") 432 | } 433 | } 434 | } 435 | } 436 | } 437 | 438 | fn escape_bb(s: &str) -> String { s.replace('[', "\\[") } 439 | --------------------------------------------------------------------------------