Compare commits

...
Author SHA1 Message Date
Deniz Şafak 337c84e9a4 v1.90fix3 2025-01-01 18:56:54 +03:00
Deniz Şafak bcbad5b8f8 Update README.md 2025-01-01 04:02:31 +03:00
Deniz Şafak f55f09079a v1.90 2025-01-01 04:00:39 +03:00
Deniz Şafak 7ec6601554 v1.90fix2 2025-01-01 03:45:45 +03:00
Deniz Şafak 10c3b7f233 Add files via upload 2025-01-01 03:45:22 +03:00
Deniz Şafak bbc9be3b93 v.190fix 2025-01-01 03:39:27 +03:00
Deniz Şafak 2ff513099f v1.90 2025-01-01 03:11:00 +03:00
Deniz Şafak 54eea0ad63 Update README.md 2024-10-26 01:07:10 +03:00
Deniz Şafak fee77034f4 Update README.md 2024-10-26 01:06:56 +03:00
Deniz Şafak af880b0e92 Update README.md 2024-10-26 00:57:16 +03:00
Deniz Şafak c495415df9 v1.83 2024-10-26 00:48:35 +03:00
4 changed files with 490 additions and 68 deletions
+15 -5
View File
@@ -16,8 +16,8 @@ HotspotAutoLogin is a script that designed to automate the login process for Wi-
- Double-click on HotspotAutoLogin.exe to launch the application.
### Option 2: Run with Python
- Clone or download the repository to your local machine.
- Install Python to your computer.
- Clone or [download the repository](https://github.com/denizsafak/HotspotAutoLogin/archive/refs/heads/main.zip) to your local machine.
- Extract from zip.
- Run "run.bat" file.
## `Features`
@@ -32,6 +32,8 @@ HotspotAutoLogin is a script that designed to automate the login process for Wi-
- You can view the log of the script's actions by clicking the "Show Log" option in the system tray menu.
## `How to Configure the config.json?`
> [!TIP]
> I recebtly, added "Add new" button to the program, so you can achieve the same thing without needing to edit the config.json.
![How to Animation.](/examples/howto.gif)
@@ -46,6 +48,8 @@ HotspotAutoLogin is a script that designed to automate the login process for Wi-
`"url":` Enter the "Request URL" in the "Headers" tab here.
`"internet_check_url":` URL to check your internet connection. Program will try to access this address to check if you have internet connection. If 8.8.8.8 is accessible **before** you log into your network, change this.
![Example Request.](/examples/Request.png)
@@ -60,9 +64,10 @@ HotspotAutoLogin is a script that designed to automate the login process for Wi-
{
"profiles": [
{
"name": "My School Wi-Fi",
"ssid": "SCHOOL_WIFI_5G",
"name": "Example Wi-Fi",
"ssid": "EXAMPLE_WIFI_5G",
"url": "https://connect.schoolwifi.com/api/portal/dynamic/authenticate",
"internet_check_url": "8.8.8.8",
"payload": {
"username": "[email protected]",
"password": "123455678"
@@ -79,9 +84,10 @@ HotspotAutoLogin is a script that designed to automate the login process for Wi-
}
},
{
"name": "My School ETHERNET",
"name": "Example ETHERNET",
"url": "http://10.3.41.15:8002/index.php?zone=dormnet",
"payload": "&auth_user=85795013%40myschool.com&auth_pass=123455678&redirurl=&accept=Login",
"internet_check_url": "8.8.8.8",
"headers": {
"Content-Type": "application/x-www-form-urlencoded",
"Connection": "keep-alive",
@@ -97,6 +103,10 @@ HotspotAutoLogin is a script that designed to automate the login process for Wi-
}
```
> [!CAUTION]
> Recent Windows updates restricts third-party apps from accessing Wi-Fi names unless location services are enabled. To fix this, turn on location services in your settings. For more details, check the article from 04/02/2024 [Changes to API behavior for Wi-Fi access and location](https://learn.microsoft.com/en-us/windows/win32/nativewifi/wi-fi-access-location-changes).
> [!NOTE]
> - The script relies on the assumption that the web portal uses basic authentication. If the portal uses a more complex login mechanism, additional adjustments may be necessary.
> - This script is primarily intended for Windows. Adaptations might be needed for other operating systems.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 101 KiB

+466 -54
View File
@@ -3,9 +3,14 @@ import os
import requests
import time
import subprocess
import re
import socket
import pystray
import threading
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.messagebox as messagebox
from urllib.parse import urlparse
from tkinter import Text, Scrollbar
from PIL import Image
from collections import deque
@@ -24,7 +29,7 @@ os.chdir(script_dir)
# Program Information
program_name = "HotspotAutoLogin"
version = "v1.83"
version = "v1.90"
github_link = "https://github.com/denizsafak/HotspotAutoLogin"
# Function to center a window on the screen
@@ -54,12 +59,17 @@ def update_profile_details(event):
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
# Insert profile details as JSON with coloring
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.tag_configure("normal", font=("Courier New", 10), foreground="#000000")
profile_json = json.dumps({k: v for k, v in selected_profile.items() if k != 'name'}, indent=4)
for line in profile_json.splitlines():
if ':' in line:
key, value = line.split(':', 1)
profile_details.insert(tk.END, key + ':', "bold")
profile_details.insert(tk.END, value + "\n", "normal")
else:
profile_details.insert(tk.END, line + "\n", "normal")
profile_details.config(state=tk.DISABLED)
else:
profile_name.config(text="Selected Profile: ")
@@ -107,17 +117,380 @@ 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 frame to hold the listbox and its scrollbar
listbox_frame = tk.Frame(profiles_frame)
listbox_frame.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
# Create a listbox to display available profiles
listbox = tk.Listbox(profiles_frame, selectmode=tk.SINGLE)
listbox.pack(side=tk.LEFT, fill=tk.Y)
listbox = tk.Listbox(listbox_frame, selectmode=tk.SINGLE)
listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
def scan_wifi_ssids():
ssids = []
try:
result = subprocess.run(
["netsh", "wlan", "show", "networks"],
capture_output=True,
text=True,
shell=True,
creationflags=subprocess.CREATE_NO_WINDOW
)
output = result.stdout
for line in output.splitlines():
line = line.strip()
if line.startswith("SSID"):
parts = line.split(" : ")
if len(parts) == 2:
ssids.append(parts[1])
except:
pass
return ssids
def add_new_profile():
def show_context_menu(event):
context_menu = tk.Menu(root, tearoff=0)
context_menu.add_command(label="Cut", command=lambda: event.widget.event_generate("<<Cut>>"))
context_menu.add_command(label="Copy", command=lambda: event.widget.event_generate("<<Copy>>"))
context_menu.add_command(label="Paste", command=lambda: event.widget.event_generate("<<Paste>>"))
context_menu.tk_popup(event.x_root, event.y_root)
def get_current_connected_ssid():
try:
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
output = subprocess.check_output(["netsh", "wlan", "show", "interfaces"], text=True, startupinfo=startupinfo)
match = re.search(r"^\s*SSID\s*:\s*(.+)$", output, re.MULTILINE)
if match:
return match.group(1).strip()
except subprocess.CalledProcessError:
pass
return None
def toggle_ethernet():
if use_ethernet_var.get():
ssid_combo.config(state="disabled")
else:
ssid_combo.config(state="normal")
def refresh_wifi_list():
ssid_list = scan_wifi_ssids()
ssid_combo["values"] = ssid_list
if ssid_list and not use_ethernet_var.get():
ssid_var.set(ssid_list[0])
def error_message(message):
if message:
error_label.config(text=message, bg="red")
if not error_label.winfo_ismapped():
error_label.pack(fill="x", pady=(5, 5))
add_window.update_idletasks()
add_window.geometry(f"{add_window.winfo_width()}x{add_window.winfo_height() + error_label.winfo_reqheight()+10}")
else:
if error_label.winfo_ismapped():
add_window.geometry(f"{add_window.winfo_width()}x{add_window.winfo_height() - error_label.winfo_reqheight()+10}")
error_label.pack_forget()
def save_profile():
raw_payload = payload_text.get("1.0", tk.END).rstrip("\n").strip(" ,")
raw_headers = headers_text.get("1.0", tk.END).rstrip("\n").strip(" ,")
# Validate inputs
name = name_var.get().strip()
ssid = ssid_var.get().strip()
url = url_var.get().strip()
internet_check_url = internet_check_url_var.get().strip()
check_every_second = check_every_second_var.get().strip()
dialog_width = dialog_width_var.get().strip()
dialog_height = dialog_height_var.get().strip()
if not name:
error_message("Name cannot be empty.")
return
if any(profile['name'].strip().lower() == name.lower() for profile in profiles):
error_message("Profile with this name already exists.")
return
if not ssid:
error_message("SSID cannot be empty.")
return
if not url:
error_message("Request URL cannot be empty.")
return
# Check if URL is valid
parsed_url = urlparse(url)
if not all([parsed_url.scheme, parsed_url.netloc]):
error_message("Invalid URL.")
return
if not raw_payload.strip():
error_message("Payload cannot be empty.")
return
if not internet_check_url:
error_message("internet_check_url_var cannot be empty.")
return
if not check_every_second:
error_message("check_every_second cannot be empty.")
return
if not dialog_width:
error_message("dialog_width cannot be empty.")
return
if not dialog_height:
error_message("dialog_height cannot be empty.")
return
try:
parsed_headers = json.loads(raw_headers)
except json.JSONDecodeError:
error_message("Headers must be valid JSON.")
return
if len(raw_payload.splitlines()) == 1:
parsed_payload = raw_payload
else:
try:
parsed_payload = json.loads(raw_payload)
except json.JSONDecodeError:
error_message("Payload must be valid JSON.")
return
# Hide error message if any
error_message("")
new_profile = {
"name": name,
"url": url,
"internet_check_url": internet_check_url,
"payload": parsed_payload,
"headers": parsed_headers,
"check_every_second": int(check_every_second),
"dialog_geometry": {"width": int(dialog_width), "height": int(dialog_height)}
}
if not use_ethernet_var.get():
new_profile["ssid"] = ssid
profiles.append(new_profile)
config["profiles"] = profiles
with open("config.json", "w") as f:
json.dump(config, f, indent=2)
listbox.insert(tk.END, name)
add_window.destroy()
def cancel():
add_window.destroy()
add_window = tk.Toplevel(root)
add_window.title("Add New Profile")
container = tk.Frame(add_window, padx=10, pady=5)
container.pack(fill="both", expand=True)
wifi_ssids = scan_wifi_ssids()
connected_ssid = get_current_connected_ssid()
if not connected_ssid and wifi_ssids:
connected_ssid = wifi_ssids[0]
if not connected_ssid:
connected_ssid = "Enter SSID"
def generate_unique_name():
base_name = "New profile"
existing_names = [profile['name'].strip().lower() for profile in profiles]
if base_name.lower() not in existing_names:
return base_name
i = 2
while f"{base_name} {i}".lower() in existing_names:
i += 1
return f"{base_name} {i}"
name_var = tk.StringVar(value=generate_unique_name())
ssid_var = tk.StringVar(value=connected_ssid)
url_var = tk.StringVar()
internet_check_url_var = tk.StringVar(value="8.8.8.8")
check_every_second_var = tk.StringVar(value="600")
dialog_width_var = tk.StringVar(value="1024")
dialog_height_var = tk.StringVar(value="500")
use_ethernet_var = tk.BooleanVar(value=False)
# Name
name_frame = tk.Frame(container)
name_frame.pack(fill="x", pady=5)
tk.Label(name_frame, text="Name:").pack(side="left")
name_entry = tk.Entry(name_frame, textvariable=name_var)
name_entry.pack(side="left", fill="x", expand=True)
name_entry.bind("<Button-3>", show_context_menu)
# SSID row
ssid_frame = tk.Frame(container)
ssid_frame.pack(fill="x", pady=5)
tk.Label(ssid_frame, text="SSID:").pack(side="left")
ssid_combo = ttk.Combobox(ssid_frame, textvariable=ssid_var, values=wifi_ssids)
ssid_combo.pack(side="left", fill="x", expand=True)
ssid_combo.bind("<Button-3>", show_context_menu)
tk.Button(ssid_frame, text="Refresh", command=refresh_wifi_list).pack(side="left", padx=5)
ethernet_chk = tk.Checkbutton(ssid_frame, text="Ethernet", variable=use_ethernet_var, command=toggle_ethernet)
ethernet_chk.pack(side="left", padx=5)
# URL
url_frame = tk.Frame(container)
url_frame.pack(fill="x", pady=5)
tk.Label(url_frame, text="Request URL:").pack(side="left")
url_entry = tk.Entry(url_frame, textvariable=url_var)
url_entry.pack(side="left", fill="x", expand=True)
url_entry.bind("<Button-3>", show_context_menu)
# internet_check_url
internet_frame = tk.Frame(container)
internet_frame.pack(fill="x", pady=5)
tk.Label(internet_frame, text="internet_check_url:").pack(side="left")
internet_entry = tk.Entry(internet_frame, textvariable=internet_check_url_var)
internet_entry.pack(side="left", fill="x", expand=True)
internet_entry.bind("<Button-3>", show_context_menu)
# payload
tk.Label(container, text="payload:").pack(anchor="w")
payload_frame = tk.Frame(container)
payload_frame.pack(fill="both", pady=5, expand=True)
payload_text = tk.Text(payload_frame, height=8)
payload_text.pack(side="left", fill="both", expand=True)
payload_text.bind("<Button-3>", show_context_menu)
payload_scroll = tk.Scrollbar(payload_frame, command=payload_text.yview)
payload_scroll.pack(side="right", fill="y")
payload_text.config(yscrollcommand=payload_scroll.set)
# headers
tk.Label(container, text="headers:").pack(anchor="w")
headers_frame = tk.Frame(container)
headers_frame.pack(fill="both", pady=5, expand=True)
headers_text = tk.Text(headers_frame, height=8)
headers_text.pack(side="left", fill="both", expand=True)
headers_text.bind("<Button-3>", show_context_menu)
headers_scroll = tk.Scrollbar(headers_frame, command=headers_text.yview)
headers_scroll.pack(side="right", fill="y")
headers_text.config(yscrollcommand=headers_scroll.set)
headers_text.insert(tk.END, """{
"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/58.0.3029.110 Safari/537.3"
}""")
# check_every_second
check_frame = tk.Frame(container)
check_frame.pack(fill="x", pady=5)
tk.Label(check_frame, text="check_every_second:").pack(side="left")
check_entry = tk.Entry(check_frame, textvariable=check_every_second_var)
check_entry.pack(side="left", fill="x", expand=True)
check_entry.bind("<Button-3>", show_context_menu)
# dialog_geometry width and height
dialog_geometry_frame = tk.Frame(container)
dialog_geometry_frame.pack(fill="x", pady=5)
tk.Label(dialog_geometry_frame, text="dialog_geometry:").pack(side="left")
tk.Label(dialog_geometry_frame, text="width:").pack(side="left", padx=(0, 0))
dialog_width_entry = tk.Entry(dialog_geometry_frame, textvariable=dialog_width_var, width=5)
dialog_width_entry.pack(side="left")
dialog_width_entry.bind("<Button-3>", show_context_menu)
tk.Label(dialog_geometry_frame, text="height:").pack(side="left", padx=(5, 0))
dialog_height_entry = tk.Entry(dialog_geometry_frame, textvariable=dialog_height_var, width=5)
dialog_height_entry.pack(side="left")
dialog_height_entry.bind("<Button-3>", show_context_menu)
# Buttons
button_frame = tk.Frame(container)
button_frame.pack(fill="x", pady=5)
cancel_button = tk.Button(
button_frame,
text="Cancel",
command=cancel,
padx=20,
pady=5,
fg="white",
bg="grey",
activebackground="#606060",
activeforeground="white",
relief=tk.RAISED,
borderwidth=2,
)
cancel_button.pack(side=tk.LEFT, fill="x", padx=(0, 2), pady=(10, 0), expand=False)
save_button = tk.Button(
button_frame,
text="Add",
command=save_profile,
padx=5,
pady=5,
fg="white",
bg="#08872a",
activebackground="#076921",
activeforeground="white",
relief=tk.RAISED,
borderwidth=2,
)
save_button.pack(side=tk.LEFT, fill="x", padx=(2, 0), pady=(10, 0), expand=True)
# Error message
error_label = tk.Label(container, text="", bg="red", fg="white")
# Make the window resizable
add_window.columnconfigure(0, weight=1)
add_window.rowconfigure(0, weight=1)
container.columnconfigure(0, weight=1)
container.rowconfigure(0, weight=1)
# Configure resizing for frames and text widgets
name_frame.columnconfigure(1, weight=1)
ssid_frame.columnconfigure(1, weight=1)
url_frame.columnconfigure(1, weight=1)
internet_frame.columnconfigure(1, weight=1)
payload_frame.columnconfigure(0, weight=1)
headers_frame.columnconfigure(0, weight=1)
check_frame.columnconfigure(1, weight=1)
dialog_geometry_frame.columnconfigure(1, weight=1)
button_frame.columnconfigure(1, weight=1)
# Calculate and set the minimum height based on the current height of the items
add_window.update_idletasks()
min_height = add_window.winfo_height()
default_width = 400
add_window.geometry(f"{default_width}x{min_height}")
add_window.minsize(default_width, min_height)
# Center the add_window on the root window
root.update_idletasks()
x = root.winfo_x() + (root.winfo_width() // 2) - (default_width // 2)
y = root.winfo_y() + (root.winfo_height() // 2) - (min_height // 2)
add_window.geometry(f"+{x}+{y}")
def remove_selected_profile():
selected_index = listbox.curselection()
if not selected_index:
return
selected_index = selected_index[0]
selected_profile = profiles[selected_index]
if messagebox.askyesno("Confirm Delete", f"Are you sure you want to delete the profile '{selected_profile['name']}'?"):
profiles.pop(selected_index)
config["profiles"] = profiles
with open("config.json", "w") as f:
json.dump(config, f, indent=2)
listbox.delete(selected_index)
profile_details.config(state=tk.NORMAL)
profile_details.delete("1.0", tk.END)
profile_details.config(state=tk.DISABLED)
profile_name.config(text="Selected Profile: ")
# Add buttons under the listbox
button_frame = tk.Frame(profiles_frame)
button_frame.pack(side=tk.LEFT, pady=(0,5))
add_button = tk.Button(
button_frame,
text="Add new",
command=add_new_profile,
padx=5,
pady=0,
fg="white",
bg="#08872a",
activebackground="#076921",
activeforeground="white",
relief=tk.RAISED,
borderwidth=2,
)
add_button.pack(side=tk.LEFT, padx=(0,5))
remove_button = tk.Button(
button_frame,
text="Remove",
command=remove_selected_profile,
padx=5,
pady=0,
fg="white",
bg="grey",
activebackground="#606060",
activeforeground="white",
relief=tk.RAISED,
borderwidth=2,
)
remove_button.pack(side=tk.LEFT, padx=0)
for profile in profiles:
listbox.insert(tk.END, profile['name'])
listbox.bind('<Delete>', lambda event: remove_selected_profile())
# Create a vertical scrollbar for the listbox
scrollbar = tk.Scrollbar(profiles_frame, orient=tk.VERTICAL)
scrollbar = tk.Scrollbar(listbox_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
@@ -140,7 +513,6 @@ 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()
@@ -253,13 +625,29 @@ def send_request():
# 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', internet_check_url, '-n', '3', '-l', '32', '-w', '20'], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=subprocess.CREATE_NO_WINDOW)
return True
except subprocess.CalledProcessError:
internet_check_url_clean = internet_check_url.replace("http://", "").replace("https://", "")
socket.setdefaulttimeout(3)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if internet_check_url_clean.replace('.', '').isdigit():
address = internet_check_url_clean
else:
try:
address = socket.gethostbyname(internet_check_url_clean)
except socket.gaierror:
return False
if internet_check_url.startswith("https://"):
port = 443
elif internet_check_url.startswith("http://"):
port = 80
else:
port = 53
server_address = (address, port)
s.connect(server_address)
except OSError as error:
return False
finally:
s.close()
return True
# Function to get the currently connected SSID using system commands (for Windows)
def get_connected_network():
@@ -274,17 +662,20 @@ def get_connected_network():
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
try:
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 as e:
return "Error: " + str(e)
except subprocess.CalledProcessError:
return False
@@ -346,6 +737,11 @@ def show_log_dialog():
# 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)
# Define tags for different styles
log_text.tag_configure("green", foreground="green")
log_text.tag_configure("red", foreground="red")
log_text.tag_configure("bold_green", foreground="green", font=("Courier New", 10, "bold"))
log_text.tag_configure("bold_red", foreground="red", font=("Courier New", 10, "bold"))
update_log()
log_dialog.protocol("WM_DELETE_WINDOW", hide_log_dialog)
center_window(log_dialog, width, height)
@@ -380,19 +776,22 @@ successful_logins_count = 0
successful_logins_label = None
# Function to add a message to the log
def add_to_log(message):
def add_to_log(message, style=None):
global log_messages, successful_logins_count
now = datetime.now()
timestamp = now.strftime("%Y-%m-%d %H:%M:%S")
log_messages.append(f"({timestamp}) {message}")
log_messages.append((f"({timestamp}) {message}", style))
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")
for message, style in get_last_log_messages():
if style:
log_text.insert(tk.END, message + "\n", style)
else:
log_text.insert(tk.END, message + "\n")
update_successful_logins_count() # Update the successful logins count
# Function to update the successful logins count label
@@ -408,8 +807,8 @@ def save_to_file(message):
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:
# Open the file in append mode and write the formatted message with utf-8 encoding
with open("log.txt", "a", encoding="utf-8") as f:
f.write(formatted_message)
# Create the system tray icon
@@ -433,6 +832,13 @@ 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 isinstance(connected_ssid, str) and "error" in connected_ssid.lower():
sleepcount = 60
message = "{}\nFailed to get SSID. If location services are disabled, please enable them. Retrying in {} seconds...".format(connected_ssid, str(sleepcount))
add_to_log(message, "bold_red")
errorcount += 1
time.sleep(sleepcount)
continue
if (connected_ssid):
connected_ssid_lower = connected_ssid.lower()
if (connected_ssid) and ((connected_ssid_lower == expected_ssid_lower)):
@@ -449,13 +855,13 @@ def check_network_status():
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)
add_to_log(message, "bold_green")
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)
add_to_log(message, "red")
save_to_file(message)
else:
sleepcount = 5
@@ -473,7 +879,7 @@ def check_network_status():
request_errorcount = 0
successful_logins_count += 1
message = "Request was successful. Checking the internet connection in {} seconds...".format(str(sleepcount))
add_to_log(message)
add_to_log(message, "green")
save_to_file(message)
except requests.exceptions.RequestException as e:
errorcount += 1
@@ -491,10 +897,10 @@ def check_network_status():
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)
message = "Request failed with HTTP error ({}). \nTrying 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)
message = "Request failed with error: {}.\nIf you are using a VPN, please disable it for now. Trying to reconnect to the network... (Errors: {}/10)".format(e, errorcount)
add_to_log(message, "red")
save_to_file(message)
time.sleep(sleepcount)
# If the payload URL is not reachable, try to reconnect to the network
@@ -512,7 +918,7 @@ def check_network_status():
except Exception as e:
errorcount += 1
message = "Failed to reconnect to Ethernet: {} (Errors: {}/10)".format(e, errorcount)
add_to_log(message)
add_to_log(message, "red")
save_to_file(message)
else:
try:
@@ -525,12 +931,12 @@ def check_network_status():
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)
add_to_log(message ,"green")
time.sleep(8)
except Exception as e:
errorcount += 1
message = "Failed to reconnect to {}: {} (Errors: {}/10)".format(ssid, e, errorcount)
add_to_log(message)
add_to_log(message, "red")
save_to_file(message)
continue
else:
@@ -548,12 +954,12 @@ def check_network_status():
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)
add_to_log(message, "red")
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)
add_to_log(message, "red")
elif wifi_enabled:
if (connected_ssid):
sleepcount = 10
@@ -562,19 +968,25 @@ def check_network_status():
else:
sleepcount = 10
message = "You are not connected to {}. Trying to connect {}...".format(expected_ssid, expected_ssid)
add_to_log(message)
add_to_log(message, "red")
try:
result = subprocess.run(['netsh', 'wlan', 'connect', 'name=' + expected_ssid], capture_output=True, text=True, startupinfo=startupinfo)
result = subprocess.run(
['netsh', 'wlan', 'connect', 'name=' + expected_ssid],
capture_output=True,
text=True,
startupinfo=startupinfo,
creationflags=subprocess.CREATE_NO_WINDOW
)
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)
add_to_log(message ,"red")
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)
add_to_log(message, "green")
except (subprocess.CalledProcessError, ValueError) as e:
errorcount += 1
sleepcount = 15
@@ -582,23 +994,23 @@ def check_network_status():
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)
add_to_log(message, "red")
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)
add_to_log(message, "red")
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)
add_to_log(message, "red")
time.sleep(sleepcount) # Sleep ... seconds before trying again
message = "Maximum error count reached. Exiting in 5 seconds..."
add_to_log(message)
add_to_log(message, "bold_red")
save_to_file(message)
time.sleep(5)
running = False
+9 -9
View File
@@ -1,13 +1,13 @@
{
"profiles": [
{
"name": "NAME_OF_YOUR_PROFILE (WI-FI EXAMPLE)",
"ssid": "SSID_OF_YOUR_WIFI",
"url": "PAYLOAD_URL_HERE",
"name": "Example Wi-Fi",
"ssid": "EXAMPLE_WIFI_5G",
"url": "https://connect.schoolwifi.com/api/portal/dynamic/authenticate",
"internet_check_url": "8.8.8.8",
"payload": {
"username": "PLEASE WRITE YOUR OWN PAYLOAD VALUES HERE. THIS IS AN EXAMPLE",
"password": "PLEASE WRITE YOUR OWN PAYLOAD VALUES HERE. THIS IS AN EXAMPLE"
"username": "[email protected]",
"password": "123455678"
},
"headers": {
"Content-Type": "application/json;charset=UTF-8",
@@ -21,10 +21,10 @@
}
},
{
"name": "NAME_OF_YOUR_PROFILE (ETHERNET EXAMPLE)",
"url": "PAYLOAD_URL_HERE",
"name": "Example ETHERNET",
"url": "http://10.3.41.15:8002/index.php?zone=dormnet",
"payload": "&auth_user=85795013%40myschool.com&auth_pass=123455678&redirurl=&accept=Login",
"internet_check_url": "8.8.8.8",
"payload": "&auth_user=XXXX%40gmail.com&auth_pass=xxx&redirurl=&accept=Login",
"headers": {
"Content-Type": "application/x-www-form-urlencoded",
"Connection": "keep-alive",
@@ -37,4 +37,4 @@
}
}
]
}
}