refactor: separate function for media ids

This commit is contained in:
VC
2022-11-05 07:57:03 +01:00
parent df75520175
commit de758c7bda
5 changed files with 68 additions and 48 deletions

2
Cargo.lock generated
View File

@@ -2016,7 +2016,7 @@ dependencies = [
[[package]] [[package]]
name = "scootaloo" name = "scootaloo"
version = "0.7.1" version = "0.7.2"
dependencies = [ dependencies = [
"chrono", "chrono",
"clap", "clap",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "scootaloo" name = "scootaloo"
version = "0.7.1" version = "0.7.2"
authors = ["VC <veretcle+framagit@mateu.be>"] authors = ["VC <veretcle+framagit@mateu.be>"]
edition = "2021" edition = "2021"

View File

@@ -13,16 +13,17 @@ mod twitter;
use twitter::*; use twitter::*;
mod util; mod util;
use crate::util::generate_media_ids;
mod state; mod state;
pub use state::{init_db, migrate_db}; pub use state::{init_db, migrate_db};
use state::{read_state, write_state, TweetToToot}; use state::{read_state, write_state, TweetToToot};
use elefren::{prelude::*, status_builder::StatusBuilder}; use elefren::{prelude::*, status_builder::StatusBuilder};
use log::{debug, error, info, warn}; use log::{debug, info};
use rusqlite::Connection; use rusqlite::Connection;
use std::{borrow::Cow, sync::Arc}; use std::sync::Arc;
use tokio::{fs::remove_file, spawn, sync::Mutex, task::JoinHandle}; use tokio::{spawn, sync::Mutex, task::JoinHandle};
/// This is where the magic happens /// This is where the magic happens
#[tokio::main] #[tokio::main]
@@ -106,46 +107,11 @@ pub async fn run(config: Config) {
// build basic status by just yielding text and dereferencing contained urls // build basic status by just yielding text and dereferencing contained urls
let mut status_text = build_basic_status(tweet); let mut status_text = build_basic_status(tweet);
let mut status_medias: Vec<String> = vec![]; // building associative media list
// reupload the attachments if any let (media_url, status_medias) =
if let Some(m) = &tweet.extended_entities { generate_media_ids(tweet, &scootaloo_cache_path, &mastodon).await;
for media in &m.media {
let local_tweet_media_path =
match get_tweet_media(media, &scootaloo_cache_path).await {
Ok(m) => m,
Err(e) => {
error!("Cannot get tweet media for {}: {}", &media.url, e);
continue;
}
};
let mastodon_media_ids = match mastodon status_text = status_text.replace(&media_url, "");
.media(Cow::from(local_tweet_media_path.to_owned()))
{
Ok(m) => {
remove_file(&local_tweet_media_path)
.await
.unwrap_or_else(|e|
warn!("Attachment for {} has been uploaded, but Im unable to remove the existing file: {}", &local_tweet_media_path, e)
);
m.id
}
Err(e) => {
error!(
"Attachment {} cannot be uploaded to Mastodon Instance: {}",
&local_tweet_media_path, e
);
continue;
}
};
status_medias.push(mastodon_media_ids);
// last step, removing the reference to the media from with the toots text
status_text = status_text.replace(&media.url, "");
}
}
// finished reuploading attachments, now lets do the toot baby!
debug!("Building corresponding Mastodon status"); debug!("Building corresponding Mastodon status");
@@ -157,6 +123,9 @@ pub async fn run(config: Config) {
status_builder.in_reply_to(&i); status_builder.in_reply_to(&i);
} }
// can be activated for test purposes
// status_builder.visibility(elefren::status_builder::Visibility::Private);
let status = status_builder let status = status_builder
.build() .build()
.unwrap_or_else(|_| panic!("Cannot build status with text {}", &status_text)); .unwrap_or_else(|_| panic!("Cannot build status with text {}", &status_text));

View File

@@ -35,7 +35,7 @@ pub async fn get_user_timeline(
) -> Result<Vec<Tweet>, Box<dyn Error>> { ) -> Result<Vec<Tweet>, Box<dyn Error>> {
// fix the page size to 200 as it is the maximum Twitter authorizes // fix the page size to 200 as it is the maximum Twitter authorizes
let (_, feed) = user_timeline(UserID::from(screen_name.to_owned()), true, false, token) let (_, feed) = user_timeline(UserID::from(screen_name.to_owned()), true, false, token)
.with_page_size(20) .with_page_size(200)
.older(lid) .older(lid)
.await?; .await?;

View File

@@ -1,11 +1,62 @@
use crate::ScootalooError; use crate::{twitter::get_tweet_media, ScootalooError};
use egg_mode::tweet::Tweet;
use elefren::prelude::*;
use log::{error, warn};
use reqwest::Url; use reqwest::Url;
use std::error::Error; use std::{borrow::Cow, error::Error};
use tokio::{ use tokio::{
fs::{create_dir_all, File}, fs::{create_dir_all, remove_file, File},
io::copy, io::copy,
}; };
/// Generate associative table between media ids and tweet extended entities
pub async fn generate_media_ids(
tweet: &Tweet,
cache_path: &str,
mastodon: &Mastodon,
) -> (String, Vec<String>) {
let mut media_ids: Vec<String> = vec![];
let mut media_url: String = "".to_string();
if let Some(m) = &tweet.extended_entities {
for media in &m.media {
// attribute the media url
media_url = media.url.clone();
let local_tweet_media_path = match get_tweet_media(media, cache_path).await {
Ok(m) => m,
Err(e) => {
error!("Cannot get tweet media for {}: {}", &media.url, e);
continue;
}
};
let mastodon_media_ids = match mastodon
.media(Cow::from(local_tweet_media_path.to_owned()))
{
Ok(m) => {
remove_file(&local_tweet_media_path).await.unwrap_or_else(|e|
warn!("Attachment for {} has been uploaded, but Im unable to remove the existing file: {}", &local_tweet_media_path, e));
m.id
}
Err(e) => {
error!(
"Attachment {} cannot be uploaded to Mastodon Instance: {}",
&local_tweet_media_path, e
);
// file is no longer useful, deleting
remove_file(&local_tweet_media_path).await.unwrap_or_else(|e|
warn!("Attachment for {} has been uploaded, but Im unable to remove the existing file: {}", &local_tweet_media_path, e));
continue;
}
};
media_ids.push(mastodon_media_ids);
}
}
(media_url, media_ids)
}
/// Gets and caches Twitter Media inside the determined temp dir /// Gets and caches Twitter Media inside the determined temp dir
pub async fn cache_media(u: &str, t: &str) -> Result<String, Box<dyn Error>> { pub async fn cache_media(u: &str, t: &str) -> Result<String, Box<dyn Error>> {
// create dir // create dir