diff --git a/src/file.rs b/src/file.rs index fe2af7c..7cac267 100644 --- a/src/file.rs +++ b/src/file.rs @@ -1,6 +1,5 @@ -use std::fs::{read_to_string, write, File}; +use std::fs::{read_to_string, write}; use std::io; -use std::io::{Read, Write}; use std::path::Path; #[derive(Debug)] @@ -15,6 +14,7 @@ impl From for FileError { } } +#[derive(Copy, Clone)] pub struct LinksFile<'a>(&'a Path); impl<'a> LinksFile<'a> { diff --git a/src/main.rs b/src/main.rs index 9b6f27b..417b9f4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,23 +1,15 @@ use std::path::Path; -use file::{FileError, LinksFile}; -use mastodon::Mastodon; - mod file; mod wikipedia; mod mastodon; +mod server; -fn main() { - dotenv::dotenv().ok(); - let app_code = std::env::var("APP_CODE").expect("APP_CODE required."); - let app_token = std::env::var("APP_TOKEN").expect("APP_TOKEN required."); - let app_instance = std::env::var("APP_INSTANCE").expect("APP_INSTANCE required."); - - let queue = LinksFile::new(Path::new("queue.txt")); - let backup = LinksFile::new(Path::new("backup.txt")); - - let mastodon = Mastodon::new(app_instance, app_token); +use file::{FileError, LinksFile}; +use mastodon::{Mastodon, Visibility}; +use wikipedia::post_body; +async fn post_link_from_file(queue: LinksFile<'_>, backup: LinksFile<'_>, mastodon: Mastodon) { // get link to post let link_to_post = match queue.remove_first_line() { Ok(a) => a, @@ -27,5 +19,29 @@ fn main() { }, Err(d) => panic!("{d:?}") }; - println!("{link_to_post}") + // convert said link into a post status + let post_status = post_body(link_to_post).await.unwrap(); + // post it on mastodon + mastodon.post_text_status(post_status, Visibility::Direct).await.unwrap(); +} + +#[tokio::main] +async fn main() { + dotenv::dotenv().ok(); + // let app_code = std::env::var("APP_CODE").expect("APP_CODE required."); + let app_token = std::env::var("APP_TOKEN").expect("APP_TOKEN required."); + let app_instance = std::env::var("APP_INSTANCE").expect("APP_INSTANCE required."); + + let queue = LinksFile::new(Path::new("queue.txt")); + let backup = LinksFile::new(Path::new("backup.txt")); + let mastodon = Mastodon::new(app_instance, app_token); + + let mut interval_timer = tokio::time::interval( + chrono::Duration::minutes(10).to_std().unwrap() + ); + + loop { + interval_timer.tick().await; + post_link_from_file(queue, backup, mastodon.clone()).await; + } } diff --git a/src/mastodon.rs b/src/mastodon.rs index 9566a78..6dc4042 100644 --- a/src/mastodon.rs +++ b/src/mastodon.rs @@ -1,5 +1,6 @@ -use reqwest::{blocking::multipart, StatusCode}; +use reqwest::{multipart, StatusCode}; +#[derive(Debug)] pub enum Error { ReqwestError(reqwest::Error), FailureStatus(reqwest::StatusCode) @@ -12,7 +13,7 @@ impl From for Error { } #[derive(Copy, Clone)] -enum Visibility { +pub enum Visibility { Public, Unlisted, Private, @@ -30,6 +31,7 @@ impl Visibility { } } +#[derive(Clone)] pub struct Mastodon { instance: String, token: String @@ -40,16 +42,16 @@ impl Mastodon { Mastodon { instance, token } } - pub fn post_text_status(&self, status: String, visibility: Visibility) -> Result<(), Error> { + pub async fn post_text_status(&self, status: String, visibility: Visibility) -> Result<(), Error> { let form = multipart::Form::new() .text("status", status) .text("visibility", visibility.enum_name()); - let client = reqwest::blocking::Client::new(); + let client = reqwest::Client::new(); let response = client .post(format!("{}/api/v1/statuses", self.instance)) .header("Authorization", format!("Bearer {}", self.token)) .multipart(form) - .send()?; + .send().await?; match response.status() { StatusCode::OK => Ok(()), s => Err(Error::FailureStatus(s)) diff --git a/src/server.rs b/src/server.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/wikipedia.rs b/src/wikipedia.rs index 7487a83..14dd1aa 100644 --- a/src/wikipedia.rs +++ b/src/wikipedia.rs @@ -30,14 +30,14 @@ pub fn slug_from_link(link: String) -> Result { } } -pub fn title_from_slug(slug: String) -> Result { +pub async fn title_from_slug(slug: String) -> Result { let escaped_slug = slug.replace("/", "%2F"); let request_url = format!( "https://api.wikimedia.org/core/v1/wikipedia/en/page/{escaped_slug}/bare" ); - let response = reqwest::blocking::get(request_url)?; - let json_body = response.text()?; + let response = reqwest::get(request_url).await?; + let json_body = response.text().await?; let body = json::parse(&json_body)?; match body["title"].as_str() { Some(x) => Ok(x.to_string()), @@ -45,8 +45,8 @@ pub fn title_from_slug(slug: String) -> Result { } } -pub fn post_body(link: String) -> Result { - let title = title_from_slug(slug_from_link(link.clone())?)?; +pub async fn post_body(link: String) -> Result { + let title = title_from_slug(slug_from_link(link.clone())?).await?; Ok(format!("Today's wikipedia article is {title}\n\n\ {link}\n\n\ #wikipedia").to_string()) @@ -66,19 +66,19 @@ mod tests { assert_eq!(slug_from_link("https://en.wikipedia.org/wiki/GNU/Linux_naming_controversy".to_string()).unwrap().as_str(), "GNU/Linux_naming_controversy") } - #[test] - fn test_title_from_slug_1() { - assert_eq!(title_from_slug("Buck-a-beer".to_string()).unwrap().as_str(), "Buck-a-beer") + #[tokio::test] + async fn test_title_from_slug_1() { + assert_eq!(title_from_slug("Buck-a-beer".to_string()).await.unwrap().as_str(), "Buck-a-beer") } - #[test] - fn test_title_from_slug_2() { - assert_eq!(title_from_slug("GNU/Linux_naming_controversy".to_string()).unwrap().as_str(), "GNU/Linux naming controversy") + #[tokio::test] + async fn test_title_from_slug_2() { + assert_eq!(title_from_slug("GNU/Linux_naming_controversy".to_string()).await.unwrap().as_str(), "GNU/Linux naming controversy") } - #[test] - fn test_post_body_1() { - let body = post_body("https://en.wikipedia.org/wiki/GNU%2FLinux_naming_controversy".to_string()).unwrap(); + #[tokio::test] + async fn test_post_body_1() { + let body = post_body("https://en.wikipedia.org/wiki/GNU%2FLinux_naming_controversy".to_string()).await.unwrap(); let expected = "Today's wikipedia article is GNU/Linux naming controversy\n\n\ https://en.wikipedia.org/wiki/GNU%2FLinux_naming_controversy\n\n\ #wikipedia";