soluzka

my_ntpath.py

Oct 9th, 2024 (edited)
368
0
Never
4
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 19.61 KB | Software | 0 0
  1. import requests
  2. from bs4 import BeautifulSoup
  3. import tkinter as tk
  4. from tkinter import messagebox, filedialog, scrolledtext
  5. import re
  6. import vlc
  7. import yt_dlp
  8. import os
  9. import base64
  10. import webbrowser
  11. import threading
  12. from urllib.parse import urljoin
  13.  
  14.  
  15. class VideoDownloaderApp:
  16.     def __init__(self):
  17.         self.window = tk.Tk()
  18.         self.window.title("Smart Video Downloader")
  19.         self.attempted_urls = []
  20.         self.scraped_urls = []
  21.         self.all_collected_urls = []
  22.         self.player = None
  23.         self.download_path = None
  24.         self.selected_code = ""  # Ensure it starts as an empty string
  25.  
  26.         self.create_widgets()
  27.         self.window.mainloop()
  28.  
  29.     def create_widgets(self):
  30.         self.window.configure(bg='blue')
  31.  
  32.         self.url_label = tk.Label(self.window, text="Enter URL to Scrape:", bg='blue', fg='red')
  33.         self.url_label.pack()
  34.  
  35.         self.url_entry = tk.Entry(self.window, width=50, bg='yellow', bd=2, fg='red', relief='solid')
  36.         self.url_entry.pack()
  37.  
  38.         self.cleanse_button = tk.Button(self.window, text="Cleanse URL", command=self.cleanse_url_action,
  39.                                          bg='green', fg='red', bd=2)
  40.         self.cleanse_button.pack(pady=5)
  41.  
  42.         self.cleanse_all_button = tk.Button(self.window, text="Cleanse All URLs", command=self.cleanse_all_urls,
  43.                                              bg='green', fg='red', bd=2)
  44.         self.cleanse_all_button.pack(pady=5)
  45.  
  46.         self.scrape_button = tk.Button(self.window, text="Scrape for Videos", command=self.scrape_videos,
  47.                                        bg='green', fg='red', bd=2)
  48.         self.scrape_button.pack(pady=5)
  49.  
  50.         self.source_listbox = tk.Listbox(self.window, height=15, width=80, bd=2, relief='solid', bg='white', fg='red', selectbackground='lightblue')
  51.         self.source_listbox.pack(pady=5)
  52.  
  53.         self.scan_button = tk.Button(self.window, text="Scan for All URLs", command=self.scan_urls,
  54.                                       bg='green', fg='red', bd=2)
  55.         self.scan_button.pack(pady=5)
  56.  
  57.         self.download_url_label = tk.Label(self.window, text="Enter or Select URL to Download:", bg='blue', fg='red')
  58.         self.download_url_label.pack()
  59.  
  60.         self.download_url_entry = tk.Entry(self.window, width=50, bg='yellow', bd=2, fg='red', relief='solid')
  61.         self.download_url_entry.pack()
  62.  
  63.         self.play_button = tk.Button(self.window, text="Play Selected Video or Entered URL", command=self.play_video,
  64.                                      bg='green', fg='red', bd=2)
  65.         self.play_button.pack(pady=5)
  66.  
  67.         self.save_info_button = tk.Button(self.window, text="Save Scrape Info as HTML", command=self.save_scrape_info_as_html,
  68.                                            bg='green', fg='red', bd=2)
  69.         self.save_info_button.pack(pady=5)
  70.  
  71.         self.download_button = tk.Button(self.window, text="Download Selected Videos", command=self.download_selected_videos,
  72.                                           bg='green', fg='red', bd=2)
  73.         self.download_button.pack(pady=5)
  74.  
  75.         self.execute_code_button = tk.Button(self.window, text="Execute Generated Code", command=self.execute_user_code,
  76.                                               bg='green', fg='red', bd=2)
  77.         self.execute_code_button.pack(pady=5)
  78.  
  79.         self.set_path_button = tk.Button(self.window, text="Set Download Directory", command=self.set_download_path,
  80.                                           bg='green', fg='red', bd=2)
  81.         self.set_path_button.pack(pady=5)
  82.  
  83.         self.download_combined_button = tk.Button(self.window, text="Download Combined HTML & JS", command=self.download_combined_content,
  84.                                                    bg='green', fg='red', bd=2)
  85.         self.download_combined_button.pack(pady=5)
  86.  
  87.         self.code_output = scrolledtext.ScrolledText(self.window, wrap=tk.WORD, height=10, width=80, bg='orange', fg='red', bd=2, relief='solid')
  88.         self.code_output.pack(pady=5)
  89.  
  90.         self.base64_options_label = tk.Label(self.window, text="Select Base64 Encoding:", bg='blue', fg='red')
  91.         self.base64_options_label.pack(pady=5)
  92.  
  93.         self.base64_type_var = tk.StringVar(value="standard")
  94.         self.base64_standard_radio = tk.Radiobutton(self.window, text="Standard Base64", variable=self.base64_type_var,
  95.                                                      value="standard", bg='blue', fg='red')
  96.         self.base64_standard_radio.pack()
  97.  
  98.         self.base64_url_radio = tk.Radiobutton(self.window, text="URL Safe Base64", variable=self.base64_type_var,
  99.                                                 value="url_safe", bg='blue', fg='red')
  100.         self.base64_url_radio.pack()
  101.  
  102.     def set_download_path(self):
  103.         self.download_path = filedialog.askdirectory(title="Select Download Directory")
  104.         if self.download_path and not os.path.isdir(self.download_path):
  105.             messagebox.showerror("Error", "Invalid download path.")
  106.             self.download_path = None
  107.         elif self.download_path:
  108.             messagebox.showinfo("Info", f"Download path set to: {self.download_path}")
  109.  
  110.     def cleanse_url_action(self):
  111.         url = self.url_entry.get()
  112.         cleaned_url = self.cleanse_url(url)
  113.         if cleaned_url:
  114.             messagebox.showinfo("Cleansed URL", f"Cleansed URL: {cleaned_url}")
  115.             self.url_entry.delete(0, tk.END)
  116.             self.url_entry.insert(0, cleaned_url)
  117.  
  118.     def cleanse_all_urls(self):
  119.         # Store cleaned URLs for updates
  120.         cleaned_scraped_urls = []
  121.         cleaned_collected_urls = []
  122.  
  123.         # Cleanse scraped URLs
  124.         for url in self.scraped_urls:
  125.             cleaned_url = self.cleanse_url(url)
  126.             if cleaned_url:
  127.                 cleaned_scraped_urls.append(cleaned_url)
  128.  
  129.         # Cleanse all collected URLs
  130.         for url in self.all_collected_urls:
  131.             cleaned_url = self.cleanse_url(url)
  132.             if cleaned_url:
  133.                 cleaned_collected_urls.append(cleaned_url)
  134.  
  135.         # Update the listbox and internal lists
  136.         self.scraped_urls = cleaned_scraped_urls
  137.         self.all_collected_urls = cleaned_collected_urls
  138.  
  139.         self.source_listbox.delete(0, tk.END)  # Clear the listbox
  140.         self.source_listbox.insert(tk.END, "Cleaned Scraped URLs:")
  141.         for cleaned_url in self.scraped_urls:
  142.             self.source_listbox.insert(tk.END, cleaned_url)
  143.  
  144.         self.source_listbox.insert(tk.END, "Cleaned Collected URLs:")
  145.         for cleaned_url in self.all_collected_urls:
  146.             self.source_listbox.insert(tk.END, cleaned_url)
  147.  
  148.     def scan_urls(self):
  149.         url = self.url_entry.get()
  150.         if not url:
  151.             messagebox.showwarning("Input Error", "Please enter a URL to scan.")
  152.             return
  153.  
  154.         self.attempted_urls.append(url)
  155.         cleaned_url = self.cleanse_url(url)
  156.         if not cleaned_url:
  157.             return
  158.  
  159.         try:
  160.             response = requests.get(cleaned_url)
  161.             response.raise_for_status()
  162.             soup = BeautifulSoup(response.text, 'html.parser')
  163.  
  164.             urls = {urljoin(cleaned_url, link.get('href')) for link in soup.find_all('a', href=True)}
  165.  
  166.             self.source_listbox.delete(0, tk.END)
  167.             self.source_listbox.insert(tk.END, f"Scanned URLs from {cleaned_url}:")
  168.             for collected_url in urls:
  169.                 self.source_listbox.insert(tk.END, collected_url)
  170.  
  171.             self.all_collected_urls = list(urls)
  172.             self.save_urls_to_file(self.all_collected_urls, "scanned_urls.txt")
  173.  
  174.         except Exception as e:
  175.             messagebox.showerror("Error", f"Failed to scan the URL: {e}")
  176.  
  177.     def scrape_videos(self):
  178.         url = self.url_entry.get()
  179.         if not url:
  180.             messagebox.showwarning("Input Error", "Please enter a URL.")
  181.             return
  182.  
  183.         self.attempted_urls.append(url)
  184.         cleaned_url = self.cleanse_url(url)
  185.         if not cleaned_url:
  186.             return
  187.  
  188.         try:
  189.             response = requests.get(cleaned_url)
  190.             response.raise_for_status()
  191.             soup = BeautifulSoup(response.text, 'html.parser')
  192.  
  193.             scraped_video_urls = []
  194.  
  195.             scraped_video_urls += [source.get('src') for video in soup.find_all('video') for source in video.find_all('source')]
  196.             scraped_video_urls += [iframe.get('src') for iframe in soup.find_all('iframe') if iframe.get('src')]
  197.  
  198.             self.source_listbox.delete(0, tk.END)
  199.             self.source_listbox.insert(tk.END, f"Scraped URLs from {cleaned_url}:")
  200.             for source in scraped_video_urls:
  201.                 self.source_listbox.insert(tk.END, source)
  202.  
  203.             for attempted_url in self.attempted_urls:
  204.                 if attempted_url not in self.source_listbox.get(0, tk.END):
  205.                     self.source_listbox.insert(tk.END, attempted_url)
  206.  
  207.             self.scraped_urls = scraped_video_urls
  208.             self.save_urls_to_file(self.scraped_urls, "scraped_video_urls.txt")
  209.  
  210.         except Exception as e:
  211.             messagebox.showerror("Error", f"Failed to scrape the URL: {e}")
  212.  
  213.     def save_urls_to_file(self, urls, default_filename):
  214.         file_path = filedialog.asksaveasfilename(defaultextension=".txt", initialfile=default_filename,
  215.                                                    filetypes=[("Text Files", "*.txt")], title="Save URLs")
  216.         if file_path:
  217.             mode = 'a' if os.path.exists(file_path) else 'w'
  218.             with open(file_path, mode, encoding='utf-8') as f:
  219.                 for url in urls:
  220.                     f.write(url + "\n")
  221.  
  222.             messagebox.showinfo("Info", f"URLs saved to {file_path}.")
  223.  
  224.     def play_video(self):
  225.         # Check if a URL is entered or the first selection is valid
  226.         entered_url = self.download_url_entry.get() or self.url_entry.get()
  227.         if entered_url:
  228.             # Create a VLC media player instance and play the video
  229.             self.player = vlc.MediaPlayer(entered_url)
  230.             if self.player is not None:  # Ensure the player is created
  231.                 self.player.play()
  232.             else:
  233.                 messagebox.showwarning("Video Error", "Failed to create media player with the entered URL.")
  234.             return
  235.  
  236.         selected_indices = self.source_listbox.curselection()
  237.         if not selected_indices:
  238.             messagebox.showwarning("Selection Error", "Please select a video source or enter a URL.")
  239.             return
  240.  
  241.         for index in selected_indices:
  242.             video_url = self.source_listbox.get(index)
  243.            
  244.             # Check if video_url is valid and not empty
  245.             if video_url:  # Ensure video_url is not None or empty
  246.                 self.player = vlc.MediaPlayer(video_url)
  247.                 if self.player is not None:  # Ensure the player is created
  248.                     self.player.play()
  249.                 else:
  250.                     messagebox.showwarning("Video Error", "Failed to create media player with the selected URL.")
  251.                 return
  252.             else:
  253.                 messagebox.showwarning("Video Error", "The selected video URL is invalid.")
  254.  
  255.     def download_selected_videos(self):
  256.         selected_indices = self.source_listbox.curselection()
  257.         if not selected_indices:
  258.             messagebox.showwarning("Selection Error", "Please select videos.")
  259.             return
  260.  
  261.         if self.download_path is None:
  262.             messagebox.showwarning("Download Path Error", "No download path set. Please set a download path first.")
  263.             return
  264.  
  265.         video_url = self.source_listbox.get(selected_indices[0])  # Now taking the first selected video URL
  266.  
  267.         choice = messagebox.askquestion("Select Output Type", "Generate Base64 Output?", icon='question')
  268.         if choice == 'yes':
  269.             choice_base64 = self.base64_type_var.get()  # Get selected base64 type
  270.             self.selected_code = self.generate_output_code(video_url, output_format='base64', base64_type=choice_base64)
  271.         else:
  272.             choice_html = messagebox.askquestion("HTML Output", "Generate HTML Output?", icon='question')
  273.             if choice_html == 'yes':
  274.                 self.selected_code = self.generate_output_code(video_url, output_format='html')
  275.             else:
  276.                 self.selected_code = self.generate_downloader_code(video_url)
  277.  
  278.         if self.selected_code is None or self.selected_code == "":
  279.             messagebox.showwarning("Code Generation Failed", "No code was generated.")
  280.             return
  281.  
  282.         self.code_output.delete(1.0, tk.END)
  283.         self.code_output.insert(tk.END, self.selected_code)
  284.  
  285.     def execute_user_code(self):
  286.         if not self.selected_code:
  287.             messagebox.showwarning("Code Error", "No previously selected code to execute.")
  288.             return
  289.  
  290.         # Run the selected code directly
  291.         threading.Thread(target=self.run_code, args=(self.selected_code,)).start()
  292.  
  293.     def generate_output_code(self, video_url, output_format='html', base64_type='standard'):
  294.         if not self.download_path:
  295.             messagebox.showwarning("Download Path Error", "Please set a download path before generating code.")
  296.             return None
  297.  
  298.         if video_url is None:  # Check video_url for None
  299.             messagebox.showwarning("URL Error", "Video URL cannot be None.")
  300.             return None
  301.  
  302.         download_path = self.download_path.replace('\\', '\\\\')
  303.         if output_format == "base64":
  304.             return f"""
  305. import yt_dlp
  306. import os
  307. import base64
  308.  
  309. def download_video():
  310.    video_url = '{video_url}'
  311.    download_path = r'{download_path}'
  312.  
  313.    ydl_opts = {{
  314.        'format': 'best',
  315.        'outtmpl': os.path.join(download_path, '%(title)s.%(ext)s'),
  316.        'quiet': True,
  317.    }}
  318.  
  319.    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
  320.        info_dict = ydl.extract_info(video_url, download=False)
  321.        video_file_path = ydl.prepare_filename(info_dict)
  322.  
  323.        ydl.download([video_url])
  324.        with open(video_file_path, 'rb') as video_file:
  325.            encoded_string = base64.b64encode(video_file.read()).decode('utf-8')
  326.            print("Base64 Encoded Video:", encoded_string)
  327.  
  328. download_video()
  329. """
  330.         elif output_format == "html":
  331.             return f"""
  332. import yt_dlp
  333. import os
  334.  
  335. def download_video():
  336.    video_url = '{video_url}'
  337.    download_path = r'{download_path}'
  338.  
  339.    ydl_opts = {{
  340.        'format': 'best',
  341.        'outtmpl': os.path.join(download_path, '%(title)s.%(ext)s'),
  342.        'quiet': True,
  343.    }}
  344.  
  345.    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
  346.        info_dict = ydl.extract_info(video_url, download=False)
  347.        video_file_path = ydl.prepare_filename(info_dict)
  348.  
  349.        try:
  350.            ydl.download([video_url])
  351.            html_output = f'<html><body><h1>Downloaded Video</h1><video width="320" height="240" controls>'
  352.            html_output += f'<source src="{{video_file_path}}" type="video/mp4">No video support.</video></body></html>'
  353.  
  354.            with open(os.path.join(download_path, 'video_output.html'), 'w', encoding='utf-8') as html_file:
  355.                html_file.write(html_output)
  356.  
  357.        except Exception as e:
  358.            print(f"An error occurred: {{e}}")
  359.  
  360. download_video()
  361. """
  362.         else:  # For downloader code
  363.             return self.generate_downloader_code(video_url)
  364.  
  365.     def generate_downloader_code(self, video_url):
  366.         if not self.download_path:
  367.             messagebox.showwarning("Download Path Error", "Please set a download path before downloading.")
  368.             return None
  369.  
  370.         if video_url is None:  # Check if video_url is None before proceeding
  371.             messagebox.showwarning("URL Error", "Video URL cannot be None.")
  372.             return None
  373.  
  374.         download_path = self.download_path.replace('\\', '\\\\')
  375.  
  376.         downloader_code = f"""
  377. import yt_dlp
  378. import os
  379.  
  380. def download_video():
  381.    video_url = '{video_url}'
  382.    ydl_opts = {{
  383.        'format': 'best',
  384.        'outtmpl': os.path.join(os.path.expanduser(r'{download_path}'), '%(title)s.%(ext)s'),
  385.    }}
  386.  
  387.    try:
  388.        with yt_dlp.YoutubeDL(ydl_opts) as ydl:
  389.            ydl.download([video_url])
  390.    except Exception as exception:
  391.        print(f"An error occurred: {{exception}}")
  392.  
  393. download_video()
  394. """
  395.         return downloader_code
  396.  
  397.     def run_code(self, user_code):
  398.         try:
  399.             exec(user_code)
  400.         except Exception as e:
  401.             messagebox.showerror("Execution Error", f"Failed to execute the code: {e}")
  402.  
  403.     def download_combined_content(self):
  404.         if not self.attempted_urls and not self.scraped_urls:
  405.             messagebox.showwarning("No URLs", "No URLs available.")
  406.             return
  407.  
  408.         base64_option = self.base64_type_var.get()
  409.         combined_urls = []
  410.         entered_url = self.url_entry.get()
  411.         if entered_url:
  412.             combined_urls.append(entered_url)
  413.  
  414.         combined_urls.extend(self.scraped_urls)
  415.  
  416.         try:
  417.             html_content = "<html><body><h1>Combined Video URLs</h1><ul>"
  418.             for video_url in combined_urls:
  419.                 html_content += f"<li>{video_url}</li>"
  420.             html_content += "</ul></body></html>"
  421.  
  422.             if base64_option == "standard":
  423.                 base64_encoded_content = base64.b64encode(html_content.encode('utf-8')).decode('utf-8')
  424.             elif base64_option == "url_safe":
  425.                 base64_encoded_content = base64.urlsafe_b64encode(html_content.encode('utf-8')).decode('utf-8')
  426.  
  427.             save_file_name = filedialog.asksaveasfilename(defaultextension=".b64", filetypes=[("Base64 Files", "*.b64")],
  428.                                                            title="Save Combined Base64 Encoded File")
  429.             if save_file_name:
  430.                 with open(save_file_name, 'w', encoding='utf-8') as b64_file:
  431.                     b64_file.write(base64_encoded_content)
  432.  
  433.                 messagebox.showinfo("Info", f"Combined Base64 encoded content saved to: {save_file_name}")
  434.  
  435.         except Exception as e:
  436.             messagebox.showerror("Error", f"Failed to download combined content: {e}")
  437.  
  438.     def save_scrape_info_as_html(self):
  439.         if not self.attempted_urls and not self.scraped_urls:
  440.             messagebox.showwarning("No Data", "No URLs to save.")
  441.             return
  442.  
  443.         html_content = "<html><body><h1>Video Scrape Info</h1><h2>Attempted URLs</h2><ul>"
  444.         for attempted_url in self.attempted_urls:
  445.             html_content += f"<li>{attempted_url}</li>"
  446.         html_content += "</ul><h2>Scraped URLs</h2><ul>"
  447.         for video_url in self.scraped_urls:
  448.             html_content += f"<li>{video_url}</li>"
  449.         html_content += "</ul></body></html>"
  450.  
  451.         file_path = filedialog.asksaveasfilename(defaultextension=".html", filetypes=[("HTML Files", "*.html")])
  452.         if file_path:
  453.             with open(file_path, 'w', encoding='utf-8') as f:
  454.                 f.write(html_content)
  455.  
  456.             messagebox.showinfo("Info", f"HTML file saved to {file_path}.")
  457.             webbrowser.open(file_path)
  458.  
  459.     def cleanse_url(self, url):
  460.         pattern = re.compile(
  461.             r'^(?:http|ftp)s?://'  
  462.             r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|'
  463.             r'localhost|'  
  464.             r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|'  
  465.             r'\[?[A-F0-9]*:[A-F0-9:]+\]?)'  
  466.             r'(?::\d+)?'
  467.             r'(?:/?|[/?]\S+)$', re.IGNORECASE)
  468.  
  469.         if re.match(pattern, url):
  470.             return url.split('?')[0]
  471.         else:
  472.             messagebox.showwarning("Invalid URL", "The provided URL is not valid.")
  473.             return None
  474.  
  475.  
  476. if __name__ == "__main__":
  477.     VideoDownloaderApp()
Comments
Add Comment
Please, Sign In to add comment