From 6e767e79814f3ee32918bf104c86f68475fd7c36 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 27 May 2026 22:45:07 +0000 Subject: [PATCH 1/6] Rewrite README with turtle personality and vibe-coded origin story https://claude.ai/code/session_01UPHMP54Aikrwv7LJsAXYne --- README.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4cd6638..ad16ccf 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,23 @@

Alertle-V2

-

Sports alert notifications powered by ESPN, EPG, and your preferred push service.

+

He's slow. Your alerts aren't.

+ +

A self-hosted EPG monitoring and alert system. Built for sports fans, but flexible enough to notify you about any programming you care about.

+ +--- + +## Meet the Alertle Turtle 🐢 + +The Alertle Turtle is our mascot, our spirit animal, and our greatest irony. He is notoriously slow. He does not rush for anyone. And yet somehow, he always makes sure your game alerts arrive on time. + +Don't miss a game. The Alertle Turtle's got you. + +## ⚡ Vibe Coded + +This entire project was built through conversation with Claude AI — no code was written by hand. No documentation was read. No Stack Overflow tabs were opened. Just vibes, prompts, and one very good turtle idea. + +If it works, great. If something breaks, that's also the vibes. PRs are welcome. So is asking an AI about it. --- @@ -39,6 +55,8 @@ The web UI will be available at `http://localhost:8888`. - Fully configurable notification templates with per-endpoint overrides - 7-day lookahead scan with configurable daily scan time - Web UI for managing subscriptions, endpoints, settings, and viewing upcoming alerts +- First-start setup wizard so you're not staring at a blank config +- Backup and restore — including import from V1 ## How It Works From 38dad3d4e594e4bb1a9a6c1965a695cf93d6cec8 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 27 May 2026 22:52:49 +0000 Subject: [PATCH 2/6] Update default notification templates - Default: description, time, venue, channels - Game summary: time, score - Digest team sports: away at home / game start time / context / channels - Digest events: event name / event start time / channels https://claude.ai/code/session_01UPHMP54Aikrwv7LJsAXYne --- notifiers/base.py | 27 ++++++++++++++------------- templates/settings.html | 24 ++++++++++++------------ 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/notifiers/base.py b/notifiers/base.py index d52fc5f..52fd234 100644 --- a/notifiers/base.py +++ b/notifiers/base.py @@ -20,24 +20,25 @@ _GAME_THUMBS_DEFAULT = "https://game-thumbs.swvn.io" -DEFAULT_TEMPLATE = """{time} -📺 {channels} -📍 {venue} -{context} -{odds} -{score}""" - -DEFAULT_GAME_SUMMARY_TEMPLATE = """🏆 {score} +DEFAULT_TEMPLATE = """{description} {time} -📺 {channels} -{description}""" +{venue} +{channels}""" -DEFAULT_DIGEST_GAME_TEMPLATE = """{context} +DEFAULT_GAME_SUMMARY_TEMPLATE = """{time} +{score}""" + +DEFAULT_DIGEST_GAME_TEMPLATE = """{away} at {home} +Game Start: {time} -📺 {channels}""" +{context} +Times & Channels +{channels}""" -DEFAULT_DIGEST_EVENT_TEMPLATE = """{context} +DEFAULT_DIGEST_EVENT_TEMPLATE = """{home} +Event Start: {time} +Times & Channels: {channels}""" diff --git a/templates/settings.html b/templates/settings.html index d5c24d7..4801891 100644 --- a/templates/settings.html +++ b/templates/settings.html @@ -37,44 +37,44 @@

Notification Template

+ placeholder="{description} {time} {venue} {channels}">{{ cfg.get('notification_defaults', {}).get('template', '') }} Available variables: {time} {channels} {broadcast} {venue} {context} {odds} {score} - {home} {away} {home_abbrev} {away_abbrev} + {description} {home} {away} {home_abbrev} {away_abbrev} {league} {sport} - Leave empty to use default: time, channels, venue, context, odds, score + Leave empty to use default: description, time, venue, channels
+ placeholder="{time} {score}">{{ cfg.get('notification_defaults', {}).get('game_summary_template', '') }} - Used for Final Score notifications. Same variables as above, plus {description} (EPG program description). - Leave empty to use default: score, time, channels, description. + Used for Final Score notifications. Same variables as above, plus {score} for the final result. + Leave empty to use default: time, score.
- + placeholder="{away} at {home} Game Start: {time} {context} Times & Channels {channels}">{{ cfg.get('notification_defaults', {}).get('digest_game_template', '') }} Formats each game in the digest for team sports (NHL, NBA, MLB, etc.). - Leave empty to use default: context, time, 📺 channels. + Leave empty to use default: matchup, game start time, context, channels.
- + placeholder="{home} Event Start: {time} Times & Channels: {channels}">{{ cfg.get('notification_defaults', {}).get('digest_event_template', '') }} Formats each event in the digest for event series (Golf, F1, Tennis, etc.). The {channels} variable includes the full broadcast schedule with time slots. - Leave empty to use default: context, time, channels. + Leave empty to use default: event name, start time, channels.
From 034eb36bddea800b48d8cee6d8261ff2b3c5b388 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 27 May 2026 22:55:56 +0000 Subject: [PATCH 3/6] Update README description to accurately reflect sports-only scope https://claude.ai/code/session_01UPHMP54Aikrwv7LJsAXYne --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad16ccf..1c48975 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@

He's slow. Your alerts aren't.

-

A self-hosted EPG monitoring and alert system. Built for sports fans, but flexible enough to notify you about any programming you care about.

+

A self-hosted sports alert system. NHL, NBA, NFL, Soccer, Golf, F1, and more — straight to your phone.

--- From 20eb13770f36d125261d14cf785a0d181df3450b Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 27 May 2026 22:59:01 +0000 Subject: [PATCH 4/6] Update docker-compose and README quick start - Remove unused PUID/PGID/GIDLIST env vars - Add pull_policy: always - Add TZ: America/Toronto - Fix volume paths (config at ./alertle-v2/config.yaml, data as named volume) - Update README quick start to show compose inline with setup steps https://claude.ai/code/session_01UPHMP54Aikrwv7LJsAXYne --- README.md | 50 +++++++++++++++++++++++++++------------------- docker-compose.yml | 13 ++++++------ 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 1c48975..d4a1c3c 100644 --- a/README.md +++ b/README.md @@ -26,21 +26,36 @@ If it works, great. If something breaks, that's also the vibes. PRs are welcome. ## Quick Start -```bash -# Pull and run with Docker Compose -curl -o docker-compose.yml https://raw.githubusercontent.com/Deekerman/Alertle-V2/main/docker-compose.yml -curl -o config.yaml https://raw.githubusercontent.com/Deekerman/Alertle-V2/main/config.yaml.example -# Edit config.yaml with your settings, then: -docker compose up -d -``` +```yaml +services: + alertle-v2: + image: ghcr.io/deekerman/alertle-v2:latest + container_name: alertle-v2 + pull_policy: always + restart: unless-stopped + environment: + TZ: America/Toronto + ALERTLE_CONFIG: /config/config.yaml + ports: + - "8888:8888" + volumes: + - ./alertle-v2/config.yaml:/config/config.yaml + - alertle_data:/app/data -Or pull the image directly: +volumes: + alertle_data: +``` ```bash -docker pull ghcr.io/deekerman/alertle-v2:latest +# Create the config directory and grab the example config +mkdir -p alertle-v2 +curl -o alertle-v2/config.yaml https://raw.githubusercontent.com/Deekerman/Alertle-V2/main/config.yaml.example + +# Edit config.yaml, then: +docker compose up -d ``` -The web UI will be available at `http://localhost:8888`. +The web UI will be available at `http://localhost:8888`. The first-start wizard will walk you through the rest. --- @@ -98,22 +113,15 @@ sudo journalctl -u alertle-v2 -f ### Docker ```bash -git clone https://github.com/Deekerman/Alertle-V2.git -cd Alertle-V2 -cp config.yaml.example config.yaml -# Edit config.yaml with your settings +mkdir -p alertle-v2 +curl -o alertle-v2/config.yaml https://raw.githubusercontent.com/Deekerman/Alertle-V2/main/config.yaml.example +curl -o docker-compose.yml https://raw.githubusercontent.com/Deekerman/Alertle-V2/main/docker-compose.yml +# Edit alertle-v2/config.yaml, then: docker compose up -d ``` The web UI will be available at `http://localhost:8888`. -```yaml -# docker-compose.yml mounts -volumes: - - ./config.yaml:/config/config.yaml - - alertle_data:/data -``` - ## Configuration Copy `config.yaml.example` to `config.yaml` and edit. The web UI at `/settings` can manage most options after first launch. diff --git a/docker-compose.yml b/docker-compose.yml index ae858f6..6fccc81 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,18 +1,17 @@ -version: "3.8" - services: alertle-v2: image: ghcr.io/deekerman/alertle-v2:latest - build: . # optional: remove this line to always pull from GHCR container_name: alertle-v2 + pull_policy: always + restart: unless-stopped + environment: + TZ: America/Toronto + ALERTLE_CONFIG: /config/config.yaml ports: - "8888:8888" volumes: - - ./config.yaml:/config/config.yaml + - ./alertle-v2/config.yaml:/config/config.yaml - alertle_data:/app/data - environment: - - ALERTLE_CONFIG=/config/config.yaml - restart: unless-stopped volumes: alertle_data: From b4f36b8893adac23faa5162bde810a52cba87434 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 27 May 2026 23:40:41 +0000 Subject: [PATCH 5/6] Fix IsADirectoryError when config path is a Docker-created directory When docker compose up runs before the host config file exists, Docker creates the bind-mount target as a directory. _load_raw() now returns {} (empty config) in that case so the app starts cleanly and the first-start wizard can run. _save_raw() raises a clear RuntimeError instead of crashing silently. https://claude.ai/code/session_01UPHMP54Aikrwv7LJsAXYne --- config.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/config.py b/config.py index 6d19d52..9758a23 100644 --- a/config.py +++ b/config.py @@ -17,13 +17,19 @@ def _load_raw() -> dict: - if not CONFIG_PATH.exists(): + if not CONFIG_PATH.exists() or CONFIG_PATH.is_dir(): return {} with CONFIG_PATH.open() as f: return yaml.safe_load(f) or {} def _save_raw(data: dict) -> None: + if CONFIG_PATH.is_dir(): + raise RuntimeError( + f"Config path '{CONFIG_PATH}' is a directory, not a file. " + "On the host, run: rm -rf ./alertle-v2/config.yaml && " + "curl -o alertle-v2/config.yaml " + ) with CONFIG_PATH.open("w") as f: yaml.dump(data, f, default_flow_style=False, allow_unicode=True) From c9139e566cd68119027a2f9574902577b8f73b2f Mon Sep 17 00:00:00 2001 From: Deekerman <33733383+Deekerman@users.noreply.github.com> Date: Wed, 27 May 2026 19:48:49 -0400 Subject: [PATCH 6/6] Update README.md --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d4a1c3c..f2a995c 100644 --- a/README.md +++ b/README.md @@ -29,21 +29,20 @@ If it works, great. If something breaks, that's also the vibes. PRs are welcome. ```yaml services: alertle-v2: - image: ghcr.io/deekerman/alertle-v2:latest + image: ghcr.io/deekerman/alertle-v2:b4f36b8 container_name: alertle-v2 pull_policy: always restart: unless-stopped environment: TZ: America/Toronto - ALERTLE_CONFIG: /config/config.yaml ports: - - "8888:8888" + - 8888:8888 volumes: - ./alertle-v2/config.yaml:/config/config.yaml - alertle_data:/app/data - volumes: - alertle_data: + alertle_data: null +networks: {} ``` ```bash