From 57535ea7a1b968f8459a513389ed1654a92b2924 Mon Sep 17 00:00:00 2001 From: CHUN YU YAO Date: Sat, 17 Jun 2023 00:04:55 +0800 Subject: [PATCH] 2023-06-17, online dictionary support json format, ibon support dictionary anwser feature. --- chrome_tixcraft.py | 478 ++++++++++++++++++++------------------------- config_launcher.py | 2 +- settings.json | 2 +- settings.py | 46 ++++- text_server.py | 47 +++-- 5 files changed, 285 insertions(+), 290 deletions(-) diff --git a/chrome_tixcraft.py b/chrome_tixcraft.py index d2e3831..5cac089 100644 --- a/chrome_tixcraft.py +++ b/chrome_tixcraft.py @@ -53,7 +53,7 @@ import webbrowser import argparse import itertools -CONST_APP_VERSION = "MaxBot (2023.6.16)" +CONST_APP_VERSION = "MaxBot (2023.6.17)" CONST_MAXBOT_CONFIG_FILE = "settings.json" CONST_MAXBOT_LAST_URL_FILE = "MAXBOT_LAST_URL.txt" @@ -197,7 +197,6 @@ def get_config_dict(args): return config_dict def write_question_to_file(question_text): - print("write_question_to_file:", question_text) with open(CONST_MAXBOT_QUESTION_FILE, "w") as text_file: 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 -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 next_step_button = None try: @@ -1393,7 +1392,7 @@ def force_press_button(driver, select_by, select_query, force_by_js=True): #print(exc) pass - if force_by_js: + if force_submit: if not next_step_button is None: is_visible = False try: @@ -2269,13 +2268,7 @@ def tixcraft_ticket_number_auto_fill(driver, select_obj, ticket_number): return is_ticket_number_assigned -def guess_tixcraft_question(driver): - show_debug_message = True # debug. - show_debug_message = False # online - - inferred_answer_string = None - answer_list = [] - +def get_tixcraft_question_text(driver): form_select = None try: form_select = driver.find_element(By.CSS_SELECTOR, '.zone-verify') @@ -2283,41 +2276,49 @@ def guess_tixcraft_question(driver): print("find verify textbox fail") pass - question_text = None + question_text = "" if form_select is not None: try: question_text = form_select.text except Exception as exc: 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 = "" - if question_text is not None: - if len(question_text) > 0: - write_question_to_file(question_text) - # format 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'【') - 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 len(question_text) > 0: + # format 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'【') + 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'】') + 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: - # PS: 這個太容易沖突,因為問題類型太多,不能直接使用。 - #inferred_answer_string = find_between(formated_html_text, u"【", u"】") - pass + if u'【' in formated_html_text and u'】' in formated_html_text: + # PS: 這個太容易沖突,因為問題類型太多,不能直接使用。 + #inferred_answer_string = find_between(formated_html_text, u"【", u"】") + pass if show_debug_message: print("formated_html_text:", formated_html_text) - is_options_in_question = False - # 請輸入"YES",代表您已詳閱且瞭解並同意。 if inferred_answer_string is None: if u'輸入"YES"' in formated_html_text: @@ -2332,13 +2333,99 @@ def guess_tixcraft_question(driver): if '輸入【同意】' in formated_html_text: inferred_answer_string = '同意' - if inferred_answer_string is None: - if not question_text is None: - inferred_answer_string, answer_list = get_answer_list_from_question_string(None, question_text) + if len(question_text) > 0: + inferred_answer_string, answer_list = get_answer_list_from_question_string(None, question_text) 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 = False # online @@ -2348,7 +2435,8 @@ def tixcraft_verify(driver, config_dict, answer_index): inferred_answer_string = "" 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"] @@ -2366,110 +2454,27 @@ def tixcraft_verify(driver, config_dict, answer_index): answer_list = json.loads("["+ presale_code +"]") except Exception as exc: 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"]: - 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] + inferred_answer_string, answer_list = guess_tixcraft_question(driver, question_text) + + for answer_item in answer_list: + if not answer_item in fail_list: + inferred_answer_string = answer_item + break 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) + print("answer_list:", answer_list) - form_input = None - try: - form_input = driver.find_element(By.CSS_SELECTOR, "input[name='checkCode']") - except Exception as exc: - print("find verify code fail") - pass + input_text_css = "input[name='checkCode']" + next_step_button_css = "" + submit_by_enter = True + 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) - 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 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 + return fail_list def tixcraft_change_captcha(driver,url): try: @@ -6714,9 +6719,9 @@ def tixcraft_main(driver, url, config_dict, tixcraft_dict, ocr, Captcha_Browser) 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: - tixcraft_dict["answer_index"] = -1 + tixcraft_dict["fail_list"] = [] # main app, to select ticket number. if '/ticket/ticket/' in url: @@ -7289,13 +7294,7 @@ def cityline_main(driver, url, config_dict): if len(url.split('/'))>=5: cityline_shows_goto_cta(driver) -def guess_ibon_question(driver): - show_debug_message = True # debug. - show_debug_message = False # online - - inferred_answer_string = None - answer_list = [] - +def get_ibon_question_text(driver): form_select = None try: 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") pass - question_text = None + question_text = "" if form_select is not None: try: question_text = form_select.text except Exception as exc: print("get text fail") - is_options_in_question = False + if question_text is None: + question_text = "" - if inferred_answer_string is None: - if not question_text is None: - inferred_answer_string, answer_list = get_answer_list_from_question_string(None, question_text) + return question_text + +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) 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 = False # online if config_dict["advanced"]["verbose"]: show_debug_message = True - presale_code = config_dict["tixcraft"]["presale_code"] - presale_code_delimiter = config_dict["tixcraft"]["presale_code_delimiter"] - - inferred_answer_string = None + inferred_answer_string = "" 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_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] - else: - is_retry_user_single_answer = True - if answer_index < 2: - inferred_answer_string = presale_code + presale_code = format_config_keyword_for_json(presale_code) + answer_list = [] + try: + answer_list = json.loads("["+ presale_code +"]") + except Exception as exc: + answer_list = [] - 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 len(inferred_answer_string)==0: + if config_dict["advanced"]["auto_guess_options"]: + inferred_answer_string, answer_list = guess_ibon_question(driver, question_text) + + for answer_item in answer_list: + if not answer_item in fail_list: + inferred_answer_string = answer_item + break 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) + print("answer_list:", answer_list) + print("fail_list:", fail_list) - form_input = None - try: - form_input = driver.find_element(By.CSS_SELECTOR, 'div.editor-box > div > div.form-group > input') - except Exception as exc: - print("find verify code fail") - pass + 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) - 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 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 - else: - if len(inputed_value)==0: - try: - form_input.click() - except Exception as exc: - pass - - return answer_index + return fail_list 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_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: # 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: + if '/application/UTK02/' in url and '.aspx?rn=' in url and '&PERFORMANCE_ID=' in url: is_match_target_feature = True - ibon_dict["answer_index"] = ibon_verification_question(driver, ibon_dict["answer_index"], config_dict) - else: - ibon_dict["answer_index"] = -1 + is_enter_verify_mode = True + ibon_dict["fail_list"] = ibon_verification_question(driver, ibon_dict["fail_list"], config_dict) + + if not is_enter_verify_mode: + ibon_dict["fail_list"] = [] if not is_match_target_feature: # 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 #is_button_clicked = force_press_button(driver, By.CSS_SELECTOR, 'a.btn.btn-primary') # plan-B, easy and better than plan-A - driver.back() - driver.refresh() + try: + driver.back() + driver.refresh() + except Exception as exc: + pass + if not is_match_target_feature: #https://orders.ibon.com.tw/application/UTK02/UTK0206_.aspx @@ -10483,7 +10427,7 @@ def main(args): # for tixcraft tixcraft_dict = {} - tixcraft_dict["answer_index"]=-1 + tixcraft_dict["fail_list"]=[] tixcraft_dict["is_popup_checkout"] = False # for kktix @@ -10493,7 +10437,7 @@ def main(args): kktix_dict["is_popup_checkout"] = False ibon_dict = {} - ibon_dict["answer_index"]=-1 + ibon_dict["fail_list"]=[] hkticketing_dict = {} hkticketing_dict["is_date_submiting"] = False diff --git a/config_launcher.py b/config_launcher.py index f5b3ba8..930ea69 100644 --- a/config_launcher.py +++ b/config_launcher.py @@ -22,7 +22,7 @@ import base64 import threading 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_CONFIG_FILE = "settings.json" diff --git a/settings.json b/settings.json index a107c14..b219b5e 100644 --- a/settings.json +++ b/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}} \ No newline at end of file +{"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}} \ No newline at end of file diff --git a/settings.py b/settings.py index c7dbca5..74c8bef 100644 --- a/settings.py +++ b/settings.py @@ -32,7 +32,7 @@ warnings.simplefilter('ignore',InsecureRequestWarning) import ssl 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_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 not ('\"' in user_input): user_input = '"' + user_input + '"' + if user_input[:1]=="{" and user_input[-1:]=="}": - user_input=user_input[1:] - user_input=user_input[:-1] + tmp_json = {} + 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:]=="]": user_input=user_input[1:] user_input=user_input[:-1] @@ -889,9 +897,18 @@ def show_preview_text(): answer_text = "" with open(CONST_MAXBOT_ANSWER_ONLINE_FILE, "r") as text_file: answer_text = text_file.readline() + + answer_text = format_config_keyword_for_json(answer_text) + + date_array = [] try: - global lbl_online_dictionary_preview - lbl_online_dictionary_preview.config(text=answer_text) + date_array = json.loads("["+ answer_text +"]") + except Exception as exc: + date_array = [] + + global lbl_online_dictionary_preview + try: + lbl_online_dictionary_preview.config(text=','.join(date_array)) except Exception as exc: 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} html_result = None 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: html_result = None #print(exc) @@ -911,6 +928,7 @@ def save_url_to_file(new_online_dictionary_url, force_write = False): #print("status_code:", status_code) if status_code == 200: html_text = html_result.text + #print("html_text:", html_text) is_write_to_file = False if force_write: @@ -919,13 +937,18 @@ def save_url_to_file(new_online_dictionary_url, force_write = False): is_write_to_file = True 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: text_file.write("%s" % html_text) return is_write_to_file def btn_preview_text_clicked(): global txt_online_dictionary_url - online_dictionary_url = txt_online_dictionary_url.get("1.0",END).strip() + online_dictionary_url = "" + try: + 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) if len(online_dictionary_url) > 0: 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) +def resetful_api_timer(): + while True: + btn_preview_text_clicked() + time.sleep(0.2) + def settings_timer(): while True: update_maxbot_runtime_status() - btn_preview_text_clicked() - time.sleep(0.2) + time.sleep(0.6) def update_maxbot_runtime_status(): is_paused = False @@ -2472,5 +2499,6 @@ def clean_tmp_file(): force_remove_file(filepath) if __name__ == "__main__": + threading.Thread(target=resetful_api_timer, daemon=True).start() clean_tmp_file() main() diff --git a/text_server.py b/text_server.py index 383e94e..900029a 100644 --- a/text_server.py +++ b/text_server.py @@ -27,7 +27,7 @@ import asyncio import tornado 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" @@ -51,6 +51,9 @@ def btn_copy_question_clicked(): question_text = txt_question.get("1.0",END).strip() pyperclip.copy(question_text) +def btn_paste_answer_by_user(): + print("btn_paste_answer_by_user") + def TextInput(root, UI_PADDING_X): row_count = 0 @@ -97,11 +100,12 @@ def TextInput(root, UI_PADDING_X): lbl_answer = Label(frame_group_header, text="Answer") lbl_answer.grid(column=0, row=group_row_count, sticky = E) - global txt_keyword - txt_keyword_value = StringVar(frame_group_header, value="") - txt_keyword = Entry(frame_group_header, width=30, textvariable = txt_keyword_value) - txt_keyword.grid(column=1, row=group_row_count, sticky = W) - + global txt_answer + global txt_answer_value + txt_answer_value = StringVar(frame_group_header, value="") + 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('', lambda e: btn_paste_answer_by_user()) frame_group_header.grid(column=0, row=row_count, padx=UI_PADDING_X, pady=15) @@ -155,10 +159,28 @@ def main_ui(): root.mainloop() + 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): - global txt_keyword - self.write(txt_keyword.get().strip()) + global txt_answer_value + 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): def get(self): @@ -183,13 +205,14 @@ def preview_question_text_file(): with open(CONST_MAXBOT_QUESTION_FILE, "r") as text_file: question_text = text_file.readline() + global txt_question try: - global txt_question - inputed_question_text = txt_question.get("1.0",END).strip() - 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 txt_question.delete("1.0","end") - txt_question.insert("1.0", question_text) + if len(question_text) > 0: + txt_question.insert("1.0", question_text) except Exception as exc: pass