Move update_feed and add_feed to own function, and create set_hook_by_name

This commit is contained in:
2022-12-05 11:15:53 +01:00
parent 3cb38f8714
commit 551644de5e
3 changed files with 154 additions and 36 deletions

View File

@ -1,4 +1,7 @@
from discord_webhook import DiscordWebhook from discord_webhook import DiscordWebhook
from pydantic import BaseModel
from reader import FeedExistsError, FeedNotFoundError, InvalidFeedURLError, ParseError, StorageError
from requests import Response
from discord_rss_bot.settings import logger, reader from discord_rss_bot.settings import logger, reader
@ -7,28 +10,118 @@ def check_feeds() -> None:
"""Check all feeds""" """Check all feeds"""
reader.update_feeds() reader.update_feeds()
entries = reader.get_entries(read=False) entries = reader.get_entries(read=False)
_check_feed(entries) send_to_discord(entries)
def check_feed(feed_url: str) -> None: def check_feed(feed_url: str) -> None:
"""Check a single feed""" """Check a single feed"""
reader.update_feeds() reader.update_feeds()
entry = reader.get_entries(feed=feed_url, read=False) entry = reader.get_entries(feed=feed_url, read=False)
_check_feed(entry) send_to_discord(entry)
def _check_feed(entries) -> None: class NoWebhookFoundError(Exception):
for entry in entries: """No webhook found error."""
reader.mark_entry_as_read(entry)
logger.debug(f"New entry: {entry.title}")
webhook_url = reader.get_tag(entry.feed.url, "webhook") def __init__(self, message):
if webhook_url: self.message = message
logger.debug(f"Sending to webhook: {webhook_url}")
webhook = DiscordWebhook(url=str(webhook_url), content=f":robot: :mega: New entry: {entry.title}\n" def __str__(self):
f"{entry.link}", rate_limit_retry=True) return self.message
response = webhook.execute()
if not response.ok:
# TODO: Send error to discord def send_to_discord(entry) -> Response:
logger.error(f"Error: {response.status_code} {response.reason}") """
reader.mark_entry_as_unread(entry) Send entries to Discord.
Args:
entry: The entry to send.
Returns:
Response: The response from the webhook.
"""
reader.mark_entry_as_read(entry)
logger.debug(f"New entry: {entry.title}")
webhook_url = reader.get_tag(entry.feed.url, "webhook")
if not webhook_url:
logger.error(f"No webhook found for feed: {entry.feed.url}")
raise NoWebhookFoundError(f"No webhook found for feed: {entry.feed.url}")
logger.debug(f"Sending to webhook: {webhook_url}")
webhook = DiscordWebhook(url=str(webhook_url), content=f":robot: :mega: New entry: {entry.title}\n"
f"{entry.link}", rate_limit_retry=True)
response = webhook.execute()
if not response.ok:
# TODO: Send error to discord
logger.error(f"Error: {response.status_code} {response.reason}")
reader.mark_entry_as_unread(entry)
return response
class IfFeedError(BaseModel):
"""Update a feed."""
feed_url: str
webhook: str
error: bool
err_msg: str = ""
exception: str = ""
def update_feed(feed_url: str, webhook: str) -> IfFeedError:
"""
Update a feed.
Args:
feed_url: The feed to update.
webhook: The webhook to use.
Returns:
IfFeedError: Error or not.
"""
try:
reader.update_feed(feed_url)
except FeedNotFoundError as error:
error_msg = "Feed not found"
logger.error(error_msg, exc_info=True)
return IfFeedError(error=True, err_msg=error_msg, feed_url=feed_url, webhook=webhook, exception=error.message)
except ParseError as error:
error_msg = "An error occurred while getting/parsing feed"
logger.error(error_msg, exc_info=True)
return IfFeedError(error=True, err_msg=error_msg, feed_url=feed_url, webhook=webhook, exception=error.message)
except StorageError as error:
error_msg = "An exception was raised by the underlying storage"
logger.error(error_msg, exc_info=True)
return IfFeedError(error=True, err_msg=error_msg, feed_url=feed_url, webhook=webhook, exception=error.message)
return IfFeedError(error=False, feed_url=feed_url, webhook=webhook)
def add_feed(feed_url: str, webhook: str, exist_ok=False, allow_invalid_url=False) -> IfFeedError:
"""
Add a feed.
Args:
feed_url: The feed to add.
webhook: The webhook to use.
exist_ok: If the feed already exists, do nothing.
allow_invalid_url: If the feed url is invalid, add it anyway.
Returns:
IfFeedError: Error or not.
"""
try:
reader.add_feed(feed=feed_url, exist_ok=exist_ok, allow_invalid_url=allow_invalid_url)
except FeedExistsError as error:
error_msg = "Feed already exists"
logger.error(f"{error_msg}: {error}")
return IfFeedError(error=True, err_msg=error_msg, feed_url=feed_url, webhook=webhook, exception=error.message)
except InvalidFeedURLError as error:
error_msg = "Invalid feed URL"
logger.error(f"{error_msg}: {error}")
return IfFeedError(error=True, err_msg=error_msg, feed_url=feed_url, webhook=webhook, exception=error.message)

View File

@ -4,13 +4,14 @@ from functools import cache
import uvicorn import uvicorn
from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.schedulers.background import BackgroundScheduler
from fastapi import FastAPI, Form, Request from fastapi import FastAPI, Form, HTTPException, Request
from fastapi.responses import FileResponse, HTMLResponse from fastapi.responses import FileResponse, HTMLResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from reader import FeedExistsError from reader import ResourceNotFoundError
from discord_rss_bot.feeds import _check_feed from discord_rss_bot.feeds import add_feed, send_to_discord, update_feed
from discord_rss_bot.settings import logger, read_settings_file, reader from discord_rss_bot.settings import logger, read_settings_file, reader
from discord_rss_bot.webhooks import set_hook_by_name
app = FastAPI() app = FastAPI()
templates = Jinja2Templates(directory="templates") templates = Jinja2Templates(directory="templates")
@ -28,7 +29,7 @@ def check_feed(request: Request, feed_url: str = Form()):
"""Check all feeds""" """Check all feeds"""
reader.update_feeds() reader.update_feeds()
entry = reader.get_entries(feed=feed_url, read=False) entry = reader.get_entries(feed=feed_url, read=False)
_check_feed(entry) send_to_discord(entry)
logger.info(f"Get feed: {feed_url}") logger.info(f"Get feed: {feed_url}")
feed = reader.get_feed(feed_url) feed = reader.get_feed(feed_url)
@ -149,13 +150,6 @@ def create_list_of_webhooks():
return enum.Enum("DiscordWebhooks", list_of_webhooks) return enum.Enum("DiscordWebhooks", list_of_webhooks)
def get_hook_by_name(name):
"""Get a webhook by name."""
settings = read_settings_file()
logger.debug(f"Webhook name: {name} with URL: {settings['webhooks'][name]}")
return settings["webhooks"][name]
@app.post("/add") @app.post("/add")
async def create_feed(feed_url: str = Form(), webhook_dropdown: str = Form()): async def create_feed(feed_url: str = Form(), webhook_dropdown: str = Form()):
""" """
@ -170,18 +164,25 @@ async def create_feed(feed_url: str = Form(), webhook_dropdown: str = Form()):
""" """
logger.info(f"Add feed: {feed_url}") logger.info(f"Add feed: {feed_url}")
logger.info(f"Webhook: {webhook_dropdown}") logger.info(f"Webhook: {webhook_dropdown}")
try:
reader.add_feed(feed_url) # Update a single feed. The feed will be updated even if updates are disabled for it.
except FeedExistsError as error: updated_feed = update_feed(feed_url, webhook_dropdown)
logger.error(f"Feed already exists: {error}")
return {"error": "Feed already exists."} # Add a new feed to the database.
reader.update_feed(feed_url) added_feed = add_feed(feed_url, webhook_dropdown)
webhook_url = get_hook_by_name(webhook_dropdown)
reader.set_tag(feed_url, "webhook", webhook_url) if updated_feed.error or added_feed.error:
error_dict = {"error": updated_feed.error, "feed": updated_feed.feed_url, "webhook": updated_feed.webhook,
"exception": updated_feed.exception}
return HTTPException(status_code=500, detail=error_dict)
# Check if set_hook_by_name() was successful.
if isinstance(set_hook_by_name(name=webhook_dropdown, feed_url=feed_url), ResourceNotFoundError):
return set_hook_by_name(name=webhook_dropdown, feed_url=feed_url)
new_tag = reader.get_tag(feed_url, "webhook") new_tag = reader.get_tag(feed_url, "webhook")
logger.info(f"New tag: {new_tag}") logger.info(f"New tag: {new_tag}")
return {"feed_url": str(feed_url), "status": "added", "webhook": webhook_url} return {"feed_url": str(feed_url), "status": "added"}
@app.get("/add", response_class=HTMLResponse) @app.get("/add", response_class=HTMLResponse)

View File

@ -0,0 +1,24 @@
from fastapi import HTTPException
from reader import ResourceNotFoundError
from discord_rss_bot.settings import logger, read_settings_file, reader
def set_hook_by_name(name: str, feed_url: str) -> None or HTTPException:
"""Set a webhook by name.
Args:
name: The name of the webhook.
feed_url: The feed to set the webhook for.
Returns:
HTTPException: The HTTP exception if the webhook was not found, otherwise None.
"""
settings = read_settings_file()
logger.debug(f"Webhook name: {name} with URL: {settings['webhooks'][name]}")
webhook_url = settings["webhooks"][name]
try:
reader.set_tag(feed_url, "webhook", webhook_url)
except ResourceNotFoundError as e:
logger.error(f"ResourceNotFoundError: {e}")
return HTTPException(status_code=500, detail=f"ResourceNotFoundError: Could not set webhook: {e}")