mirror of
https://framagit.org/veretcle/scootaloo.git
synced 2025-07-20 17:11:19 +02:00
Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5fe57f189a | ||
![]() |
83c398cebf | ||
![]() |
8f567ed6b4 | ||
![]() |
d7431862ba | ||
![]() |
f3b13eb62f | ||
![]() |
6b68c8e299 | ||
![]() |
0bb5eabdac | ||
![]() |
3d44bbfb86 | ||
![]() |
9a03c7681b | ||
![]() |
a8a8f8c13f | ||
![]() |
90a9df220a | ||
![]() |
6218c59ce5 | ||
![]() |
6ffcbfc89a | ||
![]() |
3fdd81df50 | ||
![]() |
90f47079d9 | ||
![]() |
88b73f4bc5 | ||
![]() |
87797c7ab0 | ||
![]() |
3645728ddf | ||
![]() |
69648728d7 | ||
![]() |
6af1e4c55a |
228
Cargo.lock
generated
228
Cargo.lock
generated
@@ -33,9 +33,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.59"
|
||||
version = "0.1.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
|
||||
checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -109,9 +109,9 @@ checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.77"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
|
||||
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@@ -137,9 +137,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.0.29"
|
||||
version = "4.0.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d"
|
||||
checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap_lex",
|
||||
@@ -231,9 +231,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.82"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453"
|
||||
checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
@@ -243,9 +243,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.82"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0"
|
||||
checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
@@ -258,15 +258,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.82"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71"
|
||||
checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.82"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470"
|
||||
checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -326,7 +326,7 @@ dependencies = [
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha-1 0.9.8",
|
||||
"sha-1",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"url",
|
||||
@@ -604,9 +604,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "html-escape"
|
||||
version = "0.2.12"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15315cfa9503e9aa85a477138eff76a1b203a430703548052c330b69d8d8c205"
|
||||
checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476"
|
||||
dependencies = [
|
||||
"utf8-width",
|
||||
]
|
||||
@@ -671,9 +671,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper-rustls"
|
||||
version = "0.23.1"
|
||||
version = "0.23.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59df7c4e19c950e6e0e868dcc0a300b09a9b88e9ec55bd879ca819087a77355d"
|
||||
checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c"
|
||||
dependencies = [
|
||||
"http",
|
||||
"hyper",
|
||||
@@ -760,15 +760,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ipnet"
|
||||
version = "2.5.1"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745"
|
||||
checksum = "11b0d96e660696543b251e58030cf9787df56da39dab19ad60eae7353040917e"
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330"
|
||||
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
|
||||
dependencies = [
|
||||
"hermit-abi 0.2.6",
|
||||
"io-lifetimes",
|
||||
@@ -776,20 +776,11 @@ dependencies = [
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "isolang"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b64fd6448ee8a45ce6e4365c58e4fa7d8740cba2ed70db3e9ab4879ebd93eaaa"
|
||||
dependencies = [
|
||||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
|
||||
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
@@ -808,9 +799,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.137"
|
||||
version = "0.2.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
@@ -824,18 +815,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
|
||||
checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.1.3"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
|
||||
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
@@ -858,12 +849,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "megalodon"
|
||||
version = "0.2.5"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c871fd0f7cfb5ea5f41322e31d86d2cb7f964e01e57e6399bb31fd602bf050a"
|
||||
checksum = "3b39bd378603a46216457c1c95c54f8dec37959a02c06a59cc33d00fc71a0ba0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"futures-util",
|
||||
"hex",
|
||||
"log",
|
||||
"oauth2",
|
||||
@@ -873,8 +865,8 @@ dependencies = [
|
||||
"sha1",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tokio-util",
|
||||
"tungstenite",
|
||||
"url",
|
||||
"urlencoding",
|
||||
]
|
||||
@@ -952,11 +944,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.14.0"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
|
||||
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.19",
|
||||
"hermit-abi 0.2.6",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@@ -1003,9 +995,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.43"
|
||||
version = "0.10.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "020433887e44c27ff16365eaa2d380547a94544ad509aff6eb5b6e3e0b27b376"
|
||||
checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
@@ -1035,9 +1027,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.78"
|
||||
version = "0.9.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07d5c8cb6e57b3a3612064d7b18b117912b4ce70955c2504d4b741c9e244b132"
|
||||
checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cc",
|
||||
@@ -1081,24 +1073,6 @@ version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
@@ -1125,18 +1099,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.47"
|
||||
version = "1.0.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -1291,9 +1265,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.36.4"
|
||||
version = "0.36.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb93e85278e08bb5788653183213d3a60fc242b10cb9be96586f5a73dcb67c23"
|
||||
checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
@@ -1326,9 +1300,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.11"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
||||
|
||||
[[package]]
|
||||
name = "schannel"
|
||||
@@ -1342,14 +1316,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "scootaloo"
|
||||
version = "1.1.0"
|
||||
version = "1.1.6"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"clap",
|
||||
"egg-mode",
|
||||
"futures",
|
||||
"html-escape",
|
||||
"isolang",
|
||||
"log",
|
||||
"megalodon",
|
||||
"mime",
|
||||
@@ -1370,9 +1343,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
|
||||
checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
@@ -1409,24 +1382,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.14"
|
||||
version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
|
||||
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.148"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc"
|
||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.148"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c"
|
||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1435,9 +1408,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.89"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
|
||||
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -1446,9 +1419,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_path_to_error"
|
||||
version = "0.1.8"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "184c643044780f7ceb59104cef98a5a6f12cb2288a7bc701ab93a362b49fd47d"
|
||||
checksum = "26b04f22b563c91331a10074bda3dd5492e3cc39d56bd557e91c0af42b6c7341"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -1478,17 +1451,6 @@ dependencies = [
|
||||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha-1"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest 0.10.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.5"
|
||||
@@ -1533,12 +1495,6 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.7"
|
||||
@@ -1584,9 +1540,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.104"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1618,18 +1574,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.37"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
|
||||
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.37"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
|
||||
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1693,9 +1649,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.22.0"
|
||||
version = "1.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3"
|
||||
checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bytes",
|
||||
@@ -1708,14 +1664,14 @@ dependencies = [
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"winapi",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "1.8.1"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ec8ecbbb74d42a8dd0ce8ea9bfc38ad13e2ed5203c4f272dbe144f4e17d70ac"
|
||||
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1743,6 +1699,20 @@ dependencies = [
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tungstenite"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tungstenite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-util"
|
||||
version = "0.7.4"
|
||||
@@ -1759,9 +1729,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.9"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||
checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -1800,9 +1770,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
|
||||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.17.3"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0"
|
||||
checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"byteorder",
|
||||
@@ -1812,7 +1782,7 @@ dependencies = [
|
||||
"log",
|
||||
"native-tls",
|
||||
"rand",
|
||||
"sha-1 0.10.1",
|
||||
"sha1",
|
||||
"thiserror",
|
||||
"url",
|
||||
"utf-8",
|
||||
@@ -1820,9 +1790,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.15.0"
|
||||
version = "1.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
||||
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
@@ -1841,9 +1811,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.5"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
@@ -2018,9 +1988,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.22.5"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be"
|
||||
checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
|
||||
dependencies = [
|
||||
"webpki",
|
||||
]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "scootaloo"
|
||||
version = "1.1.0"
|
||||
version = "1.1.6"
|
||||
authors = ["VC <veretcle+framagit@mateu.be>"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -14,10 +14,9 @@ toml = "^0.5"
|
||||
clap = "^4"
|
||||
egg-mode = "^0.16"
|
||||
rusqlite = "^0.27"
|
||||
isolang = "^2"
|
||||
tokio = { version = "^1", features = ["rt"]}
|
||||
futures = "^0.3"
|
||||
megalodon = "^0.2"
|
||||
megalodon = "^0.3.6"
|
||||
html-escape = "^0.2"
|
||||
reqwest = "^0.11"
|
||||
log = "^0.4"
|
||||
|
26
README.md
26
README.md
@@ -83,22 +83,20 @@ You can then run the application via `cron` for example. Here is the generic usa
|
||||
```sh
|
||||
A Twitter to Mastodon bot
|
||||
|
||||
USAGE:
|
||||
scootaloo [OPTIONS] [SUBCOMMAND]
|
||||
Usage: scootaloo [OPTIONS] [COMMAND]
|
||||
|
||||
FLAGS:
|
||||
-h, --help Prints help information
|
||||
-V, --version Prints version information
|
||||
Commands:
|
||||
register Command to register to a Mastodon Instance
|
||||
init Command to init Scootaloo DB
|
||||
migrate Command to migrate Scootaloo DB
|
||||
copyprofile Command to copy a Twitter profile into Mastodon
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
OPTIONS:
|
||||
-c, --config <CONFIG_FILE> TOML config file for scootaloo (default /usr/local/etc/scootaloo.toml)
|
||||
-l, --loglevel <LOGLEVEL> Log level. Valid values are: Off, Warn, Error, Info, Debug
|
||||
|
||||
SUBCOMMANDS:
|
||||
help Prints this message or the help of the given subcommand(s)
|
||||
init Command to init Scootaloo DB
|
||||
migrate Command to migrate Scootaloo DB
|
||||
register Command to register to a Mastodon Instance
|
||||
Options:
|
||||
-c, --config <CONFIG_FILE> TOML config file for scootaloo [default: /usr/local/etc/scootaloo.toml]
|
||||
-l, --loglevel <LOGLEVEL> Log level [possible values: Off, Warn, Error, Info, Debug]
|
||||
-h, --help Print help information
|
||||
-V, --version Print version information
|
||||
```
|
||||
|
||||
# Quirks
|
||||
|
@@ -43,10 +43,10 @@ pub struct ScootalooConfig {
|
||||
/// Parses the TOML file into a Config Struct
|
||||
pub fn parse_toml(toml_file: &str) -> Config {
|
||||
let toml_config = read_to_string(toml_file)
|
||||
.unwrap_or_else(|e| panic!("Cannot open config file {}: {}", toml_file, e));
|
||||
.unwrap_or_else(|e| panic!("Cannot open config file {toml_file}: {e}"));
|
||||
|
||||
let config: Config = toml::from_str(&toml_config)
|
||||
.unwrap_or_else(|e| panic!("Cannot parse TOML file {}: {}", toml_file, e));
|
||||
.unwrap_or_else(|e| panic!("Cannot parse TOML file {toml_file}: {e}"));
|
||||
|
||||
config
|
||||
}
|
||||
|
@@ -30,12 +30,12 @@ impl Display for ScootalooError {
|
||||
|
||||
impl From<Box<dyn Error>> for ScootalooError {
|
||||
fn from(error: Box<dyn Error>) -> Self {
|
||||
ScootalooError::new(&format!("Error in a subset crate: {}", error))
|
||||
ScootalooError::new(&format!("Error in a subset crate: {error}"))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<megalodonError> for ScootalooError {
|
||||
fn from(error: megalodonError) -> Self {
|
||||
ScootalooError::new(&format!("Error in megalodon crate: {}", error))
|
||||
ScootalooError::new(&format!("Error in megalodon crate: {error}"))
|
||||
}
|
||||
}
|
||||
|
39
src/lib.rs
39
src/lib.rs
@@ -21,7 +21,6 @@ use state::{read_state, write_state, TweetToToot};
|
||||
|
||||
use futures::StreamExt;
|
||||
use html_escape::decode_html_entities;
|
||||
use isolang::Language;
|
||||
use log::info;
|
||||
use megalodon::{
|
||||
megalodon::PostStatusInputOptions, megalodon::UpdateCredentialsInputOptions, Megalodon,
|
||||
@@ -204,9 +203,7 @@ pub async fn run(config: Config) {
|
||||
|
||||
// language if any
|
||||
if let Some(l) = &tweet.lang {
|
||||
if let Some(r) = Language::from_639_1(l) {
|
||||
post_status.language = Some(r.to_string());
|
||||
}
|
||||
post_status.language = Some(l.to_string());
|
||||
}
|
||||
|
||||
// can be activated for test purposes
|
||||
@@ -238,8 +235,8 @@ pub async fn run(config: Config) {
|
||||
// launch and wait for every handle
|
||||
while let Some(result) = stream.next().await {
|
||||
match result {
|
||||
Ok(Err(e)) => eprintln!("Error within thread: {}", e),
|
||||
Err(e) => eprintln!("Error with thread: {}", e),
|
||||
Ok(Err(e)) => eprintln!("Error within thread: {e}"),
|
||||
Err(e) => eprintln!("Error with thread: {e}"),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
@@ -263,8 +260,20 @@ pub async fn profile(config: Config, bot: Option<bool>) {
|
||||
.user
|
||||
.ok_or_else(|| ScootalooError::new("No user in Tweet!"))?;
|
||||
|
||||
let mut display_name = twitter_user.name.clone();
|
||||
display_name.truncate(30);
|
||||
let note = get_note_from_description(
|
||||
&twitter_user.description,
|
||||
&twitter_user.entities.description.urls,
|
||||
);
|
||||
|
||||
let fields_attributes = get_attribute_from_url(&twitter_user.entities.url);
|
||||
|
||||
let display_name = Some(String::from_utf16_lossy(
|
||||
&twitter_user
|
||||
.name
|
||||
.encode_utf16()
|
||||
.take(30)
|
||||
.collect::<Vec<u16>>(),
|
||||
));
|
||||
|
||||
let header = match twitter_user.profile_banner_url {
|
||||
Some(h) => Some(base64_media(&h).await?),
|
||||
@@ -272,18 +281,16 @@ pub async fn profile(config: Config, bot: Option<bool>) {
|
||||
};
|
||||
|
||||
let update_creds = UpdateCredentialsInputOptions {
|
||||
discoverable: None,
|
||||
bot,
|
||||
display_name: Some(display_name),
|
||||
note: twitter_user.description,
|
||||
display_name,
|
||||
note,
|
||||
avatar: Some(
|
||||
base64_media(&twitter_user.profile_image_url_https.replace("_normal", ""))
|
||||
.await?,
|
||||
),
|
||||
header,
|
||||
locked: None,
|
||||
source: None,
|
||||
fields_attributes: None,
|
||||
fields_attributes,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mastodon = get_mastodon_token(&mastodon_config);
|
||||
@@ -297,8 +304,8 @@ pub async fn profile(config: Config, bot: Option<bool>) {
|
||||
|
||||
while let Some(result) = stream.next().await {
|
||||
match result {
|
||||
Ok(Err(e)) => eprintln!("Error within thread: {}", e),
|
||||
Err(e) => eprintln!("Error with thread: {}", e),
|
||||
Ok(Err(e)) => eprintln!("Error within thread: {e}"),
|
||||
Err(e) => eprintln!("Error with thread: {e}"),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
@@ -63,10 +63,7 @@ fn main() {
|
||||
.short('c')
|
||||
.long("config")
|
||||
.value_name("CONFIG_FILE")
|
||||
.help(&format!(
|
||||
"TOML config file for scootaloo (default {})",
|
||||
DEFAULT_CONFIG_PATH
|
||||
))
|
||||
.help("TOML config file for scootaloo")
|
||||
.default_value(DEFAULT_CONFIG_PATH)
|
||||
.num_args(1)
|
||||
.display_order(1),
|
||||
@@ -81,7 +78,7 @@ fn main() {
|
||||
.short('c')
|
||||
.long("config")
|
||||
.value_name("CONFIG_FILE")
|
||||
.help(&format!("TOML config file for scootaloo (default {})", DEFAULT_CONFIG_PATH))
|
||||
.help("TOML config file for scootaloo")
|
||||
.default_value(DEFAULT_CONFIG_PATH)
|
||||
.num_args(1)
|
||||
.display_order(1),
|
||||
@@ -104,7 +101,7 @@ fn main() {
|
||||
.short('c')
|
||||
.long("config")
|
||||
.value_name("CONFIG_FILE")
|
||||
.help(&format!("TOML config file for scootaloo (default {})", DEFAULT_CONFIG_PATH))
|
||||
.help("TOML config file for scootaloo")
|
||||
.default_value(DEFAULT_CONFIG_PATH)
|
||||
.num_args(1)
|
||||
.display_order(1),
|
||||
|
100
src/mastodon.rs
100
src/mastodon.rs
@@ -1,7 +1,14 @@
|
||||
use crate::config::MastodonConfig;
|
||||
|
||||
use egg_mode::entities::{MentionEntity, UrlEntity};
|
||||
use megalodon::{generator, mastodon::Mastodon, megalodon::AppInputOptions};
|
||||
use egg_mode::{
|
||||
entities::{MentionEntity, UrlEntity},
|
||||
user::UserEntityDetail,
|
||||
};
|
||||
use megalodon::{
|
||||
generator,
|
||||
mastodon::Mastodon,
|
||||
megalodon::{AppInputOptions, CredentialsFieldAttribute},
|
||||
};
|
||||
use regex::Regex;
|
||||
use std::{collections::HashMap, io::stdin};
|
||||
|
||||
@@ -76,7 +83,7 @@ pub fn associate_urls(urls: &[UrlEntity], re: &Option<Regex>) -> HashMap<String,
|
||||
pub fn replace_alt_services(urls: &mut HashMap<String, String>, alts: &HashMap<String, String>) {
|
||||
for val in urls.values_mut() {
|
||||
for (k, v) in alts {
|
||||
*val = val.replace(&format!("/{}/", k), &format!("/{}/", v));
|
||||
*val = val.replace(&format!("/{k}/"), &format!("/{v}/"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,7 +120,7 @@ pub fn replace_tweet_by_toot(
|
||||
twitter_screen_name.to_lowercase(),
|
||||
tweet_id
|
||||
)) {
|
||||
*val = format!("{}/@{}/{}", base_url, mastodon_screen_name, toot_id);
|
||||
*val = format!("{base_url}/@{mastodon_screen_name}/{toot_id}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -123,6 +130,32 @@ pub fn get_mastodon_token(masto: &MastodonConfig) -> Mastodon {
|
||||
Mastodon::new(masto.base.to_string(), Some(masto.token.to_string()), None)
|
||||
}
|
||||
|
||||
/// Gets note from twitter_user description
|
||||
pub fn get_note_from_description(t: &Option<String>, urls: &[UrlEntity]) -> Option<String> {
|
||||
t.as_ref().map(|d| {
|
||||
let mut n = d.to_owned();
|
||||
let a_urls = associate_urls(urls, &None);
|
||||
decode_urls(&mut n, &a_urls);
|
||||
n
|
||||
})
|
||||
}
|
||||
|
||||
/// Gets fields_attribute from UserEntityDetail
|
||||
pub fn get_attribute_from_url(
|
||||
user_entity_detail: &Option<UserEntityDetail>,
|
||||
) -> Option<Vec<CredentialsFieldAttribute>> {
|
||||
user_entity_detail.as_ref().and_then(|u| {
|
||||
u.urls.first().and_then(|v| {
|
||||
v.expanded_url.as_ref().map(|e| {
|
||||
vec![CredentialsFieldAttribute {
|
||||
name: v.display_url.to_string(),
|
||||
value: e.to_string(),
|
||||
}]
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Generic register function
|
||||
/// As this function is supposed to be run only once, it will panic for every error it encounters
|
||||
/// Most of this function is a direct copy/paste of the official `elefren` crate
|
||||
@@ -151,7 +184,7 @@ pub async fn register(host: &str, screen_name: &str) {
|
||||
|
||||
let url = app_data.url.expect("Cannot generate registration URI!");
|
||||
|
||||
println!("Click this link to authorize on Mastodon: {}", url);
|
||||
println!("Click this link to authorize on Mastodon: {url}");
|
||||
println!("Paste the returned authorization code: ");
|
||||
|
||||
let mut input = String::new();
|
||||
@@ -207,6 +240,63 @@ token = "{}""#,
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_get_attribute_from_url() {
|
||||
let expected_credentials_field_attribute = CredentialsFieldAttribute {
|
||||
name: "Nintendojo.fr".to_string(),
|
||||
value: "https://www.nintendojo.fr".to_string(),
|
||||
};
|
||||
|
||||
let true_urls = vec![UrlEntity {
|
||||
display_url: "Nintendojo.fr".to_string(),
|
||||
expanded_url: Some("https://www.nintendojo.fr".to_string()),
|
||||
range: (1, 3),
|
||||
url: "https://t.me/balek".to_string(),
|
||||
}];
|
||||
|
||||
let false_urls = vec![UrlEntity {
|
||||
display_url: "Nintendojo.fr".to_string(),
|
||||
expanded_url: None,
|
||||
range: (1, 3),
|
||||
url: "https://t.me/balek".to_string(),
|
||||
}];
|
||||
|
||||
assert!(get_attribute_from_url(&None).is_none());
|
||||
assert!(get_attribute_from_url(&Some(UserEntityDetail { urls: false_urls })).is_none());
|
||||
|
||||
let binding = get_attribute_from_url(&Some(UserEntityDetail { urls: true_urls })).unwrap();
|
||||
let result_credentials_field_attribute = binding.first().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
result_credentials_field_attribute.name,
|
||||
expected_credentials_field_attribute.name
|
||||
);
|
||||
assert_eq!(
|
||||
result_credentials_field_attribute.value,
|
||||
expected_credentials_field_attribute.value
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_note_from_description() {
|
||||
let urls = vec![UrlEntity {
|
||||
display_url: "tamerelol".to_string(),
|
||||
expanded_url: Some("https://www.nintendojo.fr/dojobar".to_string()),
|
||||
range: (1, 3),
|
||||
url: "https://t.me/tamerelol".to_string(),
|
||||
}];
|
||||
|
||||
let some_description = Some("Youpi | https://t.me/tamerelol".to_string());
|
||||
let none_description = None;
|
||||
|
||||
assert_eq!(
|
||||
get_note_from_description(&some_description, &urls),
|
||||
Some("Youpi | https://www.nintendojo.fr/dojobar".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(get_note_from_description(&none_description, &urls), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_tweet_by_toot() {
|
||||
let mut associated_urls = HashMap::from([
|
||||
|
@@ -21,8 +21,8 @@ pub fn read_state(
|
||||
) -> Result<Option<TweetToToot>, Box<dyn Error>> {
|
||||
debug!("Reading tweet_id {:?}", s);
|
||||
let query: String = match s {
|
||||
Some(i) => format!("SELECT * FROM tweet_to_toot WHERE tweet_id = {} and twitter_screen_name = \"{}\"", i, n),
|
||||
None => format!("SELECT * FROM tweet_to_toot WHERE twitter_screen_name = \"{}\" ORDER BY tweet_id DESC LIMIT 1", n),
|
||||
Some(i) => format!("SELECT * FROM tweet_to_toot WHERE tweet_id = {i} and twitter_screen_name = \"{n}\""),
|
||||
None => format!("SELECT * FROM tweet_to_toot WHERE twitter_screen_name = \"{n}\" ORDER BY tweet_id DESC LIMIT 1"),
|
||||
};
|
||||
|
||||
let mut stmt = conn.prepare(&query)?;
|
||||
@@ -78,8 +78,7 @@ pub fn migrate_db(d: &str, s: &str) -> Result<(), Box<dyn Error>> {
|
||||
&format!(
|
||||
"ALTER TABLE tweet_to_toot
|
||||
ADD COLUMN twitter_screen_name TEXT NOT NULL
|
||||
DEFAULT \"{}\"",
|
||||
s
|
||||
DEFAULT \"{s}\""
|
||||
),
|
||||
[],
|
||||
);
|
||||
|
45
src/util.rs
45
src/util.rs
@@ -4,12 +4,18 @@ use base64::encode;
|
||||
use egg_mode::tweet::Tweet;
|
||||
use futures::{stream, stream::StreamExt};
|
||||
use log::{error, info, warn};
|
||||
use megalodon::{mastodon::Mastodon, megalodon::Megalodon};
|
||||
use megalodon::{
|
||||
entities::UploadMedia::{AsyncAttachment, Attachment},
|
||||
error,
|
||||
mastodon::Mastodon,
|
||||
megalodon::Megalodon,
|
||||
};
|
||||
use reqwest::Url;
|
||||
use std::error::Error;
|
||||
use tokio::{
|
||||
fs::{create_dir_all, remove_file, File},
|
||||
io::copy,
|
||||
time::{sleep, Duration},
|
||||
};
|
||||
|
||||
/// Generate associative table between media ids and tweet extended entities
|
||||
@@ -49,7 +55,12 @@ pub async fn generate_media_ids(
|
||||
// it doesn’t matter if we can’t remove, cache_media fn is idempotent
|
||||
remove_file(&local_tweet_media_path).await.ok();
|
||||
|
||||
Ok::<String, ScootalooError>(mastodon_media.id)
|
||||
let id = match mastodon_media {
|
||||
Attachment(m) => m.id,
|
||||
AsyncAttachment(m) => wait_until_uploaded(&mastodon, &m.id).await?,
|
||||
};
|
||||
|
||||
Ok::<String, ScootalooError>(id)
|
||||
})
|
||||
})
|
||||
.buffered(4); // there are max four medias per tweet and they need to be treated in
|
||||
@@ -72,6 +83,24 @@ pub async fn generate_media_ids(
|
||||
(media_url, media_ids)
|
||||
}
|
||||
|
||||
/// Wait on uploaded medias when necessary
|
||||
async fn wait_until_uploaded(client: &Mastodon, id: &str) -> Result<String, error::Error> {
|
||||
loop {
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
let res = client.get_media(id.to_string()).await;
|
||||
return match res {
|
||||
Ok(res) => Ok(res.json.id),
|
||||
Err(err) => match err {
|
||||
error::Error::OwnError(ref own_err) => match own_err.kind {
|
||||
error::Kind::HTTPPartialContentError => continue,
|
||||
_ => Err(err),
|
||||
},
|
||||
_ => Err(err),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms the media into a base64 equivalent
|
||||
pub async fn base64_media(u: &str) -> Result<String, Box<dyn Error>> {
|
||||
let mut response = reqwest::get(u).await?;
|
||||
@@ -85,12 +114,12 @@ pub async fn base64_media(u: &str) -> Result<String, Box<dyn Error>> {
|
||||
let content_type = response
|
||||
.headers()
|
||||
.get("content-type")
|
||||
.ok_or_else(|| ScootalooError::new(&format!("Cannot get media content type for {}", u)))?
|
||||
.ok_or_else(|| ScootalooError::new(&format!("Cannot get media content type for {u}")))?
|
||||
.to_str()?;
|
||||
|
||||
let encoded_f = encode(buffer);
|
||||
|
||||
Ok(format!("data:{};base64,{}", content_type, encoded_f))
|
||||
Ok(format!("data:{content_type};base64,{encoded_f}"))
|
||||
}
|
||||
|
||||
/// Gets and caches Twitter Media inside the determined temp dir
|
||||
@@ -107,19 +136,17 @@ pub async fn cache_media(u: &str, t: &str) -> Result<String, Box<dyn Error>> {
|
||||
.path_segments()
|
||||
.ok_or_else(|| {
|
||||
ScootalooError::new(&format!(
|
||||
"Cannot determine the destination filename for {}",
|
||||
u
|
||||
"Cannot determine the destination filename for {u}"
|
||||
))
|
||||
})?
|
||||
.last()
|
||||
.ok_or_else(|| {
|
||||
ScootalooError::new(&format!(
|
||||
"Cannot determine the destination filename for {}",
|
||||
u
|
||||
"Cannot determine the destination filename for {u}"
|
||||
))
|
||||
})?;
|
||||
|
||||
let dest_filepath = format!("{}/{}", t, dest_filename);
|
||||
let dest_filepath = format!("{t}/{dest_filename}");
|
||||
|
||||
let mut dest_file = File::create(&dest_filepath).await?;
|
||||
|
||||
|
Reference in New Issue
Block a user