diff --git a/chrome_tixcraft.py b/chrome_tixcraft.py index 378d96e..b52df6f 100644 --- a/chrome_tixcraft.py +++ b/chrome_tixcraft.py @@ -54,7 +54,7 @@ import webbrowser import argparse import chromedriver_autoinstaller -CONST_APP_VERSION = "MaxBot (2023.08.15)" +CONST_APP_VERSION = "MaxBot (2023.08.16)" CONST_MAXBOT_CONFIG_FILE = "settings.json" CONST_MAXBOT_LAST_URL_FILE = "MAXBOT_LAST_URL.txt" @@ -69,6 +69,7 @@ CONST_CHROME_VERSION_NOT_MATCH_EN="Please download the WebDriver version to matc CONST_CHROME_VERSION_NOT_MATCH_TW="請下載與您瀏覽器相同版本的WebDriver版本,或更新您的瀏覽器版本。" CONST_KKTIX_SIGN_IN_URL = "https://kktix.com/users/sign_in?back_to=%s" +CONST_CITYLINE_SIGN_IN_URL = "https://www.cityline.com/Login.html?targetUrl=https%3A%2F%2Fwww.cityline.com%2FEvents.html" CONST_URBTIX_SIGN_IN_URL = "https://www.urbtix.hk/member-login" CONST_KHAM_SIGN_IN_URL = "https://kham.com.tw/application/UTK13/UTK1306_.aspx" CONST_HKTICKETING_SIGN_IN_URL = "https://premier.hkticketing.com/Secure/ShowLogin.aspx" @@ -245,17 +246,16 @@ def full2half(keyword): def get_chinese_numeric(): my_dict = {} - my_dict['0']=['zero','零'] - my_dict['1']=['one','一','壹','①','❶','⑴'] - my_dict['2']=['two','二','貳','②','❷','⑵'] - my_dict['3']=['three','三','叁','③','❸','⑶'] - my_dict['4']=['four','四','肆','④','❹','⑷'] - my_dict['5']=['five','五','伍','⑤','❺','⑸'] - my_dict['6']=['six','六','陸','⑥','❻','⑹'] - my_dict['7']=['seven','七','柒','⑦','❼','⑺'] - my_dict['8']=['eight','八','捌','⑧','❽','⑻'] - my_dict['9']=['nine','九','玖','⑨','❾','⑼'] - + my_dict['0']=['0','0','zero','零'] + my_dict['1']=['1','1','one','一','壹','①','❶','⑴'] + my_dict['2']=['2','2','two','二','貳','②','❷','⑵'] + my_dict['3']=['3','3','three','三','叁','③','❸','⑶'] + my_dict['4']=['4','4','four','四','肆','④','❹','⑷'] + my_dict['5']=['5','5','five','五','伍','⑤','❺','⑸'] + my_dict['6']=['6','6','six','六','陸','⑥','❻','⑹'] + my_dict['7']=['7','7','seven','七','柒','⑦','❼','⑺'] + my_dict['8']=['8','8','eight','八','捌','⑧','❽','⑻'] + my_dict['9']=['9','9','nine','九','玖','⑨','❾','⑼'] return my_dict # 同義字 @@ -794,6 +794,10 @@ def get_driver_by_config(config_dict): if len(config_dict["advanced"]["urbtix_account"])>0: homepage = CONST_URBTIX_SIGN_IN_URL + if 'cityline.com' in homepage: + if len(config_dict["advanced"]["cityline_account"])>0: + homepage = CONST_CITYLINE_SIGN_IN_URL + if 'hkticketing.com' in homepage: if len(config_dict["advanced"]["hkticketing_account"])>0: homepage = CONST_HKTICKETING_SIGN_IN_URL @@ -1197,6 +1201,10 @@ def guess_answer_list_from_hint(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captch space_index = tmp_text.find(u" ", star_index) answer_char_count = tmp_text[star_index-1:star_index] if answer_char_count.isnumeric(): + answer_char_count = normalize_chinese_numeric(answer_char_count) + if answer_char_count is None: + answer_char_count = '0' + star_index -= 1 offical_hint_string_anwser = u'A' * int(answer_char_count) offical_hint_string = tmp_text[star_index: space_index] @@ -1207,6 +1215,10 @@ def guess_answer_list_from_hint(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captch space_index = tmp_text.find(u" ", star_index) answer_char_count = tmp_text[star_index-1:star_index] if answer_char_count.isnumeric(): + answer_char_count = normalize_chinese_numeric(answer_char_count) + if answer_char_count is None: + answer_char_count = '0' + star_index -= 1 offical_hint_string_anwser = u'A' * int(answer_char_count) offical_hint_string = tmp_text[star_index: space_index] @@ -1217,6 +1229,10 @@ def guess_answer_list_from_hint(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captch space_index = tmp_text.find(u" ", star_index) answer_char_count = tmp_text[star_index-1:star_index] if answer_char_count.isnumeric(): + answer_char_count = normalize_chinese_numeric(answer_char_count) + if answer_char_count is None: + answer_char_count = '0' + star_index -= 1 offical_hint_string_anwser = u'a' * int(answer_char_count) offical_hint_string = tmp_text[star_index: space_index] @@ -1227,6 +1243,10 @@ def guess_answer_list_from_hint(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captch space_index = tmp_text.find(u" ", star_index) answer_char_count = tmp_text[star_index-1:star_index] if answer_char_count.isnumeric(): + answer_char_count = normalize_chinese_numeric(answer_char_count) + if answer_char_count is None: + answer_char_count = '0' + star_index -= 1 offical_hint_string_anwser = u'a' * int(answer_char_count) offical_hint_string = tmp_text[star_index: space_index] @@ -1237,6 +1257,10 @@ def guess_answer_list_from_hint(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captch space_index = tmp_text.find(u" ", star_index) answer_char_count = tmp_text[star_index-1:star_index] if answer_char_count.isnumeric(): + answer_char_count = normalize_chinese_numeric(answer_char_count) + if answer_char_count is None: + answer_char_count = '0' + star_index -= 1 my_anwser_formated = u'[A-Za-z\d]' * int(answer_char_count) offical_hint_string = tmp_text[star_index: space_index] @@ -1247,6 +1271,10 @@ def guess_answer_list_from_hint(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captch space_index = tmp_text.find(u" ", star_index) answer_char_count = tmp_text[star_index-1:star_index] if answer_char_count.isnumeric(): + answer_char_count = normalize_chinese_numeric(answer_char_count) + if answer_char_count is None: + answer_char_count = '0' + star_index -= 1 my_anwser_formated = u'[A-Za-z\d]' * int(answer_char_count) offical_hint_string = tmp_text[star_index: space_index] @@ -6451,7 +6479,7 @@ def cityline_login(driver, account, password): ret = False el_email = None try: - el_email = driver.find_element(By.CSS_SELECTOR, 'input.ant-input') + el_email = driver.find_element(By.CSS_SELECTOR, 'input[type="text"]') except Exception as exc: pass @@ -6470,6 +6498,7 @@ def cityline_login(driver, account, password): if inputed_text is not None: if len(inputed_text) == 0: el_email.send_keys(account) + el_email.send_keys(Keys.ENTER) is_email_sent = True else: if inputed_text == account: @@ -6477,10 +6506,14 @@ def cityline_login(driver, account, password): except Exception as exc: pass + # press password to login. + if is_email_sent: + is_click_here_pressed = force_press_button(driver, By.CSS_SELECTOR,'.otp-box > ul > li:nth-child(3) > a') + el_pass = None if is_email_sent: try: - el_pass = driver.find_element(By.CSS_SELECTOR, 'input[type="password"]') + el_pass = driver.find_element(By.CSS_SELECTOR, 'input[type="password"][aria-label="Password"]') except Exception as exc: pass @@ -7666,6 +7699,15 @@ def cityline_main(driver, url, config_dict): # show HTTP ERROR 400 pass + + # https://www.cityline.com/Login.html?targetUrl=https%3A%2F%2F + # ignore url redirect + if '/Login.html' in url: + cityline_account = config_dict["advanced"]["cityline_account"] + if len(cityline_account) > 2: + cityline_login(driver, cityline_account, decryptMe(config_dict["advanced"]["cityline_password"])) + return + is_ready_to_buy_from_queue = False # Q: How to know ready to buy ticket from queue? if is_ready_to_buy_from_queue: diff --git a/config_launcher.py b/config_launcher.py index 87cd167..26ba621 100644 --- a/config_launcher.py +++ b/config_launcher.py @@ -22,7 +22,7 @@ import base64 import threading import subprocess -CONST_APP_VERSION = "MaxBot (2023.08.15)" +CONST_APP_VERSION = "MaxBot (2023.08.16)" CONST_MAXBOT_LAUNCHER_FILE = "config_launcher.json" CONST_MAXBOT_CONFIG_FILE = "settings.json" diff --git a/settings.json b/settings.json index 183e870..57bfec1 100644 --- a/settings.json +++ b/settings.json @@ -1 +1 @@ -{"homepage": "https://tixcraft.com", "browser": "chrome", "language": "\u7e41\u9ad4\u4e2d\u6587", "ticket_number": 2, "auto_check_agree": true, "ocr_captcha": {"enable": true, "beta": true, "force_submit": true, "image_source": "canvas"}, "webdriver_type": "undetected_chromedriver", "kktix": {"auto_press_next_step_button": true, "auto_fill_ticket_number": true}, "tixcraft": {"date_auto_select": {"enable": true, "date_keyword": "", "mode": "from top to bottom"}, "pass_date_is_sold_out": true, "auto_reload_coming_soon_page": true}, "area_auto_select": {"enable": true, "mode": "from top to bottom", "area_keyword": ""}, "keyword_exclude": "\"\u8f2a\u6905\",\"\u8eab\u969c\",\"\u8eab\u5fc3 \u969c\u7919\",\"Restricted View\"", "advanced": {"play_captcha_sound": {"enable": true, "filename": "ding-dong.wav"}, "tixcraft_sid": "", "ibonqware": "", "facebook_account": "", "kktix_account": "", "urbtix_account": "", "hkticketing_account": "", "kham_account": "", "ticketplus_account": "", "facebook_password": "", "kktix_password": "", "urbtix_password": "", "hkticketing_password": "", "kham_password": "", "ticketplus_password": "", "adblock_plus_enable": false, "disable_adjacent_seat": false, "headless": false, "verbose": false, "auto_guess_options": true, "user_guess_string": "", "online_dictionary_url": "", "auto_reload_page_interval": 1.0, "auto_reload_random_delay": false}} \ No newline at end of file +{"homepage": "https://tixcraft.com", "browser": "chrome", "language": "\u7e41\u9ad4\u4e2d\u6587", "ticket_number": 2, "auto_check_agree": true, "ocr_captcha": {"enable": true, "beta": true, "force_submit": true, "image_source": "canvas"}, "webdriver_type": "undetected_chromedriver", "kktix": {"auto_press_next_step_button": true, "auto_fill_ticket_number": true}, "tixcraft": {"date_auto_select": {"enable": true, "date_keyword": "", "mode": "from top to bottom"}, "pass_date_is_sold_out": true, "auto_reload_coming_soon_page": true}, "area_auto_select": {"enable": true, "mode": "from top to bottom", "area_keyword": ""}, "keyword_exclude": "\"\u8f2a\u6905\",\"\u8eab\u969c\",\"\u8eab\u5fc3 \u969c\u7919\",\"Restricted View\"", "advanced": {"play_captcha_sound": {"enable": true, "filename": "ding-dong.wav"}, "tixcraft_sid": "", "ibonqware": "", "facebook_account": "", "kktix_account": "", "cityline_account": "", "urbtix_account": "", "hkticketing_account": "", "kham_account": "", "ticketplus_account": "", "facebook_password": "", "kktix_password": "", "urbtix_password": "", "cityline_password": "", "hkticketing_password": "", "kham_password": "", "ticketplus_password": "", "adblock_plus_enable": false, "disable_adjacent_seat": false, "headless": false, "verbose": false, "auto_guess_options": true, "user_guess_string": "", "online_dictionary_url": "", "auto_reload_page_interval": 1.0, "auto_reload_random_delay": false}} \ No newline at end of file diff --git a/settings.py b/settings.py index efd0614..56c4ee7 100644 --- a/settings.py +++ b/settings.py @@ -34,7 +34,7 @@ warnings.simplefilter('ignore',InsecureRequestWarning) import ssl ssl._create_default_https_context = ssl._create_unverified_context -CONST_APP_VERSION = "MaxBot (2023.08.15)" +CONST_APP_VERSION = "MaxBot (2023.08.16)" CONST_MAXBOT_CONFIG_FILE = "settings.json" CONST_MAXBOT_LAST_URL_FILE = "MAXBOT_LAST_URL.txt" @@ -172,6 +172,7 @@ def load_translate(): en_us["ibon_ibonqware"] = 'ibon cookie ibonqware' en_us["facebook_account"] = 'Facebook account' en_us["kktix_account"] = 'KKTIX account' + en_us["cityline_account"] = 'cityline account' en_us["urbtix_account"] = 'URBTIX account' en_us["hkticketing_account"] = 'HKTICKETING account' en_us["kham_account"] = 'KHAM account' @@ -179,6 +180,7 @@ def load_translate(): en_us["facebook_password"] = 'Facebook password' en_us["kktix_password"] = 'KKTIX password' + en_us["cityline_password"] = 'cityline password' en_us["urbtix_password"] = 'URBTIX password' en_us["hkticketing_password"] = 'HKTICKETING password' en_us["kham_password"] = 'KHAM password' @@ -266,6 +268,7 @@ def load_translate(): zh_tw["ibon_ibonqware"] = 'ibon cookie ibonqware' zh_tw["facebook_account"] = 'Facebook 帳號' zh_tw["kktix_account"] = 'KKTIX 帳號' + zh_tw["cityline_account"] = 'cityline 帳號' zh_tw["urbtix_account"] = 'URBTIX 帳號' zh_tw["hkticketing_account"] = 'HKTICKETING 帳號' zh_tw["kham_account"] = '寬宏 帳號' @@ -273,6 +276,7 @@ def load_translate(): zh_tw["facebook_password"] = 'Facebook 密碼' zh_tw["kktix_password"] = 'KKTIX 密碼' + zh_tw["cityline_password"] = 'cityline 密碼' zh_tw["urbtix_password"] = 'URBTIX 密碼' zh_tw["hkticketing_password"] = 'HKTICKETING 密碼' zh_tw["kham_password"] = '寬宏 密碼' @@ -361,6 +365,7 @@ def load_translate(): zh_cn["ibon_ibonqware"] = 'ibon cookie ibonqware' zh_cn["facebook_account"] = 'Facebook 帐号' zh_cn["kktix_account"] = 'KKTIX 帐号' + zh_cn["cityline_account"] = 'cityline 帐号' zh_cn["urbtix_account"] = 'URBTIX 帐号' zh_cn["hkticketing_account"] = 'HKTICKETING 帐号' zh_cn["kham_account"] = '宽宏 帐号' @@ -368,6 +373,7 @@ def load_translate(): zh_cn["facebook_password"] = 'Facebook 密码' zh_cn["kktix_password"] = 'KKTIX 密码' + zh_cn["cityline_password"] = 'cityline 密码' zh_cn["urbtix_password"] = 'URBTIX 密码' zh_cn["hkticketing_password"] = 'HKTICKETING 密码' zh_cn["kham_password"] = '宽宏 密码' @@ -455,6 +461,7 @@ def load_translate(): ja_jp["ibon_ibonqware"] = 'ibon cookie ibonqware' ja_jp["facebook_account"] = 'Facebookのアカウント' ja_jp["kktix_account"] = 'KKTIXのアカウント' + ja_jp["cityline_account"] = 'citylineのアカウント' ja_jp["urbtix_account"] = 'URBTIXのアカウント' ja_jp["hkticketing_account"] = 'HKTICKETINGのアカウント' ja_jp["kham_account"] = 'KHAMのアカウント' @@ -462,6 +469,7 @@ def load_translate(): ja_jp["facebook_password"] = 'Facebookのパスワード' ja_jp["kktix_password"] = 'KKTIXのパスワード' + ja_jp["cityline_password"] = 'citylineのパスワード' ja_jp["urbtix_password"] = 'URBTIXのパスワード' ja_jp["hkticketing_password"] = 'HKTICKETINGのパスワード' ja_jp["kham_password"] = 'KHAMのパスワード' @@ -602,6 +610,7 @@ def get_default_config(): config_dict["advanced"]["ibonqware"] = "" config_dict["advanced"]["facebook_account"] = "" config_dict["advanced"]["kktix_account"] = "" + config_dict["advanced"]["cityline_account"] = "" config_dict["advanced"]["urbtix_account"] = "" config_dict["advanced"]["hkticketing_account"] = "" config_dict["advanced"]["kham_account"] = "" @@ -610,6 +619,7 @@ def get_default_config(): config_dict["advanced"]["facebook_password"] = "" config_dict["advanced"]["kktix_password"] = "" config_dict["advanced"]["urbtix_password"] = "" + config_dict["advanced"]["cityline_password"] = "" config_dict["advanced"]["hkticketing_password"] = "" config_dict["advanced"]["kham_password"] = "" config_dict["advanced"]["ticketplus_password"] = "" @@ -721,6 +731,7 @@ def btn_save_act(language_code, slience_mode=False): global txt_ibon_ibonqware global txt_facebook_account global txt_kktix_account + global txt_cityline_account global txt_urbtix_account global txt_hkticketing_account global txt_kham_account @@ -728,6 +739,7 @@ def btn_save_act(language_code, slience_mode=False): global txt_facebook_password global txt_kktix_password + global txt_cityline_password global txt_urbtix_password global txt_hkticketing_password global txt_kham_password @@ -863,6 +875,7 @@ def btn_save_act(language_code, slience_mode=False): config_dict["advanced"]["ibonqware"] = txt_ibon_ibonqware.get().strip() config_dict["advanced"]["facebook_account"] = txt_facebook_account.get().strip() config_dict["advanced"]["kktix_account"] = txt_kktix_account.get().strip() + config_dict["advanced"]["cityline_account"] = txt_cityline_account.get().strip() config_dict["advanced"]["urbtix_account"] = txt_urbtix_account.get().strip() config_dict["advanced"]["hkticketing_account"] = txt_hkticketing_account.get().strip() config_dict["advanced"]["kham_account"] = txt_kham_account.get().strip() @@ -870,6 +883,7 @@ def btn_save_act(language_code, slience_mode=False): config_dict["advanced"]["facebook_password"] = txt_facebook_password.get().strip() config_dict["advanced"]["kktix_password"] = txt_kktix_password.get().strip() + config_dict["advanced"]["cityline_password"] = txt_cityline_password.get().strip() config_dict["advanced"]["urbtix_password"] = txt_urbtix_password.get().strip() config_dict["advanced"]["hkticketing_password"] = txt_hkticketing_password.get().strip() config_dict["advanced"]["kham_password"] = txt_kham_password.get().strip() @@ -879,6 +893,7 @@ def btn_save_act(language_code, slience_mode=False): config_dict["advanced"]["ibonqware"] = encryptMe(config_dict["advanced"]["ibonqware"]) config_dict["advanced"]["facebook_password"] = encryptMe(config_dict["advanced"]["facebook_password"]) config_dict["advanced"]["kktix_password"] = encryptMe(config_dict["advanced"]["kktix_password"]) + config_dict["advanced"]["cityline_password"] = encryptMe(config_dict["advanced"]["cityline_password"]) config_dict["advanced"]["urbtix_password"] = encryptMe(config_dict["advanced"]["urbtix_password"]) config_dict["advanced"]["hkticketing_password"] = encryptMe(config_dict["advanced"]["hkticketing_password"]) config_dict["advanced"]["kham_password"] = encryptMe(config_dict["advanced"]["kham_password"]) @@ -1273,6 +1288,7 @@ def applyNewLanguage(): global lbl_ibon_ibonqware global lbl_facebook_account global lbl_kktix_account + global lbl_cityline_account global lbl_urbtix_account global lbl_hkticketing_account global lbl_kham_account @@ -1280,6 +1296,7 @@ def applyNewLanguage(): global lbl_facebook_password global lbl_kktix_password + global lbl_cityline_password global lbl_urbtix_password global lbl_hkticketing_password global lbl_kham_password @@ -1294,6 +1311,7 @@ def applyNewLanguage(): lbl_ibon_ibonqware.config(text=translate[language_code]["ibon_ibonqware"]) lbl_facebook_account.config(text=translate[language_code]["facebook_account"]) lbl_kktix_account.config(text=translate[language_code]["kktix_account"]) + lbl_cityline_account.config(text=translate[language_code]["cityline_account"]) lbl_urbtix_account.config(text=translate[language_code]["urbtix_account"]) lbl_hkticketing_account.config(text=translate[language_code]["hkticketing_account"]) lbl_kham_account.config(text=translate[language_code]["kham_account"]) @@ -1301,6 +1319,7 @@ def applyNewLanguage(): lbl_facebook_password.config(text=translate[language_code]["facebook_password"]) lbl_kktix_password.config(text=translate[language_code]["kktix_password"]) + lbl_cityline_password.config(text=translate[language_code]["cityline_password"]) lbl_urbtix_password.config(text=translate[language_code]["urbtix_password"]) lbl_hkticketing_password.config(text=translate[language_code]["hkticketing_password"]) lbl_kham_password.config(text=translate[language_code]["kham_password"]) @@ -2135,6 +2154,28 @@ def AutofillTab(root, config_dict, language_code, UI_PADDING_X): group_row_count +=1 + global lbl_cityline_account + lbl_cityline_account = Label(frame_group_header, text=translate[language_code]['cityline_account']) + lbl_cityline_account.grid(column=0, row=group_row_count, sticky = E) + + global txt_cityline_account + txt_cityline_account_value = StringVar(frame_group_header, value=config_dict["advanced"]["cityline_account"].strip()) + txt_cityline_account = Entry(frame_group_header, width=30, textvariable = txt_cityline_account_value) + txt_cityline_account.grid(column=1, row=group_row_count, sticky = W) + + group_row_count +=1 + + global lbl_cityline_password + lbl_cityline_password = Label(frame_group_header, text=translate[language_code]['cityline_password']) + lbl_cityline_password.grid(column=0, row=group_row_count, sticky = E) + + global txt_cityline_password + txt_cityline_password_value = StringVar(frame_group_header, value=decryptMe(config_dict["advanced"]["cityline_password"].strip())) + txt_cityline_password = Entry(frame_group_header, width=30, textvariable = txt_cityline_password_value, show="*") + txt_cityline_password.grid(column=1, row=group_row_count, sticky = W) + + group_row_count +=1 + global lbl_urbtix_account lbl_urbtix_account = Label(frame_group_header, text=translate[language_code]['urbtix_account']) lbl_urbtix_account.grid(column=0, row=group_row_count, sticky = E) diff --git a/text_server.py b/text_server.py index cb114d6..65c416c 100644 --- a/text_server.py +++ b/text_server.py @@ -28,7 +28,7 @@ import asyncio import tornado from tornado.web import Application -CONST_APP_VERSION = "MaxBot (2023.08.15)" +CONST_APP_VERSION = "MaxBot (2023.08.16)" CONST_MAXBOT_QUESTION_FILE = "MAXBOT_QUESTION.txt"