Skip to content

TheGreatCodeholio/nws_alerts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

icad_nws_alerts

Fetch recent NWS weather alerts for one or more UGC zones and keep exactly one Discord message per logical alert chain (Alert → Updates → Cancel).

The script:

  • Polls api.weather.gov/alerts (no time window, so downtime won’t miss alerts still marked status=actual).
  • Posts brand‑new, still‑active alerts to Discord.
  • Edits the same Discord message when that alert is updated / canceled / expired.
  • Ignores alerts that are already over if the script never saw them (no retro spam).
  • Stores state in one JSON file per zone (no DB).
  • Uses daily log rotation.

Designed to run every minute on Linux via cron (or a systemd timer) inside a Python virtual environment.


Features

  • Multiple zones, each with its own Discord webhook list.
  • Robust de‑dup with VTEC chain keys (falls back to canonical CAP id).
  • Automatic recovery if a Discord edit returns 404 (re‑post & update state).
  • Safe, atomic JSON writes.
  • Daily rotated logs with retention.
  • Optional: mapbox integration that will draw the alert polygons (if present)

Requirements

  • Linux
  • Python 3.10+
  • Discord webhook URL(s)

Python packages

requests
python-dateutil

(or keep them in a requirements.txt)


Directory layout (default)

repo/
├── icad_nws_alerts.py          # the script
├── lib/
│   └── utility_module.py       # contains event_codes
├── etc/
│   └── config.json             # copy from config_sample.json
├── var/
│   ├── log/
│   │   └── icad_nws_alerts.log # rotated daily
│   └── state/
│       └── <ZONE>.json         # one state file per zone
└── venv/                       # (optional) python virtualenv

You can override all paths with environment variables (see Environment variables).


Getting NOAA UGC zone IDs (county / forecast zones)

You need UGC zone IDs (e.g., SCC063) for the zone query parameter.

Quick via API

List all county zones for a state (example: South Carolina):

curl -s "https://api.weather.gov/zones?type=county&area=SC" \
| jq -r '.features[] | "\(.properties.id)\t\(.properties.name)"'

Inspect one zone:

curl -s "https://api.weather.gov/zones/county/SCC063" | jq .

You can also find tables on NWS / WFO websites that map counties to UGC IDs.

Note: UGC zones are different from SAME (EAS) FIPS codes. This script uses UGC.


Configuration (etc/config.json)

Example:

{
  "user_agent": "icad_nws_alerts (ops@example.com)",
  "log_level": "INFO",
  "zones": [
    {
      "zone_id": "SCC063",
      "label": "Lexington County, SC",
      "webhooks": [
        "https://discord.com/api/webhooks/xxx/yyy"
      ]
    },
    {
      "zone_id": "NYC015",
      "label": "Chemung County, NY",
      "webhooks": [
        "https://discord.com/api/webhooks/aaa/bbb"
      ]
    }
  ]
}

Notes

  • zones[].webhooks: The script currently uses the first webhook. (You can fan out yourself if desired.)

Environment variables (optional)

  • NOAA_ALERTS_CONFIG – full path to config.json. Default: <repo>/etc/config.json
  • NOAA_ALERTS_VARDIR – base dir for log/ and state/. Default: <repo>/var
  • NOAA_ALERTS_LOGDIR – logs dir. Default: <var>/log
  • NOAA_ALERTS_STATEDIR – state dir. Default: <var>/state
  • NOAA_ALERTS_LOGLEVEL – overrides the log_level in config

Install & Run (Linux + venv)

1) Clone & create venv

git clone https://github.com/TheGreatCodeholio/nws_alerts.git
cd icad_nws_alerts

python3 -m venv venv
source venv/bin/activate

pip install -U pip
pip install requests python-dateutil

2) Configure

mkdir -p etc var/log var/state
cp etc/config_sample.json etc/config.json
vim etc/config.json

3) Test run

source venv/bin/activate
python icad_nws_alerts.py

4) Cron (every minute)

crontab -e

Add:

* * * * * cd /opt/icad_nws_alerts && /opt/icad_nws_alerts/venv/bin/python icad_nws_alerts.py >> /opt/icad_nws_alerts/var/log/cron.out 2>&1

(Adjust paths to your install.)

Tips

  • Always use full paths in cron.
  • If you rely on env vars, either set them inline or wrap the call in a shell script that exports them first.

(Optional) systemd timer instead of cron

Create /etc/systemd/system/icad_nws_alerts.service:

[Unit]
Description=icad_nws_alerts runner

[Service]
Type=oneshot
WorkingDirectory=/opt/icad_nws_alerts
Environment=NOAA_ALERTS_CONFIG=/opt/icad_nws_alerts/etc/config.json
ExecStart=/opt/icad_nws_alerts/venv/bin/python /opt/icad_nws_alerts/icad_nws_alerts.py

Create /etc/systemd/system/icad_nws_alerts.timer:

[Unit]
Description=Run icad_nws_alerts every minute

[Timer]
OnUnitActiveSec=60s
AccuracySec=5s
Unit=icad_nws_alerts.service

[Install]
WantedBy=timers.target

Enable:

sudo systemctl daemon-reload
sudo systemctl enable --now icad_nws_alerts.timer

Posting/editing rules (summary)

  • New alert + activepost.
  • New alert + already canceled/expiredignore.
  • Seen alert updatededit that Discord message.
  • Seen alert canceled/expirededit to show cancelled.
  • Edit returns 404re‑post and update stored message id.
  • Prune state entries 7 days after expires_at.

Logging

  • Logs live in <var>/log/icad_nws_alerts.log.
  • Rotated nightly (UTC), keep 14 days by default.
  • Change via config/env vars.

State files

  • One JSON per zone: <var>/state/<ZONE>.json
  • Holds:
    • last CAP id you posted/edited for the chain
    • Discord message id
    • status (posted|updated|cleared)
    • expires_at
  • Written atomically (.tmp + replace) to avoid corruption.

Troubleshooting

Discord 404 on edit

  • Discord may purge webhook messages or someone deleted it.
  • The script detects 404 and re‑posts, updating state.

Works manually but not from cron

  • Cron has a minimal environment and a different working dir.
  • Use absolute paths and ensure your venv path is correct.

Missing alerts

  • Verify the correct UGC zone is used.
  • Script ignores already‑over alerts it has never seen.

Timezone confusion

  • Script normalizes timestamps to UTC using python-dateutil.

Contributing

PRs welcome! Please keep:

  • Backward compatibility of state JSON if possible
  • Same logging & error‑handling style
  • Minimal external dependencies

License

MIT License


Credits

  • NWS api.weather.gov
  • Discord Webhooks

About

Python script to be run by cron that will post and update weather alerts on Discord

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages