add new feature, pass date is sold out event. disable auto reload coming soon page.

master
CHUN YU YAO 2022-03-24 23:22:43 +08:00
parent d33e805508
commit 76aa579d48
2 changed files with 179 additions and 77 deletions

View File

@ -51,7 +51,7 @@ ssl._create_default_https_context = ssl._create_unverified_context
#附註1沒有寫的很好很多地方應該可以模組化。 #附註1沒有寫的很好很多地方應該可以模組化。
#附註2 #附註2
CONST_APP_VERSION = u"MaxBot (2022.03.16)" CONST_APP_VERSION = u"MaxBot (2022.03.24)"
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"
@ -86,7 +86,9 @@ area_keyword = None
area_keyword_1 = None area_keyword_1 = None
area_keyword_2 = None area_keyword_2 = None
pass_1_seat_remaining_enable = False # default not checked. pass_1_seat_remaining_enable = False # default not checked.
pass_date_is_sold_out_enable = False # default not checked.
auto_reload_coming_soon_page_enable = True # default checked.
kktix_area_auto_select_mode = None kktix_area_auto_select_mode = None
kktix_area_keyword = None kktix_area_keyword = None
@ -136,6 +138,9 @@ def load_config_from_local(driver):
global auto_guess_options global auto_guess_options
global pass_1_seat_remaining_enable global pass_1_seat_remaining_enable
global pass_date_is_sold_out_enable
global auto_reload_coming_soon_page_enable
global area_keyword_1 global area_keyword_1
global area_keyword_2 global area_keyword_2
@ -239,6 +244,14 @@ def load_config_from_local(driver):
if 'pass_1_seat_remaining' in config_dict["tixcraft"]: if 'pass_1_seat_remaining' in config_dict["tixcraft"]:
pass_1_seat_remaining_enable = config_dict["tixcraft"]["pass_1_seat_remaining"] pass_1_seat_remaining_enable = config_dict["tixcraft"]["pass_1_seat_remaining"]
pass_date_is_sold_out_enable = False
if 'pass_date_is_sold_out' in config_dict["tixcraft"]:
pass_date_is_sold_out_enable = config_dict["tixcraft"]["pass_date_is_sold_out"]
auto_reload_coming_soon_page_enable = True
if 'auto_reload_coming_soon_page' in config_dict["tixcraft"]:
auto_reload_coming_soon_page_enable = config_dict["tixcraft"]["auto_reload_coming_soon_page"]
# output config: # output config:
print("maxbot app version", CONST_APP_VERSION) print("maxbot app version", CONST_APP_VERSION)
print("python version", platform.python_version()) print("python version", platform.python_version())
@ -267,6 +280,10 @@ def load_config_from_local(driver):
print("area_keyword_2", area_keyword_2) print("area_keyword_2", area_keyword_2)
print("pass_1_seat_remaining", pass_1_seat_remaining_enable) 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) print("debug Mode", debugMode)
# entry point # entry point
@ -777,6 +794,8 @@ def get_answer_list_by_question(captcha_text_div_text):
# from detail to game # from detail to game
def tixcraft_redirect(driver, url): def tixcraft_redirect(driver, url):
ret = False
game_name = "" game_name = ""
# get game_name from url # get game_name from url
@ -790,15 +809,18 @@ def tixcraft_redirect(driver, url):
entry_url = url.replace("/activity/detail/","/activity/game/") entry_url = url.replace("/activity/detail/","/activity/game/")
#entry_url = "tixcraft.com/activity/game/%s" % (game_name,) #entry_url = "tixcraft.com/activity/game/%s" % (game_name,)
driver.get(entry_url) driver.get(entry_url)
ret = True
return ret
def date_auto_select(driver, url, date_auto_select_mode, date_keyword, pass_date_is_sold_out_enable, auto_reload_coming_soon_page_enable):
is_date_selected = False
def date_auto_select(driver, url, date_auto_select_mode, date_keyword):
debug_date_select = True # debug. debug_date_select = True # debug.
debug_date_select = False # online debug_date_select = False # online
# PS: for big events, check sold out text maybe not helpful, due to database is too busy. # PS: for big events, check sold out text maybe not helpful, due to database is too busy.
is_pass_sold_out = True sold_out_text_list = ["選購一空","No tickets available","空席なし"]
is_pass_sold_out = False
sold_out_text = ["選購一空","No tickets available","空席なし"]
game_name = "" game_name = ""
@ -812,86 +834,108 @@ def date_auto_select(driver, url, date_auto_select_mode, date_keyword):
print("date_auto_select_mode:", date_auto_select_mode) print("date_auto_select_mode:", date_auto_select_mode)
print("date_keyword:", date_keyword) print("date_keyword:", date_keyword)
check_game_detail = False
# choose date # choose date
if "/activity/game/%s" % (game_name,) in url: if "/activity/game/%s" % (game_name,) in url:
if debug_date_select:
# one or more row is matched. if len(date_keyword) == 0:
match_keyword_row = False
if len(date_keyword) == 0:
if debug_date_select:
print("date keyword is empty.") print("date keyword is empty.")
el = None
if date_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
try:
el = driver.find_element(By.CSS_SELECTOR, '.btn-next')
except Exception as exc:
print("find .btn-next fail")
else: else:
# from down to top
# [TODO]: Random selection mode is not implemented..
days = None
try:
days = driver.find_elements(By.CSS_SELECTOR, '.btn-next')
if len(days) > 0:
el = days[len(days)-1]
except Exception as exc:
pass
#print("find a tag fail")
if debug_date_select:
print("date keyword is empty.")
if el is not None:
# first date.
try:
el.click()
match_keyword_row = True
except Exception as exc:
print("try to click .btn-next fail")
else:
if debug_date_select:
print("date keyword:", date_keyword) print("date keyword:", date_keyword)
check_game_detail = True
# match keyword. if check_game_detail:
date_list = None date_list = None
try: try:
date_list = driver.find_elements(By.CSS_SELECTOR, '#gameList > table > tbody > tr') date_list = driver.find_elements(By.CSS_SELECTOR, '#gameList > table > tbody > tr')
except Exception as exc: except Exception as exc:
print("find #gameList fail") print("find #gameList fail")
if date_list is not None: button_list = []
for row in date_list: if date_list is not None:
row_text = "" for row in date_list:
try: # step 1: check keyword.
row_text = row.text is_match_keyword_row = False
except Exception as exc:
print("get text fail")
break
if len(row_text) > 0: row_text = ""
try:
row_text = row.text
except Exception as exc:
print("get text fail")
# should use continue or break?
break
if len(row_text) > 0:
if len(date_keyword) == 0:
# no keyword, match all.
is_match_keyword_row = True
else:
# check keyword.
if date_keyword in row_text: if date_keyword in row_text:
match_keyword_row = True is_match_keyword_row = True
el = None
try:
el = row.find_element(By.CSS_SELECTOR, '.btn-next')
except Exception as exc:
print("find .btn-next fail")
if el is not None: # step 2: check sold out.
# first date. if is_match_keyword_row:
try: if pass_date_is_sold_out_enable:
el.click() for sold_out_item in sold_out_text_list:
except Exception as exc: row_text_right_part = row_text[(len(sold_out_item)+5)*-1:]
print("try to click .btn-next fail") if debug_date_select:
print("check right part text:", row_text_right_part)
if sold_out_item in row_text_right_part:
is_match_keyword_row = False
if match_keyword_row: if debug_date_select:
print("match sold out text: %s, skip this row." % (sold_out_item))
# no need check next language item.
break
# step 3: add to list.
if is_match_keyword_row:
el = None
try:
el = row.find_element(By.CSS_SELECTOR, '.btn-next')
except Exception as exc:
if debug_date_select:
print("find .btn-next fail")
pass
if el is not None:
button_list.append(el)
if date_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM:
# only need one row.
if debug_date_select:
print("match date row, only need first row, start to break")
break break
if not match_keyword_row:
if len(button_list) > 0:
# default first row.
target_row_index = 0
if date_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP:
target_row_index = len(button_list) - 1
if date_auto_select_mode == CONST_RANDOM:
target_row_index = random.randint(0,len(button_list)-1)
try:
if debug_date_select:
print("clicking row number:", target_row_index)
el = button_list[target_row_index]
is_date_selected = True
el.click()
except Exception as exc:
print("try to click .btn-next fail")
# PS: Is this case need to reload page?
# (A)user input keywords, with matched text, but no hyperlink to click.
# (B)user input keywords, but not no matched text with hyperlink to click.
# [PS]: current reload condition only when No hyperlink button.
if auto_reload_coming_soon_page_enable and not is_date_selected:
# auto refresh for date list page. # auto refresh for date list page.
el_list = None el_list = None
try: try:
@ -905,6 +949,8 @@ def date_auto_select(driver, url, date_auto_select_mode, date_keyword):
pass pass
#print("find .btn-next fail:", exc) #print("find .btn-next fail:", exc)
return is_date_selected
# PURPOSE: get target area list. # PURPOSE: get target area list.
# RETURN: # RETURN:
# is_need_refresh # is_need_refresh
@ -3369,14 +3415,25 @@ def main():
# do nothing. # do nothing.
continue continue
tixcraft_redirect(driver, url) is_redirected = tixcraft_redirect(driver, url)
if is_redirected:
# start to redirecting.
continue
global date_auto_select_enable global date_auto_select_enable
global date_auto_select_mode global date_auto_select_mode
global date_keyword global date_keyword
global pass_date_is_sold_out_enable
global auto_reload_coming_soon_page_enable
is_date_selected = False
if date_auto_select_enable: if date_auto_select_enable:
date_auto_select(driver, url, date_auto_select_mode, date_keyword) is_date_selected = date_auto_select(driver, url, date_auto_select_mode, date_keyword, pass_date_is_sold_out_enable, auto_reload_coming_soon_page_enable)
if is_date_selected:
# start to redirecting.
continue
# choose area # choose area
global area_auto_select_enable global area_auto_select_enable

View File

@ -17,7 +17,7 @@ import sys
import platform import platform
import json import json
CONST_APP_VERSION = u"MaxBot (2022.03.16)" CONST_APP_VERSION = u"MaxBot (2022.03.24)"
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"
@ -89,6 +89,10 @@ def btn_save_act(slience_mode=False):
global chk_state_pass_1_seat_remaining global chk_state_pass_1_seat_remaining
global chk_state_pass_date_is_sold_out
global chk_state_auto_reload_coming_soon_page
if is_all_data_correct: if is_all_data_correct:
if combo_homepage.get().strip()=="": if combo_homepage.get().strip()=="":
is_all_data_correct = False is_all_data_correct = False
@ -134,6 +138,8 @@ def btn_save_act(slience_mode=False):
config_dict["tixcraft"]["area_auto_select"]["mode"] = combo_area_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_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())
# save config. # save config.
if is_all_data_correct: if is_all_data_correct:
@ -372,7 +378,9 @@ def MainMenu(root):
area_keyword_1 = "" area_keyword_1 = ""
area_keyword_2 = "" area_keyword_2 = ""
pass_1_seat_remaining_enable = False # default not checked. pass_1_seat_remaining_enable = False # default not checked.
pass_date_is_sold_out_enable = False # default not checked.
auto_reload_coming_soon_page_enable = True # default checked.
debugMode = False debugMode = False
@ -463,6 +471,14 @@ def MainMenu(root):
if 'pass_1_seat_remaining' in config_dict["tixcraft"]: if 'pass_1_seat_remaining' in config_dict["tixcraft"]:
pass_1_seat_remaining_enable = config_dict["tixcraft"]["pass_1_seat_remaining"] pass_1_seat_remaining_enable = config_dict["tixcraft"]["pass_1_seat_remaining"]
pass_date_is_sold_out_enable = False
if 'pass_date_is_sold_out' in config_dict["tixcraft"]:
pass_date_is_sold_out_enable = config_dict["tixcraft"]["pass_date_is_sold_out"]
auto_reload_coming_soon_page_enable = True
if 'auto_reload_coming_soon_page' in config_dict["tixcraft"]:
auto_reload_coming_soon_page_enable = config_dict["tixcraft"]["auto_reload_coming_soon_page"]
# output config: # output config:
print("setting app version", CONST_APP_VERSION) print("setting app version", CONST_APP_VERSION)
print("python version", platform.python_version()) print("python version", platform.python_version())
@ -493,6 +509,9 @@ def MainMenu(root):
print("area_keyword_2", area_keyword_2) print("area_keyword_2", area_keyword_2)
print("pass_1_seat_remaining", pass_1_seat_remaining_enable) 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) print("debug Mode", debugMode)
else: else:
@ -788,6 +807,32 @@ def MainMenu(root):
group_row_count+=1 group_row_count+=1
lbl_pass_date_is_sold_out = Label(frame_group_tixcraft, text="Pass date is sold out")
lbl_pass_date_is_sold_out.grid(column=0, row=group_row_count, sticky = E)
global chk_state_pass_date_is_sold_out
chk_state_pass_date_is_sold_out = BooleanVar()
chk_state_pass_date_is_sold_out.set(pass_date_is_sold_out_enable)
global chk_pass_date_is_sold_out
chk_pass_date_is_sold_out = Checkbutton(frame_group_tixcraft, text='Enable', variable=chk_state_pass_date_is_sold_out)
chk_pass_date_is_sold_out.grid(column=1, row=group_row_count, sticky = W)
group_row_count+=1
lbl_auto_reload_coming_soon_page = Label(frame_group_tixcraft, text="Reload coming soon page")
lbl_auto_reload_coming_soon_page.grid(column=0, row=group_row_count, sticky = E)
global chk_state_auto_reload_coming_soon_page
chk_state_auto_reload_coming_soon_page = BooleanVar()
chk_state_auto_reload_coming_soon_page.set(auto_reload_coming_soon_page_enable)
global chk_auto_reload_coming_soon_page
chk_auto_reload_coming_soon_page = Checkbutton(frame_group_tixcraft, text='Enable', variable=chk_state_auto_reload_coming_soon_page)
chk_auto_reload_coming_soon_page.grid(column=1, row=group_row_count, sticky = W)
group_row_count+=1
global frame_group_tixcraft_index global frame_group_tixcraft_index
frame_group_tixcraft_index = row_count frame_group_tixcraft_index = row_count
@ -836,7 +881,7 @@ def main():
GUI = MainMenu(root) GUI = MainMenu(root)
GUI_SIZE_WIDTH = 420 GUI_SIZE_WIDTH = 420
GUI_SIZE_HEIGHT = 395 GUI_SIZE_HEIGHT = 455
GUI_SIZE_MACOS = str(GUI_SIZE_WIDTH) + 'x' + str(GUI_SIZE_HEIGHT) GUI_SIZE_MACOS = str(GUI_SIZE_WIDTH) + 'x' + str(GUI_SIZE_HEIGHT)
GUI_SIZE_WINDOWS=str(GUI_SIZE_WIDTH-60) + 'x' + str(GUI_SIZE_HEIGHT-20) GUI_SIZE_WINDOWS=str(GUI_SIZE_WIDTH-60) + 'x' + str(GUI_SIZE_HEIGHT-20)