From fe162849f574449307d62ec8850c3b90a14cf7ad Mon Sep 17 00:00:00 2001 From: Leo Qin Date: Sat, 28 Sep 2024 17:43:36 -0700 Subject: [PATCH 1/3] feat: add delete feed --- app/app.py | 11 +++++++++++ app/backend.py | 11 +++++++++++ app/context.py | 18 +++++++++++++++++- app/storage/lmdb.py | 30 ++++++++++++++++++++++++++++++ app/storage/tinydb.py | 19 +++++++++++++++++++ app/templates/feed_config.html | 13 +++++++++++-- 6 files changed, 99 insertions(+), 3 deletions(-) diff --git a/app/app.py b/app/app.py index c737871..53176ae 100644 --- a/app/app.py +++ b/app/app.py @@ -268,6 +268,17 @@ async def refresh_feed(feed_id: str, request: Request): ) +@app.get("/api/delete_feed/{feed_id}", status_code=status.HTTP_200_OK) +async def delete_feed(feed_id: str, request: Request): + + await bk.delete_feed(feed_id=feed_id) + + return RedirectResponse( + request.url_for("feeds"), + status_code=status.HTTP_303_SEE_OTHER, + ) + + @app.post("/api/update_settings/", status_code=status.HTTP_200_OK) async def update_settings( theme: Annotated[str, Form()], diff --git a/app/backend.py b/app/backend.py index fe40a67..0257ca0 100644 --- a/app/backend.py +++ b/app/backend.py @@ -202,6 +202,17 @@ async def update_handler(self, handler: str, config: str): handler_obj = self.db.reconfigure_handler(id=handler, config=config_dict) self.db.upsert_handler(handler=handler_obj) + async def delete_feed(self, feed_id: str): + + feed = self.db.get_feed(id=feed_id) + + entries = self.db.get_entries(feed=feed) + for entry_dict in entries: + entry: FeedEntry = entry_dict.get("entry") + self.db.delete_feed_entry(feed_entry=entry) + + self.db.delete_feed(feed=feed) + @staticmethod async def list_content_handler_choices(): from app.content import content_retrieval_handlers diff --git a/app/context.py b/app/context.py index df1fc86..30c02cd 100644 --- a/app/context.py +++ b/app/context.py @@ -184,7 +184,9 @@ def upsert_feed_entry(self, feed: Feed, entry: FeedEntry) -> None: pass @abstractmethod - def get_entries(self, feed: Feed = None, after: int = 0) -> List[Mapping[str, str]]: + def get_entries( + self, feed: Feed = None, after: int = 0 + ) -> List[Mapping[str, FeedEntry]]: """ Given a feed, retrieve the entries for that feed and return a list of dicts, where each dict has key entry = FeedEntry object, feed_id = the @@ -273,6 +275,20 @@ def upsert_settings(self, settings: GlobalSettings) -> None: """ pass + @abstractmethod + def delete_feed(self, feed: Feed) -> None: + """ + Given a feed, delete the feed from the database. + """ + pass + + @abstractmethod + def delete_feed_entry(self, feed_entry: FeedEntry) -> None: + """ + Given a feed entry, delete the entry from the database. + """ + pass + @staticmethod async def get_entry_html(url: str, settings: GlobalSettings) -> str: return await settings.content_retrieval_handler.get_content(url) diff --git a/app/storage/lmdb.py b/app/storage/lmdb.py index 2b1617a..321cb17 100644 --- a/app/storage/lmdb.py +++ b/app/storage/lmdb.py @@ -306,3 +306,33 @@ def upsert_settings(self, settings: GlobalSettings) -> None: self.upsert_handler(settings.notification_handler) self.upsert_handler(settings.summarization_handler) self.upsert_handler(settings.content_retrieval_handler) + + def delete_feed(self, feed: Feed) -> None: + + with self.db.begin(db=self._db(Named.feed), write=True) as txn: + txn.delete(self._serialize(feed.id)) + + with self.db.begin(db=self._db(Named.si_feed_entry), write=True) as txn: + txn.delete(self._serialize(feed.id)) + + with self.db.begin(db=self._db(Named.poll), write=True) as txn: + txn.delete(self._serialize(feed.id)) + + with self.db.begin(db=self._db(Named.feed_start), write=True) as txn: + txn.delete(self._serialize(feed.id)) + + def delete_feed_entry(self, feed_entry: FeedEntry) -> None: + + with self.db.begin(db=self._db(Named.entry_content), write=True) as txn: + txn.delete(self._serialize(feed_entry.id)) + + with self.db.begin(db=self._db(Named.entry), write=True) as txn: + txn.delete(self._serialize(feed_entry.id)) + + with self.db.begin(db=self._db(Named.si_feed_entry), write=True) as txn: + value = txn.get(self._serialize(feed_entry.feed_id)) + + entries: List[str] = self._deserialize(value) + entries.remove(feed_entry.id) + + txn.replace(self._serialize(feed_entry.feed_id), self._serialize(entries)) diff --git a/app/storage/tinydb.py b/app/storage/tinydb.py index a0f6e46..a672d98 100644 --- a/app/storage/tinydb.py +++ b/app/storage/tinydb.py @@ -248,3 +248,22 @@ def upsert_settings(self, settings: GlobalSettings) -> None: self.upsert_handler(settings.notification_handler) self.upsert_handler(settings.summarization_handler) self.upsert_handler(settings.content_retrieval_handler) + + def delete_feed(self, feed: Feed) -> None: + feeds = self.db.table("feeds") + query = Query().id.matches(feed.id) + feeds.remove(query) + + feed_start = self.db.table("feed_start") + feed_start.remove(query) + + poll = self.db.table("poll") + poll.remove(query) + + def delete_feed_entry(self, feed_entry: FeedEntry) -> None: + entry_contents = self.db.table("entry_contents") + query = Query().id.matches(feed_entry.id) + entry_contents.remove(query) + + entries = self.db.table("entries") + entries.remove(query) diff --git a/app/templates/feed_config.html b/app/templates/feed_config.html index db7c840..d6771ee 100644 --- a/app/templates/feed_config.html +++ b/app/templates/feed_config.html @@ -81,7 +81,7 @@