Compare commits
2 commits
5976bd59a7
...
ebbfdcea63
Author | SHA1 | Date | |
---|---|---|---|
ebbfdcea63 | |||
ff0360ac07 |
5 changed files with 123 additions and 51 deletions
77
src/bot.rs
77
src/bot.rs
|
@ -12,9 +12,10 @@ use crate::settings::{BotSettings, SeriesSettings};
|
||||||
|
|
||||||
pub(crate) struct Bot {
|
pub(crate) struct Bot {
|
||||||
settings: BotSettings,
|
settings: BotSettings,
|
||||||
|
settings_id: u16,
|
||||||
health_signal: Arc<AtomicHealthSignal>,
|
health_signal: Arc<AtomicHealthSignal>,
|
||||||
history: SeriesHistory,
|
history: SeriesHistory,
|
||||||
login_time: Option<DateTime<Utc>>
|
login_time: Option<DateTime<Utc>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Wait {
|
enum Wait {
|
||||||
|
@ -23,16 +24,26 @@ enum Wait {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bot {
|
impl Bot {
|
||||||
pub(crate) fn new(health_signal: Arc<AtomicHealthSignal>, settings: BotSettings) -> Self {
|
pub(crate) fn new(health_signal: Arc<AtomicHealthSignal>, settings_id: u16, settings: BotSettings) -> Self {
|
||||||
let history: SeriesHistory = SeriesHistory::load_history();
|
let history: SeriesHistory = SeriesHistory::load_history();
|
||||||
|
|
||||||
Bot { health_signal, settings, history, login_time: None }
|
|
||||||
|
Bot { health_signal, settings_id, settings, history, login_time: None }
|
||||||
}
|
}
|
||||||
pub(crate) fn run(&mut self, series_settings: Arc<RwLock<HashMap<u16, SeriesSettings>>>, update_pending: Arc<AtomicBool>) {
|
pub(crate) fn run(
|
||||||
|
&mut self,
|
||||||
|
series_settings: Arc<RwLock<HashMap<u16, SeriesSettings>>>,
|
||||||
|
bot_settings: Arc<RwLock<HashMap<u16, BotSettings>>>,
|
||||||
|
update_pending: Arc<AtomicBool>
|
||||||
|
) {
|
||||||
|
let mut last_ping = Utc::now();
|
||||||
|
if let Some(interval) = self.settings.status_post_interval() {
|
||||||
|
last_ping -= interval
|
||||||
|
}
|
||||||
loop {
|
loop {
|
||||||
match self.health_signal.load(Ordering::SeqCst) {
|
match self.health_signal.load(Ordering::SeqCst) {
|
||||||
HealthSignal::RequestAlive => {
|
HealthSignal::RequestAlive => {
|
||||||
//self.health_signal.store(HealthSignal::ConfirmAlive, Ordering::SeqCst);
|
self.health_signal.store(HealthSignal::ConfirmAlive, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
HealthSignal::RequestStop => {
|
HealthSignal::RequestStop => {
|
||||||
break;
|
break;
|
||||||
|
@ -40,53 +51,64 @@ impl Bot {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
while update_pending.load(Ordering::SeqCst) {
|
if update_pending.load(Ordering::SeqCst) {
|
||||||
|
Logging::debug("Awaiting Config Update");
|
||||||
sleep(Duration::milliseconds(100).to_std().unwrap());
|
sleep(Duration::milliseconds(100).to_std().unwrap());
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.settings = bot_settings.read().get(&self.settings_id).unwrap().clone();
|
||||||
|
|
||||||
|
// perform status ping
|
||||||
|
if let Some(interval) = self.settings.status_post_interval() {
|
||||||
|
if Utc::now() + Duration::seconds(1) >= last_ping + interval {
|
||||||
|
if self.ping_status() {
|
||||||
|
last_ping = Utc::now();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(login_time) = self.login_time {
|
if let Some(login_time) = self.login_time {
|
||||||
if Utc::now() - login_time >= Duration::minutes(60) {
|
if Utc::now() - login_time >= Duration::minutes(60) {
|
||||||
self.logout();
|
//self.logout();
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.login();
|
//self.login();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.history = SeriesHistory::load_history();
|
self.history = SeriesHistory::load_history();
|
||||||
|
|
||||||
let run_start_time = Utc::now();
|
|
||||||
self.ping_status();
|
|
||||||
|
|
||||||
series_settings.read().iter().for_each(|(id, series)| {
|
series_settings.read().iter().for_each(|(id, series)| {
|
||||||
let new_entries = series.check();
|
//let new_entries = series.check();
|
||||||
});
|
});
|
||||||
for series in series_settings.read().iter() {
|
for series in series_settings.read().iter() {
|
||||||
//series.update(&mut self.history, &lemmy, &self.settings).await;
|
//series.update(&mut self.history, &lemmy, &self.settings).await;
|
||||||
Logging::debug("Done Updating Series");
|
Logging::debug("Done Updating Series");
|
||||||
self.wait(1, Wait::Absolute);
|
self.wait(1, Wait::Absolute);
|
||||||
}
|
}
|
||||||
Logging::debug("Awaiting Timeout");
|
|
||||||
self.wait(30, Wait::Buffer(run_start_time));
|
|
||||||
Logging::debug("Pinging Server");
|
|
||||||
self.ping_status();
|
|
||||||
Logging::debug("Awaiting Timeout 2");
|
|
||||||
self.wait(30, Wait::Absolute);
|
|
||||||
}
|
}
|
||||||
self.health_signal.store(HealthSignal::ConfirmStop, Ordering::SeqCst);
|
self.health_signal.store(HealthSignal::ConfirmStop, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ping_status(&self) {
|
fn ping_status(&self) -> bool {
|
||||||
if let Some(status_url) = &self.settings.status_post_url() {
|
if let Some(status_url) = &self.settings.status_post_url() {
|
||||||
match HTTP_CLIENT.get(status_url).send() {
|
return match HTTP_CLIENT.get(status_url).send() {
|
||||||
Ok(_) => {},
|
Ok(_) => {
|
||||||
|
true
|
||||||
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err_msg = format!("While pinging status URL: {e}");
|
let err_msg = format!("While pinging status URL: {e}");
|
||||||
Logging::error(err_msg.as_str());
|
Logging::error(err_msg.as_str());
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait(&self, seconds: i64, start_time: Wait) {
|
fn wait(&self, seconds: i64, start_time: Wait) {
|
||||||
|
@ -99,15 +121,14 @@ impl Bot {
|
||||||
sleep(Duration::milliseconds(100).to_std().unwrap());
|
sleep(Duration::milliseconds(100).to_std().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn login(&mut self) {
|
fn login(&mut self) {
|
||||||
//
|
todo!();
|
||||||
self.login_time = Some(Utc::now());
|
self.login_time = Some(Utc::now());
|
||||||
todo!()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn logout(&mut self) {
|
fn logout(&mut self) {
|
||||||
self.login_time = None;
|
self.login_time = None;
|
||||||
todo!()
|
todo!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,52 @@
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
use log::Level;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use systemd_journal_logger::connected_to_journal;
|
use systemd_journal_logger::connected_to_journal;
|
||||||
|
|
||||||
fn mem_log(msg: Option<String>) -> VecDeque<LogEvent> {
|
fn mem_log(level: Level, msg: Option<String>) -> VecDeque<LogEvent> {
|
||||||
static MEM_LOG: Mutex<VecDeque<LogEvent>> = Mutex::new(VecDeque::new());
|
static MEM_LOG_DEBUG: Mutex<VecDeque<LogEvent>> = Mutex::new(VecDeque::new());
|
||||||
|
static MEM_LOG_INFO: Mutex<VecDeque<LogEvent>> = Mutex::new(VecDeque::new());
|
||||||
|
static MEM_LOG_WARN: Mutex<VecDeque<LogEvent>> = Mutex::new(VecDeque::new());
|
||||||
|
static MEM_LOG_ERROR: Mutex<VecDeque<LogEvent>> = Mutex::new(VecDeque::new());
|
||||||
|
|
||||||
|
let max_len: i8;
|
||||||
|
|
||||||
|
let mut list = match level {
|
||||||
|
Level::Debug => {
|
||||||
|
max_len = 10;
|
||||||
|
MEM_LOG_DEBUG.lock()
|
||||||
|
},
|
||||||
|
Level::Info => {
|
||||||
|
max_len = 20;
|
||||||
|
MEM_LOG_INFO.lock()
|
||||||
|
},
|
||||||
|
Level::Warn => {
|
||||||
|
max_len = 40;
|
||||||
|
MEM_LOG_WARN.lock()
|
||||||
|
},
|
||||||
|
Level::Error => {
|
||||||
|
max_len = -1;
|
||||||
|
MEM_LOG_ERROR.lock()
|
||||||
|
},
|
||||||
|
Level::Trace => {
|
||||||
|
max_len = 10;
|
||||||
|
MEM_LOG_DEBUG.lock()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(msg) = msg {
|
if let Some(msg) = msg {
|
||||||
let now = Utc::now();
|
let now = Utc::now();
|
||||||
let log_event = LogEvent::new(now, msg);
|
let log_event = LogEvent::new(now, msg);
|
||||||
let mut lock = MEM_LOG.lock();
|
list.push_back(log_event);
|
||||||
lock.push_back(log_event);
|
if max_len != -1 {
|
||||||
while lock.len() > 10 {
|
while list.len() > max_len as usize {
|
||||||
lock.pop_front();
|
list.pop_front();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return MEM_LOG.lock().clone();
|
list.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Logging {
|
pub struct Logging {
|
||||||
|
@ -29,7 +59,7 @@ impl Logging {
|
||||||
true => log::debug!("{msg}"),
|
true => log::debug!("{msg}"),
|
||||||
false => println!("{msg}"),
|
false => println!("{msg}"),
|
||||||
}
|
}
|
||||||
mem_log(Some(msg));
|
mem_log(Level::Debug, Some(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn info(msg: &str) {
|
pub fn info(msg: &str) {
|
||||||
|
@ -38,7 +68,7 @@ impl Logging {
|
||||||
true => log::info!("{msg}"),
|
true => log::info!("{msg}"),
|
||||||
false => println!("{msg}"),
|
false => println!("{msg}"),
|
||||||
}
|
}
|
||||||
mem_log(Some(msg));
|
mem_log(Level::Info, Some(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn warn(msg: &str) {
|
pub fn warn(msg: &str) {
|
||||||
|
@ -47,7 +77,7 @@ impl Logging {
|
||||||
true => log::warn!("{msg}"),
|
true => log::warn!("{msg}"),
|
||||||
false => println!("{msg}"),
|
false => println!("{msg}"),
|
||||||
}
|
}
|
||||||
mem_log(Some(msg));
|
mem_log(Level::Warn, Some(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error(msg: &str) {
|
pub fn error(msg: &str) {
|
||||||
|
@ -56,11 +86,11 @@ impl Logging {
|
||||||
true => log::error!("{msg}"),
|
true => log::error!("{msg}"),
|
||||||
false => eprintln!("{msg}"),
|
false => eprintln!("{msg}"),
|
||||||
}
|
}
|
||||||
mem_log(Some(msg));
|
mem_log(Level::Error, Some(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_mem_log() -> VecDeque<LogEvent> {
|
pub fn get_mem_log(level: Level) -> VecDeque<LogEvent> {
|
||||||
mem_log(None)
|
mem_log(level, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -59,18 +59,19 @@ fn main() {
|
||||||
|
|
||||||
let mut health_signals: Vec<Arc<AtomicHealthSignal>> = vec![];
|
let mut health_signals: Vec<Arc<AtomicHealthSignal>> = vec![];
|
||||||
let mut update_pending: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
|
let mut update_pending: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
let series_settings = settings.read().series_settings().clone();
|
|
||||||
settings.read().bot_settings().read().iter().for_each(|(id, bot_settings)| {
|
settings.read().bot_settings().read().iter().for_each(|(id, bot_settings)| {
|
||||||
let health_signal = Arc::new(AtomicHealthSignal::new(HealthSignal::RequestAlive));
|
let health_signal = Arc::new(AtomicHealthSignal::new(HealthSignal::RequestAlive));
|
||||||
health_signals.push(health_signal.clone());
|
health_signals.push(health_signal.clone());
|
||||||
|
|
||||||
let bot_settings = bot_settings.clone();
|
let bot_settings = bot_settings.clone();
|
||||||
let series_settings = series_settings.clone();
|
let bot_id = *id;
|
||||||
|
let series_settings = settings.read().series_settings().clone();
|
||||||
|
let bot_settings_map = settings.read().bot_settings().clone();
|
||||||
let update_pending = update_pending.clone();
|
let update_pending = update_pending.clone();
|
||||||
spawn(move || {
|
spawn(move || {
|
||||||
let mut bot = Bot::new(health_signal, bot_settings);
|
let mut bot = Bot::new(health_signal, bot_id, bot_settings);
|
||||||
bot.run(series_settings, update_pending);
|
bot.run(series_settings, bot_settings_map, update_pending);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,12 @@ impl ApplicationSettings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct StatusPostSettings {
|
||||||
|
url: String,
|
||||||
|
interval: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct BotSettings {
|
pub struct BotSettings {
|
||||||
id: u16,
|
id: u16,
|
||||||
|
@ -76,7 +82,7 @@ pub struct BotSettings {
|
||||||
instance: String,
|
instance: String,
|
||||||
username: SensitiveString,
|
username: SensitiveString,
|
||||||
password: SensitiveString,
|
password: SensitiveString,
|
||||||
status_post_url: Option<String>,
|
status_post_settings: Option<StatusPostSettings>,
|
||||||
}
|
}
|
||||||
impl BotSettings {
|
impl BotSettings {
|
||||||
pub fn instance(&self) -> String {
|
pub fn instance(&self) -> String {
|
||||||
|
@ -90,7 +96,17 @@ impl BotSettings {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn status_post_url(&self) -> Option<String> {
|
pub fn status_post_url(&self) -> Option<String> {
|
||||||
self.status_post_url.clone()
|
match &self.status_post_settings {
|
||||||
|
Some(settings) => Some(settings.url.clone()),
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn status_post_interval(&self) -> Option<Duration> {
|
||||||
|
match &self.status_post_settings {
|
||||||
|
Some(settings) => Some(settings.interval),
|
||||||
|
None => None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::config::SeriesConfig;
|
||||||
use crate::fetchers::{Fetcher, FetcherTrait};
|
use crate::fetchers::{Fetcher, FetcherTrait};
|
||||||
use crate::fetchers::jnovel::JNovelFetcher;
|
use crate::fetchers::jnovel::JNovelFetcher;
|
||||||
use crate::lemmy::PostType;
|
use crate::lemmy::PostType;
|
||||||
use crate::settings::{BotSettings, PostSettings, SeriesSettings, SettingsSource};
|
use crate::settings::{BotSettings, PostSettings, SeriesSettings, SettingsSource, StatusPostSettings};
|
||||||
use crate::settings::toml::TomlSettings;
|
use crate::settings::toml::TomlSettings;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
@ -16,9 +16,10 @@ pub struct SingleBotTomlSettings {
|
||||||
username: SensitiveString,
|
username: SensitiveString,
|
||||||
password: SensitiveString,
|
password: SensitiveString,
|
||||||
status_post_url: Option<String>,
|
status_post_url: Option<String>,
|
||||||
|
status_post_interval: Option<u32>,
|
||||||
pub protected_communities: Vec<String>,
|
pub protected_communities: Vec<String>,
|
||||||
series: Vec<SeriesConfig>,
|
series: Vec<SeriesConfig>,
|
||||||
fetch_interval: usize,
|
fetch_interval: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SettingsSource for SingleBotTomlSettings {
|
impl SettingsSource for SingleBotTomlSettings {
|
||||||
|
@ -41,7 +42,10 @@ impl SettingsSource for SingleBotTomlSettings {
|
||||||
instance: self.instance.clone(),
|
instance: self.instance.clone(),
|
||||||
username: self.username.clone(),
|
username: self.username.clone(),
|
||||||
password: self.password.clone(),
|
password: self.password.clone(),
|
||||||
status_post_url: self.status_post_url.clone(),
|
status_post_settings: Some(StatusPostSettings {
|
||||||
|
url: self.status_post_url.clone().unwrap(),
|
||||||
|
interval: Duration::from_secs(self.status_post_interval.clone().unwrap() as u64)
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue