Created
January 29, 2026 01:42
-
-
Save macim/6ecb8813d7bb891dad7c3dcc4e93183f to your computer and use it in GitHub Desktop.
modsgrapper.py -> From Reddit Post
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import tkinter as tk | |
| import re | |
| import requests | |
| import pyperclip | |
| import time | |
| import webbrowser | |
| from tkinter import messagebox | |
| import winsound | |
| import threading | |
| # Function to extract the ID from a Steam link | |
| def extract_steam_id(steam_url): | |
| if steam_url.isdigit(): | |
| return steam_url | |
| else: | |
| match = re.search(r'id=(\d+)', steam_url) | |
| if match: | |
| return match.group(1) | |
| return None | |
| # Function to extract the download link using regex | |
| def extract_download_link(page_url): | |
| response = requests.get(page_url) | |
| if response.status_code == 200: | |
| download_pattern = r'(https://modsbase.com/[^"]+)' | |
| match = re.search(download_pattern, response.text) | |
| if match: | |
| return match.group(1) | |
| return None | |
| # Function executed after submitting the input | |
| def on_submit(): | |
| steam_urls_list = [] | |
| for _, entry in entry_widgets: | |
| steam_url = entry.get().strip() | |
| steam_urls_list.append(steam_url) | |
| not_found = [] # List for mods that were not found | |
| for steam_url in steam_urls_list: | |
| steam_id = extract_steam_id(steam_url) | |
| if steam_id: | |
| websites = [ | |
| f'https://stellaris.smods.ru/?s={steam_id}', | |
| f'https://hearts-of-iron-4.smods.ru/archives/{steam_id}', | |
| f'https://smods.ru/?s={steam_id}', | |
| f'https://catalogue.smods.ru/?s={steam_id}&app=1158310', | |
| f'https://catalogue.smods.ru/?s={steam_id}&app=236850' | |
| ] | |
| download_url = None | |
| for website in websites: | |
| download_url = extract_download_link(website) | |
| if download_url: | |
| break | |
| if download_url: | |
| webbrowser.open(download_url) | |
| else: | |
| not_found.append(steam_url) # No mod found | |
| else: | |
| not_found.append(steam_url) # Invalid Steam ID | |
| # Update result label | |
| if not_found: | |
| result_label.config(text=f"{len(not_found)} mods were not found.", fg="red") | |
| not_found_text.delete(1.0, tk.END) # Clear text field | |
| not_found_text.insert(tk.END, "\n".join(not_found)) # Insert not found links | |
| else: | |
| result_label.config(text="All mods were found successfully!", fg="green") | |
| # Function to monitor the clipboard | |
| def check_clipboard(): | |
| previous_clipboard = "" | |
| while clipboard_enabled.get(): # Only if enabled | |
| current_clipboard = pyperclip.paste() | |
| if current_clipboard != previous_clipboard: | |
| previous_clipboard = current_clipboard | |
| if current_clipboard: | |
| steam_id = extract_steam_id(current_clipboard) | |
| if steam_id: | |
| def show_popup_and_play_sound(): | |
| winsound.PlaySound("SystemExclamation", winsound.SND_ALIAS) | |
| proceed = messagebox.askyesno( | |
| "Confirmation", | |
| f"Link detected: {current_clipboard}\nDo you want to proceed?" | |
| ) | |
| if proceed: | |
| on_submit() | |
| show_popup_and_play_sound() | |
| time.sleep(2) | |
| # Create the GUI window | |
| root = tk.Tk() | |
| root.title("Steam Mod ID Extractor") | |
| root.geometry("700x600") | |
| root.configure(bg="#171a21") # Dark background for a modern look | |
| # Header | |
| header_label = tk.Label( | |
| root, | |
| text="Steam Mod Downloader", | |
| font=("Arial", 18, "bold"), | |
| bg="#171a21", | |
| fg="#ecf0f1" | |
| ) | |
| header_label.pack(pady=10) | |
| # Create a frame for the content | |
| content_frame = tk.Frame(root, bg="#34495e") | |
| content_frame.pack(fill="both", expand=True, padx=10, pady=10) | |
| # Scrollable canvas | |
| canvas = tk.Canvas(content_frame, bg="#34495e", highlightthickness=0) | |
| canvas.pack(side="left", fill="both", expand=True) | |
| scrollbar = tk.Scrollbar(content_frame, orient="vertical", command=canvas.yview) | |
| scrollbar.pack(side="right", fill="y") | |
| canvas.configure(yscrollcommand=scrollbar.set) | |
| inner_frame = tk.Frame(canvas, bg="#34495e") | |
| canvas.create_window((0, 0), window=inner_frame, anchor="nw") | |
| # Function to update the scroll region | |
| def update_scroll_region(event=None): | |
| canvas.configure(scrollregion=canvas.bbox("all")) | |
| inner_frame.bind("<Configure>", update_scroll_region) | |
| # List of entry widgets and their frames | |
| entry_widgets = [] | |
| def add_entry(): | |
| # Create a frame grouping the entry field and delete button | |
| entry_frame = tk.Frame(inner_frame, bg="#34495e") | |
| entry_frame.pack(pady=5, padx=10, fill="x") | |
| # Create entry field | |
| new_entry = tk.Entry( | |
| entry_frame, | |
| font=("Arial", 12), | |
| width=50, | |
| bg="#c7d5e0", | |
| fg="#171a21" | |
| ) | |
| new_entry.pack(side="left", fill="x", expand=True, padx=(0, 5)) | |
| # Add a delete button starting from the second entry | |
| if len(entry_widgets) > 0: | |
| delete_button = tk.Button( | |
| entry_frame, | |
| text="X", | |
| font=("Arial", 12, "bold"), | |
| bg="#e74c3c", | |
| fg="#ffffff", | |
| command=lambda: delete_entry(entry_frame) | |
| ) | |
| delete_button.pack(side="right") | |
| # Store the entry in the list | |
| entry_widgets.append((entry_frame, new_entry)) | |
| def delete_entry(entry_frame): | |
| # Remove the entry frame (including button) from the GUI | |
| entry_frame.destroy() | |
| # Update the list of entry widgets | |
| global entry_widgets | |
| entry_widgets = [w for w in entry_widgets if w[0] != entry_frame] | |
| # Button to process mods | |
| submit_button = tk.Button( | |
| root, | |
| text="Process Mods", | |
| command=on_submit, | |
| font=("Arial", 14), | |
| bg="#1b2838", | |
| fg="#FFFFFF", | |
| width=20 | |
| ) | |
| submit_button.pack(pady=10) | |
| # Result label | |
| result_label = tk.Label(root, text="", font=("Arial", 12), bg="#171a21", fg="#ecf0f1") | |
| result_label.pack(pady=5) | |
| # Text field for mods that were not found | |
| not_found_label = tk.Label( | |
| root, | |
| text="Not found mods:", | |
| font=("Arial", 12), | |
| bg="#171a21", | |
| fg="#ecf0f1" | |
| ) | |
| not_found_label.pack(pady=5) | |
| not_found_text = tk.Text( | |
| root, | |
| height=10, | |
| font=("Arial", 12), | |
| bg="#1b2838", | |
| fg="#FFFFFF", | |
| wrap="word" | |
| ) | |
| not_found_text.pack(pady=5, padx=10, fill="both") | |
| # Function to enable or disable clipboard monitoring | |
| clipboard_enabled = tk.BooleanVar(value=True) | |
| clipboard_toggle_button = tk.Checkbutton( | |
| root, | |
| text="Auto Downloader", | |
| variable=clipboard_enabled, | |
| font=("Arial", 12), | |
| bg="#2c3e50", | |
| fg="#ecf0f1", | |
| selectcolor="#1b2838" | |
| ) | |
| clipboard_toggle_button.pack(pady=10) | |
| # Function to automatically add another entry field | |
| def auto_add_entry(event=None): | |
| for _, entry in entry_widgets: | |
| if entry.get().strip(): | |
| add_entry() | |
| break | |
| root.bind('<Return>', auto_add_entry) | |
| # Start with one entry field | |
| add_entry() | |
| # Start the GUI | |
| root.mainloop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment