205 lines
8.4 KiB
Python
205 lines
8.4 KiB
Python
import tkinter as tk
|
|
from tkinter import ttk
|
|
from selenium import webdriver
|
|
from selenium.webdriver.common.by import By
|
|
from time import sleep
|
|
|
|
|
|
class App(tk.Tk):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.inventory = [[None for i in range(7)] for j in range(15)]
|
|
self.path = '/html/body/blockquote/table/tbody/tr[{}]/td[{}]/input'
|
|
self.selected = []
|
|
self.username = ''
|
|
self.password = ''
|
|
self.num = 0
|
|
self.week = 0
|
|
self.geometry("800x900")
|
|
self.title(
|
|
'Automatic laundry reservation for Lahden Talot student residents')
|
|
self.resizable(0, 0)
|
|
self.browser = None
|
|
|
|
# status bar
|
|
status = tk.Text(self, height=1, width=50)
|
|
status.grid(column=0, row=21,
|
|
padx=5, pady=5, columnspan=8)
|
|
status.tag_configure("center", justify='center')
|
|
status.insert(tk.END, "READY")
|
|
status.tag_add("center", 1.0, "end")
|
|
|
|
def change_status(message):
|
|
status.delete(1.0, tk.END)
|
|
status.insert(tk.END, message)
|
|
status.tag_add("center", 1.0, "end")
|
|
|
|
def next_week(week):
|
|
if week == 0:
|
|
pass
|
|
else:
|
|
for j in range(week):
|
|
self.browser.find_element(
|
|
By.XPATH, '/html/body/blockquote/table/tbody/tr[1]/td[7]/input').click()
|
|
|
|
# blank 3rd row
|
|
for i in range(7):
|
|
ttk.Label(self, text=" ").grid(
|
|
column=i+1, row=3, padx=45, pady=10)
|
|
|
|
# username
|
|
username_label = ttk.Label(self, text="Username:")
|
|
username_label.grid(column=0, row=1, sticky=tk.W, padx=5, pady=5)
|
|
username_entry = ttk.Entry(self)
|
|
username_entry.grid(column=1, row=1, sticky=tk.W,
|
|
padx=5, pady=5, columnspan=3)
|
|
|
|
# password
|
|
password_label = ttk.Label(self, text="Password:")
|
|
password_label.grid(column=0, row=2, sticky=tk.W, padx=5, pady=5)
|
|
password_entry = ttk.Entry(self, show="*")
|
|
password_entry.grid(column=1, row=2, sticky=tk.W,
|
|
padx=5, pady=5, columnspan=3)
|
|
|
|
# labels
|
|
user = ttk.Label(self, text="Username and Password will NOT be saved")
|
|
user.grid(column=0, row=0, sticky=tk.W, padx=5, pady=5, columnspan=5)
|
|
days = ['Monday', 'Tuesday', 'Wednesday',
|
|
'Thursday', 'Friday', 'Saturday', 'Sunday']
|
|
for i, day in enumerate(days):
|
|
ttk.Label(self, text=day).grid(
|
|
column=i+1, row=4, padx=5, pady=5)
|
|
hours = ['7:00 - 8:00', '8:00 - 9:00', '9:00 - 10:00', '10:00 - 11:00', '11:00 - 12:00', '12:00 - 13:00', '13:00 - 14:00',
|
|
'14:00 - 15:00', '15:00 - 16:00', '16:00 - 17:00', '17:00 - 18:00', '18:00 - 19:00', '19:00 - 20:00', '20:00 - 21:00', '21:00 - 22:00']
|
|
for i, hour in enumerate(hours):
|
|
ttk.Label(self, text=hour).grid(
|
|
column=0, row=i+5, padx=5, pady=5)
|
|
num_weeks = ttk.Label(self, text="Number of weeks to book:")
|
|
num_weeks.grid(column=4, row=1, sticky=tk.W,
|
|
padx=5, pady=5, columnspan=2)
|
|
num_entry = ttk.Entry(self, width=5)
|
|
num_entry.grid(column=6, row=1, sticky=tk.W,
|
|
padx=5, pady=5)
|
|
|
|
# each time slot has a button
|
|
|
|
def book(i, j):
|
|
if self.inventory[i][j]['text'] == 'Free':
|
|
self.inventory[i][j]['text'] = 'Added'
|
|
self.inventory[i][j]['bg'] = 'red'
|
|
self.selected.append((i, j))
|
|
else:
|
|
self.inventory[i][j]['text'] = 'Free'
|
|
self.inventory[i][j]['bg'] = 'green'
|
|
self.selected.remove((i, j))
|
|
for i in range(15):
|
|
for j in range(7):
|
|
self.inventory[i][j] = tk.Button(
|
|
self, text="Free", bg='green', command=lambda i=i, j=j: book(i, j))
|
|
self.inventory[i][j].grid(column=j+1, row=i+5, padx=5, pady=5)
|
|
|
|
# reset button
|
|
|
|
def reset():
|
|
for i in range(15):
|
|
for j in range(7):
|
|
self.inventory[i][j]['text'] = 'Free'
|
|
self.inventory[i][j]['bg'] = 'green'
|
|
self.inventory[i][j]['state'] = 'normal'
|
|
self.selected = []
|
|
self.username = ''
|
|
self.password = ''
|
|
self.num = 0
|
|
self.week = 0
|
|
username_entry.delete(0, 'end')
|
|
password_entry.delete(0, 'end')
|
|
num_entry.delete(0, 'end')
|
|
change_status("READY")
|
|
confirm['text'] = 'Confirm'
|
|
confirm['state'] = 'disabled'
|
|
start_button['state'] = 'normal'
|
|
reset_button = tk.Button(
|
|
self, text="RESET", command=reset, bg='red')
|
|
reset_button.grid(column=4, row=2, sticky=tk.W, padx=5, pady=5)
|
|
|
|
def start():
|
|
self.username = username_entry.get()
|
|
self.password = password_entry.get()
|
|
try:
|
|
self.num = int(num_entry.get())
|
|
except ValueError:
|
|
change_status("Please enter a valid number!")
|
|
return
|
|
if self.username == '' or self.password == '' or self.num == 0:
|
|
change_status("Please fill in all the fields!")
|
|
elif len(self.selected) == 0:
|
|
change_status("Please select at least one time slot!")
|
|
else:
|
|
confirm['state'] = 'normal'
|
|
change_status("Please confirm your booking!")
|
|
start_button = tk.Button(
|
|
self, text="START", command=start, bg='blue')
|
|
start_button.grid(column=5, row=2, sticky=tk.W, padx=5, pady=5)
|
|
|
|
def execute():
|
|
self.browser = webdriver.Chrome()
|
|
confirm['state'] = 'disabled'
|
|
for i in range(15):
|
|
for j in range(7):
|
|
self.inventory[i][j]['state'] = 'disabled'
|
|
start_button['state'] = 'disabled'
|
|
confirm['text'] = 'Working...'
|
|
change_status("Logging in...")
|
|
try:
|
|
self.browser.get("http://extranet.oppilastalo.fi/")
|
|
except Exception:
|
|
change_status("Connection error.")
|
|
confirm['text'] = "Error"
|
|
return
|
|
self.browser.find_element(By.XPATH,
|
|
'/html/body/div/form/table/tbody/tr[3]/td[2]/input').send_keys(self.username)
|
|
self.browser.find_element(By.XPATH,
|
|
'/html/body/div/form/table/tbody/tr[4]/td[2]/input').send_keys(self.password)
|
|
self.browser.find_element(By.XPATH,
|
|
'/html/body/div/form/table/tbody/tr[5]/td[1]/input').click()
|
|
try:
|
|
self.browser.find_element(By.XPATH, '/html/body/center/div[1]')
|
|
except Exception:
|
|
pass
|
|
else:
|
|
change_status("Wrong username or password.")
|
|
confirm['text'] = "Error"
|
|
return
|
|
change_status("Logged in.")
|
|
self.browser.find_element(By.XPATH,
|
|
'/html/body/code/a[4]').click()
|
|
while self.week < self.num:
|
|
for i in range(len(self.selected)):
|
|
change_status("Booking a slot...")
|
|
try:
|
|
self.browser.find_element(By.XPATH, self.path.format(
|
|
self.selected[i][0]+3, self.selected[i][1]+2)).click()
|
|
self.browser.find_element(By.XPATH,
|
|
'/html/body/blockquote/submenu/blockquote/input[1]').click()
|
|
change_status("Booking successful.")
|
|
self.browser.find_element(By.XPATH,
|
|
'/html/body/code/a[4]').click()
|
|
next_week(self.week)
|
|
except Exception:
|
|
change_status("Booking failed.")
|
|
continue
|
|
self.week += 1
|
|
next_week(1)
|
|
self.browser.close()
|
|
|
|
# confirm button
|
|
confirm = tk.Button(self, text="Confirm", bg="yellow", command=execute)
|
|
confirm['state'] = 'disabled'
|
|
confirm.grid(column=0, row=22,
|
|
padx=5, pady=5, columnspan=8)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app = App()
|
|
app.mainloop()
|