feat: ✨ Initial commit
This commit is contained in:
146
src/main.rs
Normal file
146
src/main.rs
Normal file
@@ -0,0 +1,146 @@
|
||||
use std::borrow::Borrow;
|
||||
/**
|
||||
* A simple personnal tutorial for my first baby steps with Rust.
|
||||
*/
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Cursor};
|
||||
|
||||
|
||||
use chrono::DateTime;
|
||||
use clap::Parser;
|
||||
use json::object;
|
||||
use rss::Channel;
|
||||
|
||||
// use log::debug;
|
||||
use log::error;
|
||||
use log::info;
|
||||
// use log::warn;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
#[clap(short, long, required = true)]
|
||||
input: String,
|
||||
|
||||
#[clap(short, long, default_value_t=String::new())]
|
||||
output: String,
|
||||
|
||||
#[clap(short, long, default_value_t = false)]
|
||||
pretty: bool,
|
||||
}
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
env_logger::init();
|
||||
|
||||
let args = Args::parse();
|
||||
|
||||
// TODO handle remote http feed discovery by parsing index and search for the feed link
|
||||
|
||||
let channel: Channel;
|
||||
|
||||
if args.input.starts_with("http://") || args.input.starts_with("https://") {
|
||||
// process download
|
||||
match reqwest::blocking::get(args.input).unwrap().bytes() {
|
||||
Ok(content) => {
|
||||
info!("Extracted {} bytes", content.len());
|
||||
let cursor = Cursor::new(content);
|
||||
channel = Channel::read_from(cursor).unwrap();
|
||||
}
|
||||
Err(e) => {
|
||||
error!("{}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// read locale file
|
||||
let file = File::open(args.input).unwrap();
|
||||
channel = Channel::read_from(BufReader::new(file)).unwrap();
|
||||
}
|
||||
|
||||
// Initialize root object with channel informations, using object macro from json crate
|
||||
let mut data = object! {
|
||||
channel: object!{
|
||||
title: channel.title(),
|
||||
link: channel.link(),
|
||||
description: channel.description(),
|
||||
last_build_date: channel.last_build_date(),
|
||||
language: channel.language(),
|
||||
copyright: channel.copyright(),
|
||||
generator: channel.generator()
|
||||
}
|
||||
};
|
||||
|
||||
// declare an mutable array to populate it with channel item data
|
||||
let mut items_data = json::JsonValue::new_array();
|
||||
|
||||
// populate the items array
|
||||
for item in channel.items() {
|
||||
let pub_datetime = DateTime::parse_from_rfc2822(item.pub_date().unwrap()).unwrap();
|
||||
|
||||
// create object to hold item data
|
||||
let mut item_data = object! {
|
||||
title: item.title(),
|
||||
link: item.link(),
|
||||
pub_date: item.pub_date(),
|
||||
pub_ts: pub_datetime.timestamp(),
|
||||
description: item.description(),
|
||||
// author: item.author()
|
||||
};
|
||||
|
||||
// populate categories
|
||||
let mut categories = json::JsonValue::new_array();
|
||||
|
||||
for category in item.categories() {
|
||||
match categories.push(category.name()) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
// memory overflow ? as a beginner, style puzzled by rust
|
||||
error!("Error pushing to items_data {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item_data["categories"] = categories;
|
||||
|
||||
if item.content().is_some() {
|
||||
item_data["content"] = json::JsonValue::String(item.content().unwrap().to_string());
|
||||
}
|
||||
|
||||
match items_data.push(item_data) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
// memory overflow ? as a beginner, style puzzled by rust
|
||||
error!("Error pushing to items_data {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// attach the items to the json data root
|
||||
data["items"] = items_data;
|
||||
|
||||
// output result
|
||||
let output_string: String = if args.pretty {
|
||||
data.pretty(4)
|
||||
} else {
|
||||
data.dump()
|
||||
};
|
||||
|
||||
if args.output.len() > 0 {
|
||||
let output_length = output_string.len();
|
||||
let filename = args.output.to_string();
|
||||
match fs::write(filename, output_string) {
|
||||
Ok(_) => {
|
||||
info!("saving {} characters to {}", output_length, args.output);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("{:?}", e);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
// no file name specified, dump json to stdout
|
||||
println!("{}", output_string);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user