From fa08ba833d04fb42785538087c64d0c08f72c243 Mon Sep 17 00:00:00 2001 From: Lyncoln Date: Sat, 31 Jan 2026 22:34:41 -0500 Subject: [PATCH] Initial commit: TVJ EPG script + Dockerfile --- Dockerfile | 22 ++++++++++++++++++ tvj_epg.py | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 Dockerfile create mode 100644 tvj_epg.py diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0700c0f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +# Use slim Python image +FROM python:3.11-slim + +# Set working directory +WORKDIR /app + +# Copy script +COPY tvj_epg.py . + +# Install requests +RUN pip install --no-cache-dir requests + +# Default update interval (hours) +ENV UPDATE_INTERVAL=6 + +# Run the script in a loop, using UPDATE_INTERVAL env variable +CMD sh -c 'while true; do \ + echo "$(date) - Updating TVJ EPG..."; \ + python tvj_epg.py; \ + echo "$(date) - Sleeping for ${UPDATE_INTERVAL} hours..."; \ + sleep $((${UPDATE_INTERVAL}*3600)); \ + done' diff --git a/tvj_epg.py b/tvj_epg.py new file mode 100644 index 0000000..853099f --- /dev/null +++ b/tvj_epg.py @@ -0,0 +1,67 @@ +import requests +import xml.etree.ElementTree as ET +from datetime import datetime, timezone + +# 1SpotMedia API config +API_URL = "https://www.1spotmedia.com/index.php/api/epg/get_epg_timeline_by_id" +CHANNEL_ID = "66e312890478fd00235244cb" +TVG_ID = "TVJ.jm@SD" + +# Output file +OUTPUT_FILE = "/app/output/tvj.xml" + +# Record script start time +script_run_time = datetime.now(tz=timezone.utc) +print(f"[{script_run_time.strftime('%Y-%m-%d %H:%M:%S UTC')}] Script run started.") + +# Fetch EPG data +resp = requests.get(API_URL, params={"id": CHANNEL_ID}, headers={"User-Agent": "Mozilla/5.0"}) +data = resp.json() + +# Determine last update time from API if available +if isinstance(data, dict) and "lastUpdate" in data: + # API may provide a timestamp in milliseconds + api_last_update_ts = data["lastUpdate"] + last_update_time = datetime.fromtimestamp(api_last_update_ts / 1000, tz=timezone.utc) +elif isinstance(data, list) and len(data) > 0: + # Fallback: use the latest program endTime + last_update_time = datetime.fromtimestamp(max(p["endTime"] for p in data) / 1000, tz=timezone.utc) +else: + last_update_time = script_run_time + +# Ensure we have a list of programs +if isinstance(data, dict): + programs = data.get("data", []) +elif isinstance(data, list): + programs = data +else: + programs = [] + +# Create XMLTV root +tv = ET.Element("tv", attrib={"generator-info-name": "custom-1spotmedia"}) + +# Add channel +channel = ET.SubElement(tv, "channel", id=TVG_ID) +ET.SubElement(channel, "display-name").text = "TVJ SD" + +# Add programs +for p in programs: + start = datetime.fromtimestamp(p["startTime"] / 1000, tz=timezone.utc) + stop = datetime.fromtimestamp(p["endTime"] / 1000, tz=timezone.utc) + + programme = ET.SubElement(tv, "programme", + start=start.strftime("%Y%m%d%H%M%S +0000"), + stop=stop.strftime("%Y%m%d%H%M%S +0000"), + channel=TVG_ID) + ET.SubElement(programme, "title").text = p["title"] + if "description" in p: + ET.SubElement(programme, "desc").text = p["description"] + +# Write XMLTV file +tree = ET.ElementTree(tv) +tree.write(OUTPUT_FILE, encoding="utf-8", xml_declaration=True) + +# Log completion with timestamps +completion_time = datetime.now(tz=timezone.utc) +print(f"[{completion_time.strftime('%Y-%m-%d %H:%M:%S UTC')}] XMLTV guide updated successfully: {OUTPUT_FILE}") +print(f"Summary: Script run time = {script_run_time.strftime('%Y-%m-%d %H:%M:%S UTC')}, Last guide update from API = {last_update_time.strftime('%Y-%m-%d %H:%M:%S UTC')}")