Merge branch 'with_media_posts' into 'master'

With media posts

See merge request veretcle/scootaloo!2
This commit is contained in:
VC
2020-03-01 21:00:45 +01:00
4 changed files with 607 additions and 63 deletions

507
Cargo.lock generated
View File

@@ -24,6 +24,12 @@ dependencies = [
"winapi 0.3.8",
]
[[package]]
name = "anyhow"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c"
[[package]]
name = "atty"
version = "0.2.14"
@@ -78,6 +84,12 @@ dependencies = [
"byteorder",
]
[[package]]
name = "base64"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
[[package]]
name = "bitflags"
version = "1.2.1"
@@ -105,6 +117,12 @@ dependencies = [
"byte-tools",
]
[[package]]
name = "bumpalo"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742"
[[package]]
name = "byte-tools"
version = "0.3.1"
@@ -128,6 +146,12 @@ dependencies = [
"iovec",
]
[[package]]
name = "bytes"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1"
[[package]]
name = "c2-chacha"
version = "0.2.3"
@@ -322,12 +346,12 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e22c203f0b006bfd33496b5005fc3d5652f5c4967f7f4c1fea4fca8f59bcefd"
dependencies = [
"base64",
"base64 0.10.1",
"chrono",
"futures",
"hmac",
"hyper",
"hyper-tls",
"hyper 0.12.35",
"hyper-tls 0.3.2",
"lazy_static",
"mime",
"native-tls",
@@ -337,7 +361,7 @@ dependencies = [
"serde_derive",
"serde_json",
"sha-1",
"tokio",
"tokio 0.1.22",
"url 1.7.2",
]
@@ -454,6 +478,21 @@ version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef"
[[package]]
name = "futures-channel"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0c77d04ce8edd9cb903932b608268b3fffec4163dc053b3b402bf47eac1f1a8"
dependencies = [
"futures-core",
]
[[package]]
name = "futures-core"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a"
[[package]]
name = "futures-cpupool"
version = "0.1.8"
@@ -464,6 +503,38 @@ dependencies = [
"num_cpus",
]
[[package]]
name = "futures-io"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a638959aa96152c7a4cddf50fcb1e3fede0583b27157c26e67d6f99904090dc6"
[[package]]
name = "futures-sink"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3466821b4bc114d95b087b850a724c6f83115e929bc88f1fa98a3304a944c8a6"
[[package]]
name = "futures-task"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27"
[[package]]
name = "futures-util"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5"
dependencies = [
"futures-core",
"futures-io",
"futures-task",
"memchr",
"pin-utils",
"slab",
]
[[package]]
name = "generic-array"
version = "0.12.3"
@@ -491,10 +562,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462"
dependencies = [
"byteorder",
"bytes",
"bytes 0.4.12",
"fnv",
"futures",
"http",
"http 0.1.21",
"indexmap",
"log",
"slab",
@@ -502,6 +573,34 @@ dependencies = [
"tokio-io",
]
[[package]]
name = "h2"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1"
dependencies = [
"bytes 0.5.4",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http 0.2.0",
"indexmap",
"log",
"slab",
"tokio 0.2.13",
"tokio-util",
]
[[package]]
name = "heck"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.8"
@@ -527,7 +626,18 @@ version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0"
dependencies = [
"bytes",
"bytes 0.4.12",
"fnv",
"itoa",
]
[[package]]
name = "http"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b"
dependencies = [
"bytes 0.5.4",
"fnv",
"itoa",
]
@@ -538,12 +648,22 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d"
dependencies = [
"bytes",
"bytes 0.4.12",
"futures",
"http",
"http 0.1.21",
"tokio-buf",
]
[[package]]
name = "http-body"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
dependencies = [
"bytes 0.5.4",
"http 0.2.0",
]
[[package]]
name = "httparse"
version = "1.3.4"
@@ -556,12 +676,12 @@ version = "0.12.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6"
dependencies = [
"bytes",
"bytes 0.4.12",
"futures",
"futures-cpupool",
"h2",
"http",
"http-body",
"h2 0.1.26",
"http 0.1.21",
"http-body 0.1.0",
"httparse",
"iovec",
"itoa",
@@ -569,7 +689,7 @@ dependencies = [
"net2",
"rustc_version",
"time",
"tokio",
"tokio 0.1.22",
"tokio-buf",
"tokio-executor",
"tokio-io",
@@ -577,7 +697,31 @@ dependencies = [
"tokio-tcp",
"tokio-threadpool",
"tokio-timer",
"want",
"want 0.2.0",
]
[[package]]
name = "hyper"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa1c527bbc634be72aa7ba31e4e4def9bbb020f5416916279b7c705cd838893e"
dependencies = [
"bytes 0.5.4",
"futures-channel",
"futures-core",
"futures-util",
"h2 0.2.1",
"http 0.2.0",
"http-body 0.3.1",
"httparse",
"itoa",
"log",
"net2",
"pin-project",
"time",
"tokio 0.2.13",
"tower-service",
"want 0.3.0",
]
[[package]]
@@ -586,23 +730,36 @@ version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f"
dependencies = [
"bytes",
"bytes 0.4.12",
"futures",
"hyper",
"hyper 0.12.35",
"native-tls",
"tokio-io",
]
[[package]]
name = "hyper-tls"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa"
dependencies = [
"bytes 0.5.4",
"hyper 0.13.2",
"native-tls",
"tokio 0.2.13",
"tokio-tls",
]
[[package]]
name = "hyperx"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad5125567a8328ced412a29a52a3ca0a2520c617d40a8bee62d12d877eec236c"
dependencies = [
"base64",
"bytes",
"base64 0.10.1",
"bytes 0.4.12",
"cfg-if",
"http",
"http 0.1.21",
"httparse",
"language-tags",
"log",
@@ -658,6 +815,15 @@ version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e"
[[package]]
name = "js-sys"
version = "0.3.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
@@ -714,7 +880,7 @@ dependencies = [
"doc-comment",
"hyperx",
"log",
"reqwest",
"reqwest 0.9.24",
"serde",
"serde_derive",
"serde_json",
@@ -844,6 +1010,16 @@ dependencies = [
"winapi 0.3.8",
]
[[package]]
name = "nom"
version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
dependencies = [
"memchr",
"version_check 0.1.5",
]
[[package]]
name = "num-integer"
version = "0.1.42"
@@ -950,6 +1126,38 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pin-project"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pin-project-lite"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae"
[[package]]
name = "pin-utils"
version = "0.1.0-alpha.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
[[package]]
name = "pkg-config"
version = "0.3.17"
@@ -1188,25 +1396,25 @@ version = "0.9.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab"
dependencies = [
"base64",
"bytes",
"base64 0.10.1",
"bytes 0.4.12",
"cookie",
"cookie_store",
"encoding_rs",
"flate2",
"futures",
"http",
"hyper",
"hyper-tls",
"http 0.1.21",
"hyper 0.12.35",
"hyper-tls 0.3.2",
"log",
"mime",
"mime_guess",
"native-tls",
"serde",
"serde_json",
"serde_urlencoded",
"serde_urlencoded 0.5.5",
"time",
"tokio",
"tokio 0.1.22",
"tokio-executor",
"tokio-io",
"tokio-threadpool",
@@ -1216,6 +1424,41 @@ dependencies = [
"winreg",
]
[[package]]
name = "reqwest"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9f62f24514117d09a8fc74b803d3d65faa27cea1c7378fb12b0d002913f3831"
dependencies = [
"base64 0.11.0",
"bytes 0.5.4",
"encoding_rs",
"futures-core",
"futures-util",
"http 0.2.0",
"http-body 0.3.1",
"hyper 0.13.2",
"hyper-tls 0.4.1",
"js-sys",
"lazy_static",
"log",
"mime",
"mime_guess",
"native-tls",
"percent-encoding 2.1.0",
"pin-project-lite",
"serde",
"serde_urlencoded 0.6.1",
"time",
"tokio 0.2.13",
"tokio-tls",
"url 2.1.1",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"winreg",
]
[[package]]
name = "rustc-demangle"
version = "0.1.16"
@@ -1249,13 +1492,14 @@ dependencies = [
[[package]]
name = "scootaloo"
version = "0.1.1"
version = "0.1.2"
dependencies = [
"clap",
"egg-mode",
"mammut",
"reqwest 0.10.3",
"serde",
"tokio",
"tokio 0.1.22",
"toml",
]
@@ -1344,6 +1588,18 @@ dependencies = [
"url 1.7.2",
]
[[package]]
name = "serde_urlencoded"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
dependencies = [
"dtoa",
"itoa",
"serde",
"url 2.1.1",
]
[[package]]
name = "sha-1"
version = "0.8.2"
@@ -1377,13 +1633,19 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc"
[[package]]
name = "sourcefile"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3"
[[package]]
name = "string"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
dependencies = [
"bytes",
"bytes 0.4.12",
]
[[package]]
@@ -1470,7 +1732,7 @@ version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6"
dependencies = [
"bytes",
"bytes 0.4.12",
"futures",
"mio",
"num_cpus",
@@ -1488,13 +1750,30 @@ dependencies = [
"tokio-uds",
]
[[package]]
name = "tokio"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa5e81d6bc4e67fe889d5783bd2a128ab2e0cfa487e0be16b6a8d177b101616"
dependencies = [
"bytes 0.5.4",
"fnv",
"iovec",
"lazy_static",
"memchr",
"mio",
"num_cpus",
"pin-project-lite",
"slab",
]
[[package]]
name = "tokio-buf"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46"
dependencies = [
"bytes",
"bytes 0.4.12",
"either",
"futures",
]
@@ -1505,7 +1784,7 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b"
dependencies = [
"bytes",
"bytes 0.4.12",
"futures",
"tokio-io",
]
@@ -1547,7 +1826,7 @@ version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674"
dependencies = [
"bytes",
"bytes 0.4.12",
"futures",
"log",
]
@@ -1587,7 +1866,7 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72"
dependencies = [
"bytes",
"bytes 0.4.12",
"futures",
"iovec",
"mio",
@@ -1624,13 +1903,23 @@ dependencies = [
"tokio-executor",
]
[[package]]
name = "tokio-tls"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bde02a3a5291395f59b06ec6945a3077602fac2b07eeeaf0dee2122f3619828"
dependencies = [
"native-tls",
"tokio 0.2.13",
]
[[package]]
name = "tokio-udp"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82"
dependencies = [
"bytes",
"bytes 0.4.12",
"futures",
"log",
"mio",
@@ -1645,7 +1934,7 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798"
dependencies = [
"bytes",
"bytes 0.4.12",
"futures",
"iovec",
"libc",
@@ -1657,6 +1946,20 @@ dependencies = [
"tokio-reactor",
]
[[package]]
name = "tokio-util"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930"
dependencies = [
"bytes 0.5.4",
"futures-core",
"futures-sink",
"log",
"pin-project-lite",
"tokio 0.2.13",
]
[[package]]
name = "toml"
version = "0.5.6"
@@ -1666,6 +1969,12 @@ dependencies = [
"serde",
]
[[package]]
name = "tower-service"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
[[package]]
name = "try-lock"
version = "0.2.2"
@@ -1714,6 +2023,12 @@ dependencies = [
"smallvec 1.2.0",
]
[[package]]
name = "unicode-segmentation"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
[[package]]
name = "unicode-width"
version = "0.1.7"
@@ -1792,12 +2107,128 @@ dependencies = [
"try-lock",
]
[[package]]
name = "want"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
dependencies = [
"log",
"try-lock",
]
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wasm-bindgen"
version = "0.2.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c"
dependencies = [
"cfg-if",
"serde",
"serde_json",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bbdd49e3e28b40dec6a9ba8d17798245ce32b019513a845369c641b275135d9"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601"
[[package]]
name = "wasm-bindgen-webidl"
version = "0.2.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef012a0d93fc0432df126a8eaf547b2dce25a8ce9212e1d3cbeef5c11157975d"
dependencies = [
"anyhow",
"heck",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"weedle",
]
[[package]]
name = "web-sys"
version = "0.3.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf97caf6aa8c2b1dac90faf0db529d9d63c93846cca4911856f78a83cebf53b"
dependencies = [
"anyhow",
"js-sys",
"sourcefile",
"wasm-bindgen",
"wasm-bindgen-webidl",
]
[[package]]
name = "weedle"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164"
dependencies = [
"nom",
]
[[package]]
name = "winapi"
version = "0.2.8"

View File

@@ -1,6 +1,6 @@
[package]
name = "scootaloo"
version = "0.1.1"
version = "0.1.2"
authors = ["VC <veretcle+framagit@mateu.be>"]
edition = "2018"
@@ -15,3 +15,5 @@ tokio = "^0.1"
egg-mode = "^0.13"
mammut = "^0.13"
reqwest = { version = "^0.10", features = ["blocking"] }

View File

@@ -5,6 +5,11 @@ A Twitter to Mastodon copy bot written in Rust
First up, create a configuration file (default path is `/usr/local/etc/scootaloo.toml`). It will look like this:
```
[scootaloo]
last_tweet_path="/usr/local/etc/last_tweet" ## file containing the last tweet id received, must be writable
cache_path="/tmp/scootaloo" ## a dir where the temporary files will be download, must be writeable
[twitter]
username="NintendojoFR" ## User Timeline to copy
@@ -13,8 +18,6 @@ consumer_key="MYCONSUMERKEY"
consumer_secret="MYCONSUMERSECRET"
access_key="MYACCESSKEY"
access_secret="MYACCESSSECRET"
last_tweet_path="/usr/local/etc/last_tweet" ## file containing the last tweet id received, must be writable
```
Then run the command with the `register` subcommand:

View File

@@ -1,10 +1,11 @@
// std
use std::{
path::Path,
borrow::Cow,
collections::HashMap,
io,
io::{stdin, copy},
fmt,
fs::{read_to_string, write},
fs::{read_to_string, write, create_dir_all, File, remove_file},
error::Error,
};
@@ -15,7 +16,7 @@ use serde::Deserialize;
use egg_mode::{
Token,
KeyPair,
entities::UrlEntity,
entities::{UrlEntity, MediaEntity, MediaType},
tweet::{
Tweet,
user_timeline,
@@ -24,9 +25,17 @@ use egg_mode::{
use tokio::runtime::current_thread::block_on_all;
// mammut
use mammut::{Mastodon, Data, Registration};
use mammut::apps::{AppBuilder, Scopes};
use mammut::status_builder::StatusBuilder;
use mammut::{
Mastodon,
Data,
Registration,
apps::{AppBuilder, Scopes},
status_builder::StatusBuilder,
media_builder::MediaBuilder,
};
// reqwest
use reqwest::blocking::Client;
/**********
* Generic usage functions
@@ -64,13 +73,51 @@ fn get_oauth2_token(config: &Config) -> Token {
/// Get twitter user timeline
fn get_user_timeline(config: &Config, token: Token, lid: Option<u64>) -> Result<Vec<Tweet>, Box<dyn Error>> {
// fix the page size to 200 as it is the maximum Twitter authorizes
let (_timeline, feed) = block_on_all(user_timeline(&config.twitter.username, true, false, &token)
let (_timeline, feed) = block_on_all(user_timeline(&config.twitter.username, true, true, &token)
.with_page_size(200)
.older(lid))?;
Ok(feed.to_vec())
}
/// decode urls from UrlEntities
fn decode_urls(urls: &Vec<UrlEntity>) -> HashMap<String, String> {
let mut decoded_urls = HashMap::new();
for url in urls {
if url.expanded_url.is_some() {
// unwrap is safe here as we just verified that there is something inside expanded_url
decoded_urls.insert(String::from(&url.url), String::from(url.expanded_url.as_deref().unwrap()));
}
}
decoded_urls
}
/// Retrieve a single media from a tweet and store it in a temporary file
fn get_tweet_media(m: &MediaEntity, t: &str) -> Result<String, Box<dyn Error>> {
match m.media_type {
MediaType::Photo => {
return cache_media(&m.media_url_https, t);
},
_ => {
match &m.video_info {
Some(v) => {
for variant in &v.variants {
if variant.content_type == "video/mp4" {
return cache_media(&variant.url, t);
}
}
return Err(Box::new(ScootalooError::new(format!("Media Type for {} is video but no mp4 file URL is available", &m.url).as_str())));
},
None => {
return Err(Box::new(ScootalooError::new(format!("Media Type for {} is video but does not contain any video_info", &m.url).as_str())));
},
}
},
};
}
/*
* Those functions are related to the Mastodon side of things
*/
@@ -88,7 +135,7 @@ fn get_mastodon_token(masto: &MastodonConfig) -> Mastodon {
}
/// build toot from tweet
fn build_status(tweet: &Tweet) -> Result<StatusBuilder, Box<dyn Error>> {
fn build_basic_status(tweet: &Tweet) -> Result<StatusBuilder, Box<dyn Error>> {
let mut toot = String::from(&tweet.text);
let decoded_urls = decode_urls(&tweet.entities.urls);
@@ -100,17 +147,36 @@ fn build_status(tweet: &Tweet) -> Result<StatusBuilder, Box<dyn Error>> {
Ok(StatusBuilder::new(toot))
}
fn decode_urls(urls: &Vec<UrlEntity>) -> HashMap<String, String> {
let mut decoded_urls = HashMap::new();
for url in urls {
if url.expanded_url.is_some() {
// unwrap is safe here as we just verified that there is something inside expanded_url
decoded_urls.insert(String::from(&url.url), String::from(url.expanded_url.as_deref().unwrap()));
}
/*
* Generic private functions
*/
fn cache_media(u: &str, t: &str) -> Result<String, Box<dyn Error>> {
// create dir
if !Path::new(t).is_dir() {
create_dir_all(t)?;
}
decoded_urls
// get file
let client = Client::new();
let mut response = client.get(u).send()?;
// create local file
let dest_filename = match response.url()
.path_segments()
.and_then(|segments| segments.last()) {
Some(r) => r,
None => {
return Err(Box::new(ScootalooError::new(format!("Cannot determine the destination filename for {}", u).as_str())));
},
};
let dest_filepath = format!("{}/{}", t, dest_filename);
let mut dest_file = File::create(&dest_filepath)?;
copy(&mut response, &mut dest_file)?;
Ok(dest_filepath)
}
/**********
@@ -149,6 +215,7 @@ impl std::error::Error for ScootalooError {
pub struct Config {
twitter: TwitterConfig,
mastodon: MastodonConfig,
scootaloo: ScootalooConfig,
}
#[derive(Debug, Deserialize)]
@@ -158,7 +225,6 @@ struct TwitterConfig {
consumer_secret: String,
access_key: String,
access_secret: String,
last_tweet_path: String,
}
#[derive(Debug, Deserialize)]
@@ -170,6 +236,12 @@ struct MastodonConfig {
token: String,
}
#[derive(Debug, Deserialize)]
struct ScootalooConfig {
last_tweet_path: String,
cache_path: String,
}
/*********
* Main functions
*********/
@@ -205,7 +277,7 @@ pub fn register(host: &str) {
println!("Paste the returned authorization code: ");
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Unable to read back registration code!");
stdin().read_line(&mut input).expect("Unable to read back registration code!");
let code = input.trim();
let mastodon = registration.create_access_token(code.to_string()).expect("Unable to create access token!");
@@ -218,7 +290,7 @@ pub fn register(host: &str) {
/// This is where the magic happens
pub fn run(config: Config) {
// retrieve the last tweet ID for the username
let last_tweet_id = read_state(&config.twitter.last_tweet_path);
let last_tweet_id = read_state(&config.scootaloo.last_tweet_path);
// get OAuth2 token
let token = get_oauth2_token(&config);
@@ -241,7 +313,8 @@ pub fn run(config: Config) {
feed.reverse();
for tweet in &feed {
let status = match build_status(tweet) {
// build basic status by just yielding text and dereferencing contained urls
let mut status = match build_basic_status(tweet) {
Ok(t) => t,
Err(e) => {
println!("Could not create status from tweet {}: {}", tweet.id ,e);
@@ -249,11 +322,46 @@ pub fn run(config: Config) {
},
};
// reupload the attachments if any
if let Some(m) = &tweet.extended_entities {
for media in &m.media {
let local_tweet_media_path = match get_tweet_media(&media, &config.scootaloo.cache_path) {
Ok(m) => m,
Err(e) => {
println!("Cannot get tweet media for {}: {}", &media.url, e);
continue;
},
};
let mastodon_media_ids = match mastodon.media(MediaBuilder::new(Cow::from(String::from(&local_tweet_media_path)))) {
Ok(m) => {
remove_file(&local_tweet_media_path).unwrap_or_else(|e|
println!("Attachment for {} has been upload, but Im unable to remove the existing file: {}", &local_tweet_media_path, e)
);
m.id
},
Err(e) => {
println!("Cannot attach media {} to Mastodon Instance: {}", &local_tweet_media_path, e);
continue;
}
};
// media has been successfully uploaded, adding it to the toot
match status.media_ids {
Some(ref mut i) => i.push(mastodon_media_ids),
None => status.media_ids = Some(vec![mastodon_media_ids]),
};
// last step, removing the reference to the media from with the toots text
status.status = status.status.replace(&media.url, "");
}
}
// publish status
mastodon.new_status(status).unwrap();
// write the current state (tweet ID) to avoid copying it another time
write_state(&config.twitter.last_tweet_path, tweet.id).unwrap_or_else(|e|
write_state(&config.scootaloo.last_tweet_path, tweet.id).unwrap_or_else(|e|
panic!("Cant write the last tweet retrieved: {}", e)
);
}