tags: 淡江大學搶課機器人開源專案

開源專案

前言:

淡江大學選課系統對於要搶課其實是非常非常容易的,因為學校每一個按鈕都有一個id,這幾乎就是最簡單的一種爬蟲方式,但是終究不是人人都會網路爬蟲或是寫程式,所以這套機器人就誕生了!

也不瞞大家,我確實用這套機器人搶了非常多的熱門課,今年也要升大四了,學分已經修得差不多了,機器人對我來說其實意義不大,所以今天開源出來讓學弟妹可以用

以下進入正文

適用環境:

  • Mac intel 處理器:macOS 10.15以上都可以使用
  • Mac Apple Silicon 處理器:macOS 13.2.1以上都可以使用
  • Windows 系統:Windows 10以上都可以使用

使用方式:

1. 先進資料夾下載執行檔案

下載位置

Windows平台請下載Public_WYSHBot_Windows
MacOS Intel處理器的請下載Public_WYSHBot_Mac(intel)
MacOS M1/M2系列處理器請下載Public_WYSHBot_MacOS(Silicon)

2. 開始執行搶課機器人

  • Windows直接點擊start.bat

    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

  • Mac系列直接下載後解壓縮直接放到應用程式資料夾中,點兩下執行

    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

  • 若Mac無法成功執行請參考備註1

3. 設定基本資料(Windows/Mac使用方式相同)

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • 先設定登入資訊(務必按下儲存登入資訊)
  • 勘誤:學號跟密碼可以任意次數更換,文字寫錯請忽略
  • 設定加退選資訊
  • 設定完加退選資訊務必按下儲存加退選清單

4. 執行搶課程式(Windows/Mac使用方式相同)

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • 按下執行搶課主程式

5. 設定搶課程式(Windows/Mac使用方式相同)

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

  • 先設定語言
  • 再設定是要立即搶課或是預約搶課
  • 完成後,執行開始搶課

6. 剩下交給上蒼

補充說明:機器人會延遲5秒鐘的原因是學校系統跟實際時間會有一些落差,會慢個幾秒,所以5秒最為保險

Demo影片:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

https://youtu.be/Fmsm59aK-LA
備註,影片中搶課主程式是分開成兩個程式,但介面一樣

備註1(開啟任何來源):

  • 請開啟任終端機:

    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

  • 在終端機中打入以下指令:

    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

    sudo spctl master-disable

  • 打入密碼(請注意這個密碼不會顯示):

    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

  • 打開設定中的隱私權與安全性:

    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

進階功能

本機器人有Premium版本,提供以下功能:

  • 完整的搶課速度
  • 極速刷課模式
  • 單一裝置登入功能
  • 帳號密碼加密,強化安全性
    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

若有需要,可以點擊以下連結:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

https://line.me/ti/g2/EQSB4VBKjoVXM0n46GDIrmdTwieWd1LIrtYpJg?utm_source=invitation&utm_medium=link_copy&utm_campaign=default

原始碼開源

以下為原始碼,可以直接下載原始檔案使用
打包:https://1drv.ms/u/s!AvwcoqTkdjpWg6gzfZLSICm9UajhOg?e=2ObdmQ

setting.py
import os
import platform
import subprocess
import tkinter as tk
from tkinter import messagebox
from tkinter import ttk
from tkinter.constants import *

import cryptocode

global ScrollBar
global window
window = tk.Tk()
global AddToList_Action
AddToList_Action = []
global AddToList_OpenCourse
AddToList_OpenCourse = []
global ExchangeFirst
ExchangeFirst = 0
global ExchangeSecond
ExchangeSecond = 0
global RemoveItem
RemoveItem = 0
working_dir = os.path.dirname(os.path.realpath(__file__))
global Login_Path
Login_Path = working_dir+"/#2_main/ProgramPlugin_1.info"
global Selective_Path
Selective_Path = working_dir+"/#2_main/ProgramPlugin_2.info"
Record = 0
def LoadTheLoginInformation():
    global Record,Login_Path
    try:
        with open(Login_Path, 'r') as f:
            global Login
            Login = f.read().splitlines()
            for i in range(len(Login)):
                if (i+1)==1 or (i+1)==3:
                    pass
                elif (i+1)==2:
                    global Account_Login_Record
                    Account_Login_Record = str(Login[i])
                    Account_textbox.insert(0, Account_Login_Record)
                    #Account_textbox.config(state='disable')
                    Record = 1
                else:
                    global Password_Login_Record
                    Password_Login_Record = str(Login[i])
                    Password_textbox.insert(0, Password_Login_Record)
    except FileNotFoundError:
        Record = 0
        messagebox.showinfo("提示","偵測到程式遭修改\n請聯絡負責人")
        os._exit()
    return
def LoginSavingInformation():
    global Record
    global Account
    Account = Account_textbox.get()
    #print(Account)
    Password = Password_textbox.get()
    #print(Password)
    global Login_Path
    try:
        if(Account!="" and Password!= ""):
            with open(Login_Path, 'w') as f:
                f.write('Account')
                f.write('\n')
                f.write(Account)
                f.write('\n')
                f.write('Password')
                f.write('\n')
                f.write(Password)
                Record = 1
        else:
            messagebox.showinfo("提示", "輸入錯誤請重試")

    except:
        messagebox.showinfo("提示", "我們偵測到了你嘗試修改程式\n請聯絡負責人")
        os._exit()

def SelectiveSaving():
    global Selective_Path
    try:
        if (Selective_Path):
            with open(Selective_Path, 'w') as f:
                f.write('')
            for i in range(len(AddToList_Action)):
                with open(Selective_Path, 'a') as f:
                    f.write(AddToList_Action[i])
                    f.write('\n')
                    f.write(AddToList_OpenCourse[i])
                    f.write('\n')
            messagebox.showinfo("提示","選課清單儲存成功")
        else:
            messagebox.showinfo("提示","儲存路徑錯誤請重試")
    except:
        messagebox.showinfo("提示", "我們偵測到了您嘗試修改過程式\n請聯絡搶課負責人")
    return
def LoadSelectivedList():
    global Selective_Path
    try:
        with open(Selective_Path, 'r') as f:
            global Selection
            Selection = f.read().splitlines()
            for i in range(len(Selection)):
                if (i+1)%2==1:
                    AddToList_Action.append(str(Selection[i]))
                elif (i+1)%2==0:
                    AddToList_OpenCourse.append(str(Selection[i]))
    except FileNotFoundError:
        pass
    return
def LoginInformatioSavingConfirmBox():
    global Record
    Account = Account_textbox.get()
    Password = Password_textbox.get()
    if (Record==1 and Account !="" and Password !=""):
        LoginSavingInformation()
        messagebox.showinfo("提示", "密碼更新成功")
    elif Account =="" or Password =="":
        messagebox.showinfo("提示", "學號或密碼不能留空")
    elif (Record==0 and Account !="" and Password !=""):
        MsgBox = tk.messagebox.askquestion("提示","請問你確定儲存學號密碼嗎?\n學號只能綁定一次喔!\n學號未來是不能修改\n\nP.S.密碼可以修改")
        if MsgBox =="yes":
            LoginSavingInformation()
            messagebox.showinfo("提示", "學號密碼設定成功")
        else:
            pass
def build_GUI():
    #Build A GUI Window
    window.title("選課設定")
    window.geometry('380x510')
    window.resizable(False, True)

    #LoginTitle
    LoginTitle = tk.Label(window,width=30,text="登入資訊",font=("normal",15),compound="center")
    LoginTitle.place(x=190,y=20,anchor=CENTER)
    AccountInformation()
    PasswordInformation()

    #Button
    #LoginSaving Button
    Save_Button = tk.Button(text="儲存登入資訊",command=LoginInformatioSavingConfirmBox)
    Save_Button.place(x=190, y=115, anchor=CENTER)
    LoadTheLoginInformation()

    #SelectiveSaving_Button
    #SelectiveTitle
    SelectiveTitle = tk.Label(width=30,text="加退選資訊",font=("normal",15),compound="center")
    SelectiveTitle.place(x=190, y=165, anchor=CENTER)
    LoadSelectivedList()
    showList()
    Options()
    window.mainloop()

#Login Information
def AccountInformation():
    #Account
    Label_Account_textbox = tk.Label(width=6,text="學號",compound="center")
    Label_Account_textbox.place(x=60,y=40)
    global Account_textbox
    Account_textbox = tk.Entry(window)
    Account_textbox.pack()
    Account_textbox.place(x=120,y=40)
def PasswordInformation():
    # Password
    Label_Password_textbox = tk.Label(width=6, text="密碼", compound="center")
    Label_Password_textbox.place(x=60,y=70)
    global Password_textbox
    Password_textbox = tk.Entry(window)
    Password_textbox.pack()
    Password_textbox.place(x=120,y=70)

#Action
def Drop():
    Remove_Target = int(Revise_Remove_Box.get()) - 1
    if (Remove_Target<len(AddToList_Action) and Remove_Target>=0):
        initial()
        AddToList_Action.pop(Remove_Target)
        AddToList_OpenCourse.pop(Remove_Target)
        #Clear TextBox
        Revise_Remove_Box.delete(0, END)
        showList()
        #messagebox.showinfo("提示", "刪除成功")
    else:
        messagebox.showinfo("提示", "輸入錯誤,請重試")
    return
def Exchange():
    FirstIndex = int(Revise_ExchangeFirst_Box.get()) - 1
    SecondIndex = int(Revise_ExchangeSecond_Box.get()) - 1
    if (FirstIndex < len(AddToList_Action) and FirstIndex >= 0 and SecondIndex < len(AddToList_Action) and SecondIndex >= 0 and SecondIndex!= FirstIndex):
        AddToList_Action[FirstIndex], AddToList_Action[SecondIndex] = AddToList_Action[SecondIndex], AddToList_Action[FirstIndex]
        AddToList_OpenCourse[FirstIndex], AddToList_OpenCourse[SecondIndex] = AddToList_OpenCourse[SecondIndex], AddToList_OpenCourse[FirstIndex]
        # Clear TextBox
        Revise_ExchangeFirst_Box.delete(0, END)
        Revise_ExchangeSecond_Box.delete(0, END)
        showList()
        messagebox.showinfo("提示", "交換成功")
    else:
        messagebox.showinfo("提示", "輸入錯誤,請重試")
    return
def initial():
    y_axis = 270
    for i in range(len(AddToList_Action)):
        y_axis = y_axis + 30
        temp = tk.Label(window,width=2,height=3,text="",font=("normal",10),compound="center")
        temp.pack()
        temp.place(x=55,y=y_axis,anchor=CENTER)

        temp_1 = tk.Label(window,width=7,height=3,text="",font=("normal",10),compound="center")
        temp_1.pack()
        temp_1.place(x=100,y=y_axis,anchor=CENTER)

        temp_2 = tk.Label(window, width=7,height=3,text="", font=("normal",10),compound="center")
        temp_2.pack()
        temp_2.place(x=170, y=y_axis,anchor=CENTER)

#Selective Information
def Options():
    # Options
    global Optional_Selective
    Optional_Selective = ttk.Combobox(window,state="readonly", width=5, values=["加選", "退選"])
    Optional_Selective.pack()
    Optional_Selective.place(x=100, y=195, anchor=CENTER)
    Optional_Selective.current(0)

    #OpenCourseBox
    global OpenCourseBox
    OpenCourseBox = tk.Entry(window,width=15)
    OpenCourseBox.pack()
    OpenCourseBox.place(x=220,y=195,anchor=CENTER)

    #AddButton
    AddButton = tk.Button(text="加入清單",command=AddToList)
    AddButton.place(x=190, y=225, anchor=CENTER)

    #================================================================================================================
    #List
    Number_Column = tk.Label(window,width=2,height=3,text="#",font=("normal",10),compound="center")
    Number_Column.pack()
    Number_Column.place(x=55,y=270,anchor=CENTER)

    Action_Column = tk.Label(window,width=7,height=3,text="操作",font=("normal",10),compound="center")
    Action_Column.pack()
    Action_Column.place(x=100,y=270,anchor=CENTER)

    CourseCode_Column = tk.Label(window, width=7,height=3, font=("normal",10), text="開課代碼",compound="center")
    CourseCode_Column.pack()
    CourseCode_Column.place(x=170, y=270,anchor=CENTER)

    #================================================================================================================
    #ReviseArea
    #ReviseTitle
    Revise_Column = tk.Label(window, width=20, height=3, font=("normal", 10), text="調整", compound="center")
    Revise_Column.pack()
    Revise_Column.place(x=300, y=270, anchor=CENTER)

    #ReviseFirst_#
    Revise_ExchangeFirst = tk.Label(window, width=2, height=1, font=("normal", 10), text="#", compound="center")
    Revise_ExchangeFirst.pack()
    Revise_ExchangeFirst.place(x=225, y=300, anchor=CENTER)

    #ReviseFirst_TextBox
    global Revise_ExchangeFirst_Box
    Revise_ExchangeFirst_Box = tk.Entry(window, width=3)
    Revise_ExchangeFirst_Box.pack()
    Revise_ExchangeFirst_Box.place(x=245, y=300, anchor=CENTER)

    #ReviseSecond_#
    Revise_ExchangeSecond = tk.Label(window, width=2, height=1, font=("normal", 10), text="#", compound="center")
    Revise_ExchangeSecond.pack()
    Revise_ExchangeSecond.place(x=270, y=300, anchor=CENTER)

    #ReviseSecond_TextBox
    global Revise_ExchangeSecond_Box
    Revise_ExchangeSecond_Box = tk.Entry(window, width=3)
    Revise_ExchangeSecond_Box.pack()
    Revise_ExchangeSecond_Box.place(x=290, y=300, anchor=CENTER)

    #ExchangeButton
    ExchangeButton = tk.Button(text="交換", command=Exchange)
    ExchangeButton.place(x=340, y=300, anchor=CENTER)

    #Remove_#
    Revise_Remove = tk.Label(window, width=2, height=1, font=("normal", 10), text="#", compound="center")
    Revise_Remove.pack()
    Revise_Remove.place(x=250, y=330, anchor=CENTER)

    #Remove_TextBox
    global Revise_Remove_Box
    Revise_Remove_Box = tk.Entry(window, width=3)
    Revise_Remove_Box.pack()
    Revise_Remove_Box.place(x=275, y=330, anchor=CENTER)

    #Remove_Button
    Remove_Button = tk.Button(text=U"刪除", command=Drop)
    Remove_Button.place(x=330, y=330, anchor=CENTER)

    #================================================================================================================
    #Saving Area
    #SavingTitle
    Saving_Column = tk.Label(window, width=20, height=2, font=("normal", 10), text=U"儲存", compound="center")
    Saving_Column.pack()
    Saving_Column.place(x=300, y=370, anchor=CENTER)

    #SavingButton
    SavingButton = tk.Button(text=U"儲存加退選清單", command=SelectiveSaving)
    SavingButton.place(x=300, y=390, anchor=CENTER)

    # ================================================================================================================
    # Execution Area
    # ExecutionTitle
    Execution_Column = tk.Label(window, width=20, height=2, font=("normal", 10), text=U"搶課", compound="center")
    Execution_Column.pack()
    Execution_Column.place(x=300, y=420, anchor=CENTER)

    # ExecutionButton
    ExecutionButton = tk.Button(text=U"執行搶課主程式", command=ExecutionMainFunction)
    ExecutionButton.place(x=300, y=440, anchor=CENTER)

def AddToList():
    if  Optional_Selective.get() == "加選" and OpenCourseBox.get() !="":
        AddToList_Action.append("Add")
        AddToList_OpenCourse.append(OpenCourseBox.get())
        OpenCourseBox.delete(0, END)
        showList()
    elif Optional_Selective.get() == "退選" and OpenCourseBox.get() !="":
        AddToList_Action.append("Remove")
        AddToList_OpenCourse.append(OpenCourseBox.get())
        OpenCourseBox.delete(0, END)
        showList()
    else:
        messagebox.showinfo("提示","開課代碼不能為空白")

def showList():
    y_axis = 270
    for i in range(len(AddToList_Action)):
        y_axis = y_axis + 30
        temp = tk.Label(window,width=2,height=3,text=i+1,font=("normal",10),compound="center")
        temp.pack()
        temp.place(x=55,y=y_axis,anchor=CENTER)

        temp_1 = tk.Label(window,width=7,height=3,text=AddToList_Action[i],font=("normal",10),compound="center")
        temp_1.pack()
        temp_1.place(x=100,y=y_axis,anchor=CENTER)

        temp_2 = tk.Label(window, width=7,height=3,text=AddToList_OpenCourse[i], font=("normal",10),compound="center")
        temp_2.pack()
        temp_2.place(x=170, y=y_axis,anchor=CENTER)

    #print(y_axis)
    if (y_axis>=480):
        wide = 380
        height = str(510+(len(AddToList_Action)-7)*30)
        mix = str(wide)+"x"+height
        window.geometry(mix)
    return

def ExecutionMainFunction():
    global working_dir
    subprocess.Popen(['python3', 'main.py'], cwd=working_dir + "/#2_main")  # OpenSource

#main function
if __name__ == '__main__':
    build_GUI()
main.py
import os
import datetime
import os
import ssl
import time
import tkinter as tk
from tkinter import messagebox
from tkinter import ttk
from tkinter.constants import *

import cryptocode
import undetected_chromedriver as uc

ssl._create_default_https_context = ssl._create_unverified_context
driver = uc.Chrome()

URL_Chinese = "https://www.ais.tku.edu.tw/EleCos/login.aspx?ReturnUrl=%2felecos%2f"
URL_English = "https://www.ais.tku.edu.tw/EleCos_English/loginE.aspx"

global ChineseScript
ChineseScript = "javascript: (function(){ var numHash={b6589fc6ab0dc82cf12099d1c2d40ab994e8410c:\"0\",\"356a192b7913b04c54574d18c28d46e6395428ab\":\"1\",da4b9237bacccdf19c0760cab7aec4a8359010b0:\"2\",\"77de68daecd823babbb58edb1c8e14d7106e83bb\":\"3\",\"1b6453892473a467d07372d45eb05abc2031647a\":\"4\",ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4:\"5\",c1dfd96eea8cc2b62785275bca38ac261256e278:\"6\",\"902ba3cda1883801594b6e1b452790cc53948fda\":\"7\",fe5dbbcea5ce7e2988b8c69bcfdfde8904aabc1f:\"8\",\"0ade7c2cf97f75d009975f4d720d1fa6c19f4897\":\"9\"};$.ajax({url:\"https://www.ais.tku.edu.tw/EleCos/Handler1.ashx\",type:\"post\",async:false,success:function(voice){document.getElementById(\"txtCONFM\").value=numHash[voice[0]]+numHash[voice[1]]+numHash[voice[2]]+numHash[voice[3]]+numHash[voice[4]]+numHash[voice[5]];}}); })();"
global EnglishScript
EnglishScript = "javascript: (function(){ var numHash={b6589fc6ab0dc82cf12099d1c2d40ab994e8410c:\"0\",\"356a192b7913b04c54574d18c28d46e6395428ab\":\"1\",da4b9237bacccdf19c0760cab7aec4a8359010b0:\"2\",\"77de68daecd823babbb58edb1c8e14d7106e83bb\":\"3\",\"1b6453892473a467d07372d45eb05abc2031647a\":\"4\",ac3478d69a3c81fa62e60f5c3696165a4e5e6ac4:\"5\",c1dfd96eea8cc2b62785275bca38ac261256e278:\"6\",\"902ba3cda1883801594b6e1b452790cc53948fda\":\"7\",fe5dbbcea5ce7e2988b8c69bcfdfde8904aabc1f:\"8\",\"0ade7c2cf97f75d009975f4d720d1fa6c19f4897\":\"9\"};$.ajax({url:\"https://www.ais.tku.edu.tw/EleCos_English/Handler1.ashx\",type:\"post\",async:false,success:function(voice){document.getElementById(\"txtCONFM\").value=numHash[voice[0]]+numHash[voice[1]]+numHash[voice[2]]+numHash[voice[3]]+numHash[voice[4]]+numHash[voice[5]];}}); })();"
global window
window = tk.Tk()

global AddToList_Action
AddToList_Action = []
global AddToList_OpenCourse
AddToList_OpenCourse = []
global CycleList
CycleList = []
Account_Login_Record = 0
Password_Login_Record = 0
working_dir = os.path.dirname(os.path.realpath(__file__))
global Login_Path
Login_Path = working_dir+"/ProgramPlugin_1.info"
global Selective_Path
Selective_Path = working_dir+"/ProgramPlugin_2.info"

def LoadTheLoginInformation():
    global Login_Path
    try:
        with open(Login_Path, 'r') as f:
            global Login
            Login = f.read().splitlines()
            for i in range(len(Login)):
                if (i+1)==1 or (i+1)==3:
                    pass
                elif (i+1)==2:
                    global Account_Login_Record
                    Account_Login_Record = str(Login[i])
                else:
                    global Password_Login_Record
                    Password_Login_Record = str(Login[i])
                    #print("Password: "+Password_Login_Record)
    except FileNotFoundError:
        messagebox.showinfo("提示", "無法載入登入資訊"+"\n"+"請先執行setting設定加退選資訊")
    if len(Login)==0:
        messagebox.showinfo("提示","沒有登入資訊"+"\n"+"請先執行setting設定登入資訊")
    return
def LoadTheSelectionInformation():
    global Selective_Path
    try:
        with open(Selective_Path, 'r') as f:
            global Selection
            Selection = f.read().splitlines()
            for i in range(len(Selection)):
                if (i+1)%2==1:
                    if str(Selection[i]) =="Add" or str(Selection[i]) =="Remove":
                        AddToList_Action.append(str(Selection[i]))
                    elif str(Selection[i]) =="Cycle":
                        pass
                elif (i+1)%2==0:
                    if str(Selection[i-1])=="Cycle":
                        CycleList.append(str(Selection[i]))
                    else:
                        AddToList_OpenCourse.append(str(Selection[i]))
                else:
                    pass

    except FileNotFoundError:
        messagebox.showinfo("提示", "無法載入加退選清單"+"\n"+"請先執行setting設定加退選資訊")
        os._exit()
    if len(Selection)==0:
        messagebox.showinfo("提示","加退選清單為空白"+"\n"+"請先執行setting設定加退選資訊")
        os._exit()
    return
def build_GUI():
    #Build A GUI Window
    LoadTheLoginInformation()
    LoadTheSelectionInformation()
    window.title("搶課程式")
    window.geometry('380x420')
    window.resizable(False, True)

    #LanguageTitle
    LanguageTitle = tk.Label(window,width=30,text="語言選擇",font=("normal",15),compound="center")
    LanguageTitle.place(x=190,y=20,anchor=CENTER)
    LanguageSelect()

    #TimeTitle
    SelectiveTitle = tk.Label(window,width=30,text="搶課排程",font=("normal",15),compound="center")
    SelectiveTitle.place(x=190, y=80, anchor=CENTER)
    TimeMode()
    initial()

    #Execution Button
    ExecutionButton = tk.Button(window,text="開始搶課", command=Execution)
    ExecutionButton.place(x=190, y=320, anchor=CENTER)

    #AboutMe
    AboutMeTitle = tk.Label(window, text="~本機器人由淡江大學 資汛工程學系 WYSH 開發製作~", font=("normal", 10), compound="center")
    AboutMeTitle.place(x=190, y=350, anchor=CENTER)
    CompilerTitle = tk.Label(window, text="使用Python3.11.2開發製作,2023/02/26編譯", font=("normal", 10),compound="center")
    CompilerTitle.place(x=190, y=370, anchor=CENTER)
    SloganTitle = tk.Label(window, text="電腦怪傑,實力不容小覷,不服來戰", font=("normal", 10),compound="center")
    SloganTitle.place(x=190, y=390, anchor=CENTER)
    window.mainloop()

def LanguageSelect():
    global var_1
    var_1 = tk.StringVar()
    global Language_Chinese, Language_English
    Language_Chinese = tk.Radiobutton(window,text='中文', command=LaguageSet,var=var_1, value=1)
    Language_English = tk.Radiobutton(window,text='English', command=LaguageSet,var=var_1, value=2)
    Language_Chinese.place(x=100, y=30)
    Language_English.place(x=220, y=30)
def LaguageSet():
    global Language_Set
    Language_Set = var_1.get()
    if Language_Set=="1":
        driver.get(URL_Chinese)
    else:
        driver.get(URL_English)
    return
def TimeMode():
    global var_2
    var_2 = tk.StringVar()
    global TimeMode_Immediately, TimeMode_Schedule
    TimeMode_Immediately = tk.Radiobutton(window,text='立即',command=TimeModeSet, var=var_2,value=3)
    TimeMode_Schedule = tk.Radiobutton(window,text='預約搶課',command=TimeModeSet, var=var_2,value=4)
    TimeMode_Immediately.place(x=100, y=100)
    TimeMode_Schedule.place(x=220, y=100)
def TimeModeSet():
    global TimeMode_Set
    TimeMode_Set = var_2.get()
    if TimeMode_Set =="3":
        initial()
    else:
        TimeSetArea()
    return
def initial():
    # TimeAreaTitle
    TimeAreaTitle = tk.Label(window,width=30, state="disable",text="時間設定", font=("normal", 15), compound="center")
    TimeAreaTitle.place(x=190, y=150, anchor=CENTER)

    # YearTitle
    YearTitle = tk.Label(window,width=3, state="disable", text="年份", font=("normal", 10), compound="center")
    YearTitle.place(x=80, y=180, anchor=CENTER)

    # YearSelectionBox
    global YearSelection
    YearSelection = ttk.Combobox(window, state="disable", width=4,
                                 values=["2023", "2024", "2025", "2026", "2027", "2028", "2029", "2030"])
    YearSelection.pack()
    YearSelection.place(x=75, y=200, anchor=CENTER)
    YearSelection.current(0)

    # MonthTitle
    MonthTitle = tk.Label(window,width=3, state="disable", text="月份", font=("normal", 10), compound="center")
    MonthTitle.place(x=125, y=180, anchor=CENTER)

    # MonthSelectionBox
    global MonthSelection
    MonthSelection = ttk.Combobox(window, state="disable", width=2,
                                  values=["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"])
    MonthSelection.pack()
    MonthSelection.place(x=125, y=200, anchor=CENTER)
    MonthSelection.current(0)

    # DateTitle
    DateTitle = tk.Label(window,width=3, state="disable", text="日期", font=("normal", 10), compound="center")
    DateTitle.place(x=170, y=180, anchor=CENTER)

    # DateSelectionBox
    global DateSelection
    DateSelection = ttk.Combobox(window, state="disable", width=2,
                                 values=["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13",
                                         "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26",
                                         "27", "28", "29", "30", "31"])
    DateSelection.pack()
    DateSelection.place(x=170, y=200, anchor=CENTER)
    DateSelection.current(10)

    # HourTitle
    HourTitle = tk.Label(window,width=3, state="disable", text="小時", font=("normal", 10), compound="center")
    HourTitle.place(x=225, y=180, anchor=CENTER)

    # HourSelectionBox
    global HourSelection
    HourSelection = ttk.Combobox(window, state="disable", width=2,
                                 values=["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12",
                                         "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"])
    HourSelection.pack()
    HourSelection.place(x=225, y=200, anchor=CENTER)
    HourSelection.current(12)

    # MinutesTitle
    MinutesTitle = tk.Label(window,width=3, state="disable", text="分", font=("normal", 10), compound="center")
    MinutesTitle.place(x=270, y=180, anchor=CENTER)

    # MinutesSelectionBox
    global MinutesSelection
    MinutesSelection = ttk.Combobox(window, state="disable", width=2,
                                    values=["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11",
                                            "12", "13",
                                            "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25",
                                            "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37",
                                            "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
                                            "50", "51", "52", "53", "54", "55", "56", "57", "58", "59"])
    MinutesSelection.pack()
    MinutesSelection.place(x=270, y=200, anchor=CENTER)
    MinutesSelection.current(30)

    # SecondTitle
    SecondTitle = tk.Label(window,width=3, state="disable", text="秒", font=("normal", 10), compound="center")
    SecondTitle.place(x=315, y=180, anchor=CENTER)

    # SecondSelectionBox
    global SecondSelection
    SecondSelection = ttk.Combobox(window, state="disable", width=2,
                                   values=["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11",
                                           "12", "13",
                                           "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25",
                                           "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37",
                                           "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
                                           "50", "51", "52", "53", "54", "55", "56", "57", "58", "59"])
    SecondSelection.pack()
    SecondSelection.place(x=315, y=200, anchor=CENTER)
    SecondSelection.current(0)
    return
def TimeSetArea():
    # TimeAreaTitle
    TimeAreaTitle = tk.Label(window,width=30, state="normal",text="時間設定", font=("normal", 15), compound="center")
    TimeAreaTitle.place(x=190, y=150, anchor=CENTER)

    #YearTitle
    YearTitle = tk.Label(window,width=3, state="normal", text="年份", font=("normal", 10), compound="center")
    YearTitle.place(x=80, y=180, anchor=CENTER)

    #YearSelectionBox
    global YearSelection
    YearSelection = ttk.Combobox(window, state="readonly",width=4,values=["2023","2024","2025","2026","2027","2028","2029","2030"])
    YearSelection.pack()
    YearSelection.place(x=75, y=200, anchor=CENTER)
    YearSelection.current(0)

    #MonthTitle
    MonthTitle = tk.Label(window,width=3, state="normal", text="月份", font=("normal", 10), compound="center")
    MonthTitle.place(x=125, y=180, anchor=CENTER)

    #MonthSelectionBox
    global MonthSelection
    MonthSelection = ttk.Combobox(window, state="readonly", width=2,values=["01", "02", "03", "04", "05", "06", "07", "08","09","10","11","12"])
    MonthSelection.pack()
    MonthSelection.place(x=125, y=200, anchor=CENTER)
    MonthSelection.current(0)

    #DateTitle
    DateTitle = tk.Label(window,width=3, state="normal", text="日期", font=("normal", 10), compound="center")
    DateTitle.place(x=170, y=180, anchor=CENTER)

    #DateSelectionBox
    global DateSelection
    DateSelection = ttk.Combobox(window, state="readonly", width=2, values=["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31"])
    DateSelection.pack()
    DateSelection.place(x=170, y=200, anchor=CENTER)
    DateSelection.current(10)

    #HourTitle
    HourTitle = tk.Label(window,width=3, state="normal", text="小時", font=("normal", 10), compound="center")
    HourTitle.place(x=225, y=180, anchor=CENTER)

    #HourSelectionBox
    global HourSelection
    HourSelection = ttk.Combobox(window, state="readonly", width=2,values=["00","01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13","14", "15", "16", "17", "18", "19", "20", "21", "22", "23"])
    HourSelection.pack()
    HourSelection.place(x=225, y=200, anchor=CENTER)
    HourSelection.current(12)

    #MinutesTitle
    MinutesTitle = tk.Label(window,width=3, state="normal", text="分", font=("normal", 10), compound="center")
    MinutesTitle.place(x=270, y=180, anchor=CENTER)

    #MinutesSelectionBox
    global MinutesSelection
    MinutesSelection = ttk.Combobox(window, state="readonly", width=2,
                                 values=["00","01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13",
                                         "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59"])
    MinutesSelection.pack()
    MinutesSelection.place(x=270, y=200, anchor=CENTER)
    MinutesSelection.current(30)

    # SecondTitle
    SecondTitle = tk.Label(window,width=3, state="normal", text="秒", font=("normal", 10), compound="center")
    SecondTitle.place(x=315, y=180, anchor=CENTER)

    #SecondSelectionBox
    global SecondSelection
    SecondSelection = ttk.Combobox(window, state="readonly", width=2,
                                    values=["00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11",
                                            "12", "13",
                                            "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25",
                                            "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37",
                                            "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
                                            "50", "51", "52", "53", "54", "55", "56", "57", "58", "59"])
    SecondSelection.pack()
    SecondSelection.place(x=315, y=200, anchor=CENTER)
    SecondSelection.current(0)
    return
def Execution():
    try:
        Account(Account_Login_Record)
        Password(Password_Login_Record)
        ConfirmNumber()
        if TimeMode_Set=="3":
            driver.find_element("xpath", "//*[@id=\"btnLogin\"]").click()  # 時間到了會自動幫你按登入
            Selection_Main()
            #pass
        else:
            TimeSet = YearSelection.get()+"-"+MonthSelection.get()+"-"+DateSelection.get()+" "+HourSelection.get()+":"+MinutesSelection.get()+":"+SecondSelection.get()#str(int(SecondSelection.get())+1)
            #print(TimeSet)
            #print(type(TimeSet))
            TimeCheck(TimeSet)
            Selection_Main()
    except:
        pass
    return

def Selection_Main():
    for i in range(len(AddToList_Action)):
        if AddToList_Action[i]=="Add":
            AddCourse(AddToList_OpenCourse[i])
        elif AddToList_Action[i]=="Remove":
            RemoveCourse(AddToList_OpenCourse[i])
        else:
            pass

#Login information
#StudentID
def Account(Account_Number):
    try:
        account = driver.find_element("xpath","//*[@id=\"txtStuNo\"]")
        account.clear()
        account.send_keys(Account_Number)#學號
    except:
        print("系統尚未開放")
    return
#StudentPassword
def Password(Password_Value):
    try:
        password = driver.find_element("xpath","//*[@id=\"txtPSWD\"]")
        password.clear()
        password.send_keys(Password_Value)#密碼
    except:
        print("系統尚未開放")
    return
def ConfirmNumber():
    #ConfirmNumber
    #try:
    ConfirmNumber = driver.find_element("xpath","//*[@id=\"txtCONFM\"]")
    ConfirmNumber.clear()
    try:
        if Language_Set=="1":
            driver.execute_script(ChineseScript)
        else:
            driver.execute_script(EnglishScript)
    except:
        ConfirmNumber.send_keys("")
    return

def TimeCheck(TIME_SET):
    #Check the time
    #格式'2023-01-11 12:29:59'
    #確認加選時間,但拜託格式不要改,空格不要刪除
    try:
        localtime = time.localtime()
        global result
        result = time.strftime("%Y-%m-%d %H:%M:%S", localtime)
        year_check = result[0]+result[1]+result[2]+result[3]
        month_check = result[5]+result[6]
        date_check = result[8]+result[9]
        hour_check = result[11]+result[12]
        minutes_check = result[14]+result[15]
        seconds_check = result[17]+result[18]
        current = datetime.datetime(int(year_check),int(month_check),int(date_check),int(hour_check),int(minutes_check),int(seconds_check))
        selection_time_set = datetime.datetime(int(YearSelection.get()),int(MonthSelection.get()),int(DateSelection.get()),int(HourSelection.get()),int(MinutesSelection.get()),int(SecondSelection.get())+5)
        #print(current<selection_time_set)
        while current<=selection_time_set:
            localtime = time.localtime()
            result = time.strftime("%Y-%m-%d %H:%M:%S", localtime)
            year_check = result[0] + result[1] + result[2] + result[3]
            month_check = result[5] + result[6]
            date_check = result[8] + result[9]
            hour_check = result[11] + result[12]
            minutes_check = result[14] + result[15]
            seconds_check = result[17] + result[18]
            current = datetime.datetime(int(year_check), int(month_check), int(date_check), int(hour_check),int(minutes_check), int(seconds_check))
            print(result)
            time.sleep(1)
            driver.refresh()
            Account(Account_Login_Record)
            Password(Password_Login_Record)
            ConfirmNumber()

        #Login
        driver.find_element("xpath", "//*[@id=\"btnLogin\"]").click()  # 時間到了會自動幫你按登入
        print("LoginTime: "+result)
    except:
        driver.find_element("xpath", "//*[@id=\"btnLogin\"]").click()  # 時間到了會自動幫你按登入
        print("已經嘗試登入")
    return

def RemoveCourse(OpenCode):
    #Remove
    #要刪除的課程
    try:
        Remove_Number = driver.find_element("xpath","//*[@id=\"txtCosEleSeq\"]")
        Remove_Number.clear()
        Remove_Number.send_keys(OpenCode) #""不要刪掉
        driver.find_element("xpath","//*[@id=\"btnDel\"]").click()
    except:
        #messagebox.showinfo("提示","系統尚未開放,請耐心等學校開放")
        print("系統尚未開放,退選失敗")
    return
def AddCourse(OpenCode):
    #Add
    #要加的課程
    try:
        Add_Number = driver.find_element("xpath","//*[@id=\"txtCosEleSeq\"]")
        Add_Number.clear()
        Add_Number.send_keys(OpenCode) #""不要刪掉
        driver.find_element("xpath","//*[@id=\"btnAdd\"]").click()
    except:
        #messagebox.showinfo("提示", "系統尚未開放,請耐心等學校開放")
        try:
            driver.find_element("xpath", "//*[@id=\"btnReLogin\"]").click()  # 按下重新登入
            Account(Account_Login_Record)
            Password(Password_Login_Record)
            ConfirmNumber()
            driver.find_element("xpath", "//*[@id=\"btnLogin\"]").click()  # 按下登入
        except:
            try:
                driver.find_element("xpath", "//*[@id=\"btnReLogin\"]").click()  # 按下重新登入
                Account(Account_Login_Record)
                Password(Password_Login_Record)
                ConfirmNumber()
                driver.find_element("xpath", "//*[@id=\"btnLogin\"]").click()  # 按下登入
            except:
                print("系統尚未開放,加選失敗")
    return

def ShowCurrentTable():
    #Show the all Class that you have selected
    driver.find_element("xpath","//*[@id=\"btnEleCos\"]").click()
#============================================================================================
#main function
#messagebox.showinfo("提示",working_dir)
if __name__ == '__main__':
    build_GUI()