mirror of
https://github.com/GaMeNu/HFCNotificator.git
synced 2024-11-16 15:24:51 +02:00
v2.2.2
Major under-the-hood optimizations to alert pushing!
This commit is contained in:
parent
989d749615
commit
44caa0a2f1
@ -1,5 +1,6 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
import datetime
|
import datetime
|
||||||
|
from typing import Self
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
@ -67,29 +68,76 @@ class Alert:
|
|||||||
self.districts = districts
|
self.districts = districts
|
||||||
self.description = desc
|
self.description = desc
|
||||||
|
|
||||||
@staticmethod
|
@classmethod
|
||||||
def from_dict(data: dict):
|
def from_dict(cls, data: dict):
|
||||||
return Alert(int(data.get('id', '0')),
|
return cls(int(data.get('id', '0')),
|
||||||
int(data.get('cat', '0')),
|
int(data.get('cat', '0')),
|
||||||
data.get('title'),
|
data.get('title'),
|
||||||
data.get('data'),
|
data.get('data'),
|
||||||
data.get('desc'))
|
data.get('desc'))
|
||||||
|
|
||||||
|
|
||||||
class AlertEmbed:
|
class AlertEmbed:
|
||||||
|
|
||||||
def __init__(self, district: db_access.District, description: str):
|
def __init__(self, alert: Alert | dict, district: db_access.District | str):
|
||||||
|
"""
|
||||||
|
Initiating the AlertEmbed class directly is equivalent to AlertEmbed.generic_alert, but is not recommended.
|
||||||
|
|
||||||
|
Please use AlertEmbed.generic_alert instead.
|
||||||
|
"""
|
||||||
self.embed = discord.Embed(color=discord.Color.from_str('#FF0000'))
|
self.embed = discord.Embed(color=discord.Color.from_str('#FF0000'))
|
||||||
self.district = district
|
self.district = district
|
||||||
|
if isinstance(alert, dict):
|
||||||
|
self.alert = Alert.from_dict(alert)
|
||||||
|
else:
|
||||||
|
self.alert = alert
|
||||||
|
|
||||||
self.embed.title = f'התראה ב{district}'
|
self.embed.title = f'התראה ב{self.district}'
|
||||||
self.embed.add_field(name='נכון ל', value=datetime.datetime.now().strftime("%H:%M:%S\n%d/%m/%Y"), inline=False)
|
self.embed.add_field(name='נכון ל', value=datetime.datetime.now().strftime("%H:%M:%S\n%d/%m/%Y"), inline=False)
|
||||||
self.embed.add_field(name='מידע נוסף', value=description)
|
self.embed.add_field(name='מידע נוסף', value=self.alert.description)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generic_alert(cls, alert: Alert | dict, district: db_access.District | str) -> Self:
|
||||||
|
ret_alem = cls(alert, district)
|
||||||
|
return ret_alem
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def missile_alert(cls, alert: Alert | dict, district: db_access.District | str) -> Self:
|
||||||
|
ret_alem = cls.generic_alert(alert, district)
|
||||||
|
|
||||||
|
if (not isinstance(district, str)) and (district.migun_time is not None):
|
||||||
|
ret_alem.embed.set_field_at(index=1, name='זמן מיגון', value=f'{district.migun_time} שניות', inline=False)
|
||||||
|
return ret_alem
|
||||||
|
|
||||||
|
ret_alem.embed.set_field_at(index=1, name='זמן מיגון', value='שגיאה באחזרת המידע', inline=False)
|
||||||
|
return ret_alem
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def auto_alert(cls, alert: Alert | dict, district: db_access.District | str) -> Self:
|
||||||
|
"""
|
||||||
|
Tired of having to CHOOSE an alert type all the time? Well this is JUST for you!
|
||||||
|
|
||||||
|
Introducing... auto_alert! Just init it like any other alert, and it will return the fitting alert right then and there*!
|
||||||
|
|
||||||
|
*"then and there" does not include any computer, end-user, developer, or any other type of tomfoolery.
|
||||||
|
|
||||||
|
(Hopefully now I'll never have to write documentation again >:) )
|
||||||
|
|
||||||
|
:param alert: Alert object or alert dict.
|
||||||
|
:param district: District object (from db_access)
|
||||||
|
:return: AlertEmbed object
|
||||||
|
"""
|
||||||
|
if isinstance(alert, dict):
|
||||||
|
alert_obj = Alert.from_dict(alert)
|
||||||
|
else:
|
||||||
|
alert_obj = alert
|
||||||
|
|
||||||
|
match alert_obj.category:
|
||||||
|
case 1:
|
||||||
|
return cls.missile_alert(alert_obj, district)
|
||||||
|
case _:
|
||||||
|
return cls.generic_alert(alert_obj, district)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def generic_alert(district: db_access.District, description: str):
|
|
||||||
ret_alem = AlertEmbed(district, description)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -241,39 +289,6 @@ class Notificator(commands.Cog):
|
|||||||
if not self.check_for_updates.is_running():
|
if not self.check_for_updates.is_running():
|
||||||
self.check_for_updates.start()
|
self.check_for_updates.start()
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def generate_alert_embed(alert_object: Alert, district: str, arrival_time: int | None, time: str,
|
|
||||||
lang: str, district_id: int) -> DistrictEmbedTemp:
|
|
||||||
|
|
||||||
"""
|
|
||||||
Generate alert embed
|
|
||||||
:param alert_object: Alert content
|
|
||||||
:param district: District alert
|
|
||||||
:param arrival_time: Time to get to a safe space
|
|
||||||
:param time: Alert Time
|
|
||||||
:param lang: Alert language
|
|
||||||
:param district_id: IDK what this param doing; Me neither LOL
|
|
||||||
:return: Alert embed for current alert
|
|
||||||
"""
|
|
||||||
# TODO: fix tha param description
|
|
||||||
# TODO: fix this entire function
|
|
||||||
# TODO: Using 1 generate alert function is probably bad, should probably split into a utility class
|
|
||||||
e = DistrictEmbedTemp(district_id=district_id, color=discord.Color.from_str('#FF0000'))
|
|
||||||
e.title = f'התראה ב{district}'
|
|
||||||
e.add_field(name=district, value=alert_object.title, inline=False)
|
|
||||||
match alert_object.category:
|
|
||||||
case 1:
|
|
||||||
if arrival_time is not None:
|
|
||||||
e.add_field(name='זמן מיגון', value=f'{arrival_time} שניות', inline=False)
|
|
||||||
else:
|
|
||||||
e.add_field(name='זמן מיגון', value='שגיאה באחזרת המידע', inline=False)
|
|
||||||
|
|
||||||
case _:
|
|
||||||
pass
|
|
||||||
e.add_field(name='נכון ל', value=time, inline=False)
|
|
||||||
e.add_field(name='מידע נוסף', value=alert_object.description)
|
|
||||||
return e
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def hfc_button_view() -> discord.ui.View:
|
def hfc_button_view() -> discord.ui.View:
|
||||||
button = discord.ui.Button(
|
button = discord.ui.Button(
|
||||||
@ -292,44 +307,17 @@ class Notificator(commands.Cog):
|
|||||||
:param new_districts: Currently active districts (districts that were not already active)
|
:param new_districts: Currently active districts (districts that were not already active)
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
try:
|
|
||||||
alert_history = AlertReqs.request_history_json()[0:100]
|
|
||||||
except requests.exceptions.Timeout as error:
|
|
||||||
self.log.error(f'Request timed out: {error}')
|
|
||||||
alert_history = None
|
|
||||||
self.log.info(f'Sending alerts to channels')
|
self.log.info(f'Sending alerts to channels')
|
||||||
|
|
||||||
embed_ls: list[DistrictEmbedTemp] = []
|
embed_ls: list[AlertEmbed] = []
|
||||||
|
|
||||||
new_alert = Alert.from_dict(alert_data)
|
|
||||||
|
|
||||||
for district in new_districts:
|
for district in new_districts:
|
||||||
district_data = self.db.get_district_by_name(district) # DB
|
district_data = self.db.get_district_by_name(district)
|
||||||
alert_time = datetime.datetime.now() # .strftime()
|
|
||||||
|
|
||||||
# TODO: THIS REQUIRES SIMPLIFICATION ASAP
|
|
||||||
if alert_history is not None:
|
|
||||||
for alert in alert_history:
|
|
||||||
if alert["data"] == district:
|
|
||||||
new_time = datetime.datetime.strptime(alert["alertDate"], "%Y-%m-%d %H:%M:%S")
|
|
||||||
time_diff = abs(alert_time - new_time)
|
|
||||||
# Check if new time is withing 5 minutes
|
|
||||||
if time_diff <= datetime.timedelta(minutes=1):
|
|
||||||
# We have a match. Assign and stop looking
|
|
||||||
alert_time = new_time
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
alert_time = datetime.datetime.now()
|
|
||||||
|
|
||||||
# it's not within 5 minutes, keep looking.
|
|
||||||
# DF Code ruined me, and now I overuse break and continue.
|
|
||||||
|
|
||||||
alert_time_str = alert_time.strftime("%H:%M:%S\n%d/%m/%Y")
|
|
||||||
if district_data is not None:
|
if district_data is not None:
|
||||||
embed_ls.append(Notificator.generate_alert_embed(new_alert, district, district_data.migun_time,
|
embed_ls.append(AlertEmbed.auto_alert(alert_data, district_data))
|
||||||
alert_time_str, 'he', district_data.district_id))
|
|
||||||
else:
|
else:
|
||||||
embed_ls.append(Notificator.generate_alert_embed(new_alert, district, None, alert_time_str, 'he', district_data.id))
|
embed_ls.append(AlertEmbed.auto_alert(alert_data, district))
|
||||||
|
|
||||||
for channel_tup in self.db.get_all_channels():
|
for channel_tup in self.db.get_all_channels():
|
||||||
channel = Channel.from_tuple(channel_tup)
|
channel = Channel.from_tuple(channel_tup)
|
||||||
@ -338,15 +326,13 @@ class Notificator(commands.Cog):
|
|||||||
else:
|
else:
|
||||||
dc_ch = self.bot.get_user(channel.district_id)
|
dc_ch = self.bot.get_user(channel.district_id)
|
||||||
|
|
||||||
channel_districts = self.db.get_channel_district_ids(channel.district_id)
|
|
||||||
|
|
||||||
for emb in embed_ls:
|
for emb in embed_ls:
|
||||||
if dc_ch is None:
|
if dc_ch is None:
|
||||||
continue
|
continue
|
||||||
if len(channel.locations) != 0 and emb.district_id not in channel.locations:
|
if len(channel.locations) != 0 and emb.district_id not in channel.locations:
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
await dc_ch.send(embed=emb, view=self.hfc_button_view())
|
await dc_ch.send(embed=emb.embed, view=self.hfc_button_view())
|
||||||
await asyncio.sleep(0.01)
|
await asyncio.sleep(0.01)
|
||||||
except BaseException as e:
|
except BaseException as e:
|
||||||
self.log.warning(f'Failed to send alert in channel id={channel.district_id}:\n'
|
self.log.warning(f'Failed to send alert in channel id={channel.district_id}:\n'
|
||||||
|
Loading…
Reference in New Issue
Block a user