latest command is back, now with the ability to choose time back
Added command documentation in README
This commit is contained in:
GaMeNu 2023-10-12 01:10:59 +03:00
parent ba5b06faf2
commit fd5149fe5f
2 changed files with 103 additions and 3 deletions

View File

@ -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! 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. 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 \<time\> \<unit\> \[page\]
Get the latest alerts from up to a certain time back.
## Self-hosting ## Self-hosting
### Requirements ### Requirements
#### Required PyPI packages (run each with `pip install`) #### Required PyPI packages (run each with `pip install`)

View File

@ -9,8 +9,6 @@ from discord.ext import commands, tasks
from discord import app_commands from discord import app_commands
import logging import logging
import db_access
from db_access import DBAccess from db_access import DBAccess
from markdown import md from markdown import md
@ -21,6 +19,11 @@ AUTHOR_ID = int(os.getenv('AUTHOR_ID'))
class AlertReqs: class AlertReqs:
@staticmethod @staticmethod
def request_alert_json() -> dict | None: 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={ req = requests.get('https://www.oref.org.il/WarningMessages/alert/alerts.json', headers={
'Referer': 'https://www.oref.org.il/', 'Referer': 'https://www.oref.org.il/',
'X-Requested-With': 'XMLHttpRequest', 'X-Requested-With': 'XMLHttpRequest',
@ -37,7 +40,12 @@ class AlertReqs:
return ret_dict return ret_dict
@staticmethod @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) req = requests.get('https://www.oref.org.il/WarningMessages/History/AlertsHistory.json', timeout=5)
content = req.text content = req.text
@ -276,6 +284,87 @@ class Notificator(commands.Cog):
return return
await self.attempt_unregistration(intr, self.db.get_channel(intr.user.id)) 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(f'Page {page_number + 1} (re-run the command to change page)\n\n' + 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}'
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') @app_commands.command(name='about', description='Info about the bot')
async def about_bot(self, intr: discord.Interaction): async def about_bot(self, intr: discord.Interaction):
e = discord.Embed(color=discord.Color.orange()) e = discord.Embed(color=discord.Color.orange())