A collection of scripts that push notifications to ntfy (and optionally Telegram)
  • Python 95.7%
  • Just 2.5%
  • Shell 1.8%
Find a file
PatillaCode d0f03b6b53 feature/news-digest (#2)
Reviewed-on: #2
Co-authored-by: PatillaCode <patillacode@gmail.com>
Co-committed-by: PatillaCode <patillacode@gmail.com>
2026-07-26 19:58:33 +02:00
bin feature/news-digest (#2) 2026-07-26 19:58:33 +02:00
docs feature/news-digest (#2) 2026-07-26 19:58:33 +02:00
just feature/news-digest (#2) 2026-07-26 19:58:33 +02:00
lib feature/news-digest (#2) 2026-07-26 19:58:33 +02:00
scripts feature/news-digest (#2) 2026-07-26 19:58:33 +02:00
.env.example feature/news-digest (#2) 2026-07-26 19:58:33 +02:00
.gitignore news.py: add staleness check and collapsed fallback digest 2026-03-18 12:51:00 +01:00
.python-version Initial bananify project 2026-03-15 16:58:44 +01:00
justfile feature/news-digest (#2) 2026-07-26 19:58:33 +02:00
pyproject.toml Initial bananify project 2026-03-15 16:58:44 +01:00
README.md feature/news-digest (#2) 2026-07-26 19:58:33 +02:00
uv.lock Initial bananify project 2026-03-15 16:58:44 +01:00

🍌 bananify

A collection of notification scripts that push useful info to ntfy (and optionally Telegram). Named after ntfy's banana mascot.

Scripts

Script Topic Schedule Source
weather.py weather 7am daily Open-Meteo (free, no key)
ssl_expiry.py ssl-expiry 9am daily TLS cert check (stdlib)
apod.py apod 10am daily NASA APOD (free)
news.py news 10am daily Configurable RSS feeds, sent as one digest
system_health.py system-health 12pm daily Local /proc / psutil
quote.py quote 7pm daily zenquotes.io (free)
adguard_stats.py adguard Sun 8pm AdGuard Home API
ssh_login.py ssh-login SSH login (PAM) PAM environment

Setup

git clone <repo-url> bananify && cd bananify
cp .env.example .env   # fill in your values
uv sync                # install deps

Configuration

All configuration lives in .env. See .env.example for all available options.

Required:

  • NTFY_URL — your ntfy server URL (e.g. https://ntfy.sh)
  • NTFY_TOKEN — ntfy access token

Optional:

  • WEATHER_LANG — geocoding/description language (en or es, default en)
  • HEALTH_MOUNT_LABELS — display names for mounts, e.g. /=Root,/mnt/media=Media
  • NTFY_TOPIC_<NAME> — override default topic per script; comma-separate to publish to multiple topics (e.g. bananify,news)
  • Telegram, AdGuard credentials, city list, RSS feeds, SSL domains, thresholds

News feeds (NEWS_FEEDS)

Each feed entry is comma-separated and supports three formats:

Format Example
url https://hnrss.org/frontpage
name|url HN|https://hnrss.org/frontpage
name|url|max HN|https://hnrss.org/frontpage|3
  • name — overrides the RSS feed title in the notification
  • max — per-feed headline limit; falls back to NEWS_MAX_HEADLINES if omitted
  • All feeds are sent as one collapsed digest, one section per feed

Running

just run weather        # run a single script
just run-all            # run all scripts once

Or call the wrapper directly:

bin/bananify weather

Scheduling (cron)

0 7 * * *   /path/to/bananify/bin/bananify weather        >> /path/to/bananify/logs/weather.log 2>&1
0 9 * * *   /path/to/bananify/bin/bananify ssl_expiry      >> /path/to/bananify/logs/ssl_expiry.log 2>&1
0 10 * * *  /path/to/bananify/bin/bananify apod            >> /path/to/bananify/logs/apod.log 2>&1
0 10 * * *  /path/to/bananify/bin/bananify news            >> /path/to/bananify/logs/news.log 2>&1
0 12 * * *  /path/to/bananify/bin/bananify system_health   >> /path/to/bananify/logs/system_health.log 2>&1
0 19 * * *  /path/to/bananify/bin/bananify quote           >> /path/to/bananify/logs/quote.log 2>&1
0 20 * * 0  /path/to/bananify/bin/bananify adguard_stats   >> /path/to/bananify/logs/adguard_stats.log 2>&1

For SSH login alerts, see docs/cron.md.

Adding a new script

  1. Create scripts/my_thing.py — import from lib.notify:
    import sys, os
    sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
    from lib.notify import load_config, send_ntfy
    
    def main():
        cfg = load_config()
        # Optional: markdown=True, attach="https://...", click="https://..."
        send_ntfy(cfg, "my-topic", "Title", "Body")
    
    if __name__ == "__main__":
        main()
    
  2. Test: just run my_thing
  3. Add a cron entry using bin/bananify my_thing