mirror of
https://github.com/Stone-Red-Code/HotspotAutoLogin.git
synced 2026-11-01 23:05:40 +01:00
v1.82
This commit is contained in:
@@ -0,0 +1,614 @@
|
||||
import json
|
||||
import os
|
||||
import requests
|
||||
import time
|
||||
import subprocess
|
||||
import pystray
|
||||
import threading
|
||||
import tkinter as tk
|
||||
from tkinter import Text, Scrollbar
|
||||
from PIL import Image
|
||||
from collections import deque
|
||||
from datetime import datetime
|
||||
import dns.resolver
|
||||
dns.resolver.override_system_resolver(dns.resolver.Resolver())
|
||||
dns.resolver.default_resolver = dns.resolver.Resolver()
|
||||
from urllib3.exceptions import InsecureRequestWarning
|
||||
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
|
||||
|
||||
# Change the current working directory to the script's directory
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
os.chdir(script_dir)
|
||||
|
||||
# Program Information
|
||||
program_name = "HotspotAutoLogin"
|
||||
version = "v1.82"
|
||||
github_link = "https://github.com/denizsafak/HotspotAutoLogin"
|
||||
|
||||
# Function to center a window on the screen
|
||||
def center_window(window, width, height):
|
||||
screen_width = window.winfo_screenwidth()
|
||||
screen_height = window.winfo_screenheight()
|
||||
x = (screen_width - width) // 2
|
||||
y = (screen_height - height) // 2
|
||||
window.geometry(f"{width}x{height}+{x}+{y}")
|
||||
|
||||
def run_profile():
|
||||
global selected_profile
|
||||
refresh_profile_details()
|
||||
selected_index = listbox.curselection()
|
||||
if selected_index:
|
||||
selected_index = int(selected_index[0])
|
||||
selected_profile = profiles[selected_index]
|
||||
root.destroy()
|
||||
|
||||
# Define a function to update the profile details
|
||||
def update_profile_details(event):
|
||||
global selected_profile
|
||||
selected_index = listbox.curselection()
|
||||
if selected_index:
|
||||
selected_index = int(selected_index[0])
|
||||
selected_profile = profiles[selected_index]
|
||||
profile_name.config(text=f"Selected Profile: {selected_profile['name']}")
|
||||
profile_details.config(state=tk.NORMAL)
|
||||
profile_details.delete(1.0, tk.END)
|
||||
# Insert profile details with all variables except "name"WWWW
|
||||
profile_details.tag_configure("bold", font=("Courier New", 10, "bold"), foreground="#08872a")
|
||||
for key, value in selected_profile.items():
|
||||
if key != 'name': # Skip displaying the "name" variable
|
||||
profile_details.insert(tk.END, f"{key}: ", "bold")
|
||||
profile_details.insert(tk.END, f"{value}\n")
|
||||
profile_details.config(state=tk.DISABLED)
|
||||
else:
|
||||
profile_name.config(text="Selected Profile: ")
|
||||
profile_details.config(state=tk.NORMAL)
|
||||
profile_details.delete(1.0, tk.END)
|
||||
profile_details.config(state=tk.DISABLED)
|
||||
|
||||
# Function to refresh the profile details
|
||||
def refresh_profile_details():
|
||||
global profiles
|
||||
# Get the index of the currently selected profile
|
||||
selected_index = listbox.curselection()
|
||||
selected_index = int(selected_index[0]) if selected_index else None
|
||||
# Reload configuration from file
|
||||
with open("config.json", "r") as f:
|
||||
config = json.load(f)
|
||||
profiles = config.get("profiles", [])
|
||||
listbox.delete(0, tk.END) # Clear the listbox
|
||||
for profile in profiles:
|
||||
listbox.insert(tk.END, profile['name'])
|
||||
# Reselect the previously selected profile if it exists
|
||||
if selected_index is not None and selected_index < len(profiles):
|
||||
listbox.select_set(selected_index)
|
||||
update_profile_details(None)
|
||||
|
||||
# Function to open the config file
|
||||
def open_config():
|
||||
subprocess.Popen(["start", "config.json"], shell=True)
|
||||
|
||||
# Load configuration from file
|
||||
with open("config.json", "r") as f:
|
||||
config = json.load(f)
|
||||
|
||||
# Get the list of profiles
|
||||
profiles = config.get("profiles", [])
|
||||
# Create the main window
|
||||
root = tk.Tk()
|
||||
root.title(f"Profile Selection - {program_name} {version}")
|
||||
root.iconbitmap("icon.ico")
|
||||
# Set a maximum size for the window
|
||||
width = 850
|
||||
height = 300
|
||||
root.minsize(width, height) # Adjust the values as needed
|
||||
center_window(root, width, height)
|
||||
# Create a frame for listing profiles
|
||||
profiles_frame = tk.Frame(root)
|
||||
profiles_frame.pack(side=tk.LEFT, fill=tk.Y, padx=10, pady=10)
|
||||
# Create a listbox to display available profiles
|
||||
listbox = tk.Listbox(profiles_frame, selectmode=tk.SINGLE)
|
||||
listbox.pack(side=tk.LEFT, fill=tk.Y)
|
||||
|
||||
for profile in profiles:
|
||||
listbox.insert(tk.END, profile['name'])
|
||||
|
||||
# Create a vertical scrollbar for the listbox
|
||||
scrollbar = tk.Scrollbar(profiles_frame, orient=tk.VERTICAL)
|
||||
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||||
# Link the listbox and scrollbar
|
||||
listbox.config(yscrollcommand=scrollbar.set)
|
||||
scrollbar.config(command=listbox.yview)
|
||||
# Bind the listbox selection event to update and refresh the profile details
|
||||
listbox.bind('<<ListboxSelect>>', lambda event: (update_profile_details(event), refresh_profile_details()))
|
||||
listbox.bind('<Return>', run_profile) # Run the selected profile when the Enter key is pressed
|
||||
# Create a frame for displaying profile details
|
||||
details_frame = tk.Frame(root)
|
||||
details_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10, pady=10)
|
||||
# Create a frame for the profile name and the Refresh button
|
||||
profile_name_frame = tk.Frame(details_frame)
|
||||
profile_name_frame.pack(fill="x", pady=(0, 5))
|
||||
# Create the label for the selected profile name
|
||||
profile_name = tk.Label(profile_name_frame, text="Selected Profile: ", anchor="w")
|
||||
profile_name.pack(side=tk.LEFT)
|
||||
# Create a Text widget for displaying profile details with a fixed height and scrollbars
|
||||
profile_details = Text(details_frame, wrap=tk.WORD, height=10, state=tk.DISABLED, exportselection=False)
|
||||
profile_details.pack(fill="both", expand=True)
|
||||
# Create a vertical scrollbar for the profile details Text widget
|
||||
profile_scrollbar = Scrollbar(profile_details, command=profile_details.yview)
|
||||
profile_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||||
# Link the profile details Text widget and scrollbar
|
||||
profile_details.config(yscrollcommand=profile_scrollbar.set)
|
||||
|
||||
# Function to exit the application
|
||||
def on_closing():
|
||||
root.destroy()
|
||||
os._exit(0)
|
||||
|
||||
root.protocol("WM_DELETE_WINDOW", on_closing)
|
||||
|
||||
# Create the "Refresh" button within the profile name frame
|
||||
refresh_button = tk.Button(
|
||||
profile_name_frame,
|
||||
text="Refresh",
|
||||
command=refresh_profile_details,
|
||||
padx=5,
|
||||
pady=0,
|
||||
fg="white",
|
||||
bg="grey",
|
||||
activebackground="#606060",
|
||||
activeforeground="white",
|
||||
relief=tk.RAISED,
|
||||
borderwidth=2,
|
||||
)
|
||||
refresh_button.pack(side=tk.RIGHT)
|
||||
|
||||
# Create the "Github" button that redirects to github.com
|
||||
github_button = tk.Button(
|
||||
profile_name_frame,
|
||||
text="Github",
|
||||
command=lambda: os.startfile(github_link),
|
||||
padx=5,
|
||||
pady=0,
|
||||
fg="white",
|
||||
bg="lightskyblue4",
|
||||
activebackground="lightsteelblue4",
|
||||
activeforeground="white",
|
||||
relief=tk.RAISED,
|
||||
borderwidth=2,
|
||||
)
|
||||
github_button.pack(side=tk.RIGHT, padx=(0, 5))
|
||||
|
||||
# Create the "Config" button
|
||||
config_button = tk.Button(
|
||||
details_frame,
|
||||
text="Config",
|
||||
command=open_config,
|
||||
padx=30,
|
||||
pady=10,
|
||||
fg="white",
|
||||
bg="grey",
|
||||
activebackground="#606060",
|
||||
activeforeground="white",
|
||||
relief=tk.RAISED,
|
||||
borderwidth=2,
|
||||
)
|
||||
config_button.pack(side=tk.LEFT, fill="x", padx=(0, 2), pady=(10, 0), expand=False)
|
||||
|
||||
# Create the "Run" button
|
||||
run_button = tk.Button(
|
||||
details_frame,
|
||||
text="Run",
|
||||
command=run_profile,
|
||||
padx=10,
|
||||
pady=10,
|
||||
fg="white",
|
||||
bg="#08872a",
|
||||
activebackground="#076921",
|
||||
activeforeground="white",
|
||||
relief=tk.RAISED,
|
||||
borderwidth=2,
|
||||
)
|
||||
|
||||
run_button.pack(side=tk.LEFT, fill="x", padx=(2, 0), pady=(10, 0), expand=True)
|
||||
# Configure weights for horizontal stretching
|
||||
details_frame.pack_propagate(False)
|
||||
# Start with no profile selected
|
||||
selected_profile = None
|
||||
|
||||
# Select the first profile by default
|
||||
if profiles:
|
||||
selected_profile = profiles[0]
|
||||
listbox.select_set(0) # Highlight the first item in the list
|
||||
update_profile_details(None) # Update the profile details
|
||||
|
||||
root.mainloop()
|
||||
|
||||
# Access the selected profile's data after the window closes
|
||||
if selected_profile:
|
||||
payload = selected_profile.get('payload')
|
||||
url = selected_profile.get('url', "")
|
||||
ssid = selected_profile.get('ssid', "")
|
||||
check_every_second = selected_profile.get('check_every_second', "")
|
||||
dialog_geometry = selected_profile.get('dialog_geometry', "")
|
||||
headers = selected_profile.get('headers', "")
|
||||
if ssid:
|
||||
expected_ssid = ssid
|
||||
expected_ssid_lower = expected_ssid.lower()
|
||||
else:
|
||||
ssid = "Ethernet"
|
||||
expected_ssid = ssid
|
||||
expected_ssid_lower = expected_ssid.lower()
|
||||
|
||||
# Function to send the request
|
||||
def send_request():
|
||||
session = requests.Session()
|
||||
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += 'HIGH:!DH:!aNULL'
|
||||
response = session.post(url, json.dumps(payload), headers=headers, allow_redirects=True, verify=False, timeout=10)
|
||||
response.raise_for_status()
|
||||
return response
|
||||
|
||||
# Function to check if internet is available
|
||||
def is_internet_available():
|
||||
try:
|
||||
# -n is the number of pings
|
||||
# -l is the size of the packet
|
||||
# -w is the timeout in seconds
|
||||
subprocess.run(['ping', '8.8.8.8', '-n', '3', '-l', '32', '-w', '20'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=subprocess.CREATE_NO_WINDOW)
|
||||
return True
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
|
||||
# Function to get the currently connected SSID using system commands (for Windows)
|
||||
def get_connected_network():
|
||||
try:
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
# Check if connected to Ethernet
|
||||
ethernet_output = subprocess.check_output(["netsh", "interface", "show", "interface"], startupinfo=startupinfo).decode("utf-8")
|
||||
ethernet_lines = ethernet_output.split("\n")
|
||||
for line in ethernet_lines:
|
||||
if "Connected" in line:
|
||||
if "Ethernet" in line:
|
||||
return "Ethernet"
|
||||
# If not connected to Ethernet, check Wi-Fi SSID
|
||||
wifi_output = subprocess.check_output(["netsh", "wlan", "show", "interfaces"], startupinfo=startupinfo).decode("utf-8")
|
||||
wifi_lines = wifi_output.split("\n")
|
||||
wifi_ssid = None
|
||||
for line in wifi_lines:
|
||||
if "SSID" in line:
|
||||
wifi_ssid = line.strip().split(": ")[1]
|
||||
break
|
||||
if wifi_ssid is not None:
|
||||
return wifi_ssid
|
||||
else:
|
||||
return False
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
|
||||
# Is connected to wifi
|
||||
def is_connected_to_wifi():
|
||||
try:
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
wifi_output = subprocess.check_output(["netsh", "wlan", "show", "interfaces"], startupinfo=startupinfo).decode("utf-8")
|
||||
wifi_lines = wifi_output.split("\n")
|
||||
for line in wifi_lines:
|
||||
if "SSID" in line:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except subprocess.CalledProcessError:
|
||||
return False
|
||||
|
||||
# Function to exit the application
|
||||
def exit_application(icon, item):
|
||||
icon.stop()
|
||||
os._exit(0)
|
||||
|
||||
# Queue to store log messages
|
||||
log_messages = deque(maxlen=15)
|
||||
log_dialog = None
|
||||
log_text = None
|
||||
log_dialog_open = False
|
||||
# Get the dialog geometry from the config file
|
||||
width = dialog_geometry["width"]
|
||||
height = dialog_geometry["height"]
|
||||
x = 0
|
||||
y = 0
|
||||
|
||||
# Function to update the window's position and size variables
|
||||
def update_window_geometry(event):
|
||||
global x, y, width, height
|
||||
x, y = event.x, event.y
|
||||
width, height = event.width, event.height
|
||||
|
||||
# Function to show the log dialog with the currently selected profile name
|
||||
def show_log_dialog():
|
||||
global log_dialog, log_text, log_dialog_open, successful_logins_label
|
||||
if not log_dialog_open:
|
||||
log_dialog_open = True
|
||||
if log_dialog:
|
||||
log_dialog.title(f"Log Messages ({selected_profile['name']})") # Update title with profile name
|
||||
log_dialog.deiconify()
|
||||
update_log()
|
||||
else:
|
||||
log_dialog = tk.Tk()
|
||||
log_dialog.title(f"Log Messages ({selected_profile['name']})") # Update title with profile name
|
||||
log_text = tk.Text(log_dialog)
|
||||
log_frame = tk.Frame(log_dialog)
|
||||
log_frame.pack(fill=tk.BOTH, expand=True)
|
||||
log_text = tk.Text(log_frame, wrap=tk.WORD)
|
||||
log_text.pack(fill=tk.BOTH, expand=True)
|
||||
log_dialog.minsize(200, 120)
|
||||
# Create label for successful logins count
|
||||
successful_logins_label = tk.Label(log_dialog, text=f"Successful Logins: {successful_logins_count}", anchor="w", padx=5)
|
||||
successful_logins_label.place(x=0, rely=1.0, anchor=tk.SW, bordermode=tk.OUTSIDE)
|
||||
update_log()
|
||||
log_dialog.protocol("WM_DELETE_WINDOW", hide_log_dialog)
|
||||
center_window(log_dialog, width, height)
|
||||
log_dialog.bind("<Configure>", update_window_geometry)
|
||||
log_dialog.mainloop()
|
||||
else:
|
||||
hide_log_dialog()
|
||||
|
||||
# Function to hide the log dialog
|
||||
def hide_log_dialog():
|
||||
global log_dialog, log_text, log_dialog_open
|
||||
log_dialog_open = False
|
||||
if log_dialog:
|
||||
log_dialog.withdraw()
|
||||
log_dialog = None
|
||||
log_text = None
|
||||
|
||||
# Function to get the last log messages
|
||||
def get_last_log_messages():
|
||||
global log_messages
|
||||
return list(log_messages)
|
||||
|
||||
# Function to update the log
|
||||
def update_log():
|
||||
if log_text:
|
||||
log_text.delete(1.0, tk.END)
|
||||
for message in get_last_log_messages():
|
||||
log_text.insert(tk.END, message + "\n")
|
||||
|
||||
# Add a global variable to keep track of successful logins count
|
||||
successful_logins_count = 0
|
||||
successful_logins_label = None
|
||||
|
||||
# Function to add a message to the log
|
||||
def add_to_log(message):
|
||||
global log_messages, successful_logins_count
|
||||
now = datetime.now()
|
||||
timestamp = now.strftime("%Y-%m-%d %H:%M:%S")
|
||||
log_messages.append(f"({timestamp}) {message}")
|
||||
update_log() # Update the log window
|
||||
|
||||
# Function to update the log
|
||||
def update_log():
|
||||
if log_text:
|
||||
log_text.delete(1.0, tk.END)
|
||||
for message in get_last_log_messages():
|
||||
log_text.insert(tk.END, message + "\n")
|
||||
update_successful_logins_count() # Update the successful logins count
|
||||
|
||||
# Function to update the successful logins count label
|
||||
def update_successful_logins_count():
|
||||
if log_dialog:
|
||||
if successful_logins_label:
|
||||
successful_logins_label.config(text=f"Successful Logins: {successful_logins_count}")
|
||||
|
||||
# Function to add a message to the log file (txt)
|
||||
def save_to_file(message):
|
||||
# Get the current date and time
|
||||
now = datetime.now()
|
||||
timestamp = now.strftime("%Y-%m-%d %H:%M:%S")
|
||||
# Format the message with the timestamp
|
||||
formatted_message = f"({timestamp}) {message}\n"
|
||||
# Open the file in append mode and write the formatted message
|
||||
with open("log.txt", "a") as f:
|
||||
f.write(formatted_message)
|
||||
|
||||
# Create the system tray icon
|
||||
def create_system_tray_icon():
|
||||
image = Image.open("icon.ico")
|
||||
menu = pystray.Menu(
|
||||
pystray.MenuItem('Show Log', show_log_dialog, default=True),
|
||||
pystray.MenuItem('Exit', exit_application)
|
||||
)
|
||||
icon = pystray.Icon("my_icon", image, "HotspotAutoLogin", menu)
|
||||
icon.run()
|
||||
|
||||
# Function to check network status
|
||||
running = True
|
||||
errorcount = 0
|
||||
request_success = False
|
||||
request_errorcount = 0
|
||||
sleepcount = check_every_second
|
||||
connected_ssid_lower = None
|
||||
def check_network_status():
|
||||
global running, errorcount, sleepcount, connected_ssid_lower, ssid, response, request_success, request_errorcount, successful_logins_count
|
||||
while running and errorcount < 10:
|
||||
connected_ssid = get_connected_network()
|
||||
if (connected_ssid):
|
||||
connected_ssid_lower = connected_ssid.lower()
|
||||
if (connected_ssid) and ((connected_ssid_lower == expected_ssid_lower)):
|
||||
if is_connected_to_wifi() and (connected_ssid == "Ethernet" and expected_ssid == "Ethernet"):
|
||||
message = "You are both connected to Wi-Fi and Ethernet. Disconnecting from Wi-Fi and continuing with Ethernet..."
|
||||
add_to_log(message)
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
subprocess.check_output(['netsh', 'wlan', 'disconnect', 'interface=' + "Wi-Fi"], startupinfo=startupinfo).decode("utf-8")
|
||||
time.sleep(5)
|
||||
if (is_internet_available()):
|
||||
sleepcount = check_every_second
|
||||
request_success = False
|
||||
request_errorcount = 0
|
||||
message = "Connected to {} and internet connection is available. Checking again in {} seconds...".format(connected_ssid, str(sleepcount))
|
||||
errorcount = 0
|
||||
add_to_log(message)
|
||||
elif request_success and request_errorcount < 3:
|
||||
# If the request was successful but there is still no internet connection, wait for a few seconds and try again
|
||||
sleepcount = 60
|
||||
request_errorcount += 1
|
||||
message = "Even the request was successful, there is still no internet connection. There might be a problem with your network. If you are using a VPN, please check your VPN connection. Giving it some time and checking again in {} seconds... (Request Again: {}/3)".format(str(sleepcount), str(request_errorcount))
|
||||
add_to_log(message)
|
||||
save_to_file(message)
|
||||
else:
|
||||
sleepcount = 5
|
||||
message = "Connected to {} but internet is down. Sending the request in {} seconds...".format(connected_ssid, str(sleepcount))
|
||||
add_to_log(message)
|
||||
save_to_file(message)
|
||||
time.sleep(sleepcount)
|
||||
try:
|
||||
# Function to send request
|
||||
response = send_request()
|
||||
if response.ok:
|
||||
errorcount = 0
|
||||
sleepcount = 15
|
||||
request_success = True
|
||||
request_errorcount = 0
|
||||
successful_logins_count += 1
|
||||
message = "Request was successful. Checking the internet connection in {} seconds...".format(str(sleepcount))
|
||||
add_to_log(message)
|
||||
save_to_file(message)
|
||||
except requests.exceptions.RequestException as e:
|
||||
errorcount += 1
|
||||
sleepcount = 3
|
||||
request_success = False
|
||||
if isinstance(e, requests.exceptions.HTTPError):
|
||||
# Handle HTTP errors with different messages for different status codes
|
||||
status_code = e.response.status_code
|
||||
if status_code == 400:
|
||||
message = "Request failed with 400 Bad Request error. Please check your payload and URL. Trying to reconnect to the network... (Errors: {}/10)".format(errorcount)
|
||||
elif status_code == 404:
|
||||
message = "Request failed with 404 Not Found error. Trying to reconnect to the network... (Errors: {}/10)".format(errorcount)
|
||||
elif status_code == 500:
|
||||
message = "Request failed with 500 Internal Server Error. Trying to reconnect to the network... (Errors: {}/10)".format(errorcount)
|
||||
elif status_code == 503:
|
||||
message = "Request failed with 503 Service Unavailable error. Trying to reconnect to the network... (Errors: {}/10)".format(errorcount)
|
||||
else:
|
||||
message = "Request failed with HTTP error ({}). Trying to reconnect to the network... (Errors: {}/10)".format(status_code, errorcount)
|
||||
else:
|
||||
message = "Request failed with error: {}. If you are usşng a VPN, please disable it for now. Trying to reconnect to the network... (Errors: {}/10)".format(e, errorcount)
|
||||
add_to_log(message)
|
||||
save_to_file(message)
|
||||
time.sleep(sleepcount)
|
||||
# If the payload URL is not reachable, try to reconnect to the network
|
||||
if connected_ssid == "Ethernet":
|
||||
try:
|
||||
# Disable and enable the Ethernet adapter
|
||||
message = "Disconnecting from Ethernet..."
|
||||
add_to_log(message)
|
||||
subprocess.check_output(['ipconfig', '/release', "Ethernet"], shell=True, text=True)
|
||||
time.sleep(5)
|
||||
subprocess.check_output(['ipconfig', '/renew', "Ethernet"], shell=True, text=True)
|
||||
message = "Connected to Ethernet. Running the script again..."
|
||||
add_to_log(message)
|
||||
time.sleep(5)
|
||||
except Exception as e:
|
||||
errorcount += 1
|
||||
message = "Failed to reconnect to Ethernet: {} (Errors: {}/10)".format(e, errorcount)
|
||||
add_to_log(message)
|
||||
save_to_file(message)
|
||||
else:
|
||||
try:
|
||||
# Disconnect and reconnect to the Wi-Fi network
|
||||
message = "Disconnecting from {}...".format(ssid)
|
||||
add_to_log(message)
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
subprocess.check_output(['netsh', 'wlan', 'disconnect', 'interface=' + "Wi-Fi"], startupinfo=startupinfo).decode("utf-8")
|
||||
time.sleep(5)
|
||||
subprocess.check_output(['netsh', 'wlan', 'connect', 'name=' + ssid], startupinfo=startupinfo).decode("utf-8")
|
||||
message = "Connected to {}. Running the script again...".format(ssid)
|
||||
add_to_log(message)
|
||||
time.sleep(8)
|
||||
except Exception as e:
|
||||
errorcount += 1
|
||||
message = "Failed to reconnect to {}: {} (Errors: {}/10)".format(ssid, e, errorcount)
|
||||
add_to_log(message)
|
||||
save_to_file(message)
|
||||
continue
|
||||
else:
|
||||
startupinfo = subprocess.STARTUPINFO()
|
||||
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
wifi_output = subprocess.check_output(["netsh", "interface", "show", "interface"], startupinfo=startupinfo).decode("utf-8")
|
||||
wifi_lines = wifi_output.split("\n")
|
||||
wifi_enabled = False
|
||||
for line in wifi_lines:
|
||||
if "Wi-Fi" in line:
|
||||
if "Enabled" in line:
|
||||
wifi_enabled = True
|
||||
break
|
||||
if connected_ssid == "Ethernet":
|
||||
sleepcount = 30
|
||||
message = "If you want to connect to {}, please unplug your ethernet cable or disconnect from {}. Checking again in {} seconds...".format(expected_ssid, connected_ssid, str(sleepcount))
|
||||
errorcount = 0
|
||||
add_to_log(message)
|
||||
elif expected_ssid == "Ethernet":
|
||||
sleepcount = 30
|
||||
message = "Looks like your ethernet cable is not plugged in. Please plug in your ethernet cable. Checking again in {} seconds...".format(str(sleepcount))
|
||||
errorcount = 0
|
||||
add_to_log(message)
|
||||
elif wifi_enabled:
|
||||
if (connected_ssid):
|
||||
sleepcount = 10
|
||||
message = "You are connected to {}, but you need to be connected to {}. Trying to connect {}...".format(connected_ssid, expected_ssid, expected_ssid)
|
||||
add_to_log(message)
|
||||
else:
|
||||
sleepcount = 10
|
||||
message = "You are not connected to {}. Trying to connect {}...".format(expected_ssid, expected_ssid)
|
||||
add_to_log(message)
|
||||
try:
|
||||
result = subprocess.run(['netsh', 'wlan', 'connect', 'name=' + expected_ssid], capture_output=True, text=True, startupinfo=startupinfo)
|
||||
if result.returncode != 0:
|
||||
if result.returncode == 1:
|
||||
sleepcount = 20
|
||||
message = "Could not find a Wi-Fi network with SSID: {}. If your Wi-Fi is disabled, please enable it. Checking again in {} seconds...".format(expected_ssid, str(sleepcount))
|
||||
add_to_log(message)
|
||||
else:
|
||||
raise subprocess.CalledProcessError(result.returncode, result.args, result.stderr)
|
||||
else:
|
||||
message = "Connected to {}. Running the script again in {} seconds...".format(expected_ssid, str(sleepcount))
|
||||
add_to_log(message)
|
||||
except (subprocess.CalledProcessError, ValueError) as e:
|
||||
errorcount += 1
|
||||
sleepcount = 15
|
||||
if isinstance(e, subprocess.CalledProcessError):
|
||||
message = "Failed to connect to {}: {}. Trying again in {} seconds... (Errors:{}/10)".format(expected_ssid, e, str(sleepcount), errorcount)
|
||||
else:
|
||||
message = str(e) + ". Trying again in {} seconds... (Errors:{}/10)".format(str(sleepcount), errorcount)
|
||||
add_to_log(message)
|
||||
save_to_file(message)
|
||||
elif wifi_enabled == False:
|
||||
sleepcount = 30
|
||||
errorcount += 1
|
||||
message = "You are not connected to Ethernet and your Wi-Fi is disabled. Please enable your Wi-Fi or plug in your ethernet cable. Checking again in {} seconds... (Errors: {}/10)".format(str(sleepcount), errorcount)
|
||||
add_to_log(message)
|
||||
save_to_file(message)
|
||||
else:
|
||||
sleepcount = 30
|
||||
errorcount += 1
|
||||
message = "Something went wrong. Please check your Wi-Fi or Ethernet connection. Checking again in {} seconds... (Errors: {}/10)".format(str(sleepcount), errorcount)
|
||||
save_to_file(message)
|
||||
add_to_log(message)
|
||||
time.sleep(sleepcount) # Sleep ... seconds before trying again
|
||||
message = "Maximum error count reached. Exiting in 5 seconds..."
|
||||
add_to_log(message)
|
||||
save_to_file(message)
|
||||
time.sleep(5)
|
||||
running = False
|
||||
os._exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Create a thread for the system tray icon
|
||||
tray_thread = threading.Thread(target=create_system_tray_icon)
|
||||
tray_thread.start()
|
||||
# Open Log Messages at startup
|
||||
open_log_messages_startup = threading.Thread(target=show_log_dialog)
|
||||
open_log_messages_startup.start()
|
||||
# Start the network status checking in the main thread
|
||||
check_network_status()
|
||||
# Wait for all threads to finish
|
||||
tray_thread.join()
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"profiles": [
|
||||
{
|
||||
"name": "My School Wi-Fi",
|
||||
"ssid": "SCHOOL_WIFI_5G",
|
||||
"url": "https://connect.schoolwifi.com/api/portal/dynamic/authenticate",
|
||||
"payload": {
|
||||
"username": "[email protected]",
|
||||
"password": "123455678"
|
||||
},
|
||||
"headers": {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
"Connection": "keep-alive",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
|
||||
},
|
||||
"check_every_second": 600,
|
||||
"dialog_geometry": {
|
||||
"width": 1024,
|
||||
"height": 500
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "My School ETHERNET",
|
||||
"url": "http://10.3.41.15:8002/index.php?zone=dormnet",
|
||||
"payload": "&auth_user=85795013%40myschool.com&auth_pass=123455678&redirurl=&accept=Login",
|
||||
"headers": {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"Connection": "keep-alive",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.69"
|
||||
},
|
||||
"check_every_second": 600,
|
||||
"dialog_geometry": {
|
||||
"width": 1024,
|
||||
"height": 500
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
@@ -0,0 +1 @@
|
||||
C:\Users\deniz\Desktop\t
|
||||
@@ -0,0 +1,4 @@
|
||||
urllib3==1.26.18
|
||||
requests==2.31.0
|
||||
pystray==0.19.5
|
||||
dnspython==2.6.1
|
||||
@@ -1,52 +1,118 @@
|
||||
@echo off
|
||||
setlocal enabledelayedexpansion
|
||||
cd /d "%~dp0"
|
||||
set NAME=HotspotAutoLogin
|
||||
set RUN=HotspotAutoLogin.pyw
|
||||
set "requirementsFile=requirements.txt"
|
||||
set PROJECTFOLDER=main
|
||||
set RUN=%PROJECTFOLDER%\HotspotAutoLogin.pyw
|
||||
set requirementsFile=%PROJECTFOLDER%\requirements.txt
|
||||
set VENV_PATH=.venv
|
||||
set ACTIVATE_PATH=%VENV_PATH%\Scripts\activate
|
||||
set CURRENT_DIR=%CD%
|
||||
set LAST_DIR_FILE=%PROJECTFOLDER%\last_known_directory.txt
|
||||
set refrenv=%PROJECTFOLDER%\refrenv.bat
|
||||
set PYTHON_DOWNLOAD_URL=https://www.python.org/ftp/python/3.12.2/python-3.12.2-amd64.exe
|
||||
|
||||
:: Display provided argument if any
|
||||
if not "%~1"=="" (
|
||||
echo Open with: "%~1"
|
||||
)
|
||||
|
||||
:: Check if Python is installed
|
||||
pip --version >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo Python is not installed.
|
||||
set /p "userinp=Do you want to install Python (y/n)? "
|
||||
if /i "!userinp!"=="y" (
|
||||
echo Opening download link...
|
||||
start https://www.python.org/downloads/
|
||||
exit /b
|
||||
pip --version >nul 2>&1 && (set python_installed=true) || (set python_installed=false)
|
||||
if not "%python_installed%"=="true" (
|
||||
echo Python is required to run this program.
|
||||
set /p "userinp=Do you want to install Python (y/n)?: "
|
||||
if /i "!userinp!"=="y" (
|
||||
echo Downloading Python...
|
||||
winget install python --accept-package-agreements
|
||||
if errorlevel 1 (
|
||||
echo Download failed using winget method. Trying to download manually...
|
||||
:bothwingetfailed
|
||||
if not exist "%PROJECTFOLDER%\python_installer.exe" (
|
||||
echo Downloading Python from %PYTHON_DOWNLOAD_URL%
|
||||
curl %PYTHON_DOWNLOAD_URL% -o %PROJECTFOLDER%\python_installer.exe
|
||||
if not exist "%PROJECTFOLDER%\python_installer.exe" (
|
||||
echo Download failed using curl. Trying with the powershell method
|
||||
powershell -Command "& {Invoke-WebRequest -Uri '%PYTHON_DOWNLOAD_URL%' -OutFile '%PROJECTFOLDER%\python_installer.exe'}"
|
||||
if errorlevel 1 (
|
||||
echo Failed to install Python. Please install Python manually and try again.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
)
|
||||
echo Installing Python. Please wait...
|
||||
start /wait %PROJECTFOLDER%\python_installer.exe /quiet InstallAllUsers=1 PrependPath=1 Include_test=0
|
||||
if errorlevel 1 (
|
||||
echo Failed to install Python. Please install Python manually and try again.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
del %PROJECTFOLDER%\python_installer.exe
|
||||
goto python_ok
|
||||
)
|
||||
) else (
|
||||
echo Please install Python and try again.
|
||||
pause
|
||||
exit /b
|
||||
echo Python is required to run this program. Please install Python and try again.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
:python_ok
|
||||
echo Python installed successfully.
|
||||
:: Refresh the environment variables
|
||||
call %refrenv%
|
||||
set python_installed=true
|
||||
)
|
||||
|
||||
:: Check if virtual environment exists
|
||||
IF NOT EXIST %VENV_PATH% (
|
||||
echo Creating virtual environment...
|
||||
python -m venv %VENV_PATH%
|
||||
echo Creating virtual environment...
|
||||
echo %CURRENT_DIR% > "%LAST_DIR_FILE%"
|
||||
python -m venv %VENV_PATH%
|
||||
) ELSE (
|
||||
goto check_python
|
||||
goto check_python
|
||||
)
|
||||
|
||||
:: Check if Python exists at the path stored in the virtual environment
|
||||
set counut_python=0
|
||||
set count_python=0
|
||||
:check_python
|
||||
%VENV_PATH%\Scripts\python.exe --version >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
set /a count_python+=1
|
||||
echo Python not found at the path stored in the virtual environment.
|
||||
echo Recreating virtual environment...
|
||||
rmdir /s /q %VENV_PATH%
|
||||
python -m venv %VENV_PATH%
|
||||
if !count_python! lss 3 (
|
||||
goto check_python
|
||||
) else (
|
||||
echo Something went wrong. Please try again.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
set /a count_python+=1
|
||||
echo Python not found at the path stored in the virtual environment.
|
||||
echo Recreating virtual environment...
|
||||
rmdir /s /q %VENV_PATH%
|
||||
python -m venv %VENV_PATH%
|
||||
if !count_python! lss 3 (
|
||||
goto check_python
|
||||
) else (
|
||||
echo Something went wrong. Please try again.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
:: Check if the current directory has changed since the last run
|
||||
if exist "%LAST_DIR_FILE%" (
|
||||
set /p last_dir=<"%LAST_DIR_FILE%"
|
||||
cd "%CURRENT_DIR%" && (
|
||||
if not exist "!last_dir!" (
|
||||
echo Current directory: %CURRENT_DIR%
|
||||
echo Last known directory: !last_dir!
|
||||
echo Looks like the directory of the program has been changed.
|
||||
echo It is hihgly recommended to recreate the virtual environment.
|
||||
set /p "recreate_venv=Recreate the virtual environment (y/n)?: "
|
||||
if /i "!recreate_venv!"=="y" (
|
||||
echo Recreating virtual environment...
|
||||
rmdir /s /q %VENV_PATH%
|
||||
python -m venv %VENV_PATH%
|
||||
:: Update the last directory file
|
||||
echo %CURRENT_DIR% > "%LAST_DIR_FILE%"
|
||||
)
|
||||
)
|
||||
)
|
||||
) else (
|
||||
:: Create the last directory file if it doesn't exist
|
||||
echo %CURRENT_DIR% > "%LAST_DIR_FILE%"
|
||||
)
|
||||
|
||||
:: Activate the virtual environment
|
||||
@@ -55,45 +121,46 @@ set count_activate=0
|
||||
echo Activating virtual environment...
|
||||
call %ACTIVATE_PATH%
|
||||
if errorlevel 1 (
|
||||
set /a count_activate+=1
|
||||
echo Failed to activate virtual environment.
|
||||
echo Recreating virtual environment...
|
||||
rmdir /s /q %VENV_PATH%
|
||||
python -m venv %VENV_PATH%
|
||||
if !count_activate! lss 3 (
|
||||
goto activate
|
||||
) else (
|
||||
echo Failed to activate virtual environment. Please try again.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
set /a count_activate+=1
|
||||
echo Failed to activate virtual environment.
|
||||
echo Recreating virtual environment...
|
||||
rmdir /s /q %VENV_PATH%
|
||||
python -m venv %VENV_PATH%
|
||||
if !count_activate! lss 3 (
|
||||
goto activate
|
||||
) else (
|
||||
echo Failed to activate virtual environment. Please try again.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
:: Get the list of installed packages using pip freeze
|
||||
echo Checking the requirements...
|
||||
for /f "tokens=1,* delims==" %%i in ('pip freeze') do (
|
||||
set installed[%%i]=%%j
|
||||
for /f "tokens=1,* delims==" %%i in ('pip freeze --all') do (
|
||||
set installed[%%i]=%%j
|
||||
)
|
||||
|
||||
:: Compare with the requirements from the requirements.txt file
|
||||
for /f "tokens=1,* delims==" %%i in (%requirementsFile%) do (
|
||||
if not "!installed[%%i]!"=="%%j" (
|
||||
echo Installing package: %%i==%%j
|
||||
pip install %%i==%%j --upgrade --quiet
|
||||
if errorlevel 1 (
|
||||
echo Failed to install %%i==%%j. Please check your internet connection and try again.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
if not "!installed[%%i]!"=="%%j" (
|
||||
echo Installing package: %%i==%%j
|
||||
pip install %%i==%%j --upgrade --quiet
|
||||
if errorlevel 1 (
|
||||
echo Failed to install %%i==%%j. Please check your internet connection and try again.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
:: Run the program
|
||||
echo Starting %NAME%...
|
||||
start /B "" "%VENV_PATH%/Scripts/pythonw.exe" %RUN%
|
||||
start /B "" "%VENV_PATH%\Scripts\pythonw.exe" %RUN% %* > nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo Failed to start %NAME%. Please try again.
|
||||
pause
|
||||
exit /b
|
||||
echo Failed to start %NAME%. Please try again.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
exit /b
|
||||
Reference in New Issue
Block a user