commit - 8dfc8f4385acc8f20be89b62b21ddace47f07a1d
commit + e0de93c7136c4b0ea0e9885640d2f98085c796d8
blob - ee0dc16a5a9427974f2c81517b1e874260651970
blob + 34633867977ba8c80b45abcb331e3405e9914966
--- README.md
+++ README.md
# rss-email
-Fetch new RSS feed items and send them via E-Mail.
+Fetch new RSS (and Atom) feed items and send them via E-Mail.
## Compiling
## Usage
-- Copy the `config.example.toml` to `~/rss-email/config.toml` and adjust the
-values
-- Create a `urls` file at `~/rss-email/urls` with one RSS url per line
+- Copy the `config.example.toml` to `~/.config/rss-email/config.toml` and adjust
+ the values
+- Create a `urls` file at `~/.config/rss-email/urls` with one RSS url per line
The database used with `rss-email` is generated automatically if it doesn't exist
yet
blob - /dev/null
blob + dc3bd979c4d2a457e33b12b87887ad7d2156482b (mode 644)
--- /dev/null
+++ migrations/20221203144155_remove_feedurl_author.down.sql
+ALTER TABLE posts ADD feedurl TEXT;
+ALTER TABLE posts ADD author TEXT;
blob - /dev/null
blob + 621ff1c27ae9af4c57e6a28191cc25bee82b01a6 (mode 644)
--- /dev/null
+++ migrations/20221203144155_remove_feedurl_author.up.sql
+ALTER TABLE posts DROP feedurl;
+ALTER TABLE posts DROP author;
blob - a3e0f555be2decc8fea2ed8ec3eedbfd660b13ce
blob + 780b448bbd3b5418e9d7e0db9205d275b8801a74
--- sqlx-data.json
+++ sqlx-data.json
},
"query": "update posts set sent = true where guid = ?"
},
- "322f282b6b0068d8f6091daf4b0835d28df627d2ef6e4b5dd2979004f00f248a": {
- "describe": {
- "columns": [],
- "nullable": [],
- "parameters": {
- "Right": 7
- }
- },
- "query": "insert or ignore into posts (guid, title, author, url, feedurl, pub_date, content) values (?, ?, ?, ?, ?, ?, ?)"
- },
"9955438bce6b0c7cd1c7896a6fdf0b7b58390a5d996ba7cef003bd4b3052353d": {
"describe": {
"columns": [
"type_info": "Text"
},
{
- "name": "author",
- "ordinal": 2,
- "type_info": "Text"
- },
- {
"name": "url",
- "ordinal": 3,
+ "ordinal": 2,
"type_info": "Text"
},
{
- "name": "feedurl",
- "ordinal": 4,
- "type_info": "Text"
- },
- {
"name": "pub_date",
- "ordinal": 5,
+ "ordinal": 3,
"type_info": "Int64"
},
{
"name": "content",
- "ordinal": 6,
+ "ordinal": 4,
"type_info": "Text"
},
{
"name": "sent",
- "ordinal": 7,
+ "ordinal": 5,
"type_info": "Bool"
}
],
true,
true,
true,
- true,
- true,
false
],
"parameters": {
}
},
"query": "select * from posts where sent != true order by pub_date desc"
+ },
+ "e8c193917469a0ee24db731dd5ccef549b01e97eb3d05deb46706bd702b587fc": {
+ "describe": {
+ "columns": [],
+ "nullable": [],
+ "parameters": {
+ "Right": 5
+ }
+ },
+ "query": "insert or ignore into posts (guid, title, url, pub_date, content) values (?, ?, ?, ?, ?)"
}
}
\ No newline at end of file
blob - b88fcb6c9489d9dddd0b323d934be7405fbe7aef
blob + 9f52e514434f9041afc4835bbec81a22f118280c
--- src/db.rs
+++ src/db.rs
// inserts a new post or updates an old one with the same guid
pub async fn insert_item(mut conn: PoolConnection<Sqlite>, post: &Post) -> anyhow::Result<()> {
- sqlx::query!("insert or ignore into posts (guid, title, author, url, feedurl, pub_date, content) values (?, ?, ?, ?, ?, ?, ?)", post.guid, post.title, post.author, post.url, post.feedurl, post.pub_date, post.content).execute(&mut conn).await?;
+ sqlx::query!(
+ "insert or ignore into posts (guid, title, url, pub_date, content) values (?, ?, ?, ?, ?)",
+ post.guid,
+ post.title,
+ post.url,
+ post.pub_date,
+ post.content
+ )
+ .execute(&mut conn)
+ .await?;
Ok(())
}
blob - 04ca37d43fdb48afb55a0e25d1162ab1ebb2c02f
blob + 6b9fc15c737a4c11fd765fb3267a921c74ad404e
--- src/models.rs
+++ src/models.rs
pub struct Post {
pub guid: String,
pub title: Option<String>,
- pub author: Option<String>,
pub url: Option<String>,
- pub feedurl: Option<String>,
pub pub_date: Option<i64>,
pub content: Option<String>,
pub sent: bool,
.value()
.to_string();
let title = item.title().map(String::from);
- let author = item.author().map(String::from);
let url = item.link().map(String::from);
- let feedurl = item.source().map(|s| String::from(s.url()));
let pub_date = time;
let content = item
.content()
Ok(Self {
guid,
title,
- author,
url,
- feedurl,
pub_date,
content,
sent: false,
impl TryFrom<atom_syndication::Entry> for Post {
type Error = anyhow::Error;
- fn try_from(mut value: atom_syndication::Entry) -> Result<Self, Self::Error> {
+ fn try_from(value: atom_syndication::Entry) -> Result<Self, Self::Error> {
let guid = value.id.clone();
let title = Some(value.title.value);
- // TODO: could be multiple authors (or none) - needs a database migration
- let author = if !value.authors.is_empty() {
- Some(value.authors.remove(0).name)
- } else {
- None
- };
let url = Some(value.id);
- // TODO: either remove feedurl from Post or find a way to supply it here
- let feedurl = None;
let pub_date = value.published.map(|p| p.timestamp());
let content = if let Some(c) = value.content {
c.value
Ok(Self {
guid,
title,
- author,
url,
- feedurl,
pub_date,
content,
sent: false,