aob-lemmy-bot/src/config.rs

248 lines
8.8 KiB
Rust

use std::path::PathBuf;
use std::sync::{Arc, RwLock};
use chrono::{Timelike, Utc};
use crate::settings::PostBody::Description;
use lemmy_db_schema::PostFeatureType;
use lemmy_db_schema::sensitive::SensitiveString;
use serde_derive::{Deserialize, Serialize};
use crate::lemmy::{Lemmy, PartInfo, PostType};
use crate::post_history::{SeriesHistory};
use crate::fetchers::{FetcherTrait, Fetcher};
use crate::fetchers::jnovel::{JNovelFetcher};
use crate::logging::Logging;
use crate::settings::PostBody;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub(crate) struct SingleBotConfig {
pub(crate) instance: String,
username: SensitiveString,
password: SensitiveString,
pub(crate) status_post_url: Option<String>,
pub(crate) protected_communities: Vec<String>,
pub(crate) series: Vec<SeriesConfig>,
}
impl SingleBotConfig {
pub(crate) fn load(&self) -> Self {
if self.instance.is_empty() {
panic!("bot instance not set!")
}
if self.username.is_empty() {
panic!("bot username not set!")
}
if self.password.is_empty() {
panic!("bot password not provided!")
}
self.series.iter().for_each(|series| {
if series.prepub_community.post_body == Description {
panic!("'Description' type Post Body only supported for Volumes!")
}
});
self.clone()
}
pub(crate) fn get_path() -> PathBuf {
confy::get_configuration_file_path(env!("CARGO_PKG_NAME"), "config").expect("Application will not without confy")
}
pub(crate) fn get_username(&self) -> SensitiveString {
self.username.clone()
}
pub(crate) fn get_password(&self) -> SensitiveString {
self.password.clone()
}
}
impl Default for SingleBotConfig {
fn default() -> Self {
SingleBotConfig {
instance: "".to_owned(),
username: SensitiveString::from("".to_owned()),
password: SensitiveString::from("".to_owned()),
status_post_url: None,
protected_communities: vec![],
series: vec![],
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub(crate) struct SeriesConfig {
pub(crate) slug: String,
pub(crate) parted: bool,
pub(crate) prepub_community: PostConfig,
pub(crate) volume_community: PostConfig,
pub(crate) fetcher: Fetcher
}
impl SeriesConfig {
pub(crate) fn update(&self, history: &mut SeriesHistory, lemmy: &Lemmy, config: &Arc<RwLock<SingleBotConfig>>) {
let info_msg = format!("Checking {} for Updates", self.slug);
Logging::info(info_msg.as_str());
let mut fetcher: Fetcher = match &self.fetcher {
Fetcher::Jnc(_) => {
Fetcher::Jnc(JNovelFetcher::new())
},
/*default => {
let err_msg = format!("Fetcher {default} not implemented");
error!(err_msg);
return;
}*/
};
match fetcher {
Fetcher::Jnc(ref mut jnc) => {
jnc.set_series(self.slug.clone());
jnc.set_part_option(self.parted);
}
}
let post_list = match fetcher.check_feed() {
Ok(data) => data,
Err(_) => {
let err_msg = format!("While checking feed for {}", self.slug);
Logging::error(err_msg.as_str());
return;
}
};
if post_list.is_empty() && Utc::now().minute() % 10 == 0 {
let info_msg = "No Updates found";
Logging::info(info_msg);
}
for post_info in post_list.iter() {
if history.check_for_post(
self.slug.as_str(),
post_info.get_part_info().unwrap_or(PartInfo::NoParts).as_string().as_str(),
post_info.get_info().title.as_str()
) {
continue
}
let post_data = post_info.get_post_data(self, lemmy);
let info = format!(
"Posting '{}' to {}",
post_info.get_info().title.as_str(),
post_info.get_post_config(self).name.as_str()
);
Logging::info(info.as_str());
let post_id = match lemmy.post(post_data) {
Some(data) => data,
None=> {
Logging::error("Error posting chapter");
return;
}
};
let read_config = config.read().expect("Read Lock Failed").clone();
if post_info.get_post_config(self).pin_settings.pin_new_post_community
&& !read_config
.protected_communities
.contains(&post_info.get_post_config(self).name)
{
let info = format!(
"Pinning '{}' to {}",
post_info.get_info().title,
post_info.get_post_config(self).name.as_str()
);
Logging::info(info.as_str());
let pinned_posts = lemmy.get_community_pinned(lemmy.get_community_id(&post_info.get_post_config(self).name)).unwrap_or_else(|| {
Logging::error("Pinning of Post to community failed");
vec![]
});
if !pinned_posts.is_empty() {
let community_pinned_post = &pinned_posts[0];
if lemmy.unpin(community_pinned_post.post.id, PostFeatureType::Community).is_none() {
Logging::error("Error un-pinning post");
}
}
if lemmy.pin(post_id, PostFeatureType::Community).is_none() {
Logging::error("Error pinning post");
}
} else if read_config
.protected_communities
.contains(&post_info.get_post_config(self).name)
{
let message = format!(
"Community '{}' for Series '{}' is protected. Is this intended?",
&post_info.get_post_config(self).name, self.slug
);
Logging::warn(message.as_str());
}
if post_info.get_post_config(self).pin_settings.pin_new_post_local {
let info = format!("Pinning '{}' to Instance", post_info.get_info().title);
Logging::info(info.as_str());
let pinned_posts = match lemmy.get_local_pinned() {
Some(data) => {data}
None => {
Logging::error("Error fetching pinned posts");
vec![]
}
};
if !pinned_posts.is_empty() {
for pinned_post in pinned_posts {
if read_config
.protected_communities
.contains(&pinned_post.community.name)
{
continue;
} else {
let community_pinned_post = &pinned_post;
if lemmy.unpin(community_pinned_post.post.id, PostFeatureType::Local).is_none() {
Logging::error("Error pinning post");
continue;
}
break;
}
}
}
if lemmy.pin(post_id, PostFeatureType::Local).is_none() {
Logging::error("Error pinning post");
};
}
let mut series_history = history.get_series(self.slug.as_str());
let mut part_history = series_history.get_part(post_info.get_part_info().unwrap_or(PartInfo::NoParts).as_string().as_str());
match post_info.post_type {
Some(post_type) => {
match post_type {
PostType::Chapter => part_history.chapter = post_info.get_info().title,
PostType::Volume => part_history.volume = post_info.get_info().title,
}
}
None => part_history.chapter = post_info.get_info().title,
}
series_history.set_part(post_info.get_part_info().unwrap_or(PartInfo::NoParts).as_string().as_str(), part_history);
history
.set_series(self.slug.as_str(), series_history);
Logging::debug("Saving History");
history.save_history();
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub(crate) struct PostConfig {
pub(crate) name: String,
pub(crate) pin_settings: PinConfig,
pub(crate) post_body: PostBody,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub(crate) struct PinConfig {
pub(crate) pin_new_post_local: bool,
pub(crate) pin_new_post_community: bool,
}