Merge branch 'report' into 'main'
Clean up output See merge request kernald/reddit-magnet!8
This commit is contained in:
commit
90c3fc5ee3
7 changed files with 224 additions and 77 deletions
38
Cargo.lock
generated
38
Cargo.lock
generated
|
|
@ -91,6 +91,17 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic"
|
||||
version = "0.6.0"
|
||||
|
|
@ -282,6 +293,19 @@ version = "1.0.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"unicode-width",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
|
|
@ -439,6 +463,12 @@ version = "1.15.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.35"
|
||||
|
|
@ -1496,10 +1526,12 @@ dependencies = [
|
|||
name = "reddit-magnet"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"clap",
|
||||
"clap-verbosity-flag",
|
||||
"color-eyre",
|
||||
"console",
|
||||
"diesel",
|
||||
"diesel_migrations",
|
||||
"directories",
|
||||
|
|
@ -2281,6 +2313,12 @@ version = "1.0.18"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
|
|
|
|||
|
|
@ -27,3 +27,5 @@ transmission-rpc = "0.5.0"
|
|||
url = "2.5.4"
|
||||
clap-verbosity-flag = "3.0.2"
|
||||
pretty_env_logger = "0.5.0"
|
||||
async-trait = "0.1.77"
|
||||
console = "0.15.8"
|
||||
|
|
|
|||
22
src/actions/action.rs
Normal file
22
src/actions/action.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
use crate::models::Magnet;
|
||||
use async_trait::async_trait;
|
||||
use color_eyre::eyre::Result;
|
||||
|
||||
/// Struct to hold the list of processed and failed magnets
|
||||
pub struct ProcessedMagnets {
|
||||
pub success: Vec<Magnet>,
|
||||
pub failed: Vec<Magnet>,
|
||||
}
|
||||
|
||||
/// Trait for actions that process magnet links
|
||||
#[async_trait]
|
||||
pub trait Action {
|
||||
/// Return the name of the action
|
||||
fn name(&self) -> &str;
|
||||
|
||||
/// Process all unprocessed magnet links and return the list of processed magnets
|
||||
async fn process_unprocessed_magnets(
|
||||
&mut self,
|
||||
db: &mut crate::db::Database,
|
||||
) -> Result<ProcessedMagnets>;
|
||||
}
|
||||
|
|
@ -1 +1,2 @@
|
|||
pub mod action;
|
||||
pub mod transmission;
|
||||
|
|
|
|||
|
|
@ -1,51 +1,63 @@
|
|||
use crate::actions::action::{Action, ProcessedMagnets};
|
||||
use crate::actions::transmission::client::TransmissionClient;
|
||||
use crate::actions::transmission::config::TransmissionConfig;
|
||||
use crate::db::{Database, TransmissionProcessedTable};
|
||||
use color_eyre::eyre::Result;
|
||||
use log::{debug, info, warn};
|
||||
use log::{debug, warn};
|
||||
|
||||
/// Action for submitting magnet links to Transmission
|
||||
pub struct TransmissionAction {
|
||||
client: TransmissionClient,
|
||||
db: Database,
|
||||
}
|
||||
|
||||
impl TransmissionAction {
|
||||
pub async fn new(config: &TransmissionConfig, db: Database) -> Result<Self> {
|
||||
pub async fn new(config: &TransmissionConfig) -> Result<Self> {
|
||||
let client = TransmissionClient::new(config)?;
|
||||
|
||||
Ok(TransmissionAction { client, db })
|
||||
Ok(TransmissionAction { client })
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl Action for TransmissionAction {
|
||||
/// Return the name of the action
|
||||
fn name(&self) -> &str {
|
||||
"Transmission"
|
||||
}
|
||||
|
||||
/// Process all unprocessed magnet links
|
||||
pub async fn process_unprocessed_magnets(&mut self) -> Result<usize> {
|
||||
let unprocessed_magnets = self
|
||||
.db
|
||||
.get_unprocessed_magnets_for_table::<TransmissionProcessedTable>()?;
|
||||
let mut processed_count = 0;
|
||||
/// Process all unprocessed magnet links and return the list of processed magnets
|
||||
async fn process_unprocessed_magnets(&mut self, db: &mut Database) -> Result<ProcessedMagnets> {
|
||||
let unprocessed_magnets =
|
||||
db.get_unprocessed_magnets_for_table::<TransmissionProcessedTable>()?;
|
||||
let mut processed_magnets = Vec::new();
|
||||
let mut failed_magnets = Vec::new();
|
||||
|
||||
for magnet in unprocessed_magnets {
|
||||
if let Some(id) = magnet.id {
|
||||
match self.client.submit_magnet(&magnet.link).await {
|
||||
Ok(_) => {
|
||||
info!(
|
||||
debug!(
|
||||
"Successfully submitted magnet link to Transmission: {}",
|
||||
magnet.title
|
||||
);
|
||||
debug!("Magnet link: {}", magnet.link);
|
||||
self.db
|
||||
.mark_magnet_processed_for_table::<TransmissionProcessedTable>(id)?;
|
||||
processed_count += 1;
|
||||
db.mark_magnet_processed_for_table::<TransmissionProcessedTable>(id)?;
|
||||
processed_magnets.push(magnet);
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to submit magnet link to Transmission: {}", e);
|
||||
failed_magnets.push(magnet);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!("Skipping magnet with null ID: {}", magnet.link);
|
||||
// Consider adding to failed_magnets if we want to report these as well
|
||||
}
|
||||
}
|
||||
|
||||
Ok(processed_count)
|
||||
Ok(ProcessedMagnets {
|
||||
success: processed_magnets,
|
||||
failed: failed_magnets,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
115
src/main.rs
115
src/main.rs
|
|
@ -1,3 +1,4 @@
|
|||
use crate::actions::action::Action;
|
||||
use crate::actions::transmission::TransmissionAction;
|
||||
use crate::args::Args;
|
||||
use crate::config::{get_db_path, load_config};
|
||||
|
|
@ -10,7 +11,7 @@ use log::{debug, info, warn};
|
|||
use multimap::MultiMap;
|
||||
use reddit_client::RedditClient;
|
||||
use regex::Regex;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs::create_dir_all;
|
||||
|
||||
mod actions;
|
||||
|
|
@ -20,6 +21,7 @@ mod db;
|
|||
mod magnet;
|
||||
mod models;
|
||||
mod reddit_client;
|
||||
mod report;
|
||||
mod schema;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -39,43 +41,6 @@ fn filter_posts(title: &str, title_filter: Option<Regex>) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
/// Prints the posts with their magnet links
|
||||
fn print_posts(posts: &[PostInfo], username: &str, title_filter: Option<Regex>) -> usize {
|
||||
println!("Magnet links from u/{}:", username);
|
||||
if let Some(pattern) = title_filter {
|
||||
println!("Filtering titles by pattern: {}", pattern);
|
||||
}
|
||||
println!("----------------------------");
|
||||
|
||||
let mut post_count = 0;
|
||||
|
||||
for post in posts {
|
||||
// Only display posts with magnet links
|
||||
if !post.magnet_links.is_empty() {
|
||||
post_count += 1;
|
||||
|
||||
println!(
|
||||
"{}. [r/{}] {} (Posted: {})",
|
||||
post_count,
|
||||
post.subreddit,
|
||||
post.title,
|
||||
post.timestamp.format("%Y-%m-%d %H:%M:%S")
|
||||
);
|
||||
|
||||
for (i, link) in post.magnet_links.iter().enumerate() {
|
||||
println!(" Link {}: {}", i + 1, link);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
if post_count == 0 {
|
||||
println!("No posts with magnet links found.");
|
||||
}
|
||||
|
||||
post_count
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
color_eyre::install()?;
|
||||
|
|
@ -117,8 +82,9 @@ async fn main() -> Result<()> {
|
|||
}
|
||||
|
||||
// Process sources and store magnet links
|
||||
let mut total_new_links = 0;
|
||||
for (source_name, source_config) in conf.sources {
|
||||
println!("\nProcessing source [{}]", source_name);
|
||||
info!("Processing source [{}]", source_name);
|
||||
|
||||
let username = source_config.username.clone();
|
||||
let title_filter = match source_config.title_filter {
|
||||
|
|
@ -130,8 +96,6 @@ async fn main() -> Result<()> {
|
|||
};
|
||||
|
||||
if let Some(submissions) = user_posts.get_vec(&username) {
|
||||
let mut filtered_posts = Vec::new();
|
||||
|
||||
for post in submissions
|
||||
.iter()
|
||||
.filter(|s| filter_posts(&*s.title, title_filter.clone()))
|
||||
|
|
@ -151,36 +115,30 @@ async fn main() -> Result<()> {
|
|||
};
|
||||
|
||||
// Store the post info in the database
|
||||
if let Err(e) = db.store_magnets(&post_info) {
|
||||
warn!("Failed to store post info in database: {}", e);
|
||||
}
|
||||
|
||||
filtered_posts.push(post_info);
|
||||
}
|
||||
}
|
||||
|
||||
print_posts(&filtered_posts, &username, title_filter);
|
||||
}
|
||||
}
|
||||
|
||||
// Process magnet links with Transmission if enabled
|
||||
if let Some(transmission_config) = conf.transmission {
|
||||
if transmission_config.enable {
|
||||
info!("Processing magnet links with Transmission");
|
||||
match TransmissionAction::new(&transmission_config, db).await {
|
||||
Ok(mut transmission_action) => {
|
||||
match transmission_action.process_unprocessed_magnets().await {
|
||||
match db.store_magnets(&post_info) {
|
||||
Ok(count) => {
|
||||
info!(
|
||||
"Successfully processed {} magnet links with Transmission",
|
||||
count
|
||||
);
|
||||
total_new_links += count;
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to process magnet links with Transmission: {}", e);
|
||||
warn!("Failed to store post info in database: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize actions
|
||||
let mut actions: Vec<Box<dyn Action>> = Vec::new();
|
||||
|
||||
// Add Transmission action if enabled
|
||||
if let Some(transmission_config) = conf.transmission {
|
||||
if transmission_config.enable {
|
||||
info!("Initializing Transmission action");
|
||||
match TransmissionAction::new(&transmission_config).await {
|
||||
Ok(transmission_action) => {
|
||||
actions.push(Box::new(transmission_action));
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to initialize Transmission action: {}", e);
|
||||
}
|
||||
|
|
@ -192,5 +150,32 @@ async fn main() -> Result<()> {
|
|||
debug!("No Transmission configuration found");
|
||||
}
|
||||
|
||||
// Process all actions and collect results
|
||||
let mut action_results = HashMap::new();
|
||||
|
||||
for action in &mut actions {
|
||||
let action_name = action.name().to_string();
|
||||
debug!("Processing magnet links with {} action", action_name);
|
||||
|
||||
match action.process_unprocessed_magnets(&mut db).await {
|
||||
Ok(processed_magnets) => {
|
||||
let count = processed_magnets.success.len();
|
||||
debug!(
|
||||
"Successfully processed {} magnet links with {}",
|
||||
count, action_name
|
||||
);
|
||||
action_results.insert(action_name, processed_magnets);
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to process magnet links with {}: {}", action_name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate report
|
||||
if let Err(e) = report::generate_report(&action_results, total_new_links) {
|
||||
warn!("Failed to generate report: {}", e);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
87
src/report.rs
Normal file
87
src/report.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
use crate::actions::action::ProcessedMagnets;
|
||||
use color_eyre::eyre::Result;
|
||||
use console::{style, Emoji};
|
||||
use log::info;
|
||||
use std::collections::HashMap;
|
||||
|
||||
static SPARKLES: Emoji = Emoji("✨", ":sparkles:");
|
||||
static ROCKET: Emoji = Emoji("🚀", ":rocket:");
|
||||
static LINK: Emoji = Emoji("🔗", ":link:");
|
||||
static WARNING: Emoji = Emoji("⚠️", ":warning:");
|
||||
|
||||
/// Generate a report of processed magnets
|
||||
pub fn generate_report(
|
||||
action_results: &HashMap<String, ProcessedMagnets>,
|
||||
total_new_links: usize,
|
||||
) -> Result<()> {
|
||||
info!("");
|
||||
info!(
|
||||
"{} {} {}",
|
||||
SPARKLES,
|
||||
style("Report Summary").bold().underlined(),
|
||||
style(format!(
|
||||
"{} new links added to the database",
|
||||
total_new_links
|
||||
))
|
||||
.bold()
|
||||
.green(),
|
||||
);
|
||||
info!("");
|
||||
|
||||
for (action_name, processed_magnets) in action_results {
|
||||
let success_count = processed_magnets.success.len();
|
||||
let failed_count = processed_magnets.failed.len();
|
||||
let total_count = success_count + failed_count;
|
||||
|
||||
// Section header for each action
|
||||
info!("");
|
||||
info!(
|
||||
"{} {} {}",
|
||||
ROCKET,
|
||||
style(format!("{}", action_name)).bold().underlined().cyan(),
|
||||
style(format!("({} new links)", total_count)).bold()
|
||||
);
|
||||
|
||||
// Success/failure summary
|
||||
if failed_count > 0 {
|
||||
info!(
|
||||
" {} Success: {}, {} Failure: {}",
|
||||
style("✅").green(),
|
||||
style(success_count).bold().green(),
|
||||
style("❌").red(),
|
||||
style(failed_count).bold().red()
|
||||
);
|
||||
} else {
|
||||
info!(
|
||||
" {} Success: {}",
|
||||
style("✅").green(),
|
||||
style(success_count).bold().green()
|
||||
);
|
||||
}
|
||||
info!("");
|
||||
|
||||
// List successful magnets
|
||||
if success_count > 0 {
|
||||
info!(
|
||||
" {} {}",
|
||||
style("✅").green(),
|
||||
style("Added:").bold().green()
|
||||
);
|
||||
for magnet in &processed_magnets.success {
|
||||
info!(" {} {}", LINK, style(&magnet.title).italic());
|
||||
}
|
||||
info!("");
|
||||
}
|
||||
|
||||
// List failed magnets
|
||||
if failed_count > 0 {
|
||||
info!(" {} {}", style("❌").red(), style("Failed:").bold().red());
|
||||
for magnet in &processed_magnets.failed {
|
||||
info!(" {} {}", WARNING, style(&magnet.title).italic());
|
||||
}
|
||||
info!("");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue