4 Commits

Author SHA1 Message Date
Ian Renton
b62ef6a9a0 WWTOTA cluster support #97 2026-01-22 19:27:36 +00:00
Ian Renton
7952ad22eb Merge branch 'main' into 97-wwtota 2026-01-22 19:00:59 +00:00
Ian Renton
33bdcca990 Proper fix for BOTA alerts 2026-01-18 12:47:34 +00:00
Ian Renton
261912b6e1 Release 1.2 2026-01-18 12:22:03 +00:00
5 changed files with 51 additions and 41 deletions

View File

@@ -20,9 +20,11 @@ class BOTA(HTTPAlertProvider):
new_alerts = [] new_alerts = []
# Find the table of upcoming alerts # Find the table of upcoming alerts
bs = BeautifulSoup(http_response.content.decode(), features="lxml") bs = BeautifulSoup(http_response.content.decode(), features="lxml")
forthcoming_activations_div = bs.body.find('div', attrs={'class': 'view-activations-public'}) div = bs.body.find('div', attrs={'class': 'view-activations-public'})
if forthcoming_activations_div: if div:
tbody = forthcoming_activations_div.find('table', attrs={'class': 'views-table'}).find('tbody') table = div.find('table', attrs={'class': 'views-table'})
if table:
tbody = table.find('tbody')
for row in tbody.find_all('tr'): for row in tbody.find_all('tr'):
cells = row.find_all('td') cells = row.find_all('td')
first_cell_text = str(cells[0].find('a').contents[0]).strip() first_cell_text = str(cells[0].find('a').contents[0]).strip()

View File

@@ -4,7 +4,7 @@ from data.sig import SIG
# General software # General software
SOFTWARE_NAME = "Spothole by M0TRT" SOFTWARE_NAME = "Spothole by M0TRT"
SOFTWARE_VERSION = "1.2-pre" SOFTWARE_VERSION = "1.3-pre"
# HTTP headers used for spot providers that use HTTP # HTTP headers used for spot providers that use HTTP
HTTP_HEADERS = {"User-Agent": SOFTWARE_NAME + ", v" + SOFTWARE_VERSION + " (operated by " + SERVER_OWNER_CALLSIGN + ")"} HTTP_HEADERS = {"User-Agent": SOFTWARE_NAME + ", v" + SOFTWARE_VERSION + " (operated by " + SERVER_OWNER_CALLSIGN + ")"}

View File

@@ -140,12 +140,14 @@ class LookupHelper:
# database live if possible. # database live if possible.
def download_clublog_ctyxml(self): def download_clublog_ctyxml(self):
try: try:
logging.info("Downloading Clublog cty.xml...") logging.info("Downloading Clublog cty.xml.gz...")
response = self.CLUBLOG_CTY_XML_CACHE.get("https://cdn.clublog.org/cty.php?api=" + self.CLUBLOG_API_KEY, response = self.CLUBLOG_CTY_XML_CACHE.get("https://cdn.clublog.org/cty.php?api=" + self.CLUBLOG_API_KEY,
headers=HTTP_HEADERS) headers=HTTP_HEADERS)
logging.info("Caching Clublog cty.xml.gz...")
open(self.CLUBLOG_XML_DOWNLOAD_LOCATION + ".gz", 'wb').write(response.content) open(self.CLUBLOG_XML_DOWNLOAD_LOCATION + ".gz", 'wb').write(response.content)
with gzip.open(self.CLUBLOG_XML_DOWNLOAD_LOCATION + ".gz", "rb") as uncompressed: with gzip.open(self.CLUBLOG_XML_DOWNLOAD_LOCATION + ".gz", "rb") as uncompressed:
file_content = uncompressed.read() file_content = uncompressed.read()
logging.info("Caching Clublog cty.xml...")
with open(self.CLUBLOG_XML_DOWNLOAD_LOCATION, "wb") as f: with open(self.CLUBLOG_XML_DOWNLOAD_LOCATION, "wb") as f:
f.write(file_content) f.write(file_content)
f.flush() f.flush()

View File

@@ -135,6 +135,10 @@ def populate_sig_ref_info(sig_ref):
sig_ref.latitude = ll[0] sig_ref.latitude = ll[0]
sig_ref.longitude = ll[1] sig_ref.longitude = ll[1]
break break
elif sig.upper() == "WWTOTA":
if not sig_ref.name:
sig_ref.name = sig_ref.id
sig_ref.url = "https://wwtota.com/seznam/karta_rozhledny.php?ref=" + sig_ref.name
elif sig.upper() == "WAB" or sig.upper() == "WAI": elif sig.upper() == "WAB" or sig.upper() == "WAI":
ll = wab_wai_square_to_lat_lon(ref_id) ll = wab_wai_square_to_lat_lon(ref_id)
if ll: if ll:

View File

@@ -1,5 +1,6 @@
from datetime import datetime from datetime import datetime
import json
import pytz import pytz
from data.sig_ref import SIGRef from data.sig_ref import SIGRef
@@ -17,23 +18,24 @@ class WWTOTA(HTTPSpotProvider):
def http_response_to_spots(self, http_response): def http_response_to_spots(self, http_response):
new_spots = [] new_spots = []
response_fixed = http_response.text.replace("\\/", "/")
response_json = json.loads(response_fixed)
# Iterate through source data # Iterate through source data
for source_spot in http_response.json()["spots"]: for source_spot in response_json["spots"]:
print(source_spot) # todo
# Convert to our spot format # Convert to our spot format
# spot = Spot(source=self.name, likely_freq = float(source_spot["freq"]) * 1000
# source_id=source_spot["spotId"], if likely_freq < 1000000:
# dx_call=source_spot["activator"].upper(), likely_freq = likely_freq * 1000
# de_call=source_spot["spotter"].upper(), spot = Spot(source=self.name,
# freq=float(source_spot["frequency"]) * 1000, dx_call=source_spot["call"].upper(),
# mode=source_spot["mode"].upper(), freq=likely_freq,
# comment=source_spot["comments"], comment=source_spot["comment"],
# sig="WWTOTA", sig="WWTOTA",
# sig_refs=[SIGRef(id=source_spot["reference"], sig="POTA", name=source_spot["name"])], sig_refs=[SIGRef(id=source_spot["ref"], sig="WWTOTA")],
# time=datetime.strptime(source_spot["spotTime"], "%Y-%m-%dT%H:%M:%S").replace( time=datetime.strptime(response_json["updated"][:10] + source_spot["time"], "%Y-%m-%d%H:%M").timestamp())
# tzinfo=pytz.UTC).timestamp())
# # Add to our list. Don't worry about de-duping, removing old spots etc. at this point; other code will do
# # Add to our list. Don't worry about de-duping, removing old spots etc. at this point; other code will do # that for us.
# # that for us. new_spots.append(spot)
# new_spots.append(spot)
return new_spots return new_spots