diff --git a/generate.py b/generate.py index 9ea3182..e377577 100644 --- a/generate.py +++ b/generate.py @@ -1,22 +1,31 @@ import requests from flask import Flask, Response +from flask_cors import CORS +import threading app = Flask(__name__) +CORS(app) # Enable CORS for all routes # List of M3U file URLs -urls = [ +URLS = [ "https://iptv-org.github.io/iptv/index.country.m3u", "https://forge.fsky.io/frost/repo/raw/branch/main/tv.m3u", "https://raw.githubusercontent.com/Free-TV/IPTV/refs/heads/master/playlist.m3u8" ] -combined_m3u = None # Variable to store the combined M3U content +# Cached M3U content and a lock for thread safety +combined_m3u = None +lock = threading.Lock() def fetch_m3u(url): - """Fetch M3U content from a given URL.""" - response = requests.get(url) - response.raise_for_status() # Raise an error for bad responses - return response.text + """Fetch M3U content from a given URL with error handling.""" + try: + response = requests.get(url, timeout=5) # Set timeout to prevent long waits + response.raise_for_status() # Raise an error for bad responses + return response.text + except requests.RequestException as e: + print(f"Error fetching {url}: {e}") + return "" def combine_m3u(urls): """Combine M3U content from multiple URLs and remove duplicates.""" @@ -31,29 +40,29 @@ def combine_m3u(urls): if line.startswith('#EXTINF:'): current_entry = line elif line and current_entry: - # Use the stream link as the key to ensure uniqueness stream_link = line.strip() if stream_link not in unique_streams: - unique_streams[stream_link] = current_entry + '\n' + stream_link - current_entry = None # Reset current entry after adding + unique_streams[stream_link] = f"{current_entry}\n{stream_link}" + current_entry = None # Reset after adding - # Return the combined M3U content return '#EXTM3U\n' + '\n'.join(unique_streams.values()) -@app.route('/all.m3u8') +@app.route('/all.m3u') def serve_m3u(): - """Serve the combined M3U file.""" + """Serve the cached combined M3U file, generating it if necessary.""" global combined_m3u - if combined_m3u is None: # Generate if not already done - combined_m3u = combine_m3u(urls) + with lock: + if combined_m3u is None: # Generate if not already done + combined_m3u = combine_m3u(URLS) return Response(combined_m3u, mimetype='application/vnd.apple.mpegurl') @app.route('/generate') def generate_m3u(): - """Regenerate the M3U file from the sources.""" + """Force regeneration of the M3U file from the sources.""" global combined_m3u - combined_m3u = combine_m3u(urls) # Regenerate the M3U content + with lock: + combined_m3u = combine_m3u(URLS) # Regenerate the M3U content return Response("M3U playlist regenerated!", mimetype='text/plain') if __name__ == '__main__': - app.run(host='0.0.0.0', port=5000) + app.run(host='0.0.0.0', port=5000, threaded=True)