Spaces:
Paused
Paused
Download app.py from gopallikehack/Gpsirdb: direct link, hf CLI and curl.
- Browser
- Download file 4.67 kB
-
https://huggingface.co/spaces/gopallikehack/Gpsirdb/resolve/main/app.py
- Command line
-
hf download hf://spaces/gopallikehack/Gpsirdb/app.py
-
curl -L -o app.py https://huggingface.co/spaces/gopallikehack/Gpsirdb/resolve/main/app.py
4.67 kB
| import re | |
| from urllib.parse import urljoin, quote | |
| import requests | |
| from flask import Flask, request, Response, jsonify, send_from_directory | |
| app = Flask(__name__, static_folder="static", static_url_path="/static") | |
| UA = ( | |
| "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " | |
| "(KHTML, like Gecko) Chrome/124.0 Safari/537.36" | |
| ) | |
| TIMEOUT = 20 | |
| def fetch(url, stream=False): | |
| headers = {"User-Agent": UA, "Accept": "*/*"} | |
| return requests.get( | |
| url, headers=headers, timeout=TIMEOUT, stream=stream, allow_redirects=True | |
| ) | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # /api/parse β fetch M3U, return JSON of channels | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| def api_parse(): | |
| url = request.args.get("url") | |
| if not url: | |
| return jsonify({"error": "missing url"}), 400 | |
| try: | |
| r = fetch(url) | |
| r.raise_for_status() | |
| text = r.text | |
| except Exception as e: | |
| return jsonify({"error": f"fetch failed: {e}"}), 502 | |
| channels = parse_m3u(text) | |
| return jsonify({"count": len(channels), "channels": channels}) | |
| def parse_m3u(text): | |
| channels = [] | |
| lines = [ln.strip() for ln in text.splitlines() if ln.strip()] | |
| pending = None | |
| for line in lines: | |
| if line.startswith("#EXTINF"): | |
| info = {"name": "", "logo": "", "group": "", "tvg_id": ""} | |
| m = re.search(r'tvg-logo="([^"]+)"', line) | |
| if m: info["logo"] = m.group(1) | |
| m = re.search(r'group-title="([^"]+)"', line) | |
| if m: info["group"] = m.group(1) | |
| m = re.search(r'tvg-id="([^"]+)"', line) | |
| if m: info["tvg_id"] = m.group(1) | |
| if "," in line: | |
| info["name"] = line.split(",", 1)[1].strip() | |
| pending = info | |
| elif line.startswith("#"): | |
| continue | |
| else: | |
| if pending is not None: | |
| pending["url"] = line | |
| channels.append(pending) | |
| pending = None | |
| return channels | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # /api/proxy β proxy HLS playlists + segments with CORS | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| def api_proxy(): | |
| target = request.args.get("url") | |
| if not target: | |
| return Response("missing url", status=400) | |
| try: | |
| upstream = fetch(target, stream=True) | |
| except Exception as e: | |
| return Response(f"fetch failed: {e}", status=502) | |
| content_type = upstream.headers.get("Content-Type", "") | |
| if "mpegurl" in content_type.lower() or target.endswith(".m3u8"): | |
| body = upstream.content.decode("utf-8", errors="replace") | |
| rewritten = rewrite_playlist(body, target) | |
| return Response( | |
| rewritten, | |
| headers={ | |
| "Access-Control-Allow-Origin": "*", | |
| "Content-Type": "application/vnd.apple.mpegurl", | |
| }, | |
| ) | |
| def generate(): | |
| for chunk in upstream.iter_content(chunk_size=64 * 1024): | |
| if chunk: | |
| yield chunk | |
| return Response( | |
| generate(), | |
| headers={ | |
| "Access-Control-Allow-Origin": "*", | |
| "Content-Type": content_type or "application/octet-stream", | |
| }, | |
| ) | |
| def rewrite_playlist(body, base_url): | |
| out = [] | |
| for line in body.splitlines(): | |
| s = line.strip() | |
| if not s: | |
| out.append(line) | |
| continue | |
| if s.startswith("#"): | |
| def repl(m): | |
| u = m.group(1) | |
| abs_u = urljoin(base_url, u) | |
| return f'URI="/api/proxy?url={quote(abs_u, safe="")}"' | |
| out.append(re.sub(r'URI="([^"]+)"', repl, line)) | |
| else: | |
| abs_u = urljoin(base_url, s) | |
| out.append(f"/api/proxy?url={quote(abs_u, safe='')}") | |
| return "\n".join(out) | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| # Serve the frontend | |
| # βββββββββββββββββββββββββββββββββββββββββββββ | |
| def index(): | |
| return send_from_directory("static", "index.html") | |
| if __name__ == "__main__": | |
| app.run(host="0.0.0.0", port=7860) |