2024-05-06 18:53:38 +00:00
use crate ::{ config ::{ Config , PostBody , SeriesConfig } , fetchers ::{ jnovel } , lemmy } ;
2024-01-08 20:07:17 +00:00
use crate ::fetchers ::jnovel ::JPostInfo ;
use crate ::lemmy ::{ Lemmy , PostInfo } ;
2023-12-30 00:27:11 +00:00
use crate ::post_history ::SeriesHistory ;
2024-05-06 18:53:38 +00:00
use chrono ::{ DateTime , Duration , Timelike , Utc } ;
2023-12-19 21:08:23 +00:00
use lemmy_api_common ::post ::CreatePost ;
2023-12-17 19:17:14 +00:00
use lemmy_db_schema ::newtypes ::{ CommunityId , LanguageId } ;
use lemmy_db_schema ::PostFeatureType ;
2023-12-30 00:27:11 +00:00
use std ::collections ::HashMap ;
2023-12-17 19:17:14 +00:00
use tokio ::time ::sleep ;
2024-01-08 20:07:17 +00:00
use crate ::fetchers ::Fetcher ;
2024-05-06 18:51:31 +00:00
use systemd_journal_logger ::connected_to_journal ;
2023-12-17 19:17:14 +00:00
2024-05-06 18:51:31 +00:00
macro_rules ! info {
( $msg :tt ) = > {
match connected_to_journal ( ) {
true = > log ::info! ( " [INFO] {} " , $msg ) ,
false = > println! ( " [INFO] {} " , $msg ) ,
}
} ;
}
macro_rules ! warn {
( $msg :tt ) = > {
match connected_to_journal ( ) {
true = > log ::warn! ( " [WARN] {} " , $msg ) ,
false = > println! ( " [WARN] {} " , $msg ) ,
}
} ;
}
macro_rules ! error {
( $msg :tt ) = > {
match connected_to_journal ( ) {
true = > log ::error! ( " [ERROR] {} " , $msg ) ,
false = > eprintln! ( " [ERROR] {} " , $msg ) ,
}
} ;
}
2024-05-06 18:53:38 +00:00
pub ( crate ) async fn run ( ) {
2023-12-17 19:17:14 +00:00
let mut last_reload : DateTime < Utc > ;
let mut lemmy : Lemmy ;
let mut login_error : bool ;
2024-05-06 18:53:38 +00:00
let mut communities : HashMap < String , CommunityId > ;
let mut post_history : SeriesHistory ;
let mut start : DateTime < Utc > ;
let mut config : Config = Config ::load ( ) ;
last_reload = Utc ::now ( ) ;
2023-12-17 19:17:14 +00:00
2024-05-06 18:53:38 +00:00
lemmy = match lemmy ::login ( & config ) . await {
Ok ( data ) = > data ,
Err ( _ ) = > panic! ( ) ,
} ;
login_error = false ;
2023-12-17 19:57:03 +00:00
2024-05-06 18:53:38 +00:00
communities = match lemmy . get_communities ( ) . await {
Ok ( data ) = > data ,
Err ( _ ) = > panic! ( ) ,
} ;
2023-12-17 19:17:14 +00:00
2024-05-06 18:53:38 +00:00
start = Utc ::now ( ) ;
2023-12-17 21:29:18 +00:00
2023-12-29 23:53:00 +00:00
let info_msg = " Bot init successful, starting normal operations " . to_owned ( ) ;
2024-05-06 18:51:31 +00:00
info! ( info_msg ) ;
2023-12-29 23:53:00 +00:00
2023-12-17 19:17:14 +00:00
loop {
2024-05-06 18:53:38 +00:00
idle ( & start , & config ) . await ;
start = Utc ::now ( ) ;
2023-12-17 19:17:14 +00:00
2024-05-06 18:53:38 +00:00
// replace with watcher
if start - last_reload > = Duration ::seconds ( config . config_reload_seconds as i64 ) {
config = Config ::load ( ) ;
2024-05-06 18:51:31 +00:00
let message = " Config reloaded " . to_owned ( ) ;
info! ( message ) ;
2023-12-29 13:35:07 +00:00
}
2024-05-06 18:53:38 +00:00
if login_error {
2024-05-06 18:51:31 +00:00
let info_msg = " Login invalid, refreshing session " ;
info! ( info_msg ) ;
lemmy = match lemmy ::login ( & config ) . await {
2024-05-06 18:53:38 +00:00
Ok ( data ) = > data ,
Err ( _ ) = > continue ,
} ;
login_error = false ;
2023-12-17 21:29:18 +00:00
}
2024-05-06 18:53:38 +00:00
if start - last_reload > = Duration ::seconds ( config . config_reload_seconds as i64 ) {
communities = match lemmy . get_communities ( ) . await {
Ok ( data ) = > data ,
Err ( _ ) = > {
login_error = true ;
continue ;
}
} ;
2024-05-06 18:51:31 +00:00
let message = " Communities reloaded " . to_owned ( ) ;
info! ( message ) ;
last_reload = Utc ::now ( ) ;
2023-12-17 19:17:14 +00:00
}
2024-05-06 18:53:38 +00:00
post_history = SeriesHistory ::load_history ( ) ;
2023-12-17 19:17:14 +00:00
2024-05-06 18:53:38 +00:00
let series = config . series . clone ( ) ;
for series in series {
if handle_series ( & series , & communities , & lemmy , & config , & mut post_history )
. await
. is_err ( )
{
login_error = true ;
continue ;
} ;
2023-12-17 21:29:18 +00:00
}
2023-12-17 19:17:14 +00:00
2024-05-06 18:53:38 +00:00
idle ( & start , & config ) . await ;
2023-12-17 19:17:14 +00:00
}
}
2024-05-06 18:53:38 +00:00
async fn idle ( start : & DateTime < Utc > , config : & Config ) {
2023-12-17 19:17:14 +00:00
let mut sleep_duration = Duration ::seconds ( 30 ) ;
2024-05-06 18:53:38 +00:00
if Utc ::now ( ) - start > sleep_duration {
2023-12-17 19:17:14 +00:00
sleep_duration = Duration ::seconds ( 60 ) ;
}
2024-05-06 18:53:38 +00:00
if let Some ( status_url ) = config . status_post_url . clone ( ) {
2023-12-17 19:17:14 +00:00
match reqwest ::get ( status_url ) . await {
Ok ( _ ) = > { }
Err ( e ) = > {
2023-12-29 23:40:12 +00:00
let err_msg = format! ( " {e} " ) ;
2024-05-06 18:51:31 +00:00
error! ( err_msg ) ;
2023-12-30 00:27:11 +00:00
}
2023-12-17 19:17:14 +00:00
}
} ;
2024-05-06 18:53:38 +00:00
while Utc ::now ( ) - start < sleep_duration {
2023-12-17 19:17:14 +00:00
sleep ( Duration ::milliseconds ( 100 ) . to_std ( ) . unwrap ( ) ) . await ;
}
}
2024-05-06 18:53:38 +00:00
async fn handle_series ( series : & SeriesConfig , communities : & HashMap < String , CommunityId > , lemmy : & Lemmy , config : & Config , post_history : & mut SeriesHistory ) -> Result < ( ) , ( ) > {
2024-01-08 20:07:17 +00:00
let jnc = jnovel ::JFetcherOptions ::new ( series . slug . clone ( ) , series . parted ) ;
let post_list = match jnc . check_feed ( ) . await {
2023-12-17 19:17:14 +00:00
Ok ( data ) = > data ,
2023-12-29 23:40:12 +00:00
Err ( _ ) = > return Err ( ( ) ) ,
2023-12-17 19:17:14 +00:00
} ;
2024-05-06 18:51:31 +00:00
if post_list . is_empty ( ) & & Utc ::now ( ) . minute ( ) % 10 = = 0 {
let info_msg = " No Updates found " ;
info! ( info_msg ) ;
}
2023-12-17 19:17:14 +00:00
2024-01-08 20:07:17 +00:00
for post_info in post_list . clone ( ) . iter ( ) {
2023-12-17 19:17:14 +00:00
let post_part_info = post_info . get_part_info ( ) ;
2024-01-08 20:07:17 +00:00
let post_lemmy_info = post_info . get_info ( ) ;
2023-12-17 19:17:14 +00:00
2024-05-06 18:53:38 +00:00
if post_history . check_for_post (
series . slug . as_str ( ) ,
post_part_info . as_string ( ) . as_str ( ) ,
post_lemmy_info . title . as_str ( ) ,
) {
continue ;
2023-12-17 21:29:18 +00:00
}
2023-12-17 19:17:14 +00:00
let post_series_config = match post_info {
2024-01-08 20:07:17 +00:00
JPostInfo ::Chapter { .. } = > & series . prepub_community ,
JPostInfo ::Volume { .. } = > & series . volume_community ,
2023-12-17 19:17:14 +00:00
} ;
let community_id = * communities
. get ( post_series_config . name . as_str ( ) )
. expect ( " Given community is invalid " ) ;
let post_body = match & post_series_config . post_body {
PostBody ::None = > None ,
PostBody ::Description = > post_info . get_description ( ) ,
PostBody ::Custom ( text ) = > Some ( text . clone ( ) ) ,
} ;
2023-12-19 21:08:23 +00:00
let post_data = CreatePost {
2023-12-30 00:22:13 +00:00
name : post_lemmy_info . title . clone ( ) ,
2023-12-17 19:35:37 +00:00
community_id ,
2023-12-17 19:17:14 +00:00
url : Some ( post_lemmy_info . url ) ,
body : post_body ,
honeypot : None ,
nsfw : None ,
language_id : Some ( LanguageId ( 37 ) ) , // TODO get this id once every few hours per API request, the ordering of IDs suggests that the EN Id might change in the future
} ;
2023-12-30 00:27:11 +00:00
let info = format! (
" Posting '{}' to {} " ,
post_lemmy_info . title . as_str ( ) ,
post_series_config . name . as_str ( )
) ;
2024-05-06 18:51:31 +00:00
info! ( info ) ;
2023-12-17 19:17:14 +00:00
let post_id = lemmy . post ( post_data ) . await ? ;
2024-05-06 18:53:38 +00:00
if post_series_config . pin_settings . pin_new_post_community
& & config
. protected_communities
. contains ( & post_series_config . name )
2023-12-18 22:33:14 +00:00
{
2024-05-06 18:53:38 +00:00
let info = format! (
" Pinning '{}' to {} " ,
post_lemmy_info . title ,
post_series_config . name . as_str ( )
) ;
2024-05-06 18:51:31 +00:00
info! ( info ) ;
2024-05-06 18:53:38 +00:00
let pinned_posts = lemmy . get_community_pinned ( community_id ) . await ? ;
if ! pinned_posts . is_empty ( ) {
let community_pinned_post = & pinned_posts [ 0 ] ;
lemmy
. unpin ( community_pinned_post . post . id , PostFeatureType ::Community )
. await ? ;
2023-12-17 19:17:14 +00:00
}
2024-05-06 18:53:38 +00:00
lemmy . pin ( post_id , PostFeatureType ::Community ) . await ? ;
} else if config
. protected_communities
. contains ( & post_series_config . name )
{
let message = format! (
" Community '{}' for Series '{}' is protected. Is this intended? " ,
& post_series_config . name , series . slug
) ;
2024-05-06 18:51:31 +00:00
warn! ( message ) ;
2023-12-18 10:23:47 +00:00
}
2023-12-17 19:17:14 +00:00
if post_series_config . pin_settings . pin_new_post_local {
2023-12-30 00:22:13 +00:00
let info = format! ( " Pinning ' {} ' to Instance " , post_lemmy_info . title ) ;
2024-05-06 18:51:31 +00:00
info! ( info ) ;
2023-12-17 19:17:14 +00:00
let pinned_posts = lemmy . get_local_pinned ( ) . await ? ;
2023-12-17 19:35:37 +00:00
if ! pinned_posts . is_empty ( ) {
2023-12-18 10:23:47 +00:00
for pinned_post in pinned_posts {
2024-05-06 18:53:38 +00:00
if config
2023-12-30 00:27:11 +00:00
. protected_communities
. contains ( & pinned_post . community . name )
{
continue ;
} else {
2023-12-18 10:23:47 +00:00
let community_pinned_post = & pinned_post ;
2023-12-30 00:27:11 +00:00
lemmy
. unpin ( community_pinned_post . post . id , PostFeatureType ::Local )
. await ? ;
break ;
2023-12-18 10:23:47 +00:00
}
}
2023-12-17 19:17:14 +00:00
}
lemmy . pin ( post_id , PostFeatureType ::Local ) . await ? ;
}
2024-05-06 18:53:38 +00:00
let mut series_history = post_history . get_series ( series . slug . as_str ( ) ) ;
2023-12-17 19:17:14 +00:00
let mut part_history = series_history . get_part ( post_part_info . as_string ( ) . as_str ( ) ) ;
match post_info {
2024-01-08 20:07:17 +00:00
JPostInfo ::Chapter { .. } = > part_history . chapter = post_info . get_info ( ) . title ,
JPostInfo ::Volume { .. } = > part_history . volume = post_info . get_info ( ) . title ,
2023-12-17 19:17:14 +00:00
}
series_history . set_part ( post_part_info . as_string ( ) . as_str ( ) , part_history ) ;
2024-05-06 18:53:38 +00:00
post_history
2023-12-30 00:27:11 +00:00
. set_series ( series . slug . as_str ( ) , series_history ) ;
2024-05-06 18:53:38 +00:00
post_history . save_history ( ) ;
2023-12-17 19:17:14 +00:00
}
Ok ( ( ) )
}