import tkinter as tk
from tkinter import ttk, scrolledtext, font
from threading import Thread
import re
import socket
import netifaces

def extract_ips(bridge_data):
pattern = re.compile(r’(\d{1,3}(?:.\d{1,3}){3}:\d+)‘)
return pattern.findall(bridge_data)

def update_console(message):
console_display.configure(state=‘normal’)
console_display.insert(tk.END, message + “\n”)
console_display.configure(state=‘disabled’)
console_display.yview(tk.END)

def is_port_open(ip, port, timeout):
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.settimeout(timeout)
sock.connect((ip, port))
return True
except socket.error:
return False

def check_ip_port(ip, port, timeout):
if is_port_open(ip, port, timeout):
update_console(f"Connection successful for {ip}:{port}“)
return True
else:
update_console(f"Connection failed for {ip}:{port}”)
return False

def check_bridges():
raw_data = bridge_input.get(‘1.0’, tk.END)
ip_port_pairs = extract_ips(raw_data)
timeout = float(timeout_entry.get())
responsive_bridges = []

for ip_port in ip_port_pairs:
ip, port = ip_port.split(’:‘)
if check_ip_port(ip, int(port), timeout):
responsive_bridges.append(ip_port)

responsive_data = ‘\n’.join([line for line in raw_data.split(’\n’)
if any(rb in line for rb in responsive_bridges)])
result_display.configure(state=‘normal’)
result_display.delete(‘1.0’, tk.END)
result_display.insert(tk.END, responsive_data)
result_display.configure(state=‘disabled’)
status_label.config(text=“Check completed”)

def copy_to_clipboard():
root.clipboard_clear()
try:
text_to_copy = result_display.get(tk.SEL_FIRST, tk.SEL_LAST)
root.clipboard_append(text_to_copy)
except tk.TclError:
pass

def get_network_interfaces():
return netifaces.interfaces()

def clear_console():
console_display.configure(state=‘normal’)
console_display.delete(‘1.0’, tk.END)
console_display.configure(state=‘disabled’)

root = tk.Tk()
root.title(“Tor Bridge Connectivity Checker”)
root.tk.call(‘tk’, ‘scaling’, 4.0)
default_font = font.nametofont(“TkDefaultFont”)
default_font.configure(size=18)
root.option_add(“*Font”, default_font)

frame = ttk.Frame(root, padding=“3”)
frame.grid(column=0, row=0, sticky=(tk.W, tk.E, tk.N, tk.S))
frame.columnconfigure(0, weight=1)
frame.rowconfigure(2, weight=1)
frame.rowconfigure(5, weight=1)
frame.rowconfigure(9, weight=1)

interfaces = get_network_interfaces()
default_interface = interfaces[-1] if interfaces else None

net_interface_label = ttk.Label(frame, text=“Network Interface:”)
net_interface_label.grid(column=0, row=0, sticky=tk.W)
net_interface_selector = ttk.Combobox(frame, values=interfaces)
net_interface_selector.set(default_interface)
net_interface_selector.grid(column=1, row=0, sticky=(tk.W, tk.E), columnspan=3)
frame.columnconfigure(1, weight=1)

thread_count_label = ttk.Label(frame, text=“Thread Count:”)
thread_count_label.grid(column=4, row=0, sticky=tk.W, padx=(4, 0))
thread_count_entry = ttk.Spinbox(frame, from_=1, to=100, increment=1, width=7)
thread_count_entry.set(10)
thread_count_entry.grid(column=5, row=0)

timeout_label = ttk.Label(frame, text=“Timeout (s):”)
timeout_label.grid(column=6, row=0, sticky=tk.W, padx=(4, 0))
timeout_entry = ttk.Spinbox(frame, from_=1, to=10, increment=0.5, width=7, format=“%.1f”)
timeout_entry.set(3.0)
timeout_entry.grid(column=7, row=0)

bridge_label = ttk.Label(frame, text=“Bridges to Check:”)
bridge_label.grid(column=0, row=1, sticky=tk.W)
bridge_input = scrolledtext.ScrolledText(frame, height=10)
bridge_input.grid(column=0, row=2, columnspan=8, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 5))
paste_button = tk.Button(frame, text=“Paste”, command=lambda: bridge_input.insert(tk.END, root.clipboard_get()))
paste_button.grid(column=0, row=3, sticky=tk.W)

result_label = ttk.Label(frame, text=“Sorted List:”)
result_label.grid(column=0, row=4, sticky=tk.W)
result_display = scrolledtext.ScrolledText(frame, height=10, state=‘disabled’)
result_display.grid(column=0, row=5, columnspan=8, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 5))
select_all_button = tk.Button(frame, text=“Select All”, command=lambda: result_display.tag_add(tk.SEL, “1.0”, tk.END))
select_all_button.grid(column=0, row=6, sticky=tk.W)
copy_button = tk.Button(frame, text=“Copy”, command=copy_to_clipboard)
copy_button.grid(column=1, row=6, sticky=tk.W)

check_button = tk.Button(frame, text=“Check Bridges”, command=check_bridges)
check_button.grid(column=2, row=6, sticky=tk.W, pady=(0, 5))

console_label = ttk.Label(frame, text=“Console Log:”)
console_label.grid(column=0, row=7, sticky=tk.W)
console_display = scrolledtext.ScrolledText(frame, height=8, state=‘disabled’, background=‘black’, foreground=‘white’)
console_display.grid(column=0, row=9, columnspan=8, sticky=(tk.W, tk.E, tk.N, tk.S))
clear_console_button = tk.Button(frame, text=“Clear”, command=clear_console)
clear_console_button.grid(column=0, row=8, sticky=tk.W)

status_label = tk.Label(frame, bd=1, relief=tk.SUNKEN, anchor=tk.W)
status_label.config(text=“Ready”)
status_label.grid(column=0, row=10, columnspan=8, sticky=(tk.W, tk.E))

root.mainloop()”
ok it seem it work as intended, but I don’t see live console log output in real time checking, need fix that. also,can you align in one straight line buttons normally, as: bellow bridges to check textrea there will be two buttons “paste” and "check “bridges”. bellow “sorted list” textarea there will be 3 buttons “select all”, “copy”, and “reset”, in that order. replace “clear” button with “reset”, to simply reset program to initial state and clear everything and stop any operations as well. again, it don’t show anything after inside “sorted list”. also, it seems that it doesn’t perform full bridges checking inside “bridges to check”. the pattern for tor bridges strings is as follows: “obfs4 159.100.247.39:443 4FA7628C90396DF837D44F2EB2DF294139987279 cert=OXUhnNSa5rG4w4Bor+OJ9nT3Y2QLlTeZiw67W6TOmWX68msA5AI429aq0JN5DDe3COr0AA iat-mode=0”, and vanilla tor bridge string: “94.244.77.84:14251 ACEF7A464BEBBBDEB4382BD2D46106DBA4D05DBB”. maybe remove all multithreadings and simply left a timeout ans set it in default 500ms to be able to adjust further? because this multithreading is a real mess. I got a headache. output fully fixed code without comments and trash. output fully fixed code without comments and trash.