Skip to content

Commit

Permalink
do i look like i know what a monad is
Browse files Browse the repository at this point in the history
A new error handling strategy has been introduced in main.rs. Instead of checking and logging errors in each step, errors are now handled using a Result type and custom ApplicationError enum. The new enum is defined in models.rs, having variants for different types of errors including fetching, parsing, first run skipping, and no new items detection. This reduces code repetition and improves readability as complex error handling scenarios are abstracted away into error variants.
  • Loading branch information
danitrap committed Jan 1, 2024
1 parent c82f9a3 commit d204bc2
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 45 deletions.
83 changes: 38 additions & 45 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mod utils;
use broadcast::send_telegram_message;
use client::fetch_hacker_news;
use config::Config;
use models::{HackerNews, HnItem};
use models::{ApplicationError, ApplicationError::*, HackerNews, HnItem};
use rss::Channel;
use simple_logger::SimpleLogger;
use tokio::time::{interval, Duration};
Expand All @@ -34,57 +34,50 @@ async fn main() {

log::info!("Fetching Hacker News");

let content = fetch_hacker_news().await;

let channel = match content {
Ok(c) => Channel::read_from(&c[..]),
Err(e) => {
log::error!("Error fetching Hacker News: {:?}", e);
continue;
}
};

let items = match channel {
Err(err) => {
log::error!("Error parsing RSS: {:?}", err);
continue;
}
Ok(channel) => channel
.items()
.iter()
.filter_map(
|item| match (item.title(), item.description(), item.guid()) {
(Some(title), Some(description), Some(guid)) => Some(HnItem::new(
title.to_string(),
description.to_string(),
guid.value.to_string(),
)),
_ => None,
},
)
.collect::<Vec<_>>(),
};

let new_items = hacker_news.whats_new(items);

if first_run {
first_run = false;
log::info!("Skipping first run");
continue;
}
let items: Result<_, ApplicationError> = fetch_hacker_news()
.await
.map_err(|_| Fetching)
.and_then(|res| Channel::read_from(&res[..]).map_err(|_| Parsing))
.map(|channel| {
channel
.items()
.iter()
.filter_map(
|item| match (item.title(), item.description(), item.guid()) {
(Some(title), Some(description), Some(guid)) => Some(HnItem::new(
title.to_string(),
description.to_string(),
guid.value.to_string(),
)),
_ => None,
},
)
.collect::<Vec<_>>()
})
.and_then(|items| hacker_news.whats_new(items).ok_or(NoNewItems))
.and_then(|items| {
if first_run {
Err(SkippingFirstRun)
} else {
Ok(items)
}
});

match new_items {
None => {
log::info!("No new items");
continue;
match items {
Err(Fetching) => log::error!("Error fetching Hacker News"),
Err(Parsing) => log::error!("Error parsing RSS"),
Err(SkippingFirstRun) => {
log::info!("Skipping first run");
first_run = false;
}
Some(items) => {
Err(NoNewItems) => log::info!("No new items"),
Ok(items) => {
log::info!("Sending {} new items to Telegram", items.len());
for item in items {
let message = format!("{}", item);
send_telegram_message(&config, message).await;
}
}
}
};
}
}
7 changes: 7 additions & 0 deletions src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ use std::fmt;
use std::hash::{Hash, Hasher};
use std::rc::Rc;

pub enum ApplicationError {
Fetching,
Parsing,
SkippingFirstRun,
NoNewItems,
}

#[derive(Clone, Debug)]
pub struct HnItem {
pub title: String,
Expand Down

0 comments on commit d204bc2

Please sign in to comment.