2021-12-01 18:31:19 +00:00
#!/usr/bin/env python3
2019-10-01 17:52:13 +00:00
#encoding=utf-8
2022-11-23 04:39:46 +00:00
# 'seleniumwire' and 'selenium 4' raise error when running python 2.x
# PS: python 2.x will be removed in future.
2022-11-17 18:17:19 +00:00
#執行方式: python chrome_tixcraft.py 或 python3 chrome_tixcraft.py
2021-12-01 18:31:19 +00:00
import os
import sys
import platform
import json
import random
2022-10-20 05:09:32 +00:00
2022-11-16 15:43:53 +00:00
from selenium import webdriver
2019-10-01 17:52:13 +00:00
# for close tab.
from selenium . common . exceptions import NoSuchWindowException
from selenium . common . exceptions import UnexpectedAlertPresentException
from selenium . common . exceptions import NoAlertPresentException
2022-11-17 18:17:19 +00:00
from selenium . common . exceptions import WebDriverException
2019-10-01 17:52:13 +00:00
# for alert 2
from selenium . webdriver . support . ui import WebDriverWait
from selenium . webdriver . support import expected_conditions as EC
2022-11-17 18:17:19 +00:00
from selenium . webdriver . support . ui import Select
from selenium . webdriver . common . by import By
2023-01-11 13:58:55 +00:00
from selenium . webdriver . common . keys import Keys
2021-12-01 18:31:19 +00:00
# for selenium 4
from selenium . webdriver . chrome . service import Service
2023-01-02 06:53:28 +00:00
from selenium . webdriver . common . action_chains import ActionChains
2019-10-01 17:52:13 +00:00
# for wait #1
import time
import re
from datetime import datetime
# for error output
import logging
logging . basicConfig ( )
logger = logging . getLogger ( ' logger ' )
2019-12-14 19:13:20 +00:00
# for check reg_info
import requests
2019-12-18 03:45:48 +00:00
import warnings
from urllib3 . exceptions import InsecureRequestWarning
warnings . simplefilter ( ' ignore ' , InsecureRequestWarning )
2019-10-01 17:52:13 +00:00
2023-01-11 13:58:55 +00:00
# ocr
import base64
2023-01-11 14:26:49 +00:00
try :
import ddddocr
2023-01-14 05:26:42 +00:00
#PS: python 3.11.1 raise PIL conflict.
from NonBrowser import NonBrowser
2023-01-11 14:26:49 +00:00
except Exception as exc :
pass
2023-01-11 13:58:55 +00:00
2023-02-22 16:05:44 +00:00
import webbrowser
2023-02-23 13:33:49 +00:00
import argparse
2023-02-22 16:05:44 +00:00
2021-12-01 18:31:19 +00:00
import ssl
ssl . _create_default_https_context = ssl . _create_unverified_context
2023-02-26 08:39:37 +00:00
CONST_APP_VERSION = u " MaxBot (2023.02.25) "
2022-12-15 11:26:51 +00:00
2022-11-21 19:01:04 +00:00
CONST_HOMEPAGE_DEFAULT = " https://tixcraft.com "
2023-02-09 17:50:34 +00:00
URL_GOOGLE_OAUTH = ' https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount?redirect_uri=https % 3A %2F %2F developers.google.com %2F oauthplayground&prompt=consent&response_type=code&client_id=407408718192.apps.googleusercontent.com&scope=email&access_type=offline&flowName=GeneralOAuthFlow '
2023-02-11 05:36:27 +00:00
CONST_CHROME_VERSION_NOT_MATCH_EN = " Please download the WebDriver version to match your browser version. "
CONST_CHROME_VERSION_NOT_MATCH_TW = " 請下載與您瀏覽器相同版本的WebDriver版本, 或更新您的瀏覽器版本。 "
2023-02-22 23:46:05 +00:00
CONST_KKTIX_SIGN_IN_URL = " https://kktix.com/users/sign_in?back_to= %s "
2023-02-11 05:36:27 +00:00
CONST_CITYLINE_SIGN_IN_URL = " https://www.cityline.com/Login.html?targetUrl=https % 3A %2F %2F www.cityline.com %2F Events.html "
CONST_URBTIX_SIGN_IN_URL = " https://www.urbtix.hk/member-login "
CONST_KHAM_SIGN_IN_URL = " https://kham.com.tw/application/UTK13/UTK1306_.aspx "
2023-02-12 09:49:55 +00:00
CONST_HKTICKETING_SIGN_IN_URL = " https://premier.hkticketing.com/Membership/Login.aspx "
2019-10-01 17:52:13 +00:00
CONST_FROM_TOP_TO_BOTTOM = u " from top to bottom "
CONST_FROM_BOTTOM_TO_TOP = u " from bottom to top "
CONST_RANDOM = u " random "
CONST_SELECT_ORDER_DEFAULT = CONST_FROM_TOP_TO_BOTTOM
CONST_SELECT_OPTIONS_DEFAULT = ( CONST_FROM_TOP_TO_BOTTOM , CONST_FROM_BOTTOM_TO_TOP , CONST_RANDOM )
CONST_SELECT_OPTIONS_ARRAY = [ CONST_FROM_TOP_TO_BOTTOM , CONST_FROM_BOTTOM_TO_TOP , CONST_RANDOM ]
2022-02-18 18:53:55 +00:00
CONT_STRING_1_SEATS_REMAINING = [ u ' @1 seat(s) remaining ' , u ' 剩餘 1@ ' , u ' @1 席残り ' ]
2021-03-21 06:14:20 +00:00
2023-02-12 03:02:16 +00:00
CONST_OCR_CAPTCH_IMAGE_SOURCE_NON_BROWSER = " NonBrowser "
CONST_OCR_CAPTCH_IMAGE_SOURCE_CANVAS = " canvas "
CONST_WEBDRIVER_TYPE_SELENIUM = " selenium "
#CONST_WEBDRIVER_TYPE_STEALTH = "stealth"
CONST_WEBDRIVER_TYPE_UC = " undetected_chromedriver "
2023-02-23 13:33:49 +00:00
def t_or_f ( arg ) :
ret = False
ua = str ( arg ) . upper ( )
if ' TRUE ' . startswith ( ua ) :
ret = True
elif ' YES ' . startswith ( ua ) :
ret = True
return ret
2023-02-11 05:36:27 +00:00
def sx ( s1 ) :
key = 18
return ' ' . join ( chr ( ord ( a ) ^ key ) for a in s1 )
def decryptMe ( b ) :
s = " "
if ( len ( b ) > 0 ) :
s = sx ( base64 . b64decode ( b ) . decode ( " UTF-8 " ) )
return s
2023-02-23 13:33:49 +00:00
def encryptMe ( s ) :
data = " "
if ( len ( s ) > 0 ) :
data = base64 . b64encode ( sx ( s ) . encode ( ' UTF-8 ' ) ) . decode ( " UTF-8 " )
return data
2022-01-12 17:14:27 +00:00
def get_app_root ( ) :
# 讀取檔案裡的參數值
basis = " "
if hasattr ( sys , ' frozen ' ) :
basis = sys . executable
else :
basis = sys . argv [ 0 ]
app_root = os . path . dirname ( basis )
return app_root
2023-02-23 13:33:49 +00:00
def get_config_dict ( args ) :
2022-01-12 17:14:27 +00:00
config_json_filename = ' settings.json '
app_root = get_app_root ( )
config_filepath = os . path . join ( app_root , config_json_filename )
2023-02-23 13:33:49 +00:00
# allow assign config by command line.
if not args . input is None :
if len ( args . input ) > 0 :
config_filepath = args . input
2022-01-12 17:14:27 +00:00
config_dict = None
if os . path . isfile ( config_filepath ) :
with open ( config_filepath ) as json_data :
config_dict = json . load ( json_data )
2023-02-22 16:05:44 +00:00
2023-02-23 13:33:49 +00:00
# start to overwrite config settings.
if not args . headless is None :
headless_flag = t_or_f ( args . headless )
if headless_flag :
config_dict [ " advanced " ] [ " headless " ] = True
if not args . homepage is None :
if len ( args . homepage ) > 0 :
config_dict [ " homepage " ] = args . homepage
if not args . browser is None :
if len ( args . browser ) > 0 :
config_dict [ " browser " ] = args . browser
if not args . tixcraft_sid is None :
if len ( args . tixcraft_sid ) > 0 :
config_dict [ " advanced " ] [ " tixcraft_sid " ] = encryptMe ( args . tixcraft_sid )
if not args . kktix_account is None :
if len ( args . kktix_account ) > 0 :
config_dict [ " advanced " ] [ " kktix_account " ] = args . kktix_account
if not args . kktix_password is None :
if len ( args . kktix_password ) > 0 :
config_dict [ " advanced " ] [ " kktix_password " ] = args . kktix_password
2023-02-26 08:39:37 +00:00
if not args . ibonqware is None :
if len ( args . ibonqware ) > 0 :
config_dict [ " advanced " ] [ " ibonqware " ] = encryptMe ( args . ibonqware )
2023-02-23 13:33:49 +00:00
2023-02-22 16:05:44 +00:00
# special case for headless.
is_headless_enable = False
if config_dict [ " advanced " ] [ " headless " ] :
# for tixcraft headless.
if len ( config_dict [ " advanced " ] [ " tixcraft_sid " ] ) > 1 :
is_headless_enable = True
else :
print ( " If you are runnig headless mode on tixcraft, you need input your cookie SID. " )
if is_headless_enable :
config_dict [ " ocr_captcha " ] [ " enable " ] = True
config_dict [ " ocr_captcha " ] [ " force_submit " ] = True
2022-01-12 17:14:27 +00:00
return config_dict
2022-11-06 09:10:35 +00:00
def format_keyword_string ( keyword ) :
if not keyword is None :
if len ( keyword ) > 0 :
keyword = keyword . replace ( ' / ' , ' / ' )
2022-11-09 20:16:41 +00:00
keyword = keyword . replace ( ' ' , ' ' )
keyword = keyword . replace ( ' , ' , ' ' )
keyword = keyword . replace ( ' , ' , ' ' )
keyword = keyword . replace ( ' $ ' , ' ' )
2022-11-06 09:10:35 +00:00
keyword = keyword . replace ( ' ' , ' ' ) . lower ( )
return keyword
def find_continuous_number ( text ) :
2023-01-02 20:37:54 +00:00
chars = " 0123456789 "
return find_continuous_pattern ( chars , text )
def find_continuous_text ( text ) :
chars = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "
return find_continuous_pattern ( chars , text )
def find_continuous_pattern ( allowed_char , text ) :
2022-11-06 09:10:35 +00:00
ret = " "
2023-01-02 20:37:54 +00:00
is_allowed_char_start = False
2022-11-06 09:10:35 +00:00
for char in text :
#print("char:", char)
2023-01-02 20:37:54 +00:00
if char in allowed_char :
if len ( ret ) == 0 and not is_allowed_char_start :
is_allowed_char_start = True
if is_allowed_char_start :
2022-11-06 09:10:35 +00:00
ret + = char
else :
# make not continuous
2023-01-02 20:37:54 +00:00
is_allowed_char_start = False
2022-11-06 09:10:35 +00:00
return ret
2022-10-25 16:04:29 +00:00
def get_favoriate_extension_path ( webdriver_path ) :
no_google_analytics_path = os . path . join ( webdriver_path , " no_google_analytics_1.1.0.0.crx " )
2023-01-12 08:55:28 +00:00
no_ad_path = os . path . join ( webdriver_path , " Adblock_3.15.2.0.crx " )
2022-10-25 16:04:29 +00:00
return no_google_analytics_path , no_ad_path
def get_chromedriver_path ( webdriver_path ) :
chromedriver_path = os . path . join ( webdriver_path , " chromedriver " )
if platform . system ( ) . lower ( ) == " windows " :
chromedriver_path = os . path . join ( webdriver_path , " chromedriver.exe " )
return chromedriver_path
2023-02-22 16:05:44 +00:00
def get_chrome_options ( webdriver_path , adblock_plus_enable , browser = " chrome " , headless = False ) :
2022-10-25 16:04:29 +00:00
chrome_options = webdriver . ChromeOptions ( )
2023-02-09 16:22:13 +00:00
if browser == " edge " :
chrome_options = webdriver . EdgeOptions ( )
2023-02-15 14:24:26 +00:00
if browser == " safari " :
chrome_options = webdriver . SafariOptions ( )
2022-10-25 16:04:29 +00:00
2022-11-09 20:16:41 +00:00
# some windows cause: timed out receiving message from renderer
2022-11-17 18:17:19 +00:00
if adblock_plus_enable :
# PS: this is ocx version.
no_google_analytics_path , no_ad_path = get_favoriate_extension_path ( webdriver_path )
2022-10-25 16:04:29 +00:00
2022-11-17 18:17:19 +00:00
if os . path . exists ( no_google_analytics_path ) :
chrome_options . add_extension ( no_google_analytics_path )
if os . path . exists ( no_ad_path ) :
chrome_options . add_extension ( no_ad_path )
2023-02-22 16:05:44 +00:00
if headless :
2023-02-23 13:33:49 +00:00
#chrome_options.add_argument('--headless')
chrome_options . add_argument ( ' --headless=new ' )
2022-10-25 16:04:29 +00:00
chrome_options . add_argument ( ' --disable-features=TranslateUI ' )
chrome_options . add_argument ( ' --disable-translate ' )
chrome_options . add_argument ( ' --lang=zh-TW ' )
# for navigator.webdriver
chrome_options . add_experimental_option ( " excludeSwitches " , [ ' enable-automation ' ] )
2023-01-07 21:43:30 +00:00
# Deprecated chrome option is ignored: useAutomationExtension
#chrome_options.add_experimental_option('useAutomationExtension', False)
2022-11-20 07:57:16 +00:00
chrome_options . add_experimental_option ( " prefs " , { " credentials_enable_service " : False , " profile.password_manager_enabled " : False } )
2022-10-25 16:04:29 +00:00
#caps = DesiredCapabilities().CHROME
caps = chrome_options . to_capabilities ( )
#caps["pageLoadStrategy"] = u"normal" # complete
caps [ " pageLoadStrategy " ] = u " eager " # interactive
#caps["pageLoadStrategy"] = u"none"
#caps["unhandledPromptBehavior"] = u"dismiss and notify" # default
2022-11-20 07:57:16 +00:00
#caps["unhandledPromptBehavior"] = u"ignore"
2022-10-25 16:04:29 +00:00
#caps["unhandledPromptBehavior"] = u"dismiss"
2022-11-20 07:57:16 +00:00
caps [ " unhandledPromptBehavior " ] = u " accept "
2022-10-25 16:04:29 +00:00
2023-02-09 16:22:13 +00:00
return chrome_options , caps
2023-02-22 16:05:44 +00:00
def load_chromdriver_normal ( webdriver_path , driver_type , adblock_plus_enable , headless ) :
2023-02-09 16:22:13 +00:00
chromedriver_path = get_chromedriver_path ( webdriver_path )
2022-10-25 16:04:29 +00:00
chrome_service = Service ( chromedriver_path )
2023-02-22 16:05:44 +00:00
chrome_options , caps = get_chrome_options ( webdriver_path , adblock_plus_enable , headless = headless )
2023-02-09 16:22:13 +00:00
driver = None
try :
# method 6: Selenium Stealth
driver = webdriver . Chrome ( service = chrome_service , options = chrome_options , desired_capabilities = caps )
except Exception as exc :
error_message = str ( exc )
left_part = None
if " Stacktrace: " in error_message :
left_part = error_message . split ( " Stacktrace: " ) [ 0 ]
print ( left_part )
2022-10-25 16:04:29 +00:00
2023-02-09 16:22:13 +00:00
if " This version of ChromeDriver only supports Chrome version " in error_message :
2023-02-11 05:36:27 +00:00
print ( CONST_CHROME_VERSION_NOT_MATCH_EN )
print ( CONST_CHROME_VERSION_NOT_MATCH_TW )
2022-10-25 16:04:29 +00:00
if driver_type == " stealth " :
from selenium_stealth import stealth
# Selenium Stealth settings
stealth ( driver ,
languages = [ " zh-TW " , " zh " ] ,
vendor = " Google Inc. " ,
platform = " Win32 " ,
webgl_vendor = " Intel Inc. " ,
renderer = " Intel Iris OpenGL Engine " ,
fix_hairline = True ,
)
2022-11-20 07:57:16 +00:00
#print("driver capabilities", driver.capabilities)
2022-10-25 16:04:29 +00:00
return driver
2023-02-22 16:05:44 +00:00
def load_chromdriver_uc ( webdriver_path , adblock_plus_enable , headless ) :
2022-10-25 16:04:29 +00:00
import undetected_chromedriver as uc
chromedriver_path = get_chromedriver_path ( webdriver_path )
options = uc . ChromeOptions ( )
options . page_load_strategy = " eager "
2022-11-20 07:57:16 +00:00
2022-10-25 16:04:29 +00:00
#print("strategy", options.page_load_strategy)
2022-11-17 18:17:19 +00:00
if adblock_plus_enable :
no_google_analytics_path , no_ad_path = get_favoriate_extension_path ( webdriver_path )
no_google_analytics_folder_path = no_google_analytics_path . replace ( ' .crx ' , ' ' )
no_ad_folder_path = no_ad_path . replace ( ' .crx ' , ' ' )
load_extension_path = " "
if os . path . exists ( no_google_analytics_folder_path ) :
load_extension_path + = " , " + no_google_analytics_folder_path
if os . path . exists ( no_ad_folder_path ) :
load_extension_path + = " , " + no_ad_folder_path
if len ( load_extension_path ) > 0 :
options . add_argument ( ' --load-extension= ' + load_extension_path [ 1 : ] )
2022-10-25 16:04:29 +00:00
2023-02-22 16:05:44 +00:00
if headless :
2023-02-23 13:33:49 +00:00
#options.add_argument('--headless')
options . add_argument ( ' --headless=new ' )
2022-10-25 16:04:29 +00:00
options . add_argument ( ' --disable-features=TranslateUI ' )
options . add_argument ( ' --disable-translate ' )
options . add_argument ( ' --lang=zh-TW ' )
2022-11-20 07:57:16 +00:00
options . add_argument ( " --password-store=basic " )
options . add_experimental_option ( " prefs " , { " credentials_enable_service " : False , " profile.password_manager_enabled " : False } )
caps = options . to_capabilities ( )
caps [ " unhandledPromptBehavior " ] = u " accept "
2022-11-14 09:26:52 +00:00
driver = None
2022-10-25 16:04:29 +00:00
if os . path . exists ( chromedriver_path ) :
print ( " Use user driver path: " , chromedriver_path )
#driver = uc.Chrome(service=chrome_service, options=options, suppress_welcome=False)
is_local_chrome_browser_lower = False
try :
2022-11-21 20:21:00 +00:00
driver = uc . Chrome ( executable_path = chromedriver_path , options = options , desired_capabilities = caps , suppress_welcome = False )
2022-10-25 16:04:29 +00:00
except Exception as exc :
2023-02-09 16:22:13 +00:00
error_message = str ( exc )
left_part = None
if " Stacktrace: " in error_message :
left_part = error_message . split ( " Stacktrace: " ) [ 0 ]
print ( left_part )
if " This version of ChromeDriver only supports Chrome version " in error_message :
2023-02-11 05:36:27 +00:00
print ( CONST_CHROME_VERSION_NOT_MATCH_EN )
print ( CONST_CHROME_VERSION_NOT_MATCH_TW )
2023-02-09 16:22:13 +00:00
is_local_chrome_browser_lower = True
2022-10-25 16:04:29 +00:00
pass
if is_local_chrome_browser_lower :
print ( " Use local user downloaded chromedriver to lunch chrome browser. " )
driver_type = " selenium "
2022-11-17 18:17:19 +00:00
driver = load_chromdriver_normal ( webdriver_path , driver_type , adblock_plus_enable )
2022-10-25 16:04:29 +00:00
else :
print ( " Oops! web driver not on path: " , chromedriver_path )
print ( ' let uc automatically download chromedriver. ' )
2023-02-18 17:41:02 +00:00
try :
driver = uc . Chrome ( options = options , desired_capabilities = caps , suppress_welcome = False )
except Exception as exc :
error_message = str ( exc )
left_part = None
if " Stacktrace: " in error_message :
left_part = error_message . split ( " Stacktrace: " ) [ 0 ]
print ( left_part )
if " This version of ChromeDriver only supports Chrome version " in error_message :
print ( CONST_CHROME_VERSION_NOT_MATCH_EN )
print ( CONST_CHROME_VERSION_NOT_MATCH_TW )
is_local_chrome_browser_lower = True
pass
2022-10-25 16:04:29 +00:00
if driver is None :
print ( " create web drive object fail! " )
else :
download_dir_path = " . "
params = {
" behavior " : " allow " ,
" downloadPath " : os . path . realpath ( download_dir_path )
}
#print("assign setDownloadBehavior.")
driver . execute_cdp_cmd ( " Page.setDownloadBehavior " , params )
2022-11-20 07:57:16 +00:00
#print("driver capabilities", driver.capabilities)
2022-10-25 16:04:29 +00:00
return driver
2022-11-23 04:39:46 +00:00
def close_browser_tabs ( driver ) :
2022-11-09 10:44:29 +00:00
if not driver is None :
try :
window_handles_count = len ( driver . window_handles )
2022-12-22 17:17:37 +00:00
if window_handles_count > 1 :
2022-11-09 10:44:29 +00:00
driver . switch_to . window ( driver . window_handles [ 1 ] )
driver . close ( )
driver . switch_to . window ( driver . window_handles [ 0 ] )
except Exception as excSwithFail :
pass
2023-02-12 03:02:16 +00:00
def get_driver_by_config ( config_dict ) :
2022-11-16 15:43:53 +00:00
global driver
2022-01-12 17:14:27 +00:00
2022-11-18 22:59:34 +00:00
homepage = None
browser = None
language = " English "
ticket_number = " 2 "
2022-01-12 17:14:27 +00:00
2022-11-18 22:59:34 +00:00
auto_press_next_step_button = False # default not checked.
auto_fill_ticket_number = False # default not checked.
auto_guess_options = False # default not checked.
2022-10-18 18:15:05 +00:00
2022-11-18 22:59:34 +00:00
kktix_area_auto_select_mode = " "
kktix_area_keyword = " "
kktix_date_keyword = " "
2022-03-24 15:22:43 +00:00
2022-11-18 22:59:34 +00:00
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.
2019-10-01 17:52:13 +00:00
2022-11-18 22:59:34 +00:00
area_keyword_1 = " "
area_keyword_2 = " "
area_keyword_3 = " "
area_keyword_4 = " "
2019-10-01 17:52:13 +00:00
2022-11-18 22:59:34 +00:00
date_keyword = " "
2019-12-14 19:13:20 +00:00
2022-11-18 22:59:34 +00:00
date_auto_select_enable = None
date_auto_select_mode = " "
2019-12-14 19:13:20 +00:00
2022-11-18 22:59:34 +00:00
area_auto_select_enable = None
area_auto_select_mode = " "
2022-11-23 04:39:46 +00:00
# read config.
homepage = config_dict [ " homepage " ]
browser = config_dict [ " browser " ]
2022-01-12 17:14:27 +00:00
2022-11-23 04:39:46 +00:00
# output debug message in client side.
ticket_number = str ( config_dict [ " ticket_number " ] )
2022-11-24 21:40:40 +00:00
pass_1_seat_remaining_enable = config_dict [ " pass_1_seat_remaining " ]
2022-11-23 04:39:46 +00:00
# for ["kktix"]
auto_press_next_step_button = config_dict [ " kktix " ] [ " auto_press_next_step_button " ]
auto_fill_ticket_number = config_dict [ " kktix " ] [ " auto_fill_ticket_number " ]
kktix_area_auto_select_mode = config_dict [ " kktix " ] [ " area_mode " ] . strip ( )
if not kktix_area_auto_select_mode in CONST_SELECT_OPTIONS_ARRAY :
kktix_area_auto_select_mode = CONST_SELECT_ORDER_DEFAULT
2022-01-12 17:14:27 +00:00
2022-11-23 04:39:46 +00:00
kktix_area_keyword_1 = config_dict [ " kktix " ] [ " area_keyword_1 " ] . strip ( )
kktix_area_keyword_1_and = config_dict [ " kktix " ] [ " area_keyword_1_and " ] . strip ( )
kktix_area_keyword_2 = config_dict [ " kktix " ] [ " area_keyword_2 " ] . strip ( )
kktix_area_keyword_2_and = config_dict [ " kktix " ] [ " area_keyword_2_and " ] . strip ( )
2022-01-12 17:14:27 +00:00
2022-11-23 04:39:46 +00:00
# disable password brute force attack
# PS: because of the question is always variable.
2022-06-24 17:29:48 +00:00
2022-11-23 04:39:46 +00:00
auto_guess_options = config_dict [ " kktix " ] [ " auto_guess_options " ]
# for ["tixcraft"]
date_auto_select_enable = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " enable " ]
date_auto_select_mode = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " mode " ]
if not date_auto_select_mode in CONST_SELECT_OPTIONS_ARRAY :
date_auto_select_mode = CONST_SELECT_ORDER_DEFAULT
date_keyword = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " date_keyword " ] . strip ( )
area_auto_select_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " enable " ]
area_auto_select_mode = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " mode " ]
if not area_auto_select_mode in CONST_SELECT_OPTIONS_ARRAY :
area_auto_select_mode = CONST_SELECT_ORDER_DEFAULT
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 ( )
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 " ]
2023-02-12 03:02:16 +00:00
driver_type = config_dict [ " webdriver_type " ]
2022-11-23 04:39:46 +00:00
# output config:
print ( " maxbot app version " , CONST_APP_VERSION )
print ( " python version " , platform . python_version ( ) )
2023-01-12 08:51:05 +00:00
print ( " platform " , platform . platform ( ) )
2022-11-23 04:39:46 +00:00
print ( " homepage " , homepage )
print ( " browser " , browser )
print ( " ticket_number " , ticket_number )
2022-11-24 21:40:40 +00:00
print ( " pass_1_seat_remaining " , pass_1_seat_remaining_enable )
2022-11-23 04:39:46 +00:00
print ( " ==[kktix]== " )
2023-01-23 13:32:47 +00:00
print ( config_dict [ " kktix " ] )
2022-11-23 04:39:46 +00:00
print ( " ==[tixcraft]== " )
2023-01-23 13:32:47 +00:00
print ( config_dict [ " tixcraft " ] )
2023-01-12 08:51:05 +00:00
print ( " ==[advanced]== " )
2023-01-23 13:32:47 +00:00
print ( config_dict [ " advanced " ] )
2023-02-12 03:02:16 +00:00
print ( " webdriver_type " , driver_type )
2022-11-23 04:39:46 +00:00
# entry point
if homepage is None :
homepage = " "
if len ( homepage ) == 0 :
homepage = CONST_HOMEPAGE_DEFAULT
Root_Dir = get_app_root ( )
webdriver_path = os . path . join ( Root_Dir , " webdriver " )
print ( " platform.system().lower(): " , platform . system ( ) . lower ( ) )
adblock_plus_enable = config_dict [ " advanced " ] [ " adblock_plus_enable " ]
print ( " adblock_plus_enable: " , adblock_plus_enable )
2023-02-22 16:05:44 +00:00
headless = config_dict [ " advanced " ] [ " headless " ]
2022-11-23 04:39:46 +00:00
if browser == " chrome " :
# method 6: Selenium Stealth
2023-02-12 03:02:16 +00:00
if driver_type != CONST_WEBDRIVER_TYPE_UC :
2023-02-22 16:05:44 +00:00
driver = load_chromdriver_normal ( webdriver_path , driver_type , adblock_plus_enable , headless )
2022-10-18 18:15:05 +00:00
else :
2022-11-23 04:39:46 +00:00
# method 5: uc
# multiprocessing not work bug.
if platform . system ( ) . lower ( ) == " windows " :
if hasattr ( sys , ' frozen ' ) :
from multiprocessing import freeze_support
freeze_support ( )
2023-02-22 16:05:44 +00:00
driver = load_chromdriver_uc ( webdriver_path , adblock_plus_enable , headless )
2022-11-23 04:39:46 +00:00
if browser == " firefox " :
# default os is linux/mac
2023-02-07 16:42:04 +00:00
# download url: https://github.com/mozilla/geckodriver/releases
2022-11-23 04:39:46 +00:00
chromedriver_path = os . path . join ( webdriver_path , " geckodriver " )
if platform . system ( ) . lower ( ) == " windows " :
chromedriver_path = os . path . join ( webdriver_path , " geckodriver.exe " )
2023-02-07 17:07:24 +00:00
if " macos " in platform . platform ( ) . lower ( ) :
if " arm64 " in platform . platform ( ) . lower ( ) :
chromedriver_path = os . path . join ( webdriver_path , " geckodriver_arm " )
2023-02-07 16:42:04 +00:00
webdriver_service = Service ( chromedriver_path )
2023-02-09 16:22:13 +00:00
driver = None
try :
2023-02-23 16:48:28 +00:00
from selenium . webdriver . firefox . options import Options
options = Options ( )
if headless :
options . add_argument ( ' --headless ' )
#options.add_argument('--headless=new')
if platform . system ( ) . lower ( ) == " windows " :
options . binary_location = r ' C: \ Program Files \ Mozilla Firefox \ firefox.exe '
driver = webdriver . Firefox ( service = webdriver_service , options = options )
2023-02-09 16:22:13 +00:00
except Exception as exc :
error_message = str ( exc )
left_part = None
if " Stacktrace: " in error_message :
left_part = error_message . split ( " Stacktrace: " ) [ 0 ]
print ( left_part )
2023-02-23 16:48:28 +00:00
else :
print ( exc )
2023-02-07 16:42:04 +00:00
if browser == " edge " :
# default os is linux/mac
# download url: https://developer.microsoft.com/zh-tw/microsoft-edge/tools/webdriver/
chromedriver_path = os . path . join ( webdriver_path , " msedgedriver " )
if platform . system ( ) . lower ( ) == " windows " :
chromedriver_path = os . path . join ( webdriver_path , " msedgedriver.exe " )
webdriver_service = Service ( chromedriver_path )
2023-02-22 16:05:44 +00:00
chrome_options , caps = get_chrome_options ( webdriver_path , adblock_plus_enable , browser = " edge " , headless = headless )
2023-02-09 16:22:13 +00:00
driver = None
try :
driver = webdriver . Edge ( service = webdriver_service , options = chrome_options )
except Exception as exc :
error_message = str ( exc )
#print(error_message)
left_part = None
if " Stacktrace: " in error_message :
left_part = error_message . split ( " Stacktrace: " ) [ 0 ]
print ( left_part )
2023-02-15 14:24:26 +00:00
if browser == " safari " :
driver = None
try :
driver = webdriver . Safari ( )
except Exception as exc :
error_message = str ( exc )
#print(error_message)
left_part = None
if " Stacktrace: " in error_message :
left_part = error_message . split ( " Stacktrace: " ) [ 0 ]
print ( left_part )
2022-11-23 04:39:46 +00:00
if driver is None :
print ( " create web driver object fail @_@; " )
2022-01-12 17:14:27 +00:00
else :
2022-11-23 04:39:46 +00:00
try :
2023-02-09 17:50:34 +00:00
if config_dict [ " advanced " ] [ " open_google_oauth_url " ] :
driver . execute_script ( " window.open( ' %s ' , ' _blank ' ); " % ( URL_GOOGLE_OAUTH ) ) ;
2023-02-11 05:36:27 +00:00
if ' kktix.c ' in homepage :
if len ( config_dict [ " advanced " ] [ " kktix_account " ] ) > 0 :
2023-02-22 23:46:05 +00:00
if not ' https://kktix.com/users/sign_in? ' in homepage :
homepage = CONST_KKTIX_SIGN_IN_URL % ( homepage )
2023-02-11 05:36:27 +00:00
if ' famiticket.com ' in homepage :
pass
if ' ibon.com ' in homepage :
pass
if ' kham.com ' in homepage :
if len ( config_dict [ " advanced " ] [ " kham_account " ] ) > 0 :
homepage = CONST_KHAM_SIGN_IN_URL
if ' urbtix.hk ' in homepage :
if len ( config_dict [ " advanced " ] [ " urbtix_account " ] ) > 0 :
homepage = CONST_URBTIX_SIGN_IN_URL
if ' cityline.com ' in homepage :
if len ( config_dict [ " advanced " ] [ " cityline_account " ] ) > 0 :
homepage = CONST_CITYLINE_SIGN_IN_URL
if ' hkticketing.com ' in homepage :
2023-02-12 09:49:55 +00:00
if len ( config_dict [ " advanced " ] [ " hkticketing_account " ] ) > 0 :
homepage = CONST_HKTICKETING_SIGN_IN_URL
2023-02-11 05:36:27 +00:00
if ' galaxymacau.com ' in homepage :
pass
2023-02-22 23:46:05 +00:00
print ( " goto url: " , homepage )
2022-11-23 04:39:46 +00:00
driver . get ( homepage )
2023-02-22 16:05:44 +00:00
tixcraft_family = False
if ' tixcraft.com ' in homepage :
tixcraft_family = True
if ' indievox.com ' in homepage :
tixcraft_family = True
if tixcraft_family :
if len ( config_dict [ " advanced " ] [ " tixcraft_sid " ] ) > 1 :
tixcraft_sid = decryptMe ( config_dict [ " advanced " ] [ " tixcraft_sid " ] )
driver . delete_cookie ( " SID " )
driver . add_cookie ( { " name " : " SID " , " value " : tixcraft_sid , " path " : " / " , " secure " : True } )
2023-02-26 08:39:37 +00:00
if ' ibon.com ' in homepage :
if len ( config_dict [ " advanced " ] [ " ibonqware " ] ) > 1 :
ibonqware = decryptMe ( config_dict [ " advanced " ] [ " ibonqware " ] )
driver . delete_cookie ( " ibonqware " )
driver . add_cookie ( { " name " : " ibonqware " , " value " : ibonqware , " domain " : " ibon.com.tw " , " secure " : True } )
2022-11-23 04:39:46 +00:00
except WebDriverException as exce2 :
print ( ' oh no not again, WebDriverException ' )
print ( ' WebDriverException: ' , exce2 )
except Exception as exce1 :
2023-02-09 17:50:34 +00:00
print ( ' get URL Exception: ' , exce1 )
2022-11-23 04:39:46 +00:00
pass
2021-12-24 10:52:37 +00:00
2022-01-12 17:14:27 +00:00
return driver
2019-10-01 17:52:13 +00:00
# common functions.
def find_between ( s , first , last ) :
try :
start = s . index ( first ) + len ( first )
end = s . index ( last , start )
return s [ start : end ]
except ValueError :
return " "
# convert web string to reg pattern
def convert_string_to_pattern ( my_str , dynamic_length = True ) :
my_hint_anwser_length = len ( my_str )
my_formated = " "
if my_hint_anwser_length > 0 :
my_anwser_symbols = u " ()[]<> {} - "
for idx in range ( my_hint_anwser_length ) :
char = my_str [ idx : idx + 1 ]
if char in my_anwser_symbols :
my_formated + = ( u ' \\ ' + char )
continue
pattern = re . compile ( u " [A-Z] " )
match_result = pattern . match ( char )
#print("match_result A:", match_result)
if not match_result is None :
my_formated + = u " [A-Z] "
pattern = re . compile ( u " [a-z] " )
match_result = pattern . match ( char )
#print("match_result a:", match_result)
if not match_result is None :
my_formated + = u " [a-z] "
pattern = re . compile ( u " [ \ d] " )
match_result = pattern . match ( char )
#print("match_result d:", match_result)
if not match_result is None :
my_formated + = u " [ \ d] "
# for dynamic length
if dynamic_length :
for i in range ( 10 ) :
my_formated = my_formated . replace ( u " [A-Z][A-Z] " , u " [A-Z] " )
my_formated = my_formated . replace ( u " [a-z][a-z] " , u " [a-z] " )
my_formated = my_formated . replace ( u " [ \ d][ \ d] " , u " [ \ d] " )
my_formated = my_formated . replace ( u " [A-Z] " , u " [A-Z]+ " )
my_formated = my_formated . replace ( u " [a-z] " , u " [a-z]+ " )
my_formated = my_formated . replace ( u " [ \ d] " , u " [ \ d]+ " )
return my_formated
2023-01-02 20:37:54 +00:00
def guess_answer_list_from_multi_options ( tmp_text ) :
2023-02-04 16:23:01 +00:00
show_debug_message = True # debug.
show_debug_message = False # online
2023-01-02 20:37:54 +00:00
options_list = None
2023-02-04 16:23:01 +00:00
matched_pattern = " "
2023-01-02 20:37:54 +00:00
if options_list is None :
if u ' 【 ' in tmp_text and u ' 】 ' in tmp_text :
2023-02-04 16:23:01 +00:00
pattern = ' 【.*?】 '
options_list = re . findall ( pattern , tmp_text )
2023-01-02 20:37:54 +00:00
if len ( options_list ) < = 2 :
options_list = None
2023-02-04 16:23:01 +00:00
else :
matched_pattern = pattern
2023-01-02 20:37:54 +00:00
if options_list is None :
if u ' ( ' in tmp_text and u ' ) ' in tmp_text :
2023-02-04 16:23:01 +00:00
pattern = ' \ (.*? \ ) '
options_list = re . findall ( pattern , tmp_text )
2023-01-02 20:37:54 +00:00
if len ( options_list ) < = 2 :
options_list = None
2023-02-04 16:23:01 +00:00
else :
matched_pattern = pattern
2023-01-02 20:37:54 +00:00
if options_list is None :
if u ' [ ' in tmp_text and u ' ] ' in tmp_text :
2023-02-04 16:23:01 +00:00
pattern = ' \ [.*? \ ] '
options_list = re . findall ( pattern , tmp_text )
2023-01-02 20:37:54 +00:00
if len ( options_list ) < = 2 :
options_list = None
2023-02-04 16:23:01 +00:00
else :
matched_pattern = pattern
if show_debug_message :
print ( " matched pattern: " , matched_pattern )
# default remove quota
is_trim_quota = not check_answer_keep_symbol ( tmp_text )
if show_debug_message :
print ( " is_trim_quota: " , is_trim_quota )
2023-01-02 20:37:54 +00:00
return_list = None
2023-01-03 22:12:21 +00:00
if not options_list is None :
options_list_length = len ( options_list )
2023-02-04 16:23:01 +00:00
if show_debug_message :
print ( " options_list_length: " , options_list_length )
print ( " options_list: " , options_list )
2023-01-03 22:12:21 +00:00
if options_list_length > 2 :
is_all_options_same_length = True
2023-02-04 16:23:01 +00:00
options_length_count = { }
2023-01-03 22:12:21 +00:00
for i in range ( options_list_length - 1 ) :
2023-02-04 16:23:01 +00:00
current_option_length = len ( options_list [ i ] )
next_option_length = len ( options_list [ i + 1 ] )
if current_option_length != next_option_length :
2023-01-03 22:12:21 +00:00
is_all_options_same_length = False
2023-02-04 16:23:01 +00:00
if current_option_length in options_length_count :
options_length_count [ current_option_length ] + = 1
else :
options_length_count [ current_option_length ] = 1
if show_debug_message :
print ( " is_all_options_same_length: " , is_all_options_same_length )
2023-01-03 22:12:21 +00:00
if is_all_options_same_length :
return_list = [ ]
for each_option in options_list :
2023-02-04 16:23:01 +00:00
if is_trim_quota :
return_list . append ( each_option [ 1 : - 1 ] )
else :
return_list . append ( each_option )
else :
#print("options_length_count:", options_length_count)
if len ( options_length_count ) > 0 :
target_option_length = 0
most_length_count = 0
for k in options_length_count . keys ( ) :
if options_length_count [ k ] > most_length_count :
most_length_count = options_length_count [ k ]
target_option_length = k
#print("most_length_count:", most_length_count)
#print("target_option_length:", target_option_length)
if target_option_length > 0 :
return_list = [ ]
for each_option in options_list :
current_option_length = len ( each_option )
if current_option_length == target_option_length :
if is_trim_quota :
return_list . append ( each_option [ 1 : - 1 ] )
else :
return_list . append ( each_option )
# something is wrong, give up those options.
if not return_list is None :
if len ( return_list ) < = 2 :
return_list = None
2023-01-02 20:37:54 +00:00
return return_list
#PS: this may get a wrong answer list. XD
def guess_answer_list_from_symbols ( captcha_text_div_text ) :
return_list = None
# need replace to space to get first options.
tmp_text = captcha_text_div_text
tmp_text = tmp_text . replace ( u ' ? ' , u ' ' )
tmp_text = tmp_text . replace ( u ' ? ' , u ' ' )
tmp_text = tmp_text . replace ( u ' 。 ' , u ' ' )
delimitor_symbols_left = [ u " ( " , u " [ " , u " { " , " " , " " , " " , " " ]
delimitor_symbols_right = [ u " ) " , u " ] " , u " } " , " : " , " . " , " ) " , " - " ]
idx = - 1
for idx in range ( len ( delimitor_symbols_left ) ) :
symbol_left = delimitor_symbols_left [ idx ]
symbol_right = delimitor_symbols_right [ idx ]
if symbol_left in tmp_text and symbol_right in tmp_text and u ' 半形 ' in tmp_text :
hint_list = re . findall ( u ' \\ ' + symbol_left + u ' [ \\ w]+ \\ ' + symbol_right , tmp_text )
#print("hint_list:", hint_list)
if not hint_list is None :
if len ( hint_list ) > 1 :
return_list = [ ]
my_answer_delimitor = symbol_right
for options in hint_list :
if len ( options ) > 2 :
my_anwser = options [ 1 : - 1 ]
#print("my_anwser:",my_anwser)
if len ( my_anwser ) > 0 :
return_list . append ( my_anwser )
if not return_list is None :
break
return return_list
def get_offical_hint_string_from_symbol ( symbol , tmp_text ) :
show_debug_message = True # debug.
show_debug_message = False # online
offical_hint_string = " "
if symbol in tmp_text :
# start to guess offical hint
if offical_hint_string == " " :
if u ' 【 ' in tmp_text and u ' 】 ' in tmp_text :
hint_list = re . findall ( u ' 【.*?】 ' , tmp_text )
if not hint_list is None :
if show_debug_message :
print ( " 【.*?】hint_list: " , hint_list )
for hint in hint_list :
if symbol in hint :
offical_hint_string = hint [ 1 : - 1 ]
break
if offical_hint_string == " " :
if u ' ( ' in tmp_text and u ' ) ' in tmp_text :
hint_list = re . findall ( u ' \ (.*? \ ) ' , tmp_text )
if not hint_list is None :
if show_debug_message :
print ( " \ (.*? \ )hint_list: " , hint_list )
for hint in hint_list :
if symbol in hint :
offical_hint_string = hint [ 1 : - 1 ]
break
if offical_hint_string == " " :
if u ' [ ' in tmp_text and u ' ] ' in tmp_text :
hint_list = re . findall ( u ' [.*?] ' , tmp_text )
if not hint_list is None :
if show_debug_message :
print ( " [.*?]hint_list: " , hint_list )
for hint in hint_list :
if symbol in hint :
offical_hint_string = hint [ 1 : - 1 ]
break
if offical_hint_string == " " :
offical_hint_string = tmp_text
return offical_hint_string
2023-01-14 08:05:00 +00:00
def guess_answer_list_from_hint ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , captcha_text_div_text ) :
2023-01-02 20:37:54 +00:00
show_debug_message = True # debug.
show_debug_message = False # online
2019-10-01 17:52:13 +00:00
return_list = None
2023-01-02 20:37:54 +00:00
2023-01-14 08:05:00 +00:00
tmp_text = format_question_string ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , captcha_text_div_text )
2023-01-02 20:37:54 +00:00
my_question = " "
my_options = " "
offical_hint_string = " "
offical_hint_string_anwser = " "
my_anwser_formated = " "
2019-10-01 17:52:13 +00:00
my_answer_delimitor = " "
2023-01-02 20:37:54 +00:00
if my_question == " " :
if u " ? " in tmp_text :
question_index = tmp_text . find ( u " ? " )
2019-10-01 17:52:13 +00:00
my_question = tmp_text [ : question_index + 1 ]
2023-01-02 20:37:54 +00:00
if my_question == " " :
2019-10-01 17:52:13 +00:00
if u " 。 " in tmp_text :
question_index = tmp_text . find ( u " 。 " )
my_question = tmp_text [ : question_index + 1 ]
2023-01-02 20:37:54 +00:00
if my_question == " " :
my_question = tmp_text
#print(u"my_question:", my_question)
# ps: hint_list is not options list
if offical_hint_string == " " :
2023-02-04 16:23:01 +00:00
# for: 若你覺得答案為 a, 請輸入 a
if ' 答案 ' in tmp_text and CONST_INPUT_SYMBOL in tmp_text :
offical_hint_string = get_offical_hint_string_from_symbol ( CONST_INPUT_SYMBOL , tmp_text )
2023-01-02 20:37:54 +00:00
if len ( offical_hint_string ) > 0 :
2023-02-04 16:23:01 +00:00
right_part = offical_hint_string . split ( CONST_INPUT_SYMBOL ) [ 1 ]
#print("right_part:", right_part)
2023-01-02 20:37:54 +00:00
if len ( offical_hint_string ) == len ( tmp_text ) :
offical_hint_string = right_part
new_hint = find_continuous_text ( right_part )
if len ( new_hint ) > 0 :
2023-02-04 16:23:01 +00:00
# TODO: 答案為B需填入Bb)
#if u'答案' in offical_hint_string and CONST_INPUT_SYMBOL in offical_hint_string:
2023-01-02 20:37:54 +00:00
offical_hint_string_anwser = new_hint
2023-02-04 16:23:01 +00:00
2023-01-02 20:37:54 +00:00
if offical_hint_string == " " :
2023-02-04 16:23:01 +00:00
offical_hint_string = get_offical_hint_string_from_symbol ( CONST_EXAMPLE_SYMBOL , tmp_text )
2023-01-02 20:37:54 +00:00
if len ( offical_hint_string ) > 0 :
2023-02-04 16:23:01 +00:00
right_part = offical_hint_string . split ( CONST_EXAMPLE_SYMBOL ) [ 1 ]
2023-01-02 20:37:54 +00:00
if len ( offical_hint_string ) == len ( tmp_text ) :
offical_hint_string = right_part
2023-02-04 16:23:01 +00:00
# PS: find first text will only get B char in this case: 答案為B需填入Bb)
2023-01-02 20:37:54 +00:00
new_hint = find_continuous_text ( right_part )
if len ( new_hint ) > 0 :
offical_hint_string_anwser = new_hint
2022-10-18 18:15:05 +00:00
2023-02-04 21:56:58 +00:00
# resize offical_hint_string_anwser for options contains in hint string.
#print("offical_hint_string_anwser:", offical_hint_string_anwser)
if len ( offical_hint_string_anwser ) > 0 :
offical_hint_string = offical_hint_string . split ( offical_hint_string_anwser ) [ 0 ]
2023-02-04 16:23:01 +00:00
2023-01-02 20:37:54 +00:00
if show_debug_message :
2023-02-04 21:56:58 +00:00
print ( " offical_hint_string: " , offical_hint_string )
2023-01-02 20:37:54 +00:00
# try rule4:
# get hint from rule 3: without '(' & '), but use "*"
if len ( offical_hint_string ) == 0 :
target_symbol = u " * "
if target_symbol in tmp_text :
star_index = tmp_text . find ( target_symbol )
space_index = tmp_text . find ( u " " , star_index + len ( target_symbol ) )
offical_hint_string = tmp_text [ star_index : space_index ]
# is need to merge next block
if len ( offical_hint_string ) > 0 :
2023-02-04 16:23:01 +00:00
target_symbol = offical_hint_string + " "
2023-01-02 20:37:54 +00:00
if target_symbol in tmp_text :
star_index = tmp_text . find ( target_symbol )
next_block_index = star_index + len ( target_symbol )
space_index = tmp_text . find ( u " " , next_block_index )
next_block = tmp_text [ next_block_index : space_index ]
if CONST_EXAMPLE_SYMBOL in next_block :
offical_hint_string + = u ' ' + next_block
# try rule5:
# get hint from rule 3: n個半形英文大寫
if len ( offical_hint_string ) == 0 :
target_symbol = u " 個半形英文大寫 "
if target_symbol in tmp_text :
star_index = tmp_text . find ( target_symbol )
space_index = tmp_text . find ( u " " , star_index )
answer_char_count = tmp_text [ star_index - 1 : star_index ]
if answer_char_count . isnumeric ( ) :
star_index - = 1
offical_hint_string_anwser = u ' A ' * int ( answer_char_count )
offical_hint_string = tmp_text [ star_index : space_index ]
target_symbol = u " 個英文大寫 "
if target_symbol in tmp_text :
star_index = tmp_text . find ( target_symbol )
space_index = tmp_text . find ( u " " , star_index )
answer_char_count = tmp_text [ star_index - 1 : star_index ]
if answer_char_count . isnumeric ( ) :
star_index - = 1
offical_hint_string_anwser = u ' A ' * int ( answer_char_count )
offical_hint_string = tmp_text [ star_index : space_index ]
target_symbol = u " 個半形英文小寫 "
if target_symbol in tmp_text :
star_index = tmp_text . find ( target_symbol )
space_index = tmp_text . find ( u " " , star_index )
answer_char_count = tmp_text [ star_index - 1 : star_index ]
if answer_char_count . isnumeric ( ) :
star_index - = 1
offical_hint_string_anwser = u ' a ' * int ( answer_char_count )
offical_hint_string = tmp_text [ star_index : space_index ]
target_symbol = u " 個英文小寫 "
if target_symbol in tmp_text :
star_index = tmp_text . find ( target_symbol )
space_index = tmp_text . find ( u " " , star_index )
answer_char_count = tmp_text [ star_index - 1 : star_index ]
if answer_char_count . isnumeric ( ) :
star_index - = 1
offical_hint_string_anwser = u ' a ' * int ( answer_char_count )
offical_hint_string = tmp_text [ star_index : space_index ]
target_symbol = u " 個英數半形字 "
if target_symbol in tmp_text :
star_index = tmp_text . find ( target_symbol )
space_index = tmp_text . find ( u " " , star_index )
answer_char_count = tmp_text [ star_index - 1 : star_index ]
if answer_char_count . isnumeric ( ) :
star_index - = 1
my_anwser_formated = u ' [A-Za-z \ d] ' * int ( answer_char_count )
offical_hint_string = tmp_text [ star_index : space_index ]
target_symbol = u " 個半形 "
if target_symbol in tmp_text :
star_index = tmp_text . find ( target_symbol )
space_index = tmp_text . find ( u " " , star_index )
answer_char_count = tmp_text [ star_index - 1 : star_index ]
if answer_char_count . isnumeric ( ) :
star_index - = 1
my_anwser_formated = u ' [A-Za-z \ d] ' * int ( answer_char_count )
offical_hint_string = tmp_text [ star_index : space_index ]
if len ( offical_hint_string ) > 0 :
2023-02-04 16:23:01 +00:00
if show_debug_message :
print ( " offical_hint_string_anwser: " , offical_hint_string_anwser )
2023-01-02 20:37:54 +00:00
my_anwser_formated = convert_string_to_pattern ( offical_hint_string_anwser )
my_options = tmp_text
if len ( my_question ) < len ( tmp_text ) :
2019-10-01 17:52:13 +00:00
my_options = my_options . replace ( my_question , u " " )
2023-01-02 20:37:54 +00:00
my_options = my_options . replace ( offical_hint_string , u " " )
# try rule7:
# check is chinese/english in question, if match, apply my_options rule.
if len ( offical_hint_string ) > 0 :
tmp_text_org = captcha_text_div_text
if CONST_EXAMPLE_SYMBOL in tmp_text :
tmp_text_org = tmp_text_org . replace ( u ' Ex: ' , ' ex: ' )
target_symbol = u " ex: "
if target_symbol in tmp_text_org :
star_index = tmp_text_org . find ( target_symbol )
my_options = tmp_text_org [ star_index - 1 : ]
2023-02-04 16:23:01 +00:00
if show_debug_message :
print ( " tmp_text: " , tmp_text )
print ( " my_options: " , my_options )
2023-01-02 20:37:54 +00:00
if len ( my_anwser_formated ) > 0 :
allow_delimitor_symbols = " )].: } "
pattern = re . compile ( my_anwser_formated )
search_result = pattern . search ( my_options )
if not search_result is None :
( span_start , span_end ) = search_result . span ( )
if len ( my_options ) > ( span_end + 1 ) + 1 :
maybe_delimitor = my_options [ span_end + 0 : span_end + 1 ]
if maybe_delimitor in allow_delimitor_symbols :
my_answer_delimitor = maybe_delimitor
2023-02-04 16:23:01 +00:00
if show_debug_message :
print ( u " my_answer_delimitor: " , my_answer_delimitor )
# default remove quota
is_trim_quota = not check_answer_keep_symbol ( tmp_text )
if show_debug_message :
print ( " is_trim_quota: " , is_trim_quota )
2023-01-02 20:37:54 +00:00
if len ( my_anwser_formated ) > 0 :
new_pattern = my_anwser_formated
if len ( my_answer_delimitor ) > 0 :
new_pattern = my_anwser_formated + u ' \\ ' + my_answer_delimitor
2023-02-04 16:23:01 +00:00
2023-01-02 20:37:54 +00:00
return_list = re . findall ( new_pattern , my_options )
2023-02-04 16:23:01 +00:00
if show_debug_message :
print ( " my_anwser_formated: " , my_anwser_formated )
print ( " new_pattern: " , new_pattern )
print ( " return_list: " , return_list )
2023-01-02 20:37:54 +00:00
if not return_list is None :
if len ( return_list ) == 1 :
# re-sample for this case.
return_list = re . findall ( my_anwser_formated , my_options )
2023-02-04 16:23:01 +00:00
# clean delimitor
if is_trim_quota :
return_list_length = len ( return_list )
if return_list_length > = 1 :
if len ( my_answer_delimitor ) > 0 :
for idx in range ( return_list_length ) :
return_list [ idx ] = return_list [ idx ] . replace ( my_answer_delimitor , ' ' )
if show_debug_message :
print ( " cleaned return_list: " , return_list )
2023-01-02 20:37:54 +00:00
return return_list
2023-01-14 08:05:00 +00:00
def format_question_string ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , captcha_text_div_text ) :
2023-01-02 20:37:54 +00:00
tmp_text = captcha_text_div_text
tmp_text = tmp_text . replace ( u ' ' , u ' ' )
tmp_text = tmp_text . replace ( u ' : ' , u ' : ' )
# for hint
tmp_text = tmp_text . replace ( u ' * ' , u ' * ' )
# replace ex.
tmp_text = tmp_text . replace ( u ' 例如 ' , CONST_EXAMPLE_SYMBOL )
tmp_text = tmp_text . replace ( u ' 如: ' , CONST_EXAMPLE_SYMBOL )
2023-01-14 08:05:00 +00:00
tmp_text = tmp_text . replace ( u ' 如為 ' , CONST_EXAMPLE_SYMBOL + ' 為 ' )
2023-01-02 20:37:54 +00:00
tmp_text = tmp_text . replace ( u ' 舉例 ' , CONST_EXAMPLE_SYMBOL )
if not CONST_EXAMPLE_SYMBOL in tmp_text :
tmp_text = tmp_text . replace ( u ' 例 ' , CONST_EXAMPLE_SYMBOL )
# important, maybe 例 & ex occurs at same time.
tmp_text = tmp_text . replace ( u ' ex: ' , CONST_EXAMPLE_SYMBOL )
tmp_text = tmp_text . replace ( u ' Ex: ' , CONST_EXAMPLE_SYMBOL )
#若你覺得
#PS:這個,可能會造成更多問題,呵呵。
SYMBOL_IF_LIST = [ ' 假設 ' , ' 如果 ' , ' 若 ' ]
for symbol_if in SYMBOL_IF_LIST :
if symbol_if in tmp_text and ' 答案 ' in tmp_text :
tmp_text = tmp_text . replace ( ' 覺得 ' , ' ' )
tmp_text = tmp_text . replace ( ' 認為 ' , ' ' )
tmp_text = tmp_text . replace ( symbol_if + ' 你答案 ' , CONST_EXAMPLE_SYMBOL + ' 答案 ' )
tmp_text = tmp_text . replace ( symbol_if + ' 答案 ' , CONST_EXAMPLE_SYMBOL + ' 答案 ' )
tmp_text = tmp_text . replace ( u ' 填入 ' , CONST_INPUT_SYMBOL )
#tmp_text = tmp_text.replace(u'[',u'(')
#tmp_text = tmp_text.replace(u']',u')')
tmp_text = tmp_text . replace ( u ' ? ' , u ' ? ' )
tmp_text = tmp_text . replace ( u ' ( ' , u ' ( ' )
tmp_text = tmp_text . replace ( u ' ) ' , u ' ) ' )
return tmp_text
2023-01-14 08:05:00 +00:00
def get_answer_list_by_question ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , captcha_text_div_text ) :
2023-02-04 16:23:01 +00:00
show_debug_message = True # debug.
show_debug_message = False # online
2023-01-02 20:37:54 +00:00
return_list = None
2023-01-14 08:05:00 +00:00
tmp_text = format_question_string ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , captcha_text_div_text )
2023-01-02 20:37:54 +00:00
# guess answer list from multi-options: 【】() []
if return_list is None :
return_list = guess_answer_list_from_multi_options ( tmp_text )
2023-02-04 16:23:01 +00:00
if show_debug_message :
if not return_list is None :
print ( " guess_answer_list_from_multi_options: " , return_list )
2023-01-02 20:37:54 +00:00
if return_list is None :
2023-01-14 08:05:00 +00:00
return_list = guess_answer_list_from_hint ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , captcha_text_div_text )
2023-02-04 16:23:01 +00:00
if show_debug_message :
if not return_list is None :
print ( " guess_answer_list_from_hint: " , return_list )
2023-01-02 20:37:54 +00:00
if return_list is None :
return_list = guess_answer_list_from_symbols ( captcha_text_div_text )
2023-02-04 16:23:01 +00:00
if show_debug_message :
if not return_list is None :
print ( " guess_answer_list_from_symbols: " , return_list )
2023-01-02 20:37:54 +00:00
return return_list
2019-10-01 17:52:13 +00:00
2023-02-26 08:39:37 +00:00
def force_press_button ( driver , select_by , select_query , force_by_js = True ) :
ret = False
next_step_button = None
try :
next_step_button = driver . find_element ( select_by , select_query )
if not next_step_button is None :
if next_step_button . is_enabled ( ) :
next_step_button . click ( )
ret = True
except Exception as exc :
print ( " find %s clickable Exception: " % ( select_query ) )
#print(exc)
pass
if force_by_js :
if not next_step_button is None :
is_visible = False
try :
if next_step_button . is_enabled ( ) :
is_visible = True
except Exception as exc :
pass
if is_visible :
try :
driver . execute_script ( " arguments[0].click(); " , next_step_button )
ret = True
except Exception as exc :
pass
return ret
2022-11-09 10:44:29 +00:00
# close some div on home url.
2023-02-18 16:41:30 +00:00
def tixcraft_home_close_window ( driver ) :
2023-01-13 19:01:47 +00:00
show_debug_message = True # debug.
show_debug_message = False # online
2022-11-09 10:44:29 +00:00
accept_all_cookies_btn = None
try :
accept_all_cookies_btn = driver . find_element ( By . ID , ' onetrust-accept-btn-handler ' )
except Exception as exc :
2023-01-13 19:01:47 +00:00
if show_debug_message :
print ( " find accept_all_cookies_btn fail " )
2022-11-09 10:44:29 +00:00
pass
if accept_all_cookies_btn is not None :
2022-11-09 18:36:17 +00:00
is_visible = False
try :
2023-02-23 13:33:49 +00:00
if accept_all_cookies_btn . is_enabled ( ) and accept_all_cookies_btn . is_displayed ( ) :
2022-11-09 18:36:17 +00:00
is_visible = True
except Exception as exc :
pass
if is_visible :
2023-01-13 19:01:47 +00:00
if show_debug_message :
print ( " accept_all_cookies_btn visible. start to press. " )
2022-11-09 10:44:29 +00:00
try :
accept_all_cookies_btn . click ( )
except Exception as exc :
2023-02-09 16:22:13 +00:00
print ( " try to click accept_all_cookies_btn fail, force click by js. " )
2022-11-09 10:44:29 +00:00
try :
driver . execute_script ( " arguments[0].click(); " , accept_all_cookies_btn )
except Exception as exc :
pass
2023-01-13 19:01:47 +00:00
else :
if show_debug_message :
print ( " accept_all_cookies_btn invisible. " )
2022-11-09 10:44:29 +00:00
close_all_alert_btns = None
try :
close_all_alert_btns = driver . find_elements ( By . CSS_SELECTOR , " [class= ' close-alert ' ] " )
except Exception as exc :
print ( " find close_all_alert_btns fail " )
if close_all_alert_btns is not None :
#print('alert count:', len(close_all_alert_btns))
for alert_btn in close_all_alert_btns :
2022-11-09 18:36:17 +00:00
# fix bug: Message: stale element reference: element is not attached to the page document
is_visible = False
try :
if alert_btn . is_enabled ( ) and alert_btn . is_displayed ( ) :
is_visible = True
except Exception as exc :
pass
if is_visible :
2022-11-09 10:44:29 +00:00
try :
alert_btn . click ( )
except Exception as exc :
2023-02-09 16:22:13 +00:00
print ( " try to click alert_btn fail, force click by js. " )
2022-11-09 10:44:29 +00:00
try :
driver . execute_script ( " arguments[0].click(); " , alert_btn )
except Exception as exc :
pass
2019-10-01 17:52:13 +00:00
# from detail to game
2022-01-12 17:14:27 +00:00
def tixcraft_redirect ( driver , url ) :
2022-03-24 15:22:43 +00:00
ret = False
2019-10-01 17:52:13 +00:00
game_name = " "
# get game_name from url
2023-01-11 13:58:55 +00:00
url_split = url . split ( " / " )
if len ( url_split ) > = 6 :
game_name = url_split [ 5 ]
2019-10-01 17:52:13 +00:00
2020-07-25 20:35:54 +00:00
if " /activity/detail/ %s " % ( game_name , ) in url :
2020-02-03 15:51:05 +00:00
# to support teamear
2020-07-25 20:35:54 +00:00
entry_url = url . replace ( " /activity/detail/ " , " /activity/game/ " )
2022-06-24 17:29:48 +00:00
print ( " redirec to new url: " , entry_url )
try :
driver . get ( entry_url )
except Exception as exec1 :
pass
2022-03-24 15:22:43 +00:00
ret = True
return ret
2023-02-09 16:22:13 +00:00
def tixcraft_date_auto_select ( driver , url , config_dict , domain_name ) :
2023-01-03 18:54:42 +00:00
show_debug_message = True # debug.
2023-01-12 08:51:05 +00:00
show_debug_message = False # online
2023-01-03 18:54:42 +00:00
2022-11-16 15:43:53 +00:00
# read config.
date_auto_select_mode = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " mode " ]
2022-11-18 22:59:34 +00:00
date_keyword = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " date_keyword " ] . strip ( )
2022-11-16 15:43:53 +00:00
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 " ]
2022-03-17 01:15:05 +00:00
# PS: for big events, check sold out text maybe not helpful, due to database is too busy.
2022-03-24 15:22:43 +00:00
sold_out_text_list = [ " 選購一空 " , " No tickets available " , " 空席なし " ]
2022-10-18 18:15:05 +00:00
2019-10-01 17:52:13 +00:00
game_name = " "
2020-07-25 20:35:54 +00:00
if " /activity/game/ " in url :
2019-10-01 17:52:13 +00:00
url_split = url . split ( " / " )
if len ( url_split ) > = 6 :
game_name = url_split [ 5 ]
2023-01-03 18:54:42 +00:00
if show_debug_message :
2022-01-12 17:14:27 +00:00
print ( ' get date game_name: ' , game_name )
print ( " date_auto_select_mode: " , date_auto_select_mode )
print ( " date_keyword: " , date_keyword )
2022-03-24 15:22:43 +00:00
check_game_detail = False
2019-10-01 17:52:13 +00:00
# choose date
2020-07-25 20:35:54 +00:00
if " /activity/game/ %s " % ( game_name , ) in url :
2023-01-03 18:54:42 +00:00
if show_debug_message :
2022-03-24 15:22:43 +00:00
if len ( date_keyword ) == 0 :
2022-01-12 17:14:27 +00:00
print ( " date keyword is empty. " )
2022-03-24 15:22:43 +00:00
else :
print ( " date keyword: " , date_keyword )
check_game_detail = True
2022-01-12 17:14:27 +00:00
2023-01-11 13:58:55 +00:00
date_list = None
2022-03-24 15:22:43 +00:00
if check_game_detail :
try :
date_list = driver . find_elements ( By . CSS_SELECTOR , ' #gameList > table > tbody > tr ' )
except Exception as exc :
print ( " find #gameList fail " )
2019-10-01 17:52:13 +00:00
2023-01-11 13:58:55 +00:00
is_coming_soon = False
coming_soon_condictions_list = [ ' 開賣 ' , ' 剩餘 ' , ' 天 ' , ' 小時 ' , ' 分鐘 ' , ' 秒 ' , ' 0 ' , ' : ' , ' / ' ]
2023-02-19 04:16:31 +00:00
2023-01-11 13:58:55 +00:00
button_list = None
if date_list is not None :
2022-03-24 15:22:43 +00:00
button_list = [ ]
2023-01-11 13:58:55 +00:00
for row in date_list :
# step 1: check keyword.
is_match_keyword_row = False
2022-03-24 15:22:43 +00:00
2023-01-11 13:58:55 +00:00
row_text = " "
try :
row_text = row . text
except Exception as exc :
print ( " get text fail " )
# should use continue or break?
break
if row_text is None :
2022-03-24 15:22:43 +00:00
row_text = " "
2019-10-01 17:52:13 +00:00
2023-01-11 13:58:55 +00:00
if len ( row_text ) > 0 :
is_match_all_coming_soon_condiction = True
for condiction_string in coming_soon_condictions_list :
if not condiction_string in row_text :
is_match_all_coming_soon_condiction = False
break
if is_match_all_coming_soon_condiction :
is_coming_soon = True
break
2022-11-13 04:50:53 +00:00
2023-01-11 13:58:55 +00:00
if len ( date_keyword ) == 0 :
# no keyword, match all.
is_match_keyword_row = True
else :
# check keyword.
if date_keyword in row_text :
2022-03-24 15:22:43 +00:00
is_match_keyword_row = True
2023-01-11 13:58:55 +00:00
# step 2: check sold out.
if is_match_keyword_row :
if pass_date_is_sold_out_enable :
for sold_out_item in sold_out_text_list :
row_text_right_part = row_text [ ( len ( sold_out_item ) + 5 ) * - 1 : ]
2023-01-03 18:54:42 +00:00
if show_debug_message :
2023-01-11 13:58:55 +00:00
print ( " check right part text: " , row_text_right_part )
if sold_out_item in row_text_right_part :
is_match_keyword_row = False
2019-10-01 17:52:13 +00:00
2023-01-03 18:54:42 +00:00
if show_debug_message :
2023-01-11 13:58:55 +00:00
print ( " match sold out text: %s , skip this row. " % ( sold_out_item ) )
# no need check next language item.
2022-03-24 15:22:43 +00:00
break
2019-10-01 17:52:13 +00:00
2023-01-11 13:58:55 +00:00
# step 3: add to list.
if is_match_keyword_row :
el = None
try :
2023-02-21 04:43:07 +00:00
el = row . find_element ( By . CSS_SELECTOR , ' button ' )
2023-01-11 13:58:55 +00:00
except Exception as exc :
if show_debug_message :
2023-02-21 06:37:43 +00:00
print ( " find button fail " )
2023-01-11 13:58:55 +00:00
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
2019-10-01 17:52:13 +00:00
2023-01-11 13:58:55 +00:00
is_date_selected = False
if button_list is not None :
2022-03-24 15:22:43 +00:00
if len ( button_list ) > 0 :
# default first row.
target_row_index = 0
2019-10-01 17:52:13 +00:00
2022-03-24 15:22:43 +00:00
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 )
2023-01-11 13:58:55 +00:00
if show_debug_message :
2023-02-09 16:22:13 +00:00
print ( " clicking at button index: " , target_row_index + 1 )
2022-10-18 18:15:05 +00:00
2023-02-09 16:22:13 +00:00
el = None
2023-01-11 13:58:55 +00:00
try :
2022-03-24 15:22:43 +00:00
el = button_list [ target_row_index ]
2023-02-09 16:22:13 +00:00
if show_debug_message :
print ( " pressing button... " )
2022-03-24 15:22:43 +00:00
el . click ( )
2023-02-09 16:22:13 +00:00
'''
ticket_url = el . get_attribute ( ' data-href ' )
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
'''
2022-09-19 16:20:51 +00:00
is_date_selected = True
2022-03-24 15:22:43 +00:00
except Exception as exc :
2023-02-21 06:37:43 +00:00
print ( " try to click button fail, force click by js. " )
2023-02-09 16:22:13 +00:00
print ( exc )
2022-09-19 16:20:51 +00:00
try :
driver . execute_script ( " arguments[0].click(); " , el )
except Exception as exc :
pass
2019-10-01 17:52:13 +00:00
2022-10-18 18:15:05 +00:00
# PS: Is this case need to reload page?
2022-03-24 15:22:43 +00:00
# (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.
2023-02-19 04:16:31 +00:00
# [PS]: current reload condition only when
2023-01-11 13:58:55 +00:00
if auto_reload_coming_soon_page_enable :
if is_coming_soon :
2023-02-09 16:22:13 +00:00
if show_debug_message :
print ( " match is_coming_soon, start to reload page. " )
2023-01-11 13:58:55 +00:00
# case 2: match one row is coming soon.
2022-03-17 01:15:05 +00:00
try :
2023-01-11 13:58:55 +00:00
driver . refresh ( )
2022-03-17 01:15:05 +00:00
except Exception as exc :
pass
2023-01-11 13:58:55 +00:00
else :
if not is_date_selected :
# case 1: No hyperlink button.
el_list = None
try :
2023-02-21 06:37:43 +00:00
el_list = driver . find_elements ( By . CSS_SELECTOR , ' button ' )
2023-01-11 13:58:55 +00:00
if el_list is None :
driver . refresh ( )
else :
if len ( el_list ) == 0 :
driver . refresh ( )
except Exception as exc :
pass
2019-10-01 17:52:13 +00:00
2022-03-24 15:22:43 +00:00
return is_date_selected
2019-10-27 01:31:22 +00:00
# PURPOSE: get target area list.
2022-10-18 18:15:05 +00:00
# RETURN:
2021-03-22 09:07:28 +00:00
# is_need_refresh
2023-01-02 06:53:28 +00:00
# matched_blocks
# PS: matched_blocks will be None, if length equals zero.
2022-02-18 18:53:55 +00:00
def get_tixcraft_target_area ( el , area_keyword , area_auto_select_mode , pass_1_seat_remaining_enable ) :
2022-11-18 22:59:34 +00:00
show_debug_message = True # debug.
show_debug_message = False # online
2022-02-18 18:53:55 +00:00
2019-10-27 01:31:22 +00:00
is_need_refresh = False
2023-01-02 06:53:28 +00:00
matched_blocks = None
2019-10-27 01:31:22 +00:00
2021-03-22 09:07:28 +00:00
area_list = None
area_list_count = 0
2019-10-27 01:31:22 +00:00
if el is not None :
2021-03-21 06:14:20 +00:00
try :
area_list = el . find_elements ( By . TAG_NAME , ' a ' )
except Exception as exc :
#print("find area list a tag fail")
pass
2019-10-27 01:31:22 +00:00
2021-03-21 06:14:20 +00:00
if area_list is not None :
2021-03-22 09:07:28 +00:00
area_list_count = len ( area_list )
if area_list_count == 0 :
2023-01-12 08:51:05 +00:00
print ( " area list is empty, do refresh! " )
2019-10-27 01:31:22 +00:00
is_need_refresh = True
else :
2023-01-12 08:51:05 +00:00
print ( " area list is None, do refresh! " )
2021-03-21 06:14:20 +00:00
is_need_refresh = True
2019-10-27 01:31:22 +00:00
2021-03-22 09:07:28 +00:00
if area_list_count > 0 :
2023-01-02 06:53:28 +00:00
matched_blocks = [ ]
2021-03-22 09:07:28 +00:00
for row in area_list :
row_is_enabled = False
try :
row_is_enabled = row . is_enabled ( )
except Exception as exc :
pass
row_text = " "
if row_is_enabled :
2021-03-21 06:14:20 +00:00
try :
2021-03-22 09:07:28 +00:00
row_text = row . text
2021-03-21 06:14:20 +00:00
except Exception as exc :
2021-03-22 09:07:28 +00:00
print ( " get text fail " )
break
2019-10-27 01:31:22 +00:00
2022-11-13 04:50:53 +00:00
if row_text is None :
row_text = " "
2021-03-22 09:07:28 +00:00
if len ( row_text ) > 0 :
2022-10-22 01:19:57 +00:00
# clean stop word.
2022-11-06 09:10:35 +00:00
row_text = format_keyword_string ( row_text )
2022-10-22 01:19:57 +00:00
2021-03-22 09:07:28 +00:00
is_append_this_row = False
2019-10-27 01:31:22 +00:00
2021-03-22 09:07:28 +00:00
if len ( area_keyword ) > 0 :
2022-10-22 01:19:57 +00:00
# clean stop word.
2022-11-06 09:10:35 +00:00
area_keyword = format_keyword_string ( area_keyword )
2022-10-22 01:19:57 +00:00
2022-11-09 17:56:12 +00:00
# allow only input stop word in keyword fields.
# for keyword#2 to select all.
if len ( area_keyword ) > 0 :
2021-03-22 09:07:28 +00:00
# must match keyword.
if area_keyword in row_text :
2021-03-21 06:14:20 +00:00
is_append_this_row = True
2021-03-22 09:07:28 +00:00
else :
# without keyword.
is_append_this_row = True
if is_append_this_row :
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-02-18 18:53:55 +00:00
print ( " pass_1_seat_remaining_enable: " , pass_1_seat_remaining_enable )
2021-03-22 09:07:28 +00:00
if pass_1_seat_remaining_enable :
area_item_font_el = None
try :
#print('try to find font tag at row:', row_text)
area_item_font_el = row . find_element ( By . TAG_NAME , ' font ' )
if not area_item_font_el is None :
font_el_text = area_item_font_el . text
2022-11-13 04:50:53 +00:00
if font_el_text is None :
font_el_text = " "
2022-02-18 18:53:55 +00:00
font_el_text = " @ %s @ " % ( font_el_text )
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-02-18 18:53:55 +00:00
print ( ' font tag text: ' , font_el_text )
pass
for check_item in CONT_STRING_1_SEATS_REMAINING :
if check_item in font_el_text :
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-02-18 18:53:55 +00:00
print ( " match pass 1 seats remaining 1 full text: " , row_text )
print ( " match pass 1 seats remaining 2 font text: " , font_el_text )
is_append_this_row = False
2021-03-22 09:07:28 +00:00
else :
#print("row withou font tag.")
2021-03-21 06:14:20 +00:00
pass
2021-03-22 09:07:28 +00:00
except Exception as exc :
#print("find font text in a tag fail:", exc)
pass
2021-03-21 06:14:20 +00:00
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-02-18 18:53:55 +00:00
print ( " is_append_this_row: " , is_append_this_row )
2021-03-22 09:07:28 +00:00
if is_append_this_row :
2023-01-02 06:53:28 +00:00
matched_blocks . append ( row )
2021-03-21 06:14:20 +00:00
2021-03-22 09:07:28 +00:00
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
print ( " only need first item, break area list loop. " )
break
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-02-18 18:53:55 +00:00
print ( " row_text: " + row_text )
print ( " match: " + area_keyword )
2022-10-18 18:15:05 +00:00
2023-01-02 06:53:28 +00:00
if len ( matched_blocks ) == 0 :
matched_blocks = None
2021-03-22 09:07:28 +00:00
is_need_refresh = True
2019-10-27 01:31:22 +00:00
2023-01-02 06:53:28 +00:00
return is_need_refresh , matched_blocks
2019-10-01 17:52:13 +00:00
# PS: auto refresh condition 1: no keyword + no hyperlink.
# PS: auto refresh condition 2: with keyword + no hyperlink.
2022-11-16 15:43:53 +00:00
def tixcraft_area_auto_select ( driver , url , config_dict ) :
2023-01-04 12:02:55 +00:00
show_debug_message = True # debug.
show_debug_message = False # online
2022-11-16 15:43:53 +00:00
# read config.
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 ( )
area_auto_select_mode = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " mode " ]
2022-11-24 21:40:40 +00:00
2023-02-11 05:36:27 +00:00
area_keyword_2_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " area_keyword_2_enable " ]
area_keyword_3_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " area_keyword_3_enable " ]
area_keyword_4_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " area_keyword_4_enable " ]
2022-11-24 21:40:40 +00:00
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
2022-11-16 15:43:53 +00:00
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-02-18 18:53:55 +00:00
print ( " area_keyword_1, area_keyword_2: " , area_keyword_1 , area_keyword_2 )
2022-11-09 17:56:12 +00:00
print ( " area_keyword_3, area_keyword_4: " , area_keyword_3 , area_keyword_4 )
2022-02-18 18:53:55 +00:00
2020-07-25 20:35:54 +00:00
if ' /ticket/area/ ' in url :
2019-10-01 17:52:13 +00:00
#driver.switch_to.default_content()
el = None
try :
el = driver . find_element ( By . CSS_SELECTOR , ' .zone ' )
except Exception as exc :
print ( " find .zone fail, do nothing. " )
if el is not None :
2022-02-18 18:53:55 +00:00
is_need_refresh , areas = get_tixcraft_target_area ( el , area_keyword_1 , area_auto_select_mode , pass_1_seat_remaining_enable )
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-02-18 18:53:55 +00:00
print ( " is_need_refresh for keyword1: " , is_need_refresh )
if is_need_refresh :
2019-10-27 01:31:22 +00:00
if areas is None :
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-02-18 18:53:55 +00:00
print ( " use area keyword #2 " , area_keyword_2 )
2022-11-23 04:39:46 +00:00
2022-02-18 18:53:55 +00:00
# only when keyword#2 filled to query.
2023-02-11 05:36:27 +00:00
if area_keyword_2_enable :
2022-02-18 18:53:55 +00:00
is_need_refresh , areas = get_tixcraft_target_area ( el , area_keyword_2 , area_auto_select_mode , pass_1_seat_remaining_enable )
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-02-18 18:53:55 +00:00
print ( " is_need_refresh for keyword2: " , is_need_refresh )
2019-10-01 17:52:13 +00:00
2022-11-09 17:56:12 +00:00
if is_need_refresh :
if areas is None :
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-11-09 17:56:12 +00:00
print ( " use area keyword #3 " , area_keyword_3 )
2022-11-23 04:39:46 +00:00
2022-11-09 17:56:12 +00:00
# only when keyword#3 filled to query.
2023-02-11 05:36:27 +00:00
if area_keyword_3_enable :
2022-11-09 17:56:12 +00:00
is_need_refresh , areas = get_tixcraft_target_area ( el , area_keyword_3 , area_auto_select_mode , pass_1_seat_remaining_enable )
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-11-09 17:56:12 +00:00
print ( " is_need_refresh for keyword3: " , is_need_refresh )
if is_need_refresh :
if areas is None :
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-11-09 17:56:12 +00:00
print ( " use area keyword #4 " , area_keyword_4 )
2022-11-23 04:39:46 +00:00
2022-11-09 17:56:12 +00:00
# only when keyword#4 filled to query.
2023-02-11 05:36:27 +00:00
if area_keyword_4_enable :
2022-11-09 17:56:12 +00:00
is_need_refresh , areas = get_tixcraft_target_area ( el , area_keyword_4 , area_auto_select_mode , pass_1_seat_remaining_enable )
2022-11-18 22:59:34 +00:00
if show_debug_message :
2022-11-09 17:56:12 +00:00
print ( " is_need_refresh for keyword4: " , is_need_refresh )
2019-10-01 17:52:13 +00:00
area_target = None
if areas is not None :
#print("area_auto_select_mode", area_auto_select_mode)
#print("len(areas)", len(areas))
if len ( areas ) > 0 :
target_row_index = 0
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
if area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
target_row_index = len ( areas ) - 1
if area_auto_select_mode == CONST_RANDOM :
target_row_index = random . randint ( 0 , len ( areas ) - 1 )
#print("target_row_index", target_row_index)
area_target = areas [ target_row_index ]
if area_target is not None :
try :
2022-11-13 04:50:53 +00:00
#print("area text:", area_target.text)
2019-10-01 17:52:13 +00:00
area_target . click ( )
except Exception as exc :
print ( " click area a link fail, start to retry... " )
try :
2022-09-19 16:20:51 +00:00
driver . execute_script ( " arguments[0].click(); " , area_target )
2019-10-01 17:52:13 +00:00
except Exception as exc :
print ( " click area a link fail, after reftry still fail. " )
print ( exc )
pass
# auto refresh for area list page.
if is_need_refresh :
try :
driver . refresh ( )
except Exception as exc :
pass
'''
el_selectSeat_iframe = None
try :
el_selectSeat_iframe = driver . find_element_by_xpath ( " //iframe[contains(@src, ' /ticket/selectSeat/ ' )] " )
except Exception as exc :
#print("find seat iframe fail")
pass
if el_selectSeat_iframe is not None :
driver . switch_to . frame ( el_selectSeat_iframe )
2022-10-18 18:15:05 +00:00
2019-10-01 17:52:13 +00:00
# click one seat
el_seat = None
try :
el_seat = driver . find_element ( By . CSS_SELECTOR , ' .empty ' )
if el_seat is not None :
try :
el_seat . click ( )
except Exception as exc :
#print("click area button fail")
pass
except Exception as exc :
print ( " find empty seat fail " )
# click submit button
el_confirm_seat = None
try :
el_confirm_seat = driver . find_element ( By . ID , ' submitSeat ' )
if el_confirm_seat is not None :
try :
el_confirm_seat . click ( )
except Exception as exc :
#print("click area button fail")
pass
except Exception as exc :
print ( " find submitSeat fail " )
'''
2022-11-16 15:43:53 +00:00
def tixcraft_ticket_agree ( driver ) :
2022-11-16 17:52:38 +00:00
click_plan = " A "
2022-11-16 15:43:53 +00:00
#click_plan = "B"
2019-10-01 17:52:13 +00:00
# check agree
form_checkbox = None
2022-11-16 15:43:53 +00:00
if click_plan == " A " :
try :
form_checkbox = driver . find_element ( By . ID , ' TicketForm_agree ' )
except Exception as exc :
print ( " find TicketForm_agree fail " )
2019-10-01 17:52:13 +00:00
2022-11-16 15:43:53 +00:00
is_finish_checkbox_click = False
if form_checkbox is not None :
try :
# TODO: check the status: checked.
if form_checkbox . is_enabled ( ) :
2023-01-12 22:29:58 +00:00
if not form_checkbox . is_selected ( ) :
form_checkbox . click ( )
2022-11-16 15:43:53 +00:00
is_finish_checkbox_click = True
except Exception as exc :
print ( " click TicketForm_agree fail " )
pass
2019-10-01 17:52:13 +00:00
2022-12-15 11:26:51 +00:00
# 使用 plan B.
#if not is_finish_checkbox_click:
# alway not use Plan B.
if False :
2022-11-16 15:43:53 +00:00
try :
2022-11-16 17:52:38 +00:00
print ( " use plan_b to check TicketForm_agree. " )
2022-11-16 15:43:53 +00:00
driver . execute_script ( " $( \" input[type= ' checkbox ' ] \" ).prop( ' checked ' , true); " )
#driver.execute_script("document.getElementById(\"TicketForm_agree\").checked;")
is_finish_checkbox_click = True
except Exception as exc :
print ( " javascript check TicketForm_agree fail " )
print ( exc )
pass
2019-10-01 17:52:13 +00:00
2022-11-16 15:43:53 +00:00
return is_finish_checkbox_click
2019-10-01 17:52:13 +00:00
2022-11-16 15:43:53 +00:00
def tixcraft_ticket_number_auto_fill ( driver , select_obj , ticket_number ) :
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = False
2022-11-16 15:43:53 +00:00
if select_obj is not None :
2019-10-01 17:52:13 +00:00
try :
# target ticket number
2022-11-16 15:43:53 +00:00
select_obj . select_by_visible_text ( ticket_number )
2019-10-01 17:52:13 +00:00
#select.select_by_value(ticket_number)
#select.select_by_index(int(ticket_number))
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2019-10-01 17:52:13 +00:00
except Exception as exc :
print ( " select_by_visible_text ticket_number fail " )
print ( exc )
try :
# target ticket number
2022-11-16 15:43:53 +00:00
select_obj . select_by_visible_text ( ticket_number )
2019-10-01 17:52:13 +00:00
#select.select_by_value(ticket_number)
#select.select_by_index(int(ticket_number))
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2019-10-01 17:52:13 +00:00
except Exception as exc :
print ( " select_by_visible_text ticket_number fail...2 " )
print ( exc )
# try buy one ticket
try :
2022-11-16 15:43:53 +00:00
select_obj . select_by_visible_text ( " 1 " )
2019-10-01 17:52:13 +00:00
#select.select_by_value("1")
#select.select_by_index(int(ticket_number))
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2019-10-01 17:52:13 +00:00
except Exception as exc :
print ( " select_by_visible_text 1 fail " )
pass
2022-12-15 11:26:51 +00:00
# Plan B.
2023-01-02 06:53:28 +00:00
# if not is_ticket_number_assigned:
2022-12-15 11:26:51 +00:00
if False :
2022-11-16 15:43:53 +00:00
if select is not None :
2019-10-01 17:52:13 +00:00
try :
2022-11-16 15:43:53 +00:00
# target ticket number
#select.select_by_visible_text(ticket_number)
print ( " assign ticker number by jQuery: " , ticket_number )
driver . execute_script ( " $( \" input[type= ' select ' ] \" ).val( \" " + ticket_number + " \" ); " )
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2019-10-01 17:52:13 +00:00
except Exception as exc :
2022-11-16 15:43:53 +00:00
print ( " jQuery select_by_visible_text ticket_number fail (after click.) " )
print ( exc )
2023-01-02 06:53:28 +00:00
return is_ticket_number_assigned
2019-10-01 17:52:13 +00:00
2023-02-17 16:54:16 +00:00
def guess_tixcraft_question ( driver ) :
2023-02-19 04:16:31 +00:00
show_debug_message = True # debug.
show_debug_message = False # online
inferred_answer_string = None
answer_list = [ ]
2019-10-01 17:52:13 +00:00
form_select = None
try :
form_select = driver . find_element ( By . CSS_SELECTOR , ' .zone-verify ' )
except Exception as exc :
2023-01-07 22:23:37 +00:00
print ( " find verify textbox fail " )
2019-10-01 17:52:13 +00:00
pass
2022-11-13 04:50:53 +00:00
question_text = None
if form_select is not None :
try :
question_text = form_select . text
except Exception as exc :
print ( " get text fail " )
2023-02-19 04:16:31 +00:00
formated_html_text = " "
2022-11-13 04:50:53 +00:00
if question_text is not None :
if len ( question_text ) > 0 :
2023-01-07 22:23:37 +00:00
# format question text.
2023-02-19 04:16:31 +00:00
formated_html_text = question_text
formated_html_text = formated_html_text . replace ( u ' 「 ' , u ' 【 ' )
formated_html_text = formated_html_text . replace ( u ' 〔 ' , u ' 【 ' )
formated_html_text = formated_html_text . replace ( u ' [ ' , u ' 【 ' )
formated_html_text = formated_html_text . replace ( u ' 〖 ' , u ' 【 ' )
formated_html_text = formated_html_text . replace ( u ' [ ' , u ' 【 ' )
formated_html_text = formated_html_text . replace ( u ' 」 ' , u ' 】 ' )
formated_html_text = formated_html_text . replace ( u ' 〕 ' , u ' 】 ' )
formated_html_text = formated_html_text . replace ( u ' ] ' , u ' 】 ' )
formated_html_text = formated_html_text . replace ( u ' 〗 ' , u ' 】 ' )
formated_html_text = formated_html_text . replace ( u ' ] ' , u ' 】 ' )
if u ' 【 ' in formated_html_text and u ' 】 ' in formated_html_text :
2022-11-13 04:50:53 +00:00
# PS: 這個太容易沖突,因為問題類型太多,不能直接使用。
2023-02-19 04:16:31 +00:00
#inferred_answer_string = find_between(formated_html_text, u"【", u"】")
2022-11-13 04:50:53 +00:00
pass
2019-10-27 03:44:53 +00:00
2022-11-20 07:57:16 +00:00
if show_debug_message :
2023-02-19 04:16:31 +00:00
print ( " formated_html_text: " , formated_html_text )
2022-11-20 07:57:16 +00:00
2019-10-27 03:44:53 +00:00
is_options_in_question = False
2022-11-20 07:57:16 +00:00
# 請輸入"YES",代表您已詳閱且瞭解並同意。
2023-01-02 20:37:54 +00:00
if inferred_answer_string is None :
2023-02-19 04:16:31 +00:00
if u ' 輸入 " YES " ' in formated_html_text :
if u ' 已詳閱 ' in formated_html_text or ' 請詳閱 ' in formated_html_text :
if u ' 同意 ' in formated_html_text :
2023-01-02 20:37:54 +00:00
inferred_answer_string = ' YES '
2019-10-27 04:33:06 +00:00
2023-01-07 22:23:37 +00:00
# 購票前請詳閱注意事項,並於驗證碼欄位輸入【同意】繼續購票流程。
if inferred_answer_string is None :
2023-02-19 04:16:31 +00:00
if ' 驗證碼 ' in formated_html_text or ' 驗證欄位 ' in formated_html_text :
if ' 已詳閱 ' in formated_html_text or ' 請詳閱 ' in formated_html_text :
if ' 輸入【同意】 ' in formated_html_text :
2023-01-07 22:23:37 +00:00
inferred_answer_string = ' 同意 '
2023-02-19 04:16:31 +00:00
if inferred_answer_string is None :
2023-02-23 13:33:49 +00:00
if not question_text is None :
inferred_answer_string , answer_list = get_answer_list_from_question_string ( None , question_text )
2023-02-19 04:16:31 +00:00
return inferred_answer_string , answer_list
2023-02-17 16:54:16 +00:00
def tixcraft_verify ( driver , presale_code , presale_code_delimiter , answer_index ) :
show_debug_message = True # debug.
show_debug_message = False # online
inferred_answer_string = None
answer_list = [ ]
2023-02-19 04:16:31 +00:00
is_retry_user_single_answer = False
if len ( presale_code ) > 0 :
2023-02-17 16:54:16 +00:00
if len ( presale_code_delimiter ) > 0 :
if presale_code_delimiter in presale_code :
answer_list = presale_code . split ( presale_code_delimiter )
if len ( answer_list ) > 0 :
if answer_index < len ( answer_list ) - 1 :
inferred_answer_string = answer_list [ answer_index + 1 ]
2023-02-19 04:16:31 +00:00
else :
is_retry_user_single_answer = True
if answer_index < 2 :
inferred_answer_string = presale_code
2023-02-17 16:54:16 +00:00
if inferred_answer_string is None :
2023-02-19 04:16:31 +00:00
inferred_answer_string , answer_list = guess_tixcraft_question ( driver )
if inferred_answer_string is None :
if not answer_list is None :
if len ( answer_list ) > 0 :
if answer_index < len ( answer_list ) - 1 :
inferred_answer_string = answer_list [ answer_index + 1 ]
2023-01-07 22:23:37 +00:00
2022-11-20 07:57:16 +00:00
if show_debug_message :
2023-02-19 04:16:31 +00:00
print ( " answer_index: " , answer_index )
2023-01-02 20:37:54 +00:00
print ( " inferred_answer_string: " , inferred_answer_string )
2023-02-19 04:16:31 +00:00
print ( " answer_index: " , answer_index )
print ( " is_retry_user_single_answer: " , is_retry_user_single_answer )
2019-10-01 17:52:13 +00:00
2022-11-20 07:57:16 +00:00
form_input = None
try :
2023-02-21 04:43:07 +00:00
form_input = driver . find_element ( By . CSS_SELECTOR , " input[name= ' checkCode ' ] " )
2022-11-20 07:57:16 +00:00
except Exception as exc :
print ( " find verify code fail " )
pass
2023-01-23 20:36:06 +00:00
inputed_value = None
2022-11-20 07:57:16 +00:00
if form_input is not None :
try :
2023-01-23 20:36:06 +00:00
inputed_value = form_input . get_attribute ( ' value ' )
2019-10-01 17:52:13 +00:00
except Exception as exc :
2022-11-20 07:57:16 +00:00
print ( " find verify code fail " )
2019-10-01 17:52:13 +00:00
pass
2023-01-23 20:36:06 +00:00
if inputed_value is None :
inputed_value = " "
2022-11-20 07:57:16 +00:00
2023-01-02 20:37:54 +00:00
if not inferred_answer_string is None :
2022-11-20 07:57:16 +00:00
is_password_sent = False
2023-01-23 20:36:06 +00:00
if len ( inputed_value ) == 0 :
2022-09-19 16:20:51 +00:00
try :
2022-11-20 07:57:16 +00:00
# PS: sometime may send key twice...
form_input . clear ( )
2023-01-02 20:37:54 +00:00
form_input . send_keys ( inferred_answer_string )
2023-02-17 16:54:16 +00:00
form_input . send_keys ( Keys . ENTER )
2022-11-20 07:57:16 +00:00
is_password_sent = True
2023-02-19 04:16:31 +00:00
2023-02-17 16:54:16 +00:00
# guess answer mode.
2023-02-19 04:16:31 +00:00
answer_index + = 1
2023-02-17 16:54:16 +00:00
2022-11-20 07:57:16 +00:00
if show_debug_message :
2023-02-17 16:54:16 +00:00
print ( " sent password by bot: " , inferred_answer_string )
2022-09-19 16:20:51 +00:00
except Exception as exc :
pass
2023-02-17 16:54:16 +00:00
else :
if inputed_value == inferred_answer_string :
2022-11-20 07:57:16 +00:00
if show_debug_message :
2023-02-17 16:54:16 +00:00
print ( " sent password by previous time. " )
is_password_sent = True
try :
form_input . send_keys ( Keys . ENTER )
except Exception as exc :
pass
2023-02-19 04:16:31 +00:00
if is_retry_user_single_answer :
# increase counter for waiting for stop retry.
answer_index + = 1
else :
# guess answer mode.
2023-02-17 16:54:16 +00:00
if answer_index > - 1 :
# here not is first option.
inferred_answer_previous = None
if answer_index < len ( answer_list ) - 1 :
inferred_answer_previous = answer_list [ answer_index ]
if inputed_value == inferred_answer_previous :
try :
form_input . clear ( )
form_input . send_keys ( inferred_answer_string )
form_input . send_keys ( Keys . ENTER )
is_password_sent = True
2022-11-20 07:57:16 +00:00
if show_debug_message :
2023-02-17 16:54:16 +00:00
print ( " sent password by bot: " , inferred_answer_string , " at index: " , answer_index + 2 )
2022-11-09 18:36:17 +00:00
2023-02-17 16:54:16 +00:00
answer_index + = 1
except Exception as exc :
pass
2023-01-07 21:43:30 +00:00
2023-02-17 16:54:16 +00:00
if is_password_sent :
for i in range ( 3 ) :
time . sleep ( 0.1 )
2023-02-23 13:33:49 +00:00
2023-02-17 16:54:16 +00:00
alert_ret = check_pop_alert ( driver )
if alert_ret :
if show_debug_message :
2023-02-19 04:16:31 +00:00
print ( " press accept button at time # " , i + 1 )
2023-02-17 16:54:16 +00:00
break
2019-10-27 01:31:22 +00:00
else :
2023-01-23 20:36:06 +00:00
if len ( inputed_value ) == 0 :
2019-10-01 17:52:13 +00:00
try :
2022-11-20 07:57:16 +00:00
form_input . click ( )
2019-10-01 17:52:13 +00:00
except Exception as exc :
pass
2023-02-17 16:54:16 +00:00
return answer_index
2019-10-01 17:52:13 +00:00
2023-01-12 15:30:34 +00:00
def tixcraft_change_captcha ( driver , url ) :
try :
driver . execute_script ( f " document.querySelector( ' .verify-img ' ).children[0].setAttribute( ' src ' , ' { url } ' ); " )
except Exception as exc :
print ( " edit captcha element fail " )
2023-01-12 11:41:49 +00:00
def tixcraft_toast ( driver , message ) :
toast_element = None
try :
my_css_selector = " .remark-word "
toast_element = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
if not toast_element is None :
driver . execute_script ( " arguments[0].innerHTML= ' %s ' ; " % message , toast_element )
except Exception as exc :
print ( " find toast element fail " )
2023-02-22 16:05:44 +00:00
def tixcraft_keyin_captcha_code ( driver , answer = " " , auto_submit = False ) :
2023-01-11 13:58:55 +00:00
is_verifyCode_editing = False
2023-01-12 22:29:58 +00:00
is_form_sumbited = False
2023-01-11 13:58:55 +00:00
# manually keyin verify code.
# start to input verify code.
form_verifyCode = None
try :
form_verifyCode = driver . find_element ( By . ID , ' TicketForm_verifyCode ' )
except Exception as exc :
print ( " find form_verifyCode fail " )
if form_verifyCode is not None :
is_visible = False
try :
if form_verifyCode . is_enabled ( ) :
is_visible = True
except Exception as exc :
pass
if is_visible :
try :
form_verifyCode . click ( )
is_verifyCode_editing = True
except Exception as exc :
print ( " click form_verifyCode fail, tring to use javascript. " )
# plan B
try :
driver . execute_script ( " document.getElementById( \" TicketForm_verifyCode \" ).focus(); " )
is_verifyCode_editing = True
except Exception as exc :
2023-01-12 22:29:58 +00:00
print ( " click form_verifyCode fail. " )
#print("start to fill answer.")
try :
if len ( answer ) > 0 :
form_verifyCode . send_keys ( answer )
if auto_submit :
form_verifyCode . send_keys ( Keys . ENTER )
is_verifyCode_editing = False
is_form_sumbited = True
else :
driver . execute_script ( " document.getElementById( \" TicketForm_verifyCode \" ).select(); " )
if len ( answer ) > 0 :
tixcraft_toast ( driver , " ※ 按 Enter 如果答案是: " + answer )
except Exception as exc :
print ( " send_keys ocr answer fail. " )
return is_verifyCode_editing , is_form_sumbited
2023-01-13 19:01:47 +00:00
def tixcraft_reload_captcha ( driver , domain_name ) :
2023-01-12 22:29:58 +00:00
# manually keyin verify code.
# start to input verify code.
ret = False
form_captcha = None
try :
2023-02-22 12:38:20 +00:00
image_id = ' TicketForm_verifyCode-image '
2023-01-13 19:01:47 +00:00
if ' indievox.com ' in domain_name :
image_id = ' TicketForm_verifyCode-image '
form_captcha = driver . find_element ( By . ID , image_id )
2023-01-12 22:29:58 +00:00
if not form_captcha is None :
form_captcha . click ( )
ret = True
except Exception as exc :
print ( " find form_captcha fail " )
return ret
2023-01-11 13:58:55 +00:00
#PS: credit to LinShihJhang's share
2023-01-13 19:01:47 +00:00
def tixcraft_auto_ocr ( driver , ocr , away_from_keyboard_enable , previous_answer , Captcha_Browser , ocr_captcha_image_source , domain_name ) :
show_debug_message = True # debug.
show_debug_message = False # online
2023-01-11 13:58:55 +00:00
print ( " start to ddddocr " )
2023-01-13 19:01:47 +00:00
2023-01-12 22:29:58 +00:00
is_need_redo_ocr = False
is_form_sumbited = False
2023-01-11 14:26:49 +00:00
orc_answer = None
if not ocr is None :
2023-01-13 19:01:47 +00:00
if show_debug_message :
print ( " away_from_keyboard_enable: " , away_from_keyboard_enable )
print ( " previous_answer: " , previous_answer )
print ( " ocr_captcha_image_source: " , ocr_captcha_image_source )
ocr_start_time = time . time ( )
img_base64 = None
if ocr_captcha_image_source == CONST_OCR_CAPTCH_IMAGE_SOURCE_NON_BROWSER :
2023-01-14 05:26:42 +00:00
if not Captcha_Browser is None :
img_base64 = base64 . b64decode ( Captcha_Browser . Request_Captcha ( ) )
2023-02-12 03:02:16 +00:00
if ocr_captcha_image_source == CONST_OCR_CAPTCH_IMAGE_SOURCE_CANVAS :
2023-02-21 04:43:07 +00:00
image_id = ' TicketForm_verifyCode-image '
2023-01-13 19:01:47 +00:00
if ' indievox.com ' in domain_name :
image_id = ' TicketForm_verifyCode-image '
try :
form_verifyCode_base64 = driver . execute_async_script ( """
var canvas = document . createElement ( ' canvas ' ) ;
var context = canvas . getContext ( ' 2d ' ) ;
var img = document . getElementById ( ' %s ' ) ;
canvas . height = img . naturalHeight ;
canvas . width = img . naturalWidth ;
context . drawImage ( img , 0 , 0 ) ;
callback = arguments [ arguments . length - 1 ] ;
callback ( canvas . toDataURL ( ) ) ;
""" % (image_id))
img_base64 = base64 . b64decode ( form_verifyCode_base64 . split ( ' , ' ) [ 1 ] )
except Exception as exc :
if show_debug_message :
print ( " canvas exception: " , str ( exc ) )
pass
if not img_base64 is None :
try :
orc_answer = ocr . classification ( img_base64 )
except Exception as exc :
pass
2023-02-07 18:02:19 +00:00
else :
if previous_answer is None :
# page is not ready, retry again.
# PS: usually occur in async script get captcha image.
is_need_redo_ocr = True
time . sleep ( 0.1 )
2023-01-13 19:01:47 +00:00
ocr_done_time = time . time ( )
ocr_elapsed_time = ocr_done_time - ocr_start_time
print ( " ocr elapsed time: " , " {:.3f} " . format ( ocr_elapsed_time ) )
2023-01-11 17:36:29 +00:00
else :
print ( " ddddocr is None " )
2023-02-19 04:16:31 +00:00
2023-01-11 13:58:55 +00:00
if not orc_answer is None :
2023-01-12 22:29:58 +00:00
orc_answer = orc_answer . strip ( )
2023-01-11 13:58:55 +00:00
print ( " orc_answer: " , orc_answer )
if len ( orc_answer ) == 4 :
2023-01-13 09:27:08 +00:00
who_care_var , is_form_sumbited = tixcraft_keyin_captcha_code ( driver , answer = orc_answer , auto_submit = away_from_keyboard_enable )
2023-01-11 13:58:55 +00:00
else :
2023-01-13 00:43:16 +00:00
if not away_from_keyboard_enable :
2023-01-12 22:29:58 +00:00
tixcraft_keyin_captcha_code ( driver )
2023-01-13 09:27:08 +00:00
tixcraft_toast ( driver , " ※ OCR辨識失敗Q_Q, 驗證碼請手動輸入... " )
2023-01-12 22:29:58 +00:00
else :
is_need_redo_ocr = True
if previous_answer != orc_answer :
previous_answer = orc_answer
2023-02-07 16:49:12 +00:00
print ( " click captcha again. " )
2023-01-13 19:01:47 +00:00
if True :
# selenium solution.
tixcraft_reload_captcha ( driver , domain_name )
2023-02-12 03:02:16 +00:00
if ocr_captcha_image_source == CONST_OCR_CAPTCH_IMAGE_SOURCE_CANVAS :
2023-02-06 16:42:31 +00:00
time . sleep ( 0.1 )
2023-01-13 19:01:47 +00:00
else :
# Non_Browser solution.
2023-01-14 05:26:42 +00:00
if not Captcha_Browser is None :
new_captcha_url = Captcha_Browser . Request_Refresh_Captcha ( ) #取得新的CAPTCHA
if new_captcha_url != " " :
tixcraft_change_captcha ( driver , new_captcha_url ) #更改CAPTCHA圖
2023-01-11 17:36:29 +00:00
else :
2023-01-12 22:29:58 +00:00
print ( " orc_answer is None " )
print ( " previous_answer: " , previous_answer )
if previous_answer is None :
tixcraft_keyin_captcha_code ( driver )
2023-02-07 18:02:19 +00:00
else :
# page is not ready, retry again.
# PS: usually occur in async script get captcha image.
# PS: previous answer is not none means OCR object works.
2023-02-19 04:16:31 +00:00
# some user enable OCR feature, but component create fail, ex: macOS arm CPU.
2023-02-07 18:02:19 +00:00
is_need_redo_ocr = True
2023-01-12 22:29:58 +00:00
return is_need_redo_ocr , previous_answer , is_form_sumbited
2023-01-11 14:26:49 +00:00
2023-01-13 19:01:47 +00:00
def tixcraft_ticket_main ( driver , config_dict , ocr , Captcha_Browser , domain_name ) :
2022-12-15 11:26:51 +00:00
auto_check_agree = config_dict [ " auto_check_agree " ]
2023-02-19 04:16:31 +00:00
2023-01-12 11:41:49 +00:00
ocr_captcha_enable = config_dict [ " ocr_captcha " ] [ " enable " ]
2023-01-13 00:43:16 +00:00
away_from_keyboard_enable = config_dict [ " ocr_captcha " ] [ " force_submit " ]
if not ocr_captcha_enable :
away_from_keyboard_enable = False
2023-02-19 04:16:31 +00:00
ocr_captcha_image_source = config_dict [ " ocr_captcha " ] [ " image_source " ]
2023-01-11 13:58:55 +00:00
2022-12-15 11:26:51 +00:00
if auto_check_agree :
2023-02-21 04:43:07 +00:00
for i in range ( 3 ) :
is_finish_checkbox_click = tixcraft_ticket_agree ( driver )
if is_finish_checkbox_click :
break
2022-11-16 15:43:53 +00:00
# allow agree not enable to assign ticket number.
2019-10-01 17:52:13 +00:00
form_select = None
try :
#form_select = driver.find_element(By.TAG_NAME, 'select')
2022-11-16 15:43:53 +00:00
#PS: select box may appear many in the page with different price.
2019-10-01 17:52:13 +00:00
form_select = driver . find_element ( By . CSS_SELECTOR , ' .mobile-select ' )
2022-11-13 04:50:53 +00:00
except Exception as exc :
print ( " find select fail " )
pass
2019-10-01 17:52:13 +00:00
2022-11-16 15:43:53 +00:00
select_obj = None
2022-11-13 04:50:53 +00:00
if form_select is not None :
2022-11-16 15:43:53 +00:00
is_visible = False
2022-11-13 04:50:53 +00:00
try :
2022-12-15 11:26:51 +00:00
if form_select . is_enabled ( ) :
is_visible = True
2022-11-13 04:50:53 +00:00
except Exception as exc :
pass
2022-11-16 15:43:53 +00:00
if is_visible :
2022-11-13 04:50:53 +00:00
try :
2022-11-16 15:43:53 +00:00
select_obj = Select ( form_select )
2022-11-13 04:50:53 +00:00
except Exception as exc :
2019-10-01 17:52:13 +00:00
pass
2022-11-23 04:39:46 +00:00
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = False
2022-11-16 15:43:53 +00:00
if not select_obj is None :
row_text = None
try :
row_text = select_obj . first_selected_option . text
except Exception as exc :
2022-11-13 04:50:53 +00:00
pass
2022-11-16 15:43:53 +00:00
if not row_text is None :
if len ( row_text ) > 0 :
if row_text != " 0 " :
# ticket assign.
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2019-10-01 17:52:13 +00:00
2023-01-11 13:58:55 +00:00
is_verifyCode_editing = False
2022-11-16 15:43:53 +00:00
2023-01-11 13:58:55 +00:00
# must wait select object ready to assign ticket number.
if not is_ticket_number_assigned :
# only this case:"ticket number changed by bot" to play sound!
# PS: I assume each time assign ticket number will succufully changed, so let sound play first.
check_and_play_sound_for_captcha ( config_dict )
2022-11-16 15:43:53 +00:00
2023-01-11 13:58:55 +00:00
ticket_number = str ( config_dict [ " ticket_number " ] )
is_ticket_number_assigned = tixcraft_ticket_number_auto_fill ( driver , select_obj , ticket_number )
2022-11-16 15:43:53 +00:00
2023-01-11 13:58:55 +00:00
# must wait ticket number assign to focus captcha.
if is_ticket_number_assigned :
2023-01-12 08:51:05 +00:00
if not ocr_captcha_enable :
2023-01-12 22:29:58 +00:00
is_verifyCode_editing = tixcraft_keyin_captcha_code ( driver )
2023-01-11 13:58:55 +00:00
else :
2023-01-12 22:29:58 +00:00
previous_answer = None
2023-01-11 13:58:55 +00:00
is_verifyCode_editing = True
2023-01-12 22:29:58 +00:00
for redo_ocr in range ( 999 ) :
2023-01-13 19:01:47 +00:00
is_need_redo_ocr , previous_answer , is_form_sumbited = tixcraft_auto_ocr ( driver , ocr , away_from_keyboard_enable , previous_answer , Captcha_Browser , ocr_captcha_image_source , domain_name )
2023-01-12 22:29:58 +00:00
if is_form_sumbited :
# start next loop.
is_verifyCode_editing = False
break
2023-02-19 04:16:31 +00:00
2023-01-13 00:43:16 +00:00
if not away_from_keyboard_enable :
2023-01-12 22:29:58 +00:00
break
2023-02-19 04:16:31 +00:00
2023-01-12 22:29:58 +00:00
if not is_need_redo_ocr :
break
2022-11-16 15:43:53 +00:00
if is_verifyCode_editing :
print ( " goto is_verifyCode_editing == True " )
2022-11-16 17:52:38 +00:00
return is_verifyCode_editing
2019-10-01 17:52:13 +00:00
2023-02-22 23:46:05 +00:00
def kktix_confirm_order_button ( driver ) :
ret = False
wait = WebDriverWait ( driver , 1 )
next_step_button = None
try :
# method #3 wait
next_step_button = wait . until ( EC . element_to_be_clickable ( ( By . CSS_SELECTOR , ' div.form-actions a.btn-primary ' ) ) )
if not next_step_button is None :
if next_step_button . is_enabled ( ) :
next_step_button . click ( )
ret = True
except Exception as exc :
print ( " wait form-actions div wait to be clickable Exception: " )
#print(exc)
pass
if not next_step_button is None :
is_visible = False
try :
if next_step_button . is_enabled ( ) :
is_visible = True
except Exception as exc :
pass
if is_visible :
try :
driver . execute_script ( " arguments[0].click(); " , next_step_button )
ret = True
except Exception as exc :
pass
return ret
2023-02-26 08:39:37 +00:00
2020-10-20 16:31:30 +00:00
# PS: There are two "Next" button in kktix.
# : 1: /events/xxx
# : 2: /events/xxx/registrations/new
2022-11-07 10:15:35 +00:00
# : This is ONLY for case-1, because case-2 lenght >5
2022-01-12 17:14:27 +00:00
def kktix_events_press_next_button ( driver ) :
2023-02-26 08:39:37 +00:00
is_button_clicked = force_press_button ( driver , By . CSS_SELECTOR , ' div.tickets a.btn-point ' )
return is_button_clicked
2020-10-20 16:31:30 +00:00
# : This is for case-2 next button.
2022-01-12 17:14:27 +00:00
def kktix_press_next_button ( driver ) :
2019-10-01 17:52:13 +00:00
ret = False
2022-09-19 16:20:51 +00:00
wait = WebDriverWait ( driver , 1 )
next_step_button = None
2019-10-01 17:52:13 +00:00
try :
# method #1
#form_actions_div = None
#form_actions_div = driver.find_element(By.ID, 'registrationsNewApp')
#next_step_button = form_actions_div.find_element(By.CSS_SELECTOR, 'div.form-actions button.btn-primary')
2019-12-14 19:13:20 +00:00
# method #2
# next_step_button = driver.find_element(By.CSS_SELECTOR, '#registrationsNewApp div.form-actions button.btn-primary')
# method #3 wait
2019-10-01 17:52:13 +00:00
next_step_button = wait . until ( EC . element_to_be_clickable ( ( By . CSS_SELECTOR , ' #registrationsNewApp div.form-actions button.btn-primary ' ) ) )
if not next_step_button is None :
if next_step_button . is_enabled ( ) :
next_step_button . click ( )
ret = True
except Exception as exc :
print ( " wait form-actions div wait to be clickable Exception: " )
print ( exc )
2022-09-19 16:20:51 +00:00
#pass
2019-10-01 17:52:13 +00:00
2022-09-19 16:20:51 +00:00
if not next_step_button is None :
2022-11-09 18:36:17 +00:00
is_visible = False
try :
if next_step_button . is_enabled ( ) :
is_visible = True
except Exception as exc :
pass
2022-11-23 04:39:46 +00:00
2022-11-09 18:36:17 +00:00
if is_visible :
2022-09-19 16:20:51 +00:00
try :
driver . execute_script ( " arguments[0].click(); " , next_step_button )
2019-10-01 17:52:13 +00:00
ret = True
2022-09-19 16:20:51 +00:00
except Exception as exc :
pass
2019-10-01 17:52:13 +00:00
return ret
def kktix_captcha_text_value ( captcha_inner_div ) :
ret = " "
if captcha_inner_div is not None :
try :
captcha_password_text = captcha_inner_div . find_element ( By . TAG_NAME , " input " )
if not captcha_password_text is None :
ret = captcha_password_text . get_attribute ( ' value ' )
else :
print ( " find captcha input field fail " )
except Exception as exc :
print ( " find captcha_inner_div Exception: " )
#print(exc)
pass
2022-10-18 18:15:05 +00:00
2019-10-01 17:52:13 +00:00
return ret
2023-01-02 20:37:54 +00:00
def kktix_input_captcha_text ( captcha_password_input_tag , inferred_answer_string , force_overwrite = False ) :
2022-10-18 18:15:05 +00:00
show_debug_message = True # debug.
2023-02-09 16:22:13 +00:00
show_debug_message = False # online
2022-10-18 18:15:05 +00:00
2022-11-20 07:57:16 +00:00
is_cpatcha_sent = False
inputed_captcha_text = " "
2022-10-18 18:15:05 +00:00
2022-11-20 07:57:16 +00:00
if not captcha_password_input_tag is None :
if force_overwrite :
2022-11-18 22:59:34 +00:00
try :
2023-01-02 20:37:54 +00:00
captcha_password_input_tag . send_keys ( inferred_answer_string )
print ( " send captcha keys: " + inferred_answer_string )
2022-11-20 07:57:16 +00:00
is_cpatcha_sent = True
2023-01-02 20:37:54 +00:00
inputed_captcha_text = inferred_answer_string
2022-11-18 22:59:34 +00:00
except Exception as exc :
pass
else :
2022-11-20 07:57:16 +00:00
# not force overwrite:
inputed_captcha_text = None
try :
inputed_captcha_text = captcha_password_input_tag . get_attribute ( ' value ' )
except Exception as exc :
pass
if inputed_captcha_text is None :
inputed_captcha_text = " "
2022-11-18 22:59:34 +00:00
if len ( inputed_captcha_text ) == 0 :
try :
2023-01-02 20:37:54 +00:00
captcha_password_input_tag . send_keys ( inferred_answer_string )
print ( " send captcha keys: " + inferred_answer_string )
2022-11-20 07:57:16 +00:00
is_cpatcha_sent = True
2022-11-18 22:59:34 +00:00
except Exception as exc :
pass
2022-11-23 04:39:46 +00:00
2022-11-20 07:57:16 +00:00
return is_cpatcha_sent
2019-10-01 17:52:13 +00:00
2022-11-24 21:40:40 +00:00
def kktix_travel_price_list ( driver , ticket_number , pass_1_seat_remaining_enable , kktix_area_keyword_1 , kktix_area_keyword_1_and ) :
2022-11-10 17:19:03 +00:00
show_debug_message = True # debug.
2023-01-03 18:54:42 +00:00
show_debug_message = False # online
2019-10-01 17:52:13 +00:00
areas = None
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = False
2019-10-01 17:52:13 +00:00
2022-10-21 13:18:07 +00:00
ticket_price_list = None
2019-10-01 17:52:13 +00:00
try :
ticket_price_list = driver . find_elements ( By . CSS_SELECTOR , ' .display-table-row ' )
2022-10-21 13:18:07 +00:00
except Exception as exc :
2022-11-10 17:19:03 +00:00
ticket_price_list = None
2022-10-21 13:18:07 +00:00
print ( " find ticket-price span Exception: " )
print ( exc )
pass
2019-10-01 17:52:13 +00:00
2022-11-10 17:19:03 +00:00
price_list_count = 0
2022-10-21 13:18:07 +00:00
if ticket_price_list is not None :
2022-11-10 17:19:03 +00:00
price_list_count = len ( ticket_price_list )
if show_debug_message :
print ( " found price count: " , price_list_count )
print ( " start to travel rows.......... " )
else :
print ( " find ticket-price span fail " )
2022-11-23 04:39:46 +00:00
2022-11-10 17:19:03 +00:00
is_travel_interrupted = False
if price_list_count > 0 :
areas = [ ]
# clean stop word.
2022-11-23 04:39:46 +00:00
kktix_area_keyword_1 = format_keyword_string ( kktix_area_keyword_1 )
kktix_area_keyword_1_and = format_keyword_string ( kktix_area_keyword_1_and )
2022-11-10 17:19:03 +00:00
if show_debug_message :
2022-11-23 04:39:46 +00:00
print ( ' kktix_area_keyword_1: ' , kktix_area_keyword_1 )
print ( ' kktix_area_keyword_1_and: ' , kktix_area_keyword_1_and )
2019-10-01 17:52:13 +00:00
2022-11-10 17:19:03 +00:00
row_index = 0
for row in ticket_price_list :
row_index + = 1
2022-10-21 13:18:07 +00:00
2022-11-10 17:19:03 +00:00
row_text = " "
try :
row_text = row . text
if show_debug_message :
print ( " get text: " , row_text , " ,at row: " , row_index )
except Exception as exc :
2022-10-21 13:18:07 +00:00
row_text = " "
2022-11-10 17:19:03 +00:00
is_travel_interrupted = True
print ( " get text fail. " )
2022-11-13 04:50:53 +00:00
if row_text is None :
row_text = " "
2022-11-10 17:19:03 +00:00
if len ( row_text ) > 0 :
# clean stop word.
row_text = format_keyword_string ( row_text )
# check ticket input textbox.
ticket_price_input = None
2022-10-21 13:18:07 +00:00
try :
2022-11-10 17:19:03 +00:00
ticket_price_input = row . find_element ( By . CSS_SELECTOR , " input[type= ' text ' ] " )
2022-10-21 13:18:07 +00:00
except Exception as exc :
2022-11-10 17:19:03 +00:00
pass
2022-10-21 13:18:07 +00:00
2022-11-10 17:19:03 +00:00
if ticket_price_input is not None :
current_ticket_number = " "
is_visible = False
2022-10-22 01:19:57 +00:00
2019-10-01 17:52:13 +00:00
try :
2022-11-10 17:19:03 +00:00
current_ticket_number = str ( ticket_price_input . get_attribute ( ' value ' ) ) . strip ( )
is_visible = ticket_price_input . is_enabled ( )
except Exception as exc :
pass
2022-11-23 04:39:46 +00:00
2022-11-10 17:19:03 +00:00
if len ( current_ticket_number ) > 0 :
if current_ticket_number != " 0 " :
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2022-10-22 01:19:57 +00:00
2023-01-02 06:53:28 +00:00
if is_ticket_number_assigned :
2022-11-10 17:19:03 +00:00
# no need to travel
break
2022-11-24 21:40:40 +00:00
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
2023-01-02 20:37:54 +00:00
2022-11-24 21:40:40 +00:00
if is_danger_notice :
# skip this row, because assign will fail, or fill ticket number as 1.
if pass_1_seat_remaining_enable :
continue
2022-11-10 17:19:03 +00:00
if is_visible :
is_match_area = False
match_area_code = 0
2022-11-23 04:39:46 +00:00
if len ( kktix_area_keyword_1 ) == 0 :
2022-11-10 17:19:03 +00:00
# keyword #1, empty, direct add to list.
is_match_area = True
match_area_code = 1
else :
# MUST match keyword #1.
2022-11-23 04:39:46 +00:00
if kktix_area_keyword_1 in row_text :
2022-11-10 17:19:03 +00:00
#print('match keyword#1')
2022-11-23 04:39:46 +00:00
2022-11-10 17:19:03 +00:00
# because of logic between keywords is AND!
2022-11-23 04:39:46 +00:00
if len ( kktix_area_keyword_1_and ) == 0 :
2022-11-10 17:19:03 +00:00
#print('keyword#2 is empty, directly match.')
# keyword #2 is empty, direct append.
is_match_area = True
match_area_code = 2
else :
2022-11-23 04:39:46 +00:00
if kktix_area_keyword_1_and in row_text :
2022-11-10 17:19:03 +00:00
#print('match keyword#2')
is_match_area = True
match_area_code = 3
2022-11-06 09:10:35 +00:00
else :
2022-11-10 17:19:03 +00:00
#print('not match keyword#2')
pass
2022-10-21 13:18:07 +00:00
else :
2022-11-10 17:19:03 +00:00
#print('not match keyword#1')
pass
2019-12-14 19:13:20 +00:00
2022-11-10 17:19:03 +00:00
if show_debug_message :
print ( " is_match_area: " , is_match_area )
print ( " match_area_code: " , match_area_code )
2019-10-01 17:52:13 +00:00
2022-11-10 17:19:03 +00:00
if is_match_area :
areas . append ( row )
2019-10-01 17:52:13 +00:00
2022-11-10 17:19:03 +00:00
if is_travel_interrupted :
# not sure to break or continue..., maybe break better.
break
2019-10-01 17:52:13 +00:00
else :
2022-11-10 17:19:03 +00:00
if show_debug_message :
print ( " no any price list found. " )
pass
# unknow issue...
if is_travel_interrupted :
pass
2023-01-02 06:53:28 +00:00
return is_ticket_number_assigned , areas
2022-11-10 17:19:03 +00:00
2022-11-24 21:40:40 +00:00
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 ) :
2022-11-10 17:19:03 +00:00
show_debug_message = True # debug.
2023-01-04 12:02:55 +00:00
show_debug_message = False # online
2022-11-10 17:19:03 +00:00
2022-11-24 21:40:40 +00:00
ticket_number_str = str ( ticket_number )
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned , areas = kktix_travel_price_list ( driver , ticket_number , pass_1_seat_remaining_enable , kktix_area_keyword_1 , kktix_area_keyword_1_and )
2022-11-10 17:19:03 +00:00
target_area = None
2023-01-02 06:53:28 +00:00
if not is_ticket_number_assigned :
2019-10-01 17:52:13 +00:00
if areas is not None :
if len ( areas ) > 0 :
target_row_index = 0
if kktix_area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
if kktix_area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
target_row_index = len ( areas ) - 1
if kktix_area_auto_select_mode == CONST_RANDOM :
target_row_index = random . randint ( 0 , len ( areas ) - 1 )
2022-11-10 17:19:03 +00:00
if show_debug_message :
print ( " target_row_index " , target_row_index )
target_area = areas [ target_row_index ]
ticket_price_input = None
if target_area is not None :
if show_debug_message :
print ( ' try to get input box element. ' )
try :
2022-11-13 04:50:53 +00:00
#print("target_area text", target_area.text)
2022-11-10 17:19:03 +00:00
ticket_price_input = target_area . find_element ( By . CSS_SELECTOR , " input[type= ' text ' ] " )
except Exception as exc :
pass
2022-11-09 18:36:17 +00:00
2022-11-10 17:19:03 +00:00
current_ticket_number = " "
is_visible = False
if ticket_price_input is not None :
if show_debug_message :
print ( " try to get input box value. " )
try :
current_ticket_number = str ( ticket_price_input . get_attribute ( ' value ' ) ) . strip ( )
is_visible = ticket_price_input . is_enabled ( )
except Exception as exc :
pass
2022-11-09 18:36:17 +00:00
2022-11-10 17:19:03 +00:00
if is_visible and len ( current_ticket_number ) > 0 :
if current_ticket_number == " 0 " :
try :
2022-11-24 21:40:40 +00:00
print ( " asssign ticket number: %s " % ticket_number_str )
2022-11-10 17:19:03 +00:00
ticket_price_input . clear ( )
2022-11-24 21:40:40 +00:00
ticket_price_input . send_keys ( ticket_number_str )
2022-10-18 18:15:05 +00:00
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2019-10-01 17:52:13 +00:00
except Exception as exc :
2022-11-10 17:19:03 +00:00
print ( " asssign ticket number to ticket-price field Exception: " )
print ( exc )
try :
ticket_price_input . clear ( )
ticket_price_input . send_keys ( " 1 " )
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2022-11-10 17:19:03 +00:00
except Exception as exc2 :
pass
else :
if show_debug_message :
print ( " value already assigned. " )
# already assigned.
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
return is_ticket_number_assigned
2019-10-01 17:52:13 +00:00
2022-11-20 07:57:16 +00:00
def kktix_get_web_datetime ( registrationsNewApp_div ) :
2022-10-18 18:15:05 +00:00
show_debug_message = True # debug.
2022-11-13 18:34:22 +00:00
show_debug_message = False # online
2022-10-18 18:15:05 +00:00
2019-12-06 18:36:43 +00:00
web_datetime = None
2019-10-01 17:52:13 +00:00
2019-12-06 18:36:43 +00:00
is_found_web_datetime = False
2022-10-18 18:15:05 +00:00
el_web_datetime_list = None
if not registrationsNewApp_div is None :
try :
2019-12-06 18:36:43 +00:00
el_web_datetime_list = registrationsNewApp_div . find_elements ( By . TAG_NAME , ' td ' )
2022-10-18 18:15:05 +00:00
except Exception as exc :
if show_debug_message :
print ( " find td.ng-binding Exception " )
print ( exc )
pass
#print("is_found_web_datetime", is_found_web_datetime)
if el_web_datetime_list is not None :
el_web_datetime_list_count = len ( el_web_datetime_list )
if el_web_datetime_list_count > 0 :
el_web_datetime = None
for el_web_datetime in el_web_datetime_list :
2022-11-13 04:50:53 +00:00
el_web_datetime_text = None
2022-10-18 18:15:05 +00:00
try :
el_web_datetime_text = el_web_datetime . text
if show_debug_message :
print ( " el_web_datetime_text: " , el_web_datetime_text )
except Exception as exc :
if show_debug_message :
print ( ' parse web datetime fail: ' )
print ( exc )
pass
2022-11-13 04:50:53 +00:00
if el_web_datetime_text is not None :
if len ( el_web_datetime_text ) > 0 :
now = datetime . now ( )
#print("now:", now)
for guess_year in range ( now . year , now . year + 3 ) :
current_year = str ( guess_year )
if current_year in el_web_datetime_text :
if u ' / ' in el_web_datetime_text :
web_datetime = el_web_datetime_text
is_found_web_datetime = True
break
if is_found_web_datetime :
break
2022-10-18 18:15:05 +00:00
else :
print ( " find td.ng-binding fail " )
2019-10-01 17:52:13 +00:00
2023-01-14 08:05:00 +00:00
if show_debug_message :
print ( ' is_found_web_datetime: ' , is_found_web_datetime )
print ( ' web_datetime: ' , web_datetime )
2019-12-06 18:36:43 +00:00
return web_datetime
2022-01-12 17:14:27 +00:00
def kktix_check_agree_checkbox ( driver ) :
2019-10-01 17:52:13 +00:00
is_need_refresh = False
2019-12-06 18:36:43 +00:00
is_finish_checkbox_click = False
2019-12-04 16:26:40 +00:00
person_agree_terms_checkbox = None
2019-10-01 17:52:13 +00:00
try :
2019-12-04 16:26:40 +00:00
person_agree_terms_checkbox = driver . find_element ( By . ID , ' person_agree_terms ' )
2022-11-18 22:59:34 +00:00
except Exception as exc :
print ( " find person_agree_terms checkbox Exception " )
pass
if person_agree_terms_checkbox is not None :
is_visible = False
try :
2019-12-04 16:26:40 +00:00
if person_agree_terms_checkbox . is_enabled ( ) :
2022-11-18 22:59:34 +00:00
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 :
2019-12-04 16:26:40 +00:00
person_agree_terms_checkbox . click ( )
2019-12-06 18:36:43 +00:00
is_finish_checkbox_click = True
2022-11-18 22:59:34 +00:00
except Exception as exc :
2019-12-04 16:26:40 +00:00
pass
2019-10-01 17:52:13 +00:00
else :
2022-11-18 22:59:34 +00:00
#print('checked')
is_finish_checkbox_click = True
2019-12-04 16:26:40 +00:00
else :
is_need_refresh = True
2022-11-18 22:59:34 +00:00
else :
is_need_refresh = True
2022-11-23 04:39:46 +00:00
2022-11-18 22:59:34 +00:00
if is_need_refresh :
print ( " find person_agree_terms checkbox fail, do refresh page. " )
2019-12-06 18:36:43 +00:00
return is_need_refresh , is_finish_checkbox_click
2019-12-14 19:13:20 +00:00
def kktix_check_register_status ( url ) :
2020-10-20 16:31:30 +00:00
#ex: https://xxx.kktix.cc/events/xxx
prefix_list = [ ' .com/events/ ' , ' .cc/events/ ' ]
2019-12-14 19:13:20 +00:00
postfix = ' /registrations/new '
2020-10-20 16:31:30 +00:00
is_match_event_code = False
event_code = " "
for prefix in prefix_list :
event_code = find_between ( url , prefix , postfix )
if len ( event_code ) > 0 :
is_match_event_code = True
#print('event_code:',event_code)
2020-10-24 03:22:14 +00:00
break
2022-10-18 18:15:05 +00:00
2019-12-14 19:13:20 +00:00
html_result = None
2020-10-20 16:31:30 +00:00
if is_match_event_code :
2020-10-24 03:22:14 +00:00
url = " https://kktix.com/g/events/ %s /register_info " % ( event_code )
#print('event_code:',event_code)
#print("url:", url)
2019-12-06 18:36:43 +00:00
2022-11-06 12:37:24 +00:00
user_agent = ' Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 '
2019-12-14 19:13:20 +00:00
headers = { " Accept-Language " : " zh-TW,zh;q=0.5 " , ' User-Agent ' : user_agent }
2019-12-06 18:36:43 +00:00
2019-12-14 19:13:20 +00:00
try :
2022-11-06 12:37:24 +00:00
html_result = requests . get ( url , headers = headers , timeout = 0.7 , allow_redirects = False )
2019-12-14 19:13:20 +00:00
except Exception as exc :
2022-11-06 12:37:24 +00:00
html_result = None
2019-12-14 19:13:20 +00:00
print ( " send reg_info request fail: " )
print ( exc )
2019-12-06 18:36:43 +00:00
2019-12-14 19:13:20 +00:00
registerStatus = None
if not html_result is None :
status_code = html_result . status_code
2020-10-24 03:22:14 +00:00
#print("status_code:",status_code)
2022-10-18 18:15:05 +00:00
2019-12-14 19:13:20 +00:00
if status_code == 200 :
html_text = html_result . text
#print("html_text:", html_text)
2019-12-04 16:26:40 +00:00
2019-12-14 19:13:20 +00:00
try :
jsLoads = json . loads ( html_text )
if ' inventory ' in jsLoads :
if ' registerStatus ' in jsLoads [ ' inventory ' ] :
registerStatus = jsLoads [ ' inventory ' ] [ ' registerStatus ' ]
except Exception as exc :
print ( " load reg_info json fail: " )
print ( exc )
2019-12-04 16:26:40 +00:00
pass
2019-10-01 17:52:13 +00:00
2020-10-24 03:22:14 +00:00
#print("registerStatus:", registerStatus)
2019-12-14 19:13:20 +00:00
return registerStatus
2019-10-01 17:52:13 +00:00
2023-01-14 08:05:00 +00:00
def get_answer_string_from_web_date ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , registrationsNewApp_div , captcha_text_div_text ) :
2022-10-18 18:15:05 +00:00
show_debug_message = True # debug.
2022-11-06 09:10:35 +00:00
show_debug_message = False # online
2022-10-18 18:15:05 +00:00
2023-01-02 20:37:54 +00:00
inferred_answer_string = None
2019-10-01 17:52:13 +00:00
2023-01-02 20:37:54 +00:00
is_need_parse_web_datetime = False
# '半形阿拉伯數字' & '半形數字'
if u ' 半形 ' in captcha_text_div_text and u ' 字 ' in captcha_text_div_text :
if u ' 演出日期 ' in captcha_text_div_text :
is_need_parse_web_datetime = True
if u ' 活動日期 ' in captcha_text_div_text :
is_need_parse_web_datetime = True
if u ' 表演日期 ' in captcha_text_div_text :
is_need_parse_web_datetime = True
if u ' 開始日期 ' in captcha_text_div_text :
is_need_parse_web_datetime = True
if u ' 演唱會日期 ' in captcha_text_div_text :
is_need_parse_web_datetime = True
if u ' 展覽日期 ' in captcha_text_div_text :
is_need_parse_web_datetime = True
if u ' 音樂會日期 ' in captcha_text_div_text :
is_need_parse_web_datetime = True
if u ' the date of the show you purchased ' in captcha_text_div_text :
is_need_parse_web_datetime = True
2022-11-18 22:59:34 +00:00
2023-01-02 20:37:54 +00:00
if show_debug_message :
print ( " is_need_parse_web_datetime: " , is_need_parse_web_datetime )
2019-10-01 17:52:13 +00:00
2023-01-02 20:37:54 +00:00
if is_need_parse_web_datetime :
web_datetime = kktix_get_web_datetime ( registrationsNewApp_div )
if not web_datetime is None :
if show_debug_message :
print ( " web_datetime: " , web_datetime )
2019-10-01 17:52:13 +00:00
2023-01-14 08:05:00 +00:00
captcha_text_formatted = format_question_string ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , captcha_text_div_text )
2023-01-02 20:37:54 +00:00
if show_debug_message :
print ( " captcha_text_formatted " , captcha_text_formatted )
2022-11-18 22:59:34 +00:00
2023-01-02 20:37:54 +00:00
my_datetime_foramted = None
2022-11-13 18:34:22 +00:00
2023-01-02 20:37:54 +00:00
# MMDD
if my_datetime_foramted is None :
if u ' 4位半形 ' in captcha_text_formatted :
my_datetime_foramted = " % m %d "
2019-10-01 17:52:13 +00:00
2023-01-02 20:37:54 +00:00
# for "如為2月30日, 請輸入0230"
if my_datetime_foramted is None :
2023-01-14 08:05:00 +00:00
right_part = " "
2023-01-02 20:37:54 +00:00
if CONST_EXAMPLE_SYMBOL in captcha_text_formatted :
right_part = captcha_text_formatted . split ( CONST_EXAMPLE_SYMBOL ) [ 1 ]
2023-01-14 08:05:00 +00:00
if CONST_INPUT_SYMBOL in right_part :
right_part = right_part . split ( CONST_INPUT_SYMBOL ) [ 1 ]
2023-01-02 20:37:54 +00:00
number_text = find_continuous_number ( right_part )
my_anwser_formated = convert_string_to_pattern ( number_text , dynamic_length = False )
if my_anwser_formated == u " [ \\ d][ \\ d][ \\ d][ \\ d][ \\ d][ \\ d][ \\ d][ \\ d] " :
my_datetime_foramted = " % Y % m %d "
if my_anwser_formated == u " [ \\ d][ \\ d][ \\ d][ \\ d] " :
my_datetime_foramted = " % m %d "
#print("my_datetime_foramted:", my_datetime_foramted)
2023-01-14 08:05:00 +00:00
if show_debug_message :
print ( " my_datetime_foramted " , my_datetime_foramted )
2023-01-02 20:37:54 +00:00
if my_datetime_foramted is None :
now = datetime . now ( )
for guess_year in range ( now . year - 4 , now . year + 2 ) :
current_year = str ( guess_year )
if current_year in captcha_text_formatted :
my_hint_index = captcha_text_formatted . find ( current_year )
my_hint_anwser = captcha_text_formatted [ my_hint_index : ]
#print("my_hint_anwser:", my_hint_anwser)
# get after.
my_delimitor_symbol = CONST_EXAMPLE_SYMBOL
if my_delimitor_symbol in my_hint_anwser :
my_delimitor_index = my_hint_anwser . find ( my_delimitor_symbol )
my_hint_anwser = my_hint_anwser [ my_delimitor_index + len ( my_delimitor_symbol ) : ]
#print("my_hint_anwser:", my_hint_anwser)
# get before.
my_delimitor_symbol = u ' , '
if my_delimitor_symbol in my_hint_anwser :
my_delimitor_index = my_hint_anwser . find ( my_delimitor_symbol )
my_hint_anwser = my_hint_anwser [ : my_delimitor_index ]
my_delimitor_symbol = u ' 。 '
if my_delimitor_symbol in my_hint_anwser :
my_delimitor_index = my_hint_anwser . find ( my_delimitor_symbol )
my_hint_anwser = my_hint_anwser [ : my_delimitor_index ]
# PS: space may not is delimitor...
my_delimitor_symbol = u ' '
if my_delimitor_symbol in my_hint_anwser :
my_delimitor_index = my_hint_anwser . find ( my_delimitor_symbol )
my_hint_anwser = my_hint_anwser [ : my_delimitor_index ]
#remove last char.
remove_last_char_list = [ ' ) ' , ' ( ' , ' . ' , ' 。 ' , ' ) ' , ' ( ' , ' [ ' , ' ] ' ]
for check_char in remove_last_char_list :
if my_hint_anwser [ - 1 : ] == check_char :
my_hint_anwser = my_hint_anwser [ : - 1 ]
my_anwser_formated = convert_string_to_pattern ( my_hint_anwser , dynamic_length = False )
if my_anwser_formated == u " [ \\ d][ \\ d][ \\ d][ \\ d][ \\ d][ \\ d][ \\ d][ \\ d] " :
my_datetime_foramted = " % Y % m %d "
if my_anwser_formated == u " [ \\ d][ \\ d][ \\ d][ \\ d]/[ \\ d][ \\ d]/[ \\ d][ \\ d] " :
my_datetime_foramted = " % Y/ % m/ %d "
if show_debug_message :
print ( " my_hint_anwser: " , my_hint_anwser )
print ( " my_anwser_formated: " , my_anwser_formated )
print ( " my_datetime_foramted: " , my_datetime_foramted )
break
if not my_datetime_foramted is None :
2023-01-14 08:05:00 +00:00
my_delimitor_symbol = ' '
2023-01-02 20:37:54 +00:00
if my_delimitor_symbol in web_datetime :
web_datetime = web_datetime [ : web_datetime . find ( my_delimitor_symbol ) ]
date_time = datetime . strptime ( web_datetime , u " % Y/ % m/ %d " )
if show_debug_message :
2023-01-14 08:05:00 +00:00
print ( " our web date_time: " , date_time )
2023-01-02 20:37:54 +00:00
ans = None
try :
2023-01-14 08:05:00 +00:00
if not date_time is None :
ans = date_time . strftime ( my_datetime_foramted )
2023-01-02 20:37:54 +00:00
except Exception as exc :
pass
inferred_answer_string = ans
2022-11-18 22:59:34 +00:00
if show_debug_message :
2023-01-14 08:05:00 +00:00
print ( " web date_time anwser: " , ans )
2022-10-18 18:15:05 +00:00
2023-01-02 20:37:54 +00:00
return inferred_answer_string
2022-10-18 18:15:05 +00:00
2023-01-14 08:05:00 +00:00
def get_answer_string_from_web_time ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , registrationsNewApp_div , captcha_text_div_text ) :
2023-01-02 20:37:54 +00:00
show_debug_message = True # debug.
2023-01-14 08:05:00 +00:00
show_debug_message = False # online
2019-10-01 17:52:13 +00:00
2023-01-02 20:37:54 +00:00
inferred_answer_string = None
# parse '演出時間'
is_need_parse_web_time = False
if u ' 半形 ' in captcha_text_div_text :
if u ' 演出時間 ' in captcha_text_div_text :
is_need_parse_web_time = True
if u ' 表演時間 ' in captcha_text_div_text :
is_need_parse_web_time = True
if u ' 開始時間 ' in captcha_text_div_text :
is_need_parse_web_time = True
if u ' 演唱會時間 ' in captcha_text_div_text :
is_need_parse_web_time = True
if u ' 展覽時間 ' in captcha_text_div_text :
is_need_parse_web_time = True
if u ' 音樂會時間 ' in captcha_text_div_text :
is_need_parse_web_time = True
if u ' the time of the show you purchased ' in captcha_text_div_text :
is_need_parse_web_time = True
#print("is_need_parse_web_time", is_need_parse_web_time)
if is_need_parse_web_time :
web_datetime = None
if not registrationsNewApp_div is None :
web_datetime = kktix_get_web_datetime ( registrationsNewApp_div )
if not web_datetime is None :
2023-01-14 08:05:00 +00:00
tmp_text = format_question_string ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , captcha_text_div_text )
2023-01-02 20:37:54 +00:00
my_datetime_foramted = None
if my_datetime_foramted is None :
my_hint_anwser = tmp_text
my_delimitor_symbol = CONST_EXAMPLE_SYMBOL
if my_delimitor_symbol in my_hint_anwser :
my_delimitor_index = my_hint_anwser . find ( my_delimitor_symbol )
my_hint_anwser = my_hint_anwser [ my_delimitor_index + len ( my_delimitor_symbol ) : ]
#print("my_hint_anwser:", my_hint_anwser)
# get before.
my_delimitor_symbol = u ' , '
if my_delimitor_symbol in my_hint_anwser :
my_delimitor_index = my_hint_anwser . find ( my_delimitor_symbol )
my_hint_anwser = my_hint_anwser [ : my_delimitor_index ]
my_delimitor_symbol = u ' 。 '
if my_delimitor_symbol in my_hint_anwser :
my_delimitor_index = my_hint_anwser . find ( my_delimitor_symbol )
my_hint_anwser = my_hint_anwser [ : my_delimitor_index ]
# PS: space may not is delimitor...
my_delimitor_symbol = u ' '
if my_delimitor_symbol in my_hint_anwser :
my_delimitor_index = my_hint_anwser . find ( my_delimitor_symbol )
my_hint_anwser = my_hint_anwser [ : my_delimitor_index ]
my_anwser_formated = convert_string_to_pattern ( my_hint_anwser , dynamic_length = False )
#print("my_hint_anwser:", my_hint_anwser)
#print(u"my_anwser_formated:", my_anwser_formated)
if my_anwser_formated == u " [ \\ d][ \\ d][ \\ d][ \\ d] " :
my_datetime_foramted = " % H % M "
if u ' 12小時 ' in tmp_text :
my_datetime_foramted = " % I % M "
if my_anwser_formated == u " [ \\ d][ \\ d]:[ \\ d][ \\ d] " :
my_datetime_foramted = " % H: % M "
if u ' 12小時 ' in tmp_text :
my_datetime_foramted = " % I: % M "
if not my_datetime_foramted is None :
date_delimitor_symbol = u ' ( '
if date_delimitor_symbol in web_datetime :
date_delimitor_symbol_index = web_datetime . find ( date_delimitor_symbol )
if date_delimitor_symbol_index > 8 :
web_datetime = web_datetime [ : date_delimitor_symbol_index - 1 ]
date_time = datetime . strptime ( web_datetime , u " % Y/ % m/ %d % H: % M " )
#print("date_time:", date_time)
ans = None
try :
ans = date_time . strftime ( my_datetime_foramted )
except Exception as exc :
pass
inferred_answer_string = ans
#print(u"my_anwser:", ans)
2022-11-18 22:59:34 +00:00
2023-01-02 20:37:54 +00:00
return inferred_answer_string
2022-10-18 18:15:05 +00:00
2023-01-02 20:37:54 +00:00
def check_answer_keep_symbol ( captcha_text_div_text ) :
is_need_keep_symbol = False
2022-11-06 09:10:35 +00:00
2023-01-02 20:37:54 +00:00
# format text
keep_symbol_tmp = captcha_text_div_text
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 也 ' , u ' 須 ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 必須 ' , u ' 須 ' )
2019-10-01 17:52:13 +00:00
2023-01-02 20:37:54 +00:00
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 全都 ' , u ' 都 ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 全部都 ' , u ' 都 ' )
2022-10-18 18:15:05 +00:00
2023-01-02 20:37:54 +00:00
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 一致 ' , u ' 相同 ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 一樣 ' , u ' 相同 ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 相等 ' , u ' 相同 ' )
2022-11-18 22:59:34 +00:00
2023-01-02 20:37:54 +00:00
if u ' 符號須都相同 ' in keep_symbol_tmp :
is_need_keep_symbol = True
2022-11-18 22:59:34 +00:00
2023-01-02 20:37:54 +00:00
if u ' 符號都相同 ' in keep_symbol_tmp :
is_need_keep_symbol = True
if u ' 符號須相同 ' in keep_symbol_tmp :
is_need_keep_symbol = True
2023-02-04 16:23:01 +00:00
# for: 大小寫含括號需一模一樣
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 含 ' , ' ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 和 ' , ' ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 與 ' , ' ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 還有 ' , ' ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 及 ' , ' ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 以及 ' , ' ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 需 ' , ' ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 必須 ' , ' ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 而且 ' , ' ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 且 ' , ' ' )
keep_symbol_tmp = keep_symbol_tmp . replace ( u ' 一模 ' , ' ' )
#print("keep_symbol_tmp:", keep_symbol_tmp)
if ' 大小寫括號相同 ' in keep_symbol_tmp :
is_need_keep_symbol = True
2023-01-02 20:37:54 +00:00
return is_need_keep_symbol
def get_answer_list_from_question_string ( registrationsNewApp_div , captcha_text_div_text ) :
show_debug_message = True # debug.
show_debug_message = False # online
inferred_answer_string = None
answer_list = None
CONST_EXAMPLE_SYMBOL = " 範例 "
2023-01-14 08:05:00 +00:00
CONST_INPUT_SYMBOL = " 輸入 "
2023-01-02 20:37:54 +00:00
2023-02-23 13:33:49 +00:00
if captcha_text_div_text is None :
captcha_text_div_text = " "
2023-01-02 20:37:54 +00:00
# 請在下方空白處輸入引號內文字:
if inferred_answer_string is None :
is_use_quota_message = False
if u " 「 " in captcha_text_div_text and u " 」 " in captcha_text_div_text :
2023-01-14 08:05:00 +00:00
if u ' 下 ' in captcha_text_div_text and u ' 空 ' in captcha_text_div_text and CONST_INPUT_SYMBOL in captcha_text_div_text and u ' 引號 ' in captcha_text_div_text and u ' 字 ' in captcha_text_div_text :
2023-01-02 20:37:54 +00:00
is_use_quota_message = True
2023-01-14 08:05:00 +00:00
if u ' 半形 ' in captcha_text_div_text and CONST_INPUT_SYMBOL in captcha_text_div_text and u ' 引號 ' in captcha_text_div_text and u ' 字 ' in captcha_text_div_text :
2023-01-02 20:37:54 +00:00
is_use_quota_message = True
#print("is_use_quota_message:" , is_use_quota_message)
if is_use_quota_message :
inferred_answer_string = find_between ( captcha_text_div_text , u " 「 " , u " 」 " )
#print("find captcha text:" , inferred_answer_string)
if inferred_answer_string is None :
is_use_quota_message = False
if u " 【 " in captcha_text_div_text and u " 】 " in captcha_text_div_text :
2023-01-14 08:05:00 +00:00
if u ' 下 ' in captcha_text_div_text and u ' 空 ' in captcha_text_div_text and CONST_INPUT_SYMBOL in captcha_text_div_text and u ' 引號 ' in captcha_text_div_text and u ' 字 ' in captcha_text_div_text :
2023-01-02 20:37:54 +00:00
is_use_quota_message = True
2023-01-14 08:05:00 +00:00
if u ' 半形 ' in captcha_text_div_text and CONST_INPUT_SYMBOL in captcha_text_div_text and u ' 引號 ' in captcha_text_div_text and u ' 字 ' in captcha_text_div_text :
2023-01-02 20:37:54 +00:00
is_use_quota_message = True
#print("is_use_quota_message:" , is_use_quota_message)
if is_use_quota_message :
inferred_answer_string = find_between ( captcha_text_div_text , u " 【 " , u " 】 " )
#print("find captcha text:" , inferred_answer_string)
# parse '演出日期'
if inferred_answer_string is None :
2023-01-14 08:05:00 +00:00
inferred_answer_string = get_answer_string_from_web_date ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , registrationsNewApp_div , captcha_text_div_text )
2023-01-02 20:37:54 +00:00
# parse '演出時間'
if inferred_answer_string is None :
2023-01-14 08:05:00 +00:00
inferred_answer_string = get_answer_string_from_web_time ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , registrationsNewApp_div , captcha_text_div_text )
2023-01-02 20:37:54 +00:00
# name of event.
if inferred_answer_string is None :
if u " name of event " in captcha_text_div_text :
if u ' ( ' in captcha_text_div_text and u ' ) ' in captcha_text_div_text and u ' ans: ' in captcha_text_div_text . lower ( ) :
target_symbol = u " ( "
star_index = captcha_text_div_text . find ( target_symbol )
target_symbol = u " : "
star_index = captcha_text_div_text . find ( target_symbol , star_index )
target_symbol = u " ) "
end_index = captcha_text_div_text . find ( target_symbol , star_index )
inferred_answer_string = captcha_text_div_text [ star_index + 1 : end_index ]
#print("inferred_answer_string:", inferred_answer_string)
# 二題式,組合問題。
is_combine_two_question = False
if u " 第一題 " in captcha_text_div_text and u " 第二題 " in captcha_text_div_text :
is_combine_two_question = True
if u " Q1. " in captcha_text_div_text and u " Q2. " in captcha_text_div_text :
if u " 二題 " in captcha_text_div_text :
is_combine_two_question = True
if u " 2題 " in captcha_text_div_text :
is_combine_two_question = True
if u " Q1: " in captcha_text_div_text and u " Q2: " in captcha_text_div_text :
if u " 二題 " in captcha_text_div_text :
is_combine_two_question = True
if u " 2題 " in captcha_text_div_text :
2022-11-18 22:59:34 +00:00
is_combine_two_question = True
2023-01-02 20:37:54 +00:00
if u " Q1 " in captcha_text_div_text and u " Q2 " in captcha_text_div_text :
if u " 二題 " in captcha_text_div_text :
is_combine_two_question = True
if u " 2題 " in captcha_text_div_text :
is_combine_two_question = True
if is_combine_two_question :
inferred_answer_string = None
#print("is_combine_two_question:", is_combine_two_question)
# still no answer.
if inferred_answer_string is None :
if not is_combine_two_question :
2023-01-14 08:05:00 +00:00
answer_list = get_answer_list_by_question ( CONST_EXAMPLE_SYMBOL , CONST_INPUT_SYMBOL , captcha_text_div_text )
2023-01-02 20:37:54 +00:00
if show_debug_message :
print ( " guess answer list: " , answer_list )
else :
if show_debug_message :
print ( " skip to guess answer because of combine question... " )
2019-10-01 17:52:13 +00:00
2023-01-02 20:37:54 +00:00
else :
2022-11-18 22:59:34 +00:00
if show_debug_message :
2023-01-02 20:37:54 +00:00
print ( " got an inferred_answer_string: " , inferred_answer_string )
return inferred_answer_string , answer_list
2019-10-01 17:52:13 +00:00
2023-01-02 20:37:54 +00:00
def kktix_reg_new_captcha ( registrationsNewApp_div , captcha_inner_div ) :
show_debug_message = True # debug.
show_debug_message = False # online
2019-10-01 17:52:13 +00:00
2023-01-02 20:37:54 +00:00
captcha_text_div = None
try :
captcha_text_div = captcha_inner_div . find_element ( By . TAG_NAME , " p " )
except Exception as exc :
pass
print ( " find p tag(captcha_text_div) fail " )
print ( exc )
captcha_text_div_text = None
if captcha_text_div is not None :
try :
captcha_text_div_text = captcha_text_div . text
except Exception as exc :
pass
# try to auto answer options.
answer_list = None
inferred_answer_string = None
if not captcha_text_div_text is None :
if show_debug_message :
print ( " captcha_text_div_text: " , captcha_text_div_text )
inferred_answer_string , answer_list = get_answer_list_from_question_string ( registrationsNewApp_div , captcha_text_div_text )
return inferred_answer_string , answer_list
2022-11-06 09:10:35 +00:00
2022-11-24 21:40:40 +00:00
def kktix_double_check_all_text_value ( driver , ticket_number_str ) :
2022-11-18 22:59:34 +00:00
is_do_press_next_button = False
2022-11-06 09:10:35 +00:00
2022-11-18 22:59:34 +00:00
# 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
2022-10-18 18:15:05 +00:00
2022-11-18 22:59:34 +00:00
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)
2022-11-24 21:40:40 +00:00
if current_ticket_number == ticket_number_str :
2022-11-18 22:59:34 +00:00
#print("bingo, match target ticket number.")
# ONLY, this case to auto press next button.
is_do_press_next_button = True
break
2019-10-01 17:52:13 +00:00
2022-11-18 22:59:34 +00:00
return is_do_press_next_button
2020-01-21 13:30:30 +00:00
2022-11-18 22:59:34 +00:00
def kktix_reg_new_main ( driver , answer_index , is_finish_checkbox_click , config_dict ) :
show_debug_message = True # debug.
2023-01-04 12:02:55 +00:00
show_debug_message = False # online
2022-10-18 18:15:05 +00:00
2022-11-18 22:59:34 +00:00
# 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)
2022-11-23 04:39:46 +00:00
2022-11-18 22:59:34 +00:00
# part 2: assign ticket number
2022-11-24 21:40:40 +00:00
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
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = False
2022-11-18 22:59:34 +00:00
if not registrationsNewApp_div is None :
kktix_area_auto_select_mode = config_dict [ " kktix " ] [ " area_mode " ]
2022-11-23 04:39:46 +00:00
kktix_area_keyword_1 = config_dict [ " kktix " ] [ " area_keyword_1 " ] . strip ( )
kktix_area_keyword_1_and = config_dict [ " kktix " ] [ " area_keyword_1_and " ] . strip ( )
kktix_area_keyword_2 = config_dict [ " kktix " ] [ " area_keyword_2 " ] . strip ( )
kktix_area_keyword_2_and = config_dict [ " kktix " ] [ " area_keyword_2_and " ] . strip ( )
2023-02-11 05:36:27 +00:00
kktix_area_keyword_2_enable = config_dict [ " kktix " ] [ " area_keyword_2_enable " ]
2022-11-23 04:39:46 +00:00
for retry_index in range ( 2 ) :
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = 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_ticket_number_assigned :
is_ticket_number_assigned = 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 )
2023-01-03 22:12:21 +00:00
#PS: keyword_2 not input, means all rows are match.
2023-01-02 06:53:28 +00:00
if not is_ticket_number_assigned :
2023-02-11 05:36:27 +00:00
if kktix_area_keyword_2_enable :
is_ticket_number_assigned = 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 )
2023-01-02 06:53:28 +00:00
if is_ticket_number_assigned :
2022-11-18 22:59:34 +00:00
break
2023-01-02 06:53:28 +00:00
#print('is_ticket_number_assigned:', is_ticket_number_assigned)
2019-10-01 17:52:13 +00:00
2022-11-18 22:59:34 +00:00
# part 3: captcha
is_captcha_appear = False
is_captcha_appear_and_filled_password = False
answer_list = None
2019-10-01 17:52:13 +00:00
2022-11-20 07:57:16 +00:00
# TODO: in guess options mode, no need to travel div again.
captcha_inner_div = None
2023-01-02 06:53:28 +00:00
if is_ticket_number_assigned :
2022-11-18 22:59:34 +00:00
try :
captcha_inner_div = driver . find_element ( By . CSS_SELECTOR , ' .custom-captcha-inner ' )
except Exception as exc :
pass
2022-10-18 18:15:05 +00:00
2022-11-20 07:57:16 +00:00
captcha_password_input_tag = None
if not captcha_inner_div is None :
try :
captcha_password_input_tag = captcha_inner_div . find_element ( By . TAG_NAME , " input " )
if show_debug_message :
print ( " found captcha input field " )
except Exception as exc :
pass
if not captcha_password_input_tag is None :
2023-01-02 20:37:54 +00:00
inferred_answer_string = None
2022-11-18 22:59:34 +00:00
if captcha_inner_div is not None :
is_captcha_appear = True
if show_debug_message :
print ( " found captcha_inner_div layor. " )
2022-11-23 04:39:46 +00:00
2022-11-18 22:59:34 +00:00
auto_guess_options = config_dict [ " kktix " ] [ " auto_guess_options " ]
2022-12-27 15:38:13 +00:00
user_guess_string = config_dict [ " kktix " ] [ " user_guess_string " ]
if len ( user_guess_string ) > 0 :
2023-01-02 20:37:54 +00:00
inferred_answer_string = user_guess_string
2022-12-27 15:38:13 +00:00
else :
if auto_guess_options :
2023-01-02 20:37:54 +00:00
inferred_answer_string , answer_list = kktix_reg_new_captcha ( registrationsNewApp_div , captcha_inner_div )
2022-12-27 15:38:13 +00:00
2023-01-02 20:37:54 +00:00
if inferred_answer_string is not None :
2022-11-20 07:57:16 +00:00
# password is not None, try to send.
2023-01-02 20:37:54 +00:00
is_cpatcha_sent = kktix_input_captcha_text ( captcha_password_input_tag , inferred_answer_string )
2022-11-20 07:57:16 +00:00
if is_cpatcha_sent :
is_captcha_appear_and_filled_password = True
else :
is_try_to_focus = False
if answer_list is None :
is_try_to_focus = True
else :
if len ( answer_list ) == 0 :
is_try_to_focus = True
if is_try_to_focus :
# password is None, focus to input, and play sound.
inputed_captcha_text = None
try :
inputed_captcha_text = captcha_password_input_tag . get_attribute ( ' value ' )
except Exception as exc :
pass
if inputed_captcha_text is None :
inputed_captcha_text = " "
if len ( inputed_captcha_text ) == 0 :
try :
2022-12-27 15:38:13 +00:00
#print("focus() captcha to input.")
2022-11-20 07:57:16 +00:00
check_and_play_sound_for_captcha ( config_dict )
captcha_password_input_tag . click ( )
time . sleep ( 1 )
# let user to input answer, bot sleep 1 second.
except Exception as exc :
pass
2022-11-23 04:39:46 +00:00
2022-11-18 22:59:34 +00:00
if show_debug_message :
print ( " is_captcha_appear: " , is_captcha_appear )
print ( " is_captcha_appear_and_filled_password: " , is_captcha_appear_and_filled_password )
2019-12-06 18:36:43 +00:00
2022-11-18 22:59:34 +00:00
# retry check agree checkbox again.
if not is_finish_checkbox_click :
2022-12-15 11:26:51 +00:00
auto_check_agree = config_dict [ " auto_check_agree " ]
if auto_check_agree :
is_need_refresh , is_finish_checkbox_click = kktix_check_agree_checkbox ( driver )
2022-11-18 22:59:34 +00:00
is_do_press_next_button = False
2023-01-02 06:53:28 +00:00
if is_ticket_number_assigned :
2022-11-18 22:59:34 +00:00
auto_press_next_step_button = config_dict [ " kktix " ] [ " auto_press_next_step_button " ]
2022-11-23 04:39:46 +00:00
if auto_press_next_step_button :
2022-11-18 22:59:34 +00:00
if is_finish_checkbox_click :
2022-11-24 21:40:40 +00:00
is_do_press_next_button = kktix_double_check_all_text_value ( driver , ticket_number_str )
2022-11-18 22:59:34 +00:00
else :
print ( " still unable to assign checkbox as selected. " )
if show_debug_message :
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 :
if is_captcha_appear_and_filled_password :
# for easy guest mode, we can fill the password correct.
#print("for easy guest mode, we can fill the password correct.")
click_ret = kktix_press_next_button ( driver )
2019-10-01 17:52:13 +00:00
else :
2022-11-18 22:59:34 +00:00
# not is easy guest mode.
#print("# not is easy guest mode.")
# merge with password dictionary, so need remove duplicate list
# PS: now, there are no password dictionary.
if not answer_list is None :
if len ( answer_list ) > 1 :
unique = [ x for i , x in enumerate ( answer_list ) if answer_list . index ( x ) == i ]
answer_list = unique
2022-11-20 07:57:16 +00:00
# start to try answers.
2022-11-18 22:59:34 +00:00
if not answer_list is None :
# for popular event
if len ( answer_list ) > 0 :
if answer_index < len ( answer_list ) - 1 :
if kktix_captcha_text_value ( captcha_inner_div ) == " " :
answer_index + = 1
2023-01-02 20:37:54 +00:00
answer_string = answer_list [ answer_index ]
2022-11-18 22:59:34 +00:00
2023-01-02 20:37:54 +00:00
if len ( answer_string ) > 0 :
print ( " send answer: " + answer_string )
is_cpatcha_sent = kktix_input_captcha_text ( captcha_password_input_tag , answer_string )
2022-11-20 07:57:16 +00:00
if is_cpatcha_sent :
2022-11-18 22:59:34 +00:00
kktix_press_next_button ( driver )
2022-10-22 01:19:57 +00:00
else :
2022-11-18 22:59:34 +00:00
# exceed index, do nothing.
2022-10-22 01:19:57 +00:00
pass
2019-10-01 17:52:13 +00:00
else :
2022-12-27 15:38:13 +00:00
# captcha appeared, but we don't have answer list.
2022-11-18 22:59:34 +00:00
pass
2019-10-01 17:52:13 +00:00
return answer_index
2022-11-16 15:43:53 +00:00
def kktix_reg_new ( driver , url , answer_index , kktix_register_status_last , config_dict ) :
2019-12-14 19:13:20 +00:00
registerStatus = kktix_register_status_last
# auto refresh for area list page.
is_need_refresh = False
is_finish_checkbox_click = False
2022-10-18 18:15:05 +00:00
2019-12-14 19:13:20 +00:00
if not is_need_refresh :
if registerStatus is None :
registerStatus = kktix_check_register_status ( url )
if not registerStatus is None :
print ( " registerStatus: " , registerStatus )
# OUT_OF_STOCK
if registerStatus != ' IN_STOCK ' :
is_need_refresh = True
2022-12-15 11:26:51 +00:00
auto_check_agree = config_dict [ " auto_check_agree " ]
if auto_check_agree :
if not is_need_refresh :
2022-01-12 17:14:27 +00:00
is_need_refresh , is_finish_checkbox_click = kktix_check_agree_checkbox ( driver )
2022-12-15 11:26:51 +00:00
if not is_need_refresh :
if not is_finish_checkbox_click :
# retry again.
is_need_refresh , is_finish_checkbox_click = kktix_check_agree_checkbox ( driver )
2022-11-18 22:59:34 +00:00
#print('check agree_terms_checkbox, is_need_refresh:',is_need_refresh)
2019-12-14 19:13:20 +00:00
if is_need_refresh :
try :
print ( " try to refresh page... " )
driver . refresh ( )
except Exception as exc :
#print("refresh fail")
pass
2022-10-18 18:15:05 +00:00
2019-12-14 19:13:20 +00:00
# reset answer_index
answer_index = - 1
registerStatus = None
else :
2022-11-18 22:59:34 +00:00
# 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 )
2019-12-14 19:13:20 +00:00
return answer_index , registerStatus
2021-12-24 10:52:37 +00:00
# PURPOSE: get target area list.
2022-01-26 12:49:16 +00:00
# PS: this is main block, use keyword to get rows.
# PS: it seems use date_auto_select_mode instead of area_auto_select_mode
2022-11-16 15:43:53 +00:00
def get_fami_target_area ( driver , date_keyword , area_keyword_1 , area_keyword_2 , area_keyword_3 , area_keyword_4 , area_auto_select_mode ) :
2022-01-26 12:49:16 +00:00
show_debug_message = True # debug.
2023-01-04 12:02:55 +00:00
show_debug_message = False # online
2022-01-26 12:49:16 +00:00
2023-01-04 12:02:55 +00:00
date_keyword = format_keyword_string ( date_keyword )
area_keyword_1 = format_keyword_string ( area_keyword_1 )
area_keyword_2 = format_keyword_string ( area_keyword_2 )
area_keyword_3 = format_keyword_string ( area_keyword_3 )
area_keyword_4 = format_keyword_string ( area_keyword_4 )
if show_debug_message :
print ( " try to find area block by keywords... " )
2021-12-24 10:52:37 +00:00
area_list = None
2019-10-01 17:52:13 +00:00
try :
2021-12-24 10:52:37 +00:00
my_css_selector = " table.session__list > tbody > tr "
area_list = driver . find_elements ( By . CSS_SELECTOR , my_css_selector )
2023-01-04 12:02:55 +00:00
except Exception as exc :
print ( " find #session date list fail " )
if show_debug_message :
print ( exc )
2022-01-26 12:49:16 +00:00
2023-01-04 12:02:55 +00:00
#PS: some blocks are generate by ajax, not appear at first time.
formated_area_list = None
if area_list is not None :
area_list_length = len ( area_list )
if show_debug_message :
print ( " lenth of area rows: " , area_list_length )
2022-01-26 12:49:16 +00:00
2023-01-04 12:02:55 +00:00
if area_list_length > 0 :
formated_area_list = [ ]
2022-01-26 12:49:16 +00:00
2023-01-04 12:02:55 +00:00
# filter list.
row_index = 0
for row in area_list :
row_index + = 1
row_is_enabled = True
el_btn = None
try :
my_css_selector = " button "
el_btn = row . find_element ( By . TAG_NAME , my_css_selector )
if el_btn is not None :
if not el_btn . is_enabled ( ) :
#print("row's button disabled!")
row_is_enabled = False
except Exception as exc :
if show_debug_message :
print ( exc )
pass
2022-01-26 12:49:16 +00:00
2023-01-04 12:02:55 +00:00
if row_is_enabled :
formated_area_list . append ( row )
2022-01-26 12:49:16 +00:00
2023-01-04 12:02:55 +00:00
matched_blocks = None
if not formated_area_list is None :
if len ( formated_area_list ) > 0 :
matched_blocks = [ ]
2022-01-26 12:49:16 +00:00
2023-01-04 12:02:55 +00:00
if len ( date_keyword ) == 0 and len ( area_keyword_1 ) == 0 and len ( area_keyword_2 ) == 0 :
# select all.
matched_blocks = formated_area_list
else :
# match keyword.
row_index = 0
for row in formated_area_list :
row_index + = 1
#print("row index:", row_index)
2019-10-01 17:52:13 +00:00
2023-01-04 12:02:55 +00:00
date_html_text = " "
area_html_text = " "
2019-10-01 17:52:13 +00:00
2023-01-04 12:02:55 +00:00
row_text = " "
try :
2021-12-24 10:52:37 +00:00
my_css_selector = " td:nth-child(1) "
td_date = row . find_element ( By . CSS_SELECTOR , my_css_selector )
if td_date is not None :
#print("date:", td_date.text)
2023-01-04 12:02:55 +00:00
date_html_text = format_keyword_string ( td_date . text )
2019-10-01 17:52:13 +00:00
2021-12-24 10:52:37 +00:00
my_css_selector = " td:nth-child(2) "
td_area = row . find_element ( By . CSS_SELECTOR , my_css_selector )
if td_area is not None :
#print("area:", td_area.text)
2023-01-04 12:02:55 +00:00
area_html_text = format_keyword_string ( td_area . text )
2019-10-01 17:52:13 +00:00
2023-01-04 12:02:55 +00:00
row_text = row . text
except Exception as exc :
print ( " get row text fail " )
break
2019-10-01 17:52:13 +00:00
2023-01-04 12:02:55 +00:00
if row_text is None :
2019-10-01 17:52:13 +00:00
row_text = " "
2022-11-23 04:39:46 +00:00
2023-01-04 12:02:55 +00:00
if len ( row_text ) > 0 :
# check date.
is_match_date = False
if len ( date_keyword ) > 0 :
if date_keyword in date_html_text :
#print("is_match_date")
2021-12-24 10:52:37 +00:00
is_match_date = True
2023-01-04 12:02:55 +00:00
else :
is_match_date = True
2021-12-24 10:52:37 +00:00
2023-01-04 12:02:55 +00:00
# check area.
is_match_area = False
if len ( area_keyword_1 ) > 0 :
if area_keyword_1 in area_html_text :
#print("is_match_area area_keyword_1")
is_match_area = True
# check keyword 2
if len ( area_keyword_2 ) > 0 :
if area_keyword_2 in area_html_text :
#print("is_match_area area_keyword_2")
2021-12-24 10:52:37 +00:00
is_match_area = True
2022-11-23 04:39:46 +00:00
2023-01-04 12:02:55 +00:00
# check keyword 3
if len ( area_keyword_3 ) > 0 :
if area_keyword_3 in area_html_text :
#print("is_match_area area_keyword_3")
is_match_area = True
2022-11-09 17:56:12 +00:00
2023-01-04 12:02:55 +00:00
# check keyword 4
if len ( area_keyword_4 ) > 0 :
if area_keyword_4 in area_html_text :
#print("is_match_area area_keyword_4")
is_match_area = True
else :
is_match_area = True
2022-11-09 17:56:12 +00:00
2023-01-04 12:02:55 +00:00
if is_match_date and is_match_area :
matched_blocks . append ( row )
2022-10-18 18:15:05 +00:00
2023-01-04 12:02:55 +00:00
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
print ( " only need first item, break area list loop. " )
break
2021-12-24 10:52:37 +00:00
2019-10-01 17:52:13 +00:00
2023-01-04 12:02:55 +00:00
return_row_count = 0
if not matched_blocks is None :
return_row_count = len ( matched_blocks )
if return_row_count == 0 :
matched_blocks = None
2019-10-01 17:52:13 +00:00
2023-01-04 12:02:55 +00:00
if show_debug_message :
print ( " return_row_count: " , return_row_count )
2019-10-01 17:52:13 +00:00
2023-01-04 12:02:55 +00:00
return matched_blocks
2019-10-01 17:52:13 +00:00
2022-11-16 15:43:53 +00:00
def fami_activity ( driver ) :
2021-12-24 10:52:37 +00:00
#print("fami_activity bingo")
2019-10-01 17:52:13 +00:00
2021-12-24 10:52:37 +00:00
#---------------------------
# part 1: press "buy" button.
#---------------------------
fami_start_to_buy_button = None
2022-11-16 15:43:53 +00:00
try :
fami_start_to_buy_button = driver . find_element ( By . ID , ' buyWaiting ' )
except Exception as exc :
pass
is_visible = False
2022-09-19 16:20:51 +00:00
if fami_start_to_buy_button is not None :
2022-11-09 18:36:17 +00:00
try :
if fami_start_to_buy_button . is_enabled ( ) :
is_visible = True
except Exception as exc :
pass
2022-11-16 15:43:53 +00:00
if is_visible :
try :
fami_start_to_buy_button . click ( )
except Exception as exc :
print ( " click buyWaiting button fail... " )
#print(exc)
#pass
2022-09-19 16:20:51 +00:00
try :
2022-11-16 15:43:53 +00:00
driver . execute_script ( " arguments[0].click(); " , fami_start_to_buy_button )
2022-09-19 16:20:51 +00:00
except Exception as exc :
2022-11-16 15:43:53 +00:00
pass
2019-10-01 17:52:13 +00:00
2019-10-27 01:31:22 +00:00
2022-11-16 15:43:53 +00:00
def fami_home ( driver , url , config_dict ) :
#print("fami_home bingo")
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = False
2022-11-18 22:59:34 +00:00
ticket_number = str ( config_dict [ " ticket_number " ] )
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 ( )
2022-10-18 18:15:05 +00:00
2021-12-24 10:52:37 +00:00
#---------------------------
# part 3: fill ticket number.
#---------------------------
ticket_el = None
2019-10-01 17:52:13 +00:00
try :
2021-12-24 10:52:37 +00:00
my_css_selector = " tr.ticket > td > select "
ticket_el = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
2022-11-16 15:43:53 +00:00
except Exception as exc :
pass
print ( " click buyWaiting button fail " )
#print(exc)
is_select_box_visible = False
if ticket_el is not None :
try :
2021-12-24 10:52:37 +00:00
if ticket_el . is_enabled ( ) :
is_select_box_visible = True
2022-11-16 15:43:53 +00:00
except Exception as exc :
pass
2022-11-23 04:39:46 +00:00
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = False
2022-11-16 15:43:53 +00:00
if is_select_box_visible :
ticket_number_select = None
try :
2021-12-24 10:52:37 +00:00
ticket_number_select = Select ( ticket_el )
2022-11-16 15:43:53 +00:00
except Exception as exc :
pass
if ticket_number_select is not None :
try :
#print("get select ticket value:" + Select(ticket_number_select).first_selected_option.text)
if ticket_number_select . first_selected_option . text == " 0 " or ticket_number_select . first_selected_option . text == " 選擇張數 " :
# target ticket number
ticket_number_select . select_by_visible_text ( ticket_number )
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2022-11-16 15:43:53 +00:00
except Exception as exc :
print ( " select_by_visible_text ticket_number fail " )
print ( exc )
2021-12-24 10:52:37 +00:00
try :
2022-11-16 15:43:53 +00:00
# try target ticket number twice
ticket_number_select . select_by_visible_text ( ticket_number )
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2021-12-24 10:52:37 +00:00
except Exception as exc :
2022-11-16 15:43:53 +00:00
print ( " select_by_visible_text ticket_number fail...2 " )
2021-12-24 10:52:37 +00:00
print ( exc )
2019-10-01 17:52:13 +00:00
2022-11-16 15:43:53 +00:00
# try buy one ticket
2021-12-24 10:52:37 +00:00
try :
2022-11-16 15:43:53 +00:00
ticket_number_select . select_by_visible_text ( " 1 " )
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2021-12-24 10:52:37 +00:00
except Exception as exc :
2022-11-16 15:43:53 +00:00
print ( " select_by_visible_text 1 fail " )
pass
2019-10-01 17:52:13 +00:00
2021-12-24 10:52:37 +00:00
#---------------------------
# part 4: press "next" button.
#---------------------------
2023-01-02 06:53:28 +00:00
if is_ticket_number_assigned :
2022-11-16 15:43:53 +00:00
fami_assign_site_button = None
try :
my_css_selector = " div.col > a.btn "
fami_assign_site_button = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
pass
2022-09-19 16:20:51 +00:00
if fami_assign_site_button is not None :
2022-11-09 18:36:17 +00:00
is_visible = False
try :
if fami_assign_site_button . is_enabled ( ) :
is_visible = True
except Exception as exc :
pass
if is_visible :
2022-09-19 16:20:51 +00:00
try :
2021-12-24 10:52:37 +00:00
fami_assign_site_button . click ( )
2022-09-19 16:20:51 +00:00
except Exception as exc :
print ( " click buyWaiting button fail " )
#print(exc)
try :
driver . execute_script ( " arguments[0].click(); " , fami_assign_site_button )
except Exception as exc :
pass
2019-10-27 01:31:22 +00:00
2021-12-24 10:52:37 +00:00
areas = None
if not is_select_box_visible :
#---------------------------
# part 2: select keywords
#---------------------------
2022-11-16 15:43:53 +00:00
areas = get_fami_target_area ( driver , date_keyword , area_keyword_1 , area_keyword_2 , area_keyword_3 , area_keyword_4 , area_auto_select_mode )
2019-10-27 01:31:22 +00:00
2022-01-26 12:49:16 +00:00
area_target = None
if areas is not None :
#print("area_auto_select_mode", area_auto_select_mode)
#print("len(areas)", len(areas))
if len ( areas ) > 0 :
target_row_index = 0
2019-10-01 17:52:13 +00:00
2022-01-26 12:49:16 +00:00
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
2019-10-01 17:52:13 +00:00
2022-01-26 12:49:16 +00:00
if area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
target_row_index = len ( areas ) - 1
2019-10-01 17:52:13 +00:00
2022-01-26 12:49:16 +00:00
if area_auto_select_mode == CONST_RANDOM :
target_row_index = random . randint ( 0 , len ( areas ) - 1 )
2019-10-01 17:52:13 +00:00
2022-01-26 12:49:16 +00:00
#print("target_row_index", target_row_index)
area_target = areas [ target_row_index ]
2019-10-01 17:52:13 +00:00
2022-01-26 12:49:16 +00:00
if area_target is not None :
2023-01-04 12:02:55 +00:00
el_btn = None
2022-11-09 18:36:17 +00:00
is_visible = False
try :
2023-01-04 12:02:55 +00:00
my_css_selector = " button "
el_btn = area_target . find_element ( By . TAG_NAME , my_css_selector )
if el_btn is not None :
if el_btn . is_enabled ( ) :
is_visible = True
2022-11-09 18:36:17 +00:00
except Exception as exc :
pass
if is_visible :
2022-01-26 12:49:16 +00:00
try :
2023-01-04 12:02:55 +00:00
el_btn . click ( )
2022-01-26 12:49:16 +00:00
except Exception as exc :
2022-09-19 16:20:51 +00:00
print ( " click buy button fail, start to retry... " )
try :
2023-01-04 12:02:55 +00:00
driver . execute_script ( " arguments[0].click(); " , el_btn )
2022-09-19 16:20:51 +00:00
except Exception as exc :
pass
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
# purpose: date auto select
2023-01-03 18:54:42 +00:00
def urbtix_date_auto_select ( driver , auto_select_mode , date_keyword , auto_reload_coming_soon_page_enable ) :
2023-01-02 06:53:28 +00:00
show_debug_message = True # debug.
2023-01-03 18:54:42 +00:00
show_debug_message = False # online
2023-01-02 06:53:28 +00:00
2019-10-01 17:52:13 +00:00
ret = False
2023-01-02 06:53:28 +00:00
matched_blocks = None
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
# clean stop word.
date_keyword = format_keyword_string ( date_keyword )
date_keyword_and = " "
area_list = None
2019-10-01 17:52:13 +00:00
try :
2023-01-02 06:53:28 +00:00
#print("try to find cityline area block")
2023-01-03 21:09:17 +00:00
my_css_selector = " div.conent-wrapper > div.list-wrapper > ul "
2023-01-02 06:53:28 +00:00
area_list = driver . find_elements ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
print ( " find #date-time-position date list fail " )
print ( exc )
2019-10-01 17:52:13 +00:00
2023-01-03 21:09:17 +00:00
#PS: some blocks are generate by ajax, not appear at first time.
formated_area_list = None
2023-01-02 06:53:28 +00:00
if area_list is not None :
area_list_count = len ( area_list )
if show_debug_message :
print ( " date_list_count: " , area_list_count )
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
if area_list_count > 0 :
2023-01-03 21:09:17 +00:00
formated_area_list = [ ]
2023-01-03 18:54:42 +00:00
# filter list.
row_index = 0
for row in area_list :
row_index + = 1
row_is_enabled = True
el_btn = None
try :
my_css_selector = " div.buy-icon "
el_btn = row . find_element ( By . CSS_SELECTOR , my_css_selector )
if el_btn is not None :
2023-01-03 21:09:17 +00:00
button_class_string = str ( el_btn . get_attribute ( ' class ' ) )
if len ( button_class_string ) > 1 :
if ' disabled ' in button_class_string :
if show_debug_message :
print ( " found disabled activity at row: " , row_index )
row_is_enabled = False
2023-01-03 18:54:42 +00:00
except Exception as exc :
if show_debug_message :
print ( exc )
pass
if row_is_enabled :
formated_area_list . append ( row )
if show_debug_message :
print ( " formated_area_list count: " , len ( formated_area_list ) )
2023-01-02 06:53:28 +00:00
if len ( date_keyword ) == 0 :
2023-01-03 18:54:42 +00:00
matched_blocks = formated_area_list
2023-01-02 06:53:28 +00:00
else :
# match keyword.
if show_debug_message :
print ( " start to match keyword: " , date_keyword )
matched_blocks = [ ]
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
row_index = 0
2023-01-03 18:54:42 +00:00
for row in formated_area_list :
2023-01-02 06:53:28 +00:00
row_index + = 1
#row_is_enabled=False
row_is_enabled = True
if row_is_enabled :
row_text = " "
2019-10-01 17:52:13 +00:00
try :
2023-01-02 06:53:28 +00:00
row_text = row . text
2019-10-01 17:52:13 +00:00
except Exception as exc :
2023-01-02 06:53:28 +00:00
print ( " get text fail " )
break
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
if row_text is None :
row_text = " "
if len ( row_text ) > 0 :
row_text = format_keyword_string ( row_text )
if show_debug_message :
print ( " row_text: " , row_text )
is_match_area = False
match_area_code = 0
if date_keyword in row_text :
if len ( date_keyword_and ) == 0 :
if show_debug_message :
print ( ' keyword_and # is empty, directly match. ' )
# keyword #2 is empty, direct append.
is_match_area = True
match_area_code = 2
else :
if date_keyword_and in row_text :
if show_debug_message :
print ( ' match keyword_and ' )
is_match_area = True
match_area_code = 3
else :
if show_debug_message :
print ( ' not match keyword_and ' )
pass
if is_match_area :
matched_blocks . append ( row )
if show_debug_message :
2023-01-04 12:02:55 +00:00
if not matched_blocks is None :
print ( " after match keyword, found count: " , len ( matched_blocks ) )
2023-01-02 06:53:28 +00:00
else :
print ( " not found date-time-position " )
pass
else :
print ( " date date-time-position is None " )
2022-07-26 16:51:43 +00:00
pass
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
target_area = None
if matched_blocks is not None :
if len ( matched_blocks ) > 0 :
target_row_index = 0
if auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
if auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
target_row_index = len ( matched_blocks ) - 1
if auto_select_mode == CONST_RANDOM :
target_row_index = random . randint ( 0 , len ( matched_blocks ) - 1 )
target_area = matched_blocks [ target_row_index ]
if target_area is not None :
el_btn = None
try :
#print("target_area text", target_area.text)
my_css_selector = " div.buy-icon "
el_btn = target_area . find_element ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
pass
if el_btn is not None :
2023-01-03 18:54:42 +00:00
is_button_enable = True
2023-01-02 06:53:28 +00:00
try :
2023-01-03 18:54:42 +00:00
if not el_btn . is_enabled ( ) :
is_button_enable = False
else :
# button enable, but class disable.
button_class_string = str ( el_btn . get_attribute ( ' class ' ) )
if len ( button_class_string ) > 1 :
if ' disabled ' in button_class_string :
is_button_enable = False
if is_button_enable :
2023-01-02 06:53:28 +00:00
el_btn . click ( )
2023-01-03 18:54:42 +00:00
ret = True
2023-01-02 06:53:28 +00:00
print ( " buy icon pressed. " )
except Exception as exc :
# use plan B
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , el_btn )
ret = True
except Exception as exc :
pass
2023-01-03 18:54:42 +00:00
else :
# no target.
if auto_reload_coming_soon_page_enable :
# auto refresh for date list page.
2023-01-03 21:09:17 +00:00
if not formated_area_list is None :
if len ( formated_area_list ) == 0 :
try :
driver . refresh ( )
time . sleep ( 1.0 )
except Exception as exc :
pass
2023-01-02 06:53:28 +00:00
return ret
def urbtix_purchase_ticket ( driver , config_dict ) :
show_debug_message = True # debug.
2023-01-03 18:54:42 +00:00
show_debug_message = False # online
2023-01-02 06:53:28 +00:00
date_auto_select_mode = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " mode " ]
date_keyword = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " date_keyword " ] . strip ( )
2023-01-03 18:54:42 +00:00
auto_reload_coming_soon_page_enable = config_dict [ " tixcraft " ] [ " auto_reload_coming_soon_page " ]
2023-01-02 06:53:28 +00:00
2023-01-03 18:54:42 +00:00
if show_debug_message :
print ( " date_keyword: " , date_keyword )
is_date_assign_by_bot = urbtix_date_auto_select ( driver , date_auto_select_mode , date_keyword , auto_reload_coming_soon_page_enable )
2023-01-02 06:53:28 +00:00
return is_date_assign_by_bot
2019-10-01 17:52:13 +00:00
# purpose: area auto select
2023-01-02 06:53:28 +00:00
def urbtix_area_auto_select ( driver , area_auto_select_mode , area_keyword_1 , area_keyword_1_and ) :
show_debug_message = True # debug.
2023-01-04 12:02:55 +00:00
show_debug_message = False # online
2023-01-02 06:53:28 +00:00
2023-01-23 13:32:47 +00:00
is_price_assign_by_bot = False
2023-01-11 00:40:31 +00:00
is_need_refresh = False
2023-01-02 06:53:28 +00:00
matched_blocks = None
# clean stop word.
area_keyword_1 = format_keyword_string ( area_keyword_1 )
area_keyword_1_and = format_keyword_string ( area_keyword_1_and )
2019-10-01 17:52:13 +00:00
area_list = None
try :
2023-01-02 06:53:28 +00:00
#print("try to find cityline area block")
my_css_selector = " div.area-info "
2019-10-01 17:52:13 +00:00
area_list = driver . find_elements ( By . CSS_SELECTOR , my_css_selector )
2023-01-02 06:53:28 +00:00
except Exception as exc :
print ( " find #ticket-price-tbl date list fail " )
print ( exc )
2019-10-01 17:52:13 +00:00
2023-01-03 21:09:17 +00:00
formated_area_list = None
2023-01-02 06:53:28 +00:00
if area_list is not None :
area_list_count = len ( area_list )
if show_debug_message :
print ( " area_list_count: " , area_list_count )
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
if area_list_count > 0 :
2023-01-03 21:09:17 +00:00
formated_area_list = [ ]
# filter list.
row_index = 0
for row in area_list :
row_index + = 1
row_is_enabled = True
try :
button_class_string = str ( row . get_attribute ( ' class ' ) )
if len ( button_class_string ) > 1 :
if ' disabled ' in button_class_string :
row_is_enabled = False
if ' selected ' in button_class_string :
# someone is selected. skip this process.
row_is_enabled = False
2023-01-23 13:32:47 +00:00
is_price_assign_by_bot = True
2023-01-03 21:09:17 +00:00
break
except Exception as exc :
pass
if row_is_enabled :
formated_area_list . append ( row )
2023-01-11 00:40:31 +00:00
else :
2023-01-03 21:09:17 +00:00
if show_debug_message :
2023-01-11 00:40:31 +00:00
print ( " area_list_count is empty. " )
pass
else :
if show_debug_message :
print ( " area_list_count is None. " )
pass
2023-01-02 06:53:28 +00:00
2023-01-23 13:32:47 +00:00
if is_price_assign_by_bot :
formated_area_list = None
2023-01-11 00:40:31 +00:00
if formated_area_list is not None :
area_list_count = len ( formated_area_list )
if show_debug_message :
print ( " formated_area_list count: " , area_list_count )
if area_list_count > 0 :
2023-01-02 06:53:28 +00:00
if len ( area_keyword_1 ) == 0 :
2023-01-03 21:09:17 +00:00
matched_blocks = formated_area_list
2023-01-02 06:53:28 +00:00
else :
# match keyword.
if show_debug_message :
print ( " start to match keyword: " , area_keyword_1 )
print ( " keyword and: " , area_keyword_1_and )
matched_blocks = [ ]
row_index = 0
2023-01-03 21:09:17 +00:00
for row in formated_area_list :
2023-01-02 06:53:28 +00:00
row_index + = 1
2023-01-02 20:37:54 +00:00
2023-01-02 06:53:28 +00:00
row_is_enabled = True
if row_is_enabled :
row_text = " "
2019-10-01 17:52:13 +00:00
try :
2023-01-02 06:53:28 +00:00
row_text = row . text
2019-10-01 17:52:13 +00:00
except Exception as exc :
2023-01-02 06:53:28 +00:00
print ( " get text fail " )
break
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
if row_text is None :
2019-10-01 17:52:13 +00:00
row_text = " "
2023-01-02 06:53:28 +00:00
if len ( row_text ) > 0 :
row_text = format_keyword_string ( row_text )
if show_debug_message :
print ( " row_text: " , row_text )
is_match_area = False
match_area_code = 0
if area_keyword_1 in row_text :
if len ( area_keyword_1_and ) == 0 :
if show_debug_message :
print ( ' keyword_and is empty, directly match. ' )
# keyword #2 is empty, direct append.
is_match_area = True
match_area_code = 2
else :
if area_keyword_1_and in row_text :
if show_debug_message :
print ( ' match keyword_and ' )
is_match_area = True
match_area_code = 3
else :
if show_debug_message :
print ( ' not match keyword_and ' )
pass
2022-11-13 04:50:53 +00:00
2023-01-02 06:53:28 +00:00
if is_match_area :
matched_blocks . append ( row )
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
if show_debug_message :
if not matched_blocks is None :
print ( " after match keyword, found count: " , len ( matched_blocks ) )
else :
2023-01-11 00:40:31 +00:00
is_need_refresh = True
2023-01-04 12:02:55 +00:00
if show_debug_message :
2023-01-11 00:40:31 +00:00
print ( " formated_area_list is empty. " )
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
target_area = None
if matched_blocks is not None :
if len ( matched_blocks ) > 0 :
2019-10-01 17:52:13 +00:00
target_row_index = 0
2023-01-02 06:53:28 +00:00
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
if area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
target_row_index = len ( matched_blocks ) - 1
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
if area_auto_select_mode == CONST_RANDOM :
target_row_index = random . randint ( 0 , len ( matched_blocks ) - 1 )
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
target_area = matched_blocks [ target_row_index ]
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
if target_area is not None :
2019-10-01 17:52:13 +00:00
try :
2023-01-02 06:53:28 +00:00
if target_area . is_enabled ( ) :
target_area . click ( )
2023-01-23 13:32:47 +00:00
is_price_assign_by_bot = True
2019-10-01 17:52:13 +00:00
except Exception as exc :
2023-01-02 06:53:28 +00:00
print ( " click target_area link fail " )
2019-10-01 17:52:13 +00:00
print ( exc )
2023-01-03 18:54:42 +00:00
# use plan B
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , target_area )
2023-01-23 13:32:47 +00:00
is_price_assign_by_bot = True
2023-01-03 18:54:42 +00:00
except Exception as exc :
pass
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
return is_need_refresh , is_price_assign_by_bot
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
def urbtix_ticket_number_auto_select ( driver , ticket_number ) :
show_debug_message = True # debug.
2023-02-09 16:22:13 +00:00
show_debug_message = False # online
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = False
ticket_number_str = str ( ticket_number )
# check ticket input textbox.
ticket_price_input = None
2019-10-01 17:52:13 +00:00
try :
2023-01-02 06:53:28 +00:00
ticket_price_input = driver . find_element ( By . CSS_SELECTOR , " input.ticket-count " )
except Exception as exc :
pass
if ticket_price_input is not None :
current_ticket_number = " "
is_visible = False
try :
current_ticket_number = str ( ticket_price_input . get_attribute ( ' value ' ) ) . strip ( )
is_visible = ticket_price_input . is_enabled ( )
except Exception as exc :
pass
if len ( current_ticket_number ) > 0 :
if current_ticket_number == " 0 " :
try :
print ( " asssign ticket number: %s " % ticket_number_str )
ticket_price_input . clear ( )
ticket_price_input . send_keys ( ticket_number_str )
is_ticket_number_assigned = True
except Exception as exc :
print ( " asssign ticket number to ticket-price field Exception: " )
print ( exc )
try :
ticket_price_input . clear ( )
ticket_price_input . send_keys ( " 1 " )
is_ticket_number_assigned = True
except Exception as exc2 :
pass
else :
# already assigned.
is_ticket_number_assigned = True
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
if is_ticket_number_assigned :
el_btn = None
try :
my_css_selector = " div.footer > div > div "
el_btn = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
pass
if el_btn is not None :
try :
if el_btn . is_enabled ( ) :
el_btn . click ( )
print ( " varify site icon pressed. " )
except Exception as exc :
# use plan B
2023-01-18 08:40:41 +00:00
'''
2023-01-02 06:53:28 +00:00
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , el_btn )
2022-07-26 16:51:43 +00:00
ret = True
2023-01-02 06:53:28 +00:00
except Exception as exc :
pass
2023-01-18 08:40:41 +00:00
'''
pass
2023-01-02 06:53:28 +00:00
else :
if show_debug_message :
print ( " varify site icon is None. " )
if is_ticket_number_assigned :
el_btn = None
try :
my_css_selector = " div.button-inner > div > div.button-text "
el_btn = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
pass
if el_btn is not None :
try :
if el_btn . is_enabled ( ) :
el_btn . click ( )
print ( " shopping-cart icon pressed. " )
except Exception as exc :
# use plan B
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , el_btn )
ret = True
except Exception as exc :
pass
else :
if show_debug_message :
print ( " shopping-cart site icon is None. " )
return is_ticket_number_assigned
2019-10-01 17:52:13 +00:00
2022-11-18 22:59:34 +00:00
def urbtix_performance ( driver , config_dict ) :
2023-01-02 06:53:28 +00:00
show_debug_message = True # debug.
show_debug_message = False # online
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
ret = False
2022-01-12 17:14:27 +00:00
2023-01-02 06:53:28 +00:00
is_price_assign_by_bot = False
2023-01-11 00:40:31 +00:00
is_need_refresh = False
2023-01-02 06:53:28 +00:00
auto_fill_ticket_number = True
2019-10-01 17:52:13 +00:00
if auto_fill_ticket_number :
2023-01-02 06:53:28 +00:00
# click price row.
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 ( )
area_keyword_1_and = " "
area_keyword_2_and = " "
2023-01-03 21:09:17 +00:00
if show_debug_message :
print ( " area_keyword_1: " , area_keyword_1 )
#print("area_keyword_1_and:", area_keyword_1_and)
print ( " area_keyword_2: " , area_keyword_2 )
#print("area_keyword_2_and:", area_keyword_2_and)
2023-01-11 00:40:31 +00:00
is_need_refresh , is_price_assign_by_bot = urbtix_area_auto_select ( driver , area_auto_select_mode , area_keyword_1 , area_keyword_1_and )
2023-01-02 06:53:28 +00:00
2023-01-11 00:40:31 +00:00
if not is_need_refresh :
if not is_price_assign_by_bot :
# try keyword_2
if len ( area_keyword_2 ) > 0 :
is_need_refresh , is_price_assign_by_bot = urbtix_area_auto_select ( driver , area_auto_select_mode , area_keyword_2 , area_keyword_2_and )
2019-10-01 17:52:13 +00:00
2023-01-11 00:40:31 +00:00
if not is_need_refresh :
if not is_price_assign_by_bot :
if len ( area_keyword_3 ) > 0 :
is_need_refresh , is_price_assign_by_bot = urbtix_area_auto_select ( driver , area_auto_select_mode , area_keyword_3 , " " )
2019-10-01 17:52:13 +00:00
2023-01-11 00:40:31 +00:00
if not is_need_refresh :
if not is_price_assign_by_bot :
if len ( area_keyword_4 ) > 0 :
is_need_refresh , is_price_assign_by_bot = urbtix_area_auto_select ( driver , area_auto_select_mode , area_keyword_4 , " " )
# un-tested. disable refresh for now.
is_need_refresh = False
if is_need_refresh :
try :
driver . refresh ( )
except Exception as exc :
pass
2023-01-02 06:53:28 +00:00
# choose ticket.
ticket_number = str ( config_dict [ " ticket_number " ] )
is_ticket_number_assigned = urbtix_ticket_number_auto_select ( driver , ticket_number )
if show_debug_message :
print ( " ticket_number: " , ticket_number )
print ( " is_ticket_number_assigned: " , is_ticket_number_assigned )
return ret
# purpose: date auto select
2023-01-03 18:54:42 +00:00
def cityline_date_auto_select ( driver , auto_select_mode , date_keyword , auto_reload_coming_soon_page_enable ) :
2023-01-02 06:53:28 +00:00
show_debug_message = True # debug.
show_debug_message = False # online
ret = False
matched_blocks = None
# clean stop word.
date_keyword = format_keyword_string ( date_keyword )
date_keyword_and = " "
area_list = None
try :
#print("try to find cityline area block")
my_css_selector = " button.date-time-position "
area_list = driver . find_elements ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
print ( " find #date-time-position date list fail " )
print ( exc )
2023-01-03 21:09:17 +00:00
#PS: some blocks are generate by ajax, not appear at first time.
formated_area_list = None
2023-02-19 04:16:31 +00:00
2023-01-02 06:53:28 +00:00
if area_list is not None :
area_list_count = len ( area_list )
if show_debug_message :
print ( " date_list_count: " , area_list_count )
if area_list_count > 0 :
2023-01-03 21:09:17 +00:00
formated_area_list = [ ]
2023-01-03 18:54:42 +00:00
# filter list.
2023-02-19 04:16:31 +00:00
2023-01-03 18:54:42 +00:00
row_index = 0
for row in area_list :
row_index + = 1
row_is_enabled = True
el_btn = None
try :
if not row . is_enabled ( ) :
row_is_enabled = False
except Exception as exc :
if show_debug_message :
print ( exc )
pass
if row_is_enabled :
formated_area_list . append ( row )
if show_debug_message :
print ( " formated_area_list count: " , len ( formated_area_list ) )
2023-01-02 06:53:28 +00:00
if len ( date_keyword ) == 0 :
2023-01-03 18:54:42 +00:00
matched_blocks = formated_area_list
2023-01-02 06:53:28 +00:00
else :
# match keyword.
if show_debug_message :
print ( " start to match keyword: " , date_keyword )
matched_blocks = [ ]
row_index = 0
2023-01-03 18:54:42 +00:00
for row in formated_area_list :
2023-01-02 06:53:28 +00:00
row_index + = 1
#row_is_enabled=False
row_is_enabled = True
if row_is_enabled :
row_text = " "
try :
row_text = row . text
except Exception as exc :
print ( " get text fail " )
break
if row_text is None :
row_text = " "
if len ( row_text ) > 0 :
row_text = format_keyword_string ( row_text )
if show_debug_message :
print ( " row_text: " , row_text )
is_match_area = False
match_area_code = 0
if date_keyword in row_text :
if len ( date_keyword_and ) == 0 :
if show_debug_message :
print ( ' keyword_and # is empty, directly match. ' )
# keyword #2 is empty, direct append.
is_match_area = True
match_area_code = 2
else :
if date_keyword_and in row_text :
if show_debug_message :
print ( ' match keyword_and ' )
is_match_area = True
match_area_code = 3
else :
if show_debug_message :
print ( ' not match keyword_and ' )
pass
if is_match_area :
matched_blocks . append ( row )
if show_debug_message :
2023-01-04 12:02:55 +00:00
if not matched_blocks is None :
print ( " after match keyword, found count: " , len ( matched_blocks ) )
2023-01-02 06:53:28 +00:00
else :
print ( " not found date-time-position " )
pass
else :
print ( " date date-time-position is None " )
pass
target_area = None
if matched_blocks is not None :
if len ( matched_blocks ) > 0 :
target_row_index = 0
if auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
if auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
target_row_index = len ( matched_blocks ) - 1
if auto_select_mode == CONST_RANDOM :
target_row_index = random . randint ( 0 , len ( matched_blocks ) - 1 )
target_area = matched_blocks [ target_row_index ]
if target_area is not None :
try :
if target_area . is_enabled ( ) :
target_area . click ( )
ret = True
except Exception as exc :
2023-01-03 18:54:42 +00:00
# use plan B
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , target_area )
ret = True
except Exception as exc :
pass
else :
# no target.
if auto_reload_coming_soon_page_enable :
# auto refresh for date list page.
2023-01-03 21:09:17 +00:00
if not formated_area_list is None :
if len ( formated_area_list ) == 0 :
try :
driver . refresh ( )
2023-01-18 08:40:41 +00:00
time . sleep ( 0.4 )
2023-01-03 21:09:17 +00:00
except Exception as exc :
pass
2023-01-02 06:53:28 +00:00
return ret
2019-10-01 17:52:13 +00:00
# purpose: area auto select
# return:
# True: area block appear.
# False: area block not appear.
2022-12-22 17:17:37 +00:00
# ps: return is successfully click on the price radio.
def cityline_area_auto_select ( driver , area_auto_select_mode , area_keyword_1 , area_keyword_1_and ) :
show_debug_message = True # debug.
show_debug_message = False # online
2023-01-23 13:32:47 +00:00
is_price_assign_by_bot = False
2023-01-11 00:40:31 +00:00
is_need_refresh = False
2023-01-02 06:53:28 +00:00
matched_blocks = None
2019-10-01 17:52:13 +00:00
2022-12-22 17:17:37 +00:00
# clean stop word.
area_keyword_1 = format_keyword_string ( area_keyword_1 )
area_keyword_1_and = format_keyword_string ( area_keyword_1_and )
2019-10-01 17:52:13 +00:00
area_list = None
try :
#print("try to find cityline area block")
2022-12-22 17:17:37 +00:00
my_css_selector = " .form-check "
2019-10-01 17:52:13 +00:00
area_list = driver . find_elements ( By . CSS_SELECTOR , my_css_selector )
2022-12-22 17:17:37 +00:00
except Exception as exc :
print ( " find #ticket-price-tbl date list fail " )
print ( exc )
2019-10-01 17:52:13 +00:00
2023-01-03 21:09:17 +00:00
formated_area_list = None
2022-12-22 17:17:37 +00:00
if area_list is not None :
area_list_count = len ( area_list )
if show_debug_message :
print ( " area_list_count: " , area_list_count )
2019-10-01 17:52:13 +00:00
2022-12-22 17:17:37 +00:00
if area_list_count > 0 :
2023-01-03 21:09:17 +00:00
formated_area_list = [ ]
# filter list.
row_index = 0
for row in area_list :
row_index + = 1
row_is_enabled = True
try :
my_css_selector = " span.price-limited > span "
span_price_limited = row . find_element ( By . CSS_SELECTOR , my_css_selector )
if not span_price_limited is None :
#print("found span limited at idx:", row_index)
span_i18n_string = str ( span_price_limited . get_attribute ( ' data-i18n ' ) )
if len ( span_i18n_string ) > 1 :
if ' soldout ' in span_i18n_string :
#print("found span limited soldout at idx:", row_index)
row_is_enabled = False
except Exception as exc :
pass
if row_is_enabled :
formated_area_list . append ( row )
2023-01-11 00:40:31 +00:00
else :
2023-01-03 21:09:17 +00:00
if show_debug_message :
2023-01-11 00:40:31 +00:00
print ( " area_list_count is empty. " )
pass
else :
if show_debug_message :
print ( " area_list_count is None. " )
pass
if formated_area_list is not None :
area_list_count = len ( formated_area_list )
if show_debug_message :
print ( " formated_area_list count: " , area_list_count )
2019-10-01 17:52:13 +00:00
2023-01-11 00:40:31 +00:00
if area_list_count > 0 :
2022-12-22 17:17:37 +00:00
if len ( area_keyword_1 ) == 0 :
2023-01-03 21:09:17 +00:00
matched_blocks = formated_area_list
2022-12-22 17:17:37 +00:00
else :
# match keyword.
if show_debug_message :
print ( " start to match keyword: " , area_keyword_1 )
print ( " keyword and: " , area_keyword_1_and )
2023-01-02 06:53:28 +00:00
matched_blocks = [ ]
2022-12-22 17:17:37 +00:00
row_index = 0
2023-01-03 21:09:17 +00:00
for row in formated_area_list :
2022-12-22 17:17:37 +00:00
row_index + = 1
#row_is_enabled=False
row_is_enabled = True
if row_is_enabled :
row_text = " "
2019-10-01 17:52:13 +00:00
try :
2022-12-22 17:17:37 +00:00
row_text = row . text
2019-10-01 17:52:13 +00:00
except Exception as exc :
2022-12-22 17:17:37 +00:00
print ( " get text fail " )
break
2019-10-01 17:52:13 +00:00
2022-12-22 17:17:37 +00:00
if row_text is None :
2019-10-01 17:52:13 +00:00
row_text = " "
2022-12-22 17:17:37 +00:00
if len ( row_text ) > 0 :
row_text = format_keyword_string ( row_text )
if show_debug_message :
print ( " row_text: " , row_text )
2022-11-13 04:50:53 +00:00
2022-12-22 17:17:37 +00:00
is_match_area = False
match_area_code = 0
2019-10-01 17:52:13 +00:00
2022-12-22 17:17:37 +00:00
if area_keyword_1 in row_text :
if len ( area_keyword_1_and ) == 0 :
if show_debug_message :
2023-01-02 06:53:28 +00:00
print ( ' keyword_and is empty, directly match. ' )
2022-12-22 17:17:37 +00:00
# keyword #2 is empty, direct append.
is_match_area = True
match_area_code = 2
else :
if area_keyword_1_and in row_text :
if show_debug_message :
2023-01-02 06:53:28 +00:00
print ( ' match keyword_and ' )
2022-12-22 17:17:37 +00:00
is_match_area = True
match_area_code = 3
else :
if show_debug_message :
2023-01-02 06:53:28 +00:00
print ( ' not match keyword_and ' )
2022-12-22 17:17:37 +00:00
pass
if is_match_area :
2023-01-02 06:53:28 +00:00
matched_blocks . append ( row )
2022-12-22 17:17:37 +00:00
if show_debug_message :
2023-01-04 12:02:55 +00:00
if not matched_blocks is None :
print ( " after match keyword, found count: " , len ( matched_blocks ) )
2019-10-01 17:52:13 +00:00
else :
2023-01-11 00:40:31 +00:00
is_need_refresh = True
2023-01-04 12:02:55 +00:00
if show_debug_message :
2023-01-11 00:40:31 +00:00
print ( " formated_area_list is empty. " )
2019-10-01 17:52:13 +00:00
2022-12-22 17:17:37 +00:00
target_area = None
2023-01-02 06:53:28 +00:00
if matched_blocks is not None :
if len ( matched_blocks ) > 0 :
2019-10-01 17:52:13 +00:00
target_row_index = 0
2022-12-22 17:17:37 +00:00
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
2019-10-01 17:52:13 +00:00
2022-12-22 17:17:37 +00:00
if area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
2023-01-02 06:53:28 +00:00
target_row_index = len ( matched_blocks ) - 1
2019-10-01 17:52:13 +00:00
2022-12-22 17:17:37 +00:00
if area_auto_select_mode == CONST_RANDOM :
2023-01-02 06:53:28 +00:00
target_row_index = random . randint ( 0 , len ( matched_blocks ) - 1 )
2019-10-01 17:52:13 +00:00
2023-01-02 06:53:28 +00:00
target_area = matched_blocks [ target_row_index ]
2019-10-01 17:52:13 +00:00
2022-12-22 17:17:37 +00:00
if target_area is not None :
2023-01-02 06:53:28 +00:00
el_btn = None
2019-10-01 17:52:13 +00:00
try :
2022-12-22 17:17:37 +00:00
#print("target_area text", target_area.text)
2019-10-01 17:52:13 +00:00
my_css_selector = " input[type=radio] "
2023-01-02 06:53:28 +00:00
el_btn = target_area . find_element ( By . CSS_SELECTOR , my_css_selector )
if el_btn is not None :
if el_btn . is_enabled ( ) :
if not el_btn . is_selected ( ) :
el_btn . click ( )
2023-01-23 13:32:47 +00:00
is_price_assign_by_bot = True
2022-12-22 17:17:37 +00:00
else :
2023-01-23 13:32:47 +00:00
is_price_assign_by_bot = True
2022-12-22 17:17:37 +00:00
#print("bingo, click target_area radio")
2019-10-01 17:52:13 +00:00
except Exception as exc :
2022-12-22 17:17:37 +00:00
print ( " click target_area radio a link fail " )
2019-10-01 17:52:13 +00:00
print ( exc )
pass
2023-01-23 13:32:47 +00:00
return is_need_refresh , is_price_assign_by_bot
2019-10-01 17:52:13 +00:00
2023-01-03 21:09:17 +00:00
#[TODO]:
# double check selected radio matched by keyword/keyword_and.
2022-11-18 22:59:34 +00:00
def cityline_area_selected_text ( driver ) :
2022-12-22 17:17:37 +00:00
ret = False
2019-10-01 17:52:13 +00:00
return ret
2022-11-18 22:59:34 +00:00
def cityline_ticket_number_auto_select ( driver , ticket_number ) :
2023-01-03 18:54:42 +00:00
selector_string = ' select.select-num '
by_method = By . CSS_SELECTOR
return assign_ticket_number_by_select ( driver , ticket_number , by_method , selector_string )
def ibon_ticket_number_auto_select ( driver , ticket_number ) :
2023-01-03 21:09:17 +00:00
selector_string = ' table.table > tbody > tr > td > select '
2023-01-03 18:54:42 +00:00
by_method = By . CSS_SELECTOR
return assign_ticket_number_by_select ( driver , ticket_number , by_method , selector_string )
def assign_ticket_number_by_select ( driver , ticket_number , by_method , selector_string ) :
2022-11-20 07:57:16 +00:00
show_debug_message = True # debug.
show_debug_message = False # online
2019-10-01 17:52:13 +00:00
2022-11-20 07:57:16 +00:00
form_select = None
2019-10-01 17:52:13 +00:00
try :
2023-01-03 18:54:42 +00:00
form_select = driver . find_element ( by_method , selector_string )
2019-10-01 17:52:13 +00:00
except Exception as exc :
2022-11-20 07:57:16 +00:00
if show_debug_message :
print ( " find ticket_number select fail " )
print ( exc )
2019-10-01 17:52:13 +00:00
pass
2022-11-20 07:57:16 +00:00
select_obj = None
if form_select is not None :
is_visible = False
2022-11-18 22:59:34 +00:00
try :
2022-11-20 07:57:16 +00:00
is_visible = form_select . is_enabled ( )
2022-11-18 22:59:34 +00:00
except Exception as exc :
pass
2022-11-20 07:57:16 +00:00
if is_visible :
2022-11-18 22:59:34 +00:00
try :
2022-11-20 07:57:16 +00:00
select_obj = Select ( form_select )
2022-11-18 22:59:34 +00:00
except Exception as exc :
pass
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = False
2022-11-20 07:57:16 +00:00
if not select_obj is None :
row_text = None
2022-11-18 22:59:34 +00:00
try :
2022-11-20 07:57:16 +00:00
row_text = select_obj . first_selected_option . text
2022-11-18 22:59:34 +00:00
except Exception as exc :
pass
2022-11-20 07:57:16 +00:00
if not row_text is None :
if len ( row_text ) > 0 :
if row_text != " 0 " :
# ticket assign.
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = True
2022-11-18 22:59:34 +00:00
2023-01-02 06:53:28 +00:00
if not is_ticket_number_assigned :
is_ticket_number_assigned = tixcraft_ticket_number_auto_fill ( driver , select_obj , ticket_number )
2022-11-20 07:57:16 +00:00
else :
if show_debug_message :
print ( " ticket_number assigned by previous action. " )
2022-11-18 22:59:34 +00:00
2023-01-02 06:53:28 +00:00
return is_ticket_number_assigned
def cityline_purchase_button_press ( driver , config_dict ) :
show_debug_message = True # debug.
show_debug_message = False # online
2019-10-01 17:52:13 +00:00
2022-12-22 17:17:37 +00:00
ret = False
2023-01-02 06:53:28 +00:00
date_auto_select_mode = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " mode " ]
date_keyword = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " date_keyword " ] . strip ( )
2023-01-03 18:54:42 +00:00
auto_reload_coming_soon_page_enable = config_dict [ " tixcraft " ] [ " auto_reload_coming_soon_page " ]
2023-01-02 06:53:28 +00:00
2023-01-03 18:54:42 +00:00
if show_debug_message :
print ( " date_keyword: " , date_keyword )
is_date_assign_by_bot = cityline_date_auto_select ( driver , date_auto_select_mode , date_keyword , auto_reload_coming_soon_page_enable )
2023-01-02 06:53:28 +00:00
el_btn = None
2022-12-22 17:17:37 +00:00
try :
2023-01-02 06:53:28 +00:00
el_btn = driver . find_element ( By . CSS_SELECTOR , ' button.purchase-btn ' )
2022-12-22 17:17:37 +00:00
except Exception as exc :
print ( " find next button fail " )
2023-01-03 18:54:42 +00:00
#print(exc)
pass
2022-12-22 17:17:37 +00:00
2023-01-02 06:53:28 +00:00
if el_btn is not None :
print ( " bingo, found next button " )
try :
if el_btn . is_enabled ( ) :
el_btn . click ( )
ret = True
except Exception as exc :
print ( " press next button fail " )
print ( exc )
# use plan B
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , el_btn )
ret = True
except Exception as exc :
pass
2022-12-22 17:17:37 +00:00
return ret
2019-10-01 17:52:13 +00:00
2022-11-18 22:59:34 +00:00
def cityline_next_button_press ( driver ) :
2019-10-01 17:52:13 +00:00
ret = False
2023-01-02 06:53:28 +00:00
el_nav = None
el_btn = None
2019-10-01 17:52:13 +00:00
try :
2023-01-02 06:53:28 +00:00
el_nav = driver . find_element ( By . CSS_SELECTOR , ' .puchase-bottom ' )
el_btn = driver . find_element ( By . CSS_SELECTOR , ' #expressPurchaseBtn ' )
2019-10-01 17:52:13 +00:00
except Exception as exc :
2023-01-02 06:53:28 +00:00
print ( " find next button fail... " )
2019-10-01 17:52:13 +00:00
print ( exc )
2023-01-02 06:53:28 +00:00
if el_btn is not None and el_nav is not None :
print ( " bingo, found next button, start to press " )
try :
if el_btn . is_enabled ( ) :
#el_btn.click()
builder = ActionChains ( driver )
builder . move_to_element ( el_nav )
builder . click ( el_btn )
builder . perform ( )
ret = True
except Exception as exc :
print ( " click next button fail... " )
print ( exc )
# use plan B
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , el_btn )
ret = True
except Exception as exc :
pass
2019-10-01 17:52:13 +00:00
return ret
2022-11-20 07:57:16 +00:00
def cityline_performance ( driver , config_dict ) :
show_debug_message = True # debug.
2023-01-02 06:53:28 +00:00
show_debug_message = False # online
2022-11-23 04:39:46 +00:00
2022-12-22 17:17:37 +00:00
is_price_assign_by_bot = False
2023-01-11 00:40:31 +00:00
is_need_refresh = False
2023-01-02 06:53:28 +00:00
auto_fill_ticket_number = True
2022-11-20 07:57:16 +00:00
if auto_fill_ticket_number :
# click price row.
2023-01-02 06:53:28 +00:00
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 ( )
area_keyword_1_and = " "
area_keyword_2_and = " "
2023-01-03 21:09:17 +00:00
if show_debug_message :
print ( " area_keyword_1: " , area_keyword_1 )
#print("area_keyword_1_and:", area_keyword_1_and)
2023-01-04 12:02:55 +00:00
print ( " area_keyword_2: " , area_keyword_2 )
#print("area_keyword_2_and:", area_keyword_2_and)
2023-02-19 04:16:31 +00:00
2023-01-03 21:09:17 +00:00
# PS: cityline price default value is selected at the first option.
2023-01-11 00:40:31 +00:00
is_need_refresh , is_price_assign_by_bot = cityline_area_auto_select ( driver , area_auto_select_mode , area_keyword_1 , area_keyword_1_and )
2022-12-22 17:17:37 +00:00
2023-01-11 00:40:31 +00:00
if not is_need_refresh :
if not is_price_assign_by_bot :
# try keyword_2
if len ( area_keyword_2 ) > 0 :
is_need_refresh , is_price_assign_by_bot = cityline_area_auto_select ( driver , area_auto_select_mode , area_keyword_2 , area_keyword_2_and )
2023-01-02 06:53:28 +00:00
2023-01-11 00:40:31 +00:00
if not is_need_refresh :
if not is_price_assign_by_bot :
if len ( area_keyword_3 ) > 0 :
is_need_refresh , is_price_assign_by_bot = cityline_area_auto_select ( driver , area_auto_select_mode , area_keyword_3 , " " )
2023-01-02 06:53:28 +00:00
2023-01-11 00:40:31 +00:00
if not is_need_refresh :
if not is_price_assign_by_bot :
if len ( area_keyword_4 ) > 0 :
is_need_refresh , is_price_assign_by_bot = cityline_area_auto_select ( driver , area_auto_select_mode , area_keyword_4 , " " )
# un-tested. disable refresh for now.
is_need_refresh = False
if is_need_refresh :
try :
driver . refresh ( )
except Exception as exc :
pass
2019-10-01 17:52:13 +00:00
2022-11-20 07:57:16 +00:00
# choose ticket.
2022-11-18 22:59:34 +00:00
ticket_number = str ( config_dict [ " ticket_number " ] )
2023-01-02 06:53:28 +00:00
is_ticket_number_assigned = cityline_ticket_number_auto_select ( driver , ticket_number )
2019-10-01 17:52:13 +00:00
2022-11-20 07:57:16 +00:00
if show_debug_message :
print ( " ticket_number: " , ticket_number )
2023-01-02 06:53:28 +00:00
print ( " is_ticket_number_assigned: " , is_ticket_number_assigned )
2022-11-20 07:57:16 +00:00
2023-01-02 06:53:28 +00:00
if is_ticket_number_assigned :
auto_press_next_step_button = True
2022-11-20 07:57:16 +00:00
if auto_press_next_step_button :
2022-12-22 17:17:37 +00:00
if not is_price_assign_by_bot :
#[TODO]:
# double check selected radio matched by keyword/keyword_and.
# cityline_area_selected_text(driver)
pass
if is_price_assign_by_bot :
2023-01-03 21:09:17 +00:00
for i in range ( 2 ) :
2022-12-22 17:17:37 +00:00
click_ret = cityline_next_button_press ( driver )
if click_ret :
break
2019-10-01 17:52:13 +00:00
2023-01-03 18:54:42 +00:00
def ibon_date_auto_select ( driver , auto_select_mode , date_keyword , auto_reload_coming_soon_page_enable ) :
show_debug_message = True # debug.
show_debug_message = False # online
2019-10-01 17:52:13 +00:00
ret = False
2023-01-03 18:54:42 +00:00
matched_blocks = None
# clean stop word.
date_keyword = format_keyword_string ( date_keyword )
date_keyword_and = " "
area_list = None
2019-10-01 17:52:13 +00:00
try :
2023-01-03 18:54:42 +00:00
#print("try to find cityline area block")
2023-02-12 09:49:55 +00:00
my_css_selector = " div.single-content > div > div.row > div > div.tr "
2023-01-03 18:54:42 +00:00
area_list = driver . find_elements ( By . CSS_SELECTOR , my_css_selector )
2022-12-27 15:38:13 +00:00
except Exception as exc :
2023-02-12 09:49:55 +00:00
print ( " find date-time rows fail " )
2023-01-03 18:54:42 +00:00
print ( exc )
2022-12-27 15:38:13 +00:00
2023-01-03 21:09:17 +00:00
#PS: some blocks are generate by ajax, not appear at first time.
formated_area_list = None
2023-01-03 18:54:42 +00:00
if area_list is not None :
area_list_count = len ( area_list )
if show_debug_message :
print ( " date_list_count: " , area_list_count )
2022-12-27 15:38:13 +00:00
2023-01-03 18:54:42 +00:00
if area_list_count > 0 :
2023-01-03 21:09:17 +00:00
formated_area_list = [ ]
2023-01-03 18:54:42 +00:00
# filter list.
row_index = 0
for row in area_list :
row_index + = 1
2023-01-23 13:32:47 +00:00
# default is enabled.
2023-01-03 18:54:42 +00:00
row_is_enabled = True
el_btn = None
try :
my_css_selector = " button "
el_btn = row . find_element ( By . TAG_NAME , my_css_selector )
if el_btn is not None :
if not el_btn . is_enabled ( ) :
#print("row's button disabled!")
row_is_enabled = False
except Exception as exc :
if show_debug_message :
print ( exc )
pass
2022-12-27 15:38:13 +00:00
2023-01-03 18:54:42 +00:00
if row_is_enabled :
formated_area_list . append ( row )
2022-12-27 15:38:13 +00:00
2023-01-23 20:36:06 +00:00
if formated_area_list is not None :
area_list_count = len ( formated_area_list )
if show_debug_message :
print ( " formated_area_list count: " , area_list_count )
if area_list_count > 0 :
2023-01-03 18:54:42 +00:00
if len ( date_keyword ) == 0 :
matched_blocks = formated_area_list
else :
# match keyword.
if show_debug_message :
print ( " start to match keyword: " , date_keyword )
matched_blocks = [ ]
2022-12-27 15:38:13 +00:00
2023-01-03 18:54:42 +00:00
row_index = 0
for row in formated_area_list :
row_index + = 1
row_is_enabled = True
if row_is_enabled :
row_text = " "
try :
row_text = row . text
except Exception as exc :
print ( " get text fail " )
break
2022-12-27 15:38:13 +00:00
2023-01-03 18:54:42 +00:00
if row_text is None :
row_text = " "
2022-12-27 15:38:13 +00:00
2023-01-03 18:54:42 +00:00
if len ( row_text ) > 0 :
row_text = format_keyword_string ( row_text )
if show_debug_message :
print ( " row_text: " , row_text )
2019-10-01 17:52:13 +00:00
2023-01-03 18:54:42 +00:00
is_match_area = False
match_area_code = 0
2022-11-16 15:43:53 +00:00
2023-01-03 18:54:42 +00:00
if date_keyword in row_text :
if len ( date_keyword_and ) == 0 :
if show_debug_message :
print ( ' keyword_and # is empty, directly match. ' )
# keyword #2 is empty, direct append.
is_match_area = True
match_area_code = 2
else :
if date_keyword_and in row_text :
if show_debug_message :
print ( ' match keyword_and ' )
is_match_area = True
match_area_code = 3
else :
if show_debug_message :
print ( ' not match keyword_and ' )
pass
2022-11-16 15:43:53 +00:00
2023-01-03 18:54:42 +00:00
if is_match_area :
matched_blocks . append ( row )
if show_debug_message :
2023-01-04 12:02:55 +00:00
if not matched_blocks is None :
print ( " after match keyword, found count: " , len ( matched_blocks ) )
2023-01-03 18:54:42 +00:00
else :
print ( " not found date-time-position " )
2022-11-16 15:43:53 +00:00
pass
2023-01-03 18:54:42 +00:00
else :
print ( " date date-time-position is None " )
pass
2022-11-16 15:43:53 +00:00
2023-01-03 18:54:42 +00:00
target_area = None
if matched_blocks is not None :
if len ( matched_blocks ) > 0 :
target_row_index = 0
if auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
if auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
target_row_index = len ( matched_blocks ) - 1
if auto_select_mode == CONST_RANDOM :
target_row_index = random . randint ( 0 , len ( matched_blocks ) - 1 )
target_area = matched_blocks [ target_row_index ]
if target_area is not None :
el_btn = None
2022-11-16 15:43:53 +00:00
try :
2023-01-03 18:54:42 +00:00
my_css_selector = " button.btn "
el_btn = target_area . find_element ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
pass
if el_btn is not None :
try :
if el_btn . is_enabled ( ) :
el_btn . click ( )
print ( " buy icon pressed. " )
ret = True
except Exception as exc :
# use plan B
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , el_btn )
ret = True
except Exception as exc :
pass
else :
# no target to click.
if auto_reload_coming_soon_page_enable :
# auto refresh for date list page.
2023-01-03 21:09:17 +00:00
if not formated_area_list is None :
if len ( formated_area_list ) == 0 :
try :
driver . refresh ( )
2023-01-18 08:40:41 +00:00
time . sleep ( 0.4 )
2023-01-03 21:09:17 +00:00
except Exception as exc :
pass
2023-01-03 18:54:42 +00:00
return ret
def ibon_activity_info ( driver , config_dict ) :
show_debug_message = True # debug.
2023-01-04 12:02:55 +00:00
show_debug_message = False # online
2023-01-03 18:54:42 +00:00
date_auto_select_mode = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " mode " ]
date_keyword = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " date_keyword " ] . strip ( )
auto_reload_coming_soon_page_enable = config_dict [ " tixcraft " ] [ " auto_reload_coming_soon_page " ]
if show_debug_message :
print ( " date_keyword: " , date_keyword )
print ( " auto_reload_coming_soon_page_enable: " , auto_reload_coming_soon_page_enable )
is_date_assign_by_bot = ibon_date_auto_select ( driver , date_auto_select_mode , date_keyword , auto_reload_coming_soon_page_enable )
return is_date_assign_by_bot
def ibon_area_auto_select ( driver , area_auto_select_mode , area_keyword_1 , area_keyword_1_and ) :
show_debug_message = True # debug.
show_debug_message = False # online
2023-01-23 13:32:47 +00:00
is_price_assign_by_bot = False
2023-01-11 00:40:31 +00:00
is_need_refresh = False
2023-01-03 18:54:42 +00:00
matched_blocks = None
# clean stop word.
area_keyword_1 = format_keyword_string ( area_keyword_1 )
area_keyword_1_and = format_keyword_string ( area_keyword_1_and )
area_list = None
try :
#print("try to find cityline area block")
my_css_selector = " div.col-md-5 > table > tbody > tr "
area_list = driver . find_elements ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
print ( " find #ticket-price-tbl date list fail " )
print ( exc )
2023-01-03 21:09:17 +00:00
formated_area_list = None
2023-01-03 18:54:42 +00:00
if area_list is not None :
area_list_count = len ( area_list )
if show_debug_message :
print ( " area_list_count: " , area_list_count )
if area_list_count > 0 :
2023-01-03 21:09:17 +00:00
formated_area_list = [ ]
# filter list.
row_index = 0
for row in area_list :
row_index + = 1
row_is_enabled = True
2023-02-26 08:39:37 +00:00
if row_is_enabled :
try :
if ' 已售完 ' in row . text :
2023-01-11 00:40:31 +00:00
row_is_enabled = False
2023-02-26 08:39:37 +00:00
except Exception as exc :
pass
if row_is_enabled :
try :
button_class_string = str ( row . get_attribute ( ' class ' ) )
if len ( button_class_string ) > 1 :
if ' disabled ' in button_class_string :
row_is_enabled = False
except Exception as exc :
pass
2023-01-03 21:09:17 +00:00
if row_is_enabled :
formated_area_list . append ( row )
2023-01-11 00:40:31 +00:00
else :
2023-01-03 21:09:17 +00:00
if show_debug_message :
2023-01-11 00:40:31 +00:00
print ( " area_list_count is empty. " )
pass
else :
if show_debug_message :
print ( " area_list_count is None. " )
pass
2023-01-23 13:32:47 +00:00
if is_price_assign_by_bot :
formated_area_list = None
2023-01-11 00:40:31 +00:00
if formated_area_list is not None :
area_list_count = len ( formated_area_list )
if show_debug_message :
print ( " formated_area_list count: " , area_list_count )
2023-01-03 18:54:42 +00:00
2023-01-11 00:40:31 +00:00
if area_list_count > 0 :
2023-01-03 18:54:42 +00:00
if len ( area_keyword_1 ) == 0 :
2023-01-03 21:09:17 +00:00
matched_blocks = formated_area_list
2023-01-03 18:54:42 +00:00
else :
# match keyword.
if show_debug_message :
print ( " start to match keyword: " , area_keyword_1 )
print ( " keyword and: " , area_keyword_1_and )
matched_blocks = [ ]
row_index = 0
2023-01-03 21:09:17 +00:00
for row in formated_area_list :
2023-01-03 18:54:42 +00:00
row_index + = 1
row_is_enabled = True
if row_is_enabled :
row_text = " "
try :
row_text = row . text
except Exception as exc :
print ( " get text fail " )
break
if row_text is None :
row_text = " "
if len ( row_text ) > 0 :
row_text = format_keyword_string ( row_text )
if show_debug_message :
print ( " row_text: " , row_text )
is_match_area = False
match_area_code = 0
if area_keyword_1 in row_text :
if len ( area_keyword_1_and ) == 0 :
if show_debug_message :
print ( ' keyword_and is empty, directly match. ' )
# keyword #2 is empty, direct append.
is_match_area = True
match_area_code = 2
else :
if area_keyword_1_and in row_text :
if show_debug_message :
print ( ' match keyword_and ' )
is_match_area = True
match_area_code = 3
else :
if show_debug_message :
print ( ' not match keyword_and ' )
pass
if is_match_area :
matched_blocks . append ( row )
if show_debug_message :
2023-01-04 12:02:55 +00:00
if not matched_blocks is None :
print ( " after match keyword, found count: " , len ( matched_blocks ) )
2023-01-03 18:54:42 +00:00
else :
2023-01-11 00:40:31 +00:00
is_need_refresh = True
2023-01-04 12:02:55 +00:00
if show_debug_message :
2023-01-11 00:40:31 +00:00
print ( " formated_area_list is empty. " )
2023-01-03 18:54:42 +00:00
target_area = None
if matched_blocks is not None :
if len ( matched_blocks ) > 0 :
target_row_index = 0
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
if area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
target_row_index = len ( matched_blocks ) - 1
if area_auto_select_mode == CONST_RANDOM :
target_row_index = random . randint ( 0 , len ( matched_blocks ) - 1 )
target_area = matched_blocks [ target_row_index ]
2023-02-26 08:39:37 +00:00
else :
is_need_refresh = True
if show_debug_message :
print ( " matched_blocks is empty. " )
2023-01-03 18:54:42 +00:00
if target_area is not None :
try :
if target_area . is_enabled ( ) :
target_area . click ( )
2023-01-23 13:32:47 +00:00
is_price_assign_by_bot = True
2023-01-03 18:54:42 +00:00
except Exception as exc :
print ( " click target_area link fail " )
print ( exc )
# use plan B
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , target_area )
2023-01-23 13:32:47 +00:00
is_price_assign_by_bot = True
2023-01-03 18:54:42 +00:00
except Exception as exc :
pass
2023-01-23 13:32:47 +00:00
return is_need_refresh , is_price_assign_by_bot
2023-01-03 18:54:42 +00:00
def ibon_performance ( driver , config_dict ) :
show_debug_message = True # debug.
2023-01-04 12:02:55 +00:00
show_debug_message = False # online
2023-01-03 18:54:42 +00:00
is_price_assign_by_bot = False
2023-01-11 00:40:31 +00:00
is_need_refresh = False
2023-01-03 18:54:42 +00:00
auto_fill_ticket_number = True
if auto_fill_ticket_number :
# click price row.
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 ( )
area_keyword_1_and = " "
area_keyword_2_and = " "
2023-02-26 08:39:37 +00:00
area_keyword_3_and = " "
area_keyword_4_and = " "
area_keyword_2_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " area_keyword_2_enable " ]
area_keyword_3_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " area_keyword_3_enable " ]
area_keyword_4_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " area_keyword_4_enable " ]
2023-01-03 18:54:42 +00:00
2023-01-03 21:09:17 +00:00
if show_debug_message :
print ( " area_keyword_1: " , area_keyword_1 )
#print("area_keyword_1_and:", area_keyword_1_and)
print ( " area_keyword_2: " , area_keyword_2 )
#print("area_keyword_2_and:", area_keyword_2_and)
2023-01-11 00:40:31 +00:00
is_need_refresh = False
2023-01-03 21:09:17 +00:00
if not is_price_assign_by_bot :
2023-01-11 00:40:31 +00:00
is_need_refresh , is_price_assign_by_bot = ibon_area_auto_select ( driver , area_auto_select_mode , area_keyword_1 , area_keyword_1_and )
2023-01-03 18:54:42 +00:00
2023-02-26 08:39:37 +00:00
if is_need_refresh :
if area_keyword_2_enable :
2023-01-11 00:40:31 +00:00
is_need_refresh , is_price_assign_by_bot = ibon_area_auto_select ( driver , area_auto_select_mode , area_keyword_2 , area_keyword_2_and )
2023-02-26 08:39:37 +00:00
if show_debug_message :
print ( " is_need_refresh for keyword2: " , is_need_refresh )
2023-01-03 18:54:42 +00:00
2023-02-26 08:39:37 +00:00
if is_need_refresh :
if area_keyword_3_enable :
is_need_refresh , is_price_assign_by_bot = ibon_area_auto_select ( driver , area_auto_select_mode , area_keyword_3 , area_keyword_3_and )
if show_debug_message :
print ( " is_need_refresh for keyword3: " , is_need_refresh )
if is_need_refresh :
if area_keyword_4_enable :
is_need_refresh , is_price_assign_by_bot = ibon_area_auto_select ( driver , area_auto_select_mode , area_keyword_4 , area_keyword_4_and )
if show_debug_message :
print ( " is_need_refresh for keyword4: " , is_need_refresh )
2023-01-03 18:54:42 +00:00
2023-01-11 00:40:31 +00:00
if is_need_refresh :
try :
driver . refresh ( )
except Exception as exc :
pass
2023-01-03 18:54:42 +00:00
2023-01-03 21:09:17 +00:00
return is_price_assign_by_bot
2023-01-03 18:54:42 +00:00
def ibon_purchase_button_press ( driver ) :
2023-02-26 08:39:37 +00:00
is_button_clicked = force_press_button ( driver , By . CSS_SELECTOR , ' #ticket-wrap > a.btn ' )
return is_button_clicked
2023-01-03 18:54:42 +00:00
2023-02-11 05:36:27 +00:00
def facebook_login ( driver , account , password ) :
2023-01-03 18:54:42 +00:00
ret = False
el_email = None
try :
el_email = driver . find_element ( By . CSS_SELECTOR , ' #email ' )
except Exception as exc :
pass
is_visible = False
if el_email is not None :
try :
if el_email . is_enabled ( ) :
is_visible = True
except Exception as exc :
pass
is_email_sent = False
if is_visible :
try :
inputed_text = el_email . get_attribute ( ' value ' )
if inputed_text is not None :
if len ( inputed_text ) == 0 :
el_email . send_keys ( account )
is_email_sent = True
2023-02-12 09:49:55 +00:00
else :
if inputed_text == account :
is_email_sent = True
2023-01-03 18:54:42 +00:00
except Exception as exc :
pass
el_pass = None
if is_email_sent :
try :
el_pass = driver . find_element ( By . CSS_SELECTOR , ' #pass ' )
except Exception as exc :
pass
2023-02-11 05:36:27 +00:00
is_password_sent = False
2023-01-03 18:54:42 +00:00
if el_pass is not None :
try :
if el_pass . is_enabled ( ) :
2023-02-11 05:36:27 +00:00
inputed_text = el_pass . get_attribute ( ' value ' )
if inputed_text is not None :
if len ( inputed_text ) == 0 :
el_pass . click ( )
if ( len ( password ) > 0 ) :
el_pass . send_keys ( password )
el_pass . send_keys ( Keys . ENTER )
is_password_sent = True
time . sleep ( 0.1 )
2023-01-03 18:54:42 +00:00
except Exception as exc :
pass
2023-02-11 05:36:27 +00:00
ret = is_password_sent
2023-01-03 18:54:42 +00:00
return ret
2023-02-11 05:36:27 +00:00
def kktix_login ( driver , account , password ) :
2023-01-03 18:54:42 +00:00
ret = False
el_email = None
try :
el_email = driver . find_element ( By . CSS_SELECTOR , ' #user_login ' )
except Exception as exc :
pass
is_visible = False
if el_email is not None :
try :
if el_email . is_enabled ( ) :
is_visible = True
except Exception as exc :
pass
is_email_sent = False
if is_visible :
try :
inputed_text = el_email . get_attribute ( ' value ' )
if inputed_text is not None :
if len ( inputed_text ) == 0 :
el_email . send_keys ( account )
is_email_sent = True
2023-02-12 09:49:55 +00:00
else :
if inputed_text == account :
is_email_sent = True
2023-01-03 18:54:42 +00:00
except Exception as exc :
pass
el_pass = None
if is_email_sent :
try :
el_pass = driver . find_element ( By . CSS_SELECTOR , ' #user_password ' )
except Exception as exc :
pass
2023-02-11 05:36:27 +00:00
is_password_sent = False
2023-01-03 18:54:42 +00:00
if el_pass is not None :
try :
if el_pass . is_enabled ( ) :
2023-02-11 05:36:27 +00:00
inputed_text = el_pass . get_attribute ( ' value ' )
if inputed_text is not None :
if len ( inputed_text ) == 0 :
el_pass . click ( )
if ( len ( password ) > 0 ) :
el_pass . send_keys ( password )
el_pass . send_keys ( Keys . ENTER )
is_password_sent = True
time . sleep ( 0.1 )
except Exception as exc :
pass
ret = is_password_sent
return ret
def cityline_login ( driver , account , password ) :
ret = False
el_email = None
try :
el_email = driver . find_element ( By . CSS_SELECTOR , ' input.ant-input ' )
except Exception as exc :
pass
is_visible = False
if el_email is not None :
try :
if el_email . is_enabled ( ) :
2023-01-03 18:54:42 +00:00
is_visible = True
2022-11-16 15:43:53 +00:00
except Exception as exc :
pass
2023-02-11 05:36:27 +00:00
is_email_sent = False
2022-11-16 15:43:53 +00:00
if is_visible :
try :
2023-02-11 05:36:27 +00:00
inputed_text = el_email . get_attribute ( ' value ' )
if inputed_text is not None :
if len ( inputed_text ) == 0 :
el_email . send_keys ( account )
is_email_sent = True
2023-02-12 09:49:55 +00:00
else :
if inputed_text == account :
is_email_sent = True
2023-02-11 05:36:27 +00:00
except Exception as exc :
pass
el_pass = None
if is_email_sent :
try :
el_pass = driver . find_element ( By . CSS_SELECTOR , ' input[type= " password " ] ' )
except Exception as exc :
pass
is_password_sent = False
if el_pass is not None :
try :
if el_pass . is_enabled ( ) :
inputed_text = el_pass . get_attribute ( ' value ' )
if inputed_text is not None :
if len ( inputed_text ) == 0 :
el_pass . click ( )
if ( len ( password ) > 0 ) :
el_pass . send_keys ( password )
el_pass . send_keys ( Keys . ENTER )
is_password_sent = True
time . sleep ( 0.1 )
2022-11-16 15:43:53 +00:00
except Exception as exc :
pass
2023-02-11 05:36:27 +00:00
ret = is_password_sent
2019-10-01 17:52:13 +00:00
return ret
2023-02-11 05:36:27 +00:00
def urbtix_login ( driver , account , password ) :
2023-01-18 08:40:41 +00:00
ret = False
el_email = None
try :
2023-02-11 05:36:27 +00:00
el_email = driver . find_element ( By . CSS_SELECTOR , ' input[name= " loginId " ] ' )
2023-01-18 08:40:41 +00:00
except Exception as exc :
#print("find #email fail")
#print(exc)
pass
is_visible = False
if el_email is not None :
try :
if el_email . is_enabled ( ) :
is_visible = True
except Exception as exc :
pass
is_email_sent = False
if is_visible :
try :
inputed_text = el_email . get_attribute ( ' value ' )
if inputed_text is not None :
if len ( inputed_text ) == 0 :
el_email . send_keys ( account )
is_email_sent = True
2023-02-12 09:49:55 +00:00
else :
if inputed_text == account :
is_email_sent = True
2023-01-18 08:40:41 +00:00
except Exception as exc :
pass
el_pass = None
if is_email_sent :
try :
2023-02-11 05:36:27 +00:00
el_pass = driver . find_element ( By . CSS_SELECTOR , ' input[name= " password " ] ' )
2023-01-18 08:40:41 +00:00
except Exception as exc :
pass
2023-02-11 05:36:27 +00:00
is_password_sent = False
2023-01-18 08:40:41 +00:00
if el_pass is not None :
try :
if el_pass . is_enabled ( ) :
2023-02-11 05:36:27 +00:00
inputed_text = el_pass . get_attribute ( ' value ' )
if inputed_text is not None :
if len ( inputed_text ) == 0 :
el_pass . click ( )
if ( len ( password ) > 0 ) :
el_pass . send_keys ( password )
is_password_sent = True
2023-01-18 08:40:41 +00:00
except Exception as exc :
pass
2023-02-11 05:36:27 +00:00
el_btn = None
if is_password_sent :
2023-01-18 08:40:41 +00:00
try :
2023-02-11 05:36:27 +00:00
el_btn = driver . find_element ( By . CSS_SELECTOR , ' .login-button ' )
if not el_btn is None :
el_btn . click ( )
2023-01-18 08:40:41 +00:00
except Exception as exc :
pass
return ret
2023-02-11 05:36:27 +00:00
def kham_login ( driver , account , password ) :
2023-01-18 08:40:41 +00:00
ret = False
el_email = None
try :
2023-02-11 05:36:27 +00:00
my_css_selector = ' table#blockLogin > tbody > tr > td > input[type= " text " ] '
el_email = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
2023-01-18 08:40:41 +00:00
except Exception as exc :
pass
is_visible = False
if el_email is not None :
try :
if el_email . is_enabled ( ) :
is_visible = True
except Exception as exc :
pass
is_email_sent = False
if is_visible :
try :
inputed_text = el_email . get_attribute ( ' value ' )
if inputed_text is not None :
if len ( inputed_text ) == 0 :
el_email . send_keys ( account )
is_email_sent = True
2023-02-12 09:49:55 +00:00
else :
if inputed_text == account :
is_email_sent = True
2023-01-18 08:40:41 +00:00
except Exception as exc :
pass
el_pass = None
if is_email_sent :
try :
2023-02-11 05:36:27 +00:00
my_css_selector = ' table#blockLogin > tbody > tr > td > input[type= " password " ] '
el_pass = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
2023-01-18 08:40:41 +00:00
except Exception as exc :
pass
2023-02-11 05:36:27 +00:00
is_password_sent = False
2023-01-18 08:40:41 +00:00
if el_pass is not None :
try :
if el_pass . is_enabled ( ) :
2023-02-11 05:36:27 +00:00
inputed_text = el_pass . get_attribute ( ' value ' )
if inputed_text is not None :
if len ( inputed_text ) == 0 :
el_pass . click ( )
if ( len ( password ) > 0 ) :
el_pass . send_keys ( password )
is_password_sent = True
time . sleep ( 0.1 )
2023-01-18 08:40:41 +00:00
except Exception as exc :
pass
2023-02-11 05:36:27 +00:00
el_btn = None
if is_password_sent :
2023-01-18 08:40:41 +00:00
try :
2023-02-11 05:36:27 +00:00
el_btn = driver . find_element ( By . CSS_SELECTOR , ' #ctl00_ContentPlaceHolder1_LOGIN_BTN ' )
if not el_btn is None :
el_btn . click ( )
2023-01-18 08:40:41 +00:00
except Exception as exc :
pass
2023-02-11 05:36:27 +00:00
ret = is_password_sent
2023-01-18 08:40:41 +00:00
return ret
2023-02-12 09:49:55 +00:00
def hkticketing_login ( driver , account , password ) :
ret = False
el_email = None
try :
my_css_selector = ' div#myTick2Col > div.formMod2Col > div.formModule > div.loginContentContainer > input.borInput '
el_email = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
#print("find_element exception")
#print(exc)
pass
is_visible = False
if el_email is not None :
try :
if el_email . is_enabled ( ) :
is_visible = True
else :
el_email . click ( )
except Exception as exc :
pass
else :
#print("account field is None.")
pass
is_email_sent = False
if is_visible :
try :
# PS: this is special case...
el_email . click ( )
inputed_text = el_email . get_attribute ( ' value ' )
if inputed_text is not None :
if len ( inputed_text ) == 0 :
#print("send account text:", account)
el_email . send_keys ( account )
is_email_sent = True
else :
if inputed_text == account :
is_email_sent = True
except Exception as exc :
pass
el_pass = None
if is_email_sent :
try :
my_css_selector = ' div.loginContentContainer > input[type= " password " ] '
el_pass = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
pass
is_password_sent = False
if el_pass is not None :
try :
if el_pass . is_enabled ( ) :
el_pass . click ( )
inputed_text = el_pass . get_attribute ( ' value ' )
if inputed_text is not None :
if len ( inputed_text ) == 0 :
el_pass . click ( )
if ( len ( password ) > 0 ) :
#print("send password text:", password)
el_pass . send_keys ( password )
el_pass . send_keys ( Keys . ENTER )
is_password_sent = True
time . sleep ( 0.1 )
else :
el_pass . click ( )
except Exception as exc :
pass
ret = is_password_sent
return ret
2022-11-20 07:57:16 +00:00
def check_and_play_sound_for_captcha ( config_dict ) :
play_captcha_sound = config_dict [ " advanced " ] [ " play_captcha_sound " ] [ " enable " ]
captcha_sound_filename = config_dict [ " advanced " ] [ " play_captcha_sound " ] [ " filename " ] . strip ( )
if play_captcha_sound :
app_root = get_app_root ( )
captcha_sound_filename = os . path . join ( app_root , captcha_sound_filename )
play_mp3_async ( captcha_sound_filename )
2022-11-17 18:17:19 +00:00
def play_mp3_async ( sound_filename ) :
2022-11-16 15:43:53 +00:00
import threading
2022-11-17 18:17:19 +00:00
threading . Thread ( target = play_mp3 , args = ( sound_filename , ) , daemon = True ) . start ( )
def play_mp3 ( sound_filename ) :
2022-11-16 15:43:53 +00:00
from playsound import playsound
try :
2022-11-17 18:17:19 +00:00
playsound ( sound_filename )
2022-11-16 15:43:53 +00:00
except Exception as exc :
msg = str ( exc )
print ( " play sound exeption: " , msg )
2022-11-17 18:17:19 +00:00
if platform . system ( ) == ' Windows ' :
import winsound
try :
winsound . PlaySound ( sound_filename , winsound . SND_FILENAME )
except Exception as exc2 :
pass
2022-11-16 15:43:53 +00:00
# purpose: check alert poped.
# PS: current version not enable...
def check_pop_alert ( driver ) :
is_alert_popup = False
# https://stackoverflow.com/questions/57481723/is-there-a-change-in-the-handling-of-unhandled-alert-in-chromedriver-and-chrome
2023-01-07 21:43:30 +00:00
default_close_alert_text = [ " " ]
2022-11-16 15:43:53 +00:00
if len ( default_close_alert_text ) > 0 :
try :
alert = None
if not driver is None :
2023-02-23 13:33:49 +00:00
#alert = driver.switch_to.alert
alert = WebDriverWait ( driver , 0.2 ) . until ( EC . alert_is_present ( ) )
2022-11-16 15:43:53 +00:00
if not alert is None :
2023-01-07 21:43:30 +00:00
alert_text = str ( alert . text )
if not alert_text is None :
2022-11-16 15:43:53 +00:00
is_match_auto_close_text = False
for txt in default_close_alert_text :
if len ( txt ) > 0 :
if txt in alert . text :
is_match_auto_close_text = True
2023-01-07 21:43:30 +00:00
else :
is_match_auto_close_text = True
#print("is_match_auto_close_text:", is_match_auto_close_text)
2022-11-16 15:43:53 +00:00
#print("alert3 text:", alert.text)
if is_match_auto_close_text :
alert . accept ( )
2023-02-23 13:33:49 +00:00
print ( " alert3 accepted " )
2022-11-16 15:43:53 +00:00
is_alert_popup = True
else :
print ( " alert3 not detected " )
except NoAlertPresentException as exc1 :
#logger.error('NoAlertPresentException for alert')
pass
except NoSuchWindowException :
2023-01-07 21:43:30 +00:00
pass
2022-11-16 15:43:53 +00:00
except Exception as exc :
2023-02-23 13:33:49 +00:00
#logger.error('Exception2 for alert')
#logger.error(exc, exc_info=True)
pass
2022-11-16 15:43:53 +00:00
return is_alert_popup
2019-10-01 17:52:13 +00:00
2022-11-20 07:57:16 +00:00
def list_all_cookies ( driver ) :
all_cookies = driver . get_cookies ( ) ;
cookies_dict = { }
for cookie in all_cookies :
cookies_dict [ cookie [ ' name ' ] ] = cookie [ ' value ' ]
print ( cookies_dict )
2023-02-22 16:05:44 +00:00
def tixcraft_main ( driver , url , config_dict , tixcraft_dict , ocr , Captcha_Browser ) :
2023-02-23 13:33:49 +00:00
tixcraft_home_close_window ( driver )
2023-01-25 15:36:14 +00:00
home_url_list = [ ' https://tixcraft.com/ ' , ' https://www.tixcraft.com/ ' , ' https://indievox.com/ ' , ' https://www.indievox.com/ ' , ' https://teamear.tixcraft.com/activity ' ]
2023-01-13 19:01:47 +00:00
for each_url in home_url_list :
if each_url == url :
2023-01-14 05:26:42 +00:00
if config_dict [ " ocr_captcha " ] [ " enable " ] :
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 )
break
2023-01-03 18:54:42 +00:00
2023-01-11 13:58:55 +00:00
if " /activity/detail/ " in url :
is_redirected = tixcraft_redirect ( driver , url )
2023-01-03 18:54:42 +00:00
is_date_selected = False
2023-01-11 13:58:55 +00:00
if " /activity/game/ " in url :
date_auto_select_enable = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " enable " ]
if date_auto_select_enable :
2023-02-09 16:22:13 +00:00
domain_name = url . split ( ' / ' ) [ 2 ]
is_date_selected = tixcraft_date_auto_select ( driver , url , config_dict , domain_name )
2023-01-03 18:54:42 +00:00
# choose area
2023-01-11 13:58:55 +00:00
if ' /ticket/area/ ' in url :
area_auto_select_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " enable " ]
if area_auto_select_enable :
tixcraft_area_auto_select ( driver , url , config_dict )
2023-01-03 18:54:42 +00:00
if ' /ticket/verify/ ' in url :
presale_code = config_dict [ " tixcraft " ] [ " presale_code " ]
2023-02-17 16:54:16 +00:00
presale_code_delimiter = config_dict [ " tixcraft " ] [ " presale_code_delimiter " ]
2023-02-22 16:05:44 +00:00
tixcraft_dict [ " answer_index " ] = tixcraft_verify ( driver , presale_code , presale_code_delimiter , tixcraft_dict [ " answer_index " ] )
2023-02-17 16:54:16 +00:00
else :
2023-02-22 16:05:44 +00:00
tixcraft_dict [ " answer_index " ] = - 1
2023-01-03 18:54:42 +00:00
# main app, to select ticket number.
if ' /ticket/ticket/ ' in url :
2023-02-22 16:05:44 +00:00
if not tixcraft_dict [ " is_verifyCode_editing " ] :
domain_name = url . split ( ' / ' ) [ 2 ]
tixcraft_dict [ " is_verifyCode_editing " ] = tixcraft_ticket_main ( driver , config_dict , ocr , Captcha_Browser , domain_name )
else :
tixcraft_dict [ " is_verifyCode_editing " ] = False
if ' /ticket/checkout ' in url :
2023-02-22 23:46:05 +00:00
if config_dict [ " advanced " ] [ " headless " ] :
if not tixcraft_dict [ " is_popup_checkout " ] :
domain_name = url . split ( ' / ' ) [ 2 ]
checkout_url = " https:// %s /ticket/checkout " % ( domain_name )
print ( " 搶票成功, 請前往該帳號訂單查看: %s " % ( checkout_url ) )
webbrowser . open_new ( checkout_url )
tixcraft_dict [ " is_popup_checkout " ] = True
2023-01-03 18:54:42 +00:00
else :
2023-02-22 16:05:44 +00:00
tixcraft_dict [ " is_popup_checkout " ] = False
2023-01-03 18:54:42 +00:00
2023-02-22 16:05:44 +00:00
return tixcraft_dict
2023-01-03 18:54:42 +00:00
2023-02-22 16:05:44 +00:00
def kktix_main ( driver , url , config_dict , kktix_dict ) :
2023-01-03 18:54:42 +00:00
auto_press_next_step_button = config_dict [ " kktix " ] [ " auto_press_next_step_button " ]
kktix_account = config_dict [ " advanced " ] [ " kktix_account " ]
is_url_contain_sign_in = False
# fix https://kktix.com/users/sign_in?back_to=https://kktix.com/events/xxxx and registerStatus: SOLD_OUT cause page refresh.
if ' /users/sign_in? ' in url :
if len ( kktix_account ) > 4 :
2023-02-11 05:36:27 +00:00
kktix_login ( driver , kktix_account , decryptMe ( config_dict [ " advanced " ] [ " kktix_password " ] ) )
2023-01-03 18:54:42 +00:00
is_url_contain_sign_in = True
if not is_url_contain_sign_in :
if ' /registrations/new ' in url :
2023-02-22 16:05:44 +00:00
kktix_dict [ " answer_index " ] , kktix_dict [ " kktix_register_status_last " ] = kktix_reg_new ( driver , url , kktix_dict [ " answer_index " ] , kktix_dict [ " kktix_register_status_last " ] , config_dict )
2023-01-03 18:54:42 +00:00
else :
is_event_page = False
if ' /events/ ' in url :
# ex: https://xxx.kktix.cc/events/xxx-copy-1
if len ( url . split ( ' / ' ) ) < = 5 :
is_event_page = True
if is_event_page :
if auto_press_next_step_button :
# pass switch check.
#print("should press next here.")
kktix_events_press_next_button ( driver )
2023-02-22 16:05:44 +00:00
kktix_dict [ " answer_index " ] = - 1
kktix_dict [ " kktix_register_status_last " ] = None
2023-02-22 23:46:05 +00:00
if ' /events/ ' in url and ' /registrations/ ' in url and " - " in url :
if config_dict [ " advanced " ] [ " headless " ] :
if not kktix_dict [ " is_popup_checkout " ] :
is_event_page = False
if len ( url . split ( ' / ' ) ) == 8 :
is_event_page = True
if is_event_page :
confirm_clicked = kktix_confirm_order_button ( driver )
if confirm_clicked :
domain_name = url . split ( ' / ' ) [ 2 ]
checkout_url = " https:// %s /account/orders " % ( domain_name )
print ( " 搶票成功, 請前往該帳號訂單查看: %s " % ( checkout_url ) )
webbrowser . open_new ( checkout_url )
tixcraft_dict [ " is_popup_checkout " ] = True
else :
kktix_dict [ " is_popup_checkout " ] = False
2023-02-22 16:05:44 +00:00
return kktix_dict
2023-01-03 18:54:42 +00:00
def famiticket_main ( driver , url , config_dict ) :
2023-01-04 12:02:55 +00:00
try :
window_handles_count = len ( driver . window_handles )
if window_handles_count > 1 :
driver . switch_to . window ( driver . window_handles [ 0 ] )
driver . close ( )
driver . switch_to . window ( driver . window_handles [ 0 ] )
except Exception as excSwithFail :
pass
2023-01-03 18:54:42 +00:00
if ' /Home/Activity/Info/ ' in url :
fami_activity ( driver )
if ' /Sales/Home/Index/ ' in url :
fami_home ( driver , url , config_dict )
2023-01-18 08:40:41 +00:00
def urbtix_performance_confirm_dialog_popup ( driver ) :
ret = False
el_div = None
try :
el_div = driver . find_element ( By . CSS_SELECTOR , ' div.notification-confirm-btn > div.button-text ' )
except Exception as exc :
#print("find modal-dialog fail")
#print(exc)
pass
if el_div is not None :
print ( " bingo, found notification-confirm-btn " )
is_visible = False
try :
if el_div . is_enabled ( ) :
if el_div . is_displayed ( ) :
is_visible = True
except Exception as exc :
pass
if is_visible :
try :
el_div . click ( )
ret = True
except Exception as exc :
# use plan B
'''
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , el_div )
ret = True
except Exception as exc :
pass
'''
pass
if ret :
time . sleep ( 0.4 )
2023-02-19 04:16:31 +00:00
2023-01-18 08:40:41 +00:00
return ret
2023-02-07 16:42:04 +00:00
2023-01-03 18:54:42 +00:00
def urbtix_main ( driver , url , config_dict ) :
# http://msg.urbtix.hk
2023-01-11 13:58:55 +00:00
waiting_for_access_url = [ ' /session/landing-timer/ ' , ' msg.urbtix.hk ' , ' busy.urbtix.hk ' ]
2023-01-11 00:40:31 +00:00
for waiting_url in waiting_for_access_url :
if waiting_url in url :
# delay to avoid ip block.
2023-01-11 17:41:53 +00:00
time . sleep ( 1.0 )
2023-01-11 00:40:31 +00:00
try :
driver . get ( ' https://www.urbtix.hk/ ' )
except Exception as exec1 :
pass
2023-01-03 18:54:42 +00:00
pass
if ' /logout? ' in url :
try :
driver . get ( ' https://www.urbtix.hk/ ' )
except Exception as exec1 :
pass
pass
2023-01-18 08:40:41 +00:00
if ' .hk/member-login ' in url :
urbtix_account = config_dict [ " advanced " ] [ " urbtix_account " ]
if len ( urbtix_account ) > 2 :
2023-02-11 05:36:27 +00:00
urbtix_login ( driver , urbtix_account , decryptMe ( config_dict [ " advanced " ] [ " urbtix_password " ] ) )
2023-01-18 08:40:41 +00:00
2023-01-03 18:54:42 +00:00
# https://www.urbtix.hk/event-detail/00000/
if ' /event-detail/ ' in url :
date_auto_select_enable = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " enable " ]
if date_auto_select_enable :
is_event_page = False
if len ( url . split ( ' / ' ) ) < = 6 :
is_event_page = True
urbtix_purchase_ticket ( driver , config_dict )
# https://www.urbtix.hk/performance-detail/?eventId=00000&performanceId=00000
2023-01-04 12:02:55 +00:00
is_performace_page = False
2023-01-03 18:54:42 +00:00
if ' /performance-detail/?eventId= ' in url :
2023-01-04 12:02:55 +00:00
is_performace_page = True
if ' performance-detail?eventId ' in url :
is_performace_page = True
if is_performace_page :
2023-01-03 18:54:42 +00:00
area_auto_select_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " enable " ]
if area_auto_select_enable :
2023-01-18 08:40:41 +00:00
is_confirm_dialog_popup = urbtix_performance_confirm_dialog_popup ( driver )
if is_confirm_dialog_popup :
print ( " is_confirm_dialog_popup! auto press confirm... " )
else :
urbtix_performance ( driver , config_dict )
2023-01-03 18:54:42 +00:00
2023-01-04 12:02:55 +00:00
def check_modal_dialog_popup ( driver ) :
ret = False
el_div = None
try :
el_div = driver . find_element ( By . CSS_SELECTOR , ' div.modal-dialog > div.modal-content ' )
except Exception as exc :
#print("find modal-dialog fail")
#print(exc)
pass
if el_div is not None :
#print("bingo, found modal-dialog")
try :
if el_div . is_enabled ( ) :
if el_div . is_displayed ( ) :
ret = True
except Exception as exc :
pass
return ret
2023-02-06 16:19:20 +00:00
def cityline_shows_goto_cta ( driver ) :
ret = False
el_btn = None
try :
el_btn = driver . find_element ( By . CSS_SELECTOR , ' .btn_cta ' )
except Exception as exc :
#print("find next button fail...")
#print(exc)
pass
if el_btn is not None :
#print("bingo, found next button, start to press")
try :
if el_btn . is_enabled ( ) and el_btn . is_displayed ( ) :
el_btn . click ( )
ret = True
except Exception as exc :
print ( " click next button fail... " )
print ( exc )
return ret
2023-02-22 12:38:20 +00:00
def cityline_home_close_window ( driver ) :
show_debug_message = True # debug.
show_debug_message = False # online
close_styles_list = [ ' .anticon-close ' , ' .cookieWrapper_closeBtn ' ]
for close_styles in close_styles_list :
close_all_alert_btns = None
try :
close_all_alert_btns = driver . find_elements ( By . CSS_SELECTOR , close_styles )
except Exception as exc :
print ( " find close button fail " )
if close_all_alert_btns is not None :
if show_debug_message :
print ( ' all close button count: ' , len ( close_all_alert_btns ) )
for alert_btn in close_all_alert_btns :
is_visible = False
try :
if alert_btn . is_enabled ( ) and alert_btn . is_displayed ( ) :
is_visible = True
except Exception as exc :
pass
if is_visible :
try :
alert_btn . click ( )
except Exception as exc :
print ( " try to click close button fail, force click by js. " )
try :
driver . execute_script ( " arguments[0].click(); " , alert_btn )
except Exception as exc :
pass
2023-01-03 18:54:42 +00:00
def cityline_main ( driver , url , config_dict ) :
2023-02-22 12:38:20 +00:00
#https://www.cityline.com/Events.html
if ' cityline.com/Events.html ' in url :
cityline_home_close_window ( driver )
2023-01-03 18:54:42 +00:00
# https://www.cityline.com/Login.html?targetUrl=https%3A%2F%2F
# ignore url redirect
if ' /Login.html ' in url :
2023-01-18 08:40:41 +00:00
cityline_account = config_dict [ " advanced " ] [ " cityline_account " ]
if len ( cityline_account ) > 2 :
2023-02-11 05:36:27 +00:00
cityline_login ( driver , cityline_account , decryptMe ( config_dict [ " advanced " ] [ " cityline_password " ] ) )
2023-01-03 18:54:42 +00:00
return
2023-02-22 12:38:20 +00:00
# https://msg.cityline.com/ https://event.cityline.com/
if ' msg.cityline.com ' or ' event.cityline.com ' in url :
2023-01-05 06:44:45 +00:00
try :
2023-02-22 12:38:20 +00:00
WebDriverWait ( driver , 10 , poll_frequency = 0.01 ) . until (
EC . element_to_be_clickable ( ( By . XPATH , " //button[@id= ' btn-retry-en-1 ' ] " ) )
)
2023-01-05 06:44:45 +00:00
driver . execute_script ( " goEvent(); " )
except Exception as exec1 :
pass
pass
2023-01-03 18:54:42 +00:00
try :
window_handles_count = len ( driver . window_handles )
if window_handles_count > 1 :
driver . switch_to . window ( driver . window_handles [ 0 ] )
driver . close ( )
driver . switch_to . window ( driver . window_handles [ 0 ] )
2023-02-06 16:19:20 +00:00
time . sleep ( 0.2 )
2023-01-03 18:54:42 +00:00
except Exception as excSwithFail :
pass
if ' /eventDetail? ' in url :
2023-01-04 12:02:55 +00:00
is_modal_dialog_popup = check_modal_dialog_popup ( driver )
if is_modal_dialog_popup :
print ( " is_modal_dialog_popup! skip... " )
else :
date_auto_select_enable = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " enable " ]
if date_auto_select_enable :
cityline_purchase_button_press ( driver , config_dict )
2023-01-03 18:54:42 +00:00
if ' /performance? ' in url :
2023-01-04 12:02:55 +00:00
is_modal_dialog_popup = check_modal_dialog_popup ( driver )
if is_modal_dialog_popup :
print ( " is_modal_dialog_popup! skip... " )
else :
area_auto_select_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " enable " ]
if area_auto_select_enable :
cityline_performance ( driver , config_dict )
2023-01-03 18:54:42 +00:00
2023-02-06 16:19:20 +00:00
if ' .htm ' in url :
if not ' /slim_end.htm ' in url :
if len ( url . split ( ' / ' ) ) > = 5 :
cityline_shows_goto_cta ( driver )
2023-02-12 09:49:55 +00:00
def ibon_verification_question ( driver , answer_index , config_dict ) :
show_debug_message = True # debug.
show_debug_message = False # online
user_guess_string = config_dict [ " kktix " ] [ " user_guess_string " ]
# part 1: check div.
question_div = None
try :
question_div = driver . find_element ( By . CSS_SELECTOR , ' ' )
except Exception as exc :
pass
#print("find input fail:", exc)
#captcha_text_div_text
2023-02-23 13:33:49 +00:00
captcha_text_div_text = None
2023-02-12 09:49:55 +00:00
captcha_password_inputbox = None
try :
captcha_password_inputbox = driver . find_element ( By . CSS_SELECTOR , ' ' )
except Exception as exc :
pass
if not captcha_password_inputbox is None :
inferred_answer_string = None
if len ( user_guess_string ) > 0 :
inferred_answer_string = user_guess_string
else :
2023-02-23 13:33:49 +00:00
if not captcha_text_div_text is None :
inferred_answer_string , answer_list = get_answer_list_from_question_string ( None , captcha_text_div_text )
2023-02-12 09:49:55 +00:00
return answer_index
2023-02-26 08:39:37 +00:00
def ibon_ticket_agree ( driver ) :
# check agree
form_checkbox = None
try :
form_checkbox = driver . find_element ( By . ID , ' agreen ' )
except Exception as exc :
print ( " find #agreen fail " )
is_finish_checkbox_click = False
if form_checkbox is not None :
try :
# TODO: check the status: checked.
if form_checkbox . is_enabled ( ) :
if not form_checkbox . is_selected ( ) :
form_checkbox . click ( )
is_finish_checkbox_click = True
except Exception as exc :
print ( " click #agreen fail " )
#pass
try :
print ( " use plan_b to check #agreen. " )
driver . execute_script ( " $( \" input[type= ' checkbox ' ] \" ).prop( ' checked ' , true); " )
is_finish_checkbox_click = True
except Exception as exc :
print ( " javascript check #agreen fail " )
print ( exc )
pass
return is_finish_checkbox_click
def ibon_check_sold_out ( driver ) :
is_sold_out = False
# check agree
div_ticket_info = None
try :
div_ticket_info = driver . find_element ( By . CSS_SELECTOR , ' #ticket-info ' )
except Exception as exc :
print ( " find #ticket-info fail " )
if div_ticket_info is not None :
try :
div_ticket_info_text = div_ticket_info . text
if not div_ticket_info_text is None :
if ' 已售完 ' in div_ticket_info_text :
is_sold_out = True
except Exception as exc :
pass
return is_sold_out
def ibon_auto_signup ( driver ) :
is_button_clicked = force_press_button ( driver , By . CSS_SELECTOR , ' .btn.btn-signup ' )
return is_button_clicked
2023-02-23 13:33:49 +00:00
def ibon_main ( driver , url , config_dict , ibon_dict ) :
2023-02-26 08:39:37 +00:00
# https://tour.ibon.com.tw/event/e23010000300mxu
if ' tour ' in url and ' /event/ ' in url :
is_event_page = False
if len ( url . split ( ' / ' ) ) == 5 :
is_event_page = True
if is_event_page :
ibon_auto_signup ( driver )
2023-01-03 18:54:42 +00:00
#https://ticket.ibon.com.tw/ActivityInfo/Details/0000?pattern=entertainment
if ' /ActivityInfo/Details/ ' in url :
is_event_page = False
2023-02-26 08:39:37 +00:00
if len ( url . split ( ' / ' ) ) == 6 :
2023-01-03 18:54:42 +00:00
is_event_page = True
if is_event_page :
date_auto_select_enable = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " enable " ]
if date_auto_select_enable :
ibon_activity_info ( driver , config_dict )
2023-02-19 04:16:31 +00:00
2023-02-12 09:49:55 +00:00
# validation question url:
# https://orders.ibon.com.tw/application/UTK02/UTK0201_0.aspx?rn=1180872370&PERFORMANCE_ID=B04M7XZT&PRODUCT_ID=B04KS88E&SHOW_PLACE_MAP=True
if ' /application/UTK02/ ' in url and ' .aspx?rn= ' in url :
#PS: not sure, use 'kktix' block or 'tixcraft' block for this feature.
#auto_guess_options = config_dict["kktix"]["auto_guess_options"]
auto_guess_options = True
if auto_guess_options :
2023-02-22 16:05:44 +00:00
#ibon_dict["answer_index"] = ibon_verification_question(driver, ibon_dict["answer_index"], config_dict)
2023-02-12 09:49:55 +00:00
pass
else :
2023-02-22 16:05:44 +00:00
ibon_dict [ " answer_index " ] = - 1
2023-01-03 18:54:42 +00:00
# https://orders.ibon.com.tw/application/UTK02/UTK0201_000.aspx?PERFORMANCE_ID=0000
if ' /application/UTK02/ ' in url and ' .aspx?PERFORMANCE_ID= ' in url :
is_event_page = False
2023-02-26 08:39:37 +00:00
if len ( url . split ( ' / ' ) ) == 6 :
2023-01-03 18:54:42 +00:00
is_event_page = True
if is_event_page :
area_auto_select_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " enable " ]
if area_auto_select_enable :
if ' PERFORMANCE_PRICE_AREA_ID= ' in url :
# step 2: assign ticket number.
ticket_number = str ( config_dict [ " ticket_number " ] )
is_ticket_number_assigned = ibon_ticket_number_auto_select ( driver , ticket_number )
if is_ticket_number_assigned :
2023-01-03 21:09:17 +00:00
click_ret = ibon_purchase_button_press ( driver )
2023-02-26 08:39:37 +00:00
else :
is_sold_out = ibon_check_sold_out ( driver )
if is_sold_out :
#is_button_clicked = force_press_button(driver, By.CSS_SELECTOR, 'a.btn.btn-primary')
driver . back ( )
driver . refresh ( )
2023-01-03 18:54:42 +00:00
else :
# step 1: select area.
ibon_performance ( driver , config_dict )
2023-02-26 08:39:37 +00:00
#https://orders.ibon.com.tw/application/UTK02/UTK0206_.aspx
if ' orders.ibon.com.tw/application/UTK02/UTK020 ' in url and ' .aspx ' in url :
is_event_page = False
if len ( url . split ( ' / ' ) ) == 6 :
is_event_page = True
if is_event_page :
auto_check_agree = config_dict [ " auto_check_agree " ]
if auto_check_agree :
is_finish_checkbox_click = False
for i in range ( 3 ) :
is_finish_checkbox_click = ibon_ticket_agree ( driver )
if is_finish_checkbox_click :
break
if is_finish_checkbox_click :
is_button_clicked = force_press_button ( driver , By . CSS_SELECTOR , ' a.btn.btn-pink.continue ' )
2023-02-22 16:05:44 +00:00
return ibon_dict
2023-02-12 09:49:55 +00:00
2023-01-23 13:32:47 +00:00
def hkticketing_home ( driver ) :
show_debug_message = True # debug.
show_debug_message = False # online
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
is_hotshow_popup = False
2023-01-07 21:43:30 +00:00
2023-01-23 13:32:47 +00:00
body_iframe = None
2023-01-11 14:26:49 +00:00
try :
2023-01-23 13:32:47 +00:00
body_iframe_list = driver . find_elements ( By . CSS_SELECTOR , ' body > iframe ' )
2023-01-11 14:26:49 +00:00
except Exception as exc :
2023-01-23 13:32:47 +00:00
if show_debug_message :
print ( " find body_iframe fail " )
2023-01-11 14:26:49 +00:00
pass
2023-01-11 13:58:55 +00:00
2023-01-23 13:32:47 +00:00
hotshow_btn = None
if not body_iframe_list is None :
if show_debug_message :
print ( " iframe count: " , len ( body_iframe_list ) )
for each_iframe in body_iframe_list :
try :
driver . switch_to . frame ( each_iframe )
hotshow_btn = driver . find_element ( By . CSS_SELECTOR , ' div.hotshow > a.btn ' )
if hotshow_btn is not None :
if hotshow_btn . is_enabled ( ) and hotshow_btn . is_displayed ( ) :
is_hotshow_popup = True
driver . switch_to . default_content ( )
except Exception as exc :
if show_debug_message :
print ( " find hotshow btn fail: " , exc )
driver . switch_to . default_content ( )
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
if show_debug_message :
print ( " is_hotshow_popup " , is_hotshow_popup )
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
accept_all_cookies_btn = None
if not is_hotshow_popup :
try :
accept_all_cookies_btn = driver . find_element ( By . ID , ' closepolicy_new ' )
except Exception as exc :
if show_debug_message :
print ( " find closepolicy_new fail " )
pass
else :
print ( " reCaptcha popup, do nothing. " )
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
if accept_all_cookies_btn is not None :
is_visible = False
2019-10-01 17:52:13 +00:00
try :
2023-01-23 13:32:47 +00:00
if accept_all_cookies_btn . is_enabled ( ) and accept_all_cookies_btn . is_displayed ( ) :
is_visible = True
except Exception as exc :
pass
if is_visible :
if show_debug_message :
print ( " closepolicy_new visible. start to press. " )
2019-10-01 17:52:13 +00:00
try :
2023-01-23 13:32:47 +00:00
accept_all_cookies_btn . click ( )
except Exception as exc :
print ( " try to click closepolicy_new fail " )
2019-10-01 17:52:13 +00:00
try :
2023-01-23 13:32:47 +00:00
driver . execute_script ( " arguments[0].click(); " , accept_all_cookies_btn )
2022-11-06 09:10:35 +00:00
except Exception as exc :
2019-10-01 17:52:13 +00:00
pass
2023-01-23 13:32:47 +00:00
else :
if show_debug_message :
print ( " closepolicy_new invisible. " )
2019-12-18 03:45:48 +00:00
2023-01-23 13:32:47 +00:00
def hkticketing_date_auto_select ( driver , auto_select_mode , date_keyword , auto_reload_coming_soon_page_enable ) :
show_debug_message = True # debug.
show_debug_message = False # online
2022-11-21 19:01:04 +00:00
2023-01-23 13:32:47 +00:00
ret = False
matched_blocks = None
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
# clean stop word.
date_keyword = format_keyword_string ( date_keyword )
date_keyword_and = " "
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
form_select = None
try :
form_select = driver . find_element ( By . CSS_SELECTOR , ' #p ' )
except Exception as exc :
print ( " find select fail " )
pass
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
select_obj = None
if form_select is not None :
is_visible = False
try :
if form_select . is_enabled ( ) :
is_visible = True
except Exception as exc :
2019-10-01 17:52:13 +00:00
pass
2023-01-23 13:32:47 +00:00
if is_visible :
try :
select_obj = Select ( form_select )
except Exception as exc :
pass
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
is_date_assigned = False
if not select_obj is None :
row_text = None
try :
row_text = select_obj . first_selected_option . text
except Exception as exc :
pass
if not row_text is None :
if len ( row_text ) > 8 :
if ' 20 ' in row_text :
# ticket assign.
is_date_assigned = True
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
if show_debug_message :
print ( " is_date_assigned: " , is_date_assigned )
2022-02-18 18:53:55 +00:00
2023-01-29 18:14:55 +00:00
#PS: some blocks are generate by ajax, not appear at first time.
formated_area_list = None
2023-01-23 13:32:47 +00:00
if not is_date_assigned :
area_list = None
try :
my_css_selector = " #p > option "
area_list = driver . find_elements ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
print ( " find #p options date list fail " )
print ( exc )
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
if area_list is not None :
area_list_count = len ( area_list )
if show_debug_message :
print ( " date_list_count: " , area_list_count )
2019-10-27 04:33:06 +00:00
2023-01-23 13:32:47 +00:00
if area_list_count > 0 :
formated_area_list = [ ]
2020-07-25 20:35:54 +00:00
2023-01-23 13:32:47 +00:00
# filter list.
row_index = 0
for row in area_list :
row_index + = 1
row_is_enabled = False
option_value_string = None
try :
if row . is_enabled ( ) :
option_value_string = str ( row . get_attribute ( ' value ' ) )
if len ( option_value_string ) > 4 :
row_is_enabled = True
# alway disable.
option_text_string = str ( row . text )
if ' Exhausted ' in option_text_string :
row_is_enabled = False
if ' 配售完畢 ' in option_text_string :
row_is_enabled = False
if ' 配售完毕 ' in option_text_string :
row_is_enabled = False
if ' No Longer On Sale ' in option_text_string :
row_is_enabled = False
if ' 已停止發售 ' in option_text_string :
row_is_enabled = False
if ' 已停止发售 ' in option_text_string :
row_is_enabled = False
2020-07-25 20:35:54 +00:00
2023-01-23 13:32:47 +00:00
except Exception as exc :
if show_debug_message :
print ( exc )
pass
2022-01-12 17:14:27 +00:00
2023-01-23 13:32:47 +00:00
if row_is_enabled :
formated_area_list . append ( row )
2019-10-01 17:52:13 +00:00
2023-01-23 20:36:06 +00:00
if formated_area_list is not None :
area_list_count = len ( formated_area_list )
if show_debug_message :
print ( " formated_area_list count: " , area_list_count )
if area_list_count > 0 :
2023-01-23 13:32:47 +00:00
if len ( date_keyword ) == 0 :
matched_blocks = formated_area_list
else :
# match keyword.
if show_debug_message :
print ( " start to match keyword: " , date_keyword )
matched_blocks = [ ]
row_index = 0
for row in formated_area_list :
row_index + = 1
row_is_enabled = True
if row_is_enabled :
row_text = " "
try :
row_text = row . text
except Exception as exc :
print ( " get text fail " )
break
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
if row_text is None :
row_text = " "
2019-10-01 17:52:13 +00:00
2023-01-23 13:32:47 +00:00
if len ( row_text ) > 0 :
row_text = format_keyword_string ( row_text )
if show_debug_message :
print ( " row_text: " , row_text )
2022-12-22 17:17:37 +00:00
2023-01-23 13:32:47 +00:00
is_match_area = False
match_area_code = 0
if date_keyword in row_text :
if len ( date_keyword_and ) == 0 :
if show_debug_message :
print ( ' keyword_and # is empty, directly match. ' )
# keyword #2 is empty, direct append.
is_match_area = True
match_area_code = 2
else :
if date_keyword_and in row_text :
if show_debug_message :
print ( ' match keyword_and ' )
is_match_area = True
match_area_code = 3
else :
if show_debug_message :
print ( ' not match keyword_and ' )
pass
if is_match_area :
matched_blocks . append ( row )
if show_debug_message :
if not matched_blocks is None :
print ( " after match keyword, found count: " , len ( matched_blocks ) )
else :
print ( " not found date-time-position " )
pass
else :
print ( " date date-time-position is None " )
pass
target_area = None
if matched_blocks is not None :
if len ( matched_blocks ) > 0 :
target_row_index = 0
if auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
if auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
target_row_index = len ( matched_blocks ) - 1
if auto_select_mode == CONST_RANDOM :
target_row_index = random . randint ( 0 , len ( matched_blocks ) - 1 )
target_area = matched_blocks [ target_row_index ]
if target_area is not None :
try :
if target_area . is_enabled ( ) :
target_area . click ( )
is_date_assigned = True
except Exception as exc :
print ( " click target_area link fail " )
print ( exc )
# use plan B
2023-02-05 14:10:57 +00:00
'''
2023-01-23 13:32:47 +00:00
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , target_area )
is_date_assigned = True
except Exception as exc :
pass
2023-02-05 14:10:57 +00:00
'''
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
# alway, auto submit
2023-01-29 18:14:55 +00:00
el_btn = None
try :
my_css_selector = " #buyButton > input "
el_btn = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
pass
if el_btn is not None :
2023-01-23 13:32:47 +00:00
try :
2023-01-29 18:14:55 +00:00
if el_btn . is_enabled ( ) and el_btn . is_displayed ( ) :
el_btn . click ( )
print ( " buy button pressed. " )
ret = True
2023-01-23 13:32:47 +00:00
except Exception as exc :
2023-01-29 18:14:55 +00:00
# use plan B
2023-02-05 14:10:57 +00:00
'''
2023-01-23 13:32:47 +00:00
try :
2023-01-29 18:14:55 +00:00
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , el_btn )
ret = True
2023-01-23 13:32:47 +00:00
except Exception as exc :
2023-01-29 18:14:55 +00:00
pass
2023-02-05 14:10:57 +00:00
'''
2023-01-29 18:14:55 +00:00
else :
if auto_reload_coming_soon_page_enable :
# auto refresh for date list page.
is_need_refresh = True
if is_date_assigned :
# if select box assign.
is_need_refresh = False
else :
if not formated_area_list is None :
if len ( formated_area_list ) > 0 :
# option waiting to assign at next loop.
is_need_refresh = False
if is_need_refresh :
2023-01-23 13:32:47 +00:00
try :
2023-01-29 18:14:55 +00:00
driver . refresh ( )
time . sleep ( 0.3 )
2023-01-23 13:32:47 +00:00
except Exception as exc :
pass
return ret
def hkticketing_show ( driver , config_dict ) :
show_debug_message = True # debug.
show_debug_message = False # online
date_auto_select_mode = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " mode " ]
date_keyword = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " date_keyword " ] . strip ( )
auto_reload_coming_soon_page_enable = config_dict [ " tixcraft " ] [ " auto_reload_coming_soon_page " ]
if show_debug_message :
print ( " date_keyword: " , date_keyword )
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 )
return is_date_assign_by_bot
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 = False # online
is_price_assign_by_bot = False
is_need_refresh = False
matched_blocks = None
# clean stop word.
area_keyword_1 = format_keyword_string ( area_keyword_1 )
area_keyword_1_and = format_keyword_string ( area_keyword_1_and )
area_list = None
try :
my_css_selector = " #ticketSelectorContainer > ul > li "
area_list = driver . find_elements ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
print ( " find #ticket-price-tbl date list fail " )
print ( exc )
formated_area_list = None
if area_list is not None :
area_list_count = len ( area_list )
if show_debug_message :
print ( " area_list_count: " , area_list_count )
if area_list_count > 0 :
formated_area_list = [ ]
# filter list.
row_index = 0
for row in area_list :
row_index + = 1
row_is_enabled = True
try :
button_class_string = str ( row . get_attribute ( ' class ' ) )
if len ( button_class_string ) > 1 :
if ' disabled ' in button_class_string :
row_is_enabled = False
if ' unavailable ' in button_class_string :
row_is_enabled = False
if ' selected ' in button_class_string :
# someone is selected. skip this process.
is_price_assign_by_bot = True
break
except Exception as exc :
pass
if row_is_enabled :
formated_area_list . append ( row )
else :
if show_debug_message :
print ( " area_list_count is empty. " )
pass
else :
if show_debug_message :
print ( " area_list_count is None. " )
pass
if is_price_assign_by_bot :
formated_area_list = None
if formated_area_list is not None :
area_list_count = len ( formated_area_list )
if show_debug_message :
print ( " formated_area_list count: " , area_list_count )
if area_list_count > 0 :
if len ( area_keyword_1 ) == 0 :
matched_blocks = formated_area_list
else :
# match keyword.
if show_debug_message :
print ( " start to match keyword: " , area_keyword_1 )
print ( " keyword and: " , area_keyword_1_and )
matched_blocks = [ ]
row_index = 0
for row in formated_area_list :
row_index + = 1
row_is_enabled = True
if row_is_enabled :
row_text = " "
try :
row_text = row . text
except Exception as exc :
print ( " get text fail " )
break
if row_text is None :
row_text = " "
if len ( row_text ) > 0 :
row_text = format_keyword_string ( row_text )
if show_debug_message :
print ( " row_text: " , row_text )
is_match_area = False
match_area_code = 0
if area_keyword_1 in row_text :
if len ( area_keyword_1_and ) == 0 :
if show_debug_message :
print ( ' keyword_and is empty, directly match. ' )
# keyword #2 is empty, direct append.
is_match_area = True
match_area_code = 2
else :
if area_keyword_1_and in row_text :
if show_debug_message :
print ( ' match keyword_and ' )
is_match_area = True
match_area_code = 3
else :
if show_debug_message :
print ( ' not match keyword_and ' )
pass
if is_match_area :
matched_blocks . append ( row )
if show_debug_message :
if not matched_blocks is None :
print ( " after match keyword, found count: " , len ( matched_blocks ) )
else :
is_need_refresh = True
if show_debug_message :
print ( " formated_area_list is empty. " )
target_area = None
if matched_blocks is not None :
if len ( matched_blocks ) > 0 :
target_row_index = 0
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
if area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
target_row_index = len ( matched_blocks ) - 1
if area_auto_select_mode == CONST_RANDOM :
target_row_index = random . randint ( 0 , len ( matched_blocks ) - 1 )
target_area = matched_blocks [ target_row_index ]
if target_area is not None :
try :
if target_area . is_enabled ( ) :
target_area . click ( )
is_price_assign_by_bot = True
except Exception as exc :
print ( " click target_area link fail " )
print ( exc )
# use plan B
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , target_area )
is_price_assign_by_bot = True
except Exception as exc :
pass
return is_need_refresh , is_price_assign_by_bot
def hkticketing_ticket_number_auto_select ( driver , ticket_number ) :
selector_string = ' select.shortSelect '
by_method = By . CSS_SELECTOR
return assign_ticket_number_by_select ( driver , ticket_number , by_method , selector_string )
2023-01-29 18:14:55 +00:00
def hkticketing_nav_to_footer ( driver ) :
try :
el_nav = None
el_nav = driver . find_element ( By . CSS_SELECTOR , ' #wrapFooter ' )
if not el_nav is None :
builder = ActionChains ( driver )
builder . move_to_element ( el_nav )
builder . click ( el_nav )
builder . perform ( )
except Exception as exc :
pass
2023-01-23 13:32:47 +00:00
def hkticketing_next_button_press ( driver ) :
ret = False
el_btn = None
try :
el_btn = driver . find_element ( By . CSS_SELECTOR , ' #continueBar > div.chooseTicketsOfferDiv > button ' )
except Exception as exc :
print ( " find next button fail... " )
print ( exc )
if el_btn is not None :
print ( " bingo, found next button, start to press " )
2023-01-29 18:14:55 +00:00
hkticketing_nav_to_footer ( driver )
2023-01-23 13:32:47 +00:00
try :
if el_btn . is_enabled ( ) and el_btn . is_displayed ( ) :
el_btn . click ( )
ret = True
except Exception as exc :
print ( " click next button fail... " )
print ( exc )
return ret
def hkticketing_go_to_payment ( driver ) :
ret = False
el_btn = None
try :
el_btn = driver . find_element ( By . CSS_SELECTOR , ' #goToPaymentButton ' )
except Exception as exc :
print ( " find next button fail... " )
print ( exc )
if el_btn is not None :
print ( " bingo, found next button, start to press " )
try :
if el_btn . is_enabled ( ) and el_btn . is_displayed ( ) :
el_btn . click ( )
ret = True
except Exception as exc :
print ( " click next button fail... " )
print ( exc )
return ret
def hkticketing_ticket_delivery_option ( driver ) :
show_debug_message = True # debug.
show_debug_message = False # online
is_delivery_option_assigned = False
form_select = None
try :
selector_string = ' #selectDeliveryType '
form_select = driver . find_element ( By . CSS_SELECTOR , selector_string )
except Exception as exc :
if show_debug_message :
print ( " find selectDeliveryType select fail " )
print ( exc )
pass
select_obj = None
if form_select is not None :
is_visible = False
try :
is_visible = form_select . is_enabled ( )
except Exception as exc :
pass
if is_visible :
try :
select_obj = Select ( form_select )
except Exception as exc :
pass
if select_obj is not None :
try :
select_obj . select_by_value ( " 1 " )
is_delivery_option_assigned = True
except Exception as exc :
print ( " delivery_option fail " )
print ( exc )
2023-01-29 18:14:55 +00:00
return is_delivery_option_assigned
def hkticketing_hide_tickets_blocks ( driver ) :
show_debug_message = True # debug.
show_debug_message = False # online
2023-01-23 13:32:47 +00:00
actionBlock_divs = None
try :
selector_string = ' div.actionBlock.note '
actionBlock_divs = driver . find_elements ( By . CSS_SELECTOR , selector_string )
for each_div in actionBlock_divs :
driver . execute_script ( " arguments[0].innerHTML= ' ' ; " , each_div ) ;
except Exception as exc :
if show_debug_message :
print ( " find selectDeliveryType select fail " )
print ( exc )
pass
2023-01-29 18:14:55 +00:00
detailModuleCopy_divs = None
try :
selector_string = ' div.detailModuleCopy '
detailModuleCopy_divs = driver . find_elements ( By . CSS_SELECTOR , selector_string )
if not detailModuleCopy_divs is None :
driver . execute_script ( " arguments[0].innerHTML= ' ' ; " , detailModuleCopy_divs ) ;
except Exception as exc :
pass
mapWrapper_divs = None
try :
selector_string = ' div.mapWrapper '
mapWrapper_divs = driver . find_elements ( By . CSS_SELECTOR , selector_string )
if not mapWrapper_divs is None :
driver . execute_script ( " arguments[0].innerHTML= ' ' ; " , mapWrapper_divs ) ;
except Exception as exc :
pass
2023-02-19 04:16:31 +00:00
2023-01-23 13:32:47 +00:00
2023-01-29 18:14:55 +00:00
def hkticketing_performance ( driver , config_dict , domain_name ) :
2023-01-23 13:32:47 +00:00
show_debug_message = True # debug.
show_debug_message = False # online
is_price_assign_by_bot = False
is_need_refresh = False
auto_fill_ticket_number = True
if auto_fill_ticket_number :
# click price row.
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 ( )
area_keyword_1_and = " "
area_keyword_2_and = " "
if show_debug_message :
print ( " area_keyword_1: " , area_keyword_1 )
#print("area_keyword_1_and:", area_keyword_1_and)
print ( " area_keyword_2: " , area_keyword_2 )
#print("area_keyword_2_and:", area_keyword_2_and)
is_need_refresh = False
if not is_price_assign_by_bot :
is_need_refresh , is_price_assign_by_bot = hkticketing_area_auto_select ( driver , area_auto_select_mode , area_keyword_1 , area_keyword_1_and )
if not is_need_refresh :
if not is_price_assign_by_bot :
# try keyword_2
if len ( area_keyword_2 ) > 0 :
is_need_refresh , is_price_assign_by_bot = hkticketing_area_auto_select ( driver , area_auto_select_mode , area_keyword_2 , area_keyword_2_and )
if not is_need_refresh :
if not is_price_assign_by_bot :
if len ( area_keyword_3 ) > 0 :
is_need_refresh , is_price_assign_by_bot = hkticketing_area_auto_select ( driver , area_auto_select_mode , area_keyword_3 , " " )
if not is_need_refresh :
if not is_price_assign_by_bot :
if len ( area_keyword_4 ) > 0 :
is_need_refresh , is_price_assign_by_bot = hkticketing_area_auto_select ( driver , area_auto_select_mode , area_keyword_4 , " " )
if is_need_refresh :
if show_debug_message :
print ( " is_need_refresh: " , is_need_refresh )
try :
driver . refresh ( )
except Exception as exc :
pass
2023-01-29 18:14:55 +00:00
# hide blocks.
hkticketing_hide_tickets_blocks ( driver )
# goto bottom.
hkticketing_nav_to_footer ( driver )
2023-01-23 13:32:47 +00:00
# choose ticket.
ticket_number = str ( config_dict [ " ticket_number " ] )
is_ticket_number_assigned = hkticketing_ticket_number_auto_select ( driver , ticket_number )
if show_debug_message :
print ( " ticket_number: " , ticket_number )
print ( " is_ticket_number_assigned: " , is_ticket_number_assigned )
# Select a delivery option
2023-01-29 18:14:55 +00:00
is_delivery_option_assigned = True
if not ' galaxymacau.com ' in domain_name :
# hkticketing
is_delivery_option_assigned = False
if is_ticket_number_assigned :
is_delivery_option_assigned = hkticketing_ticket_delivery_option ( driver )
if show_debug_message :
print ( " is_delivery_option_assigned: " , is_delivery_option_assigned )
2023-01-23 13:32:47 +00:00
if is_delivery_option_assigned :
auto_press_next_step_button = True
if auto_press_next_step_button :
if is_price_assign_by_bot :
for i in range ( 2 ) :
click_ret = hkticketing_next_button_press ( driver )
time . sleep ( 0.2 )
if click_ret :
break
return is_price_assign_by_bot
2023-01-29 18:14:55 +00:00
2023-02-05 14:10:57 +00:00
def hkticketing_escape_robot_detection ( driver ) :
ret = False
el_main_iframe = None
try :
el_main_iframe = driver . find_element ( By . ID , ' main-iframe ' )
except Exception as exc :
print ( " find el_main_iframe fail... " )
#print(exc)
pass
if el_main_iframe is not None :
print ( " bingo, found el_main_iframe, start to escape " )
entry_url = " https://queue.hkticketing.com/hotshow.html "
try :
driver . get ( entry_url )
except Exception as exc :
print ( exc )
return ret
2023-01-29 18:14:55 +00:00
2023-01-23 13:32:47 +00:00
def hkticketing_main ( driver , url , config_dict ) :
2023-01-23 20:36:06 +00:00
home_url_list = [ ' https://premier.hkticketing.com/ '
, ' https://hotshow.hkticketing.com/ '
, ' https://premier.hkticketing.com/default.aspx '
, ' https://hotshow.hkticketing.com/default.aspx '
2023-02-12 09:49:55 +00:00
, ' https://premier.hkticketing.com/Membership/Login.aspx '
, ' https://hotshow.hkticketing.com/Membership/Login.aspx '
2023-01-23 20:36:06 +00:00
]
2023-01-23 13:32:47 +00:00
for each_url in home_url_list :
if each_url == url :
hkticketing_home ( driver )
2023-02-15 14:24:26 +00:00
time . sleep ( 0.2 )
2023-01-23 13:32:47 +00:00
break
2023-01-27 09:05:46 +00:00
if ' queue.hkticketing.com/hotshow.html ' in url :
entry_url = ' http://entry-hotshow.hkticketing.com/ '
try :
driver . get ( entry_url )
except Exception as exc :
pass
2023-02-12 09:49:55 +00:00
# PS: share function with galaxymacau, but memeber is not shared.
if ' hkticketing.com/Membership/Login.aspx ' in url :
account = config_dict [ " advanced " ] [ " hkticketing_account " ] . strip ( )
if len ( account ) > 4 :
hkticketing_login ( driver , account , decryptMe ( config_dict [ " advanced " ] [ " hkticketing_password " ] ) )
2023-01-23 13:32:47 +00:00
#https://premier.hkticketing.com/shows/show.aspx?sh=XXXX
if ' shows/show.aspx? ' in url :
2023-02-09 16:22:13 +00:00
is_modal_dialog_popup = check_modal_dialog_popup ( driver )
if is_modal_dialog_popup :
print ( " is_modal_dialog_popup! skip... " )
else :
is_event_page = False
if len ( url . split ( ' / ' ) ) == 5 :
is_event_page = True
2023-01-23 13:32:47 +00:00
2023-02-09 16:22:13 +00:00
if is_event_page :
date_auto_select_enable = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " enable " ]
if date_auto_select_enable :
hkticketing_show ( driver , config_dict )
pass
2023-01-23 13:32:47 +00:00
# https://premier.hkticketing.com/events/XXX/venues/KSH/performances/XXX/tickets
if ' /events/ ' in url and ' /performances/ ' in url :
2023-02-05 14:10:57 +00:00
robot_detection = hkticketing_escape_robot_detection ( driver )
2023-02-09 16:22:13 +00:00
is_modal_dialog_popup = check_modal_dialog_popup ( driver )
if is_modal_dialog_popup :
print ( " is_modal_dialog_popup! skip... " )
else :
if ' /tickets ' in url :
domain_name = url . split ( ' / ' ) [ 2 ]
area_auto_select_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " enable " ]
if area_auto_select_enable :
hkticketing_performance ( driver , config_dict , domain_name )
pass
2023-02-19 04:16:31 +00:00
2023-02-09 16:22:13 +00:00
if ' /seatmap ' in url :
# goto bottom.
hkticketing_nav_to_footer ( driver )
hkticketing_go_to_payment ( driver )
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
def khan_go_buy_redirect ( driver ) :
ret = False
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
el_btn = None
2023-01-23 13:32:47 +00:00
try :
2023-01-23 20:36:06 +00:00
el_btn = driver . find_element ( By . CSS_SELECTOR , ' div.btn_go > input[type= " image " ] ' )
2023-01-23 13:32:47 +00:00
except Exception as exc :
2023-01-23 20:36:06 +00:00
#print("find next button fail...")
#print(exc)
2023-01-23 13:32:47 +00:00
pass
2023-01-23 20:36:06 +00:00
if el_btn is not None :
print ( " bingo, found next button, start to press " )
try :
if el_btn . is_enabled ( ) and el_btn . is_displayed ( ) :
el_btn . click ( )
ret = True
except Exception as exc :
print ( " click next button fail... " )
print ( exc )
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
return ret
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
def hkam_date_auto_select ( driver , auto_select_mode , date_keyword , auto_reload_coming_soon_page_enable ) :
show_debug_message = True # debug.
show_debug_message = False # online
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
ret = False
matched_blocks = None
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
# clean stop word.
date_keyword = format_keyword_string ( date_keyword )
date_keyword_and = " "
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
# default not selected.
is_date_assigned = False
if not is_date_assigned :
area_list = None
2023-01-23 13:32:47 +00:00
try :
2023-01-23 20:36:06 +00:00
my_css_selector = " td.contentCenterBg > table > tbody > tr > td > table > tbody > tr > td > table > tbody > tr > td > div > table > tbody > tr "
area_list = driver . find_elements ( By . CSS_SELECTOR , my_css_selector )
2023-01-23 13:32:47 +00:00
except Exception as exc :
2023-01-23 20:36:06 +00:00
print ( " find #date-time tr list fail " )
print ( exc )
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
#PS: some blocks are generate by ajax, not appear at first time.
formated_area_list = None
if area_list is not None :
area_list_count = len ( area_list )
if show_debug_message :
print ( " date_list_count: " , area_list_count )
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
if area_list_count > 0 :
formated_area_list = [ ]
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
# filter list.
row_index = 0
for row in area_list :
row_index + = 1
row_is_enabled = False
try :
row_text = row . text
if ' 立即訂購 ' in row_text :
my_css_selector = " a.showoder "
el_btn = row . find_element ( By . CSS_SELECTOR , my_css_selector )
if el_btn is not None :
if el_btn . is_enabled ( ) :
#print("row's button enabled.")
row_is_enabled = True
except Exception as exc :
if show_debug_message :
print ( exc )
pass
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
if row_is_enabled :
formated_area_list . append ( row )
else :
if show_debug_message :
print ( " area_list is None... " )
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
if formated_area_list is not None :
area_list_count = len ( formated_area_list )
if show_debug_message :
print ( " formated_area_list count: " , area_list_count )
if area_list_count > 0 :
if len ( date_keyword ) == 0 :
matched_blocks = formated_area_list
else :
# match keyword.
if show_debug_message :
print ( " start to match keyword: " , date_keyword )
matched_blocks = [ ]
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
row_index = 0
for row in formated_area_list :
row_index + = 1
row_is_enabled = True
if row_is_enabled :
row_text = " "
try :
row_text = row . text
except Exception as exc :
print ( " get text fail " )
break
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
if row_text is None :
row_text = " "
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
if len ( row_text ) > 0 :
row_text = format_keyword_string ( row_text )
if show_debug_message :
print ( " row_text: " , row_text )
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
is_match_area = False
match_area_code = 0
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
if date_keyword in row_text :
if len ( date_keyword_and ) == 0 :
if show_debug_message :
print ( ' keyword_and # is empty, directly match. ' )
# keyword #2 is empty, direct append.
is_match_area = True
match_area_code = 2
else :
if date_keyword_and in row_text :
if show_debug_message :
print ( ' match keyword_and ' )
is_match_area = True
match_area_code = 3
else :
if show_debug_message :
print ( ' not match keyword_and ' )
pass
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
if is_match_area :
matched_blocks . append ( row )
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
if show_debug_message :
if not matched_blocks is None :
print ( " after match keyword, found count: " , len ( matched_blocks ) )
else :
print ( " not found date-time-position " )
pass
else :
print ( " date date-time-position is None " )
pass
2023-01-23 13:32:47 +00:00
2023-01-23 20:36:06 +00:00
target_area = None
if matched_blocks is not None :
if len ( matched_blocks ) > 0 :
target_row_index = 0
if auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
if auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
target_row_index = len ( matched_blocks ) - 1
if auto_select_mode == CONST_RANDOM :
target_row_index = random . randint ( 0 , len ( matched_blocks ) - 1 )
target_area = matched_blocks [ target_row_index ]
if target_area is not None :
el_btn = None
try :
my_css_selector = " a.showoder "
el_btn = target_area . find_element ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
pass
if el_btn is not None :
try :
if el_btn . is_enabled ( ) and el_btn . is_displayed ( ) :
el_btn . click ( )
print ( " buy button pressed. " )
ret = True
except Exception as exc :
# use plan B
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , el_btn )
ret = True
except Exception as exc :
2023-02-19 04:16:31 +00:00
pass
2023-01-23 20:36:06 +00:00
'''
if auto_reload_coming_soon_page_enable :
# auto refresh for date list page.
if not formated_area_list is None :
if len ( formated_area_list ) == 0 :
try :
driver . refresh ( )
time . sleep ( 0.4 )
except Exception as exc :
pass
'''
return ret
def kham_product ( driver , config_dict ) :
show_debug_message = True # debug.
show_debug_message = False # online
date_auto_select_mode = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " mode " ]
date_keyword = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " date_keyword " ] . strip ( )
auto_reload_coming_soon_page_enable = config_dict [ " tixcraft " ] [ " auto_reload_coming_soon_page " ]
if show_debug_message :
print ( " date_keyword: " , date_keyword )
print ( " auto_reload_coming_soon_page_enable: " , auto_reload_coming_soon_page_enable )
is_date_assign_by_bot = hkam_date_auto_select ( driver , date_auto_select_mode , date_keyword , auto_reload_coming_soon_page_enable )
return is_date_assign_by_bot
def kham_area_auto_select ( driver , area_auto_select_mode , area_keyword_1 , area_keyword_1_and , ticket_number ) :
show_debug_message = True # debug.
show_debug_message = False # online
is_price_assign_by_bot = False
is_need_refresh = False
matched_blocks = None
# clean stop word.
area_keyword_1 = format_keyword_string ( area_keyword_1 )
area_keyword_1_and = format_keyword_string ( area_keyword_1_and )
area_list = None
try :
my_css_selector = " table.salesTable > tbody > tr > td > table > tbody > tr "
area_list = driver . find_elements ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
print ( " find #ticket-price-tbl date list fail " )
print ( exc )
2023-02-15 14:24:26 +00:00
readme_table_mode = False
if area_list is None :
readme_table_mode = True
else :
if len ( area_list ) == 0 :
readme_table_mode = True
if readme_table_mode :
if show_debug_message :
print ( " for without table.salesTable " )
try :
my_css_selector = " #readmeTable "
readme_table = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
if not readme_table is None :
if show_debug_message :
print ( " found readme_table " )
target_table = readme_table . find_element ( By . XPATH , ' ../.. ' )
if not target_table is None :
if show_debug_message :
print ( " found target_table " )
my_css_selector = " td > table > tbody > tr "
area_list = target_table . find_elements ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
print ( " find #ticket-price-tbl date list fail " )
print ( exc )
2023-01-23 20:36:06 +00:00
formated_area_list = None
if area_list is not None :
area_list_count = len ( area_list )
if show_debug_message :
print ( " area_list_count: " , area_list_count )
if area_list_count > 0 :
formated_area_list = [ ]
# filter list.
row_index = 0
for row in area_list :
row_index + = 1
2023-02-25 04:35:07 +00:00
row_is_sold_out = False
2023-01-23 20:36:06 +00:00
try :
2023-02-25 04:35:07 +00:00
row_text = row . text
if row_text is None :
row_text = " "
if ' 售完 ' in row_text :
row_is_sold_out = True
2023-01-23 20:36:06 +00:00
except Exception as exc :
pass
2023-02-25 04:35:07 +00:00
row_is_enabled = False
if not row_is_sold_out :
try :
is_row_with_id = False
tr_id_string = str ( row . get_attribute ( ' id ' ) )
if len ( tr_id_string ) > 1 :
is_row_with_id = True
if is_row_with_id :
my_css_selector = " span.textPrice "
el_remaining = row . find_element ( By . CSS_SELECTOR , my_css_selector )
if el_remaining is not None :
remaining_value = str ( el_remaining . text ) . strip ( )
if remaining_value . isnumeric ( ) :
if int ( remaining_value ) > = ticket_number :
row_is_enabled = True
else :
row_is_enabled = True
except Exception as exc :
pass
2023-01-23 20:36:06 +00:00
if row_is_enabled :
formated_area_list . append ( row )
else :
if show_debug_message :
print ( " area_list_count is empty. " )
pass
else :
if show_debug_message :
print ( " area_list_count is None. " )
pass
if formated_area_list is not None :
area_list_count = len ( formated_area_list )
if show_debug_message :
print ( " formated_area_list count: " , area_list_count )
if area_list_count > 0 :
if len ( area_keyword_1 ) == 0 :
matched_blocks = formated_area_list
else :
# match keyword.
if show_debug_message :
print ( " start to match keyword: " , area_keyword_1 )
print ( " keyword and: " , area_keyword_1_and )
matched_blocks = [ ]
row_index = 0
for row in formated_area_list :
row_index + = 1
row_is_enabled = True
if row_is_enabled :
row_text = " "
try :
row_text = row . text
except Exception as exc :
print ( " get text fail " )
break
if row_text is None :
row_text = " "
if len ( row_text ) > 0 :
row_text = format_keyword_string ( row_text )
if show_debug_message :
print ( " row_text: " , row_text )
is_match_area = False
match_area_code = 0
if area_keyword_1 in row_text :
if len ( area_keyword_1_and ) == 0 :
if show_debug_message :
print ( ' keyword_and is empty, directly match. ' )
# keyword #2 is empty, direct append.
is_match_area = True
match_area_code = 2
else :
if area_keyword_1_and in row_text :
if show_debug_message :
print ( ' match keyword_and ' )
is_match_area = True
match_area_code = 3
else :
if show_debug_message :
print ( ' not match keyword_and ' )
pass
if is_match_area :
matched_blocks . append ( row )
if show_debug_message :
if not matched_blocks is None :
print ( " after match keyword, found count: " , len ( matched_blocks ) )
else :
is_need_refresh = True
if show_debug_message :
print ( " formated_area_list is empty. " )
target_area = None
if matched_blocks is not None :
if len ( matched_blocks ) > 0 :
target_row_index = 0
if area_auto_select_mode == CONST_FROM_TOP_TO_BOTTOM :
pass
if area_auto_select_mode == CONST_FROM_BOTTOM_TO_TOP :
target_row_index = len ( matched_blocks ) - 1
if area_auto_select_mode == CONST_RANDOM :
target_row_index = random . randint ( 0 , len ( matched_blocks ) - 1 )
target_area = matched_blocks [ target_row_index ]
else :
if show_debug_message :
print ( " matched_blocks is None. " )
if target_area is not None :
try :
if target_area . is_enabled ( ) :
target_area . click ( )
is_price_assign_by_bot = True
except Exception as exc :
print ( " click target_area link fail " )
print ( exc )
# use plan B
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , target_area )
is_price_assign_by_bot = True
except Exception as exc :
pass
else :
if show_debug_message :
print ( " target_area is None, no target to click. " )
if show_debug_message :
print ( " is_need_refresh: " , is_need_refresh )
print ( " is_price_assign_by_bot: " , is_price_assign_by_bot )
return is_need_refresh , is_price_assign_by_bot
def kham_performance_ticket_number ( driver , ticket_number ) :
ret = False
form_input = None
try :
form_input = driver . find_element ( By . CSS_SELECTOR , ' td.tdtext_orangeunderline > input[type= " text " ] ' )
except Exception as exc :
#print("find modal-dialog fail")
#print(exc)
pass
inputed_value = None
if form_input is not None :
try :
inputed_value = form_input . get_attribute ( ' value ' )
except Exception as exc :
print ( " find verify code fail " )
pass
if inputed_value is None :
inputed_value = " "
if inputed_value == " " :
is_visible = False
try :
if form_input . is_enabled ( ) :
is_visible = True
except Exception as exc :
pass
if is_visible :
try :
form_input . click ( )
form_input . send_keys ( str ( ticket_number ) )
ret = True
except Exception as exc :
# use plan B
'''
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , el_div )
ret = True
except Exception as exc :
pass
'''
pass
return ret
def kham_performance ( driver , config_dict , ocr , Captcha_Browser , model_name ) :
show_debug_message = True # debug.
show_debug_message = False # online
is_price_assign_by_bot = False
is_need_refresh = False
auto_fill_ticket_number = True
if auto_fill_ticket_number :
# click price row.
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 ( )
area_keyword_1_and = " "
area_keyword_2_and = " "
ticket_number = config_dict [ " ticket_number " ]
if show_debug_message :
print ( " area_keyword_1: " , area_keyword_1 )
#print("area_keyword_1_and:", area_keyword_1_and)
print ( " area_keyword_2: " , area_keyword_2 )
#print("area_keyword_2_and:", area_keyword_2_and)
print ( " ticket_number: " , ticket_number )
is_need_refresh = False
if not is_price_assign_by_bot :
is_need_refresh , is_price_assign_by_bot = kham_area_auto_select ( driver , area_auto_select_mode , area_keyword_1 , area_keyword_1_and , ticket_number )
if not is_need_refresh :
if not is_price_assign_by_bot :
# try keyword_2
if len ( area_keyword_2 ) > 0 :
is_need_refresh , is_price_assign_by_bot = kham_area_auto_select ( driver , area_auto_select_mode , area_keyword_2 , area_keyword_2_and , ticket_number )
if not is_need_refresh :
if not is_price_assign_by_bot :
if len ( area_keyword_3 ) > 0 :
is_need_refresh , is_price_assign_by_bot = kham_area_auto_select ( driver , area_auto_select_mode , area_keyword_3 , " " , ticket_number )
if not is_need_refresh :
if not is_price_assign_by_bot :
if len ( area_keyword_4 ) > 0 :
is_need_refresh , is_price_assign_by_bot = kham_area_auto_select ( driver , area_auto_select_mode , area_keyword_4 , " " , ticket_number )
if is_need_refresh :
if show_debug_message :
print ( " is_need_refresh: " , is_need_refresh )
try :
driver . refresh ( )
except Exception as exc :
pass
# special case for UTK0202 model.
is_ticket_number_assigned = kham_performance_ticket_number ( driver , ticket_number )
if is_ticket_number_assigned :
is_captcha_sent = kham_captcha ( driver , config_dict , ocr , Captcha_Browser , model_name )
if is_captcha_sent :
el_btn = None
try :
my_css_selector = ' input[onclick= " return chkCart(); " ] '
el_btn = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
if not el_btn is None :
el_btn . click ( )
except Exception as exc :
print ( " find chkCart button fail " )
pass
return is_price_assign_by_bot
def kham_performance_confirm_dialog_popup ( driver ) :
ret = False
el_div = None
try :
el_div = driver . find_element ( By . CSS_SELECTOR , ' div.ui-dialog-buttonset > button.ui-button ' )
except Exception as exc :
#print("find modal-dialog fail")
#print(exc)
pass
if el_div is not None :
#print("bingo, found ui-dialog-buttonset confirm-btn")
is_visible = False
try :
if el_div . is_enabled ( ) :
if el_div . is_displayed ( ) :
is_visible = True
except Exception as exc :
pass
if is_visible :
try :
el_div . click ( )
ret = True
except Exception as exc :
# use plan B
'''
try :
print ( " force to click by js. " )
driver . execute_script ( " arguments[0].click(); " , el_div )
ret = True
except Exception as exc :
pass
'''
pass
return ret
def kham_keyin_captcha_code ( driver , answer = " " , auto_submit = False ) :
is_verifyCode_editing = False
is_form_sumbited = False
# manually keyin verify code.
# start to input verify code.
form_verifyCode = None
try :
#my_css_selector = 'table#blockLogin > tbody > tr > td > input[type="text"]'
my_css_selector = ' input[value= " 驗證碼 " ] '
form_verifyCode = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
print ( " find blockLogin input fail " )
try :
my_css_selector = ' input[placeholder= " 驗證碼 " ] '
form_verifyCode = driver . find_element ( By . CSS_SELECTOR , my_css_selector )
except Exception as exc :
pass
if form_verifyCode is not None :
inputed_value = None
try :
inputed_value = form_verifyCode . get_attribute ( ' value ' )
except Exception as exc :
print ( " find verify code fail " )
pass
if inputed_value is None :
inputed_value = " "
if inputed_value == " 驗證碼 " :
try :
form_verifyCode . clear ( )
except Exception as exc :
print ( " clear verify code fail " )
pass
else :
if len ( inputed_value ) > 0 :
print ( " captcha text inputed. " )
form_verifyCode = None
is_verifyCode_editing = True
if form_verifyCode is not None :
is_visible = False
try :
if form_verifyCode . is_enabled ( ) :
is_visible = True
except Exception as exc :
pass
if is_visible :
try :
form_verifyCode . click ( )
is_verifyCode_editing = True
except Exception as exc :
pass
#print("start to fill answer.")
try :
if len ( answer ) > 0 :
answer = answer . upper ( )
form_verifyCode . clear ( )
form_verifyCode . send_keys ( answer )
if auto_submit :
form_verifyCode . send_keys ( Keys . ENTER )
is_verifyCode_editing = False
is_form_sumbited = True
else :
print ( " select all captcha text " )
driver . execute_script ( " arguments[0].select(); " , form_verifyCode )
if len ( answer ) > 0 :
#tixcraft_toast(driver, "※ 按 Enter 如果答案是: " + answer)
pass
except Exception as exc :
print ( " send_keys ocr answer fail. " )
return is_verifyCode_editing , is_form_sumbited
def kham_auto_ocr ( driver , ocr , away_from_keyboard_enable , previous_answer , Captcha_Browser , ocr_captcha_image_source , model_name ) :
show_debug_message = True # debug.
show_debug_message = False # online
print ( " start to ddddocr " )
CONST_OCR_CAPTCH_IMAGE_SOURCE_NON_BROWSER = " NonBrowser "
2023-02-12 03:02:16 +00:00
CONST_OCR_CAPTCH_IMAGE_SOURCE_CANVAS = " canvas "
2023-01-23 20:36:06 +00:00
is_need_redo_ocr = False
is_form_sumbited = False
orc_answer = None
if not ocr is None :
if show_debug_message :
print ( " away_from_keyboard_enable: " , away_from_keyboard_enable )
print ( " previous_answer: " , previous_answer )
print ( " ocr_captcha_image_source: " , ocr_captcha_image_source )
ocr_start_time = time . time ( )
img_base64 = None
if ocr_captcha_image_source == CONST_OCR_CAPTCH_IMAGE_SOURCE_NON_BROWSER :
if not Captcha_Browser is None :
img_base64 = base64 . b64decode ( Captcha_Browser . Request_Captcha ( ) )
2023-02-12 03:02:16 +00:00
if ocr_captcha_image_source == CONST_OCR_CAPTCH_IMAGE_SOURCE_CANVAS :
2023-01-23 20:36:06 +00:00
image_id = ' chk_pic '
try :
form_verifyCode_base64 = driver . execute_async_script ( """
var canvas = document . createElement ( ' canvas ' ) ;
var context = canvas . getContext ( ' 2d ' ) ;
var img = document . getElementById ( ' %s ' ) ;
canvas . height = img . naturalHeight ;
canvas . width = img . naturalWidth ;
context . drawImage ( img , 0 , 0 ) ;
callback = arguments [ arguments . length - 1 ] ;
callback ( canvas . toDataURL ( ) ) ;
""" % (image_id))
img_base64 = base64 . b64decode ( form_verifyCode_base64 . split ( ' , ' ) [ 1 ] )
except Exception as exc :
if show_debug_message :
print ( " canvas exception: " , str ( exc ) )
pass
if not img_base64 is None :
try :
orc_answer = ocr . classification ( img_base64 )
except Exception as exc :
pass
2023-02-19 04:16:31 +00:00
2023-01-23 20:36:06 +00:00
ocr_done_time = time . time ( )
ocr_elapsed_time = ocr_done_time - ocr_start_time
print ( " ocr elapsed time: " , " {:.3f} " . format ( ocr_elapsed_time ) )
else :
print ( " ddddocr is None " )
2023-02-19 04:16:31 +00:00
2023-01-23 20:36:06 +00:00
if not orc_answer is None :
orc_answer = orc_answer . strip ( )
print ( " orc_answer: " , orc_answer )
if len ( orc_answer ) == 4 :
who_care_var , is_form_sumbited = kham_keyin_captcha_code ( driver , answer = orc_answer , auto_submit = away_from_keyboard_enable )
else :
if not away_from_keyboard_enable :
kham_keyin_captcha_code ( driver )
#tixcraft_toast(driver, "※ OCR辨識失敗Q_Q, 驗證碼請手動輸入...")
else :
is_need_redo_ocr = True
if previous_answer != orc_answer :
previous_answer = orc_answer
print ( " click captcha again " )
if True :
# selenium solution.
jquery_string = ' $( " #chk_pic " ).attr( " src " , " /pic.aspx?TYPE= %s &ts= " + new Date().getTime()); ' % ( model_name )
driver . execute_script ( jquery_string )
2023-02-12 03:02:16 +00:00
if ocr_captcha_image_source == CONST_OCR_CAPTCH_IMAGE_SOURCE_CANVAS :
2023-01-23 20:36:06 +00:00
time . sleep ( 0.3 )
else :
# Non_Browser solution.
if not Captcha_Browser is None :
new_captcha_url = Captcha_Browser . Request_Refresh_Captcha ( ) #取得新的CAPTCHA
if new_captcha_url != " " :
#PS:[TODO]
#tixcraft_change_captcha(driver, new_captcha_url) #更改CAPTCHA圖
pass
else :
print ( " orc_answer is None " )
print ( " previous_answer: " , previous_answer )
if previous_answer is None :
kham_keyin_captcha_code ( driver )
else :
# page is not ready, retry again.
# PS: usually occur in async script get captcha image.
is_need_redo_ocr = True
return is_need_redo_ocr , previous_answer , is_form_sumbited
def kham_captcha ( driver , config_dict , ocr , Captcha_Browser , model_name ) :
ocr_captcha_enable = config_dict [ " ocr_captcha " ] [ " enable " ]
away_from_keyboard_enable = config_dict [ " ocr_captcha " ] [ " force_submit " ]
if not ocr_captcha_enable :
away_from_keyboard_enable = False
2023-02-19 04:16:31 +00:00
ocr_captcha_image_source = config_dict [ " ocr_captcha " ] [ " image_source " ]
2023-01-23 20:36:06 +00:00
#PS: need a 'auto assign site' feature to enable away_from_keyboard feature.
away_from_keyboard_enable = False
is_cpatcha_sent = False
previous_answer = None
is_verifyCode_editing = True
for redo_ocr in range ( 999 ) :
is_need_redo_ocr , previous_answer , is_form_sumbited = kham_auto_ocr ( driver , ocr , away_from_keyboard_enable , previous_answer , Captcha_Browser , ocr_captcha_image_source , model_name )
2023-02-19 04:16:31 +00:00
2023-01-23 20:36:06 +00:00
# TODO: must ensure the answer is corrent...
is_cpatcha_sent = True
2023-02-19 04:16:31 +00:00
2023-01-23 20:36:06 +00:00
if is_form_sumbited :
break
2023-02-19 04:16:31 +00:00
2023-01-23 20:36:06 +00:00
if not away_from_keyboard_enable :
break
2023-02-19 04:16:31 +00:00
2023-01-23 20:36:06 +00:00
if not is_need_redo_ocr :
break
return is_cpatcha_sent
2023-02-18 16:41:30 +00:00
def kham_home_close_window ( driver ) :
show_debug_message = True # debug.
show_debug_message = False # online
close_all_alert_btns = None
try :
close_all_alert_btns = driver . find_elements ( By . ID , ' Close ' )
except Exception as exc :
print ( " find close_all_alert_btns fail " )
if close_all_alert_btns is not None :
if show_debug_message :
print ( ' all alert count: ' , len ( close_all_alert_btns ) )
for alert_btn in close_all_alert_btns :
is_visible = False
try :
if alert_btn . is_enabled ( ) and alert_btn . is_displayed ( ) :
is_visible = True
except Exception as exc :
pass
if is_visible :
try :
alert_btn . click ( )
except Exception as exc :
print ( " try to click alert_btn fail, force click by js. " )
try :
driver . execute_script ( " arguments[0].click(); " , alert_btn )
except Exception as exc :
pass
2023-01-23 20:36:06 +00:00
def kham_main ( driver , url , config_dict , ocr , Captcha_Browser ) :
home_url_list = [ ' https://kham.com.tw/ '
2023-02-18 16:41:30 +00:00
, ' https://kham.com.tw/application/utk01/utk0101_.aspx '
, ' https://kham.com.tw/application/utk01/utk0101_03.aspx ' ]
2023-01-23 20:36:06 +00:00
for each_url in home_url_list :
2023-02-18 16:41:30 +00:00
if each_url == url . lower ( ) :
kham_home_close_window ( driver )
2023-01-23 20:36:06 +00:00
if config_dict [ " ocr_captcha " ] [ " enable " ] :
domain_name = url . split ( ' / ' ) [ 2 ]
if not Captcha_Browser is None :
Captcha_Browser . Set_cookies ( driver . get_cookies ( ) )
Captcha_Browser . Set_Domain ( domain_name )
break
# https://kham.com.tw/application/UTK13/UTK1306_.aspx
2023-02-18 16:41:30 +00:00
if ' utk1306 ' in url . lower ( ) and ' .aspx ' in url :
2023-01-23 20:36:06 +00:00
if config_dict [ " ocr_captcha " ] [ " enable " ] :
domain_name = url . split ( ' / ' ) [ 2 ]
model_name = url . split ( ' / ' ) [ 5 ]
if len ( model_name ) > 7 :
model_name = model_name [ : 7 ]
captcha_url = ' /pic.aspx?TYPE= %s ' % ( model_name )
#PS: need set cookies once, if user change domain.
if not Captcha_Browser is None :
Captcha_Browser . Set_Domain ( domain_name , captcha_url = captcha_url )
kham_captcha ( driver , config_dict , ocr , Captcha_Browser , model_name )
#https://kham.com.tw/application/UTK02/UTK0201_.aspx?PRODUCT_ID=XXX
2023-02-18 16:41:30 +00:00
if ' utk0201_.aspx?product_id= ' in url . lower ( ) :
2023-01-23 20:36:06 +00:00
is_event_page = False
if len ( url . split ( ' / ' ) ) == 6 :
is_event_page = True
if is_event_page :
khan_go_buy_redirect ( driver )
# https://kham.com.tw/application/UTK02/UTK0201_00.aspx?PRODUCT_ID=N28TFATD
2023-02-18 16:41:30 +00:00
if ' utk0201_00.aspx?product_id= ' in url . lower ( ) :
2023-01-23 20:36:06 +00:00
is_event_page = False
if len ( url . split ( ' / ' ) ) == 6 :
is_event_page = True
if is_event_page :
date_auto_select_enable = config_dict [ " tixcraft " ] [ " date_auto_select " ] [ " enable " ]
if date_auto_select_enable :
kham_product ( driver , config_dict )
# https://kham.com.tw/application/UTK02/UTK0204_.aspx?PERFORMANCE_ID=N28UQPA1&PRODUCT_ID=N28TFATD
2023-02-18 16:41:30 +00:00
if ' .aspx?performance_id= ' in url . lower ( ) and ' product_id= ' in url . lower ( ) :
2023-01-23 20:36:06 +00:00
area_auto_select_enable = config_dict [ " tixcraft " ] [ " area_auto_select " ] [ " enable " ]
if area_auto_select_enable :
domain_name = url . split ( ' / ' ) [ 2 ]
model_name = url . split ( ' / ' ) [ 5 ]
if len ( model_name ) > 7 :
model_name = model_name [ : 7 ]
captcha_url = ' /pic.aspx?TYPE= %s ' % ( model_name )
#PS: need set cookies once, if user change domain.
if not Captcha_Browser is None :
Captcha_Browser . Set_Domain ( domain_name , captcha_url = captcha_url )
is_confirm_dialog_popup = kham_performance_confirm_dialog_popup ( driver )
if is_confirm_dialog_popup :
print ( " is_confirm_dialog_popup! auto press confirm... " )
kham_performance ( driver , config_dict , ocr , Captcha_Browser , model_name )
#https://kham.com.tw/application/UTK02/UTK0205_.aspx?PERFORMANCE_ID=XXX&GROUP_ID=30&PERFORMANCE_PRICE_AREA_ID=XXX
2023-02-18 16:41:30 +00:00
if ' .aspx?performance_id= ' in url . lower ( ) and ' performance_price_area_id= ' in url . lower ( ) :
2023-01-23 20:36:06 +00:00
is_confirm_dialog_popup = kham_performance_confirm_dialog_popup ( driver )
if is_confirm_dialog_popup :
print ( " is_confirm_dialog_popup! auto press confirm... " )
if config_dict [ " ocr_captcha " ] [ " enable " ] :
domain_name = url . split ( ' / ' ) [ 2 ]
model_name = url . split ( ' / ' ) [ 5 ]
if len ( model_name ) > 7 :
model_name = model_name [ : 7 ]
captcha_url = ' /pic.aspx?TYPE= %s ' % ( model_name )
#PS: need set cookies once, if user change domain.
if not Captcha_Browser is None :
Captcha_Browser . Set_Domain ( domain_name , captcha_url = captcha_url )
kham_captcha ( driver , config_dict , ocr , Captcha_Browser , model_name )
2023-02-18 16:41:30 +00:00
if ' /application/utk13/utk1306_.aspx ' in url . lower ( ) :
2023-02-11 05:36:27 +00:00
if config_dict [ " ocr_captcha " ] [ " enable " ] :
domain_name = url . split ( ' / ' ) [ 2 ]
model_name = url . split ( ' / ' ) [ 5 ]
if len ( model_name ) > 7 :
model_name = model_name [ : 7 ]
captcha_url = ' /pic.aspx?TYPE= %s ' % ( model_name )
#PS: need set cookies once, if user change domain.
if not Captcha_Browser is None :
Captcha_Browser . Set_Domain ( domain_name , captcha_url = captcha_url )
kham_captcha ( driver , config_dict , ocr , Captcha_Browser , model_name )
account = config_dict [ " advanced " ] [ " kham_account " ] . strip ( )
if len ( account ) > 4 :
kham_login ( driver , account , decryptMe ( config_dict [ " advanced " ] [ " kham_password " ] ) )
2023-01-23 20:36:06 +00:00
2023-02-23 13:33:49 +00:00
def main ( args ) :
config_dict = get_config_dict ( args )
2023-01-23 20:36:06 +00:00
driver = None
if not config_dict is None :
2023-02-12 03:02:16 +00:00
driver = get_driver_by_config ( config_dict )
2023-01-23 20:36:06 +00:00
else :
print ( " Load config error! " )
# internal variable. 說明:這是一個內部變數,請略過。
url = " "
last_url = " "
# for tixcraft
2023-02-22 16:05:44 +00:00
tixcraft_dict = { }
tixcraft_dict [ " answer_index " ] = - 1
tixcraft_dict [ " is_verifyCode_editing " ] = False
tixcraft_dict [ " is_popup_checkout " ] = False
2023-01-23 20:36:06 +00:00
# for kktix
2023-02-22 16:05:44 +00:00
kktix_dict = { }
kktix_dict [ " answer_index " ] = - 1
kktix_dict [ " kktix_register_status_last " ] = None
2023-02-22 23:46:05 +00:00
kktix_dict [ " is_popup_checkout " ] = False
2023-02-22 16:05:44 +00:00
ibon_dict = { }
ibon_dict [ " answer_index " ] = - 1
2023-01-23 20:36:06 +00:00
2023-02-07 16:42:04 +00:00
DISCONNECTED_MSG = ' : target window already closed '
2023-01-23 20:36:06 +00:00
ocr = None
Captcha_Browser = None
try :
if config_dict [ " ocr_captcha " ] [ " enable " ] :
ocr = ddddocr . DdddOcr ( show_ad = False , beta = True )
Captcha_Browser = NonBrowser ( )
except Exception as exc :
pass
while True :
time . sleep ( 0.1 )
is_alert_popup = False
# pass if driver not loaded.
if driver is None :
print ( " web driver not accessible! " )
break
#is_alert_popup = check_pop_alert(driver)
#MUST "do nothing: if alert popup.
#print("is_alert_popup:", is_alert_popup)
if is_alert_popup :
continue
url = " "
try :
url = driver . current_url
except NoSuchWindowException :
print ( ' NoSuchWindowException at this url: ' , url )
#print("last_url:", last_url)
#print("get_log:", driver.get_log('driver'))
2023-02-05 14:10:57 +00:00
window_handles_count = 0
2023-01-23 20:36:06 +00:00
try :
window_handles_count = len ( driver . window_handles )
2023-02-05 14:10:57 +00:00
#print("window_handles_count:", window_handles_count)
if window_handles_count > = 1 :
2023-01-23 20:36:06 +00:00
driver . switch_to . window ( driver . window_handles [ 0 ] )
2023-02-05 14:10:57 +00:00
driver . switch_to . default_content ( )
2023-02-06 16:19:20 +00:00
time . sleep ( 0.2 )
2023-02-07 16:42:04 +00:00
except Exception as excSwithFail :
#print("excSwithFail:", excSwithFail)
pass
if window_handles_count == 0 :
try :
driver_log = driver . get_log ( ' driver ' ) [ - 1 ] [ ' message ' ]
print ( " get_log: " , driver_log )
if DISCONNECTED_MSG in driver_log :
2023-02-05 14:10:57 +00:00
print ( ' quit bot by NoSuchWindowException ' )
driver . quit ( )
sys . exit ( )
break
2023-02-07 16:42:04 +00:00
except Exception as excGetDriverMessageFail :
#print("excGetDriverMessageFail:", excGetDriverMessageFail)
except_string = str ( excGetDriverMessageFail )
if ' HTTP method not allowed ' in except_string :
print ( ' quit bot by close browser ' )
driver . quit ( )
sys . exit ( )
break
2023-02-05 14:10:57 +00:00
2023-01-23 20:36:06 +00:00
except UnexpectedAlertPresentException as exc1 :
# PS: DON'T remove this line.
is_verifyCode_editing = False
print ( ' UnexpectedAlertPresentException at this url: ' , url )
#time.sleep(3.5)
# PS: do nothing...
# PS: current chrome-driver + chrome call current_url cause alert/prompt dialog disappear!
# raise exception at selenium/webdriver/remote/errorhandler.py
# after dialog disappear new excpetion: unhandled inspector error: Not attached to an active page
is_pass_alert = False
is_pass_alert = True
if is_pass_alert :
try :
driver . switch_to . alert . accept ( )
except Exception as exc :
pass
except Exception as exc :
is_verifyCode_editing = False
logger . error ( ' Maxbot URL Exception ' )
logger . error ( exc , exc_info = True )
#UnicodeEncodeError: 'ascii' codec can't encode characters in position 63-72: ordinal not in range(128)
str_exc = " "
try :
str_exc = str ( exc )
except Exception as exc2 :
pass
if len ( str_exc ) == 0 :
str_exc = repr ( exc )
exit_bot_error_strings = [ u ' Max retries exceeded '
, u ' chrome not reachable '
, u ' unable to connect to renderer '
, u ' failed to check if window was closed '
, u ' Failed to establish a new connection '
, u ' Connection refused '
, u ' disconnected '
, u ' without establishing a connection '
, u ' web view not found '
]
for each_error_string in exit_bot_error_strings :
# for python2
# say goodbye to python2
'''
try :
basestring
if isinstance ( each_error_string , unicode ) :
each_error_string = str ( each_error_string )
except NameError : # Python 3.x
basestring = str
'''
if isinstance ( str_exc , str ) :
if each_error_string in str_exc :
print ( ' quit bot by error: ' , each_error_string )
driver . quit ( )
sys . exit ( )
break
# not is above case, print exception.
print ( " Exception: " , str_exc )
pass
if url is None :
continue
else :
if len ( url ) == 0 :
continue
# 說明:輸出目前網址,覺得吵的話,請註解掉這行。
#print("url:", url)
if len ( url ) > 0 :
if url != last_url :
print ( url )
last_url = url
tixcraft_family = False
if ' tixcraft.com ' in url :
tixcraft_family = True
if ' indievox.com ' in url :
tixcraft_family = True
if tixcraft_family :
2023-02-22 16:05:44 +00:00
tixcraft_dict = tixcraft_main ( driver , url , config_dict , tixcraft_dict , ocr , Captcha_Browser )
2023-01-23 20:36:06 +00:00
# for kktix.cc and kktix.com
if ' kktix.c ' in url :
2023-02-22 16:05:44 +00:00
kktix_dict = kktix_main ( driver , url , config_dict , kktix_dict )
2023-01-23 20:36:06 +00:00
if ' famiticket.com ' in url :
famiticket_main ( driver , url , config_dict )
if ' ibon.com ' in url :
2023-02-22 16:05:44 +00:00
ibon_dict = ibon_main ( driver , url , config_dict , ibon_dict )
2023-01-23 20:36:06 +00:00
if ' kham.com ' in url :
kham_main ( driver , url , config_dict , ocr , Captcha_Browser )
2023-01-23 13:32:47 +00:00
if ' urbtix.hk ' in url :
urbtix_main ( driver , url , config_dict )
if ' cityline.com ' in url :
cityline_main ( driver , url , config_dict )
if ' hkticketing.com ' in url :
hkticketing_main ( driver , url , config_dict )
2022-11-16 15:43:53 +00:00
2023-01-29 18:14:55 +00:00
if ' galaxymacau.com ' in url :
hkticketing_main ( driver , url , config_dict )
2023-01-23 20:36:06 +00:00
2022-11-16 15:43:53 +00:00
# for facebook
facebook_login_url = ' https://www.facebook.com/login.php? '
if url [ : len ( facebook_login_url ) ] == facebook_login_url :
facebook_account = config_dict [ " advanced " ] [ " facebook_account " ] . strip ( )
if len ( facebook_account ) > 4 :
2023-02-11 05:36:27 +00:00
facebook_login ( driver , facebook_account , decryptMe ( config_dict [ " advanced " ] [ " facebook_password " ] ) )
2022-11-06 09:10:35 +00:00
2023-02-23 13:33:49 +00:00
def cli ( ) :
parser = argparse . ArgumentParser (
description = " resize image to new width " )
parser . add_argument ( " --input " ,
help = " config file path " ,
type = str )
parser . add_argument ( " --homepage " ,
help = " overwrite homepage setting " ,
type = str )
parser . add_argument ( " --tixcraft_sid " ,
help = " overwrite tixcraft sid field " ,
type = str )
parser . add_argument ( " --kktix_account " ,
help = " overwrite kktix_account field " ,
type = str )
parser . add_argument ( " --kktix_password " ,
help = " overwrite kktix_password field " ,
type = str )
2023-02-26 08:39:37 +00:00
parser . add_argument ( " --ibonqware " ,
help = " overwrite ibonqware field " ,
type = str )
2023-02-23 13:33:49 +00:00
parser . add_argument ( " --headless " ,
help = " headless mode " ,
default = ' False ' ,
type = str )
parser . add_argument ( " --browser " ,
help = " overwrite browser setting " ,
default = ' ' ,
choices = [ ' chrome ' , ' firefox ' , ' edge ' , ' safari ' ] ,
type = str )
args = parser . parse_args ( )
main ( args )
2021-12-24 10:52:37 +00:00
if __name__ == " __main__ " :
2023-01-03 18:54:42 +00:00
CONST_MODE_GUI = 0
CONST_MODE_CLI = 1
mode = CONST_MODE_GUI
#mode = CONST_MODE_CLI
2023-02-19 04:16:31 +00:00
2023-01-03 18:54:42 +00:00
if mode == CONST_MODE_GUI :
2023-02-23 13:33:49 +00:00
cli ( )
2023-01-03 18:54:42 +00:00
else :
#for test kktix infer answer.
2023-02-04 16:23:01 +00:00
captcha_text_div_text = u " 請回答下列問題,請在下方空格輸入DELIGHT( 請以半形輸入法作答, 大小寫需要一模一樣) "
2023-01-03 18:54:42 +00:00
#captcha_text_div_text = u"請在下方空白處輸入引號內文字: 「abc」"
#captcha_text_div_text = u"請在下方空白處輸入引號內文字: 「0118eveconcert」( 請以半形小寫作答。) "
#captcha_text_div_text = "在《DEEP AWAKENING見過深淵的人》專輯中, 哪一首為合唱曲目? 【V6】深淵 、【Z5】浮木、【J8】無聲、【C1】以上皆非 (請以半形輸入法作答,大小寫/阿拉伯數字需要一模一樣, 範例: A2) "
2023-02-04 16:23:01 +00:00
#captcha_text_div_text = "Super Junior 的隊長是以下哪位? 【v】神童 【w】藝聲 【x】利特 【y】始源 若你覺得答案為 a, 請輸入 a (英文為半形小寫)"
#captcha_text_div_text = "請問XXX, 請以英文為半形小寫(例如: a) a. 1月5日 b. 2月5日 c. 3月5日 d. 4月5日"
2023-02-04 21:56:58 +00:00
#captcha_text_div_text = "以下為選擇題:請問 「OHM NANON 1st Fan Meeting in Hong Kong」 舉行日期是?請以半形細楷英文於下方輸入答案 (例如: a) a. 1月5日 b. 2月5日 c. 3月5日 d. 4月5日"
2023-02-04 16:23:01 +00:00
#captcha_text_div_text = "以下哪個「不是」正確的林俊傑與其他藝人合唱的歌曲組合?(選項為歌名/合作藝人 ,請以半形輸入法作答選項,大小寫需要一模一樣,範例:jju) 選項: (jja)小酒窩/A-Sa蔡卓妍 (jjb)被風吹過的夏天/金莎 (jjc)友人說/張懷秋 (jjd)全面開戰/五月天阿信 (jje)小說/阿杜"
#captcha_text_div_text = "請問《龍的傳人2060》演唱會是以下哪位藝人的演出? ( 請以半形輸入法作答, 大小寫需要一模一樣, 範例: B2) A1.周杰倫 B2.林俊傑 C3.張學友 D4.王力宏"
#captcha_text_div_text = "王力宏何時發行第一張專輯?(請以半形輸入法作答,大小寫需要一模一樣,範例:B2) A1.1985 B2.2005 C3.2015 D4.1995"
#captcha_text_div_text = "朴寶劍三月以歌手出道的日期和單曲名為? Answer the single’ s name & the debut date. *以半形輸入,大小寫/符號須都相同。例:(E1) Please use the same format given in the options.ex:(E1) (A1)20/Bloomin'(B1)2/Blossom(C1)2/Bloomin'(D1)20/Blossom"
#captcha_text_div_text = "以下哪位不是LOVELYZ成員? (請以半形輸入選項內的英文及數字,大小寫須符合),範例:E5e。 (A1a)智愛 (B2b)美珠 (C3c)JON (D4d)叡仁"
#captcha_text_div_text = "題請問此次 RAVI的SOLO專輯名稱為?(請以半形輸入法作答,大小寫需要一模一樣,範例:Tt) Aa [ BOOK] 、 Bb [OOK BOOK.R] 、 Cc [R.OOK BOOK] 、 Dd [OOK R. BOOK]"
2023-02-04 21:56:58 +00:00
#captcha_text_div_text = "請問下列哪個選項皆為河成雲的創作歌曲? Aa) Don’ t Forget、Candle Bb) Don’ t Forget、Forever+1 Cc) Don’ t Forget、Flowerbomb Dd) Don’ t Forget、One Love 請以半形輸入,大小寫含括號需一模一樣 【範例:答案為B需填入Bb)】"
2023-02-12 09:49:55 +00:00
captcha_text_div_text = " 魏如萱得過什麼獎?(1) 金馬獎 最佳女主角(2) 金鐘獎 戲劇節目女主角(3) 金曲獎 最佳華語女歌手(4) 走鐘獎 好好聽音樂獎 (請輸入半形數字) "
2023-01-03 18:54:42 +00:00
inferred_answer_string , answer_list = get_answer_list_from_question_string ( None , captcha_text_div_text )
print ( " inferred_answer_string: " , inferred_answer_string )
print ( " answer_list: " , answer_list )
2023-01-11 13:58:55 +00:00
2023-01-12 22:29:58 +00:00
ocr = ddddocr . DdddOcr ( show_ad = False , beta = True )
2023-02-04 16:23:01 +00:00
image_file = ' captcha-xxxx.png '
if os . path . exists ( image_file ) :
with open ( image_file , ' rb ' ) as f :
image_bytes = f . read ( )
res = ocr . classification ( image_bytes )
print ( res )
2023-01-11 13:58:55 +00:00