mirror of
https://framagit.org/veretcle/scootaloo.git
synced 2025-07-20 17:11:19 +02:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3413f49d08 | ||
![]() |
d4fbccc69b | ||
![]() |
058a07865d | ||
![]() |
c6a29d1d7d | ||
![]() |
3692d6e51f | ||
![]() |
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]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.59"
|
version = "0.1.60"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
|
checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -109,9 +109,9 @@ checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.77"
|
version = "1.0.78"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
|
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@@ -137,9 +137,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.0.29"
|
version = "4.0.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d"
|
checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"clap_lex",
|
"clap_lex",
|
||||||
@@ -231,9 +231,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxx"
|
name = "cxx"
|
||||||
version = "1.0.82"
|
version = "1.0.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453"
|
checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cxxbridge-flags",
|
"cxxbridge-flags",
|
||||||
@@ -243,9 +243,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxx-build"
|
name = "cxx-build"
|
||||||
version = "1.0.82"
|
version = "1.0.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0"
|
checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"codespan-reporting",
|
"codespan-reporting",
|
||||||
@@ -258,15 +258,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxxbridge-flags"
|
name = "cxxbridge-flags"
|
||||||
version = "1.0.82"
|
version = "1.0.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71"
|
checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxxbridge-macro"
|
name = "cxxbridge-macro"
|
||||||
version = "1.0.82"
|
version = "1.0.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470"
|
checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -326,7 +326,7 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha-1 0.9.8",
|
"sha-1",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"url",
|
"url",
|
||||||
@@ -604,9 +604,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "html-escape"
|
name = "html-escape"
|
||||||
version = "0.2.12"
|
version = "0.2.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "15315cfa9503e9aa85a477138eff76a1b203a430703548052c330b69d8d8c205"
|
checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"utf8-width",
|
"utf8-width",
|
||||||
]
|
]
|
||||||
@@ -671,9 +671,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-rustls"
|
name = "hyper-rustls"
|
||||||
version = "0.23.1"
|
version = "0.23.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "59df7c4e19c950e6e0e868dcc0a300b09a9b88e9ec55bd879ca819087a77355d"
|
checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"hyper",
|
"hyper",
|
||||||
@@ -760,15 +760,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.5.1"
|
version = "2.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745"
|
checksum = "11b0d96e660696543b251e58030cf9787df56da39dab19ad60eae7353040917e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is-terminal"
|
name = "is-terminal"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330"
|
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi 0.2.6",
|
"hermit-abi 0.2.6",
|
||||||
"io-lifetimes",
|
"io-lifetimes",
|
||||||
@@ -776,20 +776,11 @@ dependencies = [
|
|||||||
"windows-sys 0.42.0",
|
"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]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.4"
|
version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
|
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
@@ -808,9 +799,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.137"
|
version = "0.2.139"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsqlite3-sys"
|
name = "libsqlite3-sys"
|
||||||
@@ -824,18 +815,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "link-cplusplus"
|
name = "link-cplusplus"
|
||||||
version = "1.0.7"
|
version = "1.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
|
checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
|
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
@@ -858,12 +849,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "megalodon"
|
name = "megalodon"
|
||||||
version = "0.2.5"
|
version = "0.3.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c871fd0f7cfb5ea5f41322e31d86d2cb7f964e01e57e6399bb31fd602bf050a"
|
checksum = "3b39bd378603a46216457c1c95c54f8dec37959a02c06a59cc33d00fc71a0ba0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"futures-util",
|
||||||
"hex",
|
"hex",
|
||||||
"log",
|
"log",
|
||||||
"oauth2",
|
"oauth2",
|
||||||
@@ -873,8 +865,8 @@ dependencies = [
|
|||||||
"sha1",
|
"sha1",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-tungstenite",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tungstenite",
|
|
||||||
"url",
|
"url",
|
||||||
"urlencoding",
|
"urlencoding",
|
||||||
]
|
]
|
||||||
@@ -952,11 +944,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_cpus"
|
name = "num_cpus"
|
||||||
version = "1.14.0"
|
version = "1.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
|
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi 0.1.19",
|
"hermit-abi 0.2.6",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1003,9 +995,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl"
|
name = "openssl"
|
||||||
version = "0.10.43"
|
version = "0.10.45"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "020433887e44c27ff16365eaa2d380547a94544ad509aff6eb5b6e3e0b27b376"
|
checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@@ -1035,9 +1027,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.78"
|
version = "0.9.80"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07d5c8cb6e57b3a3612064d7b18b117912b4ce70955c2504d4b741c9e244b132"
|
checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"cc",
|
"cc",
|
||||||
@@ -1081,24 +1073,6 @@ version = "2.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
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]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.9"
|
version = "0.2.9"
|
||||||
@@ -1125,18 +1099,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.47"
|
version = "1.0.49"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.21"
|
version = "1.0.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -1291,9 +1265,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.36.4"
|
version = "0.36.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cb93e85278e08bb5788653183213d3a60fc242b10cb9be96586f5a73dcb67c23"
|
checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"errno",
|
"errno",
|
||||||
@@ -1326,9 +1300,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.11"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schannel"
|
name = "schannel"
|
||||||
@@ -1342,14 +1316,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scootaloo"
|
name = "scootaloo"
|
||||||
version = "1.1.0"
|
version = "1.1.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"clap",
|
"clap",
|
||||||
"egg-mode",
|
"egg-mode",
|
||||||
"futures",
|
"futures",
|
||||||
"html-escape",
|
"html-escape",
|
||||||
"isolang",
|
|
||||||
"log",
|
"log",
|
||||||
"megalodon",
|
"megalodon",
|
||||||
"mime",
|
"mime",
|
||||||
@@ -1370,9 +1343,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scratch"
|
name = "scratch"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
|
checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sct"
|
name = "sct"
|
||||||
@@ -1409,24 +1382,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.14"
|
version = "1.0.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
|
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.148"
|
version = "1.0.152"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc"
|
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.148"
|
version = "1.0.152"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c"
|
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1435,9 +1408,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.89"
|
version = "1.0.91"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
|
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
@@ -1446,9 +1419,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_path_to_error"
|
name = "serde_path_to_error"
|
||||||
version = "0.1.8"
|
version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "184c643044780f7ceb59104cef98a5a6f12cb2288a7bc701ab93a362b49fd47d"
|
checksum = "26b04f22b563c91331a10074bda3dd5492e3cc39d56bd557e91c0af42b6c7341"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@@ -1478,17 +1451,6 @@ dependencies = [
|
|||||||
"opaque-debug",
|
"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]]
|
[[package]]
|
||||||
name = "sha1"
|
name = "sha1"
|
||||||
version = "0.10.5"
|
version = "0.10.5"
|
||||||
@@ -1533,12 +1495,6 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "siphasher"
|
|
||||||
version = "0.3.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.7"
|
version = "0.4.7"
|
||||||
@@ -1584,9 +1540,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.104"
|
version = "1.0.107"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce"
|
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1618,18 +1574,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.37"
|
version = "1.0.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
|
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.37"
|
version = "1.0.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
|
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1693,9 +1649,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.22.0"
|
version = "1.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3"
|
checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -1708,14 +1664,14 @@ dependencies = [
|
|||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"winapi",
|
"windows-sys 0.42.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "1.8.1"
|
version = "1.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ec8ecbbb74d42a8dd0ce8ea9bfc38ad13e2ed5203c4f272dbe144f4e17d70ac"
|
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1743,6 +1699,20 @@ dependencies = [
|
|||||||
"webpki",
|
"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]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.4"
|
version = "0.7.4"
|
||||||
@@ -1759,9 +1729,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.5.9"
|
version = "0.5.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@@ -1800,9 +1770,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tungstenite"
|
name = "tungstenite"
|
||||||
version = "0.17.3"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0"
|
checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
@@ -1812,7 +1782,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"native-tls",
|
"native-tls",
|
||||||
"rand",
|
"rand",
|
||||||
"sha-1 0.10.1",
|
"sha1",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"url",
|
"url",
|
||||||
"utf-8",
|
"utf-8",
|
||||||
@@ -1820,9 +1790,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.15.0"
|
version = "1.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
@@ -1841,9 +1811,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.5"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-normalization"
|
name = "unicode-normalization"
|
||||||
@@ -2018,9 +1988,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-roots"
|
name = "webpki-roots"
|
||||||
version = "0.22.5"
|
version = "0.22.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be"
|
checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"webpki",
|
"webpki",
|
||||||
]
|
]
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "scootaloo"
|
name = "scootaloo"
|
||||||
version = "1.1.0"
|
version = "1.1.6"
|
||||||
authors = ["VC <veretcle+framagit@mateu.be>"]
|
authors = ["VC <veretcle+framagit@mateu.be>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
@@ -14,10 +14,9 @@ toml = "^0.5"
|
|||||||
clap = "^4"
|
clap = "^4"
|
||||||
egg-mode = "^0.16"
|
egg-mode = "^0.16"
|
||||||
rusqlite = "^0.27"
|
rusqlite = "^0.27"
|
||||||
isolang = "^2"
|
|
||||||
tokio = { version = "^1", features = ["rt"]}
|
tokio = { version = "^1", features = ["rt"]}
|
||||||
futures = "^0.3"
|
futures = "^0.3"
|
||||||
megalodon = "^0.2"
|
megalodon = "^0.3.6"
|
||||||
html-escape = "^0.2"
|
html-escape = "^0.2"
|
||||||
reqwest = "^0.11"
|
reqwest = "^0.11"
|
||||||
log = "^0.4"
|
log = "^0.4"
|
||||||
|
34
README.md
34
README.md
@@ -1,3 +1,9 @@
|
|||||||
|
**Due to the new Twitter policy about API v1.1 and API v2, this project will no longer be updated as it no longer can work for free any way, shape or form.**
|
||||||
|
|
||||||
|
First of all, I’m deeply sorry about that. It worked pretty great for what it did with a level of quality I’m very proud to have achieved.
|
||||||
|
|
||||||
|
Secondly, fuck you Musk, fuck you.
|
||||||
|
|
||||||
A Twitter to Mastodon copy bot written in Rust
|
A Twitter to Mastodon copy bot written in Rust
|
||||||
|
|
||||||
It:
|
It:
|
||||||
@@ -25,7 +31,7 @@ rate_limiting = 4 ## optional, default 4, number of accounts handled simultaneou
|
|||||||
## this parameter allows you to catch such URLs and apply the `display_url` (i.e. `tout.es`) instead of the `expanded_url` (i.e. `http://tout.es`)
|
## this parameter allows you to catch such URLs and apply the `display_url` (i.e. `tout.es`) instead of the `expanded_url` (i.e. `http://tout.es`)
|
||||||
## in those particular cases
|
## in those particular cases
|
||||||
## (!) use with caution, it might have some undesired effects
|
## (!) use with caution, it might have some undesired effects
|
||||||
show_url_as_display_url_for = "^http(s)://(.+)\\.es$"
|
show_url_as_display_url_for = "^https?://(.+)\\.es$"
|
||||||
## optional, this allows you to replace the host for popular services such as YouTube of Twitter, or any other
|
## optional, this allows you to replace the host for popular services such as YouTube of Twitter, or any other
|
||||||
## with their more freely accessible equivalent
|
## with their more freely accessible equivalent
|
||||||
[scootaloo.alternative_services_for]
|
[scootaloo.alternative_services_for]
|
||||||
@@ -83,22 +89,20 @@ You can then run the application via `cron` for example. Here is the generic usa
|
|||||||
```sh
|
```sh
|
||||||
A Twitter to Mastodon bot
|
A Twitter to Mastodon bot
|
||||||
|
|
||||||
USAGE:
|
Usage: scootaloo [OPTIONS] [COMMAND]
|
||||||
scootaloo [OPTIONS] [SUBCOMMAND]
|
|
||||||
|
|
||||||
FLAGS:
|
Commands:
|
||||||
-h, --help Prints help information
|
register Command to register to a Mastodon Instance
|
||||||
-V, --version Prints version information
|
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:
|
Options:
|
||||||
-c, --config <CONFIG_FILE> TOML config file for scootaloo (default /usr/local/etc/scootaloo.toml)
|
-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
|
-l, --loglevel <LOGLEVEL> Log level [possible values: Off, Warn, Error, Info, Debug]
|
||||||
|
-h, --help Print help information
|
||||||
SUBCOMMANDS:
|
-V, --version Print version information
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Quirks
|
# Quirks
|
||||||
|
@@ -43,10 +43,10 @@ pub struct ScootalooConfig {
|
|||||||
/// Parses the TOML file into a Config Struct
|
/// Parses the TOML file into a Config Struct
|
||||||
pub fn parse_toml(toml_file: &str) -> Config {
|
pub fn parse_toml(toml_file: &str) -> Config {
|
||||||
let toml_config = read_to_string(toml_file)
|
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)
|
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
|
config
|
||||||
}
|
}
|
||||||
|
@@ -30,12 +30,12 @@ impl Display for ScootalooError {
|
|||||||
|
|
||||||
impl From<Box<dyn Error>> for ScootalooError {
|
impl From<Box<dyn Error>> for ScootalooError {
|
||||||
fn from(error: Box<dyn Error>) -> Self {
|
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 {
|
impl From<megalodonError> for ScootalooError {
|
||||||
fn from(error: megalodonError) -> Self {
|
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 futures::StreamExt;
|
||||||
use html_escape::decode_html_entities;
|
use html_escape::decode_html_entities;
|
||||||
use isolang::Language;
|
|
||||||
use log::info;
|
use log::info;
|
||||||
use megalodon::{
|
use megalodon::{
|
||||||
megalodon::PostStatusInputOptions, megalodon::UpdateCredentialsInputOptions, Megalodon,
|
megalodon::PostStatusInputOptions, megalodon::UpdateCredentialsInputOptions, Megalodon,
|
||||||
@@ -204,9 +203,7 @@ pub async fn run(config: Config) {
|
|||||||
|
|
||||||
// language if any
|
// language if any
|
||||||
if let Some(l) = &tweet.lang {
|
if let Some(l) = &tweet.lang {
|
||||||
if let Some(r) = Language::from_639_1(l) {
|
post_status.language = Some(l.to_string());
|
||||||
post_status.language = Some(r.to_string());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// can be activated for test purposes
|
// can be activated for test purposes
|
||||||
@@ -238,8 +235,8 @@ pub async fn run(config: Config) {
|
|||||||
// launch and wait for every handle
|
// launch and wait for every handle
|
||||||
while let Some(result) = stream.next().await {
|
while let Some(result) = stream.next().await {
|
||||||
match result {
|
match result {
|
||||||
Ok(Err(e)) => eprintln!("Error within thread: {}", e),
|
Ok(Err(e)) => eprintln!("Error within thread: {e}"),
|
||||||
Err(e) => eprintln!("Error with thread: {}", e),
|
Err(e) => eprintln!("Error with thread: {e}"),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,8 +260,20 @@ pub async fn profile(config: Config, bot: Option<bool>) {
|
|||||||
.user
|
.user
|
||||||
.ok_or_else(|| ScootalooError::new("No user in Tweet!"))?;
|
.ok_or_else(|| ScootalooError::new("No user in Tweet!"))?;
|
||||||
|
|
||||||
let mut display_name = twitter_user.name.clone();
|
let note = get_note_from_description(
|
||||||
display_name.truncate(30);
|
&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 {
|
let header = match twitter_user.profile_banner_url {
|
||||||
Some(h) => Some(base64_media(&h).await?),
|
Some(h) => Some(base64_media(&h).await?),
|
||||||
@@ -272,18 +281,16 @@ pub async fn profile(config: Config, bot: Option<bool>) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let update_creds = UpdateCredentialsInputOptions {
|
let update_creds = UpdateCredentialsInputOptions {
|
||||||
discoverable: None,
|
|
||||||
bot,
|
bot,
|
||||||
display_name: Some(display_name),
|
display_name,
|
||||||
note: twitter_user.description,
|
note,
|
||||||
avatar: Some(
|
avatar: Some(
|
||||||
base64_media(&twitter_user.profile_image_url_https.replace("_normal", ""))
|
base64_media(&twitter_user.profile_image_url_https.replace("_normal", ""))
|
||||||
.await?,
|
.await?,
|
||||||
),
|
),
|
||||||
header,
|
header,
|
||||||
locked: None,
|
fields_attributes,
|
||||||
source: None,
|
..Default::default()
|
||||||
fields_attributes: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mastodon = get_mastodon_token(&mastodon_config);
|
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 {
|
while let Some(result) = stream.next().await {
|
||||||
match result {
|
match result {
|
||||||
Ok(Err(e)) => eprintln!("Error within thread: {}", e),
|
Ok(Err(e)) => eprintln!("Error within thread: {e}"),
|
||||||
Err(e) => eprintln!("Error with thread: {}", e),
|
Err(e) => eprintln!("Error with thread: {e}"),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -63,10 +63,7 @@ fn main() {
|
|||||||
.short('c')
|
.short('c')
|
||||||
.long("config")
|
.long("config")
|
||||||
.value_name("CONFIG_FILE")
|
.value_name("CONFIG_FILE")
|
||||||
.help(&format!(
|
.help("TOML config file for scootaloo")
|
||||||
"TOML config file for scootaloo (default {})",
|
|
||||||
DEFAULT_CONFIG_PATH
|
|
||||||
))
|
|
||||||
.default_value(DEFAULT_CONFIG_PATH)
|
.default_value(DEFAULT_CONFIG_PATH)
|
||||||
.num_args(1)
|
.num_args(1)
|
||||||
.display_order(1),
|
.display_order(1),
|
||||||
@@ -81,7 +78,7 @@ fn main() {
|
|||||||
.short('c')
|
.short('c')
|
||||||
.long("config")
|
.long("config")
|
||||||
.value_name("CONFIG_FILE")
|
.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)
|
.default_value(DEFAULT_CONFIG_PATH)
|
||||||
.num_args(1)
|
.num_args(1)
|
||||||
.display_order(1),
|
.display_order(1),
|
||||||
@@ -104,7 +101,7 @@ fn main() {
|
|||||||
.short('c')
|
.short('c')
|
||||||
.long("config")
|
.long("config")
|
||||||
.value_name("CONFIG_FILE")
|
.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)
|
.default_value(DEFAULT_CONFIG_PATH)
|
||||||
.num_args(1)
|
.num_args(1)
|
||||||
.display_order(1),
|
.display_order(1),
|
||||||
|
100
src/mastodon.rs
100
src/mastodon.rs
@@ -1,7 +1,14 @@
|
|||||||
use crate::config::MastodonConfig;
|
use crate::config::MastodonConfig;
|
||||||
|
|
||||||
use egg_mode::entities::{MentionEntity, UrlEntity};
|
use egg_mode::{
|
||||||
use megalodon::{generator, mastodon::Mastodon, megalodon::AppInputOptions};
|
entities::{MentionEntity, UrlEntity},
|
||||||
|
user::UserEntityDetail,
|
||||||
|
};
|
||||||
|
use megalodon::{
|
||||||
|
generator,
|
||||||
|
mastodon::Mastodon,
|
||||||
|
megalodon::{AppInputOptions, CredentialsFieldAttribute},
|
||||||
|
};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::{collections::HashMap, io::stdin};
|
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>) {
|
pub fn replace_alt_services(urls: &mut HashMap<String, String>, alts: &HashMap<String, String>) {
|
||||||
for val in urls.values_mut() {
|
for val in urls.values_mut() {
|
||||||
for (k, v) in alts {
|
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(),
|
twitter_screen_name.to_lowercase(),
|
||||||
tweet_id
|
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)
|
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
|
/// Generic register function
|
||||||
/// As this function is supposed to be run only once, it will panic for every error it encounters
|
/// 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
|
/// 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!");
|
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: ");
|
println!("Paste the returned authorization code: ");
|
||||||
|
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
@@ -207,6 +240,63 @@ token = "{}""#,
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
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]
|
#[test]
|
||||||
fn test_replace_tweet_by_toot() {
|
fn test_replace_tweet_by_toot() {
|
||||||
let mut associated_urls = HashMap::from([
|
let mut associated_urls = HashMap::from([
|
||||||
|
@@ -21,8 +21,8 @@ pub fn read_state(
|
|||||||
) -> Result<Option<TweetToToot>, Box<dyn Error>> {
|
) -> Result<Option<TweetToToot>, Box<dyn Error>> {
|
||||||
debug!("Reading tweet_id {:?}", s);
|
debug!("Reading tweet_id {:?}", s);
|
||||||
let query: String = match s {
|
let query: String = match s {
|
||||||
Some(i) => format!("SELECT * FROM tweet_to_toot WHERE tweet_id = {} and twitter_screen_name = \"{}\"", i, 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 = \"{}\" ORDER BY tweet_id DESC LIMIT 1", 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)?;
|
let mut stmt = conn.prepare(&query)?;
|
||||||
@@ -78,8 +78,7 @@ pub fn migrate_db(d: &str, s: &str) -> Result<(), Box<dyn Error>> {
|
|||||||
&format!(
|
&format!(
|
||||||
"ALTER TABLE tweet_to_toot
|
"ALTER TABLE tweet_to_toot
|
||||||
ADD COLUMN twitter_screen_name TEXT NOT NULL
|
ADD COLUMN twitter_screen_name TEXT NOT NULL
|
||||||
DEFAULT \"{}\"",
|
DEFAULT \"{s}\""
|
||||||
s
|
|
||||||
),
|
),
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
45
src/util.rs
45
src/util.rs
@@ -4,12 +4,18 @@ use base64::encode;
|
|||||||
use egg_mode::tweet::Tweet;
|
use egg_mode::tweet::Tweet;
|
||||||
use futures::{stream, stream::StreamExt};
|
use futures::{stream, stream::StreamExt};
|
||||||
use log::{error, info, warn};
|
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 reqwest::Url;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
fs::{create_dir_all, remove_file, File},
|
fs::{create_dir_all, remove_file, File},
|
||||||
io::copy,
|
io::copy,
|
||||||
|
time::{sleep, Duration},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Generate associative table between media ids and tweet extended entities
|
/// 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
|
// it doesn’t matter if we can’t remove, cache_media fn is idempotent
|
||||||
remove_file(&local_tweet_media_path).await.ok();
|
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
|
.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)
|
(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
|
/// Transforms the media into a base64 equivalent
|
||||||
pub async fn base64_media(u: &str) -> Result<String, Box<dyn Error>> {
|
pub async fn base64_media(u: &str) -> Result<String, Box<dyn Error>> {
|
||||||
let mut response = reqwest::get(u).await?;
|
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
|
let content_type = response
|
||||||
.headers()
|
.headers()
|
||||||
.get("content-type")
|
.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()?;
|
.to_str()?;
|
||||||
|
|
||||||
let encoded_f = encode(buffer);
|
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
|
/// 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()
|
.path_segments()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
ScootalooError::new(&format!(
|
ScootalooError::new(&format!(
|
||||||
"Cannot determine the destination filename for {}",
|
"Cannot determine the destination filename for {u}"
|
||||||
u
|
|
||||||
))
|
))
|
||||||
})?
|
})?
|
||||||
.last()
|
.last()
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
ScootalooError::new(&format!(
|
ScootalooError::new(&format!(
|
||||||
"Cannot determine the destination filename for {}",
|
"Cannot determine the destination filename for {u}"
|
||||||
u
|
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let dest_filepath = format!("{}/{}", t, dest_filename);
|
let dest_filepath = format!("{t}/{dest_filename}");
|
||||||
|
|
||||||
let mut dest_file = File::create(&dest_filepath).await?;
|
let mut dest_file = File::create(&dest_filepath).await?;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user