Najeebsk

IPTV-M3U-YOUTUBE-PREVIEW2.0.pyw

May 26th, 2024
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 17.64 KB | None | 0 0
  1. import os
  2. import tkinter as tk
  3. from tkinter import ttk, filedialog, messagebox
  4. import requests
  5. import subprocess
  6. import threading
  7. import time
  8. import vlc
  9. import chardet
  10. from youtube_dl import YoutubeDL  # or use yt-dlp
  11. from apiclient.discovery import build
  12. from pytube import YouTube
  13.  
  14. # Constants
  15. YOUTUBE_API_KEY = 'AIzaSyCzS7PGThVFxD83UFbfU5DOSZBMTxNpEeA'
  16. YOUTUBE_API_SERVICE_NAME = 'youtube'
  17. YOUTUBE_API_VERSION = 'v3'
  18.  
  19.  
  20. def play_youtube_video():
  21.     try:
  22.         selected_channel = result_text.get(tk.ACTIVE)
  23.         if selected_channel in channels_info:
  24.             url = channels_info[selected_channel]
  25.             yt = YouTube(url)
  26.             video_url = yt.streams.filter(progressive=True, file_extension='mp4').first().url
  27.  
  28.             media = instance.media_new(video_url)
  29.             player.set_media(media)
  30.             player.play()
  31.     except Exception as e:
  32.         messagebox.showerror("Error", f"An error occurred while playing the video: {e}")
  33.  
  34. def play_local_video(url):
  35.     try:
  36.         subprocess.Popen([r"C:\Program Files\VideoLAN\VLC\vlc.exe", url])
  37.     except Exception as e:
  38.         messagebox.showerror("Error", f"An error occurred while playing the video: {e}")
  39. # Functions for the main functionalities
  40. def search_channels():
  41.     search_term = url_entry.get().lower()
  42.     if search_term.startswith("http"):
  43.         search_by_url(search_term)
  44.     else:
  45.         search_by_path_or_category(search_term)
  46.  
  47. def search_by_url(url):
  48.     try:
  49.         if os.path.exists(url):
  50.             with open(url, 'r', encoding='utf-8') as file:
  51.                 m3u_data = file.readlines()
  52.             process_m3u_data(m3u_data)
  53.         else:
  54.             response = requests.get(url)
  55.             if response.status_code == 200:
  56.                 try:
  57.                     m3u_data = response.text.split('\n')
  58.                 except UnicodeDecodeError:
  59.                     m3u_data = response.content.decode('ISO-8859-1').split('\n')
  60.                 process_m3u_data(m3u_data)
  61.             else:
  62.                 result_text.insert(tk.END, f"Error: Failed to fetch channel data. Status Code: {response.status_code}\n")
  63.     except Exception as e:
  64.         result_text.insert(tk.END, f"Error: {str(e)}\n")
  65.  
  66. def search_by_path_or_category(path):
  67.     try:
  68.         if os.path.exists(path):
  69.             try:
  70.                 with open(path, 'r', encoding='utf-8') as file:
  71.                     m3u_data = file.readlines()
  72.             except UnicodeDecodeError:
  73.                 with open(path, 'r', encoding='ISO-8859-1') as file:
  74.                     m3u_data = file.readlines()
  75.             process_m3u_data(m3u_data)
  76.         else:
  77.             selected_category = category_var.get()
  78.             if selected_category in category_urls:
  79.                 category_url = category_urls[selected_category]
  80.                 if category_url:
  81.                     search_by_url(category_url)
  82.                 else:
  83.                     result_text.insert(tk.END, f"Error: Category URL is not provided for {selected_category}\n")
  84.             else:
  85.                 result_text.insert(tk.END, f"Error: Category '{selected_category}' not found\n")
  86.     except Exception as e:
  87.         result_text.insert(tk.END, f"Error: {str(e)}\n")
  88.  
  89. def process_m3u_data(m3u_data):
  90.     result_text.delete(0, tk.END)
  91.     global channels_info
  92.     channels_info = {}
  93.     channel_name = None
  94.     for line in m3u_data:
  95.         if line.startswith('#EXTINF:'):
  96.             channel_name = line.split(',')[-1].strip()
  97.         elif line.startswith('http') and channel_name:
  98.             channels_info[channel_name] = line.strip()
  99.             result_text.insert(tk.END, channel_name)
  100.             channel_name = None
  101.  
  102. def search_youtube():
  103.     query = search_entry.get()
  104.     youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION, developerKey=YOUTUBE_API_KEY)
  105.     search_response = youtube.search().list(q=query, part='id,snippet', maxResults=10).execute()
  106.     result_text.delete(0, tk.END)
  107.     global channels_info
  108.     channels_info = {}
  109.     for item in search_response['items']:
  110.         if item['id']['kind'] == 'youtube#video':
  111.             video_title = item['snippet']['title']
  112.             video_id = item['id']['videoId']
  113.             video_url = f"https://www.youtube.com/watch?v={video_id}"
  114.             channels_info[video_title] = video_url
  115.             result_text.insert(tk.END, video_title)
  116.             print("Searching YouTube for:", query)
  117.  
  118. def play_selected_channel(event):
  119.     try:
  120.         selected_channel = result_text.get(tk.ACTIVE)
  121.         if selected_channel in channels_info:
  122.             url = channels_info[selected_channel]
  123.             if 'youtube.com' in url or 'youtu.be' in url:
  124.                 download_and_play_youtube(url)
  125.             elif os.path.exists(url):
  126.                 subprocess.Popen([r"C:\Program Files\VideoLAN\VLC\vlc.exe", url])
  127.     except (tk.TclError, KeyError):
  128.         pass
  129.  
  130. def download_and_play_youtube(url):
  131.     ydl_opts = {'format': 'best'}
  132.     with YoutubeDL(ydl_opts) as ydl:
  133.         info_dict = ydl.extract_info(url, download=False)
  134.         video_url = info_dict['url']
  135.         subprocess.Popen([r"C:\Program Files\VideoLAN\VLC\vlc.exe", video_url])
  136.  
  137. def check_links():
  138.     global working_links
  139.     working_links = {}
  140.     for channel_name, url in channels_info.items():
  141.         try:
  142.             response = requests.get(url)
  143.             if response.status_code == 200:
  144.                 working_links[channel_name] = url
  145.         except requests.RequestException:
  146.             pass
  147.  
  148.     result_text.delete(0, tk.END)
  149.     for channel_name, url in working_links.items():
  150.         result_text.insert(tk.END, f"{channel_name}: {url}\n")
  151.  
  152. def save_working_links():
  153.     with open("working_channels.m3u", "w", encoding="utf-8") as f:
  154.         for channel_name, url in working_links.items():
  155.             f.write(f"#EXTINF:-1,{channel_name}\n{url}\n")
  156.  
  157. def filter_channels(event=None):
  158.     keyword = search_entry.get().lower()
  159.     result_text.delete(0, tk.END)
  160.     for channel_name, url in channels_info.items():
  161.         if keyword in channel_name.lower():
  162.             result_text.insert(tk.END, channel_name)
  163.  
  164. def browse_file():
  165.     file_path = filedialog.askopenfilename(filetypes=[("M3U Files", "*.m3u"), ("All Files", "*.*")])
  166.     if file_path:
  167.         url_entry.delete(0, tk.END)
  168.         url_entry.insert(0, file_path)
  169.  
  170. def preview_selected_link():
  171.     def play_media():
  172.         selected_channel = result_text.get(tk.ACTIVE).strip()
  173.         if selected_channel in channels_info:
  174.             url = channels_info[selected_channel]
  175.             media = instance.media_new(url)
  176.             player.set_media(media)
  177.             player.play()
  178.             update_slider()
  179.         else:
  180.             messagebox.showerror("Error", "Selected text is not a valid URL.")
  181.  
  182.     threading.Thread(target=play_media).start()
  183.  
  184. def stop_preview():
  185.     player.stop()
  186.     preview_frame.pack_forget()
  187.  
  188. def capture_video():
  189.     try:
  190.         selected_channel = result_text.get(tk.ACTIVE).strip()
  191.         if selected_channel in channels_info:
  192.             url = channels_info[selected_channel]
  193.             filename = filedialog.asksaveasfilename(defaultextension=".mp4", filetypes=[("MP4 files", "*.mp4")])
  194.             if filename:
  195.                 command = ['ffmpeg', '-y', '-i', url, '-t', '03:55:00', '-c', 'copy', filename]
  196.                 threading.Thread(target=lambda: subprocess.run(command)).start()
  197.                 messagebox.showinfo("Capturing", f"Capturing 03:55 minutes of video to {filename}")
  198.         else:
  199.             messagebox.showerror("Error", "Selected text is not a valid URL.")
  200.     except tk.TclError:
  201.         messagebox.showerror("Error", "No text selected.")
  202.  
  203. def record_audio():
  204.     try:
  205.         selected_channel = result_text.get(tk.ACTIVE).strip()
  206.         if selected_channel in channels_info:
  207.             url = channels_info[selected_channel]
  208.             filename = filedialog.asksaveasfilename(defaultextension=".mp3", filetypes=[("MP3 files", "*.mp3")])
  209.             if filename:
  210.                 command = ['ffmpeg', '-y', '-i', url, '-f', 'mp3', '-c:a', 'libmp3lame', filename]
  211.                 global process
  212.                 process = subprocess.Popen(command)
  213.                 messagebox.showinfo("Recording", f"Recording audio to {filename}")
  214.         else:
  215.             messagebox.showerror("Error", "Selected text is not a valid URL.")
  216.     except tk.TclError:
  217.         messagebox.showerror("Error", "No text selected.")
  218.  
  219. def stop_recording():
  220.     if process:
  221.         process.terminate()
  222.         messagebox.showinfo("Stopped", "Recording stopped")
  223.  
  224. def capture_screenshots():
  225.     if player.get_media():
  226.         filename_base = filedialog.asksaveasfilename(defaultextension=".png", filetypes=[("PNG files", "*.png")])
  227.         if filename_base:
  228.             interval = 5
  229.             num_screenshots = 5
  230.             for i in range(num_screenshots):
  231.                 time.sleep(interval)
  232.                 filename = f"{filename_base}_{i+1}.png"
  233.                 player.video_take_snapshot(0, filename, 0, 0)
  234.                 messagebox.showinfo("Captured", f"Screenshot {i+1} saved to {filename}")
  235.  
  236. def update_slider():
  237.     if player.get_media():
  238.         length = player.get_length() / 1000
  239.         position = player.get_time() / 1000
  240.         if length > 0:
  241.             slider.set(position / length * 100)
  242.         root.after(1000, update_slider)
  243.  
  244. def set_position(event):
  245.     if player.get_media():
  246.         length = player.get_length() / 1000
  247.         player.set_time(int(slider.get() / 100 * length * 1000))
  248.  
  249. def on_configure(event):
  250.     if event.widget == canvas:
  251.         player.set_hwnd(canvas.winfo_id())
  252.  
  253. #def toggle_mute():
  254.     #is_muted = player.audio_get_mute()
  255.     #player.audio_set_mute(not is_muted)
  256.  
  257. def play_video(self):
  258.         if self.lst.curselection():
  259.             title = self.lst.get(self.lst.curselection())
  260.             video_url = self.video_urls.get(title)  # Get URL from dictionary
  261.             print("Playing video:", video_url)  # Print URL for debugging
  262.  
  263.             try:
  264.                 # Use pytube to get the video URL
  265.                 yt = YouTube(video_url)
  266.                 video_url = yt.streams.filter(progressive=True, file_extension='mp4').first().url
  267.  
  268.                 media = self.instance.media_new(video_url)
  269.                 self.player.set_media(media)
  270.                 self.player.set_hwnd(self.player_frame.winfo_id())
  271.                 self.player.play()
  272.                 self.current_video_label.config(text=f"Playing: {title}")
  273.             except AgeRestrictedError:
  274.                 print("Age restricted video:", video_url)
  275.                 webbrowser.open(video_url)  # Open age-restricted videos in the default web browser
  276.             except Exception as e:
  277.                 print("Error:", e)
  278.                 self.current_video_label.config(text="An error occurred while playing the video.")
  279.         else:
  280.             print("No video selected.")
  281.            
  282. def set_volume(value):
  283.         player.audio_set_volume(int(value))
  284.  
  285. # GUI setup
  286. root = tk.Tk()
  287. root.title("Najeeb IPTV Channel Link Checker")
  288. root.configure(bg="#4a4a4a")
  289.  
  290. url_frame = tk.Frame(root, bg="#4a4a4a")
  291. url_frame.pack(pady=10)
  292.  
  293. url_label = tk.Label(url_frame, text="Enter URL or local path or select category:", bg="#4a4a4a", fg="white")
  294. url_label.pack(side=tk.LEFT, padx=5)
  295.  
  296. url_entry = tk.Entry(url_frame, width=80)
  297. url_entry.pack(side=tk.LEFT, padx=5)
  298.  
  299. search_button = tk.Button(url_frame, text="Search", command=search_channels, bg="#FFA500", fg="white")
  300. search_button.pack(side=tk.LEFT, padx=5)
  301.  
  302. result_label = tk.Label(root, text="Check and save working URLs in M3U file:", bg="#4a4a4a", fg="white")
  303. result_label.pack()
  304.  
  305. search_frame = tk.Frame(root, bg="#4a4a4a")
  306. search_frame.pack()
  307.  
  308. search_label = tk.Label(search_frame, text="Search Channel Name:", bg="#4a4a4a", fg="white")
  309. search_label.pack(side=tk.LEFT, padx=5)
  310.  
  311. search_entry = tk.Entry(search_frame, width=105)
  312. search_entry.pack(side=tk.LEFT, padx=5)
  313. search_entry.bind('<KeyRelease>', filter_channels)
  314.  
  315. scrollbar = tk.Scrollbar(root, orient=tk.VERTICAL)
  316. scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
  317.  
  318. result_text = tk.Listbox(root, height=12, width=160, yscrollcommand=scrollbar.set)
  319. result_text.pack()
  320.  
  321. scrollbar.config(command=result_text.yview)
  322. result_text.bind("<Double-1>", play_selected_channel)
  323.  
  324. check_button = tk.Button(root, text="Check Links", command=check_links, bg="#008000", fg="white")
  325. check_button.pack(side=tk.RIGHT, padx=5)
  326.  
  327. save_button = tk.Button(root, text="Save Working Links", command=save_working_links, bg="#FF0000", fg="white")
  328. save_button.pack(side=tk.LEFT, padx=5)
  329.  
  330. category_urls = {
  331.     "NAJEEB-IPTV": "",
  332.     "ALL-INDEX": "https://iptv-org.github.io/iptv/index.m3u",
  333.     "CATEGORY": "https://iptv-org.github.io/iptv/index.category.m3u",
  334.     "LANGUAGE": "https://iptv-org.github.io/iptv/index.language.m3u",
  335.     "REGION": "https://iptv-org.github.io/iptv/index.region.m3u",
  336.     "Brazil": "https://iptv-org.github.io/iptv/countries/br.m3u",
  337.     "France": "https://iptv-org.github.io/iptv/countries/fr.m3u",
  338.     "India": "https://iptv-org.github.io/iptv/countries/in.m3u",
  339.     "Italy": "https://iptv-org.github.io/iptv/countries/it.m3u",
  340.     "Pakistan": "https://iptv-org.github.io/iptv/countries/pk.m3u",
  341.     "Spain": "https://iptv-org.github.io/iptv/countries/es.m3u",
  342.     "Thailand": "https://iptv-org.github.io/iptv/countries/th.m3u",
  343.     "UK": "https://iptv-org.github.io/iptv/countries/uk.m3u",
  344.     "USA": "https://iptv-org.github.io/iptv/countries/us.m3u",
  345.     "Classic": "https://iptv-org.github.io/iptv/categories/classic.m3u",
  346.     "Comedy": "https://iptv-org.github.io/iptv/categories/comedy.m3u",
  347.     "Documentary": "https://iptv-org.github.io/iptv/categories/documentary.m3u",
  348.     "Entertainment": "https://iptv-org.github.io/iptv/categories/entertainment.m3u",
  349.     "Kids": "https://iptv-org.github.io/iptv/categories/kids.m3u",
  350.     "Movies": "https://iptv-org.github.io/iptv/categories/movies.m3u",
  351.     "Music": "https://iptv-org.github.io/iptv/categories/music.m3u",
  352.     "News": "https://iptv-org.github.io/iptv/categories/news.m3u",
  353.     "Science": "https://iptv-org.github.io/iptv/categories/science.m3u",
  354.     "Sports": "https://iptv-org.github.io/iptv/categories/sports.m3u",
  355.     "Travel": "https://iptv-org.github.io/iptv/categories/travel.m3u",
  356.     "PLAYLIST-1": "C:/Users/Najeeb/Desktop/IPTV/PL1.m3u",
  357.     "PLAYLIST-2": "C:/Users/Najeeb/Desktop/IPTV/PL2.m3u",
  358.     "PLAYLIST-3": "C:/Users/Najeeb/Desktop/IPTV/PL3.m3u",
  359.     "PLAYLIST-4": "C:/Users/Najeeb/Desktop/IPTV/PL4.m3u",
  360.     "PLAYLIST-5": "C:/Users/Najeeb/Desktop/IPTV/PL5.m3u",
  361.     "PLAYLIST-6": "C:/Users/Najeeb/Desktop/IPTV/PL6.m3u",
  362.     "PLAYLIST-R": "C:/Users/Najeeb/Desktop/IPTV/PLR.m3u",
  363.     "PLAYLIST-X": "C:/Users/Najeeb/Desktop/IPTV/PLX.m3u",
  364. }
  365.  
  366. category_var = tk.StringVar(root)
  367. category_var.set("NAJEEB-IPTV")
  368. category_dropdown = ttk.OptionMenu(root, category_var, *category_urls.keys())
  369. category_dropdown.pack(pady=10)
  370.  
  371. volume_scale = tk.Scale(root, from_=0, to=100, orient="horizontal", command=set_volume, label="Volume", bg="#4a4a4a", fg="white")
  372. volume_scale.set(50)  # Set the initial volume to 50%
  373. volume_scale.pack(side="left", fill="x", padx=5, pady=5)
  374.  
  375.  
  376. button_frame = tk.Frame(root, bg="#4a4a4a")
  377. button_frame.pack()
  378.  
  379. browse_button = tk.Button(button_frame, text="Browse Playlist", command=browse_file, bg="#5a5a5a", fg="white")
  380. browse_button.pack(side=tk.LEFT, padx=5)
  381.  
  382. preview_button = tk.Button(button_frame, text="Preview", command=preview_selected_link, bg="#5a5a5a", fg="white")
  383. preview_button.pack(side=tk.LEFT, padx=5)
  384.  
  385. capture_video_button = tk.Button(button_frame, text="Capture Video", command=capture_video, bg="#5a5a5a", fg="white")
  386. capture_video_button.pack(side=tk.LEFT, padx=5)
  387.  
  388. record_button = tk.Button(button_frame, text="Record Audio", command=record_audio, bg="#5a5a5a", fg="white")
  389. record_button.pack(side=tk.LEFT, padx=5)
  390.  
  391. stop_button = tk.Button(button_frame, text="Stop Recording", command=stop_recording, bg="#5a5a5a", fg="white")
  392. stop_button.pack(side=tk.LEFT, padx=5)
  393.  
  394. capture_screenshot_button = tk.Button(button_frame, text="Capture Screenshots", command=capture_screenshots, bg="#5a5a5a", fg="white")
  395. capture_screenshot_button.pack(side=tk.LEFT, padx=5)
  396.  
  397. #toggle_mute_button = tk.Button(button_frame, text="Toggle Audio Mute", command=toggle_mute, bg="#5a5a5a", fg="white")
  398. #toggle_mute_button.pack(side=tk.LEFT, padx=5)
  399.  
  400. stop_button = tk.Button(button_frame, text="Close Preview", command=stop_preview, bg="#5a5a5a", fg="white")
  401. stop_button.pack(side=tk.LEFT, padx=5)
  402.  
  403. # YouTube search frame
  404. youtube_frame = tk.Frame(root, bg="#4a4a4a")
  405. youtube_frame.pack(pady=10)
  406.  
  407. search_label = tk.Label(youtube_frame, text="Youtube search:", bg="#4a4a4a", fg="white")
  408. search_label.pack(side=tk.LEFT, padx=5)
  409.  
  410. search_entry = tk.Entry(youtube_frame, width=70)
  411. search_entry.pack(side=tk.LEFT, padx=5)
  412.  
  413. search_button = tk.Button(youtube_frame, text="Search", command=search_youtube, bg="#FFA500", fg="white")
  414. search_button.pack(side=tk.LEFT, padx=5)
  415.  
  416. #Play
  417. play_button = tk.Button(youtube_frame, text="Play", command=play_youtube_video, bg="#FFA500", fg="white")
  418. play_button.pack(side="left", padx=5, pady=5)
  419.  
  420. preview_frame = tk.Frame(root, bg="#4a4a4a", height=200)
  421. preview_frame.pack(fill="both", expand=True)
  422. preview_frame.pack_forget()
  423.  
  424. canvas = tk.Canvas(preview_frame, bg="#4a4a4a")
  425. canvas.pack(fill="both", expand=True)
  426. canvas.bind("<Configure>", on_configure)
  427.  
  428. slider = tk.Scale(preview_frame, from_=0, to=100, orient=tk.HORIZONTAL, command=set_position, bg="#4a4a4a", fg="white")
  429. slider.pack(fill="x", padx=5)
  430.  
  431. instance = vlc.Instance()
  432. player = instance.media_player_new()
  433.  
  434. channels_info = {}
  435. working_links = {}
  436.  
  437. root.mainloop()
  438.  
Add Comment
Please, Sign In to add comment