Files
project-a13tv/CLAUDE.md
2026-03-05 09:08:52 +01:00

3.6 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Commands

Setup:

python -m venv venv
venv/bin/pip install -r requirements.txt

Run:

bash run.sh          # kills anything on port 5000, then starts the app
# or directly:
venv/bin/python app.py

The app runs on http://localhost:5000. There are no tests.

Architecture

This is a single-page IPTV channel manager for Acestream links. The entire backend is app.py (Flask) and the entire frontend is static/index.html (vanilla JS + bundled Tailwind).

Data flow

  1. Startup: app.py builds a logo index by walking tv-logos-main/ (PNG files), then loads channels.json if it exists, otherwise falls back to example.m3u.
  2. M3U parsing (parse_m3u): Reads #EXTINF lines and acestream:// URLs only — non-Acestream URL lines are silently discarded. #EXTGRP lines provide group logos.
  3. Channel grouping (group_channels): Channels sharing the same base_name + group (case-insensitive) are merged into a single channel with multiple mirrors. Each mirror stores resolution and acestream_hash.
  4. Logo resolution (resolve_logo): Priority is local logo by tvg-id slug → local logo by channel name slug → external tvg-logo URL → empty. The logo index strips trailing 2-3 letter country suffixes for fuzzy matching.
  5. Global state: The state dict holds channels, groups, group_meta, and source_file. channels.json is hot-reloaded on /api/channels requests if its mtime changed.

Channel object schema

{
  "id": "dazn-laliga",           // URL-safe slug, deduplicated with -N suffix
  "name": "DAZN LaLiga",         // base name without resolution/quality markers
  "group": "Sports",
  "subcategory": "",             // set manually via JSON import
  "country_code": "es",          // 2-letter ISO, derived from logo path or tvg-logo URL
  "logo_url": "/logos/...",      // local or external URL
  "tags": [],                    // emoji/string tags set manually
  "mirrors": [
    { "resolution": "1080p", "acestream_hash": "abc123..." }
  ]
}

API endpoints

Method Path Description
GET /api/channels Returns current channel list (hot-reloads JSON if changed)
POST /api/import/m3u Upload M3U file, replaces state
POST /api/import/json Upload JSON export, replaces state
GET /api/export/json Download channels as JSON
GET /api/export/m3u Download channels as M3U (Acestream)
GET /logos/<path> Serve files from tv-logos-main/
GET /flags/<code>.svg Serve country flag SVGs from svg/

Key files

  • app.py — entire backend; no separate modules
  • static/index.html — entire frontend; all JS inline, Tailwind via static/tailwind.js
  • channels.json — persisted channel data; auto-loaded at startup; hot-reloaded on change
  • example.m3u — fallback playlist used if channels.json is absent
  • tv-logos-main/ — local PNG logo library (indexed at startup, not committed to git)
  • svg/ — country flag SVGs named by ISO 3166-1 alpha-2 code (e.g. es.svg)

Frontend state

The JS App object in index.html holds all UI state: channels, groups, groupMeta, activeGroup, activeSubcategory, activeTags, search. All rendering is done by renderAll()renderSidebar() + renderGrid(). Event delegation is used throughout (no per-card listeners). Clicking a channel card opens a modal with sorted mirrors (diamond > gold > silver > bronze quality tiers).