diff --git a/chrome_tixcraft.py b/chrome_tixcraft.py index 80fa27b..c8990bb 100644 --- a/chrome_tixcraft.py +++ b/chrome_tixcraft.py @@ -39,7 +39,7 @@ warnings.simplefilter('ignore',InsecureRequestWarning) import ssl ssl._create_default_https_context = ssl._create_unverified_context -CONST_APP_VERSION = u"MaxBot (2022.11.22)" +CONST_APP_VERSION = u"MaxBot (2022.11.24)" CONST_HOMEPAGE_DEFAULT = "https://tixcraft.com" CONST_FROM_TOP_TO_BOTTOM = u"from top to bottom" @@ -289,6 +289,7 @@ def get_driver_by_config(config_dict, driver_type): # output debug message in client side. debugMode = config_dict["debug"] ticket_number = str(config_dict["ticket_number"]) + pass_1_seat_remaining_enable = config_dict["pass_1_seat_remaining"] # for ["kktix"] auto_press_next_step_button = config_dict["kktix"]["auto_press_next_step_button"] @@ -325,7 +326,6 @@ def get_driver_by_config(config_dict, driver_type): area_keyword_3 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_3"].strip() area_keyword_4 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_4"].strip() - pass_1_seat_remaining_enable = config_dict["tixcraft"]["pass_1_seat_remaining"] pass_date_is_sold_out_enable = config_dict["tixcraft"]["pass_date_is_sold_out"] auto_reload_coming_soon_page_enable = config_dict["tixcraft"]["auto_reload_coming_soon_page"] @@ -335,6 +335,7 @@ def get_driver_by_config(config_dict, driver_type): print("homepage", homepage) print("browser", browser) print("ticket_number", ticket_number) + print("pass_1_seat_remaining", pass_1_seat_remaining_enable) # for kktix print("==[kktix]==") @@ -359,7 +360,6 @@ def get_driver_by_config(config_dict, driver_type): print("area_keyword_3", area_keyword_3) print("area_keyword_4", area_keyword_4) - print("pass_1_seat_remaining", pass_1_seat_remaining_enable) print("pass_date_is_sold_out", pass_date_is_sold_out_enable) print("auto_reload_coming_soon_page", auto_reload_coming_soon_page_enable) print("debug Mode", debugMode) @@ -1123,7 +1123,12 @@ def tixcraft_area_auto_select(driver, url, config_dict): area_keyword_3 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_3"].strip() area_keyword_4 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_4"].strip() area_auto_select_mode = config_dict["tixcraft"]["area_auto_select"]["mode"] - pass_1_seat_remaining_enable = config_dict["tixcraft"]["pass_1_seat_remaining"] + + pass_1_seat_remaining_enable = config_dict["pass_1_seat_remaining"] + # disable pass 1 seat remaining when target ticket number is 1. + ticket_number = config_dict["ticket_number"] + if ticket_number == 1: + pass_1_seat_remaining_enable = False show_debug_message = True # debug. show_debug_message = False # online @@ -1697,7 +1702,7 @@ def kktix_input_captcha_text(captcha_password_input_tag, captcha_password_string return is_cpatcha_sent -def kktix_travel_price_list(driver, kktix_area_keyword_1, kktix_area_keyword_1_and): +def kktix_travel_price_list(driver, ticket_number, pass_1_seat_remaining_enable, kktix_area_keyword_1, kktix_area_keyword_1_and): show_debug_message = True # debug. show_debug_message = False # online @@ -1781,6 +1786,22 @@ def kktix_travel_price_list(driver, kktix_area_keyword_1, kktix_area_keyword_1_a # no need to travel break + is_danger_notice = False + if ticket_number > 1: + # start to check danger notice. + span_danger_popup = None + try: + span_danger_popup = row.find_element(By.CSS_SELECTOR, "span.danger") + if span_danger_popup.is_displayed(): + is_danger_notice = True + except Exception as exc: + pass + + if is_danger_notice: + # skip this row, because assign will fail, or fill ticket number as 1. + if pass_1_seat_remaining_enable: + continue + if is_visible: is_match_area = False match_area_code = 0 @@ -1833,11 +1854,13 @@ def kktix_travel_price_list(driver, kktix_area_keyword_1, kktix_area_keyword_1_a return is_ticket_number_assigened, areas -def kktix_assign_ticket_number(driver, ticket_number, kktix_area_auto_select_mode, kktix_area_keyword_1, kktix_area_keyword_1_and): +def kktix_assign_ticket_number(driver, ticket_number, pass_1_seat_remaining_enable, kktix_area_auto_select_mode, kktix_area_keyword_1, kktix_area_keyword_1_and): show_debug_message = True # debug. show_debug_message = False # online - is_ticket_number_assigened, areas = kktix_travel_price_list(driver, kktix_area_keyword_1, kktix_area_keyword_1_and) + ticket_number_str = str(ticket_number) + + is_ticket_number_assigened, areas = kktix_travel_price_list(driver, ticket_number, pass_1_seat_remaining_enable, kktix_area_keyword_1, kktix_area_keyword_1_and) target_area = None if not is_ticket_number_assigened: @@ -1882,9 +1905,9 @@ def kktix_assign_ticket_number(driver, ticket_number, kktix_area_auto_select_mod if is_visible and len(current_ticket_number) > 0: if current_ticket_number == "0": try: - print("asssign ticket number:%s" % str(ticket_number)) + print("asssign ticket number:%s" % ticket_number_str) ticket_price_input.clear() - ticket_price_input.send_keys(ticket_number) + ticket_price_input.send_keys(ticket_number_str) is_ticket_number_assigened = True except Exception as exc: @@ -2424,7 +2447,7 @@ def kktix_reg_new_captcha(registrationsNewApp_div, captcha_inner_div, auto_guess return captcha_password_string, answer_list, my_answer_delimitor -def kktix_double_check_all_text_value(driver, ticket_number): +def kktix_double_check_all_text_value(driver, ticket_number_str): is_do_press_next_button = False # double check ticket input textbox. @@ -2451,7 +2474,7 @@ def kktix_double_check_all_text_value(driver, ticket_number): current_ticket_number = "" if len(current_ticket_number) > 0: #print(row_index, "current_ticket_number:", current_ticket_number) - if current_ticket_number == ticket_number: + if current_ticket_number == ticket_number_str: #print("bingo, match target ticket number.") # ONLY, this case to auto press next button. @@ -2473,7 +2496,14 @@ def kktix_reg_new_main(driver, answer_index, is_finish_checkbox_click, config_di #print("find input fail:", exc) # part 2: assign ticket number - ticket_number = str(config_dict["ticket_number"]) + ticket_number_str = str(config_dict["ticket_number"]) + + pass_1_seat_remaining_enable = config_dict["pass_1_seat_remaining"] + # disable pass 1 seat remaining when target ticket number is 1. + ticket_number = config_dict["ticket_number"] + if ticket_number == 1: + pass_1_seat_remaining_enable = False + is_assign_ticket_number = False if not registrationsNewApp_div is None: kktix_area_auto_select_mode = config_dict["kktix"]["area_mode"] @@ -2483,11 +2513,11 @@ def kktix_reg_new_main(driver, answer_index, is_finish_checkbox_click, config_di kktix_area_keyword_2_and = config_dict["kktix"]["area_keyword_2_and"].strip() for retry_index in range(2): - is_assign_ticket_number = kktix_assign_ticket_number(driver, ticket_number, kktix_area_auto_select_mode, kktix_area_keyword_1, kktix_area_keyword_1_and) + is_assign_ticket_number = kktix_assign_ticket_number(driver, ticket_number, pass_1_seat_remaining_enable, kktix_area_auto_select_mode, kktix_area_keyword_1, kktix_area_keyword_1_and) if not is_assign_ticket_number: - is_assign_ticket_number = kktix_assign_ticket_number(driver, ticket_number, kktix_area_auto_select_mode, kktix_area_keyword_1, kktix_area_keyword_1_and) + is_assign_ticket_number = kktix_assign_ticket_number(driver, ticket_number, pass_1_seat_remaining_enable, kktix_area_auto_select_mode, kktix_area_keyword_1, kktix_area_keyword_1_and) if not is_assign_ticket_number: - is_assign_ticket_number = kktix_assign_ticket_number(driver, ticket_number, kktix_area_auto_select_mode, kktix_area_keyword_2, kktix_area_keyword_2_and) + is_assign_ticket_number = kktix_assign_ticket_number(driver, ticket_number, pass_1_seat_remaining_enable, kktix_area_auto_select_mode, kktix_area_keyword_2, kktix_area_keyword_2_and) if is_assign_ticket_number: break #print('is_assign_ticket_number:', is_assign_ticket_number) @@ -2570,7 +2600,7 @@ def kktix_reg_new_main(driver, answer_index, is_finish_checkbox_click, config_di auto_press_next_step_button = config_dict["kktix"]["auto_press_next_step_button"] if auto_press_next_step_button: if is_finish_checkbox_click: - is_do_press_next_button = kktix_double_check_all_text_value(driver, ticket_number) + is_do_press_next_button = kktix_double_check_all_text_value(driver, ticket_number_str) else: print("still unable to assign checkbox as selected.") diff --git a/settings.json b/settings.json index 22f2b1f..191a1a1 100644 --- a/settings.json +++ b/settings.json @@ -1 +1 @@ -{"tixcraft": {"pass_1_seat_remaining": true, "area_auto_select": {"enable": true, "area_keyword": "", "mode": "from top to bottom", "area_keyword_4": "", "area_keyword_1": "", "area_keyword_2": "", "area_keyword_3": ""}, "auto_reload_coming_soon_page": true, "date_auto_select": {"enable": true, "date_keyword": "", "mode": "from top to bottom"}, "pass_date_is_sold_out": true}, "homepage1": "https://kktix.com", "language": "\u7e41\u9ad4\u4e2d\u6587", "homepage2": "https://tixcraft.com", "kktix": {"auto_guess_options": true, "answer_dictionary": "", "area_keyword": "", "auto_press_next_step_button": true, "area_mode": "from top to bottom", "auto_fill_ticket_number": true, "auto_fill_ticket_price": "$1,500", "date_keyword": ""}, "facebook_account": "", "browser1": "chrome", "browser2": "firefox", "debug": false, "ticket_number": 2, "homepage": "https://kktix.com", "browser": "chrome", "advanced": {"play_captcha_sound": {"enable": true, "filename": "ding-dong.wav"}, "facebook_account": "", "adblock_plus_enable": false}} \ No newline at end of file +{"homepage": "https://tixcraft.com", "browser": "chrome", "language": "\u7e41\u9ad4\u4e2d\u6587", "ticket_number": 2, "pass_1_seat_remaining": true, "kktix": {"auto_press_next_step_button": true, "auto_fill_ticket_number": true, "area_mode": "from top to bottom", "area_keyword_1": "", "area_keyword_1_and": "", "area_keyword_2": "", "area_keyword_2_and": "", "auto_guess_options": true}, "tixcraft": {"date_auto_select": {"enable": true, "date_keyword": "", "mode": "from top to bottom"}, "area_auto_select": {"enable": true, "area_keyword_1": "", "area_keyword_2": "", "area_keyword_3": "", "area_keyword_4": "", "mode": "from top to bottom"}, "pass_date_is_sold_out": false, "auto_reload_coming_soon_page": true}, "advanced": {"play_captcha_sound": {"enable": true, "filename": "ding-dong.wav"}, "facebook_account": "", "adblock_plus_enable": false}, "debug": false} \ No newline at end of file diff --git a/settings.py b/settings.py index 964f4a2..7e95aaa 100644 --- a/settings.py +++ b/settings.py @@ -19,7 +19,7 @@ import json import webbrowser import pyperclip -CONST_APP_VERSION = u"MaxBot (2022.11.22)" +CONST_APP_VERSION = u"MaxBot (2022.11.24)" CONST_FROM_TOP_TO_BOTTOM = u"from top to bottom" CONST_FROM_BOTTOM_TO_TOP = u"from bottom to top" @@ -257,6 +257,7 @@ def get_default_config(): config_dict["browser"] = "chrome" config_dict["language"] = "English" config_dict["ticket_number"] = 2 + config_dict["pass_1_seat_remaining"] = True config_dict['kktix']={} config_dict["kktix"]["auto_press_next_step_button"] = True @@ -282,7 +283,6 @@ def get_default_config(): config_dict["tixcraft"]["date_auto_select"]["mode"] = CONST_SELECT_ORDER_DEFAULT config_dict["tixcraft"]["area_auto_select"]["mode"] = CONST_SELECT_ORDER_DEFAULT - config_dict["tixcraft"]["pass_1_seat_remaining"] = True config_dict["tixcraft"]["pass_date_is_sold_out"] = False config_dict["tixcraft"]["auto_reload_coming_soon_page"] = True @@ -327,6 +327,7 @@ def btn_save_act(slience_mode=False): global combo_browser global combo_language global combo_ticket_number + global chk_state_pass_1_seat_remaining global chk_state_auto_press_next_step_button global chk_state_auto_fill_ticket_number @@ -350,7 +351,6 @@ def btn_save_act(slience_mode=False): global combo_date_auto_select_mode global combo_area_auto_select_mode - global chk_state_pass_1_seat_remaining global chk_state_pass_date_is_sold_out global chk_state_auto_reload_coming_soon_page @@ -390,6 +390,8 @@ def btn_save_act(slience_mode=False): config_dict["ticket_number"] = int(combo_ticket_number.get().strip()) if is_all_data_correct: + config_dict["pass_1_seat_remaining"] = bool(chk_state_pass_1_seat_remaining.get()) + config_dict["kktix"]["auto_press_next_step_button"] = bool(chk_state_auto_press_next_step_button.get()) config_dict["kktix"]["auto_fill_ticket_number"] = bool(chk_state_auto_fill_ticket_number.get()) config_dict["kktix"]["area_mode"] = combo_kktix_area_mode.get().strip() @@ -413,7 +415,6 @@ def btn_save_act(slience_mode=False): config_dict["tixcraft"]["date_auto_select"]["mode"] = combo_date_auto_select_mode.get().strip() config_dict["tixcraft"]["area_auto_select"]["mode"] = combo_area_auto_select_mode.get().strip() - config_dict["tixcraft"]["pass_1_seat_remaining"] = bool(chk_state_pass_1_seat_remaining.get()) config_dict["tixcraft"]["pass_date_is_sold_out"] = bool(chk_state_pass_date_is_sold_out.get()) config_dict["tixcraft"]["auto_reload_coming_soon_page"] = bool(chk_state_auto_reload_coming_soon_page.get()) @@ -526,6 +527,9 @@ def btn_help_clicked(): def btn_copy_clicked(): pyperclip.copy(CONST_ADBLOCK_PLUS_ADVANCED_FILTER_DEFAULT) +def callbackTicketNumberOnChange(event): + showHidePass1SeatRemaining() + def callbackLanguageOnChange(event): applyNewLanguage() @@ -552,6 +556,7 @@ def applyNewLanguage(): global lbl_browser global lbl_language global lbl_ticket_number + global lbl_pass_1_seat_remaining # for kktix global lbl_auto_press_next_step_button @@ -573,17 +578,17 @@ def applyNewLanguage(): global lbl_area_keyword_2 global lbl_area_keyword_3 global lbl_area_keyword_4 - global lbl_pass_1_seat_remaining global lbl_pass_date_is_sold_out global lbl_auto_reload_coming_soon_page # for checkbox + global chk_pass_1_seat_remaining + global chk_auto_press_next_step_button global chk_auto_fill_ticket_number global chk_auto_guess_options global chk_date_auto_select global chk_area_auto_select - global chk_pass_1_seat_remaining global chk_pass_date_is_sold_out global chk_auto_reload_coming_soon_page global chk_play_captcha_sound @@ -604,6 +609,7 @@ def applyNewLanguage(): lbl_browser.config(text=translate[language_code]["browser"]) lbl_language.config(text=translate[language_code]["language"]) lbl_ticket_number.config(text=translate[language_code]["ticket_number"]) + lbl_pass_1_seat_remaining.config(text=translate[language_code]["pass_1_seat_remaining"]) lbl_auto_press_next_step_button.config(text=translate[language_code]["auto_press_next_step_button"]) lbl_auto_fill_ticket_number.config(text=translate[language_code]["auto_fill_ticket_number"]) @@ -622,16 +628,15 @@ def applyNewLanguage(): lbl_area_keyword_2.config(text=translate[language_code]["area_keyword_2"]) lbl_area_keyword_3.config(text=translate[language_code]["area_keyword_3"]) lbl_area_keyword_4.config(text=translate[language_code]["area_keyword_4"]) - lbl_pass_1_seat_remaining.config(text=translate[language_code]["pass_1_seat_remaining"]) lbl_pass_date_is_sold_out.config(text=translate[language_code]["pass_date_is_sold_out"]) lbl_auto_reload_coming_soon_page.config(text=translate[language_code]["auto_reload_coming_soon_page"]) + chk_pass_1_seat_remaining.config(text=translate[language_code]["enable"]) chk_auto_press_next_step_button.config(text=translate[language_code]["enable"]) chk_auto_fill_ticket_number.config(text=translate[language_code]["enable"]) chk_auto_guess_options.config(text=translate[language_code]["enable"]) chk_date_auto_select.config(text=translate[language_code]["enable"]) chk_area_auto_select.config(text=translate[language_code]["enable"]) - chk_pass_1_seat_remaining.config(text=translate[language_code]["enable"]) chk_pass_date_is_sold_out.config(text=translate[language_code]["enable"]) chk_auto_reload_coming_soon_page.config(text=translate[language_code]["enable"]) chk_play_captcha_sound.config(text=translate[language_code]["enable"]) @@ -736,6 +741,24 @@ def showHideBlocks(all_layout_visible=False): frame_group_kktix.grid_forget() showHideTixcraftBlocks() + showHidePass1SeatRemaining() + +def showHidePass1SeatRemaining(): + global combo_ticket_number + ticket_number_int = int(combo_ticket_number.get().strip()) + + global pass_1_seat_remaining_index + global lbl_pass_1_seat_remaining + global chk_pass_1_seat_remaining + + if ticket_number_int > 1: + # show. + lbl_pass_1_seat_remaining.grid(column=0, row=pass_1_seat_remaining_index, sticky = E) + chk_pass_1_seat_remaining.grid(column=1, row=pass_1_seat_remaining_index, sticky = W) + else: + # hide + lbl_pass_1_seat_remaining.grid_forget() + chk_pass_1_seat_remaining.grid_forget() # purpose: show detail blocks if master field is enable. def showHideTixcraftBlocks(): @@ -831,7 +854,8 @@ def PreferenctTab(root, config_dict, language_code, UI_PADDING_X): homepage = CONST_HOMEPAGE_DEFAULT browser = "chrome" language = "English" - ticket_number = "2" + ticket_number = 2 + pass_1_seat_remaining_enable = False auto_press_next_step_button = False auto_fill_ticket_number = False @@ -857,7 +881,6 @@ def PreferenctTab(root, config_dict, language_code, UI_PADDING_X): area_keyword_3 = "" area_keyword_4 = "" - pass_1_seat_remaining_enable = False pass_date_is_sold_out_enable = False auto_reload_coming_soon_page_enable = True @@ -871,7 +894,8 @@ def PreferenctTab(root, config_dict, language_code, UI_PADDING_X): # default ticket number # 說明:自動選擇的票數 - ticket_number = str(config_dict["ticket_number"]) + ticket_number = config_dict["ticket_number"] + pass_1_seat_remaining_enable = config_dict["pass_1_seat_remaining"] # for ["kktix"] auto_press_next_step_button = config_dict["kktix"]["auto_press_next_step_button"] @@ -907,7 +931,6 @@ def PreferenctTab(root, config_dict, language_code, UI_PADDING_X): area_keyword_2 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_2"].strip() area_keyword_3 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_3"].strip() area_keyword_4 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_4"].strip() - pass_1_seat_remaining_enable = config_dict["tixcraft"]["pass_1_seat_remaining"] pass_date_is_sold_out_enable = config_dict["tixcraft"]["pass_date_is_sold_out"] auto_reload_coming_soon_page_enable = config_dict["tixcraft"]["auto_reload_coming_soon_page"] @@ -918,6 +941,7 @@ def PreferenctTab(root, config_dict, language_code, UI_PADDING_X): print("browser", browser) print("language", language) print("ticket_number", ticket_number) + print("pass_1_seat_remaining", pass_1_seat_remaining_enable) # for kktix print("==[kktix]==") @@ -943,7 +967,6 @@ def PreferenctTab(root, config_dict, language_code, UI_PADDING_X): print("area_keyword_3", area_keyword_3) print("area_keyword_4", area_keyword_4) - print("pass_1_seat_remaining", pass_1_seat_remaining_enable) print("pass_date_is_sold_out", pass_date_is_sold_out_enable) print("auto_reload_coming_soon_page", auto_reload_coming_soon_page_enable) @@ -1024,9 +1047,27 @@ def PreferenctTab(root, config_dict, language_code, UI_PADDING_X): combo_ticket_number = ttk.Combobox(frame_group_header, state="readonly") combo_ticket_number['values']= ("1","2","3","4","5","6","7","8","9","10","11","12") #combo_ticket_number.current(0) - combo_ticket_number.set(ticket_number) + combo_ticket_number.set(str(ticket_number)) + combo_ticket_number.bind("<>", callbackTicketNumberOnChange) combo_ticket_number.grid(column=1, row=group_row_count, sticky = W) + group_row_count+=1 + + global pass_1_seat_remaining_index + pass_1_seat_remaining_index = group_row_count + + global lbl_pass_1_seat_remaining + lbl_pass_1_seat_remaining = Label(frame_group_header, text=translate[language_code]['pass_1_seat_remaining']) + lbl_pass_1_seat_remaining.grid(column=0, row=group_row_count, sticky = E) + + global chk_state_pass_1_seat_remaining + chk_state_pass_1_seat_remaining = BooleanVar() + chk_state_pass_1_seat_remaining.set(pass_1_seat_remaining_enable) + + global chk_pass_1_seat_remaining + chk_pass_1_seat_remaining = Checkbutton(frame_group_header, text=translate[language_code]['enable'], variable=chk_state_pass_1_seat_remaining) + chk_pass_1_seat_remaining.grid(column=1, row=group_row_count, sticky = W) + frame_group_header.grid(column=0, row=row_count, sticky = W, padx=UI_PADDING_X) row_count+=1 @@ -1314,20 +1355,6 @@ def PreferenctTab(root, config_dict, language_code, UI_PADDING_X): group_row_count+=1 - global lbl_pass_1_seat_remaining - lbl_pass_1_seat_remaining = Label(frame_group_tixcraft, text=translate[language_code]['pass_1_seat_remaining']) - lbl_pass_1_seat_remaining.grid(column=0, row=group_row_count, sticky = E) - - global chk_state_pass_1_seat_remaining - chk_state_pass_1_seat_remaining = BooleanVar() - chk_state_pass_1_seat_remaining.set(pass_1_seat_remaining_enable) - - global chk_pass_1_seat_remaining - chk_pass_1_seat_remaining = Checkbutton(frame_group_tixcraft, text=translate[language_code]['enable'], variable=chk_state_pass_1_seat_remaining) - chk_pass_1_seat_remaining.grid(column=1, row=group_row_count, sticky = W) - - group_row_count+=1 - global lbl_pass_date_is_sold_out lbl_pass_date_is_sold_out = Label(frame_group_tixcraft, text=translate[language_code]['pass_date_is_sold_out']) lbl_pass_date_is_sold_out.grid(column=0, row=group_row_count, sticky = E)