2022-11-19, fix KKTix auto press next button bug.

master
CHUN YU YAO 2022-11-19 06:59:34 +08:00
parent 805bd8c1c9
commit 6289db1993
2 changed files with 684 additions and 642 deletions

View File

@ -39,7 +39,7 @@ warnings.simplefilter('ignore',InsecureRequestWarning)
import ssl import ssl
ssl._create_default_https_context = ssl._create_unverified_context ssl._create_default_https_context = ssl._create_unverified_context
CONST_APP_VERSION = u"MaxBot (2022.11.18)" CONST_APP_VERSION = u"MaxBot (2022.11.19)"
CONST_FROM_TOP_TO_BOTTOM = u"from top to bottom" CONST_FROM_TOP_TO_BOTTOM = u"from top to bottom"
CONST_FROM_BOTTOM_TO_TOP = u"from bottom to top" CONST_FROM_BOTTOM_TO_TOP = u"from bottom to top"
@ -52,8 +52,6 @@ CONT_STRING_1_SEATS_REMAINING = [u'@1 seat(s) remaining',u'剩餘 1@',u'@1 席
driver = None driver = None
homepage = None
browser = None
ticket_number = None ticket_number = None
auto_press_next_step_button = False auto_press_next_step_button = False
@ -81,13 +79,6 @@ kktix_area_auto_select_mode = None
kktix_area_keyword = None kktix_area_keyword = None
kktix_date_keyword = None kktix_date_keyword = None
kktix_answer_dictionary = None
kktix_answer_dictionary_list = None
auto_guess_options = False
debugMode = False
def get_app_root(): def get_app_root():
# 讀取檔案裡的參數值 # 讀取檔案裡的參數值
basis = "" basis = ""
@ -276,38 +267,37 @@ def close_browser_tabs(driver):
def get_driver_by_config(config_dict, driver_type): def get_driver_by_config(config_dict, driver_type):
global driver global driver
global homepage homepage = None
global browser browser = None
global debugMode language = "English"
global ticket_number ticket_number = "2"
global auto_press_next_step_button
global auto_fill_ticket_number
global kktix_area_auto_select_mode
global kktix_area_keyword
global kktix_date_keyword
global kktix_answer_dictionary auto_press_next_step_button = False # default not checked.
global kktix_answer_dictionary_list auto_fill_ticket_number = False # default not checked.
auto_guess_options = False # default not checked.
global auto_guess_options kktix_area_auto_select_mode = ""
global pass_1_seat_remaining_enable kktix_area_keyword = ""
global pass_date_is_sold_out_enable kktix_date_keyword = ""
global auto_reload_coming_soon_page_enable
global area_keyword_1 pass_1_seat_remaining_enable = False # default not checked.
global area_keyword_2 pass_date_is_sold_out_enable = False # default not checked.
global area_keyword_3 auto_reload_coming_soon_page_enable = True # default checked.
global area_keyword_4
global date_auto_select_enable area_keyword_1 = ""
global date_auto_select_mode area_keyword_2 = ""
area_keyword_3 = ""
area_keyword_4 = ""
global date_keyword date_keyword = ""
global area_auto_select_enable date_auto_select_enable = None
global area_auto_select_mode date_auto_select_mode = ""
global debugMode area_auto_select_enable = None
area_auto_select_mode = ""
debugMode = False
if not config_dict is None: if not config_dict is None:
# read config. # read config.
@ -350,14 +340,7 @@ def get_driver_by_config(config_dict, driver_type):
kktix_date_keyword = kktix_date_keyword.strip() kktix_date_keyword = kktix_date_keyword.strip()
# disable password brute force attack # disable password brute force attack
if 'answer_dictionary' in config_dict["kktix"]: # PS: because of the question is always variable.
kktix_answer_dictionary = config_dict["kktix"]["answer_dictionary"]
if kktix_answer_dictionary is None:
kktix_answer_dictionary = ""
kktix_answer_dictionary = kktix_answer_dictionary.strip()
if len(kktix_answer_dictionary) > 0:
kktix_answer_dictionary_list = kktix_answer_dictionary.split(',')
if 'auto_guess_options' in config_dict["kktix"]: if 'auto_guess_options' in config_dict["kktix"]:
auto_guess_options = config_dict["kktix"]["auto_guess_options"] auto_guess_options = config_dict["kktix"]["auto_guess_options"]
@ -429,7 +412,6 @@ def get_driver_by_config(config_dict, driver_type):
print("auto_fill_ticket_number", auto_fill_ticket_number) print("auto_fill_ticket_number", auto_fill_ticket_number)
print("kktix_area_keyword", kktix_area_keyword) print("kktix_area_keyword", kktix_area_keyword)
print("kktix_date_keyword", kktix_date_keyword) print("kktix_date_keyword", kktix_date_keyword)
print("kktix_answer_dictionary", kktix_answer_dictionary)
print("auto_guess_options", auto_guess_options) print("auto_guess_options", auto_guess_options)
# for tixcraft # for tixcraft
@ -861,8 +843,6 @@ def get_answer_list_by_question(captcha_text_div_text):
my_answer_delimitor = maybe_delimitor my_answer_delimitor = maybe_delimitor
#print(u"my_answer_delimitor:", my_answer_delimitor) #print(u"my_answer_delimitor:", my_answer_delimitor)
# try all possible options. # try all possible options.
tmp_text = captcha_text_div_text tmp_text = captcha_text_div_text
tmp_text = tmp_text.replace(u' ',u' ') tmp_text = tmp_text.replace(u' ',u' ')
@ -1000,7 +980,7 @@ def tixcraft_redirect(driver, url):
def tixcraft_date_auto_select(driver, url, config_dict): def tixcraft_date_auto_select(driver, url, config_dict):
# read config. # read config.
date_auto_select_mode = config_dict["tixcraft"]["date_auto_select"]["mode"] date_auto_select_mode = config_dict["tixcraft"]["date_auto_select"]["mode"]
date_keyword = config_dict["tixcraft"]["date_auto_select"]["date_keyword"] date_keyword = config_dict["tixcraft"]["date_auto_select"]["date_keyword"].strip()
pass_date_is_sold_out_enable = config_dict["tixcraft"]["pass_date_is_sold_out"] 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"] auto_reload_coming_soon_page_enable = config_dict["tixcraft"]["auto_reload_coming_soon_page"]
@ -1155,11 +1135,8 @@ def tixcraft_date_auto_select(driver, url, config_dict):
# areas # areas
# PS: areas will be None, if length equals zero. # PS: areas will be None, if length equals zero.
def get_tixcraft_target_area(el, area_keyword, area_auto_select_mode, pass_1_seat_remaining_enable): def get_tixcraft_target_area(el, area_keyword, area_auto_select_mode, pass_1_seat_remaining_enable):
debugMode = True show_debug_message = True # debug.
debugMode = False # for online show_debug_message = False # online
if debugMode:
print("testing keyword:", area_keyword)
is_need_refresh = False is_need_refresh = False
areas = None areas = None
@ -1223,7 +1200,7 @@ def get_tixcraft_target_area(el, area_keyword, area_auto_select_mode, pass_1_sea
is_append_this_row = True is_append_this_row = True
if is_append_this_row: if is_append_this_row:
if debugMode: if show_debug_message:
print("pass_1_seat_remaining_enable:", pass_1_seat_remaining_enable) print("pass_1_seat_remaining_enable:", pass_1_seat_remaining_enable)
if pass_1_seat_remaining_enable: if pass_1_seat_remaining_enable:
area_item_font_el = None area_item_font_el = None
@ -1235,12 +1212,12 @@ def get_tixcraft_target_area(el, area_keyword, area_auto_select_mode, pass_1_sea
if font_el_text is None: if font_el_text is None:
font_el_text = "" font_el_text = ""
font_el_text = "@%s@" % (font_el_text) font_el_text = "@%s@" % (font_el_text)
if debugMode: if show_debug_message:
print('font tag text:', font_el_text) print('font tag text:', font_el_text)
pass pass
for check_item in CONT_STRING_1_SEATS_REMAINING: for check_item in CONT_STRING_1_SEATS_REMAINING:
if check_item in font_el_text: if check_item in font_el_text:
if debugMode: if show_debug_message:
print("match pass 1 seats remaining 1 full text:", row_text) print("match pass 1 seats remaining 1 full text:", row_text)
print("match pass 1 seats remaining 2 font text:", font_el_text) print("match pass 1 seats remaining 2 font text:", font_el_text)
is_append_this_row = False is_append_this_row = False
@ -1251,7 +1228,7 @@ def get_tixcraft_target_area(el, area_keyword, area_auto_select_mode, pass_1_sea
#print("find font text in a tag fail:", exc) #print("find font text in a tag fail:", exc)
pass pass
if debugMode: if show_debug_message:
print("is_append_this_row:", is_append_this_row) print("is_append_this_row:", is_append_this_row)
if is_append_this_row: if is_append_this_row:
@ -1260,7 +1237,7 @@ def get_tixcraft_target_area(el, area_keyword, area_auto_select_mode, pass_1_sea
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM: if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
print("only need first item, break area list loop.") print("only need first item, break area list loop.")
break break
if debugMode: if show_debug_message:
print("row_text:" + row_text) print("row_text:" + row_text)
print("match:" + area_keyword) print("match:" + area_keyword)
@ -1281,10 +1258,10 @@ def tixcraft_area_auto_select(driver, url, config_dict):
area_auto_select_mode = config_dict["tixcraft"]["area_auto_select"]["mode"] 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["tixcraft"]["pass_1_seat_remaining"]
debugMode = True show_debug_message = True # debug.
debugMode = False # for online show_debug_message = False # online
if debugMode: if show_debug_message:
print("area_keyword_1, area_keyword_2:", area_keyword_1, area_keyword_2) print("area_keyword_1, area_keyword_2:", area_keyword_1, area_keyword_2)
print("area_keyword_3, area_keyword_4:", area_keyword_3, area_keyword_4) print("area_keyword_3, area_keyword_4:", area_keyword_3, area_keyword_4)
@ -1299,40 +1276,40 @@ def tixcraft_area_auto_select(driver, url, config_dict):
if el is not None: if el is not None:
is_need_refresh, areas = get_tixcraft_target_area(el, area_keyword_1, area_auto_select_mode, pass_1_seat_remaining_enable) is_need_refresh, areas = get_tixcraft_target_area(el, area_keyword_1, area_auto_select_mode, pass_1_seat_remaining_enable)
if debugMode: if show_debug_message:
print("is_need_refresh for keyword1:", is_need_refresh) print("is_need_refresh for keyword1:", is_need_refresh)
if is_need_refresh: if is_need_refresh:
if areas is None: if areas is None:
if debugMode: if show_debug_message:
print("use area keyword #2", area_keyword_2) print("use area keyword #2", area_keyword_2)
# only when keyword#2 filled to query. # only when keyword#2 filled to query.
if len(area_keyword_2) > 0 : if len(area_keyword_2) > 0 :
is_need_refresh, areas = get_tixcraft_target_area(el, area_keyword_2, area_auto_select_mode, pass_1_seat_remaining_enable) is_need_refresh, areas = get_tixcraft_target_area(el, area_keyword_2, area_auto_select_mode, pass_1_seat_remaining_enable)
if debugMode: if show_debug_message:
print("is_need_refresh for keyword2:", is_need_refresh) print("is_need_refresh for keyword2:", is_need_refresh)
if is_need_refresh: if is_need_refresh:
if areas is None: if areas is None:
if debugMode: if show_debug_message:
print("use area keyword #3", area_keyword_3) print("use area keyword #3", area_keyword_3)
# only when keyword#3 filled to query. # only when keyword#3 filled to query.
if len(area_keyword_3) > 0 : if len(area_keyword_3) > 0 :
is_need_refresh, areas = get_tixcraft_target_area(el, area_keyword_3, area_auto_select_mode, pass_1_seat_remaining_enable) is_need_refresh, areas = get_tixcraft_target_area(el, area_keyword_3, area_auto_select_mode, pass_1_seat_remaining_enable)
if debugMode: if show_debug_message:
print("is_need_refresh for keyword3:", is_need_refresh) print("is_need_refresh for keyword3:", is_need_refresh)
if is_need_refresh: if is_need_refresh:
if areas is None: if areas is None:
if debugMode: if show_debug_message:
print("use area keyword #4", area_keyword_4) print("use area keyword #4", area_keyword_4)
# only when keyword#4 filled to query. # only when keyword#4 filled to query.
if len(area_keyword_4) > 0 : if len(area_keyword_4) > 0 :
is_need_refresh, areas = get_tixcraft_target_area(el, area_keyword_4, area_auto_select_mode, pass_1_seat_remaining_enable) is_need_refresh, areas = get_tixcraft_target_area(el, area_keyword_4, area_auto_select_mode, pass_1_seat_remaining_enable)
if debugMode: if show_debug_message:
print("is_need_refresh for keyword4:", is_need_refresh) print("is_need_refresh for keyword4:", is_need_refresh)
area_target = None area_target = None
@ -1838,16 +1815,25 @@ def kktix_input_captcha_text(captcha_inner_div, captcha_password_string, force_o
ret = False ret = False
if captcha_inner_div is not None and captcha_password_string is not None: captcha_password_text = None
try: try:
if show_debug_message:
print("found captcha div")
captcha_password_text = captcha_inner_div.find_element(By.TAG_NAME, "input") captcha_password_text = captcha_inner_div.find_element(By.TAG_NAME, "input")
if not captcha_password_text is None:
if show_debug_message: if show_debug_message:
print("found input field") print("found input field")
except Exception as exc:
pass
if not captcha_password_text is None:
inputed_captcha_text = ""
try:
inputed_captcha_text = captcha_password_text.get_attribute('value') inputed_captcha_text = captcha_password_text.get_attribute('value')
except Exception as exc:
pass
if inputed_captcha_text is None:
inputed_captcha_text = ""
if captcha_password_string is not None:
try:
if force_overwrite: if force_overwrite:
captcha_password_text.send_keys(captcha_password_string) captcha_password_text.send_keys(captcha_password_string)
print("send captcha keys:" + captcha_password_string) print("send captcha keys:" + captcha_password_string)
@ -1860,9 +1846,19 @@ def kktix_input_captcha_text(captcha_inner_div, captcha_password_string, force_o
ret = True ret = True
except Exception as exc: except Exception as exc:
if show_debug_message: if show_debug_message:
print("find kktix_input_captcha_text Exception:") print("kktix_input_captcha_text Exception:")
print(exc) print(exc)
pass pass
else:
# do focus()
if len(inputed_captcha_text) == 0:
try:
print("focus() captcha to input.")
captcha_password_text.click()
time.sleep(1)
# let user to input answer, bot sleep 1 second.
except Exception as exc:
pass
return ret return ret
@ -1891,7 +1887,6 @@ def kktix_travel_price_list(driver, kktix_area_keyword, kktix_date_keyword):
else: else:
print("find ticket-price span fail") print("find ticket-price span fail")
is_travel_interrupted = False is_travel_interrupted = False
if price_list_count > 0: if price_list_count > 0:
@ -2134,26 +2129,44 @@ def kktix_check_agree_checkbox(driver):
person_agree_terms_checkbox = None person_agree_terms_checkbox = None
try: try:
person_agree_terms_checkbox = driver.find_element(By.ID, 'person_agree_terms') person_agree_terms_checkbox = driver.find_element(By.ID, 'person_agree_terms')
if person_agree_terms_checkbox is not None:
if person_agree_terms_checkbox.is_enabled():
#print("find person_agree_terms checkbox")
if not person_agree_terms_checkbox.is_selected():
#print('send check to checkbox')
person_agree_terms_checkbox.click()
is_finish_checkbox_click = True
else:
#print('checked')
is_finish_checkbox_click = True
pass
else:
is_need_refresh = True
else:
is_need_refresh = True
print("find person_agree_terms checkbox fail")
except Exception as exc: except Exception as exc:
print("find person_agree_terms checkbox Exception") print("find person_agree_terms checkbox Exception")
pass pass
if person_agree_terms_checkbox is not None:
is_visible = False
try:
if person_agree_terms_checkbox.is_enabled():
is_visible = True
except Exception as exc:
pass
if is_visible:
is_checkbox_checked = False
try:
if person_agree_terms_checkbox.is_selected():
is_checkbox_checked = True
except Exception as exc:
pass
if not is_checkbox_checked:
#print('send check to checkbox')
try:
person_agree_terms_checkbox.click()
is_finish_checkbox_click = True
except Exception as exc:
pass
else:
#print('checked')
is_finish_checkbox_click = True
else:
is_need_refresh = True
else:
is_need_refresh = True
if is_need_refresh:
print("find person_agree_terms checkbox fail, do refresh page.")
return is_need_refresh, is_finish_checkbox_click return is_need_refresh, is_finish_checkbox_click
def kktix_check_register_status(url): def kktix_check_register_status(url):
@ -2208,53 +2221,16 @@ def kktix_check_register_status(url):
#print("registerStatus:", registerStatus) #print("registerStatus:", registerStatus)
return registerStatus return registerStatus
def kktix_reg_new_main(url, answer_index, registrationsNewApp_div, is_finish_checkbox_click, config_dict): def kktix_reg_new_captcha(driver, captcha_inner_div, auto_guess_options):
# read config.
auto_press_next_step_button = config_dict["kktix"]["auto_press_next_step_button"]
auto_fill_ticket_number = config_dict["kktix"]["auto_fill_ticket_number"]
ticket_number = str(config_dict["ticket_number"])
kktix_area_keyword = config_dict["kktix"]["area_keyword"].strip()
kktix_date_keyword = config_dict["kktix"]["date_keyword"].strip()
kktix_area_auto_select_mode = config_dict["kktix"]["area_mode"]
auto_guess_options = config_dict["kktix"]["auto_guess_options"]
show_debug_message = True # debug. show_debug_message = True # debug.
show_debug_message = False # online show_debug_message = False # online
#---------------------------
# part 2: ticket number
#---------------------------
is_assign_ticket_number = False
if auto_fill_ticket_number:
for retry_index in range(8):
is_assign_ticket_number = kktix_assign_ticket_number(driver, ticket_number, kktix_area_auto_select_mode, kktix_area_keyword, kktix_date_keyword)
if is_assign_ticket_number:
break
#print('is_assign_ticket_number:', is_assign_ticket_number)
#---------------------------
# part 3: captcha
#---------------------------
# is captcha div appear
is_captcha_appear = False
is_captcha_appear_and_filled_password = False
# try to auto answer options. # try to auto answer options.
answer_list = None answer_list = None
is_need_keep_symbol = False is_need_keep_symbol = False
my_answer_delimitor = "" my_answer_delimitor = ""
captcha_inner_div = None captcha_password_string = None
try:
captcha_inner_div = driver.find_element(By.CSS_SELECTOR, '.custom-captcha-inner')
except Exception as exc:
#print(exc)
#print("find captcha_inner_div fail")
pass
if captcha_inner_div is not None:
if show_debug_message:
print("found captcha_inner_div layor.")
captcha_text_div = None captcha_text_div = None
try: try:
@ -2264,12 +2240,8 @@ def kktix_reg_new_main(url, answer_index, registrationsNewApp_div, is_finish_che
print("find p tag(captcha_text_div) fail") print("find p tag(captcha_text_div) fail")
print(exc) print(exc)
captcha_password_string = None
captcha_text_div_text = None captcha_text_div_text = None
if captcha_text_div is not None: if captcha_text_div is not None:
is_captcha_appear = True
try: try:
captcha_text_div_text = captcha_text_div.text captcha_text_div_text = captcha_text_div.text
except Exception as exc: except Exception as exc:
@ -2329,7 +2301,6 @@ def kktix_reg_new_main(url, answer_index, registrationsNewApp_div, is_finish_che
captcha_password_string = find_between(captcha_text_div_text, u"", u"") captcha_password_string = find_between(captcha_text_div_text, u"", u"")
#print("find captcha text:" , captcha_password_string) #print("find captcha text:" , captcha_password_string)
# 請回答下列問題,請在下方空格輸入DELIGHT請以半形輸入法作答大小寫需要一模一樣 # 請回答下列問題,請在下方空格輸入DELIGHT請以半形輸入法作答大小寫需要一模一樣
if captcha_password_string is None: if captcha_password_string is None:
# clean stop word # clean stop word
@ -2352,16 +2323,6 @@ def kktix_reg_new_main(url, answer_index, registrationsNewApp_div, is_finish_che
captcha_password_string = captcha_password_string.replace(u'',u'') captcha_password_string = captcha_password_string.replace(u'',u'')
captcha_password_string = captcha_password_string.replace(u'文字',u'') captcha_password_string = captcha_password_string.replace(u'文字',u'')
#captcha_text_div_text = "請問下列哪張專輯為林俊傑出道專輯?(1A)飛行者(2B)礫行者(3C)樂行者(請以半形輸入法作答,大小寫需要一模一樣,範例:1A"
#captcha_text_div_text = "以下哪個「不是」正確的林俊傑與其他藝人合唱的歌曲組合?(選項為歌名/合作藝人 ,請以半形輸入法作答選項,大小寫需要一模一樣,範例:jju 選項: (jjz)I am alive/Jason Mraz (jjy)友人說/張懷秋 (jjx)豆漿油條/A-Sa蔡卓妍 (jjw)黑暗騎士/五月天阿信 (jjv)手心的薔薇/G.E.M鄧紫棋"
# for test.
#captcha_password_string = None
#captcha_text_div_text = u"以下哪個「不是」正確的林俊傑與其他藝人合唱的歌曲組合?(選項為歌名/合作藝人 ,請以半形輸入法作答選項,大小寫需要一模一樣,範例:jju 選項: (jja)小酒窩/A-Sa蔡卓妍 (jjb)被風吹過的夏天/金莎 (jjc)友人說/張懷秋 (jjd)全面開戰/五月天阿信 (jje)小說/阿杜, (0118eveconcert)0118eveconcert"
#captcha_text_div_text = u"以下哪個「不是」正確的林俊傑與其他藝人合唱的歌曲組合?(選項為歌名/合作藝人 ,請以半形輸入法作答選項,大小寫需要一模一樣,範例:jju 選項: (jja)小酒窩/A-Sa蔡卓妍 (jjb)被風吹過的夏天/金莎 (jjc)友人說/張懷秋 (jjd)全面開戰/五月天阿信 (jje)小說/阿杜"
#captcha_text_div_text = u"以下哪個「不是」正確的林俊傑與其他藝人合唱的歌曲組合?(選項為歌名/合作藝人 ,請以半形輸入法作答選項,大小寫需要一模一樣,範例:jju 選項: (jja)小酒窩/A-Sa蔡卓妍 (jjb)被風吹過的夏天/金莎 (jjc)友人說/張懷秋 (jjd)全面開戰/五月天阿信 (jje)小說/阿杜"
#captcha_text_div_text = u"請問《龍的傳人2060》演唱會是以下哪位藝人的演出請以半形輸入法作答大小寫需要一模一樣範例B2A1.周杰倫 B2.林俊傑 C3.張學友 D4.王力宏 4:4"
# parse '演出日期' # parse '演出日期'
is_need_parse_web_datetime = False is_need_parse_web_datetime = False
# '半形阿拉伯數字' & '半形數字' # '半形阿拉伯數字' & '半形數字'
@ -2629,76 +2590,137 @@ def kktix_reg_new_main(url, answer_index, registrationsNewApp_div, is_finish_che
# no need guess options. # no need guess options.
pass pass
return captcha_password_string, answer_list, my_answer_delimitor
def kktix_double_check_all_text_value(driver, ticket_number):
is_do_press_next_button = False
# double check ticket input textbox.
ticket_price_input_list = None
try:
# PS: unable directly access text's value attribute via css selector or xpath on KKTix!
my_css_selector = "input[type='text']"
#print("my_css_selector:", my_css_selector)
ticket_price_input_list = driver.find_elements(By.CSS_SELECTOR, my_css_selector)
except Exception as exc:
pass
if ticket_price_input_list is not None:
#print("bingo, found one of ticket number textbox.")
row_index = 0
for ticket_price_input in ticket_price_input_list:
row_index += 1
current_ticket_number = ""
try:
current_ticket_number = str(ticket_price_input.get_attribute('value')).strip()
except Exception as exc:
pass
if current_ticket_number is None:
current_ticket_number = ""
if len(current_ticket_number) > 0:
#print(row_index, "current_ticket_number:", current_ticket_number)
if current_ticket_number == ticket_number:
#print("bingo, match target ticket number.")
# ONLY, this case to auto press next button.
is_do_press_next_button = True
break
return is_do_press_next_button
def kktix_reg_new_main(driver, answer_index, is_finish_checkbox_click, config_dict):
show_debug_message = True # debug.
show_debug_message = False # online
# part 1: check div.
registrationsNewApp_div = None
try:
registrationsNewApp_div = driver.find_element(By.CSS_SELECTOR, '#registrationsNewApp')
except Exception as exc:
pass
#print("find input fail:", exc)
# part 2: assign ticket number
ticket_number = str(config_dict["ticket_number"])
is_assign_ticket_number = False
if not registrationsNewApp_div is None:
kktix_area_auto_select_mode = config_dict["kktix"]["area_mode"]
kktix_area_keyword = config_dict["kktix"]["area_keyword"].strip()
kktix_date_keyword = config_dict["kktix"]["date_keyword"].strip()
for retry_index in range(3):
is_assign_ticket_number = kktix_assign_ticket_number(driver, ticket_number, kktix_area_auto_select_mode, kktix_area_keyword, kktix_date_keyword)
if is_assign_ticket_number:
break
#print('is_assign_ticket_number:', is_assign_ticket_number)
# part 3: captcha
is_captcha_appear = False
is_captcha_appear_and_filled_password = False
answer_list = None
if is_assign_ticket_number:
# TODO: in guess options mode, no need to travel div again.
captcha_inner_div = None
try:
captcha_inner_div = driver.find_element(By.CSS_SELECTOR, '.custom-captcha-inner')
except Exception as exc:
pass
captcha_password_string = None
if captcha_inner_div is not None:
is_captcha_appear = True
if show_debug_message:
print("found captcha_inner_div layor.")
auto_guess_options = config_dict["kktix"]["auto_guess_options"]
captcha_password_string, answer_list, my_answer_delimitor = kktix_reg_new_captcha(driver, captcha_inner_div, auto_guess_options)
# final run.
if captcha_password_string is not None:
# password is not None, try to send. # password is not None, try to send.
# password is None, focus to input.
if kktix_input_captcha_text(captcha_inner_div, captcha_password_string): if kktix_input_captcha_text(captcha_inner_div, captcha_password_string):
is_captcha_appear_and_filled_password = True is_captcha_appear_and_filled_password = True
if auto_press_next_step_button: if show_debug_message:
# pass switch check. print("is_captcha_appear:", is_captcha_appear)
print("is_captcha_appear_and_filled_password:", is_captcha_appear_and_filled_password)
#print("is_assign_ticket_number", is_assign_ticket_number) # retry check agree checkbox again.
if is_assign_ticket_number:
# must input the ticket number correct.
#print("is_captcha_appear:", is_captcha_appear)
#print("is_captcha_appear_and_filled_password:", is_captcha_appear_and_filled_password)
# must ensure checkbox has been checked.
if not is_finish_checkbox_click: if not is_finish_checkbox_click:
for retry_i in range(5):
# retry again.
is_need_refresh, is_finish_checkbox_click = kktix_check_agree_checkbox(driver) is_need_refresh, is_finish_checkbox_click = kktix_check_agree_checkbox(driver)
time.sleep(0.1)
if is_finish_checkbox_click:
break
if not is_captcha_appear: is_do_press_next_button = False
# without captcha. if is_assign_ticket_number:
# normal mode. auto_press_next_step_button = config_dict["kktix"]["auto_press_next_step_button"]
#print("# normal mode.") if auto_press_next_step_button:
if is_finish_checkbox_click: if is_finish_checkbox_click:
click_ret = kktix_press_next_button(driver) is_do_press_next_button = kktix_double_check_all_text_value(driver, ticket_number)
if not click_ret:
print("press next button fail, retry again.")
click_ret = kktix_press_next_button(driver)
else: else:
#print("press next button successfully.") print("still unable to assign checkbox as selected.")
pass
else: if show_debug_message:
print("unable to assign checkbox value") print("is_do_press_next_button:", is_do_press_next_button)
if is_do_press_next_button:
if not is_captcha_appear:
click_ret = kktix_press_next_button(driver)
else: else:
if is_captcha_appear_and_filled_password: if is_captcha_appear_and_filled_password:
# for easy guest mode, we can fill the password correct. # for easy guest mode, we can fill the password correct.
#print("for easy guest mode, we can fill the password correct.") #print("for easy guest mode, we can fill the password correct.")
if is_finish_checkbox_click:
click_ret = kktix_press_next_button(driver) click_ret = kktix_press_next_button(driver)
if not click_ret:
print("press next button fail, retry again.")
click_ret = kktix_press_next_button(driver)
else:
#print("press next button successfully.")
pass
else:
print("unable to assign checkbox value")
else: else:
# not is easy guest mode. # not is easy guest mode.
#print("# not is easy guest mode.") #print("# not is easy guest mode.")
# password force brute # merge with password dictionary, so need remove duplicate list
if answer_list is None: # PS: now, there are no password dictionary.
if not kktix_answer_dictionary_list is None:
if len(kktix_answer_dictionary_list) > 0:
answer_list = kktix_answer_dictionary_list
# remove duplicate list
if not answer_list is None: if not answer_list is None:
if len(answer_list) > 1: if len(answer_list) > 1:
unique = [x for i, x in enumerate(answer_list) if answer_list.index(x) == i] unique = [x for i, x in enumerate(answer_list) if answer_list.index(x) == i]
answer_list = unique answer_list = unique
# start to try # start to try answer.
if not answer_list is None: if not answer_list is None:
# for popular event # for popular event
if len(answer_list) > 0: if len(answer_list) > 0:
@ -2761,22 +2783,12 @@ def kktix_reg_new(driver, url, answer_index, kktix_register_status_last, config_
if not is_need_refresh: if not is_need_refresh:
is_need_refresh, is_finish_checkbox_click = kktix_check_agree_checkbox(driver) is_need_refresh, is_finish_checkbox_click = kktix_check_agree_checkbox(driver)
if not is_need_refresh:
if not is_finish_checkbox_click: if not is_finish_checkbox_click:
# retry again. # retry again.
is_need_refresh, is_finish_checkbox_click = kktix_check_agree_checkbox(driver) is_need_refresh, is_finish_checkbox_click = kktix_check_agree_checkbox(driver)
#print('check agree_terms_checkbox, is_need_refresh:',is_need_refresh) #print('check agree_terms_checkbox, is_need_refresh:',is_need_refresh)
# check is able to buy.
registrationsNewApp_div = None
el_list = None
if not is_need_refresh:
try:
registrationsNewApp_div = driver.find_element(By.CSS_SELECTOR, '#registrationsNewApp')
except Exception as exc:
pass
#print("find input fail:", exc)
if is_need_refresh: if is_need_refresh:
try: try:
print("try to refresh page...") print("try to refresh page...")
@ -2789,7 +2801,10 @@ def kktix_reg_new(driver, url, answer_index, kktix_register_status_last, config_
answer_index = -1 answer_index = -1
registerStatus = None registerStatus = None
else: else:
answer_index = kktix_reg_new_main(url, answer_index, registrationsNewApp_div, is_finish_checkbox_click, config_dict) # check is able to buy.
auto_fill_ticket_number = config_dict["kktix"]["auto_fill_ticket_number"]
if auto_fill_ticket_number:
answer_index = kktix_reg_new_main(driver, answer_index, is_finish_checkbox_click, config_dict)
return answer_index, registerStatus return answer_index, registerStatus
@ -2994,17 +3009,18 @@ def fami_activity(driver):
def fami_home(driver, url, config_dict): def fami_home(driver, url, config_dict):
#print("fami_home bingo") #print("fami_home bingo")
global is_assign_ticket_number is_assign_ticket_number = False
global ticket_number
global date_keyword ticket_number = str(config_dict["ticket_number"])
global area_keyword_1
global area_keyword_2
global area_keyword_3
global area_keyword_4
global area_auto_select_mode date_keyword = config_dict["tixcraft"]["date_auto_select"]["date_keyword"].strip()
area_auto_select_mode = config_dict["tixcraft"]["area_auto_select"]["mode"]
area_keyword_1 = config_dict["tixcraft"]["area_auto_select"]["area_keyword_1"].strip()
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()
#--------------------------- #---------------------------
# part 3: fill ticket number. # part 3: fill ticket number.
@ -3136,7 +3152,7 @@ def fami_home(driver, url, config_dict):
except Exception as exc: except Exception as exc:
pass pass
def urbtix_ticket_number_auto_select(driver, url, ticket_number): def urbtix_ticket_number_auto_select(driver, ticket_number):
ret = False ret = False
is_assign_ticket_number = False is_assign_ticket_number = False
@ -3187,7 +3203,7 @@ def urbtix_ticket_number_auto_select(driver, url, ticket_number):
# True: area block appear. # True: area block appear.
# False: area block not appear. # False: area block not appear.
# ps: return value for date auto select. # ps: return value for date auto select.
def urbtix_area_auto_select(driver, url, kktix_area_keyword, kktix_date_keyword): def urbtix_area_auto_select(driver, kktix_area_keyword, kktix_date_keyword):
ret = False ret = False
areas = None areas = None
@ -3275,7 +3291,7 @@ def urbtix_area_auto_select(driver, url, kktix_area_keyword, kktix_date_keyword)
return ret return ret
def urbtix_next_button_press(driver, url): def urbtix_next_button_press(driver):
ret = False ret = False
try: try:
el = driver.find_element(By.CSS_SELECTOR, '#free-seat-purchase-btn') el = driver.find_element(By.CSS_SELECTOR, '#free-seat-purchase-btn')
@ -3294,32 +3310,31 @@ def urbtix_next_button_press(driver, url):
return ret return ret
def urbtix_performance(driver, url, config_dict): def urbtix_performance(driver, config_dict):
#print("urbtix performance bingo") #print("urbtix performance bingo")
global auto_fill_ticket_number kktix_area_keyword = config_dict["kktix"]["area_keyword"].strip()
global ticket_number kktix_date_keyword = config_dict["kktix"]["date_keyword"].strip()
global kktix_area_keyword
global kktix_date_keyword
global auto_press_next_step_button
ticket_number = str(config_dict["ticket_number"])
auto_fill_ticket_number = config_dict["kktix"]["auto_fill_ticket_number"]
if auto_fill_ticket_number: if auto_fill_ticket_number:
area_div_exist = urbtix_area_auto_select(driver, url, kktix_area_keyword, kktix_date_keyword) area_div_exist = urbtix_area_auto_select(driver, kktix_area_keyword, kktix_date_keyword)
ticket_number_select_exist, is_assign_ticket_number = urbtix_ticket_number_auto_select(driver, url, ticket_number) ticket_number_select_exist, is_assign_ticket_number = urbtix_ticket_number_auto_select(driver, ticket_number)
# todo. # todo.
auto_press_next_step_button = config_dict["kktix"]["auto_press_next_step_button"]
if auto_press_next_step_button: if auto_press_next_step_button:
if is_assign_ticket_number: if is_assign_ticket_number:
urbtix_next_button_press(driver, url) urbtix_next_button_press(driver)
# purpose: area auto select # purpose: area auto select
# return: # return:
# True: area block appear. # True: area block appear.
# False: area block not appear. # False: area block not appear.
# ps: return value for date auto select. # ps: return value for date auto select.
def cityline_area_auto_select(url, kktix_area_keyword): def cityline_area_auto_select(driver, kktix_area_keyword):
ret = False ret = False
areas = None areas = None
@ -3421,7 +3436,7 @@ def cityline_area_auto_select(url, kktix_area_keyword):
return ret return ret
def cityline_area_selected_text(url): def cityline_area_selected_text(driver):
ret = None ret = None
area_list = None area_list = None
@ -3471,41 +3486,69 @@ def cityline_area_selected_text(url):
return ret return ret
def cityline_ticket_number_auto_select(url): def cityline_ticket_number_auto_select(driver, ticket_number):
ret = False ret = False
is_assign_ticket_number = False is_assign_ticket_number = False
selected_value = "" selected_value = ""
el = None
try: try:
el = driver.find_element(By.CSS_SELECTOR, 'td.tix_type_select > div.chzn-container > a > span') el = driver.find_element(By.CSS_SELECTOR, 'td.tix_type_select > div.chzn-container > a > span')
except Exception as exc:
#print("find ticket_number select fail")
#print(exc)
pass
is_visible = False
if el is not None: if el is not None:
try:
if el.is_enabled(): if el.is_enabled():
is_visible = True
except Exception as exc:
pass
selected_value = None
if is_visible:
ret = True ret = True
selected_value = ""
try:
selected_value = el.text selected_value = el.text
#print("selected_value:", selected_value) except Exception as exc:
pass
if selected_value is None: if selected_value is None:
selected_value = "" selected_value = ""
#print("selected_value:", selected_value)
if selected_value == "0": if selected_value == "0":
try:
el.click() el.click()
time.sleep(0.3) time.sleep(0.3)
except Exception as exc:
pass
is_options_enabled = False is_options_enabled = False
el_options = None
try:
el_options = driver.find_element(By.CSS_SELECTOR, 'td.tix_type_select > div.chzn-container > div.chzn-drop') el_options = driver.find_element(By.CSS_SELECTOR, 'td.tix_type_select > div.chzn-container > div.chzn-drop')
if el_options is not None: if el_options is not None:
if el_options.is_enabled(): if el_options.is_enabled():
is_options_enabled = True is_options_enabled = True
except Exception as exc:
pass
#print("is_options_enabled:", is_options_enabled) #print("is_options_enabled:", is_options_enabled)
el_options_li = None
if is_options_enabled: if is_options_enabled:
try:
el_options_li = driver.find_elements(By.CSS_SELECTOR, 'td.tix_type_select > div.chzn-container > div.chzn-drop > ul > li') el_options_li = driver.find_elements(By.CSS_SELECTOR, 'td.tix_type_select > div.chzn-container > div.chzn-drop > ul > li')
except Exception as exc:
pass
if el_options_li is not None: if el_options_li is not None:
if len(el_options_li) > 0: if len(el_options_li) > 0:
for row in el_options_li: for row in el_options_li:
if row is not None: if row is not None:
try:
if row.is_enabled(): if row.is_enabled():
row_text = row.text row_text = row.text
if not row_text is None: if not row_text is None:
@ -3515,14 +3558,12 @@ def cityline_ticket_number_auto_select(url):
is_assign_ticket_number = True is_assign_ticket_number = True
break break
except Exception as exc: except Exception as exc:
#print("find ticket_number select fail")
#print(exc)
pass pass
return ret, is_assign_ticket_number return ret, is_assign_ticket_number
def cityline_next_button_press(url): def cityline_next_button_press(driver):
ret = False ret = False
try: try:
time.sleep(0.2) time.sleep(0.2)
@ -3575,7 +3616,7 @@ def cityline_event(driver):
return ret return ret
def cityline_captcha_auto_focus(url): def cityline_captcha_auto_focus(driver):
ret = False ret = False
try: try:
el = driver.find_element(By.CSS_SELECTOR, 'input[name=verify]') el = driver.find_element(By.CSS_SELECTOR, 'input[name=verify]')
@ -3616,32 +3657,33 @@ def cityline_captcha_auto_focus(url):
def cityline_performance(driver, url, config_dict): def cityline_performance(driver, url, config_dict):
#print("cityline bingo") is_assign_ticket_number = False
if "performance.do;" in url: if "performance.do;" in url:
cityline_captcha_auto_focus(url) cityline_captcha_auto_focus(driver)
global auto_fill_ticket_number kktix_area_keyword = config_dict["kktix"]["area_keyword"].strip()
global kktix_area_keyword
global auto_press_next_step_button
global is_assign_ticket_number
auto_fill_ticket_number = config_dict["kktix"]["auto_fill_ticket_number"]
if "?cid=" in url: if "?cid=" in url:
if auto_fill_ticket_number: if auto_fill_ticket_number:
area_div_exist = False area_div_exist = False
if len(kktix_area_keyword) > 0: if len(kktix_area_keyword) > 0:
area_div_exist = cityline_area_auto_select(url, kktix_area_keyword) area_div_exist = cityline_area_auto_select(driver, kktix_area_keyword)
ticket_number_select_exist, is_assign_ticket_number = cityline_ticket_number_auto_select(url) ticket_number = str(config_dict["ticket_number"])
ticket_number_select_exist, is_assign_ticket_number = cityline_ticket_number_auto_select(driver, ticket_number)
# todo. # todo.
auto_press_next_step_button = config_dict["kktix"]["auto_press_next_step_button"]
if auto_press_next_step_button: if auto_press_next_step_button:
if is_assign_ticket_number: if is_assign_ticket_number:
selected_text = cityline_area_selected_text(url) selected_text = cityline_area_selected_text(driver)
if not selected_text is None: if not selected_text is None:
if kktix_area_keyword in selected_text: if kktix_area_keyword in selected_text:
# must same with our settting to auto press. # must same with our settting to auto press.
for i in range(3): for i in range(3):
click_ret = cityline_next_button_press(url) click_ret = cityline_next_button_press(driver)
if click_ret: if click_ret:
break break
@ -3793,7 +3835,7 @@ def main():
answer_index = -1 answer_index = -1
kktix_register_status_last = None kktix_register_status_last = None
global debugMode debugMode = config_dict["debug"]
if debugMode: if debugMode:
print("Start to looping, detect browser url...") print("Start to looping, detect browser url...")
@ -4023,7 +4065,7 @@ def main():
pass pass
if '/performanceDetail/' in url: if '/performanceDetail/' in url:
urbtix_performance(driver, url, config_dict) urbtix_performance(driver, config_dict)
if 'cityline.com' in url: if 'cityline.com' in url:
if '/event.do' in url: if '/event.do' in url:

View File

@ -19,7 +19,7 @@ import json
import webbrowser import webbrowser
import pyperclip import pyperclip
CONST_APP_VERSION = u"MaxBot (2022.11.18)" CONST_APP_VERSION = u"MaxBot (2022.11.19)"
CONST_FROM_TOP_TO_BOTTOM = u"from top to bottom" CONST_FROM_TOP_TO_BOTTOM = u"from top to bottom"
CONST_FROM_BOTTOM_TO_TOP = u"from bottom to top" CONST_FROM_BOTTOM_TO_TOP = u"from bottom to top"
@ -797,6 +797,7 @@ def PreferenctTab(root, config_dict, language_code, UI_PADDING_X):
kktix_area_keyword = "" kktix_area_keyword = ""
kktix_date_keyword = "" kktix_date_keyword = ""
# disable password brute force attack # disable password brute force attack
# PS: because of the question is always variable.
#kktix_answer_dictionary = "" #kktix_answer_dictionary = ""
auto_guess_options = False # default not checked. auto_guess_options = False # default not checked.
@ -875,8 +876,7 @@ def PreferenctTab(root, config_dict, language_code, UI_PADDING_X):
date_auto_select_mode = CONST_SELECT_ORDER_DEFAULT date_auto_select_mode = CONST_SELECT_ORDER_DEFAULT
if 'date_keyword' in config_dict["tixcraft"]["date_auto_select"]: if 'date_keyword' in config_dict["tixcraft"]["date_auto_select"]:
date_keyword = config_dict["tixcraft"]["date_auto_select"]["date_keyword"] date_keyword = config_dict["tixcraft"]["date_auto_select"]["date_keyword"].strip()
date_keyword = date_keyword.strip()
area_auto_select_enable = False area_auto_select_enable = False
area_auto_select_mode = None area_auto_select_mode = None