diff --git a/Cargo.lock b/Cargo.lock index 3924ec5..5344a3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -880,10 +880,13 @@ dependencies = [ ] [[package]] -name = "htmlescape" -version = "0.3.1" +name = "html-escape" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" +checksum = "b8e7479fa1ef38eb49fb6a42c426be515df2d063f06cb8efd3e50af073dbc26c" +dependencies = [ + "utf8-width", +] [[package]] name = "http" @@ -2015,11 +2018,12 @@ dependencies = [ name = "scootaloo" version = "0.5.0" dependencies = [ + "chrono", "clap", "egg-mode", "elefren", "futures 0.3.14", - "htmlescape", + "html-escape", "log", "reqwest 0.11.3", "rusqlite", @@ -2744,6 +2748,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8-width" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" + [[package]] name = "uuid" version = "0.7.4" diff --git a/Cargo.toml b/Cargo.toml index 2aefd55..4de7cf6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +chrono = "^0.4" serde = { version = "1.0", features = ["derive"] } toml = "^0.5" clap = "^2.34" @@ -15,7 +16,7 @@ egg-mode = "^0.16" rusqlite = "^0.27" tokio = { version = "1", features = ["full"]} elefren = "^0.22" -htmlescape = "^0.3" +html-escape = "^0.2" reqwest = "^0.11" log = "^0.4" simple_logger = "^2.1" diff --git a/src/lib.rs b/src/lib.rs index 49f454c..4d98a9a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,13 +82,7 @@ pub async fn run(config: Config) { }; // build basic status by just yielding text and dereferencing contained urls - let mut status_text = match build_basic_status(tweet) { - Ok(t) => t, - Err(e) => { - error!("Could not create status from tweet {}: {}", tweet.id ,e); - continue; - }, - }; + let mut status_text = build_basic_status(tweet); let mut status_medias: Vec = vec![]; // reupload the attachments if any diff --git a/src/mastodon.rs b/src/mastodon.rs index ec079c3..5033728 100644 --- a/src/mastodon.rs +++ b/src/mastodon.rs @@ -2,11 +2,10 @@ use crate::config::MastodonConfig; use std::{ borrow::Cow, - error::Error, collections::HashMap, io::stdin, }; -use htmlescape::decode_html; +use html_escape::decode_html_entities; use egg_mode::{ tweet::Tweet, entities::{UrlEntity, MentionEntity}, @@ -48,24 +47,18 @@ pub fn get_mastodon_token(masto: &MastodonConfig) -> Mastodon { } /// Builds toot text from tweet -pub fn build_basic_status(tweet: &Tweet) -> Result> { +pub fn build_basic_status(tweet: &Tweet) -> String { let mut toot = String::from(&tweet.text); - let decoded_urls = decode_urls(&tweet.entities.urls); - for decoded_url in decoded_urls { + for decoded_url in decode_urls(&tweet.entities.urls) { toot = toot.replace(&decoded_url.0, &decoded_url.1); } - let decoded_mentions = twitter_mentions(&tweet.entities.user_mentions); - for decoded_mention in decoded_mentions { + for decoded_mention in twitter_mentions(&tweet.entities.user_mentions) { toot = toot.replace(&decoded_mention.0, &decoded_mention.1); } - if let Ok(t) = decode_html(&toot) { - toot = t; - } - - Ok(toot) + decode_html_entities(&toot).to_string() } /// Generic register function @@ -101,6 +94,9 @@ pub fn register(host: &str) { mod tests { use super::*; + use egg_mode::tweet::TweetEntities; + use chrono::prelude::*; + #[test] fn test_twitter_mentions() { let mention_entity = MentionEntity { @@ -145,5 +141,63 @@ mod tests { assert_eq!(expected_urls, decoded_urls); } + + #[test] + fn test_build_basic_status() { + let t = Tweet { + coordinates: None, + created_at: Utc::now(), + current_user_retweet: None, + display_text_range: None, + entities: TweetEntities { + hashtags: vec![], + symbols: vec![], + urls: vec![ + UrlEntity { + display_url: "youtube.com/watch?v=w5TrSa…".to_string(), + expanded_url: Some("https://www.youtube.com/watch?v=w5TrSaoYmZ8".to_string()), + range: (93, 116), + url: "https://t.co/zXw0FfX2Nt".to_string(), + } + ], + user_mentions: vec![ + MentionEntity { + id: 491500016, + range: (80, 95), + name: "Nintendo France".to_string(), + screen_name: "NintendoFrance".to_string(), + } + ], + media: None, + }, + extended_entities: None, + favorite_count: 0, + favorited: None, + filter_level: None, + id: 1491541246984306693, + in_reply_to_user_id: None, + in_reply_to_screen_name: None, + in_reply_to_status_id: None, + lang: None, + place: None, + possibly_sensitive: None, + quoted_status: None, + quoted_status_id: None, + retweet_count: 0, + retweeted: None, + retweeted_status: None, + source: None, + text: "Mother 1 & 2 sur le NES/SNES online !\nDispo maintenant. cc @NintendoFrance https://t.co/zXw0FfX2Nt".to_string(), + truncated: false, + user: None, + withheld_copyright: false, + withheld_in_countries: None, + withheld_scope: None, + }; + + let t_out = build_basic_status(&t); + + assert_eq!(&t_out, "Mother 1 & 2 sur le NES/SNES online !\nDispo maintenant. cc @NintendoFrance@twitter.com https://www.youtube.com/watch?v=w5TrSaoYmZ8"); + } }