From 514c5c4b225f7b4f767d9928b28298c4661eda70 Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Tue, 7 Oct 2025 12:59:28 -0500 Subject: [PATCH 1/2] =?UTF-8?q?v3.0.1=20=E2=80=93=20Add=20EPG=20fallback?= =?UTF-8?q?=20and=20tuner=20refresh=20improvements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Overview This release introduces the new EPG fallback system and fixes tuner refresh behavior to ensure guide data always updates instantly. Also includes a redesigned login page and minor UI polish. ### Major Additions - **EPG Fallback System** - Added `apply_epg_fallback()` helper to ensure all channels display “No Guide Data Available” when XMLTV entries are missing. - Automatically applied after login and when switching tuners. - **Invalid XML Detection** - Added logic to skip `.m3u` or `.m3u8` files used as XML sources to prevent XML parse errors. - When detected, the guide displays fallback placeholders instead of failing silently. - **Guide UI Enhancements** - Updated `guide.html` to render placeholder boxes for channels with missing EPG. - Added `.program.no-guide` CSS for visual distinction (gray/italic text, dashed border). - Template logic improved to handle empty or malformed EPG lists gracefully. - **Tuner Refresh Fix** - Fixed bug where tuner changes required user logout to update the guide. - Now refreshes `cached_channels` and `cached_epg` immediately after tuner switch. - **Login Page Redesign** - Centered floating login box with 3D shadow and right-aligned RetroIPTVGuide logo. - Clean visual alignment consistent with new theming. ### Other Improvements - Added internal debug logging for channel vs. EPG key alignment. - Codebase refactored for readability around EPG parsing and fallback integration. - Updated documentation and version constants (`APP_VERSION = v3.0.1`, `APP_RELEASE_DATE = 2025-10-07`). ### Documentation - Updated CHANGELOG.md with v3.0.1 details. - Updated ROADMAP.md to reflect fallback feature completion. - Updated README.md version badge and new guide feature details. ### Version v3.0.1 (Release Date: 2025-10-07) --- CHANGELOG.md | 38 +++++++++++++++++++++++++++---- README.md | 50 ++++++++++++++++++++-------------------- ROADMAP.md | 4 ++-- app.py | 48 ++++++++++++++++++++++++++++++++++++++- templates/guide.html | 54 +++++++++++++++++++++++++++++++------------- templates/login.html | 2 +- 6 files changed, 146 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e392c0..80d56f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 📑 Changelog +# đź“‘ Changelog All notable changes to this project will be documented here. Format based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -14,6 +14,34 @@ This project follows [Semantic Versioning](https://semver.org/). --- +## [v3.0.1] - 2025-10-07 +### Added +- **EPG Fallback System** + - Channels without XMLTV data now display “No Guide Data Available”. + - Added `apply_epg_fallback()` helper to ensure all channels have at least one program entry. + - Fallback automatically applied after login and tuner switch. +- **Invalid XML Detection** + - If a user enters the same `.m3u` URL for both M3U and XML, the system treats it as invalid XML and loads fallback placeholders instead. +- **Visual Placeholders** + - `guide.html` updated to render gray, italicized “No Guide Data Available” banners in program grid. + - Works across all existing Light/Dark/Retro themes. + +### Changed +- **Tuner Switching Behavior** + - Active tuner now refreshes immediately without requiring logout/relogin. + - Cached channel/EPG data reloaded dynamically when tuner changes. +- **Login Page UI** + - Redesigned with floating centered box, shadow, and right-aligned RetroIPTVGuide logo. + +### Fixed +- **EPG Cache Sync** + - Prevented guide from displaying outdated EPG after tuner change. + - Corrected case where missing XML data produced empty grid. + + +--- + + ## [3.0.0] - 2025-10-03 ### Added - **Windows Support**: @@ -72,7 +100,7 @@ This project follows [Semantic Versioning](https://semver.org/). - Shows dynamic system info: version, release date, Python version, OS, install path, database path, logs path, uptime. - **Admin Log Management**: - Log file size shown on Logs page (human-readable + color-coded). - - Admin-only “Clear Logs” button added to truncate activity log. + - Admin-only “Clear Logs” button added to truncate activity log. - **Automated Version Bump Tool**: - Added `bump_version.py` to sync `APP_VERSION` in app.py with CHANGELOG.md. - Inserts new version section under `[Unreleased]`. @@ -99,7 +127,7 @@ This project follows [Semantic Versioning](https://semver.org/). - Data is pulled from `app.py` constants and runtime environment, no manual edits required. #### Notes -- **Windows validation pending**: Installer and uninstaller are implemented but require verification on Windows; tracked in ROADMAP “Priority Suggestions”. +- **Windows validation pending**: Installer and uninstaller are implemented but require verification on Windows; tracked in ROADMAP “Priority Suggestions”. --- @@ -119,7 +147,7 @@ This project follows [Semantic Versioning](https://semver.org/). -## [v2.0.0] – 2025-09-24 +## [v2.0.0] – 2025-09-24 ### Added - Tuner URL validation: new validate_tuner_url() function checks XML/M3U inputs before saving. - Detects invalid/empty URLs, unresolvable hostnames, and distinguishes between public vs. private IPs. @@ -157,7 +185,7 @@ This project follows [Semantic Versioning](https://semver.org/). --- -## [v1.x.x] – 2025-09-01 → 2025-09-23 +## [v1.x.x] – 2025-09-01 → 2025-09-23 ### Added - Initial IPTV Flask application with: - User authentication (login/logout, password change). diff --git a/README.md b/README.md index e6c9542..739ad57 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,39 @@ # RetroIPTVGuide - + RetroIPTVGuide is an IPTV Web Interface inspired by 90s/2000s cable TV guides. It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https://github.com/ErsatzTV/ErsatzTV/tree/main) but should support any `.m3u` and `.xml` IPTV source. -⚠️ **Note:** This is still a BETA release. It is not recommended for direct Internet/public-facing deployments. +โ��๏ธ� **Note:** This is still a BETA release. It is not recommended for direct Internet/public-facing deployments. - [Installation / Uninstall Guide](INSTALL.md) - [Changelog](CHANGELOG.md) - [Roadmap](ROADMAP.md) - [License](LICENSE) -## ✨ Features (v3.0.0) -- 🔑 **User Authentication** +## โ�จ Features (v3.0.0) +- ๐�”‘ **User Authentication** - Login/logout system with hashed passwords. - Admin and regular user accounts. - Password change functionality. - Admin-only user management (add/delete users). -- 📡 **Tuner Management** +- ๐�“ก **Tuner Management** - Multiple tuner support stored in `tuners.db`. - Switch between active tuners via the web UI. - Update `.m3u` and `.xml` tuner URLs (persisted in DB). -- 📺 **Guide & Playback** - - Program guide rendered from XMLTV. - - Channel list parsed from M3U playlist. +- ๐�“บ **Guide & Playback** + - Program guide rendered from XMLTV with automatic fallback for missing data. + - Channels without guide entries display “No Guide Data Available”. - Video playback using HTML5 + HLS.js. - Playback events logged with user + channel + timestamp. -- 📑 **Logging** +- ๐�“‘ **Logging** - Activity log (`activity.log`) records authentication events, tuner changes, playback, and admin actions. - Admin-only **Logs page** with real-time log viewing. - Log file size display with color coding. - - Admin-only “Clear Logs” button to truncate logs. -- 🎨 **UI Enhancements** - - Unified header across all pages (Guide, Logs, Add User, Delete User, Change Password, Change Tuner). + - Admin-only โ€�Clear Logsโ€� button to truncate logs. +- ๐��จ **UI Enhancements** + - Unified header across all pages (Guide, Logs, Add User, Delete User, Change Password, Change Tuner, Login). - Active tuner display + live clock in header. - **Themes submenu** with multiple options: - Light @@ -41,8 +41,8 @@ It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https: - AOL/CompuServe - TV Guide Magazine - Theme persistence stored in browser localStorage, applied instantly across all pages. - - **About Page under Settings menu** — shows version, Python, OS, uptime, paths. -- ⚙️ **System** + - **About Page under Settings menu** โ€” shows version, Python, OS, uptime, paths. +- โ��๏ธ� **System** - Automatic initialization of `users.db` and `tuners.db` on first run. - SQLite databases use WAL mode for better concurrency. - Preloads tuner/channel/guide data from DB on startup. @@ -52,7 +52,7 @@ It is designed to work with [ErsatzTV](https://ersatztv.org/) [(GitRepo)](https: --- -## 🌐 Browser Compatibility +## ๐��� Browser Compatibility This project is designed to work with **all major browsers**. It has been tested on: - Firefox @@ -60,7 +60,7 @@ It has been tested on: - Safari - Edge -## 💻 Tested Devices & OS +## ๐�’ป Tested Devices & OS The web interface has been tested on: - **Ubuntu (desktop/server)** - **iOS (mobile/tablet)** @@ -70,31 +70,31 @@ The web interface has been tested on: - **MacOS** - **Windows** -## 🛠️ Installation Platform +## ๐���๏ธ� Installation Platform - **Debian Based Linux (desktop/server)** - **Windows 10/11** -## 📺 Screenshots +## ๐�“บ Screenshots -## 📺 Guide Page +## ๐�“บ Guide Page  -## 📺 Video Pop Out +## ๐�“บ Video Pop Out  -## 📺 Video Pop Out on Desktop +## ๐�“บ Video Pop Out on Desktop  -## 📺 TV Guide Magazine Theme +## ๐�“บ TV Guide Magazine Theme  -## 📺 AOL / CompuServe Theme +## ๐�“บ AOL / CompuServe Theme  --- -## 🤝 Contributing -Contributions are welcome! Here’s how you can help: +## ๐�ค� Contributing +Contributions are welcome! Hereโ€�s how you can help: 1. **Report Issues**: Found a bug or want to suggest a feature? Open an [issue](../../issues). 2. **Submit Pull Requests**: Fork the repo, make changes, and submit a PR. Please ensure code is tested before submitting. 3. **Improve Documentation**: Help refine the installation guide, add screenshots, or improve explanations in the README. diff --git a/ROADMAP.md b/ROADMAP.md index fc8290f..7704779 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -10,7 +10,7 @@ These are **not yet implemented**, but provide a development path for future rel ### 1. Tuner Management - [x] Add ability to **add/remove tuners** from the UI (v2.3.0). - [x] Add ability to rename tuners via the UI (v2.3.0). -- [ ] Support for **.m3u8 single-channel playlists** as tuner sources. +- [ ] Support for **.m3u8 single-channel playlists** as tuner sources (planned v3.1.0). - Option A: Special-case `.m3u8` handling in parser. - Option B: Add explicit `hls` column to `tuners.db`. - [x] Validate tuner URLs (ping/check format before saving) (v2.0.0). @@ -26,8 +26,8 @@ These are **not yet implemented**, but provide a development path for future rel ### 3. Guide & Playback - [ ] Add **search/filter box** to guide for channels/programs. - [ ] Add ability to set **favorites** for quick channel access. +- [x] Add fallback message (“No Guide Data Available”) for channels missing EPG info (v3.0.1). - [ ] Add **reminders/notifications** for upcoming programs. -- [ ] (Future) Support recording/saving streams for offline playback. ### 4. User Management - [ ] Add role-based access control (admin, regular user, read-only). diff --git a/app.py b/app.py index b0cfbb3..47e405e 100644 --- a/app.py +++ b/app.py @@ -1,4 +1,4 @@ -APP_VERSION = "v3.0.0" +APP_VERSION = "v3.0.1" APP_RELEASE_DATE = "2025-09-26" from flask import Flask, render_template, request, redirect, url_for, flash @@ -225,6 +225,11 @@ def parse_m3u(m3u_url): # ------------------- XMLTV EPG Parsing ------------------- def parse_epg(xml_url): programs = {} + + # ✅ Handle when user pastes same .m3u for XML + if xml_url.lower().endswith(('.m3u', '.m3u8')): + return programs # empty, fallback will fill it later + try: r = requests.get(xml_url, timeout=15) r.raise_for_status() @@ -261,6 +266,23 @@ def parse_epg(xml_url): programs[cid].append({'title': title, 'desc': desc, 'start': start, 'stop': stop}) return programs +# ------------------- EPG Fallback Helper ------------------- +def apply_epg_fallback(channels, epg): + """Ensure each channel has at least one program entry, even if missing in XML.""" + for ch in channels: + tvg_id = ch.get('tvg_id') + if not tvg_id: + continue + if tvg_id not in epg or not epg[tvg_id]: + epg[tvg_id] = [{ + 'title': 'No Guide Data Available', + 'desc': '', + 'start': None, + 'stop': None + }] + return epg + + # ------------------- Routes ------------------- @app.route('/') def home(): @@ -282,6 +304,8 @@ def login(): global cached_channels, cached_epg cached_channels = parse_m3u(m3u_url) cached_epg = parse_epg(xml_url) + # ✅ Apply “No Guide Data Available” fallback + cached_epg = apply_epg_fallback(cached_channels, cached_epg) return redirect(url_for('guide')) else: log_event(username if username else "unknown", "Failed login attempt") @@ -414,6 +438,16 @@ def change_tuner(): log_event(current_user.username, f"Switched active tuner to {new_tuner}") flash(f"Active tuner switched to {new_tuner}") + # ✅ Refresh cached guide data immediately + global cached_channels, cached_epg + tuners = get_tuners() + m3u_url = tuners[new_tuner]["m3u"] + xml_url = tuners[new_tuner]["xml"] + cached_channels = parse_m3u(m3u_url) + cached_epg = parse_epg(xml_url) + # ✅ Apply “No Guide Data Available” fallback + cached_epg = apply_epg_fallback(cached_channels, cached_epg) + elif action == "update_urls": tuner = request.form["tuner"] xml_url = request.form["xml_url"] @@ -485,6 +519,18 @@ def guide(): total_width = slots * SLOT_MINUTES * SCALE minutes_from_start = (now - grid_start).total_seconds() / 60.0 now_offset = int(minutes_from_start * SCALE) + + # --- DEBUG: Show alignment between M3U and EPG --- + #print("\n=== DEBUG: Cached Channels and EPG Keys ===") + #print("First 5 channel IDs from M3U:") + #for ch in cached_channels[:5]: + # print(" ", ch.get('tvg_id')) + + #print("\nFirst 5 EPG keys:") + #for key in list(cached_epg.keys())[:5]: + # print(" ", key) + #print("==========================================\n") + return render_template( 'guide.html', diff --git a/templates/guide.html b/templates/guide.html index 91f8371..cc1ad11 100644 --- a/templates/guide.html +++ b/templates/guide.html @@ -208,6 +208,15 @@ body.retro-magazine .now-line { background:#000; height:3px; } body.retro-magazine #current-tuner { color:#000000 !important; font-weight:bold; } + /* Placeholder when no guide data exists */ + .program.no-guide { + font-style: italic; + color: #999; + background: #2a2a2a; + border: 1px dashed #555; + } + + @@ -299,22 +308,35 @@
{{ msg }}
+{{ msg }}
{% endfor %} {% endif %} {% endwith %} From 8ea58f07df0b412d557047e74f4793182a67b97b Mon Sep 17 00:00:00 2001 From: thehack904 <35552907+thehack904@users.noreply.github.com> Date: Tue, 7 Oct 2025 13:24:49 -0500 Subject: [PATCH 2/2] Update install.sh Bumped version to correct 3.0.1 and added Installation complete statement back on linux install --- install.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/install.sh b/install.sh index 56d3bd5..d17c79a 100644 --- a/install.sh +++ b/install.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -VERSION="2.1.0" +VERSION="3.0.1" TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S") LOGFILE="install_${TIMESTAMP}.log" @@ -220,6 +220,14 @@ else echo "Unsupported environment: $OSTYPE" exit 1 fi + +echo "" +echo "Installation complete!" +echo "End time: $(date)" +echo "Access the server in your browser at: http://