2023-06-17, online dictionary support json format, ibon support dictionary anwser feature.
parent
e090be7d29
commit
57535ea7a1
|
@ -53,7 +53,7 @@ import webbrowser
|
||||||
import argparse
|
import argparse
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
CONST_APP_VERSION = "MaxBot (2023.6.16)"
|
CONST_APP_VERSION = "MaxBot (2023.6.17)"
|
||||||
|
|
||||||
CONST_MAXBOT_CONFIG_FILE = "settings.json"
|
CONST_MAXBOT_CONFIG_FILE = "settings.json"
|
||||||
CONST_MAXBOT_LAST_URL_FILE = "MAXBOT_LAST_URL.txt"
|
CONST_MAXBOT_LAST_URL_FILE = "MAXBOT_LAST_URL.txt"
|
||||||
|
@ -197,7 +197,6 @@ def get_config_dict(args):
|
||||||
return config_dict
|
return config_dict
|
||||||
|
|
||||||
def write_question_to_file(question_text):
|
def write_question_to_file(question_text):
|
||||||
print("write_question_to_file:", question_text)
|
|
||||||
with open(CONST_MAXBOT_QUESTION_FILE, "w") as text_file:
|
with open(CONST_MAXBOT_QUESTION_FILE, "w") as text_file:
|
||||||
text_file.write("%s" % question_text)
|
text_file.write("%s" % question_text)
|
||||||
|
|
||||||
|
@ -1379,7 +1378,7 @@ def get_answer_list_by_question(CONST_EXAMPLE_SYMBOL, CONST_INPUT_SYMBOL, captch
|
||||||
|
|
||||||
return return_list
|
return return_list
|
||||||
|
|
||||||
def force_press_button(driver, select_by, select_query, force_by_js=True):
|
def force_press_button(driver, select_by, select_query, force_submit=True):
|
||||||
ret = False
|
ret = False
|
||||||
next_step_button = None
|
next_step_button = None
|
||||||
try:
|
try:
|
||||||
|
@ -1393,7 +1392,7 @@ def force_press_button(driver, select_by, select_query, force_by_js=True):
|
||||||
#print(exc)
|
#print(exc)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if force_by_js:
|
if force_submit:
|
||||||
if not next_step_button is None:
|
if not next_step_button is None:
|
||||||
is_visible = False
|
is_visible = False
|
||||||
try:
|
try:
|
||||||
|
@ -2269,13 +2268,7 @@ def tixcraft_ticket_number_auto_fill(driver, select_obj, ticket_number):
|
||||||
|
|
||||||
return is_ticket_number_assigned
|
return is_ticket_number_assigned
|
||||||
|
|
||||||
def guess_tixcraft_question(driver):
|
def get_tixcraft_question_text(driver):
|
||||||
show_debug_message = True # debug.
|
|
||||||
show_debug_message = False # online
|
|
||||||
|
|
||||||
inferred_answer_string = None
|
|
||||||
answer_list = []
|
|
||||||
|
|
||||||
form_select = None
|
form_select = None
|
||||||
try:
|
try:
|
||||||
form_select = driver.find_element(By.CSS_SELECTOR, '.zone-verify')
|
form_select = driver.find_element(By.CSS_SELECTOR, '.zone-verify')
|
||||||
|
@ -2283,17 +2276,27 @@ def guess_tixcraft_question(driver):
|
||||||
print("find verify textbox fail")
|
print("find verify textbox fail")
|
||||||
pass
|
pass
|
||||||
|
|
||||||
question_text = None
|
question_text = ""
|
||||||
if form_select is not None:
|
if form_select is not None:
|
||||||
try:
|
try:
|
||||||
question_text = form_select.text
|
question_text = form_select.text
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print("get text fail")
|
print("get text fail")
|
||||||
|
|
||||||
|
if question_text is None:
|
||||||
|
question_text = ""
|
||||||
|
|
||||||
|
return question_text
|
||||||
|
|
||||||
|
def guess_tixcraft_question(driver, question_text):
|
||||||
|
show_debug_message = True # debug.
|
||||||
|
show_debug_message = False # online
|
||||||
|
|
||||||
|
inferred_answer_string = None
|
||||||
|
answer_list = []
|
||||||
|
|
||||||
formated_html_text = ""
|
formated_html_text = ""
|
||||||
if question_text is not None:
|
|
||||||
if len(question_text) > 0:
|
if len(question_text) > 0:
|
||||||
write_question_to_file(question_text)
|
|
||||||
# format question text.
|
# format question text.
|
||||||
formated_html_text = question_text
|
formated_html_text = question_text
|
||||||
formated_html_text = formated_html_text.replace(u'「',u'【')
|
formated_html_text = formated_html_text.replace(u'「',u'【')
|
||||||
|
@ -2316,8 +2319,6 @@ def guess_tixcraft_question(driver):
|
||||||
if show_debug_message:
|
if show_debug_message:
|
||||||
print("formated_html_text:", formated_html_text)
|
print("formated_html_text:", formated_html_text)
|
||||||
|
|
||||||
is_options_in_question = False
|
|
||||||
|
|
||||||
# 請輸入"YES",代表您已詳閱且瞭解並同意。
|
# 請輸入"YES",代表您已詳閱且瞭解並同意。
|
||||||
if inferred_answer_string is None:
|
if inferred_answer_string is None:
|
||||||
if u'輸入"YES"' in formated_html_text:
|
if u'輸入"YES"' in formated_html_text:
|
||||||
|
@ -2332,13 +2333,99 @@ def guess_tixcraft_question(driver):
|
||||||
if '輸入【同意】' in formated_html_text:
|
if '輸入【同意】' in formated_html_text:
|
||||||
inferred_answer_string = '同意'
|
inferred_answer_string = '同意'
|
||||||
|
|
||||||
if inferred_answer_string is None:
|
if len(question_text) > 0:
|
||||||
if not question_text is None:
|
|
||||||
inferred_answer_string, answer_list = get_answer_list_from_question_string(None, question_text)
|
inferred_answer_string, answer_list = get_answer_list_from_question_string(None, question_text)
|
||||||
|
|
||||||
return inferred_answer_string, answer_list
|
return inferred_answer_string, answer_list
|
||||||
|
|
||||||
def tixcraft_verify(driver, config_dict, answer_index):
|
def fill_common_verify_form(driver, config_dict, inferred_answer_string, fail_list, input_text_css, next_step_button_css, submit_by_enter):
|
||||||
|
show_debug_message = True # debug.
|
||||||
|
show_debug_message = False # online
|
||||||
|
|
||||||
|
if config_dict["advanced"]["verbose"]:
|
||||||
|
show_debug_message = True
|
||||||
|
|
||||||
|
form_input_list = []
|
||||||
|
try:
|
||||||
|
form_input_list = driver.find_elements(By.CSS_SELECTOR, input_text_css)
|
||||||
|
except Exception as exc:
|
||||||
|
if show_debug_message:
|
||||||
|
print("find verify code input textbox fail")
|
||||||
|
pass
|
||||||
|
if form_input_list is None:
|
||||||
|
form_input_list = []
|
||||||
|
|
||||||
|
form_input_count = len(form_input_list)
|
||||||
|
if show_debug_message:
|
||||||
|
print("input textbox count:", form_input_count)
|
||||||
|
|
||||||
|
is_do_press_next_button = False
|
||||||
|
|
||||||
|
form_input = None
|
||||||
|
if form_input_count > 0:
|
||||||
|
form_input = form_input_list[0]
|
||||||
|
|
||||||
|
if form_input_count == 1:
|
||||||
|
is_do_press_next_button = True
|
||||||
|
|
||||||
|
inputed_value = None
|
||||||
|
if form_input is not None:
|
||||||
|
try:
|
||||||
|
inputed_value = form_input.get_attribute('value')
|
||||||
|
except Exception as exc:
|
||||||
|
if show_debug_message:
|
||||||
|
print("get_attribute of verify code fail")
|
||||||
|
pass
|
||||||
|
|
||||||
|
if inputed_value is None:
|
||||||
|
inputed_value = ""
|
||||||
|
|
||||||
|
is_answer_sent = False
|
||||||
|
if form_input is not None:
|
||||||
|
if len(inferred_answer_string) > 0:
|
||||||
|
try:
|
||||||
|
# PS: sometime may send key twice...
|
||||||
|
form_input.clear()
|
||||||
|
form_input.send_keys(inferred_answer_string)
|
||||||
|
is_button_clicked = False
|
||||||
|
if is_do_press_next_button:
|
||||||
|
if submit_by_enter:
|
||||||
|
form_input.send_keys(Keys.ENTER)
|
||||||
|
is_button_clicked = True
|
||||||
|
if len(next_step_button_css) > 0:
|
||||||
|
is_button_clicked = force_press_button(driver, By.CSS_SELECTOR, next_step_button_css)
|
||||||
|
|
||||||
|
if is_button_clicked:
|
||||||
|
is_answer_sent = True
|
||||||
|
fail_list.append(inferred_answer_string)
|
||||||
|
if show_debug_message:
|
||||||
|
print("sent password by bot:", inferred_answer_string, " at #", len(fail_list))
|
||||||
|
except Exception as exc:
|
||||||
|
if show_debug_message:
|
||||||
|
print(exc)
|
||||||
|
pass
|
||||||
|
|
||||||
|
if is_answer_sent:
|
||||||
|
for i in range(3):
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
alert_ret = check_pop_alert(driver)
|
||||||
|
if alert_ret:
|
||||||
|
if show_debug_message:
|
||||||
|
print("press accept button at time #", i+1)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# no answer to fill.
|
||||||
|
if len(inputed_value)==0:
|
||||||
|
try:
|
||||||
|
form_input.click()
|
||||||
|
time.sleep(0.1)
|
||||||
|
except Exception as exc:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return is_answer_sent, fail_list
|
||||||
|
|
||||||
|
def tixcraft_verify(driver, config_dict, fail_list):
|
||||||
show_debug_message = True # debug.
|
show_debug_message = True # debug.
|
||||||
show_debug_message = False # online
|
show_debug_message = False # online
|
||||||
|
|
||||||
|
@ -2348,7 +2435,8 @@ def tixcraft_verify(driver, config_dict, answer_index):
|
||||||
inferred_answer_string = ""
|
inferred_answer_string = ""
|
||||||
answer_list = []
|
answer_list = []
|
||||||
|
|
||||||
is_retry_user_single_answer = False
|
question_text = get_tixcraft_question_text(driver)
|
||||||
|
write_question_to_file(question_text)
|
||||||
|
|
||||||
presale_code = config_dict["advanced"]["user_guess_string"]
|
presale_code = config_dict["advanced"]["user_guess_string"]
|
||||||
|
|
||||||
|
@ -2366,110 +2454,27 @@ def tixcraft_verify(driver, config_dict, answer_index):
|
||||||
answer_list = json.loads("["+ presale_code +"]")
|
answer_list = json.loads("["+ presale_code +"]")
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
answer_list = []
|
answer_list = []
|
||||||
if len(answer_list) > 0:
|
|
||||||
if answer_index < len(answer_list)-1:
|
|
||||||
inferred_answer_string = answer_list[answer_index+1]
|
|
||||||
|
|
||||||
if inferred_answer_string is None:
|
if len(inferred_answer_string)==0:
|
||||||
if config_dict["advanced"]["auto_guess_options"]:
|
if config_dict["advanced"]["auto_guess_options"]:
|
||||||
inferred_answer_string, answer_list = guess_tixcraft_question(driver)
|
inferred_answer_string, answer_list = guess_tixcraft_question(driver, question_text)
|
||||||
if inferred_answer_string is None:
|
|
||||||
if not answer_list is None:
|
for answer_item in answer_list:
|
||||||
if len(answer_list) > 0:
|
if not answer_item in fail_list:
|
||||||
if answer_index < len(answer_list)-1:
|
inferred_answer_string = answer_item
|
||||||
inferred_answer_string = answer_list[answer_index+1]
|
break
|
||||||
|
|
||||||
if show_debug_message:
|
if show_debug_message:
|
||||||
print("answer_index:", answer_index)
|
print("answer_index:", answer_index)
|
||||||
print("inferred_answer_string:", inferred_answer_string)
|
print("inferred_answer_string:", inferred_answer_string)
|
||||||
print("answer_index:", answer_index)
|
print("answer_list:", answer_list)
|
||||||
print("is_retry_user_single_answer:", is_retry_user_single_answer)
|
|
||||||
|
|
||||||
form_input = None
|
input_text_css = "input[name='checkCode']"
|
||||||
try:
|
next_step_button_css = ""
|
||||||
form_input = driver.find_element(By.CSS_SELECTOR, "input[name='checkCode']")
|
submit_by_enter = True
|
||||||
except Exception as exc:
|
is_answer_sent, fail_list = fill_common_verify_form(driver, config_dict, inferred_answer_string, fail_list, input_text_css, next_step_button_css, submit_by_enter)
|
||||||
print("find verify code fail")
|
|
||||||
pass
|
|
||||||
|
|
||||||
inputed_value = None
|
return fail_list
|
||||||
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 not inferred_answer_string is None:
|
|
||||||
is_password_sent = False
|
|
||||||
if len(inputed_value)==0:
|
|
||||||
try:
|
|
||||||
# PS: sometime may send key twice...
|
|
||||||
form_input.clear()
|
|
||||||
form_input.send_keys(inferred_answer_string)
|
|
||||||
form_input.send_keys(Keys.ENTER)
|
|
||||||
is_password_sent = True
|
|
||||||
|
|
||||||
# guess answer mode.
|
|
||||||
answer_index += 1
|
|
||||||
|
|
||||||
if show_debug_message:
|
|
||||||
print("sent password by bot:", inferred_answer_string)
|
|
||||||
except Exception as exc:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if inputed_value == inferred_answer_string:
|
|
||||||
if show_debug_message:
|
|
||||||
print("sent password by previous time.")
|
|
||||||
is_password_sent = True
|
|
||||||
try:
|
|
||||||
form_input.send_keys(Keys.ENTER)
|
|
||||||
except Exception as exc:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if is_retry_user_single_answer:
|
|
||||||
# increase counter for waiting for stop retry.
|
|
||||||
answer_index += 1
|
|
||||||
else:
|
|
||||||
# guess answer mode.
|
|
||||||
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
|
|
||||||
if show_debug_message:
|
|
||||||
print("sent password by bot:", inferred_answer_string, "at index:", answer_index+2)
|
|
||||||
|
|
||||||
answer_index += 1
|
|
||||||
except Exception as exc:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if is_password_sent:
|
|
||||||
for i in range(3):
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
alert_ret = check_pop_alert(driver)
|
|
||||||
if alert_ret:
|
|
||||||
if show_debug_message:
|
|
||||||
print("press accept button at time #", i+1)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if len(inputed_value)==0:
|
|
||||||
try:
|
|
||||||
form_input.click()
|
|
||||||
except Exception as exc:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return answer_index
|
|
||||||
|
|
||||||
def tixcraft_change_captcha(driver,url):
|
def tixcraft_change_captcha(driver,url):
|
||||||
try:
|
try:
|
||||||
|
@ -6714,9 +6719,9 @@ def tixcraft_main(driver, url, config_dict, tixcraft_dict, ocr, Captcha_Browser)
|
||||||
|
|
||||||
|
|
||||||
if '/ticket/verify/' in url:
|
if '/ticket/verify/' in url:
|
||||||
tixcraft_dict["answer_index"] = tixcraft_verify(driver, config_dict, tixcraft_dict["answer_index"])
|
tixcraft_dict["fail_list"] = tixcraft_verify(driver, config_dict, tixcraft_dict["fail_list"])
|
||||||
else:
|
else:
|
||||||
tixcraft_dict["answer_index"] = -1
|
tixcraft_dict["fail_list"] = []
|
||||||
|
|
||||||
# main app, to select ticket number.
|
# main app, to select ticket number.
|
||||||
if '/ticket/ticket/' in url:
|
if '/ticket/ticket/' in url:
|
||||||
|
@ -7289,13 +7294,7 @@ def cityline_main(driver, url, config_dict):
|
||||||
if len(url.split('/'))>=5:
|
if len(url.split('/'))>=5:
|
||||||
cityline_shows_goto_cta(driver)
|
cityline_shows_goto_cta(driver)
|
||||||
|
|
||||||
def guess_ibon_question(driver):
|
def get_ibon_question_text(driver):
|
||||||
show_debug_message = True # debug.
|
|
||||||
show_debug_message = False # online
|
|
||||||
|
|
||||||
inferred_answer_string = None
|
|
||||||
answer_list = []
|
|
||||||
|
|
||||||
form_select = None
|
form_select = None
|
||||||
try:
|
try:
|
||||||
form_select = driver.find_element(By.CSS_SELECTOR, 'div.editor-box > div > div.form-group > label')
|
form_select = driver.find_element(By.CSS_SELECTOR, 'div.editor-box > div > div.form-group > label')
|
||||||
|
@ -7303,148 +7302,80 @@ def guess_ibon_question(driver):
|
||||||
print("find verify textbox fail")
|
print("find verify textbox fail")
|
||||||
pass
|
pass
|
||||||
|
|
||||||
question_text = None
|
question_text = ""
|
||||||
if form_select is not None:
|
if form_select is not None:
|
||||||
try:
|
try:
|
||||||
question_text = form_select.text
|
question_text = form_select.text
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print("get text fail")
|
print("get text fail")
|
||||||
|
|
||||||
is_options_in_question = False
|
if question_text is None:
|
||||||
|
question_text = ""
|
||||||
|
|
||||||
if inferred_answer_string is None:
|
return question_text
|
||||||
if not question_text is None:
|
|
||||||
|
def guess_ibon_question(driver, question_text):
|
||||||
|
show_debug_message = True # debug.
|
||||||
|
show_debug_message = False # online
|
||||||
|
|
||||||
|
inferred_answer_string = None
|
||||||
|
answer_list = []
|
||||||
|
|
||||||
|
if len(question_text) > 0:
|
||||||
inferred_answer_string, answer_list = get_answer_list_from_question_string(None, question_text)
|
inferred_answer_string, answer_list = get_answer_list_from_question_string(None, question_text)
|
||||||
|
|
||||||
return inferred_answer_string, answer_list
|
return inferred_answer_string, answer_list
|
||||||
|
|
||||||
def ibon_verification_question(driver, answer_index, config_dict):
|
def ibon_verification_question(driver, fail_list, config_dict):
|
||||||
show_debug_message = True # debug.
|
show_debug_message = True # debug.
|
||||||
show_debug_message = False # online
|
show_debug_message = False # online
|
||||||
|
|
||||||
if config_dict["advanced"]["verbose"]:
|
if config_dict["advanced"]["verbose"]:
|
||||||
show_debug_message = True
|
show_debug_message = True
|
||||||
|
|
||||||
presale_code = config_dict["tixcraft"]["presale_code"]
|
inferred_answer_string = ""
|
||||||
presale_code_delimiter = config_dict["tixcraft"]["presale_code_delimiter"]
|
|
||||||
|
|
||||||
inferred_answer_string = None
|
|
||||||
answer_list = []
|
answer_list = []
|
||||||
|
|
||||||
is_retry_user_single_answer = False
|
question_text = get_ibon_question_text(driver)
|
||||||
|
write_question_to_file(question_text)
|
||||||
|
|
||||||
|
presale_code = config_dict["advanced"]["user_guess_string"]
|
||||||
|
|
||||||
|
# load from internet.
|
||||||
|
if len(presale_code) == 0:
|
||||||
|
if len(config_dict["advanced"]["online_dictionary_url"]) > 0:
|
||||||
|
if os.path.exists(CONST_MAXBOT_ANSWER_ONLINE_FILE):
|
||||||
|
with open(CONST_MAXBOT_ANSWER_ONLINE_FILE, "r") as text_file:
|
||||||
|
presale_code = text_file.readline()
|
||||||
|
|
||||||
if len(presale_code) > 0:
|
if len(presale_code) > 0:
|
||||||
if len(presale_code_delimiter) > 0:
|
presale_code = format_config_keyword_for_json(presale_code)
|
||||||
if presale_code_delimiter in presale_code:
|
answer_list = []
|
||||||
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]
|
|
||||||
else:
|
|
||||||
is_retry_user_single_answer = True
|
|
||||||
if answer_index < 2:
|
|
||||||
inferred_answer_string = presale_code
|
|
||||||
|
|
||||||
if inferred_answer_string is None:
|
|
||||||
inferred_answer_string, answer_list = guess_ibon_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]
|
|
||||||
|
|
||||||
if show_debug_message:
|
|
||||||
print("answer_index:", answer_index)
|
|
||||||
print("inferred_answer_string:", inferred_answer_string)
|
|
||||||
print("answer_index:", answer_index)
|
|
||||||
print("is_retry_user_single_answer:", is_retry_user_single_answer)
|
|
||||||
|
|
||||||
form_input = None
|
|
||||||
try:
|
try:
|
||||||
form_input = driver.find_element(By.CSS_SELECTOR, 'div.editor-box > div > div.form-group > input')
|
answer_list = json.loads("["+ presale_code +"]")
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print("find verify code fail")
|
answer_list = []
|
||||||
pass
|
|
||||||
|
|
||||||
inputed_value = None
|
if len(inferred_answer_string)==0:
|
||||||
if form_input is not None:
|
if config_dict["advanced"]["auto_guess_options"]:
|
||||||
try:
|
inferred_answer_string, answer_list = guess_ibon_question(driver, question_text)
|
||||||
inputed_value = form_input.get_attribute('value')
|
|
||||||
except Exception as exc:
|
|
||||||
print("find verify code fail")
|
|
||||||
pass
|
|
||||||
|
|
||||||
if inputed_value is None:
|
for answer_item in answer_list:
|
||||||
inputed_value = ""
|
if not answer_item in fail_list:
|
||||||
|
inferred_answer_string = answer_item
|
||||||
if not inferred_answer_string is None:
|
|
||||||
is_password_sent = False
|
|
||||||
if len(inputed_value)==0:
|
|
||||||
try:
|
|
||||||
# PS: sometime may send key twice...
|
|
||||||
form_input.clear()
|
|
||||||
form_input.send_keys(inferred_answer_string)
|
|
||||||
is_button_clicked = force_press_button(driver, By.CSS_SELECTOR,'div.editor-box > div > div.form-group > a.btn')
|
|
||||||
if is_button_clicked:
|
|
||||||
is_password_sent = True
|
|
||||||
|
|
||||||
# guess answer mode.
|
|
||||||
answer_index += 1
|
|
||||||
|
|
||||||
if show_debug_message:
|
|
||||||
print("sent password by bot:", inferred_answer_string)
|
|
||||||
except Exception as exc:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if inputed_value == inferred_answer_string:
|
|
||||||
if show_debug_message:
|
|
||||||
print("sent password by previous time.")
|
|
||||||
is_password_sent = True
|
|
||||||
try:
|
|
||||||
form_input.send_keys(Keys.ENTER)
|
|
||||||
except Exception as exc:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if is_retry_user_single_answer:
|
|
||||||
# increase counter for waiting for stop retry.
|
|
||||||
answer_index += 1
|
|
||||||
else:
|
|
||||||
# guess answer mode.
|
|
||||||
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)
|
|
||||||
is_button_clicked = force_press_button(driver, By.CSS_SELECTOR,'div.editor-box > div > div.form-group > a.btn')
|
|
||||||
is_password_sent = True
|
|
||||||
if show_debug_message:
|
|
||||||
print("sent password by bot:", inferred_answer_string, "at index:", answer_index+2)
|
|
||||||
|
|
||||||
answer_index += 1
|
|
||||||
except Exception as exc:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if is_password_sent:
|
|
||||||
for i in range(3):
|
|
||||||
time.sleep(0.1)
|
|
||||||
|
|
||||||
alert_ret = check_pop_alert(driver)
|
|
||||||
if alert_ret:
|
|
||||||
if show_debug_message:
|
|
||||||
print("press accept button at time #", i+1)
|
|
||||||
break
|
break
|
||||||
else:
|
|
||||||
if len(inputed_value)==0:
|
|
||||||
try:
|
|
||||||
form_input.click()
|
|
||||||
except Exception as exc:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return answer_index
|
if show_debug_message:
|
||||||
|
print("inferred_answer_string:", inferred_answer_string)
|
||||||
|
print("answer_list:", answer_list)
|
||||||
|
print("fail_list:", fail_list)
|
||||||
|
|
||||||
|
input_text_css = 'div.editor-box > div > div.form-group > input'
|
||||||
|
next_step_button_css = 'div.editor-box > div > a.btn'
|
||||||
|
submit_by_enter = False
|
||||||
|
is_answer_sent, fail_list = fill_common_verify_form(driver, config_dict, inferred_answer_string, fail_list, input_text_css, next_step_button_css, submit_by_enter)
|
||||||
|
|
||||||
|
return fail_list
|
||||||
|
|
||||||
|
|
||||||
def ibon_ticket_agree(driver):
|
def ibon_ticket_agree(driver):
|
||||||
|
@ -7716,14 +7647,23 @@ def ibon_main(driver, url, config_dict, ibon_dict, ocr, Captcha_Browser):
|
||||||
is_match_target_feature = True
|
is_match_target_feature = True
|
||||||
is_date_assign_by_bot = ibon_date_auto_select(driver, config_dict)
|
is_date_assign_by_bot = ibon_date_auto_select(driver, config_dict)
|
||||||
|
|
||||||
|
if 'ibon.com.tw/error.html?' in url:
|
||||||
|
try:
|
||||||
|
driver.back()
|
||||||
|
except Exception as exc:
|
||||||
|
pass
|
||||||
|
|
||||||
|
is_enter_verify_mode = False
|
||||||
if not is_match_target_feature:
|
if not is_match_target_feature:
|
||||||
# validation question url:
|
# 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
|
# 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:
|
if '/application/UTK02/' in url and '.aspx?rn=' in url and '&PERFORMANCE_ID=' in url:
|
||||||
is_match_target_feature = True
|
is_match_target_feature = True
|
||||||
ibon_dict["answer_index"] = ibon_verification_question(driver, ibon_dict["answer_index"], config_dict)
|
is_enter_verify_mode = True
|
||||||
else:
|
ibon_dict["fail_list"] = ibon_verification_question(driver, ibon_dict["fail_list"], config_dict)
|
||||||
ibon_dict["answer_index"] = -1
|
|
||||||
|
if not is_enter_verify_mode:
|
||||||
|
ibon_dict["fail_list"] = []
|
||||||
|
|
||||||
if not is_match_target_feature:
|
if not is_match_target_feature:
|
||||||
# https://orders.ibon.com.tw/application/UTK02/UTK0201_000.aspx?PERFORMANCE_ID=0000
|
# https://orders.ibon.com.tw/application/UTK02/UTK0201_000.aspx?PERFORMANCE_ID=0000
|
||||||
|
@ -7783,8 +7723,12 @@ def ibon_main(driver, url, config_dict, ibon_dict, ocr, Captcha_Browser):
|
||||||
# plan-A
|
# plan-A
|
||||||
#is_button_clicked = force_press_button(driver, By.CSS_SELECTOR, 'a.btn.btn-primary')
|
#is_button_clicked = force_press_button(driver, By.CSS_SELECTOR, 'a.btn.btn-primary')
|
||||||
# plan-B, easy and better than plan-A
|
# plan-B, easy and better than plan-A
|
||||||
|
try:
|
||||||
driver.back()
|
driver.back()
|
||||||
driver.refresh()
|
driver.refresh()
|
||||||
|
except Exception as exc:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
if not is_match_target_feature:
|
if not is_match_target_feature:
|
||||||
#https://orders.ibon.com.tw/application/UTK02/UTK0206_.aspx
|
#https://orders.ibon.com.tw/application/UTK02/UTK0206_.aspx
|
||||||
|
@ -10483,7 +10427,7 @@ def main(args):
|
||||||
|
|
||||||
# for tixcraft
|
# for tixcraft
|
||||||
tixcraft_dict = {}
|
tixcraft_dict = {}
|
||||||
tixcraft_dict["answer_index"]=-1
|
tixcraft_dict["fail_list"]=[]
|
||||||
tixcraft_dict["is_popup_checkout"] = False
|
tixcraft_dict["is_popup_checkout"] = False
|
||||||
|
|
||||||
# for kktix
|
# for kktix
|
||||||
|
@ -10493,7 +10437,7 @@ def main(args):
|
||||||
kktix_dict["is_popup_checkout"] = False
|
kktix_dict["is_popup_checkout"] = False
|
||||||
|
|
||||||
ibon_dict = {}
|
ibon_dict = {}
|
||||||
ibon_dict["answer_index"]=-1
|
ibon_dict["fail_list"]=[]
|
||||||
|
|
||||||
hkticketing_dict = {}
|
hkticketing_dict = {}
|
||||||
hkticketing_dict["is_date_submiting"] = False
|
hkticketing_dict["is_date_submiting"] = False
|
||||||
|
|
|
@ -22,7 +22,7 @@ import base64
|
||||||
import threading
|
import threading
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
CONST_APP_VERSION = "MaxBot (2023.6.16)"
|
CONST_APP_VERSION = "MaxBot (2023.6.17)"
|
||||||
|
|
||||||
CONST_MAXBOT_LAUNCHER_FILE = "config_launcher.json"
|
CONST_MAXBOT_LAUNCHER_FILE = "config_launcher.json"
|
||||||
CONST_MAXBOT_CONFIG_FILE = "settings.json"
|
CONST_MAXBOT_CONFIG_FILE = "settings.json"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"homepage": "https://tixcraft.com", "browser": "chrome", "language": "English", "ticket_number": 2, "pass_1_seat_remaining": true, "auto_check_agree": true, "ocr_captcha": {"enable": true, "force_submit": true, "image_source": "canvas"}, "webdriver_type": "undetected_chromedriver", "kktix": {"auto_press_next_step_button": true, "auto_fill_ticket_number": true}, "tixcraft": {"date_auto_select": {"enable": true, "date_keyword": "", "mode": "from top to bottom"}, "pass_date_is_sold_out": true, "auto_reload_coming_soon_page": true}, "area_auto_select": {"enable": true, "mode": "from top to bottom", "area_keyword": "", "area_keyword_exclude": "\"\u8f2a\u6905\",\"\u8eab\u969c\",\"\u8eab\u5fc3 \u969c\u7919\""}, "advanced": {"play_captcha_sound": {"enable": true, "filename": "ding-dong.wav"}, "tixcraft_sid": "", "ibonqware": "", "facebook_account": "", "kktix_account": "", "cityline_account": "", "urbtix_account": "", "hkticketing_account": "", "kham_account": "", "facebook_password": "", "kktix_password": "", "cityline_password": "", "urbtix_password": "", "hkticketing_password": "", "kham_password": "", "adblock_plus_enable": false, "disable_adjacent_seat": false, "headless": false, "verbose": false, "auto_guess_options": false, "user_guess_string": "", "online_dictionary_url": "", "auto_reload_page_interval": 1.5, "auto_reload_random_delay": false}}
|
{"homepage": "https://tixcraft.com", "browser": "chrome", "language": "\u7e41\u9ad4\u4e2d\u6587", "ticket_number": 2, "pass_1_seat_remaining": true, "auto_check_agree": true, "ocr_captcha": {"enable": true, "force_submit": true, "image_source": "canvas"}, "webdriver_type": "undetected_chromedriver", "kktix": {"auto_press_next_step_button": true, "auto_fill_ticket_number": true}, "tixcraft": {"date_auto_select": {"enable": true, "date_keyword": "", "mode": "from top to bottom"}, "pass_date_is_sold_out": true, "auto_reload_coming_soon_page": true}, "area_auto_select": {"enable": true, "mode": "from top to bottom", "area_keyword": "", "area_keyword_exclude": "\"\u8f2a\u6905\",\"\u8eab\u969c\",\"\u8eab\u5fc3 \u969c\u7919\""}, "advanced": {"play_captcha_sound": {"enable": true, "filename": "ding-dong.wav"}, "tixcraft_sid": "", "ibonqware": "", "facebook_account": "", "kktix_account": "", "cityline_account": "", "urbtix_account": "", "hkticketing_account": "", "kham_account": "", "facebook_password": "", "kktix_password": "", "cityline_password": "", "urbtix_password": "", "hkticketing_password": "", "kham_password": "", "adblock_plus_enable": false, "disable_adjacent_seat": false, "headless": false, "verbose": false, "auto_guess_options": false, "user_guess_string": "", "online_dictionary_url": "", "auto_reload_page_interval": 1.5, "auto_reload_random_delay": false}}
|
42
settings.py
42
settings.py
|
@ -32,7 +32,7 @@ warnings.simplefilter('ignore',InsecureRequestWarning)
|
||||||
import ssl
|
import ssl
|
||||||
ssl._create_default_https_context = ssl._create_unverified_context
|
ssl._create_default_https_context = ssl._create_unverified_context
|
||||||
|
|
||||||
CONST_APP_VERSION = "MaxBot (2023.6.16)"
|
CONST_APP_VERSION = "MaxBot (2023.6.17)"
|
||||||
|
|
||||||
CONST_MAXBOT_CONFIG_FILE = "settings.json"
|
CONST_MAXBOT_CONFIG_FILE = "settings.json"
|
||||||
CONST_MAXBOT_LAST_URL_FILE = "MAXBOT_LAST_URL.txt"
|
CONST_MAXBOT_LAST_URL_FILE = "MAXBOT_LAST_URL.txt"
|
||||||
|
@ -468,9 +468,17 @@ def format_config_keyword_for_json(user_input):
|
||||||
if len(user_input) > 0:
|
if len(user_input) > 0:
|
||||||
if not ('\"' in user_input):
|
if not ('\"' in user_input):
|
||||||
user_input = '"' + user_input + '"'
|
user_input = '"' + user_input + '"'
|
||||||
|
|
||||||
if user_input[:1]=="{" and user_input[-1:]=="}":
|
if user_input[:1]=="{" and user_input[-1:]=="}":
|
||||||
user_input=user_input[1:]
|
tmp_json = {}
|
||||||
user_input=user_input[:-1]
|
try:
|
||||||
|
tmp_json = json.loads(user_input)
|
||||||
|
key=list(tmp_json.keys())[0]
|
||||||
|
first_item=tmp_json[key]
|
||||||
|
user_input=json.dumps(first_item)
|
||||||
|
except Exception as exc:
|
||||||
|
pass
|
||||||
|
|
||||||
if user_input[:1]=="[" and user_input[-1:]=="]":
|
if user_input[:1]=="[" and user_input[-1:]=="]":
|
||||||
user_input=user_input[1:]
|
user_input=user_input[1:]
|
||||||
user_input=user_input[:-1]
|
user_input=user_input[:-1]
|
||||||
|
@ -889,9 +897,18 @@ def show_preview_text():
|
||||||
answer_text = ""
|
answer_text = ""
|
||||||
with open(CONST_MAXBOT_ANSWER_ONLINE_FILE, "r") as text_file:
|
with open(CONST_MAXBOT_ANSWER_ONLINE_FILE, "r") as text_file:
|
||||||
answer_text = text_file.readline()
|
answer_text = text_file.readline()
|
||||||
|
|
||||||
|
answer_text = format_config_keyword_for_json(answer_text)
|
||||||
|
|
||||||
|
date_array = []
|
||||||
try:
|
try:
|
||||||
|
date_array = json.loads("["+ answer_text +"]")
|
||||||
|
except Exception as exc:
|
||||||
|
date_array = []
|
||||||
|
|
||||||
global lbl_online_dictionary_preview
|
global lbl_online_dictionary_preview
|
||||||
lbl_online_dictionary_preview.config(text=answer_text)
|
try:
|
||||||
|
lbl_online_dictionary_preview.config(text=','.join(date_array))
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -902,7 +919,7 @@ def save_url_to_file(new_online_dictionary_url, force_write = False):
|
||||||
headers = {"Accept-Language": "zh-TW,zh;q=0.5", 'User-Agent': user_agent}
|
headers = {"Accept-Language": "zh-TW,zh;q=0.5", 'User-Agent': user_agent}
|
||||||
html_result = None
|
html_result = None
|
||||||
try:
|
try:
|
||||||
html_result = requests.get(new_online_dictionary_url , headers=headers, timeout=0.7, allow_redirects=False)
|
html_result = requests.get(new_online_dictionary_url , headers=headers, timeout=0.5, allow_redirects=False)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
html_result = None
|
html_result = None
|
||||||
#print(exc)
|
#print(exc)
|
||||||
|
@ -911,6 +928,7 @@ def save_url_to_file(new_online_dictionary_url, force_write = False):
|
||||||
#print("status_code:", status_code)
|
#print("status_code:", status_code)
|
||||||
if status_code == 200:
|
if status_code == 200:
|
||||||
html_text = html_result.text
|
html_text = html_result.text
|
||||||
|
#print("html_text:", html_text)
|
||||||
|
|
||||||
is_write_to_file = False
|
is_write_to_file = False
|
||||||
if force_write:
|
if force_write:
|
||||||
|
@ -919,13 +937,18 @@ def save_url_to_file(new_online_dictionary_url, force_write = False):
|
||||||
is_write_to_file = True
|
is_write_to_file = True
|
||||||
|
|
||||||
if is_write_to_file:
|
if is_write_to_file:
|
||||||
|
html_text = format_config_keyword_for_json(html_text)
|
||||||
with open(CONST_MAXBOT_ANSWER_ONLINE_FILE, "w") as text_file:
|
with open(CONST_MAXBOT_ANSWER_ONLINE_FILE, "w") as text_file:
|
||||||
text_file.write("%s" % html_text)
|
text_file.write("%s" % html_text)
|
||||||
return is_write_to_file
|
return is_write_to_file
|
||||||
|
|
||||||
def btn_preview_text_clicked():
|
def btn_preview_text_clicked():
|
||||||
global txt_online_dictionary_url
|
global txt_online_dictionary_url
|
||||||
|
online_dictionary_url = ""
|
||||||
|
try:
|
||||||
online_dictionary_url = txt_online_dictionary_url.get("1.0",END).strip()
|
online_dictionary_url = txt_online_dictionary_url.get("1.0",END).strip()
|
||||||
|
except Exception as exc:
|
||||||
|
pass
|
||||||
online_dictionary_url = format_config_keyword_for_json(online_dictionary_url)
|
online_dictionary_url = format_config_keyword_for_json(online_dictionary_url)
|
||||||
if len(online_dictionary_url) > 0:
|
if len(online_dictionary_url) > 0:
|
||||||
url_array = []
|
url_array = []
|
||||||
|
@ -2146,11 +2169,15 @@ def AutofillTab(root, config_dict, language_code, UI_PADDING_X):
|
||||||
|
|
||||||
frame_group_header.grid(column=0, row=row_count, padx=UI_PADDING_X)
|
frame_group_header.grid(column=0, row=row_count, padx=UI_PADDING_X)
|
||||||
|
|
||||||
|
def resetful_api_timer():
|
||||||
|
while True:
|
||||||
|
btn_preview_text_clicked()
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
||||||
def settings_timer():
|
def settings_timer():
|
||||||
while True:
|
while True:
|
||||||
update_maxbot_runtime_status()
|
update_maxbot_runtime_status()
|
||||||
btn_preview_text_clicked()
|
time.sleep(0.6)
|
||||||
time.sleep(0.2)
|
|
||||||
|
|
||||||
def update_maxbot_runtime_status():
|
def update_maxbot_runtime_status():
|
||||||
is_paused = False
|
is_paused = False
|
||||||
|
@ -2472,5 +2499,6 @@ def clean_tmp_file():
|
||||||
force_remove_file(filepath)
|
force_remove_file(filepath)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
threading.Thread(target=resetful_api_timer, daemon=True).start()
|
||||||
clean_tmp_file()
|
clean_tmp_file()
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -27,7 +27,7 @@ import asyncio
|
||||||
import tornado
|
import tornado
|
||||||
from tornado.web import Application
|
from tornado.web import Application
|
||||||
|
|
||||||
CONST_APP_VERSION = "MaxBot (2023.6.16)"
|
CONST_APP_VERSION = "MaxBot (2023.6.17)"
|
||||||
|
|
||||||
CONST_MAXBOT_QUESTION_FILE = "MAXBOT_QUESTION.txt"
|
CONST_MAXBOT_QUESTION_FILE = "MAXBOT_QUESTION.txt"
|
||||||
|
|
||||||
|
@ -51,6 +51,9 @@ def btn_copy_question_clicked():
|
||||||
question_text = txt_question.get("1.0",END).strip()
|
question_text = txt_question.get("1.0",END).strip()
|
||||||
pyperclip.copy(question_text)
|
pyperclip.copy(question_text)
|
||||||
|
|
||||||
|
def btn_paste_answer_by_user():
|
||||||
|
print("btn_paste_answer_by_user")
|
||||||
|
|
||||||
def TextInput(root, UI_PADDING_X):
|
def TextInput(root, UI_PADDING_X):
|
||||||
row_count = 0
|
row_count = 0
|
||||||
|
|
||||||
|
@ -97,11 +100,12 @@ def TextInput(root, UI_PADDING_X):
|
||||||
lbl_answer = Label(frame_group_header, text="Answer")
|
lbl_answer = Label(frame_group_header, text="Answer")
|
||||||
lbl_answer.grid(column=0, row=group_row_count, sticky = E)
|
lbl_answer.grid(column=0, row=group_row_count, sticky = E)
|
||||||
|
|
||||||
global txt_keyword
|
global txt_answer
|
||||||
txt_keyword_value = StringVar(frame_group_header, value="")
|
global txt_answer_value
|
||||||
txt_keyword = Entry(frame_group_header, width=30, textvariable = txt_keyword_value)
|
txt_answer_value = StringVar(frame_group_header, value="")
|
||||||
txt_keyword.grid(column=1, row=group_row_count, sticky = W)
|
txt_answer = Entry(frame_group_header, width=30, textvariable = txt_answer_value)
|
||||||
|
txt_answer.grid(column=1, row=group_row_count, sticky = W)
|
||||||
|
txt_answer.bind('<Control-v>', lambda e: btn_paste_answer_by_user())
|
||||||
|
|
||||||
frame_group_header.grid(column=0, row=row_count, padx=UI_PADDING_X, pady=15)
|
frame_group_header.grid(column=0, row=row_count, padx=UI_PADDING_X, pady=15)
|
||||||
|
|
||||||
|
@ -155,10 +159,28 @@ def main_ui():
|
||||||
|
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
|
|
||||||
|
|
||||||
class MainHandler(tornado.web.RequestHandler):
|
class MainHandler(tornado.web.RequestHandler):
|
||||||
|
def format_config_keyword_for_json(self, user_input):
|
||||||
|
if len(user_input) > 0:
|
||||||
|
if not ('\"' in user_input):
|
||||||
|
user_input = '"' + user_input + '"'
|
||||||
|
return user_input
|
||||||
|
|
||||||
|
def compose_as_json(self, user_input):
|
||||||
|
user_input = self.format_config_keyword_for_json(user_input)
|
||||||
|
return "{\"data\":[%s]}" % user_input
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
global txt_keyword
|
global txt_answer_value
|
||||||
self.write(txt_keyword.get().strip())
|
answer_text = ""
|
||||||
|
try:
|
||||||
|
answer_text = txt_answer_value.get().strip()
|
||||||
|
except Exception as exc:
|
||||||
|
pass
|
||||||
|
answer_text_output = self.compose_as_json(answer_text)
|
||||||
|
#print("answer_text_output:", answer_text_output)
|
||||||
|
self.write(answer_text_output)
|
||||||
|
|
||||||
class QuestionHandler(tornado.web.RequestHandler):
|
class QuestionHandler(tornado.web.RequestHandler):
|
||||||
def get(self):
|
def get(self):
|
||||||
|
@ -183,12 +205,13 @@ def preview_question_text_file():
|
||||||
with open(CONST_MAXBOT_QUESTION_FILE, "r") as text_file:
|
with open(CONST_MAXBOT_QUESTION_FILE, "r") as text_file:
|
||||||
question_text = text_file.readline()
|
question_text = text_file.readline()
|
||||||
|
|
||||||
try:
|
|
||||||
global txt_question
|
global txt_question
|
||||||
inputed_question_text = txt_question.get("1.0",END).strip()
|
try:
|
||||||
if inputed_question_text != question_text:
|
displayed_question_text = txt_question.get("1.0",END).strip()
|
||||||
|
if displayed_question_text != question_text:
|
||||||
# start to refresh
|
# start to refresh
|
||||||
txt_question.delete("1.0","end")
|
txt_question.delete("1.0","end")
|
||||||
|
if len(question_text) > 0:
|
||||||
txt_question.insert("1.0", question_text)
|
txt_question.insert("1.0", question_text)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
pass
|
pass
|
||||||
|
|
Loading…
Reference in New Issue