From a11846e9be29689cf5f66b0537b5811fe32173a9 Mon Sep 17 00:00:00 2001 From: Jesus Anaya Date: Sun, 10 May 2026 08:28:01 -0500 Subject: [PATCH 1/2] claude.md --- CLAUDE.md | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..7c9e0ed --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,84 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Commands + +```bash +# Build +go build epgo + +# Build with version info stripped (production) +go build -ldflags="-s -w" -o epgo + +# Cross-compile (used by CI) +GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o epgo_linux_amd64 + +# Tidy dependencies +go mod tidy + +# Run (interactive config) +./epgo -configure myconfig.yaml + +# Run (fetch EPG data and generate XMLTV) +./epgo -config myconfig.yaml +``` + +There are no tests in this project. + +## Architecture + +EPGo fetches EPG data from the [Schedules Direct](https://schedulesdirect.org) API and generates XMLTV files for use with media servers (Plex, Jellyfin, etc.). + +### Two execution modes + +**`-configure`** → `Configure()` in `configure.go` +Interactive TUI for managing credentials, lineups, and channel selection. Writes the YAML config file and cache. Uses `promptui` for menus. + +**`-config`** → `sd.Update()` in `data.go` +Headless pipeline: open cache → login → fetch status → fetch lineup/schedule/program/metadata from SD → write cache → generate XMLTV file. + +### The `SD` struct (`struct_sd.go`, `sd.go`) + +Central API client. Uses a function-field pattern — `sd.Login`, `sd.Status`, `sd.Lineups`, etc. are closures assigned in `sd.Init()`. All HTTP calls funnel through `sd.Connect()`. The SD API base URL is `https://json.schedulesdirect.org/20141201/`. + +Token caching: on login, the token and its expiry timestamp are stored in `Cache.Token` / `Cache.TokenExpires` and persisted to the cache JSON file. On subsequent runs, the cached token is reused if it expires more than 5 minutes from now. + +### The `cache` struct (`struct_cache.go`, `cache.go`) + +Single JSON file (default: `config_cache.json`) that persists between runs to avoid re-downloading unchanged data. Contains: + +- `Channel` — `map[stationID]EPGoCache` with station metadata (name, callsign, logo, LCN) +- `Schedule` — `map[stationID][]EPGoCache` with airtimes +- `Program` — `map[programID]EPGoCache` with program details +- `Metadata` — `map[programID]EPGoCache` with artwork URLs +- `Token` / `TokenExpires` — cached SD auth token + +`Cache.Init()` reinitializes only the Channel/Schedule/Program/Metadata maps without touching the token fields. + +### Config file (`struct_config.go`, `configure.go`) + +YAML file managed by `config.Open()` / `config.Save()`. When opened, the code detects missing option blocks by scanning the raw YAML bytes and injects defaults — this is the config migration mechanism (no version field, purely string-matching based). + +The `channel` struct is dual-purpose: serialized to YAML for the config file, and also encoded directly to XML for XMLTV output (via Go struct tags). The `Lcn` field is XML-only (`yaml:"-"`), populated from the SD lineup map's `atscMajor.atscMinor` for OTA or the `channel` string for cable/satellite. + +### XMLTV generation (`xmltv.go`) + +Streams XML directly to file using `xml.NewEncoder`. Channels are written first (from `Cache.Channel`), then programmes (from `Cache.Schedule` joined with `Cache.Program` and `Cache.Metadata`). Channel IDs follow the format `epgo..schedulesdirect.org`. + +The `dd_progid` episode number is formatted as `EP01938443.3118` — the first 10 characters of the program ID followed by a dot and the remaining digits. + +### Image server (`server.go`) + +Optional HTTP file server started with `-serve dir:port` or automatically after XMLTV generation when `Config.Server.Enable = true`. Serves downloaded artwork from the configured image path. + +### Key globals + +- `Config` — the parsed YAML config (`config` struct) +- `Cache` — the JSON cache (`cache` struct, includes `sync.RWMutex`) +- `Token` — the current SD auth token string (mirrors `Cache.Token` during a run) +- `logger` — `*slog.Logger` using text handler to stdout + +### Branch workflow + +Development happens on the `development` branch. Changes are merged to `master` for releases. The `development-release.yaml` CI workflow publishes a rolling pre-release on every push to `development`; `release.yaml` publishes versioned releases on `v*` tags. From 30caa96bcb23615e2ed1ec069845ce3a29ce9922 Mon Sep 17 00:00:00 2001 From: Jesus Anaya Date: Fri, 15 May 2026 18:10:32 -0500 Subject: [PATCH 2/2] docs --- README.md | 121 ++++++++++++++++++++++++++++++++++++--------- sample-config.yaml | 3 +- 2 files changed, 99 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 23756f2..d520890 100644 --- a/README.md +++ b/README.md @@ -12,49 +12,66 @@ subredit: [epgo](https://www.reddit.com/r/EpGo/) - [Schedules Direct](https://www.schedulesdirect.org/ "Schedules Direct") Account - Computer with 1-2 GB memory -- [Go](https://golang.org/ "Golang") to build the binary -- [Optional] Docker to run it in a dockerize environment +- [Go](https://golang.org/ "Golang") 1.21+ to build the binary +- [Optional] Docker to run it in a containerized environment ## Installation ### Option 1 -- Build Binary -The following command must be executed with the terminal / command prompt inside the source code folder. +Run the following commands inside the source code folder: ```bash go mod tidy go build epgo ``` -This will spit out a binary for your OS named `epgo` +This produces a binary named `epgo` for your OS. -### Option 2 -- Docker +For a smaller production binary: -I need to set up the docker image. However, you can build your own by running: +```bash +go build -ldflags="-s -w" -o epgo +``` -#### **docker-compose** +To cross-compile (e.g., for Linux on AMD64): -clone this repo: +```bash +GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o epgo_linux_amd64 +``` + +### Option 2 -- Docker + +Clone the repo and use the provided `docker-compose.yaml`: ```bash git clone https://github.com/Chuchodavids/EpGo.git ``` -```docker-compose +```yaml +# docker-compose.yaml services: - epgo: - container_name: epgo - build: . - environment: - - TZ=America/Chicago - volumes: - - YOUR_CONFIG.YAML_FOLDER:/app/ - restart: always + epgo: + container_name: epgo + build: + context: . + args: + # Or amd64 + - TARGETARCH=arm64 + environment: + - TZ=America/Chicago + volumes: + # Assumes config.yaml is in the same directory as this docker-compose.yaml + - ./config.yaml:/app/config.yaml + command: -config /app/config.yaml + restart: never ``` -### Option 3 -- download binary +The Docker image is built from the included `Dockerfile`, which downloads the latest release binary from GitHub. -go to [releases](https://github.com/Chuchodavids/EpGo/releases) and download the needed version +### Option 3 -- Download Binary + +Go to [releases](https://github.com/Chuchodavids/EpGo/releases) and download the binary for your platform. You can also use the `download.sh` script included in the repository. ## Using the APP @@ -65,8 +82,10 @@ go to [releases](https://github.com/Chuchodavids/EpGo/releases) and download the = Get data from Schedules Direct with configuration file. [filename.yaml] -configure string = Create or modify the configuration file. [filename.yaml] +-serve string + = Start a local HTTP server to serve files from the specified directory. [directory:port] -version - = shows the current version + = shows the current version (v3.2.1) -h : Show help ``` @@ -134,7 +153,7 @@ Account: Files: Cache: config_cache.json XMLTV: config.xml - The MovieDB cache file: imdb_image_cache.json + The MovieDB cache file: config_tmdb_cache.json Server: Enable: false Address: localhost @@ -145,7 +164,7 @@ Options: Subtitle into Description: false Insert credits tag into XML file: false Images: - Download Images: false + Download Images from Schedules Direct: false Image Path: "" The MovieDB: Enable: false @@ -197,6 +216,14 @@ EPG data for the specified days. Schedules Direct has EPG data for the next 12-1 --- +```yaml +Live and New icons: false +``` + +**true:** Appends a unicode superscript "LIVE" or "New" badge to the programme title for live broadcasts and first-run episodes, respectively. + +--- + ```yaml Subtitle into Description: false ``` @@ -225,11 +252,11 @@ Alan zieht aus, da seine Freundin Kandi und er in Las Vegas eine Million Dollar ### Images: (Can be customized) ```yaml -Download Images: false +Download Images from Schedules Direct: false Image Path: "" ``` -- **Download Images**: `true` or `false`. If `true`, images will be downloaded to the `Image Path`. If `Image Path` is not set, it will default to a folder named `images`. +- **Download Images from Schedules Direct**: `true` or `false`. If `true`, images will be downloaded to the `Image Path`. If `Image Path` is not set, it will default to a folder named `images`. - **Image Path**: The path where the images will be downloaded. #### The MovieDB @@ -243,6 +270,8 @@ The MovieDB: - **Enable**: `true` or `false` to enable or disable The MovieDB as a fallback image source. - **Api Key**: Your The MovieDB API key. +The TMDB cache file (default: `config_tmdb_cache.json`) persists search results to avoid redundant API calls. + --- ```yaml @@ -393,6 +422,50 @@ Example: 2020/07/18 19:10:53 [ERROR] Could not find requested image. Post message to http://forums.schedulesdirect.org/viewforum.php?f=6 if you are having issues. [SD API Error Code: 5000] Program ID: EP03481925 ``` +--- + +## LCN (Logical Channel Number) + +Each channel in the XMLTV output includes an `lcn` attribute for subchannel auto-matching in media servers like Plex and Jellyfin. The LCN is populated from the Schedules Direct lineup map — for OTA channels it uses `atscMajor.atscMinor`, and for cable/satellite it uses the channel number string. + +```xml + + WGBO-DT + 66.1 + 66.1 + + +``` + +--- + +## Image Server + +When `Server.Enable` is set to `true` in the config, the HTTP image server starts automatically after XMLTV generation in `-config` mode. You can also start it independently with the `-serve` flag: + +```bash +./epgo -serve /path/to/images:8080 +``` + +--- + +## Cron Scheduling + +To keep EPG data up to date, run EPGo on a schedule. Example crontab entries: + +``` +@reboot /app/epgo --config /data/livetv/config.yaml +00 * * * * /app/epgo --config /data/livetv/config.yaml +``` + +A `cronjob` file with these examples is included in the repository. + +--- + +## Cache Cleanup + +After each XMLTV generation, stale program and metadata entries are automatically purged from the cache file. This keeps the cache size manageable without manual intervention. + ### Create the XMLTV file using the command line (CLI): ```bash diff --git a/sample-config.yaml b/sample-config.yaml index 74a5d43..8a2c7af 100644 --- a/sample-config.yaml +++ b/sample-config.yaml @@ -10,11 +10,12 @@ Server: Address: localhost Port: "80" Options: + Live and New icons: false Schedule Days: 1 Subtitle into Description: false Insert credits tag into XML file: false Images: - Download Images: false + Download Images from Schedules Direct: false Image Path: "" The MovieDB: Enable: false