Compare commits

..

No commits in common. "main" and "v0.0.2" have entirely different histories.
main ... v0.0.2

13 changed files with 279 additions and 422 deletions

1
.github/CODEOWNERS vendored Normal file
View file

@ -0,0 +1 @@
* @troylusty

10
.github/dependabot.yml vendored Normal file
View file

@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "weekly"
groups:
dev-dependencies:
patterns:
- "*"

28
.github/workflows/rust.yml vendored Normal file
View file

@ -0,0 +1,28 @@
name: Rust
on:
push:
tags:
- "v*.*.*"
env:
CARGO_TERM_COLOR: always
BIN_NAME: target/release/packard
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build release
run: cargo build --release
- name: Upload release assets
uses: softprops/action-gh-release@v2
with:
files: ${{ env.BIN_NAME }}

587
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,22 +1,21 @@
[package] [package]
name = "packard" name = "packard"
version = "0.0.4" version = "0.0.2"
edition = "2021" edition = "2021"
description = "A terminal based feed checker." description = "A terminal based feed checker."
authors = ["Troy Lusty <hello@troylusty.com>"] authors = ["Troy Lusty <hello@troylusty.com>"]
[dependencies] [dependencies]
chrono = "0.4.41" chrono = "0.4.39"
clap = { version = "4.5.37", features = ["derive"] } clap = { version = "4.5.26", features = ["derive"] }
reqwest = "0.12.15" reqwest = "0.12.12"
rss = "2.0.12" rss = "2.0.11"
serde = { version = "1.0.219", features = ["derive"] } serde = { version = "1.0.217", features = ["derive"] }
tokio = { version = "1.44.2", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] }
toml = "0.8.22" toml = "0.8.19"
xdg = "2.5.2" xdg = "2.5.2"
futures = "0.3.31" futures = "0.3.31"
indicatif = "0.17.11" indicatif = "0.17.9"
anyhow = "1.0.98"
[profile.dev] [profile.dev]
opt-level = 0 opt-level = 0

View file

@ -1,10 +1,10 @@
<div align="center"> <div align="center">
<h1>️📰 Packard</h1> <h1>️📰 Packard</h1>
<img alt="Release" src="https://img.shields.io/gitea/v/release/troy/packard?gitea_url=https%3A%2F%2Fcode.threepop.com"> <img alt="GitHub Release" src="https://img.shields.io/github/v/release/troylusty/packard">
<h5>Packard is a simple RSS aggregator meant to allow you to take a quick glance at what's occurring in topics you care about.</h5> <h5>Packard is a simple RSS aggregator meant to allow you to take a quick glance at what's occurring in topics you care about.</h5>
</div> </div>
![Demo](demo/demo.gif) ![Demo](https://github.com/user-attachments/assets/17f228c7-a931-4988-a1c0-8cc7190d4349)
This is my first attempt at making something with Rust so that I may learn alongside creating something that I personally find useful. This is my first attempt at making something with Rust so that I may learn alongside creating something that I personally find useful.
@ -14,17 +14,17 @@ On NixOS you can install Packard by including it as an input in flake.nix, then
```nix ```nix
inputs = { inputs = {
packard.url = "git+https://code.threepop.com/troy/packard"; packard.url = "github:troylusty/packard";
}; };
```
... ```nix
environment.systemPackages = { environment.systemPackages = {
inputs.packard.packages."${pkgs.system}".default inputs.packard.packages."${pkgs.system}".default
}; };
``` ```
Alternatively, the [latest release](https://github.com/threepop/packard/releases/latest) binary is available. Alternatively, [the latest release](https://github.com/troylusty/packard/releases/latest) binary is available.
## Configuration ## Configuration

View file

@ -8,12 +8,11 @@ Set Width 1200
Set Height 600 Set Height 600
Type@250ms "packard" Sleep 500ms Type@250ms "packard" Sleep 500ms
Hide Type " -c 48 -l news" Show Sleep 500ms Type@150ms " -c 48 -l news | less" Sleep 500ms Enter
Type@200ms " | less" Sleep 500ms Enter
Sleep 3s Sleep 3s
PageDown@50ms 1 PageDown@50ms 1
Sleep 1s Sleep 1s
PageDown@50ms 2 PageDown@50ms 2
Sleep 1s Sleep 2s
PageUp@50ms 3 PageUp@50ms 3
Sleep 3s Sleep 3s

Binary file not shown.

Before

Width:  |  Height:  |  Size: 761 KiB

View file

@ -6,6 +6,5 @@ pkgs.mkShell {
rustfmt rustfmt
pkg-config pkg-config
openssl openssl
cargo-edit
]; ];
} }

View file

@ -2,6 +2,7 @@ use clap::Parser;
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap; use std::collections::HashMap;
use std::fs; use std::fs;
use toml;
use xdg::BaseDirectories; use xdg::BaseDirectories;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]

View file

@ -1,9 +1,9 @@
use anyhow::{Context, Result};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use futures::future::join_all; use futures::future::join_all;
use indicatif::ProgressBar; use indicatif::ProgressBar;
use reqwest::get; use reqwest::get;
use rss::Channel; use rss::Channel;
use std::error::Error;
#[derive(Debug)] #[derive(Debug)]
pub struct FeedItem { pub struct FeedItem {
@ -13,14 +13,9 @@ pub struct FeedItem {
pub pub_date: DateTime<Utc>, pub pub_date: DateTime<Utc>,
} }
async fn fetch_rss(url: &str, pb: &ProgressBar) -> Result<Channel> { async fn fetch_rss(url: &str, pb: &ProgressBar) -> Result<Channel, Box<dyn Error>> {
let response = get(url) let response = get(url).await?.text().await?;
.await let channel = Channel::read_from(response.as_bytes())?;
.context("Failed to send request")?
.text()
.await
.context("Failed to read response text")?;
let channel = Channel::read_from(response.as_bytes()).context("Failed to parse RSS feed")?;
pb.inc(1); pb.inc(1);
pb.set_message(format!("Processing: {}", channel.title)); pb.set_message(format!("Processing: {}", channel.title));
Ok(channel) Ok(channel)

View file

@ -1,12 +1,13 @@
use indicatif::ProgressStyle; use indicatif::ProgressStyle;
use tokio::io; use std::error::Error;
use tokio;
mod config; mod config;
mod data; mod data;
mod utils; mod utils;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), io::Error> { async fn main() -> Result<(), Box<dyn Error>> {
let config = config::validate_config(); let config = config::validate_config();
let args = config::parse_cli(); let args = config::parse_cli();
let (count, skip_amount, list) = config::collate_values(args, &config); let (count, skip_amount, list) = config::collate_values(args, &config);
@ -27,7 +28,7 @@ async fn main() -> Result<(), io::Error> {
"\x1b[1m>\x1b[0m \x1b[1;32m\x1b]8;;{}\x1b\\{}\x1b]8;;\x1b\\\x1b[0m\n\x1b[3m\x1b[2m{}\x1b[0m\n\x1b[2m{}\x1b[0m\n", "\x1b[1m>\x1b[0m \x1b[1;32m\x1b]8;;{}\x1b\\{}\x1b]8;;\x1b\\\x1b[0m\n\x1b[3m\x1b[2m{}\x1b[0m\n\x1b[2m{}\x1b[0m\n",
item.link, item.link,
item.title, item.title,
utils::trim_chars(&utils::remove_html_tags(&item.description)), utils::trim_chars(&item.description),
item.pub_date.to_string() item.pub_date.to_string()
); );
} }

View file

@ -7,20 +7,3 @@ pub fn trim_chars(input: &str) -> String {
trimmed trimmed
} }
} }
pub fn remove_html_tags(input: &str) -> String {
let mut result = String::new();
let mut in_tag = false;
for c in input.chars() {
if c == '<' {
in_tag = true;
} else if c == '>' {
in_tag = false;
} else if !in_tag {
result.push(c);
}
}
result
}