diff --git a/.gitignore b/.gitignore index d91a80f..062bb79 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target .last_tweet .config.toml +.config.json diff --git a/Cargo.lock b/Cargo.lock index c9ac9f9..4830266 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] @@ -116,9 +116,9 @@ checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "async-compression" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" +checksum = "7e614738943d3f68c628ae3dbce7c3daffb196665f82f8c8ea6b65de73c79429" dependencies = [ "flate2", "futures-core", @@ -287,9 +287,9 @@ checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.24" +version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938" +checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" dependencies = [ "shlex", ] @@ -556,9 +556,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -571,9 +571,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -581,15 +581,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -598,15 +598,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -615,21 +615,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -668,9 +668,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "h2" @@ -893,7 +893,7 @@ dependencies = [ "http 1.1.0", "hyper 1.4.1", "hyper-util", - "rustls 0.23.13", + "rustls 0.23.14", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -1005,9 +1005,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is-terminal" @@ -1265,25 +1265,22 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.20.1" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" -dependencies = [ - "portable-atomic", -] +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "oolatoocs" -version = "3.0.3" +version = "3.1.0" dependencies = [ "atrium-api", "bsky-sdk", @@ -1395,12 +1392,6 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" -[[package]] -name = "portable-atomic" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" - [[package]] name = "ppv-lite86" version = "0.2.20" @@ -1477,7 +1468,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.13", + "rustls 0.23.14", "socket2", "thiserror", "tokio", @@ -1494,7 +1485,7 @@ dependencies = [ "rand", "ring", "rustc-hash", - "rustls 0.23.13", + "rustls 0.23.14", "slab", "thiserror", "tinyvec", @@ -1666,7 +1657,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.13", + "rustls 0.23.14", "rustls-pemfile 2.2.0", "rustls-pki-types", "serde", @@ -1756,9 +1747,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.13" +version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" dependencies = [ "once_cell", "ring", @@ -1834,9 +1825,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ "windows-sys 0.59.0", ] @@ -2215,7 +2206,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.13", + "rustls 0.23.14", "rustls-pki-types", "tokio", ] @@ -2228,7 +2219,7 @@ checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" dependencies = [ "futures-util", "log", - "rustls 0.23.13", + "rustls 0.23.14", "rustls-native-certs", "rustls-pki-types", "tokio", @@ -2350,7 +2341,7 @@ dependencies = [ "httparse", "log", "rand", - "rustls 0.23.13", + "rustls 0.23.14", "rustls-pki-types", "sha1", "thiserror", @@ -2375,9 +2366,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" diff --git a/Cargo.toml b/Cargo.toml index 52e59c3..bf0bd79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "oolatoocs" -version = "3.0.3" +version = "3.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/README.md b/README.md index 312b935..1be3f86 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ oauth_token_secret = "" [bluesky] handle = "nintendojofr.bsky.social" password = "" +config_path = "/var/lib/oolatoocs/bsky.json" ``` ## How to generate the Mastodon keys? @@ -64,7 +65,7 @@ Will I some day make a subcommand to generate it? Maybe… ## How to generate the Bluesky part? -You’ll need your handle and password. I strongly recommend a dedicated application password. +You’ll need your handle and password. I strongly recommend a dedicated application password. You’ll also need a writable path to store the Bsky session. # How to run diff --git a/src/bsky.rs b/src/bsky.rs index 4552b64..ba07630 100644 --- a/src/bsky.rs +++ b/src/bsky.rs @@ -3,11 +3,15 @@ use atrium_api::{ app::bsky::feed::post::RecordData, com::atproto::repo::upload_blob::Output, types::string::Datetime, types::string::Language, }; -use bsky_sdk::{rich_text::RichText, BskyAgent}; +use bsky_sdk::{ + agent::config::{Config, FileStore}, + rich_text::RichText, + BskyAgent, +}; use log::error; use megalodon::entities::attachment::{Attachment, AttachmentType}; use regex::Regex; -use std::error::Error; +use std::{error::Error, fs::exists}; /// Intermediary struct to deal with replies more easily #[derive(Debug)] @@ -16,6 +20,34 @@ pub struct BskyReply { pub root_record_uri: String, } +pub async fn get_session(config: &BlueskyConfig) -> Result> { + if exists(&config.config_path)? { + let bluesky = BskyAgent::builder() + .config(Config::load(&FileStore::new(&config.config_path)).await?) + .build() + .await?; + + if bluesky.api.com.atproto.server.get_session().await.is_ok() { + bluesky + .to_config() + .await + .save(&FileStore::new(&config.config_path)) + .await?; + return Ok(bluesky); + } + } + + let bluesky = BskyAgent::builder().build().await?; + bluesky.login(&config.handle, &config.password).await?; + bluesky + .to_config() + .await + .save(&FileStore::new(&config.config_path)) + .await?; + + Ok(bluesky) +} + pub async fn build_post_record( config: &BlueskyConfig, text: &str, @@ -196,6 +228,7 @@ mod tests { let bsky_conf = BlueskyConfig { handle: "tamerelol.bsky.social".to_string(), password: "dtc".to_string(), + config_path: "nope".to_string(), }; let created_record_data = build_post_record(&bsky_conf, text, &None, None, &None) diff --git a/src/config.rs b/src/config.rs index 3468662..719d0ae 100644 --- a/src/config.rs +++ b/src/config.rs @@ -35,6 +35,7 @@ pub struct MastodonConfig { pub struct BlueskyConfig { pub handle: String, pub password: String, + pub config_path: String, } /// parses TOML file into Config struct diff --git a/src/lib.rs b/src/lib.rs index bb18ce1..a3b5062 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -use bsky_sdk::BskyAgent; use log::debug; mod error; @@ -22,7 +21,7 @@ mod twitter; use twitter::{delete_tweet, generate_media_ids, post_tweet, transform_poll}; mod bsky; -use bsky::{build_post_record, generate_media_records, BskyReply}; +use bsky::{build_post_record, generate_media_records, get_session, BskyReply}; use rusqlite::Connection; @@ -33,10 +32,9 @@ pub async fn run(config: &Config) { let mastodon = get_mastodon_instance(&config.mastodon); - let bluesky = BskyAgent::builder() - .build() + let bluesky = get_session(&config.bluesky) .await - .unwrap_or_else(|e| panic!("Can’t build Bsky Agent: {}", e)); + .unwrap_or_else(|e| panic!("Cannot get Bsky session: {}", e)); let last_entry = read_state(&conn, None).unwrap_or_else(|e| panic!("Cannot get last toot id: {}", e)); @@ -64,13 +62,6 @@ pub async fn run(config: &Config) { panic!("Cannot delete Tweet ID ({}): {}", t.tweet_id, e) }); } - - debug!("Create Bsky session prior to deletion"); - bluesky - .login(&config.bluesky.handle, &config.bluesky.password) - .await - .unwrap_or_else(|e| panic!("Cannot login to Bsky: {}", e)); - for local_record_uri in local_record_uris.into_iter() { bluesky .delete_record(&local_record_uri) @@ -108,14 +99,6 @@ pub async fn run(config: &Config) { continue; // skip in case we can’t strip something }; - debug!("Now we need a valid Bsky session, creating it"); - if bluesky.api.com.atproto.server.get_session().await.is_err() { - bluesky - .login(&config.bluesky.handle, &config.bluesky.password) - .await - .unwrap_or_else(|e| panic!("Cannot login to Bsky: {}", e)); - } - // threads if necessary let (mut tweet_reply_to, mut record_reply_to) = toot .in_reply_to_id