ASMARA/utilities.py
Anastasia Mayer 5f8b8deaa0
...
2024-01-14 06:42:23 -06:00

634 lines
28 KiB
Python

"""
Note: Please do absolute imports, it allows me to clean up shit we don't use, and doesn't import extra code. It should be more efficient anyways.
"""
# Standard Library
from datetime import datetime as DT
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from enum import Enum
from io import BytesIO
from json import dump, loads
from os import system
from platform import system as osType
from smtplib import SMTP
from threading import Lock
from time import localtime, timezone
# Third-Party
from discord_webhook import DiscordEmbed, DiscordWebhook
from EAS2Text.EAS2Text import EAS2Text
class severity(Enum):
## 6
trace = [6, "TRACELOG > {}"] # For extra data text (Ex. Startup)
## 5
playoutStats = [
5,
"PLAYLOG > {}",
] # For playout stats (Now Playing, Header/Tone/EOM logs)
## 4
debug = [4, "{}"] # For extra data text (Ex. Startup)
debugWarn = [
4,
"WARNING > *** {} ***",
] # For notice text in DBG mode only (Ex. Monitor Down)
debugErr = [
4,
"ERROR > *** {} ***",
] # For extra data text in DBG mode only (Ex. Startup)
## 3
info = [3, "{}"] # For common text (Ex. Mon start/stop)
## 2
alert = [2, "{}"] # For alert recv messages
## 1
warning = [1, "WARNING > *** {} ***"] # For notice text (Ex. Monitor Down)
## 0
error = [
0,
"ERROR > *** {} ***",
] # For critical error text (Ex. Program Error)
fatal = [
0,
"FATAL > *** {} ***",
] # For fatal error text (Ex. Program crash)
boot = [0, ""] ## Boot and info scripts
## -1
menu = [-1, "{}"] # For menus
class utilities:
__printLock__ = Lock()
__emailLock__ = Lock()
__verbosity__ = 0
__defConfig__ = loads(
"""{
"Monitors": [],
"Callsign": "ASMARA/1",
"Emulation": "",
"Logger": {
"Email": {
"Enabled": false,
"Server": "eas@server.com",
"Port": 587,
"Username": "user",
"Password": "hackme",
"To": [
"user.name@server.com"
]
},
"Enabled": false,
"Audio": false,
"Webhooks": []
},
"LocalFIPS": [
"055079"
],
"PlayoutManager": {
"Channels": 2,
"SampleRate": 44100,
"Icecast":{
"Enabled": false,
"WaitingStatus": "WACN Radio - No Audio",
"Address": "127.0.0.1",
"Port": "8000",
"Source": "source",
"Pass": "None",
"Mountpoint": "Test",
"Bitrate": "128k"
},
"Audio": false,
"Export": {
"Enabled": false,
"Folder": "OldAlerts"
},
"Override": {
"Enabled": false,
"Folder": "Override"
},
"AutoDJ": {
"Enabled": true,
"Folder": "PlayoutAudio",
"IDFolder": "IDAudio",
"IDSongs": 4,
"Tone": true
},
"LeadIn": {
"Enabled": false,
"File": "",
"Type": ""
},
"LeadOut": {
"Enabled": false,
"File": "",
"Type": ""
}
},
"Filters": [
{
"Name": "Local Alerts",
"Originators": [
"*"
],
"EventCodes": [
"*"
],
"SameCodes": [
"LOCAL"
],
"CallSigns": [
"*"
],
"Action": "Live:Now"
},
{
"Name": "Tests",
"Originators": [
"*"
],
"EventCodes": [
"RWT",
"DMO"
],
"SameCodes": [
"*"
],
"CallSigns": [
"*"
],
"Action": "Ignore:Now"
},
{
"Name": "Catch All",
"Originators": [
"*"
],
"EventCodes": [
"*"
],
"SameCodes": [
"*"
],
"CallSigns": [
"*"
],
"Action": "Relay:Now"
}
],
"LogFile": ".log"
}"""
)
__stats__ = loads(
"""{
"EVENTS": {
"ADR": "http://acrn.gwes-eas.network/Icons/index.php?img=chat&hex=",
"AVA": "http://acrn.gwes-eas.network/Icons/index.php?img=avalanche&hex=",
"AVW": "http://acrn.gwes-eas.network/Icons/index.php?img=avalanche&hex=",
"BHW": "http://acrn.gwes-eas.network/Icons/index.php?img=biohazard&hex=",
"BLU": "http://acrn.gwes-eas.network/Icons/index.php?img=policeman&hex=",
"BWW": "http://acrn.gwes-eas.network/Icons/index.php?img=water-heating&hex=",
"BZW": "http://acrn.gwes-eas.network/Icons/index.php?img=snow&hex=",
"CAE": "http://acrn.gwes-eas.network/Icons/index.php?img=child-with-pacifier&hex=",
"CDW": "http://acrn.gwes-eas.network/Icons/index.php?img=break&hex=",
"CEM": "http://acrn.gwes-eas.network/Icons/index.php?img=break&hex=",
"CFA": "http://acrn.gwes-eas.network/Icons/index.php?img=beach&hex=",
"CFW": "http://acrn.gwes-eas.network/Icons/index.php?img=beach&hex=",
"CHW": "http://acrn.gwes-eas.network/Icons/index.php?img=biohazard&hex=",
"CWW": "http://acrn.gwes-eas.network/Icons/index.php?img=biohazard&hex=",
"DBA": "http://acrn.gwes-eas.network/Icons/index.php?img=dam&hex=",
"DBW": "http://acrn.gwes-eas.network/Icons/index.php?img=dam&hex=",
"DEW": "http://acrn.gwes-eas.network/Icons/index.php?img=biohazard&hex=",
"DMO": "http://acrn.gwes-eas.network/Icons/index.php?img=test-tube&hex=",
"DSW": "http://acrn.gwes-eas.network/Icons/index.php?img=wind&hex=",
"EAN": "http://acrn.gwes-eas.network/Icons/index.php?img=mushroom-cloud&hex=",
"EAT": "http://acrn.gwes-eas.network/Icons/index.php?img=mushroom-cloud&hex=",
"EQW": "http://acrn.gwes-eas.network/Icons/index.php?img=earthquakes&hex=",
"EVA": "http://acrn.gwes-eas.network/Icons/index.php?img=escape&hex=",
"EVI": "http://acrn.gwes-eas.network/Icons/index.php?img=escape&hex=",
"EWW": "http://acrn.gwes-eas.network/Icons/index.php?img=wind&hex=",
"FCW": "http://acrn.gwes-eas.network/Icons/index.php?img=biohazard&hex=",
"FFS": "http://acrn.gwes-eas.network/Icons/index.php?img=floods&hex=",
"FFA": "http://acrn.gwes-eas.network/Icons/index.php?img=floods&hex=",
"FFW": "http://acrn.gwes-eas.network/Icons/index.php?img=floods&hex=",
"FLS": "http://acrn.gwes-eas.network/Icons/index.php?img=sea-waves&hex=",
"FLA": "http://acrn.gwes-eas.network/Icons/index.php?img=sea-waves&hex=",
"FLW": "http://acrn.gwes-eas.network/Icons/index.php?img=sea-waves&hex=",
"FRW": "http://acrn.gwes-eas.network/Icons/index.php?img=fire&hex=",
"FSW": "http://acrn.gwes-eas.network/Icons/index.php?img=snowflake&hex=",
"FZW": "http://acrn.gwes-eas.network/Icons/index.php?img=snowflake&hex=",
"HMW": "http://acrn.gwes-eas.network/Icons/index.php?img=biohazard&hex=",
"HUS": "http://acrn.gwes-eas.network/Icons/index.php?img=hurricane&hex=",
"HUA": "http://acrn.gwes-eas.network/Icons/index.php?img=hurricane&hex=",
"HUW": "http://acrn.gwes-eas.network/Icons/index.php?img=hurricane&hex=",
"HWA": "http://acrn.gwes-eas.network/Icons/index.php?img=wind&hex=",
"HWW": "http://acrn.gwes-eas.network/Icons/index.php?img=wind&hex=",
"IBW": "http://acrn.gwes-eas.network/Icons/index.php?img=snowflake&hex=",
"IFW": "http://acrn.gwes-eas.network/Icons/index.php?img=fire&hex=",
"LAE": "http://acrn.gwes-eas.network/Icons/index.php?img=break&hex=",
"LEW": "http://acrn.gwes-eas.network/Icons/index.php?img=policeman&hex=",
"LSW": "http://acrn.gwes-eas.network/Icons/index.php?img=avalanche&hex=",
"NAT": "http://acrn.gwes-eas.network/Icons/index.php?img=speaker&hex=",
"NIC": "http://acrn.gwes-eas.network/Icons/index.php?img=chat&hex=",
"NMN": "http://acrn.gwes-eas.network/Icons/index.php?img=chat&hex=",
"NPT": "http://acrn.gwes-eas.network/Icons/index.php?img=test-tube&hex=",
"NST": "http://acrn.gwes-eas.network/Icons/index.php?img=quiet&hex=",
"NUW": "http://acrn.gwes-eas.network/Icons/index.php?img=radio-active&hex=",
"POS": "http://acrn.gwes-eas.network/Icons/index.php?img=electrical&hex=",
"RHW": "http://acrn.gwes-eas.network/Icons/index.php?img=radio-active&hex=",
"RMT": "http://acrn.gwes-eas.network/Icons/index.php?img=important-month&hex=",
"RWT": "http://acrn.gwes-eas.network/Icons/index.php?img=important-week&hex=",
"SCS": "http://acrn.gwes-eas.network/Icons/index.php?img=school&hex=",
"SMW": "http://acrn.gwes-eas.network/Icons/index.php?img=beach&hex=",
"SPS": "http://acrn.gwes-eas.network/Icons/index.php?img=rain&hex=",
"SPW": "http://acrn.gwes-eas.network/Icons/index.php?img=cottage&hex=",
"SQW": "http://acrn.gwes-eas.network/Icons/index.php?img=snow&hex=",
"SSA": "http://acrn.gwes-eas.network/Icons/index.php?img=beach&hex=",
"SSW": "http://acrn.gwes-eas.network/Icons/index.php?img=beach&hex=",
"SVA": "http://acrn.gwes-eas.network/Icons/index.php?img=cloudshot&hex=",
"SVR": "http://acrn.gwes-eas.network/Icons/index.php?img=cloudshot&hex=",
"SVS": "http://acrn.gwes-eas.network/Icons/index.php?img=rain&hex=",
"TOA": "http://acrn.gwes-eas.network/Icons/index.php?img=tornado&hex=",
"TOR": "http://acrn.gwes-eas.network/Icons/index.php?img=tornado&hex=",
"TOE": "http://acrn.gwes-eas.network/Icons/index.php?img=call&hex=",
"TRA": "http://acrn.gwes-eas.network/Icons/index.php?img=beach&hex=",
"TRW": "http://acrn.gwes-eas.network/Icons/index.php?img=beach&hex=",
"TSA": "http://acrn.gwes-eas.network/Icons/index.php?img=tsunami&hex=",
"TSW": "http://acrn.gwes-eas.network/Icons/index.php?img=tsunami&hex=",
"TXB": "http://acrn.gwes-eas.network/Icons/index.php?img=internet-antenna&hex=",
"TXF": "http://acrn.gwes-eas.network/Icons/index.php?img=internet-antenna&hex=",
"TXO": "http://acrn.gwes-eas.network/Icons/index.php?img=internet-antenna&hex=",
"TXP": "http://acrn.gwes-eas.network/Icons/index.php?img=internet-antenna&hex=",
"VOA": "http://acrn.gwes-eas.network/Icons/index.php?img=volcano&hex=",
"VOW": "http://acrn.gwes-eas.network/Icons/index.php?img=volcano&hex=",
"WFA": "http://acrn.gwes-eas.network/Icons/index.php?img=fire&hex=",
"WFW": "http://acrn.gwes-eas.network/Icons/index.php?img=fire&hex=",
"WSA": "http://acrn.gwes-eas.network/Icons/index.php?img=snow&hex=",
"WSW": "http://acrn.gwes-eas.network/Icons/index.php?img=snow&hex="
}
}
"""
)
# Class variable
__unk__ = 0x797979
__adv__ = 0xFFCC00
__wat__ = 0xFF6600
__war__ = 0xFF0000
@classmethod
def cls(cls):
if osType() == "Windows":
system("cls")
else:
system("clear")
@classmethod
def getOS(cls):
return osType()
@classmethod
def setVerbosity(cls, __verbosity__: int = 0):
cls.__verbosity__ = __verbosity__
@classmethod
def autoPrint(
cls,
text: str,
classType: str = "MAIN",
sev: Enum = severity.info,
end: str = "\n",
):
if sev == severity.boot or sev == severity.menu:
if sev.value[0] <= cls.__verbosity__:
with cls.__printLock__:
for line in text.split("\n"):
print(f"{line}", end=end)
else:
if sev.value[0] <= cls.__verbosity__:
now = f"[{DT.now().strftime('%H:%M:%S')}{cls.__getTZ__()[0]}]"
with cls.__printLock__:
for line in text.split("\n"):
print(
f"{now} > [{classType}] {sev.value[1].format(line)}",
end=end,
)
@classmethod
def writeDefConfig(cls, config):
with open(config, "w") as f:
dump(cls.__defConfig__, f, indent=4)
with open(".log", "w") as f:
f.write('{"ASMARA/1": {"Alerts":{}, "Weekly":{"Timestamp": 0}}}')
@classmethod
def __getTZ__(cls):
tzone = str(timezone / 3600.0)
locTime = localtime().tm_isdst
TMZ = "UTC"
if tzone == "4.0":
TMZ = "AST"
if locTime > 0 == True:
TMZ = "ADT"
elif tzone == "5.0":
TMZ = "EST"
if locTime > 0 == True:
TMZ = "EDT"
elif tzone == "6.0":
TMZ = "CST"
if locTime > 0 == True:
TMZ = "CDT"
elif tzone == "7.0":
TMZ = "MST"
if locTime > 0 == True:
TMZ = "MDT"
elif tzone == "8.0":
TMZ = "PST"
if locTime > 0 == True:
TMZ = "PDT"
return TMZ
@classmethod
def __genEmailSig__(cls, call, version):
return f"""<div class="moz-signature"><div class="WordSection1"><table class="MsoNormalTable" style="border-collapse: collapse;" border="0" width="499" cellspacing="0" cellpadding="0"><tbody><tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes;"><td style="width: 5.5in; padding: 0in 0in 0in 0in;" width="528">&nbsp;</td></tr><tr style="mso-yfti-irow: 2; height: 88.15pt;"><td style="width: 5.5in; border: none; border-bottom: dotted windowtext 1.0pt; padding: 0in 0in 0in 0in; height: 88.15pt;" width="528"><table class="MsoNormalTable" style="border-collapse: collapse; height: 5px;" border="0" width="524" cellspacing="0" cellpadding="0"><tbody><tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes;"><td style="width: 75.25pt; padding: 2.9pt 0in 2.9pt 0in;" width="100"><p class="MsoNormal"><span style="font-family: Poppins; mso-fareast-font-family: 'Times New Roman'; mso-no-proof: yes;"><img src="http://acrn.gwes-eas.network/Icons/ACORN_LOGO_2.png" style="width: 137px; height: auto"/><br /></span></p></td><td style="width: 390.25pt; padding: 2.9pt 0in 2.9pt 0in;" width="520"><span style="font-size: 9.0pt; font-family: Poppins; mso-fareast-font-family: 'Times New Roman'; mso-no-proof: yes;"></span><table class="MsoNormalTable" style="border-collapse: collapse;" border="0" width="358" cellspacing="0" cellpadding="0"><tbody><tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes;"><td style="width: 257.5pt; padding: 2.9pt 5.75pt 2.9pt 5.75pt;" width="343"><p class="MsoNormal"><span style="font-family: Verdana;"><strong>{call} Software ENDEC Logs</strong></span><br /><span style="font-family: Poppins; mso-fareast-font-family: 'Times New Roman'; mso-no-proof: yes;"> </span></p><p class="MsoNormal"><span style="font-size: 9.0pt; font-family: Poppins; mso-fareast-font-family: 'Times New Roman'; mso-no-proof: yes;"><span style="font-family: Verdana;">Do Not Reply, This is a Software-Generated Message.</span></span><br /><span style="font-family: Verdana;"><span style="font-size: 9pt;"></span></span></p><span style="font-size: 9.0pt; font-family: Poppins; mso-fareast-font-family: 'Times New Roman'; mso-no-proof: yes;"><span style="font-family: Verdana;"> </span></span></td></tr><tr style="mso-yfti-irow: 1;"><td style="width: 257.5pt; padding: 2.9pt 5.75pt 2.9pt 5.75pt;" width="343"><p class="MsoNormal"><span style="font-family: Verdana;"><span style="font-size: 8.0pt; font-family: 'Poppins Light'; mso-fareast-font-family: 'Times New Roman'; color: #7f7f7f; mso-no-proof: yes;">WACN Technologies ASMARA Version {version}</span></span><span style="font-size: 8.0pt; font-family: 'Poppins Light'; mso-fareast-font-family: 'Times New Roman'; mso-no-proof: yes;"></span></p><p class="MsoNormal"><span style="font-size: 8.0pt; font-family: 'Poppins Light'; mso-fareast-font-family: 'Times New Roman'; color: #7f7f7f; mso-no-proof: yes;"><span style="font-family: Verdana;">© 2022<span style="mso-spacerun: yes;"> </span> <a href="https://acrn.gwes-eas.network/">WACN Technologies</a></span></span></p></td></tr></tbody></table></td></tr></tbody></table></td></tr><tr style="mso-yfti-irow: 3; mso-yfti-lastrow: yes; height: 3.0pt;"><td style="width: 5.5in; padding: 0in 0in 0in 0in; height: 3.0pt;" width="528"><p class="MsoNormal" style="text-align: center;"><strong><span style="font-size: 7.0pt; font-family: Poppins; mso-fareast-font-family: 'Times NewRoman'; color: #70ad47; mso-no-proof: yes;"><span style="color: #18ff00; font-family: Verdana;">P</span></span></strong><span style="color: #18ff00; font-family: Verdana;"><span style="font-size: 7pt;">&nbsp;Save a tree. Don't print this e-mail unless it's necessary.</span></span><span style="font-family: Poppins; mso-fareast-font-family: 'Times New Roman'; mso-no-proof: yes;"> </span></p></td></tr></tbody></table><p class="MsoNormal">&nbsp;</p></div></div>"""
@classmethod
def __sendEmail__(
cls,
station: str,
alertTitle: str,
relay: str,
mon: str,
filt: str,
EASData: EAS2Text,
header: str,
version: str,
mon2: str,
filt2: str,
server: tuple,
):
try:
message = MIMEMultipart("alternative")
message[
"Subject"
] = f"{station.strip()} Software ENDEC: - {alertTitle}"
message[
"From"
] = f"{station.strip()} Software ENDEC Logs <{server['Username']}>"
message["To"] = ", ".join(server["To"])
html = f"""
<h3><strong>{alertTitle} - {relay}</strong></h3>
<p>{mon if mon != "" else ""}{filt if filt != "" else ""}
<b>EAS Text Translation:</b> {EASData.EASText}
<br><br>
<b>EAS Protocol Data:</b> {header}
</p>
{cls.__genEmailSig__(station, version)}
"""
text = f"----AUTOMATED MESSAGE---\n\n{alertTitle} - {relay}\n{mon2}{filt2}\nEAS Text Translation:\n{EASData.EASText}\n\nEAS Protocol Data:\n{header}\n\n------DO NOT REPLY------\n(SENT FROM ASMARA VERSION {version})"
part1 = MIMEText(text, "plain")
part2 = MIMEText(html, "html")
message.attach(part1)
message.attach(part2)
with SMTP(server["Server"], server["Port"]) as mailServ:
mailServ.login(server["Username"], server["Password"])
mailServ.sendmail(
server["Username"], server["To"], message.as_string()
)
cls.autoPrint(
text="Successfully Sent Email!",
classType="EMAIL",
sev=severity.debug,
)
except Exception as E:
cls.autoPrint(
text=f"{type(E).__name__}, {E}",
classType="EMAIL",
sev=severity.debugErr,
)
tb = E.__traceback__
while tb is not None:
cls.autoPrint(
text=f"File: {tb.tb_frame.f_code.co_filename}\nFunc: {tb.tb_frame.f_code.co_name}\nLine: {tb.tb_lineno}",
classType="EMAIL",
sev=severity.debugErr,
)
tb = tb.tb_next
cls.autoPrint(
text="Failed to send Email to Server. Please check Email configurations.",
classType="EMAIL",
sev=severity.debugWarn,
)
@classmethod
def log(
cls,
station: str,
webhooks: list,
status: str,
header: str,
filter: str = "",
monitorNum: str = "",
audioLog: bool = False,
audioFile="", ## Will take a String or a List object.
server: str = "",
version: str = "0.0.0",
oldEmbed=None,
email=False,
):
"""Logs the incoming data to Discord, Email, or Desktop
Args:
station (str): The callsign of the current station.
webhooks (list): The discord webhooks to send the logs to.
status (str): The status message to associate the alert to, such as "Recieved Alert Sent".
header (str): The SAME data.
filter (str, optional): A ENDEC filter to say matched against. Defaults to "".
monitorNum (str, optional): The monitor number the alert was received on. Defaults to "".
AudioLog (bool, optional): Is there an audio file? Defaults to False.
AudioFile (str or list, optional): Path to audio if str, OR a list in the format of [Filename, BytesIO Object]. Defaults to "".
version (str, optional): ENDEC version string. Defaults to "0.0.0".
oldEmbed (_type_, optional): A previous EMBED to update. Defaults to None.
email (bool, optional): Send Email? Defaults to False.
Returns:
_type_: _description_
"""
EASData = EAS2Text(header)
try:
alertTitle = " ".join(EASData.evntText.split(" ")[1:])
if any(
word.lower() in alertTitle.lower()
for word in [
"Demo",
"Test",
"Advisory",
"Statement",
"Administrative",
"Practice",
"Transmitter",
"Network",
]
):
color = cls.__adv__
elif any(word.lower() in alertTitle.lower() for word in ["Watch"]):
color = cls.__wat__
elif any(
word.lower() in alertTitle.lower()
for word in [
"Warning",
"Emergency",
"Alert",
"Evacuation",
"Notification",
"Action",
"Center",
]
):
color = cls.__war__
else:
color = cls.__unk__
alertImage = str(cls.__stats__["EVENTS"][EASData.evnt]) + str(
hex(color)
)
except Exception as e:
# print(e)
alertTitle = f"Unknown Alert ({header.split('-')[2]})"
color = cls.__unk__
alertImage = (
"http://acrn.gwes-eas.network/Icons/index.php?img=break&hex="
+ str(hex(color))
)
relay = f"{status} at {DT.now().strftime('%m/%d/%Y %H:%M:%S ') + cls.__getTZ__()}"
if server == "Audio":
server = "Local Audio Monitor"
elif server == "Radio":
server = "Local SDR Monitor"
notif = ""
mon = ""
mon2 = ""
filt = ""
filt2 = ""
embed = DiscordEmbed(title=alertTitle, description=relay, color=color)
embed.set_author(name=f"{station.strip()} - Software ENDEC Logs")
embed.set_footer(text=f"ASMARA {version} | © 2022 WACN Tech.")
if monitorNum != "" and server != "":
embed.add_embed_field(
name="Recieved From:",
value=f"Monitor #{monitorNum}\n({server})",
inline=True,
)
notif += f"Recieved From: {monitorNum}\n"
mon = f"<b>Received From:</b> {monitorNum} <small>({server})</small><br>"
mon2 = f"\nRecieved From: {monitorNum} ({server})\n"
if filter != "":
embed.add_embed_field(
name="Matched Filter:", value=filter, inline=True
)
filt = f"<b>Matched Filter:</b> {filter}<br><br>"
filt2 = f"Matched Filter: {filter}\n"
embed.add_embed_field(
name="EAS Text Data:",
value=f"```{EASData.EASText}```",
inline=False,
)
notif += f"{EASData.EASText}\n"
embed.add_embed_field(
name="EAS Protocol Data:", value=f"```{header}```", inline=False
)
if alertImage:
embed.set_thumbnail(url=alertImage)
webhook = DiscordWebhook(url=webhooks, rate_limit_retry=True)
webhook.add_embed(embed)
try:
if oldEmbed:
if audioLog == True:
if type(audioFile) == str:
with open(audioFile, "rb") as f:
webhook.add_file(file=f.read(), filename=audioFile)
f.close()
elif type(audioFile) == list:
with BytesIO() as f:
audioFile[1].export(
out_f=f,
format="wav",
codec="pcm_s16le",
)
f.seek(0)
webhook.add_file(
file=f.read(), filename=audioFile[0]
)
oldLog = webhook.edit(oldEmbed)
cls.autoPrint(
text="Successfully Updated Webhook!",
classType="LOGGER",
sev=severity.debug,
)
else:
if audioLog == True:
if type(audioFile) == str:
with open(audioFile, "rb") as f:
webhook.add_file(file=f.read(), filename=audioFile)
f.close()
elif type(audioFile) == list:
with BytesIO() as f:
audioFile[1].export(
out_f=f,
format="wav",
codec="pcm_s16le",
)
f.seek(0)
webhook.add_file(
file=f.read(), filename=audioFile[0]
)
oldLog = webhook.execute()
cls.autoPrint(
text="Successfully Posted Log to Webhook!",
classType="LOGGER",
sev=severity.debug,
)
if email:
with cls.__emailLock__:
cls.__sendEmail__(
station,
alertTitle,
relay,
mon,
filt,
EASData,
header,
version,
mon2,
filt2,
email,
)
except Exception as E:
cls.autoPrint(
text=f"{type(E).__name__}, {E}",
classType="LOGGER",
sev=severity.debugErr,
)
tb = E.__traceback__
while tb is not None:
cls.autoPrint(
text=f"File: {tb.tb_frame.f_code.co_filename}\nFunc: {tb.tb_frame.f_code.co_name}\nLine: {tb.tb_lineno}",
classType="LOGGER",
sev=severity.debugErr,
)
tb = tb.tb_next
cls.autoPrint(
text="Failed to send Log to Discord, Check your connection, or webhooks.",
classType="LOGGER",
sev=severity.debugWarn,
)
return oldLog