Skip to content

Commit 8da7d27

Browse files
committed
Switch from fastfeedparser to feedparser
Sadly fastfeedparser doesn't collect an id for each entry, and since an entry's link is optional, we don't always have enough info to create a new entry, since we need the entry id to create a valid Atom feed.
1 parent b4d07fa commit 8da7d27

File tree

5 files changed

+49
-221
lines changed

5 files changed

+49
-221
lines changed

example/uv.lock

Lines changed: 15 additions & 70 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "django-rss-filter"
3-
version = "0.1.0"
3+
version = "0.2.0"
44
description = "Filter public RSS feeds, remove articles that contain certain keywords or categories."
55
authors = [
66
{name = "Kevin Renskers", email = "[email protected]"},
@@ -12,8 +12,8 @@ keywords = ["rss", "atom", "feed", "filter", "mute", "django"]
1212
requires-python = ">=3.9"
1313
dependencies = [
1414
"django>=3.2.0",
15-
"fastfeedparser>=0.3.7",
1615
"feedgen>=1.0.0",
16+
"feedparser>=6.0.11",
1717
"httpx>=0.28.1",
1818
]
1919

@@ -26,7 +26,7 @@ dev = [
2626
]
2727

2828
[project.urls]
29-
Homepage = "https://github.com/loopwerk/django-rss-filter/issues"
29+
Homepage = "https://github.com/loopwerk/django-rss-filter/"
3030
Repository = "https://github.com/loopwerk/django-rss-filter.git"
3131
Issues = "https://github.com/loopwerk/django-rss-filter/issues"
3232

rssfilter/utils.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
import fastfeedparser
1+
import feedparser
22
from feedgen.feed import FeedGenerator
33

44

55
def validate_feed(feed_url: str) -> bool:
66
try:
7-
fastfeedparser.parse(feed_url)
7+
feedparser.parse(feed_url)
88
return True
99
except ValueError:
1010
return False
1111

1212

1313
def filter_feed(feed_body: str, filtered_words: str, filtered_categories: str) -> str:
14-
feed = fastfeedparser.parse(feed_body)
14+
feed = feedparser.parse(feed_body)
1515

1616
fg = FeedGenerator()
17-
fg.id(feed.feed.link)
17+
fg.id(feed.feed.get("id", feed.feed.link))
1818
fg.title(feed.feed.title)
1919
fg.link(href=feed.feed.link)
2020
fg.description(feed.feed.get("description", "Filtered feed"))
@@ -32,12 +32,12 @@ def filter_feed(feed_body: str, filtered_words: str, filtered_categories: str) -
3232

3333
# Check if the categories/terms contain filtered categories
3434
if len(filtered_categories_list) and hasattr(entry, "tags"):
35-
terms = [tag["term"].lower() for tag in entry.tags]
35+
terms = [tag.term.lower() for tag in entry.tags]
3636
if any(filtered_category in term for term in terms for filtered_category in filtered_categories_list):
3737
continue
3838

3939
fe = fg.add_entry()
40-
fe.id(entry.link)
40+
fe.id(entry.get("id", entry.link))
4141
fe.title(entry.title)
4242
fe.link(href=entry.link)
4343
fe.description(entry.get("description", ""))

tests/test_utils.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import fastfeedparser
1+
import feedparser
22
from django.test import TestCase
33

44
from rssfilter.utils import filter_feed
@@ -37,40 +37,40 @@
3737
class UtilsTest(TestCase):
3838
def test_filter_words(self):
3939
filtered_feed_body = filter_feed(body, filtered_words="One", filtered_categories="")
40-
filtered_feed = fastfeedparser.parse(filtered_feed_body)
40+
filtered_feed = feedparser.parse(filtered_feed_body)
4141

4242
self.assertEqual(len(filtered_feed.entries), 1)
4343
self.assertEqual(filtered_feed.entries[0].title, "Article Two")
4444

4545
def test_filter_words_case_insenstive(self):
4646
filtered_feed_body = filter_feed(body, filtered_words="ONE", filtered_categories="")
47-
filtered_feed = fastfeedparser.parse(filtered_feed_body)
47+
filtered_feed = feedparser.parse(filtered_feed_body)
4848

4949
self.assertEqual(len(filtered_feed.entries), 1)
5050
self.assertEqual(filtered_feed.entries[0].title, "Article Two")
5151

5252
def test_filter_words_empty(self):
5353
filtered_feed_body = filter_feed(body, filtered_words="", filtered_categories="")
54-
filtered_feed = fastfeedparser.parse(filtered_feed_body)
54+
filtered_feed = feedparser.parse(filtered_feed_body)
5555

5656
self.assertEqual(len(filtered_feed.entries), 2)
5757

5858
def test_filter_words_not_found(self):
5959
filtered_feed_body = filter_feed(body, filtered_words="Foo", filtered_categories="")
60-
filtered_feed = fastfeedparser.parse(filtered_feed_body)
60+
filtered_feed = feedparser.parse(filtered_feed_body)
6161

6262
self.assertEqual(len(filtered_feed.entries), 2)
6363

6464
def test_filter_words_comma_seperated(self):
6565
filtered_feed_body = filter_feed(body, filtered_words="Foo, Bar, One", filtered_categories="")
66-
filtered_feed = fastfeedparser.parse(filtered_feed_body)
66+
filtered_feed = feedparser.parse(filtered_feed_body)
6767

6868
self.assertEqual(len(filtered_feed.entries), 1)
6969
self.assertEqual(filtered_feed.entries[0].title, "Article Two")
7070

7171
def test_filter_categories(self):
7272
filtered_feed_body = filter_feed(body, filtered_words="", filtered_categories="Category Four")
73-
filtered_feed = fastfeedparser.parse(filtered_feed_body)
73+
filtered_feed = feedparser.parse(filtered_feed_body)
7474

7575
self.assertEqual(len(filtered_feed.entries), 1)
7676
self.assertEqual(filtered_feed.entries[0].title, "Article One")

0 commit comments

Comments
 (0)