summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--src/channel.rs4
-rw-r--r--src/config.rs15
-rw-r--r--src/main.rs39
4 files changed, 37 insertions, 22 deletions
diff --git a/.gitignore b/.gitignore
index 3b683d5..525274c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/target
rss-aggregator.toml
+subscriptions.txt
diff --git a/src/channel.rs b/src/channel.rs
index f4d4941..154382a 100644
--- a/src/channel.rs
+++ b/src/channel.rs
@@ -1,9 +1,9 @@
use chrono::Utc;
use rss::Channel;
-use crate::config::ChannelConfig;
+use crate::config::Config;
-pub fn make_new_empty_channel(config: ChannelConfig) -> Channel {
+pub fn make_new_empty_channel(config: Config) -> Channel {
Channel {
title: config.title,
link: config.link,
diff --git a/src/config.rs b/src/config.rs
index a5652c1..fa3dfba 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -5,13 +5,8 @@ use serde::Deserialize;
#[derive(Deserialize)]
pub struct Config {
+ pub subscriptions_path: Option<String>,
#[serde(default)]
- pub urls: Vec<String>,
- pub channel: ChannelConfig,
-}
-
-#[derive(Deserialize)]
-pub struct ChannelConfig {
pub title: String,
pub link: String,
pub description: String,
@@ -40,12 +35,12 @@ pub struct ChannelConfig {
pub fn default_config_file_locations() -> Vec<String> {
let mut default_config_file_locations = vec![
- String::from("/etc/rss-aggregator.toml"),
+ String::from("/etc/rss-aggregator/config.toml"),
];
let config_dir = dirs::config_dir()
.and_then(|config_dir| config_dir.into_string().ok());
if let Some(config_dir) = config_dir {
- default_config_file_locations.push(format!("{config_dir}/rss-aggregator.toml"));
+ default_config_file_locations.push(format!("{config_dir}/rss-aggregator/config.toml"));
};
default_config_file_locations
}
@@ -58,10 +53,10 @@ impl Config {
Ok(toml::from_str(&contents)?)
}
- pub fn find_config() -> Option<Config> {
+ pub fn find_config() -> Option<(Config, String)> {
for path in default_config_file_locations() {
if let Ok(config) = Self::parse_config_file_at_path(&path) {
- return Some(config);
+ return Some((config, path));
};
};
None
diff --git a/src/main.rs b/src/main.rs
index ced1391..387f1c9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,14 +2,14 @@ mod channel;
mod config;
mod retrieve;
-use std::future;
+use std::{fs::File, future, io::{BufRead, BufReader}, path::{Path, PathBuf}};
use anyhow::anyhow;
use clap::Parser;
use futures::{StreamExt, executor::block_on};
use rss::Channel;
-use crate::{channel::make_new_empty_channel, config::{ChannelConfig, Config}, retrieve::retrieve};
+use crate::{channel::make_new_empty_channel, config::Config, retrieve::retrieve};
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
@@ -21,22 +21,41 @@ struct Args {
fn main() {
let args = Args::parse();
- let config = load_config(&args.config_file).unwrap();
- let channel = generate_channel(config.urls, config.channel);
+ let (urls, config) = load_config(&args.config_file).unwrap();
+ let channel = generate_channel(urls, config);
let _ = channel.pretty_write_to(std::io::stdout(), b' ', 4).unwrap();
}
-fn load_config(config_file_arg: &str) -> anyhow::Result<Config> {
- match config_file_arg {
+fn load_config(config_file_arg: &str) -> anyhow::Result<(Vec<String>, Config)> {
+ let (config, config_path) = match config_file_arg {
"" => Config::find_config().ok_or_else(||
anyhow!("Failed to find config. Paths searched: {:#?}", config::default_config_file_locations())),
- path => Config::parse_config_file_at_path(path).map_err(|err|
+ path => Config::parse_config_file_at_path(path).map(|config| (config, String::from(path))).map_err(|err|
anyhow!("Failed to parse config at {}. Error: {}", path, err)),
- }
+ }?;
+
+ let subscriptions_path: PathBuf = config.subscriptions_path.as_ref()
+ .map(|p| Path::new(&p).to_path_buf())
+ .unwrap_or_else(
+ || Path::new(&config_path)
+ .parent()
+ .unwrap_or_else(|| Path::new("/"))
+ .join("subscriptions.txt"));
+ let urls: Vec<String> = if subscriptions_path.is_file() {
+ let subscriptions_file = File::open(subscriptions_path)?;
+ BufReader::new(subscriptions_file).lines()
+ .filter(|line| line.is_err() || line.as_ref().is_ok_and(|line|
+ line.trim().len() > 0 && !line.trim().starts_with("#")))
+ .collect::<Result<Vec<String>, std::io::Error>>()?
+ } else {
+ Vec::new()
+ };
+
+ Ok((urls, config))
}
-fn generate_channel(urls: Vec<String>, channel_config: ChannelConfig) -> Channel {
- let mut channel = make_new_empty_channel(channel_config);
+fn generate_channel(urls: Vec<String>, config: Config) -> Channel {
+ let mut channel = make_new_empty_channel(config);
block_on(async {
retrieve(urls.iter().map(AsRef::as_ref)).await.for_each(|c| {
channel.items.append(&mut c.into_items());