2023-02-27, bug fixs for tixcraft and hkticketing, PS: hkticketing is dectected...

master
CHUN YU YAO 2023-02-28 17:11:45 +08:00
parent c1bd8ca781
commit a027410b28
2 changed files with 97 additions and 79 deletions

View File

@ -53,7 +53,7 @@ import argparse
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 (2023.02.26)" CONST_APP_VERSION = u"MaxBot (2023.02.27)"
CONST_HOMEPAGE_DEFAULT = "https://tixcraft.com" CONST_HOMEPAGE_DEFAULT = "https://tixcraft.com"
URL_GOOGLE_OAUTH = 'https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount?redirect_uri=https%3A%2F%2Fdevelopers.google.com%2Foauthplayground&prompt=consent&response_type=code&client_id=407408718192.apps.googleusercontent.com&scope=email&access_type=offline&flowName=GeneralOAuthFlow' URL_GOOGLE_OAUTH = 'https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount?redirect_uri=https%3A%2F%2Fdevelopers.google.com%2Foauthplayground&prompt=consent&response_type=code&client_id=407408718192.apps.googleusercontent.com&scope=email&access_type=offline&flowName=GeneralOAuthFlow'
@ -141,6 +141,9 @@ def get_config_dict(args):
if not args.homepage is None: if not args.homepage is None:
if len(args.homepage) > 0: if len(args.homepage) > 0:
config_dict["homepage"] = args.homepage config_dict["homepage"] = args.homepage
if not args.ticket_number is None:
if args.homepage > 0:
config_dict["ticket_number"] = args.ticket_number
if not args.browser is None: if not args.browser is None:
if len(args.browser) > 0: if len(args.browser) > 0:
config_dict["browser"] = args.browser config_dict["browser"] = args.browser
@ -159,7 +162,7 @@ def get_config_dict(args):
config_dict["advanced"]["ibonqware"] = encryptMe(args.ibonqware) config_dict["advanced"]["ibonqware"] = encryptMe(args.ibonqware)
# special case for headless. # special case for headless to enable away from keyboard mode.
is_headless_enable = False is_headless_enable = False
if config_dict["advanced"]["headless"]: if config_dict["advanced"]["headless"]:
# for tixcraft headless. # for tixcraft headless.
@ -240,6 +243,7 @@ def get_chrome_options(webdriver_path, adblock_plus_enable, browser="chrome", he
chrome_options.add_argument('--disable-features=TranslateUI') chrome_options.add_argument('--disable-features=TranslateUI')
chrome_options.add_argument('--disable-translate') chrome_options.add_argument('--disable-translate')
chrome_options.add_argument('--lang=zh-TW') chrome_options.add_argument('--lang=zh-TW')
#chrome_options.add_argument('--disable-web-security')
# for navigator.webdriver # for navigator.webdriver
chrome_options.add_experimental_option("excludeSwitches", ['enable-automation']) chrome_options.add_experimental_option("excludeSwitches", ['enable-automation'])
@ -323,6 +327,7 @@ def load_chromdriver_uc(webdriver_path, adblock_plus_enable, headless):
options.add_argument('--disable-features=TranslateUI') options.add_argument('--disable-features=TranslateUI')
options.add_argument('--disable-translate') options.add_argument('--disable-translate')
options.add_argument('--lang=zh-TW') options.add_argument('--lang=zh-TW')
#options.add_argument('--disable-web-security')
options.add_argument("--password-store=basic") options.add_argument("--password-store=basic")
options.add_experimental_option("prefs", {"credentials_enable_service": False, "profile.password_manager_enabled": False}) options.add_experimental_option("prefs", {"credentials_enable_service": False, "profile.password_manager_enabled": False})
@ -639,6 +644,7 @@ def get_driver_by_config(config_dict):
tixcraft_sid = decryptMe(config_dict["advanced"]["tixcraft_sid"]) tixcraft_sid = decryptMe(config_dict["advanced"]["tixcraft_sid"])
driver.delete_cookie("SID") driver.delete_cookie("SID")
driver.add_cookie({"name":"SID", "value": tixcraft_sid, "path" : "/", "secure":True}) driver.add_cookie({"name":"SID", "value": tixcraft_sid, "path" : "/", "secure":True})
set_non_browser_cookies(driver, url, Captcha_Browser)
if 'ibon.com' in homepage: if 'ibon.com' in homepage:
@ -1298,7 +1304,8 @@ def tixcraft_date_auto_select(driver, url, config_dict, domain_name):
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"]
# 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.
sold_out_text_list = ["選購一空","No tickets available","空席なし"] sold_out_text_list = ["選購一空","已售完","No tickets available","Sold out","空席なし","完売した"]
find_ticket_text_list = ['立即訂購','Find tickets','お申込みへ進む']
game_name = "" game_name = ""
@ -1330,11 +1337,11 @@ def tixcraft_date_auto_select(driver, url, config_dict, domain_name):
print("find #gameList fail") print("find #gameList fail")
is_coming_soon = False is_coming_soon = False
coming_soon_condictions_list = ['開賣','剩餘','','小時','分鐘','','0',':','/'] coming_soon_condictions_list_tw = ['開賣','剩餘','','小時','分鐘','','0',':','/']
button_list = None matched_row_list = None
if date_list is not None: if date_list is not None:
button_list = [] matched_row_list = []
for row in date_list: for row in date_list:
# step 1: check keyword. # step 1: check keyword.
is_match_keyword_row = False is_match_keyword_row = False
@ -1352,7 +1359,7 @@ def tixcraft_date_auto_select(driver, url, config_dict, domain_name):
if len(row_text) > 0: if len(row_text) > 0:
is_match_all_coming_soon_condiction = True is_match_all_coming_soon_condiction = True
for condiction_string in coming_soon_condictions_list: for condiction_string in coming_soon_condictions_list_tw:
if not condiction_string in row_text: if not condiction_string in row_text:
is_match_all_coming_soon_condiction = False is_match_all_coming_soon_condiction = False
break break
@ -1368,81 +1375,73 @@ def tixcraft_date_auto_select(driver, url, config_dict, domain_name):
if date_keyword in row_text: if date_keyword in row_text:
is_match_keyword_row = True is_match_keyword_row = True
# step 2: check sold out.
# step 2: check button in row.
if is_match_keyword_row:
is_match_keyword_row = False
for text_item in find_ticket_text_list:
if text_item in row_text:
is_match_keyword_row = True
break
# step 3: check sold out.
if is_match_keyword_row: if is_match_keyword_row:
if pass_date_is_sold_out_enable: if pass_date_is_sold_out_enable:
for sold_out_item in sold_out_text_list: for sold_out_item in sold_out_text_list:
row_text_right_part = row_text[(len(sold_out_item)+5)*-1:] row_text_right_part = row_text[(len(sold_out_item)+5)*-1:]
if show_debug_message: if show_debug_message:
print("check right part text:", row_text_right_part) #print("check right part text:", row_text_right_part)
pass
if sold_out_item in row_text_right_part: if sold_out_item in row_text_right_part:
is_match_keyword_row = False is_match_keyword_row = False
if show_debug_message: if show_debug_message:
print("match sold out text: %s, skip this row." % (sold_out_item)) print("match sold out text: %s, skip this row." % (sold_out_item))
# no need check next language item.
break break
# step 3: add to list. # step 4: add to list.
if is_match_keyword_row: if is_match_keyword_row:
el = None if show_debug_message:
try: print("match row text: %s" % (row_text))
el = row.find_element(By.CSS_SELECTOR, 'button') matched_row_list.append(row)
except Exception as exc:
if show_debug_message:
print("find button 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 show_debug_message:
print("match date row, only need first row, start to break")
break
is_date_selected = False is_date_selected = False
if button_list is not None: if matched_row_list is not None:
if len(button_list) > 0: matched_row_count = len(matched_row_list)
if show_debug_message:
print("matched_row_count:", matched_row_count)
if matched_row_count > 0:
# default first row. # default first row.
target_row_index = 0 target_row_index = 0
if date_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP: if date_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP:
target_row_index = len(button_list) - 1 target_row_index = len(matched_row_list) - 1
if date_auto_select_mode == CONST_RANDOM: if date_auto_select_mode == CONST_RANDOM:
target_row_index = random.randint(0,len(button_list)-1) target_row_index = random.randint(0,len(matched_row_list)-1)
if show_debug_message: if show_debug_message:
print("clicking at button index:", target_row_index+1) print("clicking at button index:", target_row_index+1)
el = None target_row = matched_row_list[target_row_index]
target_button = None
try: try:
el = button_list[target_row_index] target_button = target_row.find_element(By.CSS_SELECTOR, 'button')
if show_debug_message: if target_button.is_enabled():
print("pressing button...") if show_debug_message:
el.click() print("pressing button...")
''' target_button.click()
ticket_url = el.get_attribute('data-href') is_date_selected = True
is_redirected = False
if not ticket_url is None:
if len(ticket_url) > 0:
driver.get("https:%s%s" % (domain_name, ticket_url))
is_redirected = True
'''
is_date_selected = True
except Exception as exc: except Exception as exc:
print("try to click button fail, force click by js.") if show_debug_message:
print(exc) print("find or press button fail")
try:
driver.execute_script("arguments[0].click();", el)
except Exception as exc:
pass
# PS: Is this case need to reload page? if not target_button is None:
# (A)user input keywords, with matched text, but no hyperlink to click. print("try to click button fail, force click by js.")
# (B)user input keywords, but not no matched text with hyperlink to click. #print(exc)
try:
driver.execute_script("arguments[0].click();", target_button)
except Exception as exc:
pass
# [PS]: current reload condition only when # [PS]: current reload condition only when
if auto_reload_coming_soon_page_enable: if auto_reload_coming_soon_page_enable:
@ -1460,8 +1459,10 @@ def tixcraft_date_auto_select(driver, url, config_dict, domain_name):
# case 1: No hyperlink button. # case 1: No hyperlink button.
el_list = None el_list = None
try: try:
el_list = driver.find_elements(By.CSS_SELECTOR, 'button') el_list = driver.find_elements(By.CSS_SELECTOR, '#gameList > table > tbody > tr > td > button.btn')
if el_list is None: if el_list is None:
if show_debug_message:
print("No buttons in list, do refresh...")
driver.refresh() driver.refresh()
else: else:
if len(el_list) == 0: if len(el_list) == 0:
@ -2128,7 +2129,8 @@ def tixcraft_auto_ocr(driver, ocr, away_from_keyboard_enable, previous_answer, C
if ocr_captcha_image_source == CONST_OCR_CAPTCH_IMAGE_SOURCE_CANVAS: if ocr_captcha_image_source == CONST_OCR_CAPTCH_IMAGE_SOURCE_CANVAS:
image_id = 'TicketForm_verifyCode-image' image_id = 'TicketForm_verifyCode-image'
if 'indievox.com' in domain_name: if 'indievox.com' in domain_name:
image_id = 'TicketForm_verifyCode-image' #image_id = 'TicketForm_verifyCode-image'
pass
try: try:
form_verifyCode_base64 = driver.execute_async_script(""" form_verifyCode_base64 = driver.execute_async_script("""
var canvas = document.createElement('canvas'); var canvas = document.createElement('canvas');
@ -2141,6 +2143,11 @@ def tixcraft_auto_ocr(driver, ocr, away_from_keyboard_enable, previous_answer, C
callback(canvas.toDataURL()); callback(canvas.toDataURL());
""" % (image_id)) """ % (image_id))
img_base64 = base64.b64decode(form_verifyCode_base64.split(',')[1]) img_base64 = base64.b64decode(form_verifyCode_base64.split(',')[1])
if img_base64 is None:
if not Captcha_Browser is None:
print("canvas get image fail, use plan_b: NonBrowser")
img_base64 = base64.b64decode(Captcha_Browser.Request_Captcha())
except Exception as exc: except Exception as exc:
if show_debug_message: if show_debug_message:
print("canvas exception:", str(exc)) print("canvas exception:", str(exc))
@ -2161,7 +2168,7 @@ def tixcraft_auto_ocr(driver, ocr, away_from_keyboard_enable, previous_answer, C
ocr_elapsed_time = ocr_done_time - ocr_start_time ocr_elapsed_time = ocr_done_time - ocr_start_time
print("ocr elapsed time:", "{:.3f}".format(ocr_elapsed_time)) print("ocr elapsed time:", "{:.3f}".format(ocr_elapsed_time))
else: else:
print("ddddocr is None") print("ddddocr component is not able to use, you may running in arm environment.")
if not orc_answer is None: if not orc_answer is None:
orc_answer = orc_answer.strip() orc_answer = orc_answer.strip()
@ -5741,17 +5748,20 @@ def list_all_cookies(driver):
cookies_dict[cookie['name']] = cookie['value'] cookies_dict[cookie['name']] = cookie['value']
print(cookies_dict) print(cookies_dict)
def set_non_browser_cookies(driver, url, Captcha_Browser):
domain_name = url.split('/')[2]
#PS: need set cookies once, if user change domain.
if not Captcha_Browser is None:
Captcha_Browser.Set_cookies(driver.get_cookies())
Captcha_Browser.Set_Domain(domain_name)
def tixcraft_main(driver, url, config_dict, tixcraft_dict, ocr, Captcha_Browser): def tixcraft_main(driver, url, config_dict, tixcraft_dict, ocr, Captcha_Browser):
tixcraft_home_close_window(driver) tixcraft_home_close_window(driver)
home_url_list = ['https://tixcraft.com/','https://www.tixcraft.com/','https://indievox.com/','https://www.indievox.com/','https://teamear.tixcraft.com/activity'] home_url_list = ['https://tixcraft.com/','https://www.tixcraft.com/','https://indievox.com/','https://www.indievox.com/','https://teamear.tixcraft.com/activity']
for each_url in home_url_list: for each_url in home_url_list:
if each_url == url: if each_url == url:
if config_dict["ocr_captcha"]["enable"]: if config_dict["ocr_captcha"]["enable"]:
domain_name = url.split('/')[2] set_non_browser_cookies(driver, url, Captcha_Browser)
#PS: need set cookies once, if user change domain.
if not Captcha_Browser is None:
Captcha_Browser.Set_cookies(driver.get_cookies())
Captcha_Browser.Set_Domain(domain_name)
break break
if "/activity/detail/" in url: if "/activity/detail/" in url:
@ -6336,7 +6346,6 @@ def hkticketing_date_auto_select(driver, auto_select_mode, date_keyword, auto_re
show_debug_message = True # debug. show_debug_message = True # debug.
show_debug_message = False # online show_debug_message = False # online
ret = False
matched_blocks = None matched_blocks = None
# clean stop word. # clean stop word.
@ -6530,9 +6539,6 @@ def hkticketing_date_auto_select(driver, auto_select_mode, date_keyword, auto_re
if target_area.is_enabled(): if target_area.is_enabled():
target_area.click() target_area.click()
is_date_assigned = True is_date_assigned = True
#PS:must delay here, due to next loop coming to soon, will cause refresh.
time.sleep(0.5)
except Exception as exc: except Exception as exc:
print("click target_area link fail") print("click target_area link fail")
print(exc) print(exc)
@ -6547,6 +6553,7 @@ def hkticketing_date_auto_select(driver, auto_select_mode, date_keyword, auto_re
''' '''
# alway, auto submit # alway, auto submit
is_date_submiting = False
el_btn = None el_btn = None
try: try:
my_css_selector = "#buyButton > input" my_css_selector = "#buyButton > input"
@ -6559,8 +6566,9 @@ def hkticketing_date_auto_select(driver, auto_select_mode, date_keyword, auto_re
if el_btn.is_enabled() and el_btn.is_displayed(): if el_btn.is_enabled() and el_btn.is_displayed():
el_btn.click() el_btn.click()
print("buy button pressed.") print("buy button pressed.")
ret = True is_date_submiting = True
except Exception as exc: except Exception as exc:
pass
# use plan B # use plan B
''' '''
try: try:
@ -6597,7 +6605,7 @@ def hkticketing_date_auto_select(driver, auto_select_mode, date_keyword, auto_re
except Exception as exc: except Exception as exc:
pass pass
return ret return is_date_submiting
def hkticketing_show(driver, config_dict): def hkticketing_show(driver, config_dict):
show_debug_message = True # debug. show_debug_message = True # debug.
@ -6610,9 +6618,9 @@ def hkticketing_show(driver, config_dict):
if show_debug_message: if show_debug_message:
print("date_keyword:", date_keyword) print("date_keyword:", date_keyword)
print("auto_reload_coming_soon_page_enable:", auto_reload_coming_soon_page_enable) print("auto_reload_coming_soon_page_enable:", auto_reload_coming_soon_page_enable)
is_date_assign_by_bot = hkticketing_date_auto_select(driver, date_auto_select_mode, date_keyword, auto_reload_coming_soon_page_enable) is_date_submiting = hkticketing_date_auto_select(driver, date_auto_select_mode, date_keyword, auto_reload_coming_soon_page_enable)
return is_date_assign_by_bot return is_date_submiting
def hkticketing_area_auto_select(driver, area_auto_select_mode, area_keyword_1, area_keyword_1_and): def hkticketing_area_auto_select(driver, area_auto_select_mode, area_keyword_1, area_keyword_1_and):
show_debug_message = True # debug. show_debug_message = True # debug.
@ -6966,7 +6974,7 @@ def hkticketing_performance(driver, config_dict, domain_name):
pass pass
# hide blocks. # hide blocks.
hkticketing_hide_tickets_blocks(driver) #hkticketing_hide_tickets_blocks(driver)
# goto bottom. # goto bottom.
hkticketing_nav_to_footer(driver) hkticketing_nav_to_footer(driver)
@ -7009,7 +7017,7 @@ def hkticketing_escape_robot_detection(driver):
try: try:
el_main_iframe = driver.find_element(By.ID, 'main-iframe') el_main_iframe = driver.find_element(By.ID, 'main-iframe')
except Exception as exc: except Exception as exc:
print("find el_main_iframe fail...") #print("find el_main_iframe fail...")
#print(exc) #print(exc)
pass pass
@ -7027,7 +7035,7 @@ def hkticketing_escape_robot_detection(driver):
return ret return ret
def hkticketing_main(driver, url, config_dict): def hkticketing_main(driver, url, config_dict, hkticketing_dict):
home_url_list = ['https://premier.hkticketing.com/' home_url_list = ['https://premier.hkticketing.com/'
,'https://hotshow.hkticketing.com/' ,'https://hotshow.hkticketing.com/'
,'https://premier.hkticketing.com/default.aspx' ,'https://premier.hkticketing.com/default.aspx'
@ -7068,8 +7076,9 @@ def hkticketing_main(driver, url, config_dict):
if is_event_page: if is_event_page:
date_auto_select_enable = config_dict["tixcraft"]["date_auto_select"]["enable"] date_auto_select_enable = config_dict["tixcraft"]["date_auto_select"]["enable"]
if date_auto_select_enable: if date_auto_select_enable:
hkticketing_show(driver, config_dict) if not hkticketing_dict["is_date_submiting"]:
pass hkticketing_dict["is_date_submiting"] = hkticketing_show(driver, config_dict)
pass
# https://premier.hkticketing.com/events/XXX/venues/KSH/performances/XXX/tickets # https://premier.hkticketing.com/events/XXX/venues/KSH/performances/XXX/tickets
if '/events/' in url and '/performances/' in url: if '/events/' in url and '/performances/' in url:
@ -7091,6 +7100,8 @@ def hkticketing_main(driver, url, config_dict):
hkticketing_nav_to_footer(driver) hkticketing_nav_to_footer(driver)
hkticketing_go_to_payment(driver) hkticketing_go_to_payment(driver)
return hkticketing_dict
def khan_go_buy_redirect(driver): def khan_go_buy_redirect(driver):
ret = False ret = False
@ -8041,6 +8052,9 @@ def main(args):
ibon_dict = {} ibon_dict = {}
ibon_dict["answer_index"]=-1 ibon_dict["answer_index"]=-1
hkticketing_dict = {}
hkticketing_dict["is_date_submiting"] = False
DISCONNECTED_MSG = ': target window already closed' DISCONNECTED_MSG = ': target window already closed'
ocr = None ocr = None
@ -8214,10 +8228,10 @@ def main(args):
cityline_main(driver, url, config_dict) cityline_main(driver, url, config_dict)
if 'hkticketing.com' in url: if 'hkticketing.com' in url:
hkticketing_main(driver, url, config_dict) hkticketing_dict = hkticketing_main(driver, url, config_dict, hkticketing_dict)
if 'galaxymacau.com' in url: if 'galaxymacau.com' in url:
hkticketing_main(driver, url, config_dict) hkticketing_dict = hkticketing_main(driver, url, config_dict, hkticketing_dict)
# for facebook # for facebook
facebook_login_url = 'https://www.facebook.com/login.php?' facebook_login_url = 'https://www.facebook.com/login.php?'
@ -8238,6 +8252,10 @@ def cli():
help="overwrite homepage setting", help="overwrite homepage setting",
type=str) type=str)
parser.add_argument("--ticket_number",
help="overwrite ticket_number setting",
type=int)
parser.add_argument("--tixcraft_sid", parser.add_argument("--tixcraft_sid",
help="overwrite tixcraft sid field", help="overwrite tixcraft sid field",
type=str) type=str)

View File

@ -20,7 +20,7 @@ import webbrowser
import pyperclip import pyperclip
import base64 import base64
CONST_APP_VERSION = u"MaxBot (2023.02.26)" CONST_APP_VERSION = u"MaxBot (2023.02.27)"
CONST_SETTINGS_CONFIG_FILENAME = "settings.json" CONST_SETTINGS_CONFIG_FILENAME = "settings.json"