commit
						b8a237d285
					
				| 
						 | 
				
			
			@ -44,7 +44,7 @@ except Exception as exc:
 | 
			
		|||
    print(exc)
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
CONST_APP_VERSION = "MaxBot (2024.04.09)"
 | 
			
		||||
CONST_APP_VERSION = "MaxBot (2024.04.10)"
 | 
			
		||||
 | 
			
		||||
CONST_MAXBOT_ANSWER_ONLINE_FILE = "MAXBOT_ONLINE_ANSWER.txt"
 | 
			
		||||
CONST_MAXBOT_CONFIG_FILE = "settings.json"
 | 
			
		||||
| 
						 | 
				
			
			@ -1826,12 +1826,14 @@ def fill_common_verify_form(driver, config_dict, inferred_answer_string, fail_li
 | 
			
		|||
                        if submit_by_enter:
 | 
			
		||||
                            form_input_1.send_keys(Keys.ENTER)
 | 
			
		||||
                            is_button_clicked = True
 | 
			
		||||
                        else:
 | 
			
		||||
                            if len(next_step_button_css) > 0:
 | 
			
		||||
                                is_button_clicked = press_button(driver, By.CSS_SELECTOR, next_step_button_css)
 | 
			
		||||
                except Exception as exc:
 | 
			
		||||
                    if show_debug_message:
 | 
			
		||||
                        print(exc)
 | 
			
		||||
                    pass
 | 
			
		||||
                
 | 
			
		||||
                if is_button_clicked:
 | 
			
		||||
                    is_answer_sent = True
 | 
			
		||||
                    fail_list.append(inferred_answer_string)
 | 
			
		||||
| 
						 | 
				
			
			@ -1841,7 +1843,6 @@ def fill_common_verify_form(driver, config_dict, inferred_answer_string, fail_li
 | 
			
		|||
                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:
 | 
			
		||||
| 
						 | 
				
			
			@ -2441,7 +2442,7 @@ def kktix_press_next_button(driver):
 | 
			
		|||
        #print("button_count:",button_count)
 | 
			
		||||
        if button_count > 0:
 | 
			
		||||
            try:
 | 
			
		||||
                #print("click on last button")
 | 
			
		||||
                #print("click on last button:", button_count)
 | 
			
		||||
                but_button_list[button_count-1].click()
 | 
			
		||||
                time.sleep(0.3)
 | 
			
		||||
                ret = True
 | 
			
		||||
| 
						 | 
				
			
			@ -2451,59 +2452,6 @@ def kktix_press_next_button(driver):
 | 
			
		|||
 | 
			
		||||
    return ret
 | 
			
		||||
 | 
			
		||||
def kktix_captcha_inputed_text(captcha_inner_div):
 | 
			
		||||
    ret = ""
 | 
			
		||||
    if not captcha_inner_div is 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
 | 
			
		||||
 | 
			
		||||
    return ret
 | 
			
		||||
 | 
			
		||||
def kktix_input_captcha_text(captcha_password_input_element, inferred_answer_string, force_overwrite = False):
 | 
			
		||||
    show_debug_message = True       # debug.
 | 
			
		||||
    show_debug_message = False      # online
 | 
			
		||||
 | 
			
		||||
    is_captcha_sent = False
 | 
			
		||||
    inputed_captcha_text = ""
 | 
			
		||||
 | 
			
		||||
    if not captcha_password_input_element is None:
 | 
			
		||||
        if force_overwrite:
 | 
			
		||||
            try:
 | 
			
		||||
                captcha_password_input_element.send_keys(inferred_answer_string)
 | 
			
		||||
                print("send captcha keys:" + inferred_answer_string)
 | 
			
		||||
                is_captcha_sent = True
 | 
			
		||||
            except Exception as exc:
 | 
			
		||||
                pass
 | 
			
		||||
        else:
 | 
			
		||||
            # not force overwrite:
 | 
			
		||||
            inputed_captcha_text = None
 | 
			
		||||
            try:
 | 
			
		||||
                inputed_captcha_text = captcha_password_input_element.get_attribute('value')
 | 
			
		||||
            except Exception as exc:
 | 
			
		||||
                pass
 | 
			
		||||
            if inputed_captcha_text is None:
 | 
			
		||||
                inputed_captcha_text = ""
 | 
			
		||||
 | 
			
		||||
            if len(inputed_captcha_text) == 0:
 | 
			
		||||
                try:
 | 
			
		||||
                    captcha_password_input_element.send_keys(inferred_answer_string)
 | 
			
		||||
                    print("send captcha keys:" + inferred_answer_string)
 | 
			
		||||
                    is_captcha_sent = True
 | 
			
		||||
                except Exception as exc:
 | 
			
		||||
                    pass
 | 
			
		||||
            else:
 | 
			
		||||
                if inputed_captcha_text == inferred_answer_string:
 | 
			
		||||
                    is_captcha_sent = True
 | 
			
		||||
 | 
			
		||||
    return is_captcha_sent
 | 
			
		||||
 | 
			
		||||
def kktix_travel_price_list(driver, config_dict, kktix_area_auto_select_mode, kktix_area_keyword):
 | 
			
		||||
    show_debug_message = True       # debug.
 | 
			
		||||
| 
						 | 
				
			
			@ -2929,12 +2877,16 @@ def kktix_reg_captcha(driver, config_dict, fail_list, registrationsNewApp_div):
 | 
			
		|||
                inferred_answer_string = answer_item
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
        if len(answer_list) > 0:
 | 
			
		||||
            answer_list = list(dict.fromkeys(answer_list))
 | 
			
		||||
 | 
			
		||||
        if show_debug_message:
 | 
			
		||||
            print("inferred_answer_string:", inferred_answer_string)
 | 
			
		||||
            print("answer_list:", answer_list)
 | 
			
		||||
            print("fail_list:", fail_list)
 | 
			
		||||
 | 
			
		||||
        # PS: auto-focus() when empty inferred_answer_string with empty inputed text value.
 | 
			
		||||
        if len(inferred_answer_string) > 0:
 | 
			
		||||
            input_text_css = 'div.custom-captcha-inner > div > div > input'
 | 
			
		||||
            next_step_button_css = ''
 | 
			
		||||
            submit_by_enter = False
 | 
			
		||||
| 
						 | 
				
			
			@ -2943,6 +2895,10 @@ def kktix_reg_captcha(driver, config_dict, fail_list, registrationsNewApp_div):
 | 
			
		|||
 | 
			
		||||
            # due multi next buttons(pick seats/best seats)
 | 
			
		||||
            kktix_press_next_button(driver)
 | 
			
		||||
            time.sleep(0.75)
 | 
			
		||||
 | 
			
		||||
            fail_list.append(inferred_answer_string)
 | 
			
		||||
        #print("new fail_list:", fail_list)
 | 
			
		||||
 | 
			
		||||
    return fail_list, is_question_popup
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -8354,7 +8310,7 @@ def softix_powerweb_main(driver, url, config_dict):
 | 
			
		|||
def khan_go_buy_redirect(driver, domain_name):
 | 
			
		||||
    is_button_clicked = False
 | 
			
		||||
    if 'kham.com' in domain_name:
 | 
			
		||||
        is_button_clicked = press_button(driver, By.CSS_SELECTOR, 'p > a > button.red')
 | 
			
		||||
        is_button_clicked = press_button(driver, By.CSS_SELECTOR, 'div#content > p > a > button[onclick].red')
 | 
			
		||||
    if 'ticket.com' in domain_name:
 | 
			
		||||
        is_button_clicked = press_button(driver, By.CSS_SELECTOR, 'div.row > div > a.btn.btn-order.btn-block')
 | 
			
		||||
    if 'udnfunlife.com' in domain_name:
 | 
			
		||||
| 
						 | 
				
			
			@ -8386,8 +8342,10 @@ def hkam_date_auto_select(driver, domain_name, config_dict):
 | 
			
		|||
    try:
 | 
			
		||||
        # for kham.com
 | 
			
		||||
        my_css_selector = "table.eventTABLE > tbody > tr"
 | 
			
		||||
        
 | 
			
		||||
        if 'ticket.com' in domain_name:
 | 
			
		||||
            my_css_selector = "div.description > table.table.table-striped.itable > tbody > tr"
 | 
			
		||||
        
 | 
			
		||||
        if 'udnfunlife.com' in domain_name:
 | 
			
		||||
            my_css_selector = "div.yd_session-block"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -8454,19 +8412,19 @@ def hkam_date_auto_select(driver, domain_name, config_dict):
 | 
			
		|||
                    else:
 | 
			
		||||
                        # kham.
 | 
			
		||||
                        price_disabled_html = '"lightblue"'
 | 
			
		||||
                        
 | 
			
		||||
                        if 'ticket.com' in domain_name:
 | 
			
		||||
                            price_disabled_html = '<del>'
 | 
			
		||||
 | 
			
		||||
                        if "<td" in row_html:
 | 
			
		||||
                            td_array = row_html.split("<td")
 | 
			
		||||
                            if len(td_array) > 3:
 | 
			
		||||
                                td_target = "<td" + td_array[3]
 | 
			
		||||
                                td_target = td_array[3]
 | 
			
		||||
                                price_array = td_target.split("、")
 | 
			
		||||
                                is_all_priece_disabled = True
 | 
			
		||||
                                for each_price in price_array:
 | 
			
		||||
                                    if not (price_disabled_html in each_price):
 | 
			
		||||
                                        is_all_priece_disabled = False
 | 
			
		||||
 | 
			
		||||
                                if is_all_priece_disabled:
 | 
			
		||||
                                    row_text = ""
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -9222,7 +9180,8 @@ def kham_main(driver, url, config_dict, ocr, Captcha_Browser):
 | 
			
		|||
            is_event_page = True
 | 
			
		||||
 | 
			
		||||
        if is_event_page:
 | 
			
		||||
            khan_go_buy_redirect(driver, domain_name)
 | 
			
		||||
            #khan_go_buy_redirect(driver, domain_name)
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    # https://kham.com.tw/application/UTK02/UTK0201_00.aspx?PRODUCT_ID=N28TFATD
 | 
			
		||||
    if 'utk0201_00.aspx?product_id=' in url.lower():
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
#!/usr/bin/env python3
 | 
			
		||||
#encoding=utf-8
 | 
			
		||||
#執行方式:python chrome_tixcraft.py 或 python3 chrome_tixcraft.py
 | 
			
		||||
import argparse
 | 
			
		||||
import base64
 | 
			
		||||
import json
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +32,7 @@ except Exception as exc:
 | 
			
		|||
    print(exc)
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
CONST_APP_VERSION = "MaxBot (2024.04.09)"
 | 
			
		||||
CONST_APP_VERSION = "MaxBot (2024.04.10)"
 | 
			
		||||
 | 
			
		||||
CONST_MAXBOT_ANSWER_ONLINE_FILE = "MAXBOT_ONLINE_ANSWER.txt"
 | 
			
		||||
CONST_MAXBOT_CONFIG_FILE = "settings.json"
 | 
			
		||||
| 
						 | 
				
			
			@ -214,7 +213,8 @@ async def nodriver_check_checkbox(tab, select_query, value='true'):
 | 
			
		|||
        try:
 | 
			
		||||
            element = await tab.query_selector(select_query)
 | 
			
		||||
            if element:
 | 
			
		||||
                await element.apply('function (element) { element.checked='+ value +'; } ')
 | 
			
		||||
                #await element.apply('function (element) { element.checked='+ value +'; } ')
 | 
			
		||||
                await element.click()
 | 
			
		||||
                is_checkbox_checked = True
 | 
			
		||||
        except Exception as exc:
 | 
			
		||||
            #print("check checkbox fail for selector:", select_query)
 | 
			
		||||
| 
						 | 
				
			
			@ -651,6 +651,9 @@ async def nodriver_kktix_reg_captcha(tab, config_dict, fail_list, registrationsN
 | 
			
		|||
                inferred_answer_string = answer_item
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
        if len(answer_list) > 0:
 | 
			
		||||
            answer_list = list(dict.fromkeys(answer_list))
 | 
			
		||||
 | 
			
		||||
        if show_debug_message:
 | 
			
		||||
            print("inferred_answer_string:", inferred_answer_string)
 | 
			
		||||
            print("question_text:", question_text)
 | 
			
		||||
| 
						 | 
				
			
			@ -658,6 +661,7 @@ async def nodriver_kktix_reg_captcha(tab, config_dict, fail_list, registrationsN
 | 
			
		|||
            print("fail_list:", fail_list)
 | 
			
		||||
 | 
			
		||||
        # PS: auto-focus() when empty inferred_answer_string with empty inputed text value.
 | 
			
		||||
        if len(inferred_answer_string) > 0:
 | 
			
		||||
            input_text_css = 'div.custom-captcha-inner > div > div > input'
 | 
			
		||||
            next_step_button_css = ''
 | 
			
		||||
            submit_by_enter = False
 | 
			
		||||
| 
						 | 
				
			
			@ -666,10 +670,19 @@ async def nodriver_kktix_reg_captcha(tab, config_dict, fail_list, registrationsN
 | 
			
		|||
            if len(answer_list) > 0:
 | 
			
		||||
                input_text = await tab.query_selector(input_text_css)
 | 
			
		||||
                if not input_text is None:
 | 
			
		||||
                await input_text.send_keys(answer_list[0])
 | 
			
		||||
 | 
			
		||||
                    await input_text.click()
 | 
			
		||||
                    await input_text.apply('function (element) {element.value = ""; } ')
 | 
			
		||||
                    await input_text.send_keys(inferred_answer_string)
 | 
			
		||||
                    time.sleep(0.1)
 | 
			
		||||
 | 
			
		||||
                    # due multi next buttons(pick seats/best seats)
 | 
			
		||||
                    print("click")
 | 
			
		||||
                    await nodriver_kktix_press_next_button(tab)
 | 
			
		||||
                    time.sleep(0.75)
 | 
			
		||||
 | 
			
		||||
                    fail_list.append(inferred_answer_string)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    return fail_list, is_question_popup
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -769,7 +782,7 @@ async def nodriver_kktix_reg_new_main(tab, config_dict, fail_list, played_sound_
 | 
			
		|||
                        play_sound_while_ordering(config_dict)
 | 
			
		||||
                    played_sound_ticket = True
 | 
			
		||||
 | 
			
		||||
                is_finish_checkbox_click = await nodriver_check_checkbox(tab, 'input[type="checkbox"]')
 | 
			
		||||
                is_finish_checkbox_click = await nodriver_check_checkbox(tab, 'input[type="checkbox"]:not(:checked)')
 | 
			
		||||
 | 
			
		||||
                # whole event question.
 | 
			
		||||
                fail_list, is_question_popup = await nodriver_kktix_reg_captcha(tab, config_dict, fail_list, registrationsNewApp_div)
 | 
			
		||||
| 
						 | 
				
			
			@ -1072,7 +1085,7 @@ async def nodriver_tixcraft_input_check_code(tab, config_dict, fail_list, questi
 | 
			
		|||
 | 
			
		||||
async def nodriver_tixcraft_ticket_main_agree(tab, config_dict):
 | 
			
		||||
    for i in range(3):
 | 
			
		||||
        is_finish_checkbox_click = await nodriver_check_checkbox(tab, '#TicketForm_agree')
 | 
			
		||||
        is_finish_checkbox_click = await nodriver_check_checkbox(tab, '#TicketForm_agree:not(:checked)')
 | 
			
		||||
        if is_finish_checkbox_click:
 | 
			
		||||
            break
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1450,7 +1463,7 @@ async def nodriver_ticketplus_main(tab, url, config_dict, ocr, Captcha_Browser):
 | 
			
		|||
 | 
			
		||||
async def nodriver_ibon_ticket_agree(tab):
 | 
			
		||||
    for i in range(3):
 | 
			
		||||
        is_finish_checkbox_click = await nodriver_check_checkbox(tab, '#agreen')
 | 
			
		||||
        is_finish_checkbox_click = await nodriver_check_checkbox(tab, '#agreen:not(:checked)')
 | 
			
		||||
        if is_finish_checkbox_click:
 | 
			
		||||
            break
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1481,7 +1494,7 @@ async def nodriver_ibon_main(tab, url, config_dict, ocr, Captcha_Browser):
 | 
			
		|||
            is_event_page = True
 | 
			
		||||
        if is_event_page:
 | 
			
		||||
            # ibon auto press signup
 | 
			
		||||
            await nodriver_press_button('.btn.btn-signup')
 | 
			
		||||
            await nodriver_press_button(tab, '.btn.btn-signup')
 | 
			
		||||
 | 
			
		||||
    is_match_target_feature = False
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1560,7 +1573,7 @@ async def nodriver_ibon_main(tab, url, config_dict, ocr, Captcha_Browser):
 | 
			
		|||
 | 
			
		||||
                if 'PRODUCT_ID=' in url.upper():
 | 
			
		||||
                    # step 1: select area.
 | 
			
		||||
                    is_match_target_feature = True
 | 
			
		||||
                    is_price_assign_by_bot = False
 | 
			
		||||
                    # TODO:
 | 
			
		||||
                    #is_price_assign_by_bot = ibon_performance(driver, config_dict)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1578,8 +1591,7 @@ async def nodriver_ibon_main(tab, url, config_dict, ocr, Captcha_Browser):
 | 
			
		|||
                if is_do_ibon_performance_with_ticket_number:
 | 
			
		||||
                    if config_dict["advanced"]["disable_adjacent_seat"]:
 | 
			
		||||
                        # TODO:
 | 
			
		||||
                        #is_finish_checkbox_click = ibon_allow_not_adjacent_seat(driver, config_dict)
 | 
			
		||||
                        pass
 | 
			
		||||
                        is_finish_checkbox_click = await nodriver_check_checkbox(tab, '.asp-checkbox > input[type="checkbox"]:not(:checked)')
 | 
			
		||||
 | 
			
		||||
                    # captcha
 | 
			
		||||
                    is_captcha_sent = False
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										149
									
								
								settings.py
								
								
								
								
							
							
						
						
									
										149
									
								
								settings.py
								
								
								
								
							| 
						 | 
				
			
			@ -1,12 +1,5 @@
 | 
			
		|||
#!/usr/bin/env python3
 | 
			
		||||
#encoding=utf-8
 | 
			
		||||
try:
 | 
			
		||||
    # for Python2
 | 
			
		||||
    import tkMessageBox as messagebox
 | 
			
		||||
    import ttk
 | 
			
		||||
    from Tkinter import *
 | 
			
		||||
except ImportError:
 | 
			
		||||
    # for Python3
 | 
			
		||||
try:
 | 
			
		||||
    import tkinter.font as tkfont
 | 
			
		||||
    from tkinter import *
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +34,7 @@ try:
 | 
			
		|||
except Exception as exc:
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
CONST_APP_VERSION = "MaxBot (2024.04.09)"
 | 
			
		||||
CONST_APP_VERSION = "MaxBot (2024.04.10)"
 | 
			
		||||
 | 
			
		||||
CONST_MAXBOT_ANSWER_ONLINE_FILE = "MAXBOT_ONLINE_ANSWER.txt"
 | 
			
		||||
CONST_MAXBOT_CONFIG_FILE = "settings.json"
 | 
			
		||||
| 
						 | 
				
			
			@ -694,8 +687,11 @@ def get_default_config():
 | 
			
		|||
def read_last_url_from_file():
 | 
			
		||||
    ret = ""
 | 
			
		||||
    if os.path.exists(CONST_MAXBOT_LAST_URL_FILE):
 | 
			
		||||
        try:
 | 
			
		||||
            with open(CONST_MAXBOT_LAST_URL_FILE, "r") as text_file:
 | 
			
		||||
                ret = text_file.readline()
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            pass
 | 
			
		||||
    return ret
 | 
			
		||||
 | 
			
		||||
def load_json():
 | 
			
		||||
| 
						 | 
				
			
			@ -706,13 +702,16 @@ def load_json():
 | 
			
		|||
 | 
			
		||||
    config_dict = None
 | 
			
		||||
    if os.path.isfile(config_filepath):
 | 
			
		||||
        try:
 | 
			
		||||
            with open(config_filepath) as json_data:
 | 
			
		||||
                config_dict = json.load(json_data)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            pass
 | 
			
		||||
    else:
 | 
			
		||||
        config_dict = get_default_config()
 | 
			
		||||
    return config_filepath, config_dict
 | 
			
		||||
 | 
			
		||||
def btn_restore_defaults_clicked(language_code):
 | 
			
		||||
def btn_restore_defaults_clicked():
 | 
			
		||||
    app_root = util.get_app_root()
 | 
			
		||||
    config_filepath = os.path.join(app_root, CONST_MAXBOT_CONFIG_FILE)
 | 
			
		||||
    if os.path.exists(str(config_filepath)):
 | 
			
		||||
| 
						 | 
				
			
			@ -723,6 +722,8 @@ def btn_restore_defaults_clicked(language_code):
 | 
			
		|||
            pass
 | 
			
		||||
 | 
			
		||||
    config_dict = get_default_config()
 | 
			
		||||
    language_code = get_language_code_by_name(config_dict["language"])
 | 
			
		||||
 | 
			
		||||
    messagebox.showinfo(translate[language_code]["restore_defaults"], translate[language_code]["done"])
 | 
			
		||||
 | 
			
		||||
    global root
 | 
			
		||||
| 
						 | 
				
			
			@ -731,8 +732,11 @@ def btn_restore_defaults_clicked(language_code):
 | 
			
		|||
def do_maxbot_idle():
 | 
			
		||||
    app_root = util.get_app_root()
 | 
			
		||||
    idle_filepath = os.path.join(app_root, CONST_MAXBOT_INT28_FILE)
 | 
			
		||||
    try:
 | 
			
		||||
        with open(CONST_MAXBOT_INT28_FILE, "w") as text_file:
 | 
			
		||||
            text_file.write("")
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
def btn_idle_clicked(language_code):
 | 
			
		||||
    do_maxbot_idle()
 | 
			
		||||
| 
						 | 
				
			
			@ -748,7 +752,7 @@ def btn_resume_clicked(language_code):
 | 
			
		|||
    do_maxbot_resume()
 | 
			
		||||
    update_maxbot_runtime_status()
 | 
			
		||||
 | 
			
		||||
def btn_launcher_clicked(language_code):
 | 
			
		||||
def btn_launcher_clicked():
 | 
			
		||||
    Root_Dir = ""
 | 
			
		||||
    save_ret = btn_save_act(slience_mode=True)
 | 
			
		||||
    if save_ret:
 | 
			
		||||
| 
						 | 
				
			
			@ -1087,7 +1091,6 @@ def btn_save_act(slience_mode=False):
 | 
			
		|||
                # min value is 20 seconds.
 | 
			
		||||
                config_dict["advanced"]["reset_browser_interval"] = 20
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    # save config.
 | 
			
		||||
    if is_all_data_correct:
 | 
			
		||||
        if not slience_mode:
 | 
			
		||||
| 
						 | 
				
			
			@ -1104,7 +1107,7 @@ def btn_save_act(slience_mode=False):
 | 
			
		|||
    return is_all_data_correct
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def btn_run_clicked(language_code):
 | 
			
		||||
def btn_run_clicked():
 | 
			
		||||
    print('run button pressed.')
 | 
			
		||||
    Root_Dir = ""
 | 
			
		||||
    save_ret = btn_save_act(slience_mode=True)
 | 
			
		||||
| 
						 | 
				
			
			@ -1146,9 +1149,13 @@ def launch_maxbot():
 | 
			
		|||
def show_preview_text():
 | 
			
		||||
    if os.path.exists(CONST_MAXBOT_ANSWER_ONLINE_FILE):
 | 
			
		||||
        answer_text = ""
 | 
			
		||||
        try:
 | 
			
		||||
            with open(CONST_MAXBOT_ANSWER_ONLINE_FILE, "r") as text_file:
 | 
			
		||||
                answer_text = text_file.readline()
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
        if len(answer_text) > 0:
 | 
			
		||||
            answer_text = util.format_config_keyword_for_json(answer_text)
 | 
			
		||||
 | 
			
		||||
        date_array = []
 | 
			
		||||
| 
						 | 
				
			
			@ -1157,10 +1164,12 @@ def show_preview_text():
 | 
			
		|||
        except Exception as exc:
 | 
			
		||||
            date_array = []
 | 
			
		||||
 | 
			
		||||
        if len(date_array) > 0:
 | 
			
		||||
            preview_string = text=','.join(date_array)
 | 
			
		||||
            global lbl_online_dictionary_preview_data
 | 
			
		||||
            if 'lbl_online_dictionary_preview_data' in globals():
 | 
			
		||||
                try:
 | 
			
		||||
                lbl_online_dictionary_preview_data.config(text=','.join(date_array))
 | 
			
		||||
                    lbl_online_dictionary_preview_data.config(preview_string)
 | 
			
		||||
                except Exception as exc:
 | 
			
		||||
                    pass
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1182,6 +1191,7 @@ def btn_preview_text_clicked():
 | 
			
		|||
            url_array = []
 | 
			
		||||
 | 
			
		||||
        force_write = False
 | 
			
		||||
        if len(url_array)>0:
 | 
			
		||||
            if len(url_array)==1:
 | 
			
		||||
                force_write = True
 | 
			
		||||
            for each_url in url_array:
 | 
			
		||||
| 
						 | 
				
			
			@ -2600,6 +2610,13 @@ def change_maxbot_status_by_keyword():
 | 
			
		|||
 | 
			
		||||
def check_maxbot_config_unsaved(config_dict):
 | 
			
		||||
    # alert not saved config.
 | 
			
		||||
    selected_tab_index = -1
 | 
			
		||||
 | 
			
		||||
    global tabControl
 | 
			
		||||
    if 'tabControl' in globals():
 | 
			
		||||
        selected_tab_index = tabControl.index(tabControl.select())
 | 
			
		||||
 | 
			
		||||
    if selected_tab_index==0:
 | 
			
		||||
        global combo_homepage
 | 
			
		||||
        global combo_ticket_number
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2607,10 +2624,17 @@ def check_maxbot_config_unsaved(config_dict):
 | 
			
		|||
        global txt_area_keyword
 | 
			
		||||
        global txt_keyword_exclude
 | 
			
		||||
 | 
			
		||||
    global txt_idle_keyword
 | 
			
		||||
    global txt_resume_keyword
 | 
			
		||||
    global txt_idle_keyword_second
 | 
			
		||||
    global txt_resume_keyword_second
 | 
			
		||||
        global txt_date_keyword_highlightthickness
 | 
			
		||||
        if not 'txt_date_keyword_highlightthickness' in globals():
 | 
			
		||||
            txt_date_keyword_highlightthickness = 0
 | 
			
		||||
 | 
			
		||||
        global txt_area_keyword_highlightthickness
 | 
			
		||||
        if not 'txt_area_keyword_highlightthickness' in globals():
 | 
			
		||||
            txt_area_keyword_highlightthickness = 0
 | 
			
		||||
 | 
			
		||||
        global txt_keyword_exclude_highlightthickness
 | 
			
		||||
        if not 'txt_keyword_exclude_highlightthickness' in globals():
 | 
			
		||||
            txt_keyword_exclude_highlightthickness = 0
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            date_keyword = ""
 | 
			
		||||
| 
						 | 
				
			
			@ -2628,6 +2652,54 @@ def check_maxbot_config_unsaved(config_dict):
 | 
			
		|||
                keyword_exclude = txt_keyword_exclude.get("1.0",END).strip()
 | 
			
		||||
                keyword_exclude = util.format_config_keyword_for_json(keyword_exclude)
 | 
			
		||||
 | 
			
		||||
            highlightthickness = 0
 | 
			
		||||
            if 'combo_homepage' in globals():
 | 
			
		||||
                if len(combo_homepage.get().strip())>0:
 | 
			
		||||
                    if config_dict["homepage"] != combo_homepage.get().strip():
 | 
			
		||||
                        highlightthickness = 2
 | 
			
		||||
            
 | 
			
		||||
            highlightthickness = 0
 | 
			
		||||
            if 'combo_ticket_number' in globals():
 | 
			
		||||
                if len(combo_ticket_number.get().strip())>0:
 | 
			
		||||
                    if config_dict["ticket_number"] != int(combo_ticket_number.get().strip()):
 | 
			
		||||
                        highlightthickness = 2
 | 
			
		||||
            # fail, tkinter combobox border style is not working anymore
 | 
			
		||||
            #combo_ticket_number.config(highlightthickness=highlightthickness, highlightbackground="red")
 | 
			
		||||
 | 
			
		||||
            highlightthickness = 0
 | 
			
		||||
            if config_dict["date_auto_select"]["date_keyword"] != date_keyword:
 | 
			
		||||
                highlightthickness = 2
 | 
			
		||||
 | 
			
		||||
            if txt_date_keyword_highlightthickness != highlightthickness:
 | 
			
		||||
                txt_date_keyword_highlightthickness = highlightthickness
 | 
			
		||||
                txt_date_keyword.config(highlightthickness=highlightthickness, highlightbackground="red")
 | 
			
		||||
 | 
			
		||||
            highlightthickness = 0
 | 
			
		||||
            if config_dict["area_auto_select"]["area_keyword"] != area_keyword:
 | 
			
		||||
                highlightthickness = 2
 | 
			
		||||
 | 
			
		||||
            if txt_area_keyword_highlightthickness != highlightthickness:
 | 
			
		||||
                txt_area_keyword_highlightthickness = highlightthickness
 | 
			
		||||
                txt_area_keyword.config(highlightthickness=highlightthickness, highlightbackground="red")
 | 
			
		||||
 | 
			
		||||
            highlightthickness = 0
 | 
			
		||||
            if config_dict["keyword_exclude"] != keyword_exclude:
 | 
			
		||||
                highlightthickness = 2
 | 
			
		||||
 | 
			
		||||
            if txt_keyword_exclude_highlightthickness != highlightthickness:
 | 
			
		||||
                txt_keyword_exclude_highlightthickness = highlightthickness
 | 
			
		||||
                txt_keyword_exclude.config(highlightthickness=highlightthickness, highlightbackground="red")
 | 
			
		||||
        except Exception as exc:
 | 
			
		||||
            #print(exc)
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    if selected_tab_index==5:
 | 
			
		||||
        global txt_idle_keyword
 | 
			
		||||
        global txt_resume_keyword
 | 
			
		||||
        global txt_idle_keyword_second
 | 
			
		||||
        global txt_resume_keyword_second
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            idle_keyword = ""
 | 
			
		||||
            if 'txt_idle_keyword' in globals():
 | 
			
		||||
                idle_keyword = txt_idle_keyword.get("1.0",END).strip()
 | 
			
		||||
| 
						 | 
				
			
			@ -2648,38 +2720,6 @@ def check_maxbot_config_unsaved(config_dict):
 | 
			
		|||
                resume_keyword_second = txt_resume_keyword_second.get("1.0",END).strip()
 | 
			
		||||
                resume_keyword_second = util.format_config_keyword_for_json(resume_keyword_second)
 | 
			
		||||
 | 
			
		||||
        highlightthickness = 0
 | 
			
		||||
        if 'combo_homepage' in globals():
 | 
			
		||||
            if len(combo_homepage.get().strip())>0:
 | 
			
		||||
                if config_dict["homepage"] != combo_homepage.get().strip():
 | 
			
		||||
                    highlightthickness = 2
 | 
			
		||||
        
 | 
			
		||||
        if highlightthickness > 0:
 | 
			
		||||
            showHideBlocks()
 | 
			
		||||
 | 
			
		||||
        highlightthickness = 0
 | 
			
		||||
        if 'combo_ticket_number' in globals():
 | 
			
		||||
            if len(combo_ticket_number.get().strip())>0:
 | 
			
		||||
                if config_dict["ticket_number"] != int(combo_ticket_number.get().strip()):
 | 
			
		||||
                    highlightthickness = 2
 | 
			
		||||
        # fail, tkinter combobox border style is not working anymore
 | 
			
		||||
        #combo_ticket_number.config(highlightthickness=highlightthickness, highlightbackground="red")
 | 
			
		||||
 | 
			
		||||
        highlightthickness = 0
 | 
			
		||||
        if config_dict["date_auto_select"]["date_keyword"] != date_keyword:
 | 
			
		||||
            highlightthickness = 2
 | 
			
		||||
        txt_date_keyword.config(highlightthickness=highlightthickness, highlightbackground="red")
 | 
			
		||||
 | 
			
		||||
        highlightthickness = 0
 | 
			
		||||
        if config_dict["area_auto_select"]["area_keyword"] != area_keyword:
 | 
			
		||||
            highlightthickness = 2
 | 
			
		||||
        txt_area_keyword.config(highlightthickness=highlightthickness, highlightbackground="red")
 | 
			
		||||
 | 
			
		||||
        highlightthickness = 0
 | 
			
		||||
        if config_dict["keyword_exclude"] != keyword_exclude:
 | 
			
		||||
            highlightthickness = 2
 | 
			
		||||
        txt_keyword_exclude.config(highlightthickness=highlightthickness, highlightbackground="red")
 | 
			
		||||
 | 
			
		||||
            highlightthickness = 0
 | 
			
		||||
            if config_dict["advanced"]["idle_keyword"] != idle_keyword:
 | 
			
		||||
                highlightthickness = 2
 | 
			
		||||
| 
						 | 
				
			
			@ -2737,8 +2777,11 @@ def sync_status_to_extension(status):
 | 
			
		|||
        status_json={}
 | 
			
		||||
        status_json["status"]=status
 | 
			
		||||
        #print("dump json to path:", target_path)
 | 
			
		||||
        try:
 | 
			
		||||
            with open(target_path, 'w') as outfile:
 | 
			
		||||
                json.dump(status_json, outfile)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
def update_maxbot_runtime_status():
 | 
			
		||||
    is_paused = False
 | 
			
		||||
| 
						 | 
				
			
			@ -2989,19 +3032,19 @@ def get_action_bar(root, language_code):
 | 
			
		|||
    global btn_restore_defaults
 | 
			
		||||
    global btn_launcher
 | 
			
		||||
 | 
			
		||||
    btn_run = ttk.Button(frame_action, text=translate[language_code]['run'], command= lambda: btn_run_clicked(language_code))
 | 
			
		||||
    btn_run = ttk.Button(frame_action, text=translate[language_code]['run'], command=btn_run_clicked)
 | 
			
		||||
    btn_run.grid(column=0, row=0)
 | 
			
		||||
 | 
			
		||||
    btn_save = ttk.Button(frame_action, text=translate[language_code]['save'], command= lambda: btn_save_clicked() )
 | 
			
		||||
    btn_save = ttk.Button(frame_action, text=translate[language_code]['save'], command=btn_save_clicked)
 | 
			
		||||
    btn_save.grid(column=1, row=0)
 | 
			
		||||
 | 
			
		||||
    btn_exit = ttk.Button(frame_action, text=translate[language_code]['exit'], command=btn_exit_clicked)
 | 
			
		||||
    #btn_exit.grid(column=2, row=0)
 | 
			
		||||
 | 
			
		||||
    btn_launcher = ttk.Button(frame_action, text=translate[language_code]['config_launcher'], command= lambda: btn_launcher_clicked(language_code))
 | 
			
		||||
    btn_launcher = ttk.Button(frame_action, text=translate[language_code]['config_launcher'], command= btn_launcher_clicked)
 | 
			
		||||
    btn_launcher.grid(column=2, row=0)
 | 
			
		||||
 | 
			
		||||
    btn_restore_defaults = ttk.Button(frame_action, text=translate[language_code]['restore_defaults'], command= lambda: btn_restore_defaults_clicked(language_code))
 | 
			
		||||
    btn_restore_defaults = ttk.Button(frame_action, text=translate[language_code]['restore_defaults'], command= btn_restore_defaults_clicked)
 | 
			
		||||
    btn_restore_defaults.grid(column=3, row=0)
 | 
			
		||||
 | 
			
		||||
    return frame_action
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										33
									
								
								util.py
								
								
								
								
							
							
						
						
									
										33
									
								
								util.py
								
								
								
								
							| 
						 | 
				
			
			@ -25,19 +25,25 @@ def get_ip_address():
 | 
			
		|||
    try:
 | 
			
		||||
        gethostname = socket.gethostname()
 | 
			
		||||
    except Exception as exc:
 | 
			
		||||
        print(exc)
 | 
			
		||||
        print("gethostname", exc)
 | 
			
		||||
        gethostname = None
 | 
			
		||||
 | 
			
		||||
    default_ip = "127.0.0.1"
 | 
			
		||||
    ip = default_ip
 | 
			
		||||
    if not gethostname is None:
 | 
			
		||||
 | 
			
		||||
    check_public_ip = True    
 | 
			
		||||
    if "macos" in platform.platform().lower():
 | 
			
		||||
        if "arm64" in platform.platform().lower():
 | 
			
		||||
            check_public_ip = False
 | 
			
		||||
 | 
			
		||||
    if check_public_ip and not gethostname is None:
 | 
			
		||||
        try:
 | 
			
		||||
            ip = [l for l in ([ip for ip in socket.gethostbyname_ex(gethostname)[2]
 | 
			
		||||
                if not ip.startswith("127.")][:1], [[(s.connect(('8.8.8.8', 53)),
 | 
			
		||||
                s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET,
 | 
			
		||||
                socket.SOCK_DGRAM)]][0][1]]) if l][0][0]
 | 
			
		||||
        except Exception as exc:
 | 
			
		||||
            print(exc)
 | 
			
		||||
            print("gethostbyname_ex", exc)
 | 
			
		||||
            ip = gethostname
 | 
			
		||||
    
 | 
			
		||||
    #print("get_ip_address:", ip)
 | 
			
		||||
| 
						 | 
				
			
			@ -162,8 +168,11 @@ def is_text_match_keyword(keyword_string, text):
 | 
			
		|||
 | 
			
		||||
def save_json(config_dict, target_path):
 | 
			
		||||
    json_str = json.dumps(config_dict, indent=4)
 | 
			
		||||
    try:
 | 
			
		||||
        with open(target_path, 'w') as outfile:
 | 
			
		||||
            outfile.write(json_str)
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
def write_string_to_file(filename, data):
 | 
			
		||||
    outfile = None
 | 
			
		||||
| 
						 | 
				
			
			@ -448,8 +457,12 @@ def dump_settings_to_maxbot_plus_extension(ext, config_dict, CONST_MAXBOT_CONFIG
 | 
			
		|||
            os.unlink(target_path)
 | 
			
		||||
        except Exception as exc:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        with open(target_path, 'w') as outfile:
 | 
			
		||||
            json.dump(config_dict, outfile)
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    # add host_permissions
 | 
			
		||||
    target_path = ext
 | 
			
		||||
| 
						 | 
				
			
			@ -457,8 +470,11 @@ def dump_settings_to_maxbot_plus_extension(ext, config_dict, CONST_MAXBOT_CONFIG
 | 
			
		|||
 | 
			
		||||
    manifest_dict = None
 | 
			
		||||
    if os.path.isfile(target_path):
 | 
			
		||||
        try:
 | 
			
		||||
            with open(target_path) as json_data:
 | 
			
		||||
                manifest_dict = json.load(json_data)
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    local_remote_url_array = []
 | 
			
		||||
    local_remote_url = config_dict["advanced"]["remote_url"]
 | 
			
		||||
| 
						 | 
				
			
			@ -482,8 +498,11 @@ def dump_settings_to_maxbot_plus_extension(ext, config_dict, CONST_MAXBOT_CONFIG
 | 
			
		|||
 | 
			
		||||
        if is_manifest_changed:
 | 
			
		||||
            json_str = json.dumps(manifest_dict, indent=4)
 | 
			
		||||
            try:
 | 
			
		||||
                with open(target_path, 'w') as outfile:
 | 
			
		||||
                    outfile.write(json_str)
 | 
			
		||||
            except Exception as e:
 | 
			
		||||
                pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def dump_settings_to_maxblock_plus_extension(ext, config_dict, CONST_MAXBOT_CONFIG_FILE, CONST_MAXBLOCK_EXTENSION_FILTER):
 | 
			
		||||
| 
						 | 
				
			
			@ -501,9 +520,13 @@ def dump_settings_to_maxblock_plus_extension(ext, config_dict, CONST_MAXBOT_CONF
 | 
			
		|||
            os.unlink(target_path)
 | 
			
		||||
        except Exception as exc:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        with open(target_path, 'w') as outfile:
 | 
			
		||||
            config_dict["domain_filter"]=CONST_MAXBLOCK_EXTENSION_FILTER
 | 
			
		||||
            json.dump(config_dict, outfile)
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
# convert web string to reg pattern
 | 
			
		||||
def convert_string_to_pattern(my_str, dynamic_length=True):
 | 
			
		||||
| 
						 | 
				
			
			@ -1375,8 +1398,12 @@ def get_answer_list_from_user_guess_string(config_dict, CONST_MAXBOT_ANSWER_ONLI
 | 
			
		|||
    # load from internet.
 | 
			
		||||
    user_guess_string = ""
 | 
			
		||||
    if os.path.exists(CONST_MAXBOT_ANSWER_ONLINE_FILE):
 | 
			
		||||
        try:
 | 
			
		||||
            with open(CONST_MAXBOT_ANSWER_ONLINE_FILE, "r") as text_file:
 | 
			
		||||
                user_guess_string = text_file.readline()
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    if len(user_guess_string) > 0:
 | 
			
		||||
        user_guess_string = format_config_keyword_for_json(user_guess_string)
 | 
			
		||||
        try:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1 @@
 | 
			
		|||
$a_btn=$("#content").find("p > a > button[onclick]");
 | 
			
		||||
if($a_btn.length>0) {
 | 
			
		||||
	$click_event=$a_btn.attr("onclick");
 | 
			
		||||
	$a_btn.click();
 | 
			
		||||
}
 | 
			
		||||
$("body > div.buynow > a button[onclick].red").click();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,3 +3,4 @@ $("div#ad3").remove();
 | 
			
		|||
$("div#buyTicket").remove();
 | 
			
		||||
$("div#marquee").remove();
 | 
			
		||||
$("div.footer").remove();
 | 
			
		||||
$(".popoutBG").remove();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -122,7 +122,8 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://ticket.com.tw/application/utk01/utk0101_.aspx"
 | 
			
		||||
                "https://ticket.com.tw/application/utk01/utk0101_.aspx",
 | 
			
		||||
                "https://ticket.com.tw/application/UTK01/utk0101_.aspx"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
            "js": [
 | 
			
		||||
| 
						 | 
				
			
			@ -132,6 +133,7 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://ticket.com.tw/application/utk02/UTK0201_.aspx?PRODUCT_ID=*",
 | 
			
		||||
                "https://ticket.com.tw/application/UTK02/UTK0201_.aspx?PRODUCT_ID=*"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
| 
						 | 
				
			
			@ -143,6 +145,7 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://ticket.com.tw/application/utk02/UTK0201_00.aspx?PRODUCT_ID=*",
 | 
			
		||||
                "https://ticket.com.tw/application/UTK02/UTK0201_00.aspx?PRODUCT_ID=*"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
| 
						 | 
				
			
			@ -154,6 +157,7 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://ticket.com.tw/application/utk02/UTK0204_.aspx?*",
 | 
			
		||||
                "https://ticket.com.tw/application/UTK02/UTK0204_.aspx?*"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
| 
						 | 
				
			
			@ -165,9 +169,13 @@
 | 
			
		|||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://ticket.com.tw/application/UTK02/UTK0205_.aspx?*",
 | 
			
		||||
                "https://ticket.com.tw/application/UTK02/UTK0202_.aspx?*",
 | 
			
		||||
                "https://ticket.com.tw/application/utk02/UTK0202_.aspx?*",
 | 
			
		||||
                "https://ticket.com.tw/application/UTK02/UTK0205_.aspx?*",
 | 
			
		||||
                "https://ticket.com.tw/application/utk02/UTK0202_.aspx?*",
 | 
			
		||||
                "https://kham.com.tw/application/UTK02/UTK0205_.aspx?*",
 | 
			
		||||
                "https://kham.com.tw/application/UTK02/UTK0202_.aspx?*"
 | 
			
		||||
                "https://kham.com.tw/application/utk02/UTK0205_.aspx?*",
 | 
			
		||||
                "https://kham.com.tw/application/UTK02/UTK0202_.aspx?*",
 | 
			
		||||
                "https://kham.com.tw/application/utk02/UTK0202_.aspx?*"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
            "js": [
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +185,8 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://kham.com.tw/application/utk01/UTK0101_03.aspx"
 | 
			
		||||
                "https://kham.com.tw/application/utk01/UTK0101_03.aspx",
 | 
			
		||||
                "https://kham.com.tw/application/UTK01/UTK0101_03.aspx"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
            "js": [
 | 
			
		||||
| 
						 | 
				
			
			@ -187,6 +196,7 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://kham.com.tw/application/utk02/UTK0201_.aspx?PRODUCT_ID=*",
 | 
			
		||||
                "https://kham.com.tw/application/UTK02/UTK0201_.aspx?PRODUCT_ID=*"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
| 
						 | 
				
			
			@ -198,6 +208,7 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://kham.com.tw/application/utk02/UTK0201_00.aspx?PRODUCT_ID=*",
 | 
			
		||||
                "https://kham.com.tw/application/UTK02/UTK0201_00.aspx?PRODUCT_ID=*"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
| 
						 | 
				
			
			@ -209,7 +220,9 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://kham.com.tw/application/utk02/UTK0204_.aspx?*",
 | 
			
		||||
                "https://kham.com.tw/application/UTK02/UTK0204_.aspx?*",
 | 
			
		||||
                "https://kham.com.tw/application/utk02/UTK0201_000.aspx?PERFORMANCE_ID=*&PRODUCT_ID=*",
 | 
			
		||||
                "https://kham.com.tw/application/UTK02/UTK0201_000.aspx?PERFORMANCE_ID=*&PRODUCT_ID=*"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
| 
						 | 
				
			
			@ -230,6 +243,7 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://orders.ibon.com.tw/application/utk02/UTK0201_000.aspx?*",
 | 
			
		||||
                "https://orders.ibon.com.tw/application/UTK02/UTK0201_000.aspx?*"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
| 
						 | 
				
			
			@ -240,6 +254,7 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://orders.ibon.com.tw/application/utk02/UTK0201_000.aspx?*",
 | 
			
		||||
                "https://orders.ibon.com.tw/application/UTK02/UTK0201_000.aspx?*"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
| 
						 | 
				
			
			@ -251,7 +266,9 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://orders.ibon.com.tw/application/utk02/UTK0201_001.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*",
 | 
			
		||||
                "https://orders.ibon.com.tw/application/UTK02/UTK0201_001.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*",
 | 
			
		||||
                "https://orders.ibon.com.tw/application/utk02/UTK0202_.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*",
 | 
			
		||||
                "https://orders.ibon.com.tw/application/UTK02/UTK0202_.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
| 
						 | 
				
			
			@ -262,7 +279,9 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://orders.ibon.com.tw/application/utkK02/UTK0201_001.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*",
 | 
			
		||||
                "https://orders.ibon.com.tw/application/UTK02/UTK0201_001.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*",
 | 
			
		||||
                "https://orders.ibon.com.tw/application/utk02/UTK0202_.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*",
 | 
			
		||||
                "https://orders.ibon.com.tw/application/UTK02/UTK0202_.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
| 
						 | 
				
			
			@ -274,7 +293,9 @@
 | 
			
		|||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "matches": [
 | 
			
		||||
                "https://orders.ibon.com.tw/application/utk02/UTK0201_0.aspx?*PERFORMANCE_ID=*PRODUCT_ID=*",
 | 
			
		||||
                "https://orders.ibon.com.tw/application/UTK02/UTK0201_0.aspx?*PERFORMANCE_ID=*PRODUCT_ID=*",
 | 
			
		||||
                "https://orders.ibon.com.tw/application/utk02/UTK0201_0.aspx?*PRODUCT_ID=*PERFORMANCE_ID=*",
 | 
			
		||||
                "https://orders.ibon.com.tw/application/UTK02/UTK0201_0.aspx?*PRODUCT_ID=*PERFORMANCE_ID=*"
 | 
			
		||||
            ],
 | 
			
		||||
            "run_at": "document_end",
 | 
			
		||||
| 
						 | 
				
			
			@ -434,5 +455,5 @@
 | 
			
		|||
            ]
 | 
			
		||||
        }
 | 
			
		||||
    ],
 | 
			
		||||
    "version": "1.0.24"
 | 
			
		||||
    "version": "1.0.25"
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue