Added code that generates playlist and epg
All checks were successful
AWS Deploy on Push / build (push) Successful in 1m14s

This commit is contained in:
2025-05-15 12:18:38 -05:00
parent 26f57c39ba
commit 8c9ea4187e
8 changed files with 409 additions and 1 deletions

View File

View File

@@ -0,0 +1,135 @@
import os
import argparse
import requests
import logging
from requests.exceptions import RequestException, Timeout, ConnectionError, HTTPError
class StreamValidator:
def __init__(self, timeout=10, user_agent=None):
self.timeout = timeout
self.session = requests.Session()
self.session.headers.update({
'User-Agent': user_agent or 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
})
def validate_stream(self, url):
"""Validate a media stream URL with multiple fallback checks"""
try:
headers = {'Range': 'bytes=0-1024'}
with self.session.get(
url,
headers=headers,
timeout=self.timeout,
stream=True,
allow_redirects=True
) as response:
if response.status_code not in [200, 206]:
return False, f"Invalid status code: {response.status_code}"
content_type = response.headers.get('Content-Type', '')
if not self._is_valid_content_type(content_type):
return False, f"Invalid content type: {content_type}"
try:
next(response.iter_content(chunk_size=1024))
return True, "Stream is valid"
except (ConnectionError, Timeout):
return False, "Connection failed during content read"
except HTTPError as e:
return False, f"HTTP Error: {str(e)}"
except ConnectionError as e:
return False, f"Connection Error: {str(e)}"
except Timeout:
return False, "Connection timeout"
except RequestException as e:
return False, f"Request Exception: {str(e)}"
except Exception as e:
return False, f"Validation error: {str(e)}"
def _is_valid_content_type(self, content_type):
valid_types = [
'video/mp2t', 'application/vnd.apple.mpegurl',
'application/dash+xml', 'video/mp4',
'video/webm', 'application/octet-stream',
'application/x-mpegURL'
]
return any(ct in content_type for ct in valid_types)
def parse_playlist(self, file_path):
"""Extract stream URLs from M3U playlist file"""
urls = []
try:
with open(file_path, 'r') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#'):
urls.append(line)
except Exception as e:
logging.error(f"Error reading playlist file: {str(e)}")
raise
return urls
def main():
parser = argparse.ArgumentParser(
description='Validate streaming URLs from command line arguments or playlist files',
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument(
'sources',
nargs='+',
help='List of URLs or file paths containing stream URLs'
)
parser.add_argument(
'--timeout',
type=int,
default=20,
help='Timeout in seconds for stream checks'
)
parser.add_argument(
'--output',
default='deadstreams.txt',
help='Output file name for inactive streams'
)
args = parser.parse_args()
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[logging.FileHandler('stream_check.log'), logging.StreamHandler()]
)
validator = StreamValidator(timeout=args.timeout)
dead_streams = []
all_urls = []
# Process command line arguments
for source in args.sources:
if os.path.isfile(source):
try:
all_urls.extend(validator.parse_playlist(source))
logging.info(f"Parsed playlist file: {source}")
except Exception as e:
logging.error(f"Failed to process file {source}: {str(e)}")
else:
all_urls.append(source)
# Validate all collected URLs
for url in all_urls:
logging.info(f"Checking: {url}")
valid, message = validator.validate_stream(url)
status = "ALIVE" if valid else "DEAD"
print(f"{url}\nStatus: {status}\nDetails: {message}\n")
if not valid:
dead_streams.append(url)
# Save dead streams to file
if dead_streams:
with open(args.output, 'w') as f:
f.write('\n'.join(dead_streams))
logging.info(f"Found {len(dead_streams)} dead streams. Saved to {args.output}.")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,15 @@
import os
from dotenv import load_dotenv
# Load environment variables from a .env file if it exists
load_dotenv()
IPTV_SERVER_URL = os.getenv("IPTV_SERVER_URL", "https://iptv.fiorinis.com")
# Super iptv-server admin credentials for basic auth
# Reads from environment variables IPTV_SERVER_ADMIN_USER and IPTV_SERVER_ADMIN_PASSWORD
IPTV_SERVER_ADMIN_USER = os.getenv("IPTV_SERVER_ADMIN_USER", "admin")
IPTV_SERVER_ADMIN_PASSWORD = os.getenv("IPTV_SERVER_ADMIN_PASSWORD", "adminpassword")
# URL for the EPG XML file to place in the playlist's header
EPG_URL = os.getenv("EPG_URL", "https://example.com/epg.xml.gz")