Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import tkinter as tk
- from tkinter import messagebox, filedialog, ttk
- import requests
- import re
- class M3UTransformer:
- def __init__(self, root):
- self.root = root
- self.root.title("NAJEEB M3U Transformer")
- self.root.geometry("900x600") # Set fixed window size
- self.root.resizable(False, False) # Lock window size
- self.channels = [] # List to store channel data
- # Define a style for ttk widgets
- self.style = ttk.Style()
- self.style.theme_use("clam") # Modern theme
- self.style.configure("TLabel", font=("Arial", 10), background="#f0f0f0", foreground="#333333", padding=5)
- self.style.configure("TButton", font=("Arial", 10), padding=5)
- self.style.map("Download.TButton", background=[("active", "#4CAF50"), ("!active", "#45a049")])
- self.style.map("Browse.TButton", background=[("active", "#2196F3"), ("!active", "#1E88E5")])
- self.style.map("Convert.TButton", background=[("active", "#FF9800"), ("!active", "#FB8C00")])
- self.style.configure("TEntry", font=("Arial", 10), padding=5)
- # GUI Components
- self.create_widgets()
- def create_widgets(self):
- # URL Entry
- ttk.Label(self.root, text="Enter M3U URL:").grid(row=0, column=0, sticky="e", padx=10, pady=10)
- self.url_entry = ttk.Entry(self.root, width=90)
- self.url_entry.grid(row=0, column=1, padx=10, pady=10)
- # Download Button
- ttk.Button(self.root, text="Download & Transform", style="Download.TButton", command=self.download_and_transform).grid(
- row=0, column=2, padx=10, pady=10
- )
- # Browse File Button
- ttk.Button(self.root, text="Browse & Transform", style="Browse.TButton", command=self.browse_and_transform).grid(
- row=1, column=2, padx=10, pady=10
- )
- # Raw Text Conversion Section
- ttk.Label(self.root, text="Paste Raw Text:").grid(row=1, column=0, sticky="ne", padx=10, pady=10)
- # Add a scrollbar to the raw text field
- self.raw_text_frame = ttk.Frame(self.root)
- self.raw_text_frame.grid(row=2, column=1, padx=10, pady=10, sticky="nsew")
- self.raw_text_scrollbar = ttk.Scrollbar(self.raw_text_frame, orient="vertical")
- self.raw_text_scrollbar.pack(side="right", fill="y")
- self.raw_text = tk.Text(self.raw_text_frame, width=50, height=10, yscrollcommand=self.raw_text_scrollbar.set, bg="#ffffff", fg="#333333", font=("Arial", 10))
- self.raw_text.pack(side="left", fill="both", expand=True)
- self.raw_text_scrollbar.config(command=self.raw_text.yview)
- # Convert Raw Text Button
- ttk.Button(self.root, text="Convert Raw Text", style="Convert.TButton", command=self.convert_raw_text).grid(
- row=2, column=2, padx=10, pady=10
- )
- # Status Label
- self.status_label = ttk.Label(self.root, text="Enter M3U URL, browse for a file, or paste raw text.", background="#f0f0f0", foreground="#333333")
- self.status_label.grid(row=3, column=0, columnspan=3, pady=20)
- # Configure grid to make it responsive
- self.root.grid_rowconfigure(2, weight=1)
- self.root.grid_columnconfigure(1, weight=1)
- def download_and_transform(self):
- """Download the M3U file from the provided URL and transform it."""
- m3u_url = self.url_entry.get().strip()
- if not m3u_url:
- messagebox.showwarning("Warning", "Please enter a valid M3U URL.")
- return
- try:
- # Download the M3U file
- self.status_label.config(text="Downloading M3U file...")
- response = requests.get(m3u_url)
- response.raise_for_status() # Raise an error for bad responses (4xx, 5xx)
- m3u_content = response.text.splitlines()
- # Transform and save the M3U file
- self.transform_and_save(m3u_content, source="URL")
- except requests.exceptions.RequestException as e:
- self.status_label.config(text="Error downloading M3U file.")
- messagebox.showerror("Error", f"Failed to download M3U file: {e}")
- except Exception as e:
- self.status_label.config(text="Error transforming M3U file.")
- messagebox.showerror("Error", f"An error occurred: {e}")
- def browse_and_transform(self):
- """Browse for an M3U file on the local PC and transform it."""
- file_path = filedialog.askopenfilename(filetypes=[("M3U Files", "*.m3u")])
- if not file_path:
- return
- try:
- # Read the M3U file
- self.status_label.config(text="Reading local M3U file...")
- with open(file_path, "r", encoding="utf-8") as file:
- m3u_content = file.readlines()
- # Transform and save the M3U file
- self.transform_and_save(m3u_content, source="Local File")
- except Exception as e:
- self.status_label.config(text="Error reading M3U file.")
- messagebox.showerror("Error", f"An error occurred: {e}")
- def convert_raw_text(self):
- """Convert raw text input into an M3U file."""
- raw_input = self.raw_text.get("1.0", tk.END).strip()
- if not raw_input:
- messagebox.showwarning("Warning", "Please paste raw text containing channel names and URLs.")
- return
- try:
- # Parse raw text into channel name and stream URL pairs
- self.status_label.config(text="Parsing raw text...")
- lines = raw_input.splitlines()
- self.channels.clear()
- for line in lines:
- match = re.match(r"^(.+)\s+(https?://.+)$", line.strip())
- if match:
- channel_name = match.group(1).strip()
- stream_url = match.group(2).strip()
- # Construct new EXTINF line in the desired format
- new_extinf = (
- f'#EXTINF:-1 tvg-name="{channel_name}" '
- f'tvg-id="{channel_name.lower().replace(" ", "_")}" '
- f'tvg-logo="" tvg-subtitle="", {channel_name}'
- )
- self.channels.append((new_extinf, stream_url))
- # Save the transformed M3U file locally
- output_file = "converted_playlist.m3u"
- with open(output_file, "w", encoding="utf-8") as file:
- for extinf, url in self.channels:
- file.write(extinf + "\n")
- file.write(url + "\n")
- self.status_label.config(text=f"Conversion complete! Saved as '{output_file}'")
- messagebox.showinfo("Success", f"Converted M3U file saved as '{output_file}'")
- except Exception as e:
- self.status_label.config(text="Error converting raw text.")
- messagebox.showerror("Error", f"An error occurred: {e}")
- def transform_and_save(self, m3u_content, source):
- """Transform the M3U content and save it to a new file."""
- self.channels.clear()
- i = 0
- while i < len(m3u_content):
- line = m3u_content[i].strip()
- if line.startswith("#EXTINF"):
- # Extract channel name from the EXTINF line
- match = re.search(r',\s*(.+)', line)
- if match:
- channel_name = match.group(1)
- stream_url = m3u_content[i + 1].strip()
- # Construct new EXTINF line in the desired format
- new_extinf = (
- f'#EXTINF:-1 tvg-name="{channel_name}" '
- f'tvg-id="{channel_name.lower().replace(" ", "_")}" '
- f'tvg-logo="" tvg-subtitle="", {channel_name}'
- )
- self.channels.append((new_extinf, stream_url))
- i += 2
- else:
- i += 1
- # Save the transformed M3U file locally
- output_file = "transformed_playlist.m3u"
- with open(output_file, "w", encoding="utf-8") as file:
- for extinf, url in self.channels:
- file.write(extinf + "\n")
- file.write(url + "\n")
- self.status_label.config(text=f"Transformation complete! Saved as '{output_file}'")
- messagebox.showinfo(
- "Success",
- f"Transformed M3U file saved as '{output_file}' (Source: {source})"
- )
- if __name__ == "__main__":
- root = tk.Tk()
- app = M3UTransformer(root)
- root.mainloop()
Add Comment
Please, Sign In to add comment