From 727d7af2069271f53edd258b798f8f560bb86e53 Mon Sep 17 00:00:00 2001 From: GaMeNu <98153342+GaMeNu@users.noreply.github.com> Date: Thu, 12 Oct 2023 01:10:59 +0300 Subject: [PATCH] v2.1.0 latest command is back, now with the ability to choose time back Added command documentation in README --- README.md | 11 ++++++ cog_notificator.py | 95 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 103 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5ce70b5..fd53c5e 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,17 @@ Invite the bot to a server, and /register a channel, and you're ready to go! Alternatively, you can DM the bot to receive alerts directly to your DMs! Please do note that the bot instance listed here is hosted on a private machine, and may be a bit slow. + +## Command documentation +### /about +Get some info about the bot +### /register +Run in a channel to register it to receive alerts +### /unregister +Run in a registered channel to stop it from receiving alerts +### /latest \ \ \[page\] +Get the latest alerts from up to a certain time back. + ## Self-hosting ### Requirements #### Required PyPI packages (run each with `pip install`) diff --git a/cog_notificator.py b/cog_notificator.py index 1aaff0e..352a9cc 100644 --- a/cog_notificator.py +++ b/cog_notificator.py @@ -9,8 +9,6 @@ from discord.ext import commands, tasks from discord import app_commands import logging - -import db_access from db_access import DBAccess from markdown import md @@ -21,6 +19,11 @@ AUTHOR_ID = int(os.getenv('AUTHOR_ID')) class AlertReqs: @staticmethod def request_alert_json() -> dict | None: + """ + Request a json of the current running alert + :return: JSON object as Python dict, or None if there's no alert running + :raises requests.exceptions.Timeout: If request times out (5 seconds) + """ req = requests.get('https://www.oref.org.il/WarningMessages/alert/alerts.json', headers={ 'Referer': 'https://www.oref.org.il/', 'X-Requested-With': 'XMLHttpRequest', @@ -37,7 +40,12 @@ class AlertReqs: return ret_dict @staticmethod - def request_history_json() -> dict | None: + def request_history_json() -> dict: + """ + Request a json of the alert history from last day + :return: JSON object as Python dict + :raises requests.exceptions.Timeout: If request times out (5 seconds) + """ req = requests.get('https://www.oref.org.il/WarningMessages/History/AlertsHistory.json', timeout=5) content = req.text @@ -276,6 +284,87 @@ class Notificator(commands.Cog): return await self.attempt_unregistration(intr, self.db.get_channel(intr.user.id)) + @app_commands.command(name='latest', + description='Get all alerts up to a certain time back (may be slightly outdated)') + async def latest_alerts(self, intr: discord.Interaction, time: int, unit: str, page: int = 1): + units = ['h', 'hours', 'm', 'minutes', 's', 'seconds'] + if unit not in units: + await intr.response.send_message(f'Invalid time unit, please use one of the following:\n' + f'{", ".join(units)}') + return + time_s = time + if unit in ['h', 'hours']: + time_s *= 3600 + elif unit in ['m', 'minutes']: + time_s *= 60 + + if time_s > 86400: + await intr.response.send_message('You can currently only view history up to 1 day back.\n' + f'Please use the {md.u(md.hl("Home Front Command Website", "https://www.oref.org.il/"))} to view alerts further back') + return + + page_number = page - 1 + alert_count = 20 + + try: + history_page = Notificator.get_alert_history_page(time_s, page_number, alert_count) + except requests.exceptions.Timeout: + await intr.response.send_message('Request timed out.') + return + except ValueError: + await intr.response.send_message('Page number is too high.') + return + + if history_page == '': + history_page = 'No results found.' + + view = self.hfc_button_view() + await intr.response.send_message(history_page, + view=view) + + @staticmethod + def get_alert_history_page(time_back: int, page_number: int, alerts_in_page: int) -> str: + alert_history = AlertReqs.request_history_json() + + current_time = datetime.datetime.now() + time_back = datetime.timedelta(seconds=time_back) + + alert_counter = 0 + + for alert in alert_history: + # This can be merged with the other loop to optimize performance. + # Especially considering Python is a slow language. + # Too bad! + alert_date = datetime.datetime.strptime(alert["alertDate"], "%Y-%m-%d %H:%M:%S") + + if abs(current_time - alert_date) > time_back: + break + + alert_counter += 1 + + max_page = alert_counter // alerts_in_page + + if alert_counter % alerts_in_page != 0: + max_page += 1 + + if page_number > max_page: + raise ValueError("Page number out of range") + + ret_str = f'Page {page_number + 1}/{alert_counter//alerts_in_page + 1}\n\n' + for alert in alert_history[(page_number * alerts_in_page):((page_number + 1) * alerts_in_page)]: + alert_date = datetime.datetime.strptime(alert["alertDate"], "%Y-%m-%d %H:%M:%S") + + if abs(current_time - alert_date) > time_back: + break + + ret_str += f'התראה ב{md.b(alert["data"])}\n' \ + f'{md.u(alert["title"])}\n' \ + f'בשעה {alert["alertDate"]}\n\n' + + + + return ret_str + @app_commands.command(name='about', description='Info about the bot') async def about_bot(self, intr: discord.Interaction): e = discord.Embed(color=discord.Color.orange())