8 Commits

Author SHA1 Message Date
VC
5606d00da2 Merge branch '10-better-embed-links-for-bsky' into 'main'
: add embed card when available

Closes #10

See merge request veretcle/oolatoocs!29
2025-01-26 08:50:43 +00:00
VC
4cb80b0607 : add embed card when available 2025-01-26 09:33:20 +01:00
VC
bbe14f1f30 Merge branch 'feat_update_dependencies' into 'main'
⬆️: update all dependencies

See merge request veretcle/oolatoocs!28
2025-01-24 14:43:51 +00:00
VC
6fbc011914 ⬆️: update all dependencies 2025-01-24 15:38:46 +01:00
VC
8f23c2459b Merge branch 'feat_megalodon_update' into 'main'
⬆️: megalodon 1.0.0

See merge request veretcle/oolatoocs!27
2025-01-24 14:20:44 +00:00
VC
26805feadb ⬆️: megalodon 1.0.0 2025-01-24 15:12:08 +01:00
VC
3a8fd538fc Merge branch '11-optimize-image-upload' into 'main'
🎨: improve bsky image upload

Closes #11

See merge request veretcle/oolatoocs!26
2025-01-24 13:43:06 +00:00
VC
891f46ec2f 🎨: improve bsky image upload 2025-01-24 14:34:01 +01:00
5 changed files with 288 additions and 176 deletions

290
Cargo.lock generated
View File

@@ -17,18 +17,6 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "aho-corasick"
version = "1.1.3"
@@ -44,12 +32,6 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1"
[[package]]
name = "allocator-api2"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]]
name = "android-tzdata"
version = "0.1.1"
@@ -168,6 +150,12 @@ dependencies = [
"syn",
]
[[package]]
name = "atomic-waker"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]]
name = "atrium-api"
version = "0.24.10"
@@ -479,6 +467,16 @@ dependencies = [
"libc",
]
[[package]]
name = "core-foundation"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
@@ -496,9 +494,9 @@ dependencies = [
[[package]]
name = "cpufeatures"
version = "0.2.16"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
dependencies = [
"libc",
]
@@ -617,16 +615,26 @@ dependencies = [
]
[[package]]
name = "env_logger"
version = "0.10.2"
name = "env_filter"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
dependencies = [
"humantime",
"is-terminal",
"log",
"regex",
"termcolor",
]
[[package]]
name = "env_logger"
version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"humantime",
"log",
]
[[package]]
@@ -709,6 +717,12 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
[[package]]
name = "foreign-types"
version = "0.3.2"
@@ -733,6 +747,21 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "futures"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.31"
@@ -740,6 +769,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
@@ -748,6 +778,17 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-executor"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.31"
@@ -783,6 +824,7 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
@@ -858,6 +900,25 @@ dependencies = [
"tracing",
]
[[package]]
name = "h2"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e"
dependencies = [
"atomic-waker",
"bytes",
"fnv",
"futures-core",
"futures-sink",
"http 1.2.0",
"indexmap",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "half"
version = "2.4.1"
@@ -868,29 +929,22 @@ dependencies = [
"crunchy",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
dependencies = [
"ahash",
"allocator-api2",
]
[[package]]
name = "hashbrown"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
dependencies = [
"foldhash",
]
[[package]]
name = "hashlink"
version = "0.8.4"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
dependencies = [
"hashbrown 0.14.5",
"hashbrown",
]
[[package]]
@@ -899,12 +953,6 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
[[package]]
name = "hex"
version = "0.4.3"
@@ -1013,7 +1061,7 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-util",
"h2",
"h2 0.3.26",
"http 0.2.12",
"http-body 0.4.6",
"httparse",
@@ -1036,6 +1084,7 @@ dependencies = [
"bytes",
"futures-channel",
"futures-util",
"h2 0.4.7",
"http 1.2.0",
"http-body 1.0.1",
"httparse",
@@ -1078,19 +1127,6 @@ dependencies = [
"webpki-roots 0.26.7",
]
[[package]]
name = "hyper-tls"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [
"bytes",
"hyper 0.14.32",
"native-tls",
"tokio",
"tokio-native-tls",
]
[[package]]
name = "hyper-tls"
version = "0.6.0"
@@ -1334,7 +1370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
dependencies = [
"equivalent",
"hashbrown 0.15.2",
"hashbrown",
]
[[package]]
@@ -1365,17 +1401,6 @@ version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
[[package]]
name = "is-terminal"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e19b23d53f35ce9f56aebc7d1bb4e6ac1e9c0db7ac85c8d1760c04379edced37"
dependencies = [
"hermit-abi",
"libc",
"windows-sys 0.59.0",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
@@ -1455,9 +1480,9 @@ dependencies = [
[[package]]
name = "libsqlite3-sys"
version = "0.27.0"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716"
checksum = "ad8935b44e7c13394a179a438e0cebba0fe08fe01b54f152e29a93b5cf993fd4"
dependencies = [
"pkg-config",
"vcpkg",
@@ -1522,9 +1547,9 @@ dependencies = [
[[package]]
name = "megalodon"
version = "0.13.10"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef39d0ff14ab57bc76f675ca00dae297eb2e75ae28281a0b7a451bcf9cc94b6"
checksum = "6053001f2fd3082f7c6007225fef9cf6c0bbea96d8fc82976fb0dcfda3bcbf30"
dependencies = [
"async-trait",
"chrono",
@@ -1620,9 +1645,9 @@ dependencies = [
[[package]]
name = "native-tls"
version = "0.2.12"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466"
checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c"
dependencies = [
"libc",
"log",
@@ -1630,7 +1655,7 @@ dependencies = [
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework 2.11.1",
"security-framework-sys",
"tempfile",
]
@@ -1781,20 +1806,21 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "oolatoocs"
version = "4.1.1"
version = "4.2.0"
dependencies = [
"atrium-api",
"bsky-sdk",
"chrono",
"clap",
"env_logger",
"futures",
"html-escape",
"image",
"log",
"megalodon",
"oauth1-request",
"regex",
"reqwest 0.11.27",
"reqwest 0.12.12",
"rusqlite",
"serde",
"tokio",
@@ -1804,9 +1830,9 @@ dependencies = [
[[package]]
name = "openssl"
version = "0.10.68"
version = "0.10.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5"
checksum = "f5e534d133a060a3c19daec1eb3e98ec6f4685978834f2dbadfe2ec215bab64e"
dependencies = [
"bitflags 2.8.0",
"cfg-if",
@@ -1830,9 +1856,9 @@ dependencies = [
[[package]]
name = "openssl-probe"
version = "0.1.5"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
[[package]]
name = "openssl-sys"
@@ -2221,18 +2247,15 @@ dependencies = [
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"h2 0.3.26",
"http 0.2.12",
"http-body 0.4.6",
"hyper 0.14.32",
"hyper-rustls 0.24.2",
"hyper-tls 0.5.0",
"ipnet",
"js-sys",
"log",
"mime",
"mime_guess",
"native-tls",
"once_cell",
"percent-encoding",
"pin-project-lite",
@@ -2242,16 +2265,13 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"sync_wrapper 0.1.2",
"system-configuration",
"system-configuration 0.5.1",
"tokio",
"tokio-native-tls",
"tokio-rustls 0.24.1",
"tokio-util",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-streams",
"web-sys",
"webpki-roots 0.25.4",
"winreg",
@@ -2266,14 +2286,16 @@ dependencies = [
"async-compression",
"base64 0.22.1",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2 0.4.7",
"http 1.2.0",
"http-body 1.0.1",
"http-body-util",
"hyper 1.5.2",
"hyper-rustls 0.27.5",
"hyper-tls 0.6.0",
"hyper-tls",
"hyper-util",
"ipnet",
"js-sys",
@@ -2292,6 +2314,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"sync_wrapper 1.0.2",
"system-configuration 0.6.1",
"tokio",
"tokio-native-tls",
"tokio-rustls 0.26.1",
@@ -2330,9 +2353,9 @@ dependencies = [
[[package]]
name = "rusqlite"
version = "0.30.0"
version = "0.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a78046161564f5e7cd9008aff3b2990b3850dc8e0349119b98e8f251e099f24d"
checksum = "1c6d5e5acb6f6129fe3f7ba0a7fc77bca1942cb568535e18e7bc40262baf3110"
dependencies = [
"bitflags 2.8.0",
"chrono",
@@ -2396,15 +2419,14 @@ dependencies = [
[[package]]
name = "rustls-native-certs"
version = "0.7.3"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5"
checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3"
dependencies = [
"openssl-probe",
"rustls-pemfile 2.2.0",
"rustls-pki-types",
"schannel",
"security-framework",
"security-framework 3.2.0",
]
[[package]]
@@ -2499,7 +2521,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags 2.8.0",
"core-foundation",
"core-foundation 0.9.4",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316"
dependencies = [
"bitflags 2.8.0",
"core-foundation 0.10.0",
"core-foundation-sys",
"libc",
"security-framework-sys",
@@ -2745,8 +2780,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"system-configuration-sys",
"core-foundation 0.9.4",
"system-configuration-sys 0.5.0",
]
[[package]]
name = "system-configuration"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags 2.8.0",
"core-foundation 0.9.4",
"system-configuration-sys 0.6.0",
]
[[package]]
@@ -2759,6 +2805,16 @@ dependencies = [
"libc",
]
[[package]]
name = "system-configuration-sys"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "system-deps"
version = "6.2.2"
@@ -2792,15 +2848,6 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.69"
@@ -2938,9 +2985,9 @@ dependencies = [
[[package]]
name = "tokio-tungstenite"
version = "0.23.1"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd"
checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9"
dependencies = [
"futures-util",
"log",
@@ -3076,9 +3123,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "tungstenite"
version = "0.23.0"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8"
checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a"
dependencies = [
"byteorder",
"bytes",
@@ -3109,9 +3156,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
[[package]]
name = "unicode-ident"
version = "1.0.14"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243"
[[package]]
name = "unicode-segmentation"
@@ -3367,15 +3414,6 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082"
[[package]]
name = "winapi-util"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "windows-core"
version = "0.52.0"

View File

@@ -1,6 +1,6 @@
[package]
name = "oolatoocs"
version = "4.1.1"
version = "4.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -8,19 +8,20 @@ edition = "2021"
[dependencies]
chrono = "^0.4"
clap = "^4"
env_logger = "^0.10"
env_logger = "^0.11"
futures = "^0.3"
html-escape = "^0.2"
log = "^0.4"
megalodon = "^0.13"
megalodon = "^1.0"
oauth1-request = "^0.6"
regex = "^1.10"
reqwest = { version = "^0.11", features = ["json", "stream", "multipart"] }
rusqlite = { version = "^0.30", features = ["chrono"] }
reqwest = { version = "^0.12", features = ["json", "stream", "multipart"] }
rusqlite = { version = "^0.33", features = ["chrono"] }
serde = { version = "^1.0", features = ["derive"] }
tokio = { version = "^1.33", features = ["rt-multi-thread", "macros"] }
toml = "^0.8"
bsky-sdk = "^0.1"
atrium-api = "^0.24"
atrium-api = { version = "^0.24", features = ["namespace-appbsky"] }
image = "^0.25"
webp = "^0.3"

View File

@@ -8,9 +8,13 @@ use bsky_sdk::{
rich_text::RichText,
BskyAgent,
};
use futures::{stream, StreamExt};
use image::ImageReader;
use log::{debug, error};
use megalodon::entities::attachment::{Attachment, AttachmentType};
use log::{debug, error, warn};
use megalodon::entities::{
attachment::{Attachment, AttachmentType},
card::Card,
};
use regex::Regex;
use std::{error::Error, fs::exists, io::Cursor};
use webp::*;
@@ -144,7 +148,43 @@ async fn get_record(
Ok(record)
}
// its ugly af but it gets the job done for now
/// Generate an embed card record into Bsky
/// If the preview image does not exist or fails to upload, it is simply ignored
pub async fn generate_embed_records(
bsky: &BskyAgent,
card: &Card,
) -> Option<atrium_api::types::Union<atrium_api::app::bsky::feed::post::RecordEmbedRefs>> {
// uploads the image card, if it fails, simply ignore everything
let blob = if let Some(url) = &card.image {
if let Ok(image_blob) = upload_media(true, bsky, url).await {
Some(image_blob.blob.clone())
} else {
None
}
} else {
None
};
let record_card = atrium_api::app::bsky::embed::external::ExternalData {
description: card.description.clone(),
thumb: blob,
title: card.title.clone(),
uri: card.url.clone(),
};
Some(atrium_api::types::Union::Refs(
atrium_api::app::bsky::feed::post::RecordEmbedRefs::AppBskyEmbedExternalMain(Box::new(
atrium_api::app::bsky::embed::external::MainData {
external: record_card.into(),
}
.into(),
)),
))
}
/// Generate an array of Bsky media records
/// As Bsky does not support multiple video in a record or mix of video and images, video has the
/// highest priority
pub async fn generate_media_records(
bsky: &BskyAgent,
media_attach: &[Attachment],
@@ -152,39 +192,66 @@ pub async fn generate_media_records(
let mut embed: Option<
atrium_api::types::Union<atrium_api::app::bsky::feed::post::RecordEmbedRefs>,
> = None;
let mut images = Vec::new();
let mut videos: Vec<atrium_api::app::bsky::embed::video::MainData> = Vec::new();
for media in media_attach.iter() {
match media.r#type {
AttachmentType::Image => {
let blob = upload_media(true, bsky, &media.url).await.unwrap();
let image_media_attach: Vec<_> = media_attach
.iter()
.filter(|x| x.r#type == AttachmentType::Image)
.cloned()
.collect();
let video_media_attach: Vec<_> = media_attach
.iter()
.filter(|x| (x.r#type == AttachmentType::Video || x.r#type == AttachmentType::Gifv))
.cloned()
.collect();
images.push(
// Bsky only tasks 1 video per post, so well try to treat that first and exit
if !video_media_attach.is_empty() {
// treat only the very first video, ignore the rest
let media = &video_media_attach[0];
let blob = upload_media(false, bsky, &media.url).await.unwrap();
embed = Some(atrium_api::types::Union::Refs(
atrium_api::app::bsky::feed::post::RecordEmbedRefs::AppBskyEmbedVideoMain(Box::new(
atrium_api::app::bsky::embed::video::MainData {
alt: media.description.clone(),
aspect_ratio: None,
captions: None,
video: blob.data.blob,
}
.into(),
)),
));
// returns immediately, we dont want to treat the other medias
return embed;
}
let mut stream = stream::iter(image_media_attach)
.map(|media| {
let bsky = bsky.clone();
tokio::task::spawn(async move {
debug!("Treating media {}", &media.url);
upload_media(true, &bsky, &media.url).await.map(|i| {
atrium_api::app::bsky::embed::images::ImageData {
alt: media
.description
.clone()
.map_or("".to_string(), |v| v.to_owned()),
aspect_ratio: None,
image: blob.data.blob,
image: i.data.blob,
}
.into(),
);
}
AttachmentType::Gifv | AttachmentType::Video => {
let blob = upload_media(false, bsky, &media.url).await.unwrap();
})
})
})
.buffered(4);
videos.push(atrium_api::app::bsky::embed::video::MainData {
alt: media.description.clone(),
aspect_ratio: None,
captions: None,
video: blob.data.blob,
});
}
_ => {
error!("Not an image, not a video, what happened here?");
}
let mut images = Vec::new();
while let Some(result) = stream.next().await {
match result {
Ok(Ok(v)) => images.push(v.into()),
Ok(Err(e)) => warn!("Cannot treat a specific media: {}", e),
Err(e) => error!("Something went wrong when joining main thread: {}", e),
}
}
@@ -196,19 +263,14 @@ pub async fn generate_media_records(
));
}
// if a video has been uploaded, it takes priority as you can only have 1 video per post
if !videos.is_empty() {
embed = Some(atrium_api::types::Union::Refs(
atrium_api::app::bsky::feed::post::RecordEmbedRefs::AppBskyEmbedVideoMain(Box::new(
videos[0].clone().into(),
)),
))
}
embed
}
async fn upload_media(is_image: bool, bsky: &BskyAgent, u: &str) -> Result<Output, Box<dyn Error>> {
async fn upload_media(
is_image: bool,
bsky: &BskyAgent,
u: &str,
) -> Result<Output, Box<dyn Error + Send + Sync>> {
let dl = reqwest::get(u).await?;
let content_length = dl.content_length().ok_or("Content length unavailable")?;
let bytes = if content_length <= 1_000_000 || !is_image {

View File

@@ -18,7 +18,9 @@ mod utils;
use utils::{generate_multi_tweets, strip_everything};
mod bsky;
use bsky::{build_post_record, generate_media_records, get_session, BskyReply};
use bsky::{
build_post_record, generate_embed_records, generate_media_records, get_session, BskyReply,
};
use rusqlite::Connection;
@@ -27,7 +29,8 @@ pub async fn run(config: &Config) {
let conn = Connection::open(&config.oolatoocs.db_path)
.unwrap_or_else(|e| panic!("Cannot open DB: {}", e));
let mastodon = get_mastodon_instance(&config.mastodon);
let mastodon = get_mastodon_instance(&config.mastodon)
.unwrap_or_else(|e| panic!("Cannot instantiate Mastodon: {}", e));
let bluesky = get_session(&config.bluesky)
.await
@@ -151,14 +154,21 @@ pub async fn run(config: &Config) {
};
// treats medias
let record_medias = generate_media_records(&bluesky, &toot.media_attachments).await;
let mut record_embed = generate_media_records(&bluesky, &toot.media_attachments).await;
// treats embed cards if any
if let Some(card) = &toot.card {
if record_embed.is_none() {
record_embed = generate_embed_records(&bluesky, card).await;
}
}
// posts corresponding tweet
let record = build_post_record(
&config.bluesky,
&tweet_content,
&toot.language,
record_medias,
record_embed,
&record_reply_to,
)
.await

View File

@@ -12,12 +12,12 @@ use std::error::Error;
use std::io::stdin;
/// Get Mastodon Object instance
pub fn get_mastodon_instance(config: &MastodonConfig) -> Mastodon {
Mastodon::new(
pub fn get_mastodon_instance(config: &MastodonConfig) -> Result<Mastodon, Box<dyn Error>> {
Ok(Mastodon::new(
config.base.to_string(),
Some(config.token.to_string()),
None,
)
)?)
}
/// Get the edited_at field from the specified toot
@@ -71,7 +71,8 @@ pub async fn get_mastodon_timeline_since(
/// Most of this function is a direct copy/paste of the official `elefren` crate
#[tokio::main]
pub async fn register(host: &str) {
let mastodon = generator(megalodon::SNS::Mastodon, host.to_string(), None, None);
let mastodon = generator(megalodon::SNS::Mastodon, host.to_string(), None, None)
.expect("Cannot build Mastodon generator object");
let options = AppInputOptions {
redirect_uris: None,