Added core functionality.

This commit is contained in:
vorboyvo 2024-12-28 17:02:22 -05:00
parent ed40f2e299
commit 7a12fc4490
5 changed files with 53 additions and 35 deletions

View file

@ -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<io::Error> for FileError {
}
}
#[derive(Copy, Clone)]
pub struct LinksFile<'a>(&'a Path);
impl<'a> LinksFile<'a> {

View file

@ -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;
}
}

View file

@ -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<reqwest::Error> 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))

0
src/server.rs Normal file
View file

View file

@ -30,14 +30,14 @@ pub fn slug_from_link(link: String) -> Result<String, Error> {
}
}
pub fn title_from_slug(slug: String) -> Result<String, Error> {
pub async fn title_from_slug(slug: String) -> Result<String, Error> {
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<String, Error> {
}
}
pub fn post_body(link: String) -> Result<String, Error> {
let title = title_from_slug(slug_from_link(link.clone())?)?;
pub async fn post_body(link: String) -> Result<String, Error> {
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";