Fixed the f-string typo on line 240: change_type = f"Severity changed: {prev.get('severity')} → {entry['severity']}"

This commit is contained in:
Phil 2025-11-20 15:27:03 +00:00
parent 4e352e01fb
commit 3f5cb1a1c5

View File

@ -17,7 +17,7 @@ FEED_URL = "https://aastatus.net/atom.cgi"
WEBHOOK_URL = "https://discord.com/api/webhooks/XXXXXXX" # Discord webhook URL WEBHOOK_URL = "https://discord.com/api/webhooks/XXXXXXX" # Discord webhook URL
STATE_FILE = Path("/tmp/aaisp_atom_state.json") STATE_FILE = Path("/tmp/aaisp_atom_state.json")
# Event colors (default fallbacks) # Event colors
COLOR_MINOR_OPEN = 0xFFFF00 # yellow COLOR_MINOR_OPEN = 0xFFFF00 # yellow
COLOR_MAJOR_OPEN = 0xFF0000 # red COLOR_MAJOR_OPEN = 0xFF0000 # red
COLOR_CLOSED = 0x2ECC71 # green COLOR_CLOSED = 0x2ECC71 # green
@ -54,7 +54,9 @@ def fetch_feed(url):
raise raise
def get_first_valid_entry(feed_xml): def parse_feed_entries(feed_xml):
"""Return a list of all valid entries in the feed."""
entries = []
try: try:
root = ET.fromstring(feed_xml) root = ET.fromstring(feed_xml)
atom_ns = "{http://www.w3.org/2005/Atom}" atom_ns = "{http://www.w3.org/2005/Atom}"
@ -104,7 +106,7 @@ def get_first_valid_entry(feed_xml):
updated = entry.findtext(f"{atom_ns}updated", "") updated = entry.findtext(f"{atom_ns}updated", "")
published = entry.findtext(f"{atom_ns}published", "") published = entry.findtext(f"{atom_ns}published", "")
return { entries.append({
"id": id_elem.text.strip(), "id": id_elem.text.strip(),
"title": html.unescape(title_text), "title": html.unescape(title_text),
"link": link, "link": link,
@ -114,9 +116,9 @@ def get_first_valid_entry(feed_xml):
"severity": severity, "severity": severity,
"status": status, "status": status,
"content": html.unescape(content_text) "content": html.unescape(content_text)
} })
return None return entries
except ET.ParseError as e: except ET.ParseError as e:
logger.error(f"XML parsing error: {e}") logger.error(f"XML parsing error: {e}")
@ -134,26 +136,18 @@ def html_to_markdown(html_content):
return md.strip()[:3500] return md.strip()[:3500]
### COLOR LOGIC (refactored, table-driven) ### ### COLOR LOGIC (table-driven) ###
def get_event_color(status, severity): def get_event_color(status, severity):
"""
Determines the Discord embed colour based on status & severity.
Uses a lookup table for clarity and easy extensions.
"""
# Special case colours for Planned Maintenance (PEW)
SPECIAL_COLORS = { SPECIAL_COLORS = {
("PEW", "Open"): 0x51D3D4, ("PEW", "Open"): 0x51D3D4,
("PEW", "Planned"): 0x51D3D4, ("PEW", "Planned"): 0x51D3D4,
} }
# Direct match first
key = (severity, status) key = (severity, status)
if key in SPECIAL_COLORS: if key in SPECIAL_COLORS:
return SPECIAL_COLORS[key] return SPECIAL_COLORS[key]
# Normal rules
if status == "Closed": if status == "Closed":
return COLOR_CLOSED return COLOR_CLOSED
@ -212,51 +206,51 @@ def main():
logger.info("[*] Fetching feed...") logger.info("[*] Fetching feed...")
feed_xml = fetch_feed(FEED_URL) feed_xml = fetch_feed(FEED_URL)
logger.info("[*] Parsing...") logger.info("[*] Parsing feed entries...")
entry = get_first_valid_entry(feed_xml) entries = parse_feed_entries(feed_xml)
if not entry: if not entries:
logger.warning("No entry found") logger.warning("No entries found")
return return
incident_id = entry["id"]
state = load_state() state = load_state()
prev = state.get(incident_id) for entry in entries:
incident_id = entry["id"]
prev = state.get(incident_id)
# Determine if an update is needed must_post = False
must_post = False change_type = "New entry"
change_type = "New entry"
if prev is None: if prev is None:
must_post = True
change_type = "New Incident Detected"
else:
# Compare important fields
if entry["status"] != prev.get("status"):
must_post = True must_post = True
change_type = f"Status changed: {prev.get('status')}{entry['status']}" change_type = "New Incident Detected"
elif entry["severity"] != prev.get("severity"): else:
must_post = True if entry["status"] != prev.get("status"):
change_type = f"Severity changed: {prev.get('severity']}{entry['severity']}" must_post = True
elif entry["updated"] != prev.get("updated"): change_type = f"Status changed: {prev.get('status')}{entry['status']}"
must_post = True elif entry["severity"] != prev.get("severity"):
change_type = "Feed updated" must_post = True
elif entry["content"] != prev.get("content"): change_type = f"Severity changed: {prev.get('severity')}{entry['severity']}"
must_post = True elif entry["updated"] != prev.get("updated"):
change_type = "Content updated" must_post = True
change_type = "Feed updated"
elif entry["content"] != prev.get("content"):
must_post = True
change_type = "Content updated"
if must_post: if must_post:
logger.info(f"[+] Posting update: {change_type}") logger.info(f"[+] Posting update: {change_type} ({entry['title']})")
payload = build_discord_payload(entry, change_type) payload = build_discord_payload(entry, change_type)
post_to_discord(WEBHOOK_URL, payload) post_to_discord(WEBHOOK_URL, payload)
# Save state
state[incident_id] = {
"status": entry["status"],
"severity": entry["severity"],
"updated": entry["updated"],
"content": entry["content"]
}
# Save state no matter what
state[incident_id] = {
"status": entry["status"],
"severity": entry["severity"],
"updated": entry["updated"],
"content": entry["content"]
}
save_state(state) save_state(state)