mirror of
https://github.com/YGGverse/pulsarss.git
synced 2026-03-31 09:05:29 +00:00
implement debug output features
This commit is contained in:
parent
196ec99361
commit
2ef0c8e7ff
4 changed files with 58 additions and 11 deletions
|
|
@ -28,6 +28,9 @@ pulsarss --source https://path/to/feed.rss
|
||||||
* `source`, `s` - RSS feed source (required)
|
* `source`, `s` - RSS feed source (required)
|
||||||
* `target`, `t` - Destination directory (`public` by default)
|
* `target`, `t` - Destination directory (`public` by default)
|
||||||
* `update`, `u` - Update timeout in seconds (`60` by default)
|
* `update`, `u` - Update timeout in seconds (`60` by default)
|
||||||
|
* `output`, `o` - Print output (`d` by default):
|
||||||
|
* `d` - debug
|
||||||
|
* `n` - disable
|
||||||
|
|
||||||
### Autostart
|
### Autostart
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,11 @@ pub struct Argument {
|
||||||
#[arg(short, long, default_value_t = String::from("public"))]
|
#[arg(short, long, default_value_t = String::from("public"))]
|
||||||
pub target: String,
|
pub target: String,
|
||||||
|
|
||||||
/// Update timeout in seconds (60 by default)
|
/// Update timeout in seconds (`60` by default)
|
||||||
#[arg(short, long, default_value_t = 60)]
|
#[arg(short, long, default_value_t = 60)]
|
||||||
pub update: u64,
|
pub update: u64,
|
||||||
|
|
||||||
|
/// Show output (`d` by default)
|
||||||
|
#[arg(short, long, default_value_t = String::from("d"))]
|
||||||
|
pub output: String,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
src/main.rs
31
src/main.rs
|
|
@ -1,5 +1,7 @@
|
||||||
mod argument;
|
mod argument;
|
||||||
|
mod output;
|
||||||
|
|
||||||
|
use output::Output;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
|
@ -8,16 +10,17 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
use std::{thread::sleep, time::Duration};
|
use std::{thread::sleep, time::Duration};
|
||||||
|
|
||||||
let argument = Argument::parse();
|
let argument = Argument::parse();
|
||||||
|
let output = Output::build(&argument.output);
|
||||||
|
|
||||||
let mut index: Vec<usize> = Vec::new();
|
output.debug("crawler started");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
crawl(&mut index, &argument.source, &argument.target)?;
|
crawl(&argument.source, &argument.target, &output)?;
|
||||||
sleep(Duration::from_secs(argument.update));
|
sleep(Duration::from_secs(argument.update));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn crawl(index: &mut Vec<usize>, source: &str, target: &str) -> Result<(), Box<dyn Error>> {
|
fn crawl(source: &str, target: &str, output: &Output) -> Result<(), Box<dyn Error>> {
|
||||||
use reqwest::blocking::get;
|
use reqwest::blocking::get;
|
||||||
use rss::Channel;
|
use rss::Channel;
|
||||||
use std::{
|
use std::{
|
||||||
|
|
@ -25,13 +28,18 @@ fn crawl(index: &mut Vec<usize>, source: &str, target: &str) -> Result<(), Box<d
|
||||||
io::Write,
|
io::Write,
|
||||||
};
|
};
|
||||||
|
|
||||||
for item in Channel::read_from(&get(source)?.bytes()?[..])?.items() {
|
output.debug("update begin");
|
||||||
let id = index.len() + 1;
|
|
||||||
|
|
||||||
let path = &path(id, target, item.pub_date().unwrap(), true)?;
|
let mut total = 0;
|
||||||
|
let mut exist = 0;
|
||||||
|
for item in Channel::read_from(&get(source)?.bytes()?[..])?.items() {
|
||||||
|
total += 1;
|
||||||
|
|
||||||
|
let path = &path(target, item.pub_date().unwrap(), true)?;
|
||||||
|
|
||||||
if metadata(path).is_ok() {
|
if metadata(path).is_ok() {
|
||||||
continue; // skip existing records
|
exist += 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut file = File::create(path)?;
|
let mut file = File::create(path)?;
|
||||||
|
|
@ -45,14 +53,17 @@ fn crawl(index: &mut Vec<usize>, source: &str, target: &str) -> Result<(), Box<d
|
||||||
)
|
)
|
||||||
.as_bytes(),
|
.as_bytes(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
index.push(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output.debug(&format!(
|
||||||
|
"update completed (added: {} / exist: {exist} / total: {total})",
|
||||||
|
total - exist
|
||||||
|
));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(_id: usize, base: &str, pub_date: &str, mkdir: bool) -> Result<String, Box<dyn Error>> {
|
fn path(base: &str, pub_date: &str, mkdir: bool) -> Result<String, Box<dyn Error>> {
|
||||||
use chrono::{DateTime, Datelike, Timelike};
|
use chrono::{DateTime, Datelike, Timelike};
|
||||||
use std::{fs::create_dir_all, path::MAIN_SEPARATOR};
|
use std::{fs::create_dir_all, path::MAIN_SEPARATOR};
|
||||||
|
|
||||||
|
|
|
||||||
29
src/output.rs
Normal file
29
src/output.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
struct Level {
|
||||||
|
debug: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Output(Level);
|
||||||
|
|
||||||
|
impl Output {
|
||||||
|
pub fn build(level: &str) -> Self {
|
||||||
|
Self(Level {
|
||||||
|
debug: level.contains("d"),
|
||||||
|
// @TODO other flags
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn debug(&self, message: &str) {
|
||||||
|
if self.0.debug {
|
||||||
|
eprintln!("[debug] [{}] {message}", time());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn time() -> String {
|
||||||
|
let system_time = SystemTime::now();
|
||||||
|
let datetime: DateTime<Utc> = system_time.into();
|
||||||
|
datetime.to_rfc3339()
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue