From d3a32fa776b2d22d68adf68615984fd9755bb249 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Sun, 27 Apr 2025 20:38:19 +0300 Subject: Add opml endpoint, more settings --- app/server.py | 38 ++++++++++++++++++++++++++++++++++++-- plugins/JsonApiSourcePlugin.py | 28 +++++++++++++++++++--------- 2 files changed, 55 insertions(+), 11 deletions(-) diff --git a/app/server.py b/app/server.py index 8e90dea..0d1becc 100644 --- a/app/server.py +++ b/app/server.py @@ -1,7 +1,7 @@ +import os from typing import Any, cast import bottle from tinydb import Query - from app.DatabaseManager import database_manager @@ -17,6 +17,10 @@ def feed_to_tr(feed: dict[str, str]) -> str: return f'{feed_id_to_td(feed["feed_id"])}{feed_last_build_date_to_td(feed.get("feed_last_build_date", ""))}' +def opml_to_tr() -> str: + return 'All feeds (OPML)' + + def feeds_to_table(feeds: list[dict[str, str]]) -> str: if len(feeds) == 0: return ( @@ -24,7 +28,7 @@ def feeds_to_table(feeds: list[dict[str, str]]) -> str: + "If you did that already, you might have to wait a bit for the data to propagate." ) - trs: list[str] = [feed_to_tr(feed) for feed in feeds] + trs: list[str] = [feed_to_tr(feed) for feed in feeds] + [opml_to_tr()] thead = f"FeedLast build date" tbody = f'{"".join(trs)}' return "" + thead + tbody + "
" @@ -114,6 +118,36 @@ def feed(feed_id: str): feed_xml: str = feed["feed_xml"] return feed_xml +@bottle.route("/opml") +def opml(): + if database_manager.db is None: + raise Exception("Database is not initialized") + + base_url = os.environ.get("AGGRO_BASE_URL", "http://localhost:8080") + + _feeds = database_manager.feeds.all() + feeds = cast(list[dict[str, str]], _feeds) + + bottle.response.set_header("content-type", "text/xml") + + outlines = "\n".join( + f'' + for feed in feeds + ) + + opml = f""" + + + Aggro Subscriptions + + +{outlines} + + +""" + return opml + + def run_web_server(host: str, port: int): bottle.run(host=host, port=port) diff --git a/plugins/JsonApiSourcePlugin.py b/plugins/JsonApiSourcePlugin.py index c799a05..b202349 100644 --- a/plugins/JsonApiSourcePlugin.py +++ b/plugins/JsonApiSourcePlugin.py @@ -12,7 +12,9 @@ class Plugin(PluginInterface): def __init__(self, id: str, params: Params) -> None: super().__init__("JsonApiSourcePlugin", id, params) self.url: str = get_config(params, "url").strip("/") - self.method: str = get_config_or_default(params, "method", "get").strip().tolower() + self.method: str = get_config_or_default(params, "method", "get").strip().lower() + self.body: str | None = get_config_or_default(params, "body", None) + self.headers: dict = get_config_or_default(params, "headers", {}) self.selector_post: str = get_config(params, "selector_post") self.selector_title: str | None = get_config_or_default( params, "selector_title", None @@ -55,14 +57,22 @@ class Plugin(PluginInterface): result_items: list[Item] = [] with requests.session() as session: fetch_fn = getattr(session, self.method) - api_resp = fetch_fn(self.url, allow_redirects=True) + body = ( + json.dumps(self.body) + if self.body and (type(self.body) is dict or type(self.body) is list) + else self.body + ) + api_resp = fetch_fn(self.url, allow_redirects=True, data=body, headers=self.headers) data = json.loads(api_resp.text) - post_items = eval(self.selector_post, {"data": data}) + + ctx = {"json": json, "data": data} + post_items = eval(self.selector_post, ctx) for post in post_items: + ctx = {"json": json, "post": post, "data": data} if self.selector_link: link = eval( - self.selector_link, {"post": post, "data": data} + self.selector_link, ctx ).strip() guid = ItemGUID(link, is_perma_link=True) else: @@ -71,28 +81,28 @@ class Plugin(PluginInterface): if self.selector_title: title = eval( - self.selector_title, {"post": post, "data": data} + self.selector_title, ctx ).strip() else: title = None if self.selector_description: description = eval( - self.selector_description, {"post": post, "data": data} + self.selector_description, ctx ).strip() else: description = None if self.selector_date: date = eval( - self.selector_date, {"post": post, "data": data} + self.selector_date, ctx ).strip() else: date = None if self.selector_author: author = eval( - self.selector_author, {"post": post, "data": data} + self.selector_author, ctx ).strip() else: author = None @@ -100,7 +110,7 @@ class Plugin(PluginInterface): if self.selector_image: try: image_src = eval( - self.selector_image, {"post": post, "data": data} + self.selector_image, ctx ).strip() except Exception: print_exc() -- cgit v1.3