Files
scootaloo/src/twitter.rs
2022-11-03 23:30:50 +01:00

188 lines
6.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use crate::config::MastodonConfig;
use crate::config::TwitterConfig;
use crate::util::cache_media;
use crate::ScootalooError;
use egg_mode::{
entities::{MediaEntity, MediaType},
tweet::{user_timeline, Tweet},
user::UserID,
KeyPair, Token,
};
use std::error::Error;
/// Gets Twitter oauth2 token
pub fn get_oauth2_token(config: &TwitterConfig) -> Token {
let con_token = KeyPair::new(
config.consumer_key.to_owned(),
config.consumer_secret.to_owned(),
);
let access_token = KeyPair::new(
config.access_key.to_owned(),
config.access_secret.to_owned(),
);
Token::Access {
consumer: con_token,
access: access_token,
}
}
/// Gets Twitter user timeline
pub async fn get_user_timeline(
config: &MastodonConfig,
token: &Token,
lid: Option<u64>,
) -> Result<Vec<Tweet>, Box<dyn Error>> {
// fix the page size to 200 as it is the maximum Twitter authorizes
let (_, feed) = user_timeline(
UserID::from(config.twitter_screen_name.to_owned()),
true,
false,
token,
)
.with_page_size(200)
.older(lid)
.await?;
Ok(feed.to_vec())
}
/// Retrieves a single media from a tweet and store it in a temporary file
pub async fn get_tweet_media(m: &MediaEntity, t: &str) -> Result<String, Box<dyn Error>> {
match m.media_type {
MediaType::Photo => cache_media(&m.media_url_https, t).await,
_ => match &m.video_info {
Some(v) => match &v.variants.iter().find(|&x| x.content_type == "video/mp4") {
Some(u) => cache_media(&u.url, t).await,
None => Err(ScootalooError::new(&format!(
"Media Type for {} is video but no mp4 file URL is available",
&m.url
))
.into()),
},
None => Err(ScootalooError::new(&format!(
"Media Type for {} is video but does not contain any video_info",
&m.url
))
.into()),
},
}
}
#[cfg(test)]
mod tests {
use super::*;
use egg_mode::entities::{
MediaSize, MediaSizes,
MediaType::{Gif, Photo},
ResizeMode::Crop,
ResizeMode::Fit,
VideoInfo, VideoVariant,
};
use std::fs::remove_dir_all;
const TMP_DIR: &'static str = "/tmp/scootaloo_get_tweet_media_test";
#[tokio::test]
async fn test_get_tweet_media() {
let m_photo = MediaEntity {
display_url: "pic.twitter.com/sHrwmP69Yv".to_string(),
expanded_url: "https://twitter.com/NintendojoFR/status/1555473821121056771/photo/1"
.to_string(),
id: 1555473771280080896,
range: (91, 114),
media_url: "http://pbs.twimg.com/media/FZYnJ1qWIAAReHt.jpg".to_string(),
media_url_https: "https://pbs.twimg.com/media/FZYnJ1qWIAAReHt.jpg"
.to_string(),
sizes: MediaSizes {
thumb: MediaSize {
w: 150,
h: 150,
resize: Crop
},
small: MediaSize {
w: 680,
h: 510,
resize: Fit
},
medium: MediaSize {
w: 1200,
h: 900,
resize: Fit
},
large: MediaSize {
w: 1280,
h: 960,
resize: Fit
}
},
source_status_id: None,
media_type: Photo,
url: "https://t.co/sHrwmP69Yv".to_string(),
video_info: None,
ext_alt_text: Some("Le menu «\u{a0}Classes » du jeu vidéo Xenoblade Chronicles 3 (Switch). Laffinité du personnage pour la classe est notée par quatre lettres : C, A, C, A (caca)."
.to_string())
};
let m_video = MediaEntity {
display_url: "pic.twitter.com/xDln0RrkjU".to_string(),
expanded_url: "https://twitter.com/NintendojoFR/status/1551822196833673218/photo/1"
.to_string(),
id: 1551822189711790081,
range: (275, 298),
media_url: "http://pbs.twimg.com/tweet_video_thumb/FYkuD0RXEAE-iDx.jpg".to_string(),
media_url_https: "https://pbs.twimg.com/tweet_video_thumb/FYkuD0RXEAE-iDx.jpg"
.to_string(),
sizes: MediaSizes {
thumb: MediaSize {
w: 150,
h: 150,
resize: Crop,
},
small: MediaSize {
w: 320,
h: 240,
resize: Fit,
},
medium: MediaSize {
w: 320,
h: 240,
resize: Fit,
},
large: MediaSize {
w: 320,
h: 240,
resize: Fit,
},
},
source_status_id: None,
media_type: Gif,
url: "https://t.co/xDln0RrkjU".to_string(),
video_info: Some(VideoInfo {
aspect_ratio: (4, 3),
duration_millis: None,
variants: vec![VideoVariant {
bitrate: Some(0),
content_type: "video/mp4".parse::<mime::Mime>().unwrap(),
url: "https://video.twimg.com/tweet_video/FYkuD0RXEAE-iDx.mp4".to_string(),
}],
}),
ext_alt_text: Some("Scared Nintendo GIF".to_string()),
};
let tweet_media_photo = get_tweet_media(&m_photo, TMP_DIR).await.unwrap();
let tweet_media_video = get_tweet_media(&m_video, TMP_DIR).await.unwrap();
assert_eq!(
tweet_media_photo,
format!("{}/FZYnJ1qWIAAReHt.jpg", TMP_DIR)
);
assert_eq!(
tweet_media_video,
format!("{}/FYkuD0RXEAE-iDx.mp4", TMP_DIR)
);
remove_dir_all(TMP_DIR).unwrap();
}
}