mirror of
https://framagit.org/veretcle/oolatoocs.git
synced 2025-07-20 12:31:18 +02:00
111 lines
3.7 KiB
Rust
111 lines
3.7 KiB
Rust
mod error;
|
||
pub use error::OolatoocsError;
|
||
|
||
mod config;
|
||
pub use config::{parse_toml, Config};
|
||
|
||
mod state;
|
||
pub use state::init_db;
|
||
#[allow(unused_imports)]
|
||
use state::{read_state, write_state, TweetToToot};
|
||
|
||
mod mastodon;
|
||
use mastodon::get_mastodon_timeline_since;
|
||
pub use mastodon::register;
|
||
|
||
mod utils;
|
||
use utils::strip_everything;
|
||
|
||
mod twitter;
|
||
#[allow(unused_imports)]
|
||
use twitter::{post_tweet, upload_chunk_media, upload_simple_media};
|
||
|
||
use futures::{stream, StreamExt};
|
||
use log::{error, warn};
|
||
use megalodon::entities::attachment::AttachmentType;
|
||
use rusqlite::Connection;
|
||
use std::error::Error;
|
||
|
||
#[tokio::main]
|
||
pub async fn run(config: &Config) {
|
||
let conn = Connection::open(&config.oolatoocs.db_path)
|
||
.unwrap_or_else(|e| panic!("Cannot open DB: {}", e));
|
||
|
||
let last_toot_id = read_state(&conn, None)
|
||
.unwrap_or_else(|e| panic!("Cannot get last toot id: {}", e))
|
||
.map(|r| r.toot_id);
|
||
|
||
let timeline = get_mastodon_timeline_since(&config.mastodon, last_toot_id)
|
||
.await
|
||
.unwrap_or_else(|e| panic!("Cannot get instance: {}", e));
|
||
|
||
for toot in timeline {
|
||
let Ok(tweet_content) = strip_everything(&toot.content, &toot.tags) else {
|
||
continue; // skip in case we can’t strip something
|
||
};
|
||
|
||
let mut medias: Vec<u64> = vec![];
|
||
|
||
// if we wanted to cut toot in half, now would be the right time to do so
|
||
|
||
let media_attachments = toot.media_attachments.clone();
|
||
let mut stream = stream::iter(media_attachments)
|
||
.map(|media| {
|
||
let twitter_config = config.twitter.clone();
|
||
tokio::task::spawn(async move {
|
||
match media.r#type {
|
||
AttachmentType::Image => {
|
||
upload_simple_media(&twitter_config, &media.url, &media.description)
|
||
.await
|
||
}
|
||
AttachmentType::Gifv => {
|
||
upload_chunk_media(&twitter_config, &media.url, "tweet_gif").await
|
||
}
|
||
AttachmentType::Video => {
|
||
upload_chunk_media(&twitter_config, &media.url, "tweet_video").await
|
||
}
|
||
_ => Err::<u64, Box<dyn Error + Send + Sync>>(
|
||
OolatoocsError::new(&format!(
|
||
"Cannot treat this type of media: {}",
|
||
&media.url
|
||
))
|
||
.into(),
|
||
),
|
||
}
|
||
})
|
||
})
|
||
.buffered(4);
|
||
|
||
while let Some(result) = stream.next().await {
|
||
match result {
|
||
Ok(Ok(v)) => medias.push(v),
|
||
Ok(Err(e)) => warn!("Cannot treat media: {}", e),
|
||
Err(e) => error!("Something went wrong when joining the main thread: {}", e),
|
||
}
|
||
}
|
||
|
||
// threads if necessary
|
||
let reply_to = toot.in_reply_to_id.and_then(|t| {
|
||
read_state(&conn, Some(t.parse::<u64>().unwrap()))
|
||
.ok()
|
||
.flatten()
|
||
.map(|s| s.tweet_id)
|
||
});
|
||
|
||
// posts corresponding tweet
|
||
let tweet_id = post_tweet(&config.twitter, &tweet_content, &medias, &reply_to)
|
||
.await
|
||
.unwrap_or_else(|e| panic!("Cannot Tweet {}: {}", toot.id, e));
|
||
|
||
// writes the current state of the tweet
|
||
write_state(
|
||
&conn,
|
||
TweetToToot {
|
||
tweet_id,
|
||
toot_id: toot.id.parse::<u64>().unwrap(),
|
||
},
|
||
)
|
||
.unwrap_or_else(|e| panic!("Cannot store Toot/Tweet ({}/{}): {}", &toot.id, tweet_id, e));
|
||
}
|
||
}
|