8 Commits

Author SHA1 Message Date
VC
5fe57f189a Merge branch 'feat_wait_for_upload' into 'master'
Feat wait for upload

See merge request veretcle/scootaloo!54
2023-02-09 14:51:14 +00:00
VC
83c398cebf feat: wait 1 full sec between loop when uploading big media 2023-02-09 15:19:22 +01:00
VC
8f567ed6b4 chore: bump version 2023-02-09 15:18:12 +01:00
VC
d7431862ba Merge branch 'fix_copy_lang' into 'master'
Fix copy lang

See merge request veretcle/scootaloo!53
2023-02-09 14:12:25 +00:00
VC
f3b13eb62f refactor: conforms to clippy 1.67 recommandations 2023-02-09 11:32:22 +01:00
VC
6b68c8e299 fix: no need for defaults with clap v4 2023-02-09 11:31:58 +01:00
VC
0bb5eabdac fix: copy the original lang from Twitter to Mastodon 2023-02-09 10:58:34 +01:00
VC
3d44bbfb86 refactor: remove isolang, bump version 2023-02-09 10:58:12 +01:00
9 changed files with 27 additions and 69 deletions

36
Cargo.lock generated
View File

@@ -776,15 +776,6 @@ dependencies = [
"windows-sys 0.42.0", "windows-sys 0.42.0",
] ]
[[package]]
name = "isolang"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b64fd6448ee8a45ce6e4365c58e4fa7d8740cba2ed70db3e9ab4879ebd93eaaa"
dependencies = [
"phf",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.5" version = "1.0.5"
@@ -1082,24 +1073,6 @@ version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "phf"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_shared"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
dependencies = [
"siphasher",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.9" version = "0.2.9"
@@ -1343,14 +1316,13 @@ dependencies = [
[[package]] [[package]]
name = "scootaloo" name = "scootaloo"
version = "1.1.4" version = "1.1.6"
dependencies = [ dependencies = [
"base64", "base64",
"clap", "clap",
"egg-mode", "egg-mode",
"futures", "futures",
"html-escape", "html-escape",
"isolang",
"log", "log",
"megalodon", "megalodon",
"mime", "mime",
@@ -1523,12 +1495,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "siphasher"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.7" version = "0.4.7"

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "scootaloo" name = "scootaloo"
version = "1.1.4" version = "1.1.6"
authors = ["VC <veretcle+framagit@mateu.be>"] authors = ["VC <veretcle+framagit@mateu.be>"]
edition = "2021" edition = "2021"
@@ -14,7 +14,6 @@ toml = "^0.5"
clap = "^4" clap = "^4"
egg-mode = "^0.16" egg-mode = "^0.16"
rusqlite = "^0.27" rusqlite = "^0.27"
isolang = "^2"
tokio = { version = "^1", features = ["rt"]} tokio = { version = "^1", features = ["rt"]}
futures = "^0.3" futures = "^0.3"
megalodon = "^0.3.6" megalodon = "^0.3.6"

View File

@@ -43,10 +43,10 @@ pub struct ScootalooConfig {
/// Parses the TOML file into a Config Struct /// Parses the TOML file into a Config Struct
pub fn parse_toml(toml_file: &str) -> Config { pub fn parse_toml(toml_file: &str) -> Config {
let toml_config = read_to_string(toml_file) let toml_config = read_to_string(toml_file)
.unwrap_or_else(|e| panic!("Cannot open config file {}: {}", toml_file, e)); .unwrap_or_else(|e| panic!("Cannot open config file {toml_file}: {e}"));
let config: Config = toml::from_str(&toml_config) let config: Config = toml::from_str(&toml_config)
.unwrap_or_else(|e| panic!("Cannot parse TOML file {}: {}", toml_file, e)); .unwrap_or_else(|e| panic!("Cannot parse TOML file {toml_file}: {e}"));
config config
} }

View File

@@ -30,12 +30,12 @@ impl Display for ScootalooError {
impl From<Box<dyn Error>> for ScootalooError { impl From<Box<dyn Error>> for ScootalooError {
fn from(error: Box<dyn Error>) -> Self { fn from(error: Box<dyn Error>) -> Self {
ScootalooError::new(&format!("Error in a subset crate: {}", error)) ScootalooError::new(&format!("Error in a subset crate: {error}"))
} }
} }
impl From<megalodonError> for ScootalooError { impl From<megalodonError> for ScootalooError {
fn from(error: megalodonError) -> Self { fn from(error: megalodonError) -> Self {
ScootalooError::new(&format!("Error in megalodon crate: {}", error)) ScootalooError::new(&format!("Error in megalodon crate: {error}"))
} }
} }

View File

@@ -21,7 +21,6 @@ use state::{read_state, write_state, TweetToToot};
use futures::StreamExt; use futures::StreamExt;
use html_escape::decode_html_entities; use html_escape::decode_html_entities;
use isolang::Language;
use log::info; use log::info;
use megalodon::{ use megalodon::{
megalodon::PostStatusInputOptions, megalodon::UpdateCredentialsInputOptions, Megalodon, megalodon::PostStatusInputOptions, megalodon::UpdateCredentialsInputOptions, Megalodon,
@@ -204,9 +203,7 @@ pub async fn run(config: Config) {
// language if any // language if any
if let Some(l) = &tweet.lang { if let Some(l) = &tweet.lang {
if let Some(r) = Language::from_639_1(l) { post_status.language = Some(l.to_string());
post_status.language = Some(r.to_string());
}
} }
// can be activated for test purposes // can be activated for test purposes
@@ -238,8 +235,8 @@ pub async fn run(config: Config) {
// launch and wait for every handle // launch and wait for every handle
while let Some(result) = stream.next().await { while let Some(result) = stream.next().await {
match result { match result {
Ok(Err(e)) => eprintln!("Error within thread: {}", e), Ok(Err(e)) => eprintln!("Error within thread: {e}"),
Err(e) => eprintln!("Error with thread: {}", e), Err(e) => eprintln!("Error with thread: {e}"),
_ => (), _ => (),
} }
} }
@@ -307,8 +304,8 @@ pub async fn profile(config: Config, bot: Option<bool>) {
while let Some(result) = stream.next().await { while let Some(result) = stream.next().await {
match result { match result {
Ok(Err(e)) => eprintln!("Error within thread: {}", e), Ok(Err(e)) => eprintln!("Error within thread: {e}"),
Err(e) => eprintln!("Error with thread: {}", e), Err(e) => eprintln!("Error with thread: {e}"),
_ => (), _ => (),
} }
} }

View File

@@ -63,10 +63,7 @@ fn main() {
.short('c') .short('c')
.long("config") .long("config")
.value_name("CONFIG_FILE") .value_name("CONFIG_FILE")
.help(format!( .help("TOML config file for scootaloo")
"TOML config file for scootaloo (default {})",
DEFAULT_CONFIG_PATH
))
.default_value(DEFAULT_CONFIG_PATH) .default_value(DEFAULT_CONFIG_PATH)
.num_args(1) .num_args(1)
.display_order(1), .display_order(1),
@@ -81,7 +78,7 @@ fn main() {
.short('c') .short('c')
.long("config") .long("config")
.value_name("CONFIG_FILE") .value_name("CONFIG_FILE")
.help(format!("TOML config file for scootaloo (default {})", DEFAULT_CONFIG_PATH)) .help("TOML config file for scootaloo")
.default_value(DEFAULT_CONFIG_PATH) .default_value(DEFAULT_CONFIG_PATH)
.num_args(1) .num_args(1)
.display_order(1), .display_order(1),
@@ -104,7 +101,7 @@ fn main() {
.short('c') .short('c')
.long("config") .long("config")
.value_name("CONFIG_FILE") .value_name("CONFIG_FILE")
.help(format!("TOML config file for scootaloo (default {})", DEFAULT_CONFIG_PATH)) .help("TOML config file for scootaloo")
.default_value(DEFAULT_CONFIG_PATH) .default_value(DEFAULT_CONFIG_PATH)
.num_args(1) .num_args(1)
.display_order(1), .display_order(1),

View File

@@ -83,7 +83,7 @@ pub fn associate_urls(urls: &[UrlEntity], re: &Option<Regex>) -> HashMap<String,
pub fn replace_alt_services(urls: &mut HashMap<String, String>, alts: &HashMap<String, String>) { pub fn replace_alt_services(urls: &mut HashMap<String, String>, alts: &HashMap<String, String>) {
for val in urls.values_mut() { for val in urls.values_mut() {
for (k, v) in alts { for (k, v) in alts {
*val = val.replace(&format!("/{}/", k), &format!("/{}/", v)); *val = val.replace(&format!("/{k}/"), &format!("/{v}/"));
} }
} }
} }
@@ -120,7 +120,7 @@ pub fn replace_tweet_by_toot(
twitter_screen_name.to_lowercase(), twitter_screen_name.to_lowercase(),
tweet_id tweet_id
)) { )) {
*val = format!("{}/@{}/{}", base_url, mastodon_screen_name, toot_id); *val = format!("{base_url}/@{mastodon_screen_name}/{toot_id}");
} }
} }
} }
@@ -184,7 +184,7 @@ pub async fn register(host: &str, screen_name: &str) {
let url = app_data.url.expect("Cannot generate registration URI!"); let url = app_data.url.expect("Cannot generate registration URI!");
println!("Click this link to authorize on Mastodon: {}", url); println!("Click this link to authorize on Mastodon: {url}");
println!("Paste the returned authorization code: "); println!("Paste the returned authorization code: ");
let mut input = String::new(); let mut input = String::new();

View File

@@ -21,8 +21,8 @@ pub fn read_state(
) -> Result<Option<TweetToToot>, Box<dyn Error>> { ) -> Result<Option<TweetToToot>, Box<dyn Error>> {
debug!("Reading tweet_id {:?}", s); debug!("Reading tweet_id {:?}", s);
let query: String = match s { let query: String = match s {
Some(i) => format!("SELECT * FROM tweet_to_toot WHERE tweet_id = {} and twitter_screen_name = \"{}\"", i, n), Some(i) => format!("SELECT * FROM tweet_to_toot WHERE tweet_id = {i} and twitter_screen_name = \"{n}\""),
None => format!("SELECT * FROM tweet_to_toot WHERE twitter_screen_name = \"{}\" ORDER BY tweet_id DESC LIMIT 1", n), None => format!("SELECT * FROM tweet_to_toot WHERE twitter_screen_name = \"{n}\" ORDER BY tweet_id DESC LIMIT 1"),
}; };
let mut stmt = conn.prepare(&query)?; let mut stmt = conn.prepare(&query)?;
@@ -78,8 +78,7 @@ pub fn migrate_db(d: &str, s: &str) -> Result<(), Box<dyn Error>> {
&format!( &format!(
"ALTER TABLE tweet_to_toot "ALTER TABLE tweet_to_toot
ADD COLUMN twitter_screen_name TEXT NOT NULL ADD COLUMN twitter_screen_name TEXT NOT NULL
DEFAULT \"{}\"", DEFAULT \"{s}\""
s
), ),
[], [],
); );

View File

@@ -15,6 +15,7 @@ use std::error::Error;
use tokio::{ use tokio::{
fs::{create_dir_all, remove_file, File}, fs::{create_dir_all, remove_file, File},
io::copy, io::copy,
time::{sleep, Duration},
}; };
/// Generate associative table between media ids and tweet extended entities /// Generate associative table between media ids and tweet extended entities
@@ -85,6 +86,7 @@ pub async fn generate_media_ids(
/// Wait on uploaded medias when necessary /// Wait on uploaded medias when necessary
async fn wait_until_uploaded(client: &Mastodon, id: &str) -> Result<String, error::Error> { async fn wait_until_uploaded(client: &Mastodon, id: &str) -> Result<String, error::Error> {
loop { loop {
sleep(Duration::from_secs(1)).await;
let res = client.get_media(id.to_string()).await; let res = client.get_media(id.to_string()).await;
return match res { return match res {
Ok(res) => Ok(res.json.id), Ok(res) => Ok(res.json.id),
@@ -112,12 +114,12 @@ pub async fn base64_media(u: &str) -> Result<String, Box<dyn Error>> {
let content_type = response let content_type = response
.headers() .headers()
.get("content-type") .get("content-type")
.ok_or_else(|| ScootalooError::new(&format!("Cannot get media content type for {}", u)))? .ok_or_else(|| ScootalooError::new(&format!("Cannot get media content type for {u}")))?
.to_str()?; .to_str()?;
let encoded_f = encode(buffer); let encoded_f = encode(buffer);
Ok(format!("data:{};base64,{}", content_type, encoded_f)) Ok(format!("data:{content_type};base64,{encoded_f}"))
} }
/// Gets and caches Twitter Media inside the determined temp dir /// Gets and caches Twitter Media inside the determined temp dir
@@ -134,19 +136,17 @@ pub async fn cache_media(u: &str, t: &str) -> Result<String, Box<dyn Error>> {
.path_segments() .path_segments()
.ok_or_else(|| { .ok_or_else(|| {
ScootalooError::new(&format!( ScootalooError::new(&format!(
"Cannot determine the destination filename for {}", "Cannot determine the destination filename for {u}"
u
)) ))
})? })?
.last() .last()
.ok_or_else(|| { .ok_or_else(|| {
ScootalooError::new(&format!( ScootalooError::new(&format!(
"Cannot determine the destination filename for {}", "Cannot determine the destination filename for {u}"
u
)) ))
})?; })?;
let dest_filepath = format!("{}/{}", t, dest_filename); let dest_filepath = format!("{t}/{dest_filename}");
let mut dest_file = File::create(&dest_filepath).await?; let mut dest_file = File::create(&dest_filepath).await?;