Made it functional, adding a bunch of blocking api stuff. A while ago so idk really.

This commit is contained in:
vorboyvo 2025-11-12 15:10:38 -05:00
parent 71da65576b
commit acec764eac
4 changed files with 44 additions and 28 deletions

View file

@ -36,13 +36,13 @@ impl<'a> LinksFile<'a> {
let file_contents = read_to_string(self.0)?; let file_contents = read_to_string(self.0)?;
let mut file_lines = file_contents.split("\n"); let mut file_lines = file_contents.split("\n");
let mut line = file_lines.next(); let mut line = file_lines.next();
// run through all empty lines
while let Some("") = line { while let Some("") = line {
line = file_lines.next(); line = file_lines.next();
}; };
let line_clean = match line { let line_clean = match line {
Some("") => return Err(FileError::EmptyLine),
Some(a) => a, Some(a) => a,
None => panic!("Iterator returns None, something wrong happened") None => return Err(FileError::EmptyLine)
}; };
let rest_of_file = file_lines let rest_of_file = file_lines
.collect::<Vec<&str>>() .collect::<Vec<&str>>()

View file

@ -1,5 +1,5 @@
use std::path::Path; use std::path::Path;
use tokio::{spawn}; use tokio::{spawn, task::spawn_blocking};
use tokio_cron_scheduler::{Job, JobScheduler}; use tokio_cron_scheduler::{Job, JobScheduler};
mod file; mod file;
@ -24,35 +24,33 @@ async fn post_link_from_file(queue: LinksFile<'_>, backup: LinksFile<'_>, mastod
// convert said link into a post status // convert said link into a post status
let post_status = post_body(link_to_post).await.unwrap(); let post_status = post_body(link_to_post).await.unwrap();
// post it on mastodon // post it on mastodon
mastodon.post_text_status(post_status, Visibility::Public).await.unwrap(); spawn_blocking(
move || {
mastodon.post_text_status(post_status, Visibility::Public).unwrap();
}
);
} }
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
dotenv::dotenv().ok(); dotenv::dotenv().ok();
// let app_code = std::env::var("APP_CODE").expect("APP_CODE required."); // 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 dwh_app_token = std::env::var("DWH_APP_TOKEN").expect("DWH_APP_TOKEN required.");
let app_instance = std::env::var("APP_INSTANCE").expect("APP_INSTANCE required."); let dwh_app_instance = std::env::var("DWH_APP_INSTANCE").expect("DWH_APP_INSTANCE required.");
let dwh_cron_schedule = std::env::var("DWH_CRON_SCHEDULE").expect("DWH_CRON_SCHEDULE required.");
let sched = JobScheduler::new().await.unwrap(); let sched = JobScheduler::new().await.unwrap();
sched.add( sched.add(
Job::new_async("0 0 8 * * *", move |_uuid, _l| { Job::new_async(dwh_cron_schedule, move |_uuid, _l| {
Box::pin({ Box::pin({
let app_instance_cloned = app_instance.clone(); let app_instance_cloned = dwh_app_instance.clone();
let app_token_cloned = app_token.clone(); let app_token_cloned = dwh_app_token.clone();
async move { async move {
let queue = LinksFile::new(Path::new("queue.txt")); let queue = LinksFile::new(Path::new("queue.txt"));
let backup = LinksFile::new(Path::new("backup.txt")); let backup = LinksFile::new(Path::new("backup.txt"));
let mastodon = Mastodon::new(app_instance_cloned, app_token_cloned); let mastodon = Mastodon::new(app_instance_cloned, app_token_cloned);
post_link_from_file(queue, backup, mastodon.clone()).await;
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;
};
} }
}) })
}).unwrap() }).unwrap()

View file

@ -1,4 +1,4 @@
use reqwest::{multipart, StatusCode}; use reqwest::{blocking::{Client, multipart}, StatusCode};
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
@ -34,24 +34,31 @@ impl Visibility {
#[derive(Clone)] #[derive(Clone)]
pub struct Mastodon { pub struct Mastodon {
instance: String, instance: String,
token: String token: String,
} }
impl Mastodon { impl Mastodon {
pub fn new(instance: String, token: String) -> Self { pub fn new(instance: String, token: String) -> Self {
Mastodon { instance, token } Mastodon {
instance,
token,
}
} }
pub async fn post_text_status(&self, status: String, visibility: Visibility) -> Result<(), Error> { pub fn post_text_status(&self, status: String, visibility: Visibility) -> Result<(), Error> {
let form = multipart::Form::new() let form = multipart::Form::new()
.text("status", status) .text("status", status)
.text("visibility", visibility.enum_name()); .text("visibility", visibility.enum_name());
let client = reqwest::Client::new(); let client = reqwest::blocking::Client::builder()
let response = client .danger_accept_invalid_certs(true)
.build()
.expect("");
let response = client
.post(format!("{}/api/v1/statuses", self.instance)) .post(format!("{}/api/v1/statuses", self.instance))
.header("Authorization", format!("Bearer {}", self.token)) .header("Authorization", format!("Bearer {}", self.token))
.multipart(form) .multipart(form)
.send().await?; .send()?;
match response.status() { match response.status() {
StatusCode::OK => Ok(()), StatusCode::OK => Ok(()),
s => Err(Error::FailureStatus(s)) s => Err(Error::FailureStatus(s))

View file

@ -1,4 +1,7 @@
use regex::Regex; use regex::Regex;
use tokio::task::spawn_blocking;
static APP_USER_AGENT: &str = r"DailyWikiHuman/0.0 (https://en.wikipedia.org/wiki/User:WittyWidi) generic-library/0.0";
#[derive(Debug)] #[derive(Debug)]
pub enum Error{ pub enum Error{
@ -30,14 +33,19 @@ pub fn slug_from_link(link: String) -> Result<String, Error> {
} }
} }
pub async fn title_from_slug(slug: String) -> Result<String, Error> { pub fn title_from_slug(slug: String) -> Result<String, Error> {
let escaped_slug = slug.replace("/", "%2F"); let escaped_slug = slug.replace("/", "%2F");
let client = reqwest::blocking::Client::builder()
.user_agent(APP_USER_AGENT)
.build()
.expect("");
let request_url = let request_url =
format!( format!(
"https://api.wikimedia.org/core/v1/wikipedia/en/page/{escaped_slug}/bare" "https://api.wikimedia.org/core/v1/wikipedia/en/page/{escaped_slug}/bare"
); );
let response = reqwest::get(request_url).await?; let response = client.get(request_url).send()?;
let json_body = response.text().await?; let json_body = response.text()?;
println!("{:?}", json_body);
let body = json::parse(&json_body)?; let body = json::parse(&json_body)?;
match body["title"].as_str() { match body["title"].as_str() {
Some(x) => Ok(x.to_owned()), Some(x) => Ok(x.to_owned()),
@ -46,7 +54,10 @@ pub async fn title_from_slug(slug: String) -> Result<String, Error> {
} }
pub async fn post_body(link: String) -> Result<String, Error> { pub async fn post_body(link: String) -> Result<String, Error> {
let title = title_from_slug(slug_from_link(link.clone())?).await?; let link_copy = link.clone();
let title = spawn_blocking(
move || {title_from_slug(slug_from_link(link_copy)?)}
).await.expect("failed with JoinError")?;
Ok(format!("Today's wikipedia article is {title}\n\n\ Ok(format!("Today's wikipedia article is {title}\n\n\
{link}\n\n\ {link}\n\n\
#wikipedia").to_owned()) #wikipedia").to_owned())