separate modules into different files
This commit is contained in:
parent
5a9338f64d
commit
28d59a4c7a
4 changed files with 117 additions and 102 deletions
107
src/main.rs
107
src/main.rs
|
@ -1,86 +1,10 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use clap::Parser;
|
||||
use futures::future::join_all;
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
use reqwest::get;
|
||||
use rss::Channel;
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use indicatif::ProgressStyle;
|
||||
use std::error::Error;
|
||||
use std::fs;
|
||||
use terminal_link::Link;
|
||||
use tokio;
|
||||
use toml;
|
||||
use xdg::BaseDirectories;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Cli {
|
||||
#[arg(short, long)]
|
||||
verbose: bool,
|
||||
#[arg(short, long)]
|
||||
count: Option<u8>,
|
||||
#[arg(short = 'l', long)]
|
||||
selected_list: Option<String>,
|
||||
#[arg(short, long)]
|
||||
skip_amount: Option<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Config {
|
||||
count: Option<u8>,
|
||||
skip_amount: Option<u8>,
|
||||
selected_list: Option<String>,
|
||||
lists: HashMap<String, Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FeedItem {
|
||||
title: String,
|
||||
description: String,
|
||||
link: String,
|
||||
pub_date: DateTime<Utc>,
|
||||
}
|
||||
|
||||
async fn fetch_rss(url: &str, pb: &ProgressBar) -> Result<Channel, Box<dyn Error>> {
|
||||
let response = get(url).await?.text().await?;
|
||||
let channel = Channel::read_from(response.as_bytes())?;
|
||||
pb.inc(1);
|
||||
pb.set_message(format!("Processing: {}", channel.title));
|
||||
Ok(channel)
|
||||
}
|
||||
|
||||
fn parse_feed(channel: &Channel) -> Vec<FeedItem> {
|
||||
channel
|
||||
.items()
|
||||
.iter()
|
||||
.map(|item| FeedItem {
|
||||
title: item.title().unwrap_or("No title").to_string(),
|
||||
description: item.description().unwrap_or("No description").to_string(),
|
||||
link: item.link().unwrap_or("No link").to_string(),
|
||||
pub_date: item
|
||||
.pub_date()
|
||||
.and_then(|date_str| DateTime::parse_from_rfc2822(date_str).ok())
|
||||
.map(|dt| dt.with_timezone(&Utc))
|
||||
.unwrap_or_else(|| Utc::now()),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn validate_config() -> Config {
|
||||
let xdg_dirs = BaseDirectories::new().expect("Failed to get XDG directories");
|
||||
let config_path = xdg_dirs
|
||||
.place_config_file("packard/config.toml")
|
||||
.expect("Failed to determine config file path");
|
||||
|
||||
if !config_path.exists() {
|
||||
eprintln!("Configuration file not found at {:?}", config_path);
|
||||
}
|
||||
|
||||
let config_content = fs::read_to_string(&config_path).expect("Failed to read config file");
|
||||
let config: Config = toml::de::from_str(&config_content).expect("Failed to parse TOML");
|
||||
config
|
||||
}
|
||||
mod config;
|
||||
mod data;
|
||||
|
||||
fn trim_chars(input: &str) -> String {
|
||||
let trimmed: String = input.chars().take(256).collect();
|
||||
|
@ -92,29 +16,10 @@ fn trim_chars(input: &str) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
async fn run_tasks(sources: Vec<String>, count: u8, skip: u8, pb: &ProgressBar) -> Vec<FeedItem> {
|
||||
let fetch_futures: Vec<_> = sources.iter().map(|url| fetch_rss(url, &pb)).collect();
|
||||
|
||||
let channels = join_all(fetch_futures).await;
|
||||
|
||||
let mut all_items = Vec::new();
|
||||
|
||||
for channel in channels.into_iter().filter_map(Result::ok) {
|
||||
let feed_items = parse_feed(&channel);
|
||||
all_items.extend(feed_items);
|
||||
}
|
||||
|
||||
all_items.sort_by(|a, b| b.pub_date.cmp(&a.pub_date));
|
||||
all_items.truncate((count + skip).into());
|
||||
let removed_items = all_items.split_off(skip.into());
|
||||
|
||||
removed_items
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
let config = validate_config();
|
||||
let args = Cli::parse();
|
||||
let config = config::validate_config();
|
||||
let args = config::parse_cli();
|
||||
|
||||
if args.verbose {
|
||||
println!("{:?}", args);
|
||||
|
@ -157,7 +62,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||
ProgressStyle::with_template("[{elapsed}] {bar:40.green/black} {msg}").unwrap(),
|
||||
);
|
||||
|
||||
let all_items = run_tasks(values.to_vec(), count, skip_amount, &pb).await;
|
||||
let all_items = data::run_tasks(values.to_vec(), count, skip_amount, &pb).await;
|
||||
pb.finish_and_clear();
|
||||
|
||||
for item in all_items {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue