import re import requests import gradio as gr from pathlib import Path import random import string def _random_name(ext=".m3u", length=3): # Make a very short random filename like a9z.m3u return "".join(random.choices(string.ascii_lowercase + string.digits, k=length)) + ext def _to_raw_github(url: str) -> str: if "github.com" in url and "/blob/" in url: return url.replace("github.com", "raw.githubusercontent.com").replace("/blob/", "/") return url def _clean_parenthetical(text: str) -> str: m = re.search(r"\(([^)]*)\)", text) if not m: return text inside = m.group(1) parts = [p.strip() for p in inside.split(" / ")] mt_seg = None for p in parts: if re.search(r"\bMT\b", p): mt_seg = p break if not mt_seg: return text mt_seg_clean = mt_seg.replace(",", "") start, end = m.span() return text[:start] + f"({mt_seg_clean})" + text[end:] def _filter_text(content: str) -> str: out_lines = [] for line in content.splitlines(): if "(" in line and " / " in line and "MT" in line: out_lines.append(_clean_parenthetical(line)) else: out_lines.append(line) return "\n".join(out_lines) def filter_from_url(url: str): if not url or not url.strip(): return "Please paste a URL." url = _to_raw_github(url.strip()) try: r = requests.get(url, timeout=20) except Exception as e: return f"Error fetching file: {e}" if r.status_code != 200: return f"Error fetching file: HTTP {r.status_code}" filtered = _filter_text(r.text) out_path = Path("/tmp") / _random_name() out_path.write_text(filtered, encoding="utf-8") return str(out_path) def filter_from_file(file_obj): if file_obj is None: return "Please upload a file." text = Path(file_obj.name).read_text(encoding="utf-8", errors="ignore") filtered = _filter_text(text) out_path = Path("/tmp") / _random_name() out_path.write_text(filtered, encoding="utf-8") return str(out_path) with gr.Blocks(title="M3U Cleaner") as demo: gr.Markdown("### removes commas in short random name like `a9z`.") with gr.Tab("From URL"): url_in = gr.Textbox(label="M3U URL", placeholder="https://…/file.m3u8") url_btn = gr.Button("Clean") url_out = gr.File(label="Download filtered M3U") url_btn.click(filter_from_url, inputs=url_in, outputs=url_out) with gr.Tab("From File"): file_in = gr.File(label="Upload .m3u or .m3u8") file_btn = gr.Button("Clean") file_out = gr.File(label="Download filtered M3U") file_btn.click(filter_from_file, inputs=file_in, outputs=file_out) demo.queue() if __name__ == "__main__": demo.launch()