emergency Canada alerts #145

Closed
opened 2026-10-05 01:25:48 +02:00 by adam · 9 comments
Owner

Describe the bug

In get_rss_feed() (modules/rss.py), each feed entry's link is extracted:

link = find_any(item, [
    'link',
    '{http://purl.org/rss/1.0/}link',
    '{http://www.w3.org/2005/Atom}link'
])
if not link:
    link_elem = item.find('{http://www.w3.org/2005/Atom}link')
    if link_elem is not None and 'href' in link_elem.attrib:
        link = link_elem.attrib['href']

...but it's never actually used. The final formatted entry only includes title and description:

formatted_entries.append(f"{title}\n{description}\n")

So link is extracted for nothing - the variable is computed and then silently dropped. This affects every configured feed, not just one in particular.

Why this matters more than it might seem

This becomes a real problem for anything alert/warning-oriented. I'm running an Environment Canada alerts feed as one of my configured RSS sources (for real severe weather alerts, since NOAA/iPAWS obviously doesn't apply outside the US) - and readrss ecalert correctly shows the alert title and a short summary, but gives no way to click through to the full details. For something like a severe weather warning, that's a meaningful gap - the short summary alone often isn't enough to act on.

Suggested fix

Simplest fix - just include the link in the formatted entry:

formatted_entries.append(f"{title}\n{description}\n{link}\n")

Might be worth truncating/shortening very long URLs if message length is a concern, but even including it as-is would be a big improvement over dropping it entirely.

Additional context

Tested against multiple feeds (a tech news feed, a subreddit feed, and Environment Canada's alert feed) - the link is missing from output in all cases, confirming this isn't feed-specific.

**Describe the bug** In `get_rss_feed()` (`modules/rss.py`), each feed entry's `link` is extracted: ```python link = find_any(item, [ 'link', '{http://purl.org/rss/1.0/}link', '{http://www.w3.org/2005/Atom}link' ]) if not link: link_elem = item.find('{http://www.w3.org/2005/Atom}link') if link_elem is not None and 'href' in link_elem.attrib: link = link_elem.attrib['href'] ``` ...but it's never actually used. The final formatted entry only includes title and description: ```python formatted_entries.append(f"{title}\n{description}\n") ``` So `link` is extracted for nothing - the variable is computed and then silently dropped. This affects every configured feed, not just one in particular. **Why this matters more than it might seem** This becomes a real problem for anything alert/warning-oriented. I'm running an Environment Canada alerts feed as one of my configured RSS sources (for real severe weather alerts, since NOAA/iPAWS obviously doesn't apply outside the US) - and `readrss ecalert` correctly shows the alert title and a short summary, but gives no way to click through to the full details. For something like a severe weather warning, that's a meaningful gap - the short summary alone often isn't enough to act on. **Suggested fix** Simplest fix - just include the link in the formatted entry: ```python formatted_entries.append(f"{title}\n{description}\n{link}\n") ``` Might be worth truncating/shortening very long URLs if message length is a concern, but even including it as-is would be a big improvement over dropping it entirely. **Additional context** Tested against multiple feeds (a tech news feed, a subreddit feed, and Environment Canada's alert feed) - the link is missing from output in all cases, confirming this isn't feed-specific. <!-- github-sync-id:5278505197 -->
adam closed this issue 2026-10-05 01:25:48 +02:00
Author
Owner

Yea I left a lot of open stubs for random ideas or modding.

Space is at a premium, is the biggest reason, links can be messy.
Also when this area was written I don't know there was any markdown yet.

What's the feed you use? Is there another way it could be incorporated. I dug for a bit on Canada sources for alerts and haven't found good ones (all in the app only, or pay for?)

Yea I left a lot of open stubs for random ideas or modding. Space is at a premium, is the biggest reason, links can be messy. Also when this area was written I don't know there was any markdown yet. What's the feed you use? Is there another way it could be incorporated. I dug for a bit on Canada sources for alerts and haven't found good ones (all in the app only, or pay for?) <!-- github-comment-id:5454944678 -->
Author
Owner

Makes total sense on the space/markdown constraints - a bare link probably isn't the right fix for every feed (hackaday/reddit don't really need it cluttering things up). Alerts specifically feel like the one category where it earns its keep though.

The feed I'm using is:

https://weather.gc.ca/rss/battleboard/onrm22_e.xml
(onrm22 = "Saugeen Shores - Kincardine - Southern Bruce County", my specific region)

On finding Canadian alert sources - I hit the same wall you did at first. EC's own docs page (https://www.canada.ca/en/environment-climate-change/services/weather-general-tools-resources/weatheroffice-online-services/atom-feeds.html) has region codes for basically all of Canada, but a bunch of the older/guessable-looking codes floating around online are now dead - EC apparently resized a lot of their alert regions at some point, so old codes 404.

The only reliable way I found to get a current working code for a given area was through EC's own site directly (their local weather page for a location has an RSS icon that links to the currently-valid feed for that spot) - not something guessable from lat/lon.

On "another way to incorporate it" - given the codes are consistent across the country (weather.gc.ca/rss/battleboard/{region-code}_e.xml, free, no API key), this could actually work as a proper first-class alert type, similar to how iPAWS/NOAA alerts already work (ipawsAlertEnabled, FIPS/SAME codes) rather than going through the generic RSS reader.

Something like:

( # Environment Canada alerts (Canada equivalent to iPAWS)
ecAlertEnabled = False
ecAlertRegionCode = onrm22

Then it could route to the same emergency_handler channel/interface the other alert types already use, and since it's specifically an alert (not a casual read), including the link there wouldn't run into the same space-budget concern as the general RSS reader - it'd be a deliberate design choice for that one alert type rather than a blanket change everywhere.

Happy to help test if useful, since I've already got a real region running it.

Makes total sense on the space/markdown constraints - a bare link probably isn't the right fix for every feed (hackaday/reddit don't really need it cluttering things up). Alerts specifically feel like the one category where it earns its keep though. The feed I'm using is: https://weather.gc.ca/rss/battleboard/onrm22_e.xml (onrm22 = "Saugeen Shores - Kincardine - Southern Bruce County", my specific region) On finding Canadian alert sources - I hit the same wall you did at first. EC's own docs page (https://www.canada.ca/en/environment-climate-change/services/weather-general-tools-resources/weatheroffice-online-services/atom-feeds.html) has region codes for basically all of Canada, but a bunch of the older/guessable-looking codes floating around online are now dead - EC apparently resized a lot of their alert regions at some point, so old codes 404. The only reliable way I found to get a current working code for a given area was through EC's own site directly (their local weather page for a location has an RSS icon that links to the currently-valid feed for that spot) - not something guessable from lat/lon. On "another way to incorporate it" - given the codes are consistent across the country (weather.gc.ca/rss/battleboard/{region-code}_e.xml, free, no API key), this could actually work as a proper first-class alert type, similar to how iPAWS/NOAA alerts already work (ipawsAlertEnabled, FIPS/SAME codes) rather than going through the generic RSS reader. Something like: ( # Environment Canada alerts (Canada equivalent to iPAWS) ecAlertEnabled = False ecAlertRegionCode = onrm22 Then it could route to the same emergency_handler channel/interface the other alert types already use, and since it's specifically an alert (not a casual read), including the link there wouldn't run into the same space-budget concern as the general RSS reader - it'd be a deliberate design choice for that one alert type rather than a blanket change everywhere. Happy to help test if useful, since I've already got a real region running it. <!-- github-comment-id:5459088470 -->
Author
Owner

Image Sample screenshot.

<img width="479" height="181" alt="Image" src="https://github.com/user-attachments/assets/6f3cd3e6-6de9-4b9a-b6f0-f96c1aab26df" /> Sample screenshot. <!-- github-comment-id:5487653815 -->
Author
Owner

What's the root for that

No alerts in effect

Is what I see when I snoop about need an alert to trap it.

https://weather.gc.ca/rss/battleboard/onrm22_e.xml

What's the root for that No alerts in effect Is what I see when I snoop about need an alert to trap it. https://weather.gc.ca/rss/battleboard/onrm22_e.xml <!-- github-comment-id:5487743030 -->
Author
Owner

Good questions — here's what I know:

The root/pattern: It's consistent across all of Canada:

https://weather.gc.ca/rss/battleboard/{region-code}_e.xml

Just swap the region code for any area (mine is onrm22). Environment and Climate Change Canada's documentation page has the full list of codes for the whole country:

[Environment Canada Atom Feeds](https://www.canada.ca/en/environment-climate-change/services/weather-general-tools-resources/weatheroffice-online-services/atom-feeds.html)

Format-wise, it's Atom, not classic RSS — the root element is <feed> with <entry> items (not <rss><channel><item>), so it's worth watching for that if you're reusing existing RSS parsing code that expects the RSS structure.

On "need an alert to trap it" — you don't actually need to wait for a live one. The feed always returns exactly one <entry>, and the title text itself tells you which state you're in:

  • No alert: the title is literally "No alerts in effect, {your region name}"
  • Real alert: the title is the actual alert type, e.g. "SPECIAL WEATHER STATEMENT, Saugeen Shores - Kincardine - Southern Bruce County"

So the detection logic is just a simple string check. Here's what I'm actually running right now (Python, but the logic translates easily):

is_no_alert = "no alerts in effect" in title.lower()

If that's True, stay quiet. If False, it's a real alert — grab <entry><title>, <entry><summary>, and <entry><link href="...">, and you've got everything needed.

I can paste the raw XML structure of the "no alerts" placeholder if that would help you test the parsing without a live alert. I don't have a saved copy of a real fired one, just the bot's own summarized output from when one hit my area recently, but the placeholder plus this logic should be enough to build and test against.

Good questions — here's what I know: **The root/pattern:** It's consistent across all of Canada: `https://weather.gc.ca/rss/battleboard/{region-code}_e.xml` Just swap the region code for any area (mine is `onrm22`). Environment and Climate Change Canada's documentation page has the full list of codes for the whole country: [[Environment Canada Atom Feeds](https://www.canada.ca/en/environment-climate-change/services/weather-general-tools-resources/weatheroffice-online-services/atom-feeds.html)](https://www.canada.ca/en/environment-climate-change/services/weather-general-tools-resources/weatheroffice-online-services/atom-feeds.html) **Format-wise, it's Atom, not classic RSS** — the root element is `<feed>` with `<entry>` items (not `<rss><channel><item>`), so it's worth watching for that if you're reusing existing RSS parsing code that expects the RSS structure. **On "need an alert to trap it"** — you don't actually need to wait for a live one. The feed always returns exactly one `<entry>`, and the title text itself tells you which state you're in: * No alert: the title is literally `"No alerts in effect, {your region name}"` * Real alert: the title is the actual alert type, e.g. `"SPECIAL WEATHER STATEMENT, Saugeen Shores - Kincardine - Southern Bruce County"` So the detection logic is just a simple string check. Here's what I'm actually running right now (Python, but the logic translates easily): ```python is_no_alert = "no alerts in effect" in title.lower() ``` If that's `True`, stay quiet. If `False`, it's a real alert — grab `<entry><title>`, `<entry><summary>`, and `<entry><link href="...">`, and you've got everything needed. I can paste the raw XML structure of the "no alerts" placeholder if that would help you test the parsing without a live alert. I don't have a saved copy of a real fired one, just the bot's own summarized output from when one hit my area recently, but the placeholder plus this logic should be enough to build and test against. <!-- github-comment-id:5495738839 -->
Author
Owner

Actually, I was wrong. I do have a real one saved from when an alert fired for my area a couple weeks back - here's the raw XML:

<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-ca">
<title>Saugeen Shores - Kincardine - Southern Bruce County - Weather Alert - Environment Canada</title>
<link rel="related" href="https://weather.gc.ca/warnings/report_e.html?onrm22" type="text/html"/>
<link rel="self" href="https://weather.gc.ca/rss/battleboard/onrm22_e.xml" type="application/atom+xml"/>
<link rel="alternate" href="https://meteo.gc.ca/rss/battleboard/onrm22_f.xml" type="application/atom+xml"/>
<author>
<name>Environment Canada</name>
<uri>https://weather.gc.ca</uri>
</author>
<updated>2026-08-22T08:48:52Z</updated>
<id>tag:weather.gc.ca,2013-04-16:20260822084852</id>
<logo>https://weather.gc.ca/cacheable/images/img/wmms-alt.png</logo>
<icon>https://weather.gc.ca/template/gcweb/v15.0.0/GCWeb/assets/favicon.ico</icon>
<rights>Copyright 2026, Environment Canada</rights>
<entry>
<title>SPECIAL WEATHER STATEMENT, Saugeen Shores - Kincardine - Southern Bruce County</title>
<link type="text/html" href="https://weather.gc.ca/warnings/report_e.html?onrm22"/>
<updated>2026-08-22T08:48:25Z</updated>
<published>2026-08-22T08:48:25Z</published>
<category term="Alerts"/>
<summary type="html">Issued: 4:48 AM EDT Saturday 22 August 2026</summary>
<id>tag:weather.gc.ca,2013-04-16:onrm22_w1:20260822084825</id>
</entry>
</feed>

Same shape as the "no alerts" placeholder, just with a real title/summary/id instead of the placeholder text - should be enough to build and test the parsing without needing to wait for a live one.

Actually, I was wrong. I do have a real one saved from when an alert fired for my area a couple weeks back - here's the raw XML: ```xml <feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-ca"> <title>Saugeen Shores - Kincardine - Southern Bruce County - Weather Alert - Environment Canada</title> <link rel="related" href="https://weather.gc.ca/warnings/report_e.html?onrm22" type="text/html"/> <link rel="self" href="https://weather.gc.ca/rss/battleboard/onrm22_e.xml" type="application/atom+xml"/> <link rel="alternate" href="https://meteo.gc.ca/rss/battleboard/onrm22_f.xml" type="application/atom+xml"/> <author> <name>Environment Canada</name> <uri>https://weather.gc.ca</uri> </author> <updated>2026-08-22T08:48:52Z</updated> <id>tag:weather.gc.ca,2013-04-16:20260822084852</id> <logo>https://weather.gc.ca/cacheable/images/img/wmms-alt.png</logo> <icon>https://weather.gc.ca/template/gcweb/v15.0.0/GCWeb/assets/favicon.ico</icon> <rights>Copyright 2026, Environment Canada</rights> <entry> <title>SPECIAL WEATHER STATEMENT, Saugeen Shores - Kincardine - Southern Bruce County</title> <link type="text/html" href="https://weather.gc.ca/warnings/report_e.html?onrm22"/> <updated>2026-08-22T08:48:25Z</updated> <published>2026-08-22T08:48:25Z</published> <category term="Alerts"/> <summary type="html">Issued: 4:48 AM EDT Saturday 22 August 2026</summary> <id>tag:weather.gc.ca,2013-04-16:onrm22_w1:20260822084825</id> </entry> </feed> ``` Same shape as the "no alerts" placeholder, just with a real title/summary/id instead of the placeholder text - should be enough to build and test the parsing without needing to wait for a live one. <!-- github-comment-id:5501265369 -->
Author
Owner

give that a test

give that a test <!-- github-comment-id:5515623065 -->
Author
Owner

Tested it with a live EC alert today. The EC feed parsing works and the alert was retrieved correctly, but I found one small issue in handleAlertBroadcast().

The new alert_types list includes "ec", but "ec" was missing from the last_alerts dictionary. This caused:

Error in handleAlertBroadcast: 'ec'

I added:

"ec": {"time": 0, "message": ""},

to last_alerts, restarted the BBS, and the next scheduled check successfully broadcast the EC alert.

So the EC alert code itself is working — it looks like that last_alerts entry was missed in the commit. 👍

I'm leaving it running now to test the alert handling/deduplication as well. Specifically, I'm watching to make sure the same EC alert isn't broadcast repeatedly, while a changed alert (such as a new alert or an ENDED update) is recognized and broadcast as a new message. I'll also see what happens when the feed returns the normal "no alerts in effect" response.

Tested it with a live EC alert today. The EC feed parsing works and the alert was retrieved correctly, but I found one small issue in `handleAlertBroadcast()`. The new `alert_types` list includes `"ec"`, but `"ec"` was missing from the `last_alerts` dictionary. This caused: `Error in handleAlertBroadcast: 'ec'` I added: ```python id="q9k8ms" "ec": {"time": 0, "message": ""}, ``` to `last_alerts`, restarted the BBS, and the next scheduled check successfully broadcast the EC alert. So the EC alert code itself is working — it looks like that `last_alerts` entry was missed in the commit. 👍 I'm leaving it running now to test the alert handling/deduplication as well. Specifically, I'm watching to make sure the same EC alert isn't broadcast repeatedly, while a changed alert (such as a new alert or an `ENDED` update) is recognized and broadcast as a new message. I'll also see what happens when the feed returns the normal "no alerts in effect" response. <!-- github-comment-id:5517864546 -->
Author
Owner

nice thanks, corrected.

nice thanks, corrected. <!-- github-comment-id:5517960404 -->
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/meshing-around#145