Skip to content

Instantly share code, notes, and snippets.

@macim
Created January 29, 2026 01:42
Show Gist options
  • Select an option

  • Save macim/6ecb8813d7bb891dad7c3dcc4e93183f to your computer and use it in GitHub Desktop.

Select an option

Save macim/6ecb8813d7bb891dad7c3dcc4e93183f to your computer and use it in GitHub Desktop.
modsgrapper.py -> From Reddit Post
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