...
This commit is contained in:
commit
5f8b8deaa0
0
IDAudio/plhoacldeer
Normal file
0
IDAudio/plhoacldeer
Normal file
35
LICENSE
Normal file
35
LICENSE
Normal file
|
@ -0,0 +1,35 @@
|
|||
Global Weather and EAS Society EAS Relay Network License for Internally Developed Software
|
||||
|
||||
Internally developed software developed by the Network Development team ("ERN-ND") is granted to those who have access as a privilege, not a right.
|
||||
|
||||
As such, ERN-ND can take away access to said software under this license agreement. Usage of the software means that you, the end user, agree to all provisions within this agreement.
|
||||
|
||||
Alright, now that the legal stuff is out of the way, here is what you can do under this license agreement:
|
||||
|
||||
- Use the software
|
||||
- Make changes to the configuration of the software
|
||||
- If access was granted by ERN-ND, modifications to the source code are allowed, however the changes are limited to:
|
||||
- Quality of Life
|
||||
- Extended functionality in specific applications
|
||||
- Aesthetic modifications
|
||||
- Porting to unsupported platforms
|
||||
These changes are allowed under the condition that:
|
||||
- Source code modifications are made available to ERN-ND
|
||||
- They are not designed to bypass security regarding Software Licensing or gaining access to IPAWS.
|
||||
- You declare to ERN-ND that by modifying the software, you are relinquishing any further support for software issues regarding the modfications unless the modifications make it into the main source tree using a pull request that is approved.
|
||||
- This license is retained within the software in a unmodified state.
|
||||
|
||||
Here is what you can't do:
|
||||
|
||||
- Make unauthorized changes to the software
|
||||
- Reverse engineer the software
|
||||
- Bypass the activation of the software
|
||||
- Redistribute the software
|
||||
- Run the software on any electronic device that is owned (or hosted) by an individual not bound under this license agreement
|
||||
- Attempt to retrieve the GWES-ERN IPAWS Access Key without express authorization by the Network Operations team.
|
||||
|
||||
|
||||
Violations of this agreement will result in removal of access to any software that is developed under this agreement and may prevent you from being eligible for further software access indefinitely.
|
||||
|
||||
TL;DR- You can use the software, change the software config, and make modifications as long as they are not extensive and code is made available to network devs. Just know we won't help you if you break it.
|
||||
Any violations will make you look like a jackass and access will be revoked as needed. You wouldn't download a car so why steal shit you don't own.
|
1
OldAlerts/theHolderOfPlaces
Normal file
1
OldAlerts/theHolderOfPlaces
Normal file
|
@ -0,0 +1 @@
|
|||
boof
|
1
Override/holdplacer
Normal file
1
Override/holdplacer
Normal file
|
@ -0,0 +1 @@
|
|||
doot
|
0
PlayoutAudio/plhoacldeer
Normal file
0
PlayoutAudio/plhoacldeer
Normal file
157
README.md
Normal file
157
README.md
Normal file
|
@ -0,0 +1,157 @@
|
|||
# WACN TECH - ASMARA
|
||||
### Automated System for Monitoring And Relaying Alerts
|
||||
|
||||
<IMG HERE WHEN AVAILABLE>
|
||||
|
||||
<STATS HERE WHEN AVAILABLE>
|
||||
|
||||
The comprehensive software EAS solution.
|
||||
|
||||
## Features
|
||||
> - [x] EAS Generation and Translation using stable and tested systems
|
||||
> - [x] Live and buffered audio flow systems
|
||||
> - [x] Audio file and log generation systems
|
||||
> - [x] Easy to use
|
||||
> - [x] Built-In Discord and Email logging
|
||||
> - [x] Comprehensive audio quality
|
||||
> - [x] AutoDJ for Playout, with a Tone Only mode.
|
||||
> - [x] InfiniteMonitor System for unlimited monitoring
|
||||
> - [x] Back-to-back Alert Detection on all monitors
|
||||
> - [x] MultiATTN Attention Detection on all Monitors
|
||||
> - [x] ENDEC Header Style Emulation
|
||||
> - [x] The Fastest and most reliable system on the market for over 6 monitors
|
||||
> - [x] Built-in Icecast Playout with Metadata
|
||||
> - [x] Direct stream monitoring
|
||||
> - [x] SDR monitoring
|
||||
|
||||
|
||||
## Installation
|
||||
This system currently only runs on MacOS and Linux.
|
||||
|
||||
If you are running the Compiled ASMARA Binary, skip to step 2.
|
||||
|
||||
### Step 1
|
||||
Install Python dependencies
|
||||
```
|
||||
sudo apt update
|
||||
sudo apt install python3 python3-pip python3-pyaudio
|
||||
pip3 install -r requirements.txt
|
||||
```
|
||||
|
||||
### Step 2
|
||||
Install other dependencies.
|
||||
#### FFmpeg:
|
||||
```
|
||||
sudo apt update
|
||||
sudo apt install ffmpeg
|
||||
```
|
||||
#### Samedec:
|
||||
```
|
||||
sudo apt update
|
||||
sudo apt install curl git
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
git clone https://github.com/cbs228/sameold.git
|
||||
cd sameold
|
||||
cargo install --path crates/samedec
|
||||
```
|
||||
> NOTE: Add RUST to path with `source $HOME/.cargo/env` after CURL, otherwise restart your terminal or log out/in before installing sameold, otherwise cargo will not work.
|
||||
|
||||
### Step 3
|
||||
Test ASMARA's config generation by running
|
||||
`python3 asmara.py -d` if using Python, or
|
||||
`./asmara -d` if using compiled binaries.
|
||||
> Configs will by default be stored in `.config` if not specified.
|
||||
> To specify a config, add it after the ASMARA executable, and all flags.
|
||||
> E.G. `./asmara -d CONFIGFILE.CFG` for a file named `CONFIGFILE.CFG`
|
||||
|
||||
## Configuration
|
||||
DO LATER
|
||||
|
||||
## Usage
|
||||
To run ASMARA, use the executable or the raw Python script.
|
||||
|
||||
For the Python executable:
|
||||
```
|
||||
python3 asmara.py
|
||||
```
|
||||
For the Compiled Binary:
|
||||
```
|
||||
./asmara
|
||||
```
|
||||
|
||||
### Verbosity
|
||||
|
||||
If you would like more info in the terminal, you can increase the `verbosity` flag.
|
||||
For a higher verbosity, run `-v`. The more `v`s you add increase the verbosity. (E.G. `-vvvv` is higher than `-vv`)
|
||||
|
||||
For debug info, run `-d` for debug.
|
||||
|
||||
For the lowest verbosity, run `-q` for quiet mode.
|
||||
|
||||
### Extra Flags:
|
||||
`-A` gives data about ASMARA.
|
||||
|
||||
`-V` gives the current version of ASMARA.
|
||||
|
||||
`-u` updates the current version of ASMARA if there is a newer version available in the internal updater system. use `-n` to disable the internal updater for this session. (NOT IMPLEMENTED YET.)
|
||||
|
||||
`-U` sets your config file to always update if available. `-N` disables this feature, and update notifications. (NOT IMPLEMENTED YET.)
|
||||
|
||||
### Config Files:
|
||||
Adding a file on to the end of the executable after all flags will set that file as a config file.
|
||||
> Note: Must be a valid ASMARA config file for that version. Using an incompatible file may cause problems, and-or corruption of the said file.
|
||||
|
||||
Example:
|
||||
```
|
||||
python3 asmara.py -vvvv .config2
|
||||
```
|
||||
to use `.config2` as the selected config file. If the file does not exist, it will be created.
|
||||
> Note: The config file *must* always come after the flags. Adding a flag after the config file may result in unexpected behavior.
|
||||
|
||||
## Changelog
|
||||
DO LATER
|
||||
|
||||
## License
|
||||
This software is licensed under `GWES-ERN LIDS` for ERN Network Development Partners (`ERN-ND`). This license applies to any and all user(s) of this software.
|
||||
|
||||
Please read the license carefully.
|
||||
|
||||
```
|
||||
Global Weather and EAS Society EAS Relay Network License for Internally Developed Software
|
||||
|
||||
Internally developed software developed by the Network Development team ("ERN-ND") is granted to those who have access as a privilege, not a right.
|
||||
|
||||
As such, ERN-ND can take away access to said software under this license agreement. Usage of the software means that you, the end user, agree to all provisions within this agreement.
|
||||
|
||||
Alright, now that the legal stuff is out of the way, here is what you can do under this license agreement:
|
||||
|
||||
- Use the software
|
||||
- Make changes to the configuration of the software
|
||||
- If access was granted by ERN-ND, modifications to the source code are allowed, however the changes are limited to:
|
||||
- Quality of Life
|
||||
- Extended functionality in specific applications
|
||||
- Aesthetic modifications
|
||||
- Porting to unsupported platforms
|
||||
These changes are allowed under the condition that:
|
||||
- Source code modifications are made available to ERN-ND
|
||||
- They are not designed to bypass security regarding Software Licensing or gaining access to IPAWS.
|
||||
- You declare to ERN-ND that by modifying the software, you are relinquishing any further support for software issues regarding the modifications unless the modifications make it into the main source tree using a pull request that is approved.
|
||||
- This license is retained within the software in a unmodified state.
|
||||
|
||||
Here is what you can't do:
|
||||
|
||||
- Make unauthorized changes to the software
|
||||
- Reverse engineer the software
|
||||
- Bypass the activation of the software
|
||||
- Redistribute the software
|
||||
- Run the software on any electronic device that is owned (or hosted) by an individual not bound under this license agreement
|
||||
- Attempt to retrieve the GWES-ERN IPAWS Access Key without express authorization by the Network Operations team.
|
||||
|
||||
|
||||
Violations of this agreement will result in removal of access to any software that is developed under this agreement and may prevent you from being eligible for further software access indefinitely.
|
||||
|
||||
TL;DR- You can use the software, change the software config, and make modifications as long as they are not extensive and code is made available to network devs. Just know we won't help you if you break it.
|
||||
Any violations will make you look like a jackass and access will be revoked as needed. You wouldn't download a car so why steal shit you don't own.
|
||||
```
|
||||
|
||||
###### Copyright © 2023 WACN Technologes and GWES ERN
|
58
flow.txt
Normal file
58
flow.txt
Normal file
|
@ -0,0 +1,58 @@
|
|||
This file is here to help understand the app flow of ASMARA
|
||||
|
||||
|
||||
Functions / Classes:
|
||||
boot Func:
|
||||
Parses Arguements, and calls MAIN Functions
|
||||
main:
|
||||
Takes in Config File and creates an AS_MAN class
|
||||
|
||||
|
||||
File Flow:
|
||||
|
||||
asmara.py (imports utilities.py)
|
||||
|
||||
|
||||
Program Flow:
|
||||
|
||||
run > boot > main > AS_MAN*
|
||||
> Init
|
||||
> setConfig
|
||||
> MakeConfig
|
||||
> loadConfig
|
||||
> setLog
|
||||
> setIcePlayout
|
||||
> setCallsign
|
||||
> setLocalFIPS
|
||||
> setLeadIn
|
||||
> setLeadOut
|
||||
> setSamplerate
|
||||
> setChannels
|
||||
> setLogger
|
||||
> setEmail
|
||||
> setExport
|
||||
> setFilters
|
||||
> loadLogs
|
||||
> setTone
|
||||
> MANAGER*
|
||||
> AlertFileDump
|
||||
> OVERRIDE*
|
||||
> alertToOld
|
||||
> PLAYOUT*
|
||||
> SetIcePlayer
|
||||
> UpdateIcecastNP
|
||||
> Make URL Ready
|
||||
> KillIcePlayer
|
||||
> DATAPUMP*
|
||||
> AddCount
|
||||
> AUTODJ*
|
||||
> AS_MON* (Per Monitor)
|
||||
> DECODER*
|
||||
> samedec*
|
||||
> alertToOld
|
||||
> Filter
|
||||
> MONITOR*
|
||||
> ffmpeg|rtl_fm*
|
||||
> ATTN Detect
|
||||
> alertToOld
|
||||
> RELAY
|
10
pyproject.toml
Normal file
10
pyproject.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
[tool.black]
|
||||
line-length = 79
|
||||
target-version = ["py310"]
|
||||
|
||||
[tool.isort]
|
||||
import_heading_stdlib = "Standard Library"
|
||||
import_heading_thirdparty = "Third-Party"
|
||||
import_heading_firstparty = "First-Party"
|
||||
import_heading_localfolder = "Local Folder"
|
||||
profile = "black"
|
6
requirements.txt
Normal file
6
requirements.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
EAS2Text
|
||||
EASGen
|
||||
pydub
|
||||
discord_webhook==0.17.0
|
||||
requests
|
||||
numpy
|
633
utilities.py
Normal file
633
utilities.py
Normal file
|
@ -0,0 +1,633 @@
|
|||
"""
|
||||
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"> </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;"> 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"> </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
|
Loading…
Reference in a new issue