Utilize cascading errors instead of bools

This commit is contained in:
Neshura 2023-07-31 19:50:22 +02:00
parent d31f291e26
commit 210ca895db
Signed by: Neshura
GPG key ID: B6983AAA6B9A7A6C
2 changed files with 51 additions and 42 deletions

View file

@ -98,15 +98,15 @@ impl Config {
} }
pub(crate) fn check_feeds(&mut self, post_history: &mut Vec<PrevPost> pub(crate) fn check_feeds(&mut self, post_history: &mut Vec<PrevPost>
, community_ids: &CommunitiesVector, auth: &Sensitive<String>) -> Result<Vec<CreatePost>, ()> { , community_ids: &CommunitiesVector, auth: &Sensitive<String>) -> Result<Vec<CreatePost>, reqwest::Error> {
let mut post_queue: Vec<CreatePost> = vec![]; let mut post_queue: Vec<CreatePost> = vec![];
self.feeds.iter().for_each(|feed| { match self.feeds.iter().map(|feed| {
let res = match CLIENT let res = match CLIENT
.get(feed.feed_url.clone()) .get(feed.feed_url.clone())
.send() { .send() {
Ok(data) => data.text().unwrap(), Ok(data) => data.text().unwrap(),
Err(_) => return () Err(e) => return Err(e)
}; };
let data: FeedData = serde_json::from_str(&res).unwrap(); let data: FeedData = serde_json::from_str(&res).unwrap();
@ -152,7 +152,11 @@ impl Config {
} }
} }
sleep(time::Duration::from_millis(100)); // Should prevent dos-ing J-Novel servers sleep(time::Duration::from_millis(100)); // Should prevent dos-ing J-Novel servers
}); return Ok(());
}).collect() {
Ok(()) => {}
Err(e) => return Err(e)
}
PrevPost::save(&post_history); PrevPost::save(&post_history);
return Ok(post_queue); return Ok(post_queue);
@ -270,7 +274,7 @@ impl CommunitiesVector {
} }
#[warn(unused_results)] #[warn(unused_results)]
pub(crate) fn load(&mut self, auth: &Sensitive<String>, base: &String) -> bool { pub(crate) fn load(&mut self, auth: &Sensitive<String>, base: &String) -> Result<(), reqwest::Error> {
let params = ListCommunities { let params = ListCommunities {
auth: Some(auth.clone()), auth: Some(auth.clone()),
type_: Some(ListingType::Local), type_: Some(ListingType::Local),
@ -281,10 +285,8 @@ impl CommunitiesVector {
.get(base.clone() + "/api/v3/community/list") .get(base.clone() + "/api/v3/community/list")
.query(&params) .query(&params)
.send() { .send() {
Ok(data) => { Ok(data) => data.text().unwrap(),
data.text().unwrap() Err(e) => return Err(e)
}
Err(_) => {return false}
}; };
let site_data: ListCommunitiesResponse = serde_json::from_str(&res).unwrap(); let site_data: ListCommunitiesResponse = serde_json::from_str(&res).unwrap();
@ -297,7 +299,7 @@ impl CommunitiesVector {
}); });
self.ids = ids; self.ids = ids;
return true; return Ok(());
} }
pub(crate) fn find(&self, name: &LemmyCommunities) -> CommunityId { pub(crate) fn find(&self, name: &LemmyCommunities) -> CommunityId {

View file

@ -10,7 +10,7 @@ use lemmy_db_schema::{
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use reqwest::{blocking::Client, StatusCode}; use reqwest::{blocking::Client, StatusCode};
use std::{thread::sleep, time, io}; use std::{thread::sleep, time, io, error::Error};
mod config; mod config;
@ -50,7 +50,7 @@ impl Bot {
/// ///
/// * `return` : Returns true if token was succesfully retrieved, false otherwise /// * `return` : Returns true if token was succesfully retrieved, false otherwise
#[warn(unused_results)] #[warn(unused_results)]
pub(crate) fn login(&mut self) -> bool { pub(crate) fn login(&mut self) -> Result<(), reqwest::Error> {
let login_params = Login { let login_params = Login {
username_or_email: self.secrets.lemmy.get_username(), username_or_email: self.secrets.lemmy.get_username(),
password: self.secrets.lemmy.get_password(), password: self.secrets.lemmy.get_password(),
@ -62,7 +62,7 @@ impl Bot {
.json(&login_params) .json(&login_params)
.send() { .send() {
Ok(data) => data, Ok(data) => data,
Err(_) => return false, Err(e) => return Err(e),
}; };
@ -71,10 +71,10 @@ impl Bot {
let jwt = data.jwt.clone().expect("JWT Token could not be acquired"); let jwt = data.jwt.clone().expect("JWT Token could not be acquired");
self.auth = jwt; self.auth = jwt;
return true; return Ok(());
} else { } else {
println!("Error Code: {:?}", res.status()); println!("Error Code: {:?}", res.status());
return false; return Err(res.error_for_status().unwrap_err());
} }
} }
@ -83,22 +83,22 @@ impl Bot {
/// * `post_data` : Object of type [CreatePost] containing post info /// * `post_data` : Object of type [CreatePost] containing post info
/// * `return` : Returns true if Post was succesful, false otherwise /// * `return` : Returns true if Post was succesful, false otherwise
#[warn(unused_results)] #[warn(unused_results)]
pub(crate) fn post(&mut self, post_data: CreatePost) -> bool { pub(crate) fn post(&mut self, post_data: CreatePost) -> Result<(), reqwest::Error> {
let res = match CLIENT let res = match CLIENT
.post(self.config.instance.clone() + "/api/v3/post") .post(self.config.instance.clone() + "/api/v3/post")
.json(&post_data) .json(&post_data)
.send() { .send() {
Ok(data) => data, Ok(data) => data,
Err(_) => return false Err(e) => return Err(e)
}; };
// TODO: process res to get info about if post was successfuly (mostly if jwt token was valid) // TODO: process res to get info about if post was successfuly (mostly if jwt token was valid)
return true; return Ok(());
} }
#[warn(unused_results)] #[warn(unused_results)]
pub(crate) fn run_once(&mut self, mut prev_time: NaiveTime) -> bool { pub(crate) fn run_once(&mut self, mut prev_time: NaiveTime) -> Result<(), reqwest::Error> {
println!("{:#<1$}", "", 30); println!("{:#<1$}", "", 30);
self.start_time = Utc::now(); self.start_time = Utc::now();
@ -106,7 +106,10 @@ impl Bot {
println!("Reloading Config"); println!("Reloading Config");
prev_time = self.start_time.time(); prev_time = self.start_time.time();
self.config.load(); self.config.load();
if !self.community_ids.load(&self.auth, &self.config.instance) {return false}; // Return early if community id's cannot be loaded match self.community_ids.load(&self.auth, &self.config.instance) {
Ok(_) => {},
Err(e) => return Err(e)
};
println!("Done!"); println!("Done!");
} }
@ -115,19 +118,19 @@ impl Bot {
println!("Checking Feeds"); println!("Checking Feeds");
let post_queue: Vec<CreatePost> = match self.config.check_feeds(&mut self.post_history, &self.community_ids, &self.auth) { let post_queue: Vec<CreatePost> = match self.config.check_feeds(&mut self.post_history, &self.community_ids, &self.auth) {
Ok(data) => data, Ok(data) => data,
Err(_) => return false Err(e) => return Err(e)
}; };
println!("Done!"); println!("Done!");
post_queue.iter().for_each(|post| { post_queue.iter().for_each(|post| {
println!("Posting: {}", post.name); println!("Posting: {}", post.name);
loop { loop {
if self.post(post.clone()) {break}; if self.post(post.clone()).is_ok() {break};
println!("Post attempt failed, retrying"); println!("Post attempt failed, retrying");
} }
}); });
return true; return Ok(());
} }
pub(crate) fn idle(&self) { pub(crate) fn idle(&self) {
@ -177,28 +180,32 @@ fn run_bot() {
// Get all needed auth tokens at the start // Get all needed auth tokens at the start
let mut old = Utc::now().time(); let mut old = Utc::now().time();
let mut this = Bot::new(); let mut this = Bot::new();
if this.login() { match this.login() {
this.community_ids.load(&this.auth, &this.config.instance); Ok(_) => {
this.community_ids.load(&this.auth, &this.config.instance);
// Enter a loop (not for debugging) // Enter a loop (not for debugging)
loop { loop {
this.idle(); this.idle();
// 3 retries in case of connection issues // 3 retries in case of connection issues
let mut loop_breaker: u8 = 0; let mut loop_breaker: u8 = 0;
while !this.run_once(old) && loop_breaker <= 3 { while !this.run_once(old).is_ok() && loop_breaker <= 3 {
println!("Unable to complete Bot cycle, retrying with fresh login credentials"); println!("Unable to complete Bot cycle, retrying with fresh login credentials");
if this.login() { if this.login().is_ok() {
this.community_ids.load(&this.auth, &this.config.instance); this.community_ids.load(&this.auth, &this.config.instance);
} }
sleep(time::Duration::from_secs(10)); sleep(time::Duration::from_secs(10));
loop_breaker += 1; loop_breaker += 1;
}; };
this.print_info(); this.print_info();
this.idle(); this.idle();
}
},
Err(e) => {
println!("Unable to get initial login:\n {:#?}", e);
} }
} }
} }
fn main() -> Result<(), io::Error> { fn main() {
run_bot(); run_bot();
Ok(())
} }