Implemented control from tray
This commit is contained in:
parent
0791ad6191
commit
a3f1fc1dd2
|
@ -50,7 +50,7 @@ class Alcasar:
|
||||||
return ConnectionResults.CANT_DETECT_PORTAL
|
return ConnectionResults.CANT_DETECT_PORTAL
|
||||||
|
|
||||||
# We need a "challenge" value stored in a hidden input in the authentication
|
# We need a "challenge" value stored in a hidden input in the authentication
|
||||||
# page to be sent to in the post request
|
# page to be sent to it the post request
|
||||||
soup = BeautifulSoup(connection_page.text, features="html.parser")
|
soup = BeautifulSoup(connection_page.text, features="html.parser")
|
||||||
input_challenge = soup.find("input", {"name": "challenge"})
|
input_challenge = soup.find("input", {"name": "challenge"})
|
||||||
if input_challenge is None:
|
if input_challenge is None:
|
||||||
|
|
92
main.py
92
main.py
|
@ -1,12 +1,100 @@
|
||||||
|
import time
|
||||||
|
|
||||||
|
import settings_manager
|
||||||
from alcasar import Alcasar, ConnectionResults, DisconnectResult
|
from alcasar import Alcasar, ConnectionResults, DisconnectResult
|
||||||
|
from settings_manager import SettingsWindow
|
||||||
|
from tray_manager import TrayManager
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
|
||||||
|
class AlcasarMonitor:
|
||||||
|
def __init__(self):
|
||||||
|
self.alcasar = Alcasar()
|
||||||
|
self.tray_manager = TrayManager("AlcasarAuto", default_show=True, ImagePath=r".\assets\desactived_ico.png")
|
||||||
|
self.connect_button = self.tray_manager.Menu.create_item("Connect",
|
||||||
|
item_type=self.tray_manager.Menu.ItemType.BUTTON,
|
||||||
|
callback=self.connect)
|
||||||
|
self.disconnect_button = self.tray_manager.Menu.create_item("Disconnect",
|
||||||
|
item_type=self.tray_manager.Menu.ItemType.BUTTON,
|
||||||
|
callback=self.disconnect)
|
||||||
|
|
||||||
|
self.settings_button = self.tray_manager.Menu.create_item("Settings",
|
||||||
|
item_type=self.tray_manager.Menu.ItemType.BUTTON,
|
||||||
|
callback=self.ask_credentials)
|
||||||
|
self.auto_connect_check = self.tray_manager.Menu.create_item("Auto Connect",
|
||||||
|
item_type=self.tray_manager.Menu.ItemType.CHECK,
|
||||||
|
callback=self.toggle_auto_connect)
|
||||||
|
self.settings_window = settings_manager.SettingsWindow()
|
||||||
|
self.settings_manager = settings_manager.SettingsManager()
|
||||||
|
|
||||||
|
self.state = False
|
||||||
|
|
||||||
|
self.request_settings_open = False
|
||||||
|
self.just_disconnected = False
|
||||||
|
|
||||||
|
Thread(target=self.connection_state_loop).start()
|
||||||
|
self.loop()
|
||||||
|
|
||||||
|
def ask_credentials(self):
|
||||||
|
self.request_settings_open = True
|
||||||
|
|
||||||
|
def toggle_auto_connect(self):
|
||||||
|
new_value = self.tray_manager.Menu.get_status(self.auto_connect_check)
|
||||||
|
self.settings_manager.set("auto_connect", new_value)
|
||||||
|
|
||||||
|
def disconnect(self):
|
||||||
|
self.just_disconnected = True
|
||||||
|
self.alcasar.disconnect()
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
self.alcasar.connect(self.settings_manager.get("username"),
|
||||||
|
self.settings_manager.get("password"))
|
||||||
|
self.just_disconnected = False
|
||||||
|
|
||||||
|
def loop(self):
|
||||||
|
last_state = None
|
||||||
|
while True:
|
||||||
|
state = self.state
|
||||||
|
if state != last_state:
|
||||||
|
if state:
|
||||||
|
self.tray_manager.set_icon(r".\assets\actived_ico.png")
|
||||||
|
print("connected")
|
||||||
|
else:
|
||||||
|
self.tray_manager.set_icon(r".\assets\desactived_ico.png")
|
||||||
|
print("Disconnected")
|
||||||
|
if self.settings_manager.get("auto_connect") and not self.just_disconnected:
|
||||||
|
self.connect()
|
||||||
|
|
||||||
|
last_state = state
|
||||||
|
|
||||||
|
if self.request_settings_open:
|
||||||
|
self.__ask_credentials()
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
||||||
|
def __ask_credentials(self):
|
||||||
|
self.request_settings_open = False
|
||||||
|
print("ask credentials")
|
||||||
|
credentials = self.settings_window.get_credentials(self.settings_manager.get("username"), self.settings_manager.get("password"))
|
||||||
|
self.settings_manager.set("username", credentials[0])
|
||||||
|
self.settings_manager.set("password", credentials[1])
|
||||||
|
|
||||||
|
def connection_state_loop(self):
|
||||||
|
while True:
|
||||||
|
self.state = self.alcasar.update_statut()[0]
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
alcasar_monitor = AlcasarMonitor()
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
alcasar = Alcasar()
|
alcasar = Alcasar()
|
||||||
|
|
||||||
print("Checking if the computer is connected on an Alcasar WI-FI...")
|
print("Checking if the computer is connected on an Alcasar WI-FI...")
|
||||||
if alcasar.detect():
|
if alcasar.detect():
|
||||||
print("Alcasar Detected! Connecting...")
|
print("Alcasar Detected! Connecting...")
|
||||||
result = alcasar.connect("USERNAME", "PASSWORD")
|
result = alcasar.connect("BENDJEY", "Q8CSKR")
|
||||||
|
|
||||||
# Check result
|
# Check result
|
||||||
match result:
|
match result:
|
||||||
|
@ -24,4 +112,4 @@ if __name__ == '__main__':
|
||||||
input("disconnect ?")
|
input("disconnect ?")
|
||||||
alcasar.disconnect()
|
alcasar.disconnect()
|
||||||
else:
|
else:
|
||||||
print("Not detected")
|
print("Not detected")"""
|
||||||
|
|
|
@ -1,5 +1,50 @@
|
||||||
|
import os
|
||||||
|
import tkinter
|
||||||
from tkinter import ttk, Tk, Canvas, BOTH, Frame
|
from tkinter import ttk, Tk, Canvas, BOTH, Frame
|
||||||
import time
|
import time
|
||||||
|
import json
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
import _tkinter
|
||||||
|
|
||||||
|
SETTINGS_FOLDER = os.getenv('APPDATA')+"\\AlcasarAuto\\"
|
||||||
|
SETTINGS_FILE = SETTINGS_FOLDER + "settings.json"
|
||||||
|
|
||||||
|
|
||||||
|
class SettingsManager:
|
||||||
|
def __init__(self):
|
||||||
|
if not os.path.isdir(SETTINGS_FOLDER):
|
||||||
|
os.mkdir(SETTINGS_FOLDER)
|
||||||
|
|
||||||
|
self.settings = {}
|
||||||
|
|
||||||
|
if not os.path.isfile(SETTINGS_FILE):
|
||||||
|
self.setup_default_settings()
|
||||||
|
else:
|
||||||
|
self.load_settings()
|
||||||
|
|
||||||
|
def load_settings(self):
|
||||||
|
with open(SETTINGS_FILE, "r") as file:
|
||||||
|
self.settings = json.loads(file.read())
|
||||||
|
|
||||||
|
def get(self, key):
|
||||||
|
return self.settings[key]
|
||||||
|
|
||||||
|
def set(self, key, value):
|
||||||
|
self.settings[key] = value
|
||||||
|
self.save_settings()
|
||||||
|
|
||||||
|
def save_settings(self):
|
||||||
|
with open(SETTINGS_FILE, "w") as file:
|
||||||
|
file.write(json.dumps(self.settings))
|
||||||
|
|
||||||
|
def setup_default_settings(self):
|
||||||
|
self.settings = {
|
||||||
|
"username": "",
|
||||||
|
"password": "",
|
||||||
|
"auto_connect": False
|
||||||
|
}
|
||||||
|
self.save_settings()
|
||||||
|
|
||||||
|
|
||||||
class SettingsWindow(Tk):
|
class SettingsWindow(Tk):
|
||||||
|
@ -23,7 +68,6 @@ class SettingsWindow(Tk):
|
||||||
fieldbackground=self.field_bg_color, bordercolor=self.outline_color,
|
fieldbackground=self.field_bg_color, bordercolor=self.outline_color,
|
||||||
lightcolor=self.outline_color, darkcolor=self.outline_color)
|
lightcolor=self.outline_color, darkcolor=self.outline_color)
|
||||||
|
|
||||||
print()
|
|
||||||
self.theme.map("TButton",
|
self.theme.map("TButton",
|
||||||
background=[('!active', self.bg_color), ('active', self.active_field_bg_color)])
|
background=[('!active', self.bg_color), ('active', self.active_field_bg_color)])
|
||||||
|
|
||||||
|
@ -44,7 +88,16 @@ class SettingsWindow(Tk):
|
||||||
self.username_entry = ttk.Entry(self.credential_frame, style="TEntry")
|
self.username_entry = ttk.Entry(self.credential_frame, style="TEntry")
|
||||||
self.password_entry = ttk.Entry(self.credential_frame, show="●", style="TEntry")
|
self.password_entry = ttk.Entry(self.credential_frame, show="●", style="TEntry")
|
||||||
|
|
||||||
self.save_button = ttk.Button(self.base_canvas, text="Save", style="TButton")
|
self.save_button = ttk.Button(self.base_canvas, text="Save", style="TButton", command=self.close)
|
||||||
|
|
||||||
|
self.username = ""
|
||||||
|
self.password = ""
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.state = None
|
||||||
|
self.username = self.username_entry.get()
|
||||||
|
self.password = self.password_entry.get()
|
||||||
|
self.withdraw()
|
||||||
|
|
||||||
def round_rectangle(self, x1, y1, x2, y2, radius=25, **kwargs): # Creating a rounded rectangle
|
def round_rectangle(self, x1, y1, x2, y2, radius=25, **kwargs): # Creating a rounded rectangle
|
||||||
"""Draw a rounded rectangle
|
"""Draw a rounded rectangle
|
||||||
|
@ -57,7 +110,13 @@ class SettingsWindow(Tk):
|
||||||
x1, y1 + radius, x1, y1 + radius, x1, y1]
|
x1, y1 + radius, x1, y1 + radius, x1, y1]
|
||||||
|
|
||||||
return self.base_canvas.create_polygon(points, **kwargs, smooth=True, fill=self.bg_color)
|
return self.base_canvas.create_polygon(points, **kwargs, smooth=True, fill=self.bg_color)
|
||||||
|
|
||||||
|
def fill_credentials(self, username, password):
|
||||||
|
self.username_entry.delete(0, tkinter.END)
|
||||||
|
self.password_entry.delete(0, tkinter.END)
|
||||||
|
self.username_entry.insert(0, username)
|
||||||
|
self.password_entry.insert(0, password)
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
self.title_label.pack(expand=True)
|
self.title_label.pack(expand=True)
|
||||||
|
|
||||||
|
@ -73,15 +132,23 @@ class SettingsWindow(Tk):
|
||||||
|
|
||||||
def loop(self):
|
def loop(self):
|
||||||
self.state = "normal"
|
self.state = "normal"
|
||||||
|
self.update()
|
||||||
while self.state == "normal":
|
while self.state == "normal":
|
||||||
self.update()
|
self.update()
|
||||||
if self.focus_get() is None:
|
try:
|
||||||
self.quit()
|
if self.focus_get() is None:
|
||||||
|
self.close()
|
||||||
|
break
|
||||||
|
except _tkinter.TclError:
|
||||||
break
|
break
|
||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
|
|
||||||
|
def get_credentials(self, username, password):
|
||||||
|
"""Username and password used to prefill entries"""
|
||||||
|
self.fill_credentials(username, password)
|
||||||
|
self.deiconify()
|
||||||
|
self.focus_force()
|
||||||
|
self.setup()
|
||||||
|
self.loop()
|
||||||
|
return self.username, self.password
|
||||||
|
|
||||||
settings = SettingsWindow()
|
|
||||||
settings.setup()
|
|
||||||
|
|
||||||
settings.loop()
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from os.path import exists as __os_path_exists
|
from os.path import exists
|
||||||
from pystray import Icon as pystray_Icon, Menu as pystray_Menu, MenuItem as pystray_MenuItem
|
from pystray import Icon as pystray_Icon, Menu as pystray_Menu, MenuItem as pystray_MenuItem
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from threading import Thread as threading_Thread
|
from threading import Thread as threading_Thread
|
||||||
|
@ -9,7 +9,7 @@ from functools import partial
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Menu():
|
class Menu:
|
||||||
class Default(Enum):
|
class Default(Enum):
|
||||||
DEFAULT = "DefaultValue"
|
DEFAULT = "DefaultValue"
|
||||||
|
|
||||||
|
@ -29,8 +29,7 @@ class Menu():
|
||||||
self.id = 0
|
self.id = 0
|
||||||
self.ItemsFromID = {} # id: pystray.MenuItem, (DicKey, callback, item_type, {"current": bool | None, "requested": bool | None}, index)
|
self.ItemsFromID = {} # id: pystray.MenuItem, (DicKey, callback, item_type, {"current": bool | None, "requested": bool | None}, index)
|
||||||
self.IDsFromItem = {} # pystray.MenuItem: id
|
self.IDsFromItem = {} # pystray.MenuItem: id
|
||||||
|
self.tray = None
|
||||||
|
|
||||||
|
|
||||||
def create_item(self, text: str, callback: FunctionType | None = None, item_type: ItemType = ItemType.LABEL, checkdefault: bool = False, index: int | None = None, FORCE_ID: int | None = None):
|
def create_item(self, text: str, callback: FunctionType | None = None, item_type: ItemType = ItemType.LABEL, checkdefault: bool = False, index: int | None = None, FORCE_ID: int | None = None):
|
||||||
"""Create an item that will be displayed in the options of the app notification in the notification tray\n
|
"""Create an item that will be displayed in the options of the app notification in the notification tray\n
|
||||||
|
@ -355,6 +354,7 @@ class TrayManager():
|
||||||
#self.tray pystray.Icon() object
|
#self.tray pystray.Icon() object
|
||||||
|
|
||||||
self.Menu = Menu()
|
self.Menu = Menu()
|
||||||
|
self.Menu.tray = self
|
||||||
|
|
||||||
default_image = Image.new("L", (32, 32), 255)
|
default_image = Image.new("L", (32, 32), 255)
|
||||||
self.Icons = [default_image]
|
self.Icons = [default_image]
|
||||||
|
@ -363,7 +363,7 @@ class TrayManager():
|
||||||
|
|
||||||
#Set the icon of the app in the notification tray
|
#Set the icon of the app in the notification tray
|
||||||
if ImagePath:
|
if ImagePath:
|
||||||
if __os_path_exists(ImagePath):
|
if exists(ImagePath):
|
||||||
#Open image as PIL.Image.Image object and add it to Icons list
|
#Open image as PIL.Image.Image object and add it to Icons list
|
||||||
image = Image.open(ImagePath)
|
image = Image.open(ImagePath)
|
||||||
self.Icons.append(image)
|
self.Icons.append(image)
|
||||||
|
@ -412,7 +412,7 @@ class TrayManager():
|
||||||
|
|
||||||
#Check if IconPath exist
|
#Check if IconPath exist
|
||||||
if ImagePath:
|
if ImagePath:
|
||||||
if __os_path_exists(ImagePath):
|
if exists(ImagePath):
|
||||||
#Open image as PIL.Image.Image object and add it to Icons list
|
#Open image as PIL.Image.Image object and add it to Icons list
|
||||||
|
|
||||||
image = Image.open(ImagePath)
|
image = Image.open(ImagePath)
|
||||||
|
|
Loading…
Reference in a new issue