2024-01-05, support captcha on extension.
parent
a60d3fd899
commit
f2e0c654f8
|
@ -1,6 +1,10 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
#encoding=utf-8
|
#encoding=utf-8
|
||||||
#執行方式:python chrome_tixcraft.py 或 python3 chrome_tixcraft.py
|
#執行方式:python chrome_tixcraft.py 或 python3 chrome_tixcraft.py
|
||||||
|
#import jieba
|
||||||
|
#from DrissionPage import ChromiumPage
|
||||||
|
import argparse
|
||||||
|
import base64
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
@ -8,11 +12,15 @@ import pathlib
|
||||||
import platform
|
import platform
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
|
import ssl
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
#import jieba
|
import warnings
|
||||||
|
import webbrowser
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
import chromedriver_autoinstaller_max
|
||||||
|
import requests
|
||||||
from selenium import webdriver
|
from selenium import webdriver
|
||||||
from selenium.common.exceptions import (NoAlertPresentException,
|
from selenium.common.exceptions import (NoAlertPresentException,
|
||||||
NoSuchWindowException,
|
NoSuchWindowException,
|
||||||
|
@ -24,58 +32,35 @@ from selenium.webdriver.common.by import By
|
||||||
from selenium.webdriver.common.keys import Keys
|
from selenium.webdriver.common.keys import Keys
|
||||||
from selenium.webdriver.support import expected_conditions as EC
|
from selenium.webdriver.support import expected_conditions as EC
|
||||||
from selenium.webdriver.support.ui import Select, WebDriverWait
|
from selenium.webdriver.support.ui import Select, WebDriverWait
|
||||||
|
|
||||||
#from DrissionPage import ChromiumPage
|
|
||||||
|
|
||||||
logging.basicConfig()
|
|
||||||
logger = logging.getLogger('logger')
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
# for check kktix reg_info
|
|
||||||
import requests
|
|
||||||
from urllib3.exceptions import InsecureRequestWarning
|
from urllib3.exceptions import InsecureRequestWarning
|
||||||
|
|
||||||
warnings.simplefilter('ignore',InsecureRequestWarning)
|
from NonBrowser import NonBrowser
|
||||||
import ssl
|
|
||||||
|
|
||||||
ssl._create_default_https_context = ssl._create_unverified_context
|
|
||||||
|
|
||||||
# ocr
|
|
||||||
import base64
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import ddddocr
|
import ddddocr
|
||||||
from NonBrowser import NonBrowser
|
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
import argparse
|
CONST_APP_VERSION = "MaxBot (2024.01.05)"
|
||||||
import webbrowser
|
|
||||||
|
|
||||||
import chromedriver_autoinstaller_max
|
|
||||||
|
|
||||||
CONST_APP_VERSION = "MaxBot (2024.01.04)"
|
|
||||||
|
|
||||||
CONST_MAXBOT_CONFIG_FILE = "settings.json"
|
|
||||||
CONST_MAXBOT_LAST_URL_FILE = "MAXBOT_LAST_URL.txt"
|
|
||||||
CONST_MAXBOT_INT28_FILE = "MAXBOT_INT28_IDLE.txt"
|
|
||||||
CONST_MAXBOT_ANSWER_ONLINE_FILE = "MAXBOT_ONLINE_ANSWER.txt"
|
CONST_MAXBOT_ANSWER_ONLINE_FILE = "MAXBOT_ONLINE_ANSWER.txt"
|
||||||
|
CONST_MAXBOT_CONFIG_FILE = "settings.json"
|
||||||
|
CONST_MAXBOT_EXTENSION_NAME = "Maxbotplus_1.0.0"
|
||||||
|
CONST_MAXBOT_INT28_FILE = "MAXBOT_INT28_IDLE.txt"
|
||||||
|
CONST_MAXBOT_LAST_URL_FILE = "MAXBOT_LAST_URL.txt"
|
||||||
CONST_MAXBOT_QUESTION_FILE = "MAXBOT_QUESTION.txt"
|
CONST_MAXBOT_QUESTION_FILE = "MAXBOT_QUESTION.txt"
|
||||||
MAXBOT_EXTENSION_NAME = "Maxbotplus_1.0.0"
|
|
||||||
|
|
||||||
CONST_HOMEPAGE_DEFAULT = "https://tixcraft.com"
|
|
||||||
URL_CHROME_DRIVER = 'https://chromedriver.chromium.org/'
|
|
||||||
|
|
||||||
CONST_CHROME_VERSION_NOT_MATCH_EN="Please download the WebDriver version to match your browser version."
|
CONST_CHROME_VERSION_NOT_MATCH_EN="Please download the WebDriver version to match your browser version."
|
||||||
CONST_CHROME_VERSION_NOT_MATCH_TW="請下載與您瀏覽器相同版本的WebDriver版本,或更新您的瀏覽器版本。"
|
CONST_CHROME_VERSION_NOT_MATCH_TW="請下載與您瀏覽器相同版本的WebDriver版本,或更新您的瀏覽器版本。"
|
||||||
|
CONST_CHROME_DRIVER_WEBSITE = 'https://chromedriver.chromium.org/'
|
||||||
|
|
||||||
CONST_KKTIX_SIGN_IN_URL = "https://kktix.com/users/sign_in?back_to=%s"
|
|
||||||
CONST_FAMI_SIGN_IN_URL = "https://www.famiticket.com.tw/Home/User/SignIn"
|
|
||||||
CONST_CITYLINE_SIGN_IN_URL = "https://www.cityline.com/Login.html?targetUrl=https%3A%2F%2Fwww.cityline.com%2FEvents.html"
|
CONST_CITYLINE_SIGN_IN_URL = "https://www.cityline.com/Login.html?targetUrl=https%3A%2F%2Fwww.cityline.com%2FEvents.html"
|
||||||
CONST_URBTIX_SIGN_IN_URL = "https://www.urbtix.hk/member-login"
|
CONST_FAMI_SIGN_IN_URL = "https://www.famiticket.com.tw/Home/User/SignIn"
|
||||||
CONST_KHAM_SIGN_IN_URL = "https://kham.com.tw/application/UTK13/UTK1306_.aspx"
|
|
||||||
CONST_TICKET_SIGN_IN_URL = "https://ticket.com.tw/application/utk13/utk1306_.aspx"
|
|
||||||
CONST_HKTICKETING_SIGN_IN_URL = "https://premier.hkticketing.com/Secure/ShowLogin.aspx"
|
CONST_HKTICKETING_SIGN_IN_URL = "https://premier.hkticketing.com/Secure/ShowLogin.aspx"
|
||||||
|
CONST_KHAM_SIGN_IN_URL = "https://kham.com.tw/application/UTK13/UTK1306_.aspx"
|
||||||
|
CONST_KKTIX_SIGN_IN_URL = "https://kktix.com/users/sign_in?back_to=%s"
|
||||||
|
CONST_TICKET_SIGN_IN_URL = "https://ticket.com.tw/application/utk13/utk1306_.aspx"
|
||||||
|
CONST_URBTIX_SIGN_IN_URL = "https://www.urbtix.hk/member-login"
|
||||||
|
|
||||||
CONST_FROM_TOP_TO_BOTTOM = "from top to bottom"
|
CONST_FROM_TOP_TO_BOTTOM = "from top to bottom"
|
||||||
CONST_FROM_BOTTOM_TO_TOP = "from bottom to top"
|
CONST_FROM_BOTTOM_TO_TOP = "from bottom to top"
|
||||||
|
@ -91,10 +76,14 @@ CONST_OCR_CAPTCH_IMAGE_SOURCE_CANVAS = "canvas"
|
||||||
CONST_WEBDRIVER_TYPE_SELENIUM = "selenium"
|
CONST_WEBDRIVER_TYPE_SELENIUM = "selenium"
|
||||||
CONST_WEBDRIVER_TYPE_UC = "undetected_chromedriver"
|
CONST_WEBDRIVER_TYPE_UC = "undetected_chromedriver"
|
||||||
CONST_WEBDRIVER_TYPE_DP = "DrissionPage"
|
CONST_WEBDRIVER_TYPE_DP = "DrissionPage"
|
||||||
CONST_AUTO_RELOAD_RANDOM_DELAY_MAX_SECOND = 4
|
|
||||||
CONST_CHROME_FAMILY = ["chrome","edge","brave"]
|
CONST_CHROME_FAMILY = ["chrome","edge","brave"]
|
||||||
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
||||||
|
|
||||||
|
warnings.simplefilter('ignore',InsecureRequestWarning)
|
||||||
|
ssl._create_default_https_context = ssl._create_unverified_context
|
||||||
|
logging.basicConfig()
|
||||||
|
logger = logging.getLogger('logger')
|
||||||
|
|
||||||
def t_or_f(arg):
|
def t_or_f(arg):
|
||||||
ret = False
|
ret = False
|
||||||
ua = str(arg).upper()
|
ua = str(arg).upper()
|
||||||
|
@ -379,7 +368,7 @@ def is_all_alpha_or_numeric(text):
|
||||||
def get_favoriate_extension_path(webdriver_path, config_dict):
|
def get_favoriate_extension_path(webdriver_path, config_dict):
|
||||||
#print("webdriver_path:", webdriver_path)
|
#print("webdriver_path:", webdriver_path)
|
||||||
extension_list = []
|
extension_list = []
|
||||||
extension_list.append(os.path.join(webdriver_path, MAXBOT_EXTENSION_NAME + ".crx"))
|
extension_list.append(os.path.join(webdriver_path, CONST_MAXBOT_EXTENSION_NAME + ".crx"))
|
||||||
return extension_list
|
return extension_list
|
||||||
|
|
||||||
def get_chromedriver_path(webdriver_path):
|
def get_chromedriver_path(webdriver_path):
|
||||||
|
@ -408,12 +397,10 @@ def get_brave_bin_path():
|
||||||
return brave_path
|
return brave_path
|
||||||
|
|
||||||
def get_chrome_options(webdriver_path, config_dict):
|
def get_chrome_options(webdriver_path, config_dict):
|
||||||
browser=config_dict["browser"]
|
|
||||||
|
|
||||||
chrome_options = webdriver.ChromeOptions()
|
chrome_options = webdriver.ChromeOptions()
|
||||||
if browser=="edge":
|
if config_dict["browser"]=="edge":
|
||||||
chrome_options = webdriver.EdgeOptions()
|
chrome_options = webdriver.EdgeOptions()
|
||||||
if browser=="safari":
|
if config_dict["browser"]=="safari":
|
||||||
chrome_options = webdriver.SafariOptions()
|
chrome_options = webdriver.SafariOptions()
|
||||||
|
|
||||||
is_log_performace = False
|
is_log_performace = False
|
||||||
|
@ -424,7 +411,8 @@ def get_chrome_options(webdriver_path, config_dict):
|
||||||
break
|
break
|
||||||
|
|
||||||
if is_log_performace:
|
if is_log_performace:
|
||||||
chrome_options.set_capability("goog:loggingPrefs",{"performance": "ALL"})
|
if config_dict["browser"] in CONST_CHROME_FAMILY:
|
||||||
|
chrome_options.set_capability("goog:loggingPrefs",{"performance": "ALL"})
|
||||||
|
|
||||||
# PS: this is crx version.
|
# PS: this is crx version.
|
||||||
extension_list = get_favoriate_extension_path(webdriver_path, config_dict)
|
extension_list = get_favoriate_extension_path(webdriver_path, config_dict)
|
||||||
|
@ -454,7 +442,7 @@ def get_chrome_options(webdriver_path, config_dict):
|
||||||
if len(config_dict["advanced"]["proxy_server_port"]) > 2:
|
if len(config_dict["advanced"]["proxy_server_port"]) > 2:
|
||||||
chrome_options.add_argument('--proxy-server=%s' % config_dict["advanced"]["proxy_server_port"])
|
chrome_options.add_argument('--proxy-server=%s' % config_dict["advanced"]["proxy_server_port"])
|
||||||
|
|
||||||
if browser=="brave":
|
if config_dict["browser"]=="brave":
|
||||||
brave_path = get_brave_bin_path()
|
brave_path = get_brave_bin_path()
|
||||||
if os.path.exists(brave_path):
|
if os.path.exists(brave_path):
|
||||||
chrome_options.binary_location = brave_path
|
chrome_options.binary_location = brave_path
|
||||||
|
@ -488,7 +476,7 @@ def load_chromdriver_normal(config_dict, driver_type):
|
||||||
if not os.path.exists(chromedriver_path):
|
if not os.path.exists(chromedriver_path):
|
||||||
print("Please download chromedriver and extract zip to webdriver folder from this url:")
|
print("Please download chromedriver and extract zip to webdriver folder from this url:")
|
||||||
print("請下在面的網址下載與你chrome瀏覽器相同版本的chromedriver,解壓縮後放到webdriver目錄裡:")
|
print("請下在面的網址下載與你chrome瀏覽器相同版本的chromedriver,解壓縮後放到webdriver目錄裡:")
|
||||||
print(URL_CHROME_DRIVER)
|
print(CONST_CHROME_DRIVER_WEBSITE)
|
||||||
else:
|
else:
|
||||||
chrome_service = Service(chromedriver_path)
|
chrome_service = Service(chromedriver_path)
|
||||||
chrome_options = get_chrome_options(webdriver_path, config_dict)
|
chrome_options = get_chrome_options(webdriver_path, config_dict)
|
||||||
|
@ -592,14 +580,17 @@ def get_uc_options(uc, config_dict, webdriver_path):
|
||||||
ext = ext.replace('.crx','')
|
ext = ext.replace('.crx','')
|
||||||
if os.path.exists(ext):
|
if os.path.exists(ext):
|
||||||
# sync config.
|
# sync config.
|
||||||
if MAXBOT_EXTENSION_NAME in ext:
|
if CONST_MAXBOT_EXTENSION_NAME in ext:
|
||||||
target_path = ext
|
target_path = ext
|
||||||
target_path = os.path.join(target_path, "data")
|
target_path = os.path.join(target_path, "data")
|
||||||
target_path = os.path.join(target_path, "settings.json")
|
target_path = os.path.join(target_path, CONST_MAXBOT_CONFIG_FILE)
|
||||||
#print("save as to:", target_path)
|
#print("save as to:", target_path)
|
||||||
if os.path.exists(target_path):
|
try:
|
||||||
with open(target_path, 'w') as outfile:
|
os.unlink(target_path)
|
||||||
json.dump(config_dict, outfile)
|
except Exception as exc:
|
||||||
|
pass
|
||||||
|
with open(target_path, 'w') as outfile:
|
||||||
|
json.dump(config_dict, outfile)
|
||||||
load_extension_path += ("," + os.path.abspath(ext))
|
load_extension_path += ("," + os.path.abspath(ext))
|
||||||
|
|
||||||
if len(load_extension_path) > 0:
|
if len(load_extension_path) > 0:
|
||||||
|
@ -765,8 +756,6 @@ def get_driver_by_config(config_dict):
|
||||||
# entry point
|
# entry point
|
||||||
if homepage is None:
|
if homepage is None:
|
||||||
homepage = ""
|
homepage = ""
|
||||||
if len(homepage) == 0:
|
|
||||||
homepage = CONST_HOMEPAGE_DEFAULT
|
|
||||||
|
|
||||||
Root_Dir = get_app_root()
|
Root_Dir = get_app_root()
|
||||||
webdriver_path = os.path.join(Root_Dir, "webdriver")
|
webdriver_path = os.path.join(Root_Dir, "webdriver")
|
||||||
|
@ -3394,7 +3383,7 @@ def tixcraft_assign_ticket_number(driver, config_dict):
|
||||||
def tixcraft_ticket_main(driver, config_dict, ocr, Captcha_Browser, domain_name):
|
def tixcraft_ticket_main(driver, config_dict, ocr, Captcha_Browser, domain_name):
|
||||||
# use extension instead of selenium.
|
# use extension instead of selenium.
|
||||||
# checkbox javascrit code at chrome extension.
|
# checkbox javascrit code at chrome extension.
|
||||||
if config_dict["browser"] in ["firefox", "edge", "safari"]:
|
if not config_dict["browser"] in CONST_CHROME_FAMILY:
|
||||||
tixcraft_ticket_main_agree(driver, config_dict)
|
tixcraft_ticket_main_agree(driver, config_dict)
|
||||||
|
|
||||||
is_ticket_number_assigned = False
|
is_ticket_number_assigned = False
|
||||||
|
@ -4712,7 +4701,7 @@ if (typeof $.kkUser.checked_status_register_code === 'undefined') {
|
||||||
|
|
||||||
def kktix_reg_auto_reload(driver, url, config_dict):
|
def kktix_reg_auto_reload(driver, url, config_dict):
|
||||||
# auto reload javascrit code at chrome extension.
|
# auto reload javascrit code at chrome extension.
|
||||||
if config_dict["browser"] in ["firefox", "edge", "safari"]:
|
if not config_dict["browser"] in CONST_CHROME_FAMILY:
|
||||||
kktix_check_register_status(driver, url)
|
kktix_check_register_status(driver, url)
|
||||||
|
|
||||||
is_finish_checkbox_click = False
|
is_finish_checkbox_click = False
|
||||||
|
@ -12132,7 +12121,7 @@ def ticketplus_main(driver, url, config_dict, ocr, Captcha_Browser, ticketplus_d
|
||||||
|
|
||||||
is_reloading = False
|
is_reloading = False
|
||||||
# move below code to chrome extension.
|
# move below code to chrome extension.
|
||||||
if config_dict["browser"] in ["firefox", "edge", "safari"]:
|
if not config_dict["browser"] in CONST_CHROME_FAMILY:
|
||||||
is_reloading = ticketplus_order_auto_reload_coming_soon(driver)
|
is_reloading = ticketplus_order_auto_reload_coming_soon(driver)
|
||||||
|
|
||||||
if not is_reloading:
|
if not is_reloading:
|
||||||
|
|
|
@ -22,7 +22,7 @@ import sys
|
||||||
import threading
|
import threading
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
|
||||||
CONST_APP_VERSION = "MaxBot (2024.01.04)"
|
CONST_APP_VERSION = "MaxBot (2024.01.05)"
|
||||||
|
|
||||||
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": "\u7e41\u9ad4\u4e2d\u6587", "ticket_number": 2, "ocr_captcha": {"enable": true, "beta": true, "force_submit": true, "image_source": "canvas"}, "webdriver_type": "undetected_chromedriver", "date_auto_select": {"enable": true, "date_keyword": "", "mode": "random"}, "area_auto_select": {"enable": true, "mode": "random", "area_keyword": ""}, "keyword_exclude": "\"\u8f2a\u6905\",\"\u8eab\u969c\",\"\u8eab\u5fc3 \u969c\u7919\",\"Restricted View\",\"\u71c8\u67f1\u906e\u853d\",\"\u8996\u7dda\u4e0d\u5b8c\u6574\"", "kktix": {"auto_press_next_step_button": true, "auto_fill_ticket_number": true}, "tixcraft": {"pass_date_is_sold_out": true, "auto_reload_coming_soon_page": true}, "advanced": {"play_captcha_sound": {"enable": true, "filename": "ding-dong.wav"}, "tixcraft_sid": "", "ibonqware": "", "facebook_account": "", "kktix_account": "", "fami_account": "", "cityline_account": "", "urbtix_account": "", "hkticketing_account": "", "kham_account": "", "ticket_account": "", "udn_account": "", "ticketplus_account": "", "facebook_password": "", "kktix_password": "", "fami_password": "", "urbtix_password": "", "cityline_password": "", "hkticketing_password": "", "kham_password": "", "ticket_password": "", "udn_password": "", "ticketplus_password": "", "disable_adjacent_seat": false, "hide_some_image": true, "block_facebook_network": false, "headless": false, "verbose": false, "auto_guess_options": true, "user_guess_string": "", "online_dictionary_url": "", "auto_reload_page_interval": 0.1, "proxy_server_port": ""}}
|
{"homepage": "https://tixcraft.com", "browser": "chrome", "language": "\u7e41\u9ad4\u4e2d\u6587", "ticket_number": 2, "ocr_captcha": {"enable": true, "beta": true, "force_submit": true, "image_source": "canvas"}, "webdriver_type": "undetected_chromedriver", "date_auto_select": {"enable": true, "date_keyword": "", "mode": "random"}, "area_auto_select": {"enable": true, "mode": "random", "area_keyword": ""}, "keyword_exclude": "\"\u8f2a\u6905\",\"\u8eab\u969c\",\"\u8eab\u5fc3 \u969c\u7919\",\"Restricted View\",\"\u71c8\u67f1\u906e\u853d\",\"\u8996\u7dda\u4e0d\u5b8c\u6574\"", "kktix": {"auto_press_next_step_button": true, "auto_fill_ticket_number": true}, "tixcraft": {"pass_date_is_sold_out": true, "auto_reload_coming_soon_page": true}, "advanced": {"play_captcha_sound": {"enable": true, "filename": "ding-dong.wav"}, "tixcraft_sid": "", "ibonqware": "", "facebook_account": "", "kktix_account": "", "fami_account": "", "cityline_account": "", "urbtix_account": "", "hkticketing_account": "", "kham_account": "", "ticket_account": "", "udn_account": "", "ticketplus_account": "", "facebook_password": "", "kktix_password": "", "fami_password": "", "urbtix_password": "", "cityline_password": "", "hkticketing_password": "", "kham_password": "", "ticket_password": "", "udn_password": "", "ticketplus_password": "", "disable_adjacent_seat": false, "hide_some_image": false, "block_facebook_network": false, "headless": false, "verbose": false, "auto_guess_options": true, "user_guess_string": "", "remote_url": "\"http://127.0.0.1:16888/\"", "auto_reload_page_interval": 0.1, "proxy_server_port": ""}}
|
414
settings.py
414
settings.py
|
@ -13,11 +13,13 @@ except ImportError:
|
||||||
from tkinter import messagebox
|
from tkinter import messagebox
|
||||||
from tkinter.filedialog import asksaveasfilename
|
from tkinter.filedialog import asksaveasfilename
|
||||||
|
|
||||||
|
import asyncio
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import socket
|
import socket
|
||||||
|
import ssl
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
|
@ -27,26 +29,26 @@ import webbrowser
|
||||||
|
|
||||||
import pyperclip
|
import pyperclip
|
||||||
import requests
|
import requests
|
||||||
|
import tornado
|
||||||
|
from tornado.web import Application
|
||||||
from urllib3.exceptions import InsecureRequestWarning
|
from urllib3.exceptions import InsecureRequestWarning
|
||||||
|
|
||||||
warnings.simplefilter('ignore',InsecureRequestWarning)
|
try:
|
||||||
import ssl
|
import ddddocr
|
||||||
|
except Exception as exc:
|
||||||
|
pass
|
||||||
|
|
||||||
ssl._create_default_https_context = ssl._create_unverified_context
|
CONST_APP_VERSION = "MaxBot (2024.01.05)"
|
||||||
|
|
||||||
CONST_APP_VERSION = "MaxBot (2024.01.04)"
|
|
||||||
|
|
||||||
CONST_MAXBOT_CONFIG_FILE = "settings.json"
|
|
||||||
CONST_MAXBOT_LAST_URL_FILE = "MAXBOT_LAST_URL.txt"
|
|
||||||
CONST_MAXBOT_INT28_FILE = "MAXBOT_INT28_IDLE.txt"
|
|
||||||
CONST_MAXBOT_ANSWER_ONLINE_FILE = "MAXBOT_ONLINE_ANSWER.txt"
|
CONST_MAXBOT_ANSWER_ONLINE_FILE = "MAXBOT_ONLINE_ANSWER.txt"
|
||||||
|
CONST_MAXBOT_CONFIG_FILE = "settings.json"
|
||||||
|
CONST_MAXBOT_EXTENSION_NAME = "Maxbotplus_1.0.0"
|
||||||
|
CONST_MAXBOT_EXTENSION_STATUS_JSON = "status.json"
|
||||||
|
CONST_MAXBOT_INT28_FILE = "MAXBOT_INT28_IDLE.txt"
|
||||||
|
CONST_MAXBOT_LAST_URL_FILE = "MAXBOT_LAST_URL.txt"
|
||||||
CONST_MAXBOT_QUESTION_FILE = "MAXBOT_QUESTION.txt"
|
CONST_MAXBOT_QUESTION_FILE = "MAXBOT_QUESTION.txt"
|
||||||
|
|
||||||
MAXBOT_EXTENSION_NAME = "Maxbotplus_1.0.0"
|
CONST_SERVER_PORT = 16888
|
||||||
MAXBOT_EXTENSION_STATUS_JSON = "status.json"
|
|
||||||
|
|
||||||
CONST_SERVER_PORT_DEFAULT = 8888
|
|
||||||
CONST_SERVER_PORT = CONST_SERVER_PORT_DEFAULT
|
|
||||||
|
|
||||||
CONST_FROM_TOP_TO_BOTTOM = "from top to bottom"
|
CONST_FROM_TOP_TO_BOTTOM = "from top to bottom"
|
||||||
CONST_FROM_BOTTOM_TO_TOP = "from bottom to top"
|
CONST_FROM_BOTTOM_TO_TOP = "from bottom to top"
|
||||||
|
@ -54,23 +56,6 @@ CONST_CENTER = "center"
|
||||||
CONST_RANDOM = "random"
|
CONST_RANDOM = "random"
|
||||||
CONST_SELECT_ORDER_DEFAULT = CONST_RANDOM
|
CONST_SELECT_ORDER_DEFAULT = CONST_RANDOM
|
||||||
CONST_SELECT_OPTIONS_DEFAULT = (CONST_FROM_TOP_TO_BOTTOM, CONST_FROM_BOTTOM_TO_TOP, CONST_CENTER, CONST_RANDOM)
|
CONST_SELECT_OPTIONS_DEFAULT = (CONST_FROM_TOP_TO_BOTTOM, CONST_FROM_BOTTOM_TO_TOP, CONST_CENTER, CONST_RANDOM)
|
||||||
CONST_ADBLOCK_PLUS_ADVANCED_FILTER_DEFAULT = '''tixcraft.com###topAlert
|
|
||||||
tixcraft.com##.col-md-7.col-xs-12.mgt-16.mx-auto
|
|
||||||
tixcraft.com##.col-md-7.col-xs-12.mgt-16.text-center
|
|
||||||
tixcraft.com##.footer.clearfix
|
|
||||||
tixcraft.com##.page-info.row.line-btm.mg-0
|
|
||||||
tixcraft.com##.row.justify-content-start.navbar-location
|
|
||||||
tixcraft.com##.topBar.alert-box.emergency
|
|
||||||
||facebook.com/plugins/share_button.php
|
|
||||||
||google-analytics.com^
|
|
||||||
||googletagmanager.com^
|
|
||||||
||googletagservices.com^
|
|
||||||
||play.google.com^
|
|
||||||
||player.youku.com^
|
|
||||||
||twitter.com^
|
|
||||||
||youtube.com/iframe_api^
|
|
||||||
||e2elog.fetnet.net^
|
|
||||||
'''
|
|
||||||
CONST_EXCLUDE_DEFAULT = "\"輪椅\",\"身障\",\"身心 障礙\",\"Restricted View\",\"燈柱遮蔽\",\"視線不完整\""
|
CONST_EXCLUDE_DEFAULT = "\"輪椅\",\"身障\",\"身心 障礙\",\"Restricted View\",\"燈柱遮蔽\",\"視線不完整\""
|
||||||
CONST_CAPTCHA_SOUND_FILENAME_DEFAULT = "ding-dong.wav"
|
CONST_CAPTCHA_SOUND_FILENAME_DEFAULT = "ding-dong.wav"
|
||||||
CONST_HOMEPAGE_DEFAULT = "https://tixcraft.com"
|
CONST_HOMEPAGE_DEFAULT = "https://tixcraft.com"
|
||||||
|
@ -81,7 +66,6 @@ CONST_OCR_CAPTCH_IMAGE_SOURCE_CANVAS = "canvas"
|
||||||
CONST_WEBDRIVER_TYPE_SELENIUM = "selenium"
|
CONST_WEBDRIVER_TYPE_SELENIUM = "selenium"
|
||||||
CONST_WEBDRIVER_TYPE_UC = "undetected_chromedriver"
|
CONST_WEBDRIVER_TYPE_UC = "undetected_chromedriver"
|
||||||
CONST_WEBDRIVER_TYPE_DP = "DrissionPage"
|
CONST_WEBDRIVER_TYPE_DP = "DrissionPage"
|
||||||
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
|
|
||||||
|
|
||||||
CONST_SUPPORTED_SITES = ["https://kktix.com"
|
CONST_SUPPORTED_SITES = ["https://kktix.com"
|
||||||
,"https://tixcraft.com (拓元)"
|
,"https://tixcraft.com (拓元)"
|
||||||
|
@ -102,9 +86,9 @@ CONST_SUPPORTED_SITES = ["https://kktix.com"
|
||||||
,"https://ticketing.galaxymacau.com/ (澳門銀河)"
|
,"https://ticketing.galaxymacau.com/ (澳門銀河)"
|
||||||
,"http://premier.ticketek.com.au"
|
,"http://premier.ticketek.com.au"
|
||||||
]
|
]
|
||||||
# 目前機器人已失效, 因為官方的 reCaptcha 可以檢測出機器人。
|
|
||||||
'''
|
warnings.simplefilter('ignore',InsecureRequestWarning)
|
||||||
'''
|
ssl._create_default_https_context = ssl._create_unverified_context
|
||||||
|
|
||||||
translate={}
|
translate={}
|
||||||
|
|
||||||
|
@ -132,10 +116,13 @@ def load_translate():
|
||||||
en_us["and"] = 'And with'
|
en_us["and"] = 'And with'
|
||||||
|
|
||||||
en_us["local_dictionary"] = 'Local Dictionary'
|
en_us["local_dictionary"] = 'Local Dictionary'
|
||||||
en_us["online_dictionary_url"] = 'Online Dictionary URL'
|
en_us["remote_url"] = 'Remote URL'
|
||||||
|
en_us["server_url"] = 'Server URL'
|
||||||
en_us["auto_guess_options"] = 'Guess Options in Question'
|
en_us["auto_guess_options"] = 'Guess Options in Question'
|
||||||
en_us["user_guess_string"] = 'Fill Answers in Question'
|
en_us["user_guess_string"] = 'Fill Answers in Question'
|
||||||
en_us["preview"] = 'Preview'
|
en_us["preview"] = 'Preview'
|
||||||
|
en_us["question"] = 'Question'
|
||||||
|
en_us["answer"] = 'Answer'
|
||||||
|
|
||||||
en_us["date_auto_select"] = 'Date Auto Select'
|
en_us["date_auto_select"] = 'Date Auto Select'
|
||||||
en_us["date_select_order"] = 'Date select order'
|
en_us["date_select_order"] = 'Date select order'
|
||||||
|
@ -173,6 +160,7 @@ def load_translate():
|
||||||
en_us["preference"] = 'Preference'
|
en_us["preference"] = 'Preference'
|
||||||
en_us["advanced"] = 'Advanced'
|
en_us["advanced"] = 'Advanced'
|
||||||
en_us["verification_word"] = "Verification code"
|
en_us["verification_word"] = "Verification code"
|
||||||
|
en_us["maxbot_server"] = 'Server'
|
||||||
en_us["autofill"] = 'Autofill'
|
en_us["autofill"] = 'Autofill'
|
||||||
en_us["runtime"] = 'Runtime'
|
en_us["runtime"] = 'Runtime'
|
||||||
en_us["about"] = 'About'
|
en_us["about"] = 'About'
|
||||||
|
@ -235,10 +223,13 @@ def load_translate():
|
||||||
zh_tw["and"] = '而且(同列)'
|
zh_tw["and"] = '而且(同列)'
|
||||||
|
|
||||||
zh_tw["local_dictionary"] = '使用者自定字典'
|
zh_tw["local_dictionary"] = '使用者自定字典'
|
||||||
zh_tw["online_dictionary_url"] = '線上字典檔網址'
|
zh_tw["remote_url"] = '遠端網址'
|
||||||
|
zh_tw["server_url"] = '伺服器網址'
|
||||||
zh_tw["auto_guess_options"] = '自動猜測驗證問題'
|
zh_tw["auto_guess_options"] = '自動猜測驗證問題'
|
||||||
zh_tw["user_guess_string"] = '驗證問題中的答案清單'
|
zh_tw["user_guess_string"] = '驗證問題中的答案清單'
|
||||||
zh_tw["preview"] = '預覽'
|
zh_tw["preview"] = '預覽'
|
||||||
|
zh_tw["question"] = '驗證問題'
|
||||||
|
zh_tw["answer"] = '答案'
|
||||||
|
|
||||||
zh_tw["date_auto_select"] = '日期自動點選'
|
zh_tw["date_auto_select"] = '日期自動點選'
|
||||||
zh_tw["date_select_order"] = '日期排序方式'
|
zh_tw["date_select_order"] = '日期排序方式'
|
||||||
|
@ -275,6 +266,7 @@ def load_translate():
|
||||||
zh_tw["preference"] = '偏好設定'
|
zh_tw["preference"] = '偏好設定'
|
||||||
zh_tw["advanced"] = '進階設定'
|
zh_tw["advanced"] = '進階設定'
|
||||||
zh_tw["verification_word"] = "驗證問題"
|
zh_tw["verification_word"] = "驗證問題"
|
||||||
|
zh_tw["maxbot_server"] = '伺服器'
|
||||||
zh_tw["autofill"] = '自動填表單'
|
zh_tw["autofill"] = '自動填表單'
|
||||||
zh_tw["runtime"] = '執行階段'
|
zh_tw["runtime"] = '執行階段'
|
||||||
zh_tw["about"] = '關於'
|
zh_tw["about"] = '關於'
|
||||||
|
@ -338,10 +330,13 @@ def load_translate():
|
||||||
zh_cn["and"] = '而且(同列)'
|
zh_cn["and"] = '而且(同列)'
|
||||||
|
|
||||||
zh_cn["local_dictionary"] = '本地字典'
|
zh_cn["local_dictionary"] = '本地字典'
|
||||||
zh_cn["online_dictionary_url"] = '在线词典网址'
|
zh_cn["remote_url"] = '远端网址'
|
||||||
|
zh_cn["server_url"] = '服务器地址'
|
||||||
zh_cn["auto_guess_options"] = '自动猜测验证问题'
|
zh_cn["auto_guess_options"] = '自动猜测验证问题'
|
||||||
zh_cn["user_guess_string"] = '验证问题的答案列表'
|
zh_cn["user_guess_string"] = '验证问题的答案列表'
|
||||||
zh_cn["preview"] = '预览'
|
zh_cn["preview"] = '预览'
|
||||||
|
zh_cn["question"] = '验证问题'
|
||||||
|
zh_cn["answer"] = '答案'
|
||||||
|
|
||||||
zh_cn["date_auto_select"] = '日期自动点选'
|
zh_cn["date_auto_select"] = '日期自动点选'
|
||||||
zh_cn["date_select_order"] = '日期排序方式'
|
zh_cn["date_select_order"] = '日期排序方式'
|
||||||
|
@ -378,6 +373,7 @@ def load_translate():
|
||||||
zh_cn["preference"] = '偏好设定'
|
zh_cn["preference"] = '偏好设定'
|
||||||
zh_cn["advanced"] = '进阶设定'
|
zh_cn["advanced"] = '进阶设定'
|
||||||
zh_cn["verification_word"] = "验证字"
|
zh_cn["verification_word"] = "验证字"
|
||||||
|
zh_cn["maxbot_server"] = '伺服器'
|
||||||
zh_cn["autofill"] = '自动填表单'
|
zh_cn["autofill"] = '自动填表单'
|
||||||
zh_cn["runtime"] = '运行'
|
zh_cn["runtime"] = '运行'
|
||||||
zh_cn["about"] = '关于'
|
zh_cn["about"] = '关于'
|
||||||
|
@ -442,10 +438,13 @@ def load_translate():
|
||||||
ja_jp["and"] = 'そして(同列)'
|
ja_jp["and"] = 'そして(同列)'
|
||||||
|
|
||||||
ja_jp["local_dictionary"] = 'ローカル辞書'
|
ja_jp["local_dictionary"] = 'ローカル辞書'
|
||||||
ja_jp["online_dictionary_url"] = 'オンライン辞書のURL'
|
ja_jp["remote_url"] = 'リモートURL'
|
||||||
|
ja_jp["server_url"] = 'サーバーURL'
|
||||||
ja_jp["auto_guess_options"] = '自動推測検証問題'
|
ja_jp["auto_guess_options"] = '自動推測検証問題'
|
||||||
ja_jp["user_guess_string"] = '検証用の質問の回答リスト'
|
ja_jp["user_guess_string"] = '検証用の質問の回答リスト'
|
||||||
ja_jp["preview"] = 'プレビュー'
|
ja_jp["preview"] = 'プレビュー'
|
||||||
|
ja_jp["question"] = '質問'
|
||||||
|
ja_jp["answer"] = '答え'
|
||||||
|
|
||||||
ja_jp["date_auto_select"] = '日付自動選択'
|
ja_jp["date_auto_select"] = '日付自動選択'
|
||||||
ja_jp["date_select_order"] = '日付のソート方法'
|
ja_jp["date_select_order"] = '日付のソート方法'
|
||||||
|
@ -482,6 +481,7 @@ def load_translate():
|
||||||
ja_jp["preference"] = '設定'
|
ja_jp["preference"] = '設定'
|
||||||
ja_jp["advanced"] = '高度な設定'
|
ja_jp["advanced"] = '高度な設定'
|
||||||
ja_jp["verification_word"] = "確認の言葉"
|
ja_jp["verification_word"] = "確認の言葉"
|
||||||
|
ja_jp["maxbot_server"] = 'サーバ'
|
||||||
ja_jp["autofill"] = 'オートフィル'
|
ja_jp["autofill"] = 'オートフィル'
|
||||||
ja_jp["runtime"] = 'ランタイム'
|
ja_jp["runtime"] = 'ランタイム'
|
||||||
ja_jp["about"] = '情報'
|
ja_jp["about"] = '情報'
|
||||||
|
@ -681,7 +681,7 @@ def get_default_config():
|
||||||
config_dict["advanced"]["verbose"] = False
|
config_dict["advanced"]["verbose"] = False
|
||||||
config_dict["advanced"]["auto_guess_options"] = True
|
config_dict["advanced"]["auto_guess_options"] = True
|
||||||
config_dict["advanced"]["user_guess_string"] = ""
|
config_dict["advanced"]["user_guess_string"] = ""
|
||||||
config_dict["advanced"]["online_dictionary_url"] = ""
|
config_dict["advanced"]["remote_url"] = "http://127.0.0.1:%d/" % (CONST_SERVER_PORT)
|
||||||
|
|
||||||
config_dict["advanced"]["auto_reload_page_interval"] = 0.1
|
config_dict["advanced"]["auto_reload_page_interval"] = 0.1
|
||||||
config_dict["advanced"]["proxy_server_port"] = ""
|
config_dict["advanced"]["proxy_server_port"] = ""
|
||||||
|
@ -765,7 +765,7 @@ def btn_save_act(language_code, slience_mode=False):
|
||||||
global chk_state_area_auto_select
|
global chk_state_area_auto_select
|
||||||
global txt_area_keyword
|
global txt_area_keyword
|
||||||
global txt_keyword_exclude
|
global txt_keyword_exclude
|
||||||
global txt_online_dictionary_url
|
global txt_remote_url
|
||||||
|
|
||||||
global combo_date_auto_select_mode
|
global combo_date_auto_select_mode
|
||||||
global combo_area_auto_select_mode
|
global combo_area_auto_select_mode
|
||||||
|
@ -872,8 +872,8 @@ def btn_save_act(language_code, slience_mode=False):
|
||||||
user_guess_string = txt_user_guess_string.get("1.0",END).strip()
|
user_guess_string = txt_user_guess_string.get("1.0",END).strip()
|
||||||
user_guess_string = format_config_keyword_for_json(user_guess_string)
|
user_guess_string = format_config_keyword_for_json(user_guess_string)
|
||||||
|
|
||||||
online_dictionary_url = txt_online_dictionary_url.get("1.0",END).strip()
|
remote_url = txt_remote_url.get("1.0",END).strip()
|
||||||
online_dictionary_url = format_config_keyword_for_json(online_dictionary_url)
|
remote_url = format_config_keyword_for_json(remote_url)
|
||||||
|
|
||||||
# test keyword format.
|
# test keyword format.
|
||||||
if is_all_data_correct:
|
if is_all_data_correct:
|
||||||
|
@ -904,19 +904,19 @@ def btn_save_act(language_code, slience_mode=False):
|
||||||
is_all_data_correct = False
|
is_all_data_correct = False
|
||||||
|
|
||||||
if is_all_data_correct:
|
if is_all_data_correct:
|
||||||
if len(online_dictionary_url) > 0:
|
if len(remote_url) > 0:
|
||||||
try:
|
try:
|
||||||
test_array = json.loads("["+ online_dictionary_url +"]")
|
test_array = json.loads("["+ remote_url +"]")
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
print(exc)
|
print(exc)
|
||||||
messagebox.showinfo(translate[language_code]["save"], "Error:" + translate[language_code]["online_dictionary_url"])
|
messagebox.showinfo(translate[language_code]["save"], "Error:" + translate[language_code]["remote_url"])
|
||||||
is_all_data_correct = False
|
is_all_data_correct = False
|
||||||
|
|
||||||
if is_all_data_correct:
|
if is_all_data_correct:
|
||||||
config_dict["area_auto_select"]["area_keyword"] = area_keyword
|
config_dict["area_auto_select"]["area_keyword"] = area_keyword
|
||||||
config_dict["keyword_exclude"] = keyword_exclude
|
config_dict["keyword_exclude"] = keyword_exclude
|
||||||
config_dict["advanced"]["user_guess_string"] = user_guess_string
|
config_dict["advanced"]["user_guess_string"] = user_guess_string
|
||||||
config_dict["advanced"]["online_dictionary_url"] = online_dictionary_url
|
config_dict["advanced"]["remote_url"] = remote_url
|
||||||
|
|
||||||
if is_all_data_correct:
|
if is_all_data_correct:
|
||||||
config_dict["area_auto_select"]["enable"] = bool(chk_state_area_auto_select.get())
|
config_dict["area_auto_select"]["enable"] = bool(chk_state_area_auto_select.get())
|
||||||
|
@ -1045,13 +1045,12 @@ def write_string_to_file(filename, data):
|
||||||
if not outfile is None:
|
if not outfile is None:
|
||||||
outfile.write("%s" % data)
|
outfile.write("%s" % data)
|
||||||
|
|
||||||
def save_url_to_file(new_online_dictionary_url, force_write = False):
|
def save_url_to_file(new_remote_url, force_write = False):
|
||||||
html_text = ""
|
html_text = ""
|
||||||
if len(new_online_dictionary_url) > 0:
|
if len(new_remote_url) > 0:
|
||||||
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.5, allow_redirects=False)
|
html_result = requests.get(new_remote_url , timeout=0.5, allow_redirects=False)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
html_result = None
|
html_result = None
|
||||||
#print(exc)
|
#print(exc)
|
||||||
|
@ -1076,17 +1075,17 @@ def save_url_to_file(new_online_dictionary_url, force_write = False):
|
||||||
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_remote_url
|
||||||
online_dictionary_url = ""
|
remote_url = ""
|
||||||
try:
|
try:
|
||||||
online_dictionary_url = txt_online_dictionary_url.get("1.0",END).strip()
|
remote_url = txt_remote_url.get("1.0",END).strip()
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
pass
|
pass
|
||||||
online_dictionary_url = format_config_keyword_for_json(online_dictionary_url)
|
remote_url = format_config_keyword_for_json(remote_url)
|
||||||
if len(online_dictionary_url) > 0:
|
if len(remote_url) > 0:
|
||||||
url_array = []
|
url_array = []
|
||||||
try:
|
try:
|
||||||
url_array = json.loads("["+ online_dictionary_url +"]")
|
url_array = json.loads("["+ remote_url +"]")
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
url_array = []
|
url_array = []
|
||||||
|
|
||||||
|
@ -1094,7 +1093,7 @@ def btn_preview_text_clicked():
|
||||||
if len(url_array)==1:
|
if len(url_array)==1:
|
||||||
force_write = True
|
force_write = True
|
||||||
for each_url in url_array:
|
for each_url in url_array:
|
||||||
#print("new_online_dictionary_url:", new_online_dictionary_url)
|
#print("new_remote_url:", new_remote_url)
|
||||||
is_write_to_file = save_url_to_file(each_url, force_write=force_write)
|
is_write_to_file = save_url_to_file(each_url, force_write=force_write)
|
||||||
if is_write_to_file:
|
if is_write_to_file:
|
||||||
break
|
break
|
||||||
|
@ -1144,19 +1143,9 @@ def run_python_script(script_name):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def btn_open_text_server_clicked():
|
def btn_open_text_server_clicked():
|
||||||
global txt_online_dictionary_url
|
global tab4
|
||||||
online_dictionary_url = ""
|
global tabControl
|
||||||
try:
|
tabControl.select(tab4)
|
||||||
online_dictionary_url = txt_online_dictionary_url.get("1.0",END).strip()
|
|
||||||
except Exception as exc:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if online_dictionary_url=="":
|
|
||||||
local_ip = get_ip_address()
|
|
||||||
ip_address = "http://%s:%d/" % (local_ip,CONST_SERVER_PORT)
|
|
||||||
txt_online_dictionary_url.insert("1.0", ip_address)
|
|
||||||
|
|
||||||
run_python_script("text_server")
|
|
||||||
|
|
||||||
def btn_preview_sound_clicked():
|
def btn_preview_sound_clicked():
|
||||||
global txt_captcha_sound_filename
|
global txt_captcha_sound_filename
|
||||||
|
@ -1195,9 +1184,6 @@ def btn_donate_clicked():
|
||||||
def btn_help_clicked():
|
def btn_help_clicked():
|
||||||
webbrowser.open(URL_HELP)
|
webbrowser.open(URL_HELP)
|
||||||
|
|
||||||
def btn_copy_clicked():
|
|
||||||
pyperclip.copy(CONST_ADBLOCK_PLUS_ADVANCED_FILTER_DEFAULT)
|
|
||||||
|
|
||||||
def callbackLanguageOnChange(event):
|
def callbackLanguageOnChange(event):
|
||||||
applyNewLanguage()
|
applyNewLanguage()
|
||||||
|
|
||||||
|
@ -1273,8 +1259,11 @@ def applyNewLanguage():
|
||||||
|
|
||||||
global chk_headless
|
global chk_headless
|
||||||
global chk_verbose
|
global chk_verbose
|
||||||
global lbl_online_dictionary_url
|
global lbl_remote_url
|
||||||
|
global lbl_server_url
|
||||||
global lbl_online_dictionary_preview
|
global lbl_online_dictionary_preview
|
||||||
|
global lbl_question
|
||||||
|
global lbl_answer
|
||||||
global chk_auto_guess_options
|
global chk_auto_guess_options
|
||||||
|
|
||||||
global tabControl
|
global tabControl
|
||||||
|
@ -1333,9 +1322,12 @@ def applyNewLanguage():
|
||||||
lbl_headless.config(text=translate[language_code]["headless"])
|
lbl_headless.config(text=translate[language_code]["headless"])
|
||||||
lbl_verbose.config(text=translate[language_code]["verbose"])
|
lbl_verbose.config(text=translate[language_code]["verbose"])
|
||||||
|
|
||||||
lbl_online_dictionary_url.config(text=translate[language_code]["online_dictionary_url"])
|
lbl_remote_url.config(text=translate[language_code]["remote_url"])
|
||||||
|
lbl_server_url.config(text=translate[language_code]["server_url"])
|
||||||
lbl_online_dictionary_preview.config(text=translate[language_code]["preview"])
|
lbl_online_dictionary_preview.config(text=translate[language_code]["preview"])
|
||||||
lbl_auto_guess_options.config(text=translate[language_code]["auto_guess_options"])
|
lbl_auto_guess_options.config(text=translate[language_code]["auto_guess_options"])
|
||||||
|
lbl_question.config(text=translate[language_code]["question"])
|
||||||
|
lbl_answer.config(text=translate[language_code]["answer"])
|
||||||
|
|
||||||
lbl_maxbot_status.config(text=translate[language_code]["running_status"])
|
lbl_maxbot_status.config(text=translate[language_code]["running_status"])
|
||||||
lbl_maxbot_last_url.config(text=translate[language_code]["running_url"])
|
lbl_maxbot_last_url.config(text=translate[language_code]["running_url"])
|
||||||
|
@ -1361,9 +1353,10 @@ def applyNewLanguage():
|
||||||
tabControl.tab(0, text=translate[language_code]["preference"])
|
tabControl.tab(0, text=translate[language_code]["preference"])
|
||||||
tabControl.tab(1, text=translate[language_code]["advanced"])
|
tabControl.tab(1, text=translate[language_code]["advanced"])
|
||||||
tabControl.tab(2, text=translate[language_code]["verification_word"])
|
tabControl.tab(2, text=translate[language_code]["verification_word"])
|
||||||
tabControl.tab(3, text=translate[language_code]["autofill"])
|
tabControl.tab(3, text=translate[language_code]["maxbot_server"])
|
||||||
tabControl.tab(4, text=translate[language_code]["runtime"])
|
tabControl.tab(4, text=translate[language_code]["autofill"])
|
||||||
tabControl.tab(5, text=translate[language_code]["about"])
|
tabControl.tab(5, text=translate[language_code]["runtime"])
|
||||||
|
tabControl.tab(6, text=translate[language_code]["about"])
|
||||||
|
|
||||||
global lbl_tixcraft_sid
|
global lbl_tixcraft_sid
|
||||||
global lbl_ibon_ibonqware
|
global lbl_ibon_ibonqware
|
||||||
|
@ -2114,14 +2107,14 @@ def VerificationTab(root, config_dict, language_code, UI_PADDING_X):
|
||||||
|
|
||||||
group_row_count+=1
|
group_row_count+=1
|
||||||
|
|
||||||
global lbl_online_dictionary_url
|
global lbl_remote_url
|
||||||
lbl_online_dictionary_url = Label(frame_group_header, text=translate[language_code]['online_dictionary_url'])
|
lbl_remote_url = Label(frame_group_header, text=translate[language_code]['remote_url'])
|
||||||
lbl_online_dictionary_url.grid(column=0, row=group_row_count, sticky = E+N)
|
lbl_remote_url.grid(column=0, row=group_row_count, sticky = E+N)
|
||||||
|
|
||||||
global txt_online_dictionary_url
|
global txt_remote_url
|
||||||
txt_online_dictionary_url = Text(frame_group_header, width=30, height=4)
|
txt_remote_url = Text(frame_group_header, width=30, height=4)
|
||||||
txt_online_dictionary_url.grid(column=1, row=group_row_count, sticky = W)
|
txt_remote_url.grid(column=1, row=group_row_count, sticky = W)
|
||||||
txt_online_dictionary_url.insert("1.0", config_dict['advanced']["online_dictionary_url"].strip())
|
txt_remote_url.insert("1.0", config_dict['advanced']["remote_url"].strip())
|
||||||
|
|
||||||
icon_preview_text_filename = "icon_chrome_4.gif"
|
icon_preview_text_filename = "icon_chrome_4.gif"
|
||||||
icon_preview_text_img = PhotoImage(file=icon_preview_text_filename)
|
icon_preview_text_img = PhotoImage(file=icon_preview_text_filename)
|
||||||
|
@ -2159,6 +2152,70 @@ def VerificationTab(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 ServerTab(root, config_dict, language_code, UI_PADDING_X):
|
||||||
|
row_count = 0
|
||||||
|
|
||||||
|
frame_group_header = Frame(root)
|
||||||
|
group_row_count = 0
|
||||||
|
|
||||||
|
global lbl_server_url
|
||||||
|
lbl_server_url = Label(frame_group_header, text=translate[language_code]['server_url'])
|
||||||
|
lbl_server_url.grid(column=0, row=group_row_count, sticky = E)
|
||||||
|
|
||||||
|
local_ip = get_ip_address()
|
||||||
|
ip_address = "http://%s:%d/" % (local_ip, CONST_SERVER_PORT)
|
||||||
|
global lbl_ip_address
|
||||||
|
lbl_ip_address = Label(frame_group_header, text=ip_address)
|
||||||
|
lbl_ip_address.grid(column=1, row=group_row_count, sticky = W)
|
||||||
|
|
||||||
|
icon_copy_filename = "icon_copy_2.gif"
|
||||||
|
icon_copy_img = PhotoImage(file=icon_copy_filename)
|
||||||
|
|
||||||
|
lbl_icon_copy_ip = Label(frame_group_header, image=icon_copy_img, cursor="hand2")
|
||||||
|
lbl_icon_copy_ip.image = icon_copy_img
|
||||||
|
lbl_icon_copy_ip.grid(column=2, row=group_row_count, sticky = W+N)
|
||||||
|
lbl_icon_copy_ip.bind("<Button-1>", lambda e: btn_copy_ip_clicked())
|
||||||
|
|
||||||
|
group_row_count += 1
|
||||||
|
|
||||||
|
global lbl_question
|
||||||
|
lbl_question = Label(frame_group_header, text=translate[language_code]['question'])
|
||||||
|
lbl_question.grid(column=0, row=group_row_count, sticky = E+N)
|
||||||
|
|
||||||
|
global txt_question
|
||||||
|
txt_question = Text(frame_group_header, width=50, height=22)
|
||||||
|
txt_question.grid(column=1, row=group_row_count, sticky = W)
|
||||||
|
txt_question.insert("1.0", "")
|
||||||
|
|
||||||
|
lbl_icon_copy_question = Label(frame_group_header, image=icon_copy_img, cursor="hand2")
|
||||||
|
lbl_icon_copy_question.image = icon_copy_img
|
||||||
|
#lbl_icon_copy_question.grid(column=2, row=group_row_count, sticky = W+N)
|
||||||
|
lbl_icon_copy_question.bind("<Button-1>", lambda e: btn_copy_question_clicked())
|
||||||
|
|
||||||
|
icon_query_filename = "icon_query_5.gif"
|
||||||
|
icon_query_img = PhotoImage(file=icon_query_filename)
|
||||||
|
|
||||||
|
lbl_icon_query_question = Label(frame_group_header, image=icon_query_img, cursor="hand2")
|
||||||
|
lbl_icon_query_question.image = icon_query_img
|
||||||
|
lbl_icon_query_question.grid(column=2, row=group_row_count, sticky = W+N)
|
||||||
|
lbl_icon_query_question.bind("<Button-1>", lambda e: btn_query_question_clicked())
|
||||||
|
|
||||||
|
group_row_count += 1
|
||||||
|
|
||||||
|
global lbl_answer
|
||||||
|
lbl_answer = Label(frame_group_header, text=translate[language_code]['answer'])
|
||||||
|
lbl_answer.grid(column=0, row=group_row_count, sticky = E)
|
||||||
|
|
||||||
|
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('<Control-v>', lambda e: btn_paste_answer_by_user())
|
||||||
|
|
||||||
|
frame_group_header.grid(column=0, row=row_count, padx=UI_PADDING_X, pady=15)
|
||||||
|
|
||||||
|
|
||||||
def AutofillTab(root, config_dict, language_code, UI_PADDING_X):
|
def AutofillTab(root, config_dict, language_code, UI_PADDING_X):
|
||||||
row_count = 0
|
row_count = 0
|
||||||
|
|
||||||
|
@ -2362,6 +2419,7 @@ def AutofillTab(root, config_dict, language_code, UI_PADDING_X):
|
||||||
def resetful_api_timer():
|
def resetful_api_timer():
|
||||||
while True:
|
while True:
|
||||||
btn_preview_text_clicked()
|
btn_preview_text_clicked()
|
||||||
|
preview_question_text_file()
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
|
|
||||||
def settings_timer():
|
def settings_timer():
|
||||||
|
@ -2372,9 +2430,9 @@ def settings_timer():
|
||||||
def clean_extension_status():
|
def clean_extension_status():
|
||||||
Root_Dir = get_app_root()
|
Root_Dir = get_app_root()
|
||||||
webdriver_path = os.path.join(Root_Dir, "webdriver")
|
webdriver_path = os.path.join(Root_Dir, "webdriver")
|
||||||
target_path = os.path.join(webdriver_path, MAXBOT_EXTENSION_NAME)
|
target_path = os.path.join(webdriver_path, CONST_MAXBOT_EXTENSION_NAME)
|
||||||
target_path = os.path.join(target_path, "data")
|
target_path = os.path.join(target_path, "data")
|
||||||
target_path = os.path.join(target_path, MAXBOT_EXTENSION_STATUS_JSON)
|
target_path = os.path.join(target_path, CONST_MAXBOT_EXTENSION_STATUS_JSON)
|
||||||
if os.path.exists(target_path):
|
if os.path.exists(target_path):
|
||||||
try:
|
try:
|
||||||
os.unlink(target_path)
|
os.unlink(target_path)
|
||||||
|
@ -2385,9 +2443,9 @@ def clean_extension_status():
|
||||||
def sync_status_to_extension(status):
|
def sync_status_to_extension(status):
|
||||||
Root_Dir = get_app_root()
|
Root_Dir = get_app_root()
|
||||||
webdriver_path = os.path.join(Root_Dir, "webdriver")
|
webdriver_path = os.path.join(Root_Dir, "webdriver")
|
||||||
target_path = os.path.join(webdriver_path, MAXBOT_EXTENSION_NAME)
|
target_path = os.path.join(webdriver_path, CONST_MAXBOT_EXTENSION_NAME)
|
||||||
target_path = os.path.join(target_path, "data")
|
target_path = os.path.join(target_path, "data")
|
||||||
target_path = os.path.join(target_path, MAXBOT_EXTENSION_STATUS_JSON)
|
target_path = os.path.join(target_path, CONST_MAXBOT_EXTENSION_STATUS_JSON)
|
||||||
#print("save as to:", target_path)
|
#print("save as to:", target_path)
|
||||||
status_json={}
|
status_json={}
|
||||||
status_json["status"]=status
|
status_json["status"]=status
|
||||||
|
@ -2618,14 +2676,18 @@ def load_GUI(root, config_dict):
|
||||||
tab3 = Frame(tabControl)
|
tab3 = Frame(tabControl)
|
||||||
tabControl.add(tab3, text=translate[language_code]['verification_word'])
|
tabControl.add(tab3, text=translate[language_code]['verification_word'])
|
||||||
|
|
||||||
|
global tab4
|
||||||
tab4 = Frame(tabControl)
|
tab4 = Frame(tabControl)
|
||||||
tabControl.add(tab4, text=translate[language_code]['autofill'])
|
tabControl.add(tab4, text=translate[language_code]['maxbot_server'])
|
||||||
|
|
||||||
tab5 = Frame(tabControl)
|
tab5 = Frame(tabControl)
|
||||||
tabControl.add(tab5, text=translate[language_code]['runtime'])
|
tabControl.add(tab5, text=translate[language_code]['autofill'])
|
||||||
|
|
||||||
tab6 = Frame(tabControl)
|
tab6 = Frame(tabControl)
|
||||||
tabControl.add(tab6, text=translate[language_code]['about'])
|
tabControl.add(tab6, text=translate[language_code]['runtime'])
|
||||||
|
|
||||||
|
tab7 = Frame(tabControl)
|
||||||
|
tabControl.add(tab7, text=translate[language_code]['about'])
|
||||||
|
|
||||||
tabControl.grid(column=0, row=row_count)
|
tabControl.grid(column=0, row=row_count)
|
||||||
tabControl.select(tab1)
|
tabControl.select(tab1)
|
||||||
|
@ -2639,9 +2701,10 @@ def load_GUI(root, config_dict):
|
||||||
PreferenctTab(tab1, config_dict, language_code, UI_PADDING_X)
|
PreferenctTab(tab1, config_dict, language_code, UI_PADDING_X)
|
||||||
AdvancedTab(tab2, config_dict, language_code, UI_PADDING_X)
|
AdvancedTab(tab2, config_dict, language_code, UI_PADDING_X)
|
||||||
VerificationTab(tab3, config_dict, language_code, UI_PADDING_X)
|
VerificationTab(tab3, config_dict, language_code, UI_PADDING_X)
|
||||||
AutofillTab(tab4, config_dict, language_code, UI_PADDING_X)
|
ServerTab(tab4, config_dict, language_code, UI_PADDING_X)
|
||||||
RuntimeTab(tab5, config_dict, language_code, UI_PADDING_X)
|
AutofillTab(tab5, config_dict, language_code, UI_PADDING_X)
|
||||||
AboutTab(tab6, language_code)
|
RuntimeTab(tab6, config_dict, language_code, UI_PADDING_X)
|
||||||
|
AboutTab(tab7, language_code)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -2721,7 +2784,168 @@ def clean_tmp_file():
|
||||||
for filepath in remove_file_list:
|
for filepath in remove_file_list:
|
||||||
force_remove_file(filepath)
|
force_remove_file(filepath)
|
||||||
|
|
||||||
|
def get_ip_address():
|
||||||
|
default_ip = "127.0.0.1"
|
||||||
|
ip = default_ip
|
||||||
|
try:
|
||||||
|
ip = [l for l in ([ip for ip in socket.gethostbyname_ex(socket.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)
|
||||||
|
try:
|
||||||
|
ip = socket.gethostname()
|
||||||
|
except Exception as exc2:
|
||||||
|
print(exc2)
|
||||||
|
ip = default_ip
|
||||||
|
return ip
|
||||||
|
|
||||||
|
def btn_copy_ip_clicked():
|
||||||
|
local_ip = get_ip_address()
|
||||||
|
ip_address = "http://%s:%d/" % (local_ip,CONST_SERVER_PORT)
|
||||||
|
pyperclip.copy(ip_address)
|
||||||
|
|
||||||
|
def btn_copy_question_clicked():
|
||||||
|
global txt_question
|
||||||
|
question_text = txt_question.get("1.0",END).strip()
|
||||||
|
if len(question_text) > 0:
|
||||||
|
pyperclip.copy(question_text)
|
||||||
|
|
||||||
|
def btn_query_question_clicked():
|
||||||
|
global txt_question
|
||||||
|
question_text = txt_question.get("1.0",END).strip()
|
||||||
|
if len(question_text) > 0:
|
||||||
|
webbrowser.open("https://www.google.com/search?q="+question_text)
|
||||||
|
|
||||||
|
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_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):
|
||||||
|
global txt_question
|
||||||
|
txt_question.insert("1.0", "")
|
||||||
|
|
||||||
|
class VersionHandler(tornado.web.RequestHandler):
|
||||||
|
def get(self):
|
||||||
|
self.write({"version":self.application.version})
|
||||||
|
|
||||||
|
|
||||||
|
class OcrHandler(tornado.web.RequestHandler):
|
||||||
|
def get(self):
|
||||||
|
self.write({"answer": "1234"})
|
||||||
|
|
||||||
|
def post(self):
|
||||||
|
self.set_header("Access-Control-Allow-Origin", "*")
|
||||||
|
self.set_header("Access-Control-Allow-Headers", "x-requested-with")
|
||||||
|
self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
|
||||||
|
|
||||||
|
_body = None
|
||||||
|
is_pass_check = True
|
||||||
|
errorMessage = ""
|
||||||
|
errorCode = 0
|
||||||
|
|
||||||
|
if is_pass_check:
|
||||||
|
is_pass_check = False
|
||||||
|
try :
|
||||||
|
_body = json.loads(self.request.body)
|
||||||
|
is_pass_check = True
|
||||||
|
except Exception:
|
||||||
|
errorMessage = "wrong json format"
|
||||||
|
errorCode = 1001
|
||||||
|
pass
|
||||||
|
|
||||||
|
img_base64 = None
|
||||||
|
image_data = ""
|
||||||
|
if is_pass_check:
|
||||||
|
if 'image_data' in _body:
|
||||||
|
image_data = _body['image_data']
|
||||||
|
if len(image_data) > 0:
|
||||||
|
img_base64 = base64.b64decode(image_data)
|
||||||
|
else:
|
||||||
|
errorMessage = "image_data not exist"
|
||||||
|
errorCode = 1002
|
||||||
|
|
||||||
|
#print("is_pass_check:", is_pass_check)
|
||||||
|
#print("errorMessage:", errorMessage)
|
||||||
|
#print("errorCode:", errorCode)
|
||||||
|
ocr_answer = ""
|
||||||
|
if not img_base64 is None:
|
||||||
|
try:
|
||||||
|
ocr_answer = self.application.ocr.classification(img_base64)
|
||||||
|
print("ocr_answer:", ocr_answer)
|
||||||
|
except Exception as exc:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.write({"answer": ocr_answer})
|
||||||
|
|
||||||
|
async def main_server():
|
||||||
|
ocr = None
|
||||||
|
try:
|
||||||
|
ocr = ddddocr.DdddOcr(show_ad=False, beta=True)
|
||||||
|
except Exception as exc:
|
||||||
|
print(exc)
|
||||||
|
pass
|
||||||
|
|
||||||
|
app = Application([
|
||||||
|
(r"/", MainHandler),
|
||||||
|
(r"/version", VersionHandler),
|
||||||
|
(r"/ocr", OcrHandler),
|
||||||
|
(r"/query", MainHandler),
|
||||||
|
(r"/question", QuestionHandler),
|
||||||
|
])
|
||||||
|
app.ocr = ocr;
|
||||||
|
app.version = CONST_APP_VERSION;
|
||||||
|
|
||||||
|
app.listen(CONST_SERVER_PORT)
|
||||||
|
await asyncio.Event().wait()
|
||||||
|
|
||||||
|
def web_server():
|
||||||
|
asyncio.run(main_server())
|
||||||
|
|
||||||
|
def preview_question_text_file():
|
||||||
|
if os.path.exists(CONST_MAXBOT_QUESTION_FILE):
|
||||||
|
infile = None
|
||||||
|
if platform.system() == 'Windows':
|
||||||
|
infile = open(CONST_MAXBOT_QUESTION_FILE, 'r', encoding='UTF-8')
|
||||||
|
else:
|
||||||
|
infile = open(CONST_MAXBOT_QUESTION_FILE, 'r')
|
||||||
|
|
||||||
|
if not infile is None:
|
||||||
|
question_text = infile.readline()
|
||||||
|
|
||||||
|
global txt_question
|
||||||
|
try:
|
||||||
|
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")
|
||||||
|
if len(question_text) > 0:
|
||||||
|
txt_question.insert("1.0", question_text)
|
||||||
|
except Exception as exc:
|
||||||
|
pass
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
threading.Thread(target=resetful_api_timer, daemon=True).start()
|
threading.Thread(target=resetful_api_timer, daemon=True).start()
|
||||||
|
threading.Thread(target=web_server, daemon=True).start()
|
||||||
clean_tmp_file()
|
clean_tmp_file()
|
||||||
main()
|
main()
|
||||||
|
|
258
text_server.py
258
text_server.py
File diff suppressed because one or more lines are too long
|
@ -5,13 +5,15 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
chrome.runtime.onInstalled.addListener(function(){
|
chrome.runtime.onInstalled.addListener(function(){
|
||||||
console.log("onInstalled");
|
//console.log("onInstalled");
|
||||||
|
|
||||||
let default_status='ON';
|
let default_status='ON';
|
||||||
chrome.action.setBadgeText({
|
chrome.action.setBadgeText({
|
||||||
text: default_status
|
text: default_status
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const default_webserver_runing=false;
|
||||||
|
|
||||||
fetch("data/settings.json")
|
fetch("data/settings.json")
|
||||||
.then((resp) => resp.json())
|
.then((resp) => resp.json())
|
||||||
.then((settings) =>
|
.then((settings) =>
|
||||||
|
@ -19,10 +21,11 @@ chrome.runtime.onInstalled.addListener(function(){
|
||||||
chrome.storage.local.set(
|
chrome.storage.local.set(
|
||||||
{
|
{
|
||||||
settings: settings,
|
settings: settings,
|
||||||
status: default_status
|
status: default_status,
|
||||||
|
webserver_runing: default_webserver_runing
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
console.log("dump settings.json to storage");
|
console.log("dump settings.json to extension storage");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -56,7 +59,7 @@ chrome.action.onClicked.addListener(async (tab) => {
|
||||||
{
|
{
|
||||||
next_flag = false;
|
next_flag = false;
|
||||||
}
|
}
|
||||||
console.log("next_flag:"+next_flag);
|
//console.log("next_flag:"+next_flag);
|
||||||
set_status_to(next_flag);
|
set_status_to(next_flag);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -87,19 +90,78 @@ async function stopHeartbeat()
|
||||||
|
|
||||||
startHeartbeat();
|
startHeartbeat();
|
||||||
|
|
||||||
|
async function ocr(data_url, image_data, tabId)
|
||||||
|
{
|
||||||
|
//console.log("data_url:"+data_url);
|
||||||
|
fetch(data_url,{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
image_data: image_data
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(response =>
|
||||||
|
{
|
||||||
|
if (response.ok)
|
||||||
|
{
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
else if (response.status === 404)
|
||||||
|
{
|
||||||
|
let result_json={"answer": "", "fail": 'error 404'};
|
||||||
|
//console.log(result_json);
|
||||||
|
//sendResponse(result_json);
|
||||||
|
return Promise.reject('error 404')
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
let result_json={"answer": "", "fail": response.status};
|
||||||
|
//console.log(result_json);
|
||||||
|
//sendResponse(result_json);
|
||||||
|
return Promise.reject('some other error: ' + response.status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((data) =>
|
||||||
|
{
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
let result_json=data;
|
||||||
|
console.log(result_json);
|
||||||
|
//sendResponse(result_json);
|
||||||
|
chrome.tabs.sendMessage(tabId, result_json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.catch(error =>
|
||||||
|
{
|
||||||
|
//console.log('error is', error)
|
||||||
|
let result_json={"answer": "", "fail": error};
|
||||||
|
//console.log(result_json);
|
||||||
|
//sendResponse(result_json);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||||
let request_json = request;
|
let request_json = request;
|
||||||
let result_json={"answer": "pong from background"};
|
let result_json={"answer": "pong from background"};
|
||||||
if(request_json.act=="decrypt") {
|
if(request_json.action=="decrypt") {
|
||||||
console.log(typeof crypto_decrypt);
|
console.log(typeof crypto_decrypt);
|
||||||
let answer="";
|
let answer="";
|
||||||
if(typeof crypto_decrypt === 'function') {
|
if(typeof crypto_decrypt === 'function') {
|
||||||
answer=crypto_decrypt(request_json.data.text,request_json.data.KEY,request_json.data.IV);
|
answer=crypto_decrypt(request_json.data.text,request_json.data.KEY,request_json.data.IV);
|
||||||
}
|
}
|
||||||
result_json={"answer": answer};
|
result_json={"answer": answer};
|
||||||
|
sendResponse(result_json);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(request_json.action=="ocr") {
|
||||||
|
const tabId = sender.tab.id;
|
||||||
|
ocr(request_json.data.url, request_json.data.image_data, tabId);
|
||||||
}
|
}
|
||||||
//let result = JSON.stringify(result_json);
|
|
||||||
sendResponse(result_json);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"homepage": "https://tixcraft.com", "browser": "chrome", "language": "\u7e41\u9ad4\u4e2d\u6587", "ticket_number": 2, "ocr_captcha": {"enable": true, "beta": true, "force_submit": true, "image_source": "canvas"}, "webdriver_type": "undetected_chromedriver", "date_auto_select": {"enable": true, "date_keyword": "", "mode": "random"}, "area_auto_select": {"enable": true, "mode": "random", "area_keyword": ""}, "keyword_exclude": "\"\u8f2a\u6905\",\"\u8eab\u969c\",\"\u8eab\u5fc3 \u969c\u7919\",\"Restricted View\",\"\u71c8\u67f1\u906e\u853d\",\"\u8996\u7dda\u4e0d\u5b8c\u6574\"", "kktix": {"auto_press_next_step_button": true, "auto_fill_ticket_number": true}, "tixcraft": {"pass_date_is_sold_out": true, "auto_reload_coming_soon_page": true}, "advanced": {"play_captcha_sound": {"enable": true, "filename": "ding-dong.wav"}, "tixcraft_sid": "", "ibonqware": "", "facebook_account": "", "kktix_account": "", "fami_account": "", "cityline_account": "", "urbtix_account": "", "hkticketing_account": "", "kham_account": "", "ticket_account": "", "udn_account": "", "ticketplus_account": "", "facebook_password": "", "kktix_password": "", "fami_password": "", "urbtix_password": "", "cityline_password": "", "hkticketing_password": "", "kham_password": "", "ticket_password": "", "udn_password": "", "ticketplus_password": "", "disable_adjacent_seat": false, "hide_some_image": true, "block_facebook_network": false, "headless": false, "verbose": false, "auto_guess_options": true, "user_guess_string": "", "online_dictionary_url": "", "auto_reload_page_interval": 0.1, "proxy_server_port": ""}}
|
{"homepage": "https://tixcraft.com", "browser": "chrome", "language": "\u7e41\u9ad4\u4e2d\u6587", "ticket_number": 2, "ocr_captcha": {"enable": true, "beta": true, "force_submit": true, "image_source": "canvas"}, "webdriver_type": "undetected_chromedriver", "date_auto_select": {"enable": true, "date_keyword": "", "mode": "random"}, "area_auto_select": {"enable": true, "mode": "random", "area_keyword": ""}, "keyword_exclude": "\"\u8f2a\u6905\",\"\u8eab\u969c\",\"\u8eab\u5fc3 \u969c\u7919\",\"Restricted View\",\"\u71c8\u67f1\u906e\u853d\",\"\u8996\u7dda\u4e0d\u5b8c\u6574\"", "kktix": {"auto_press_next_step_button": true, "auto_fill_ticket_number": true}, "tixcraft": {"pass_date_is_sold_out": true, "auto_reload_coming_soon_page": true}, "advanced": {"play_captcha_sound": {"enable": true, "filename": "ding-dong.wav"}, "tixcraft_sid": "", "ibonqware": "", "facebook_account": "", "kktix_account": "", "fami_account": "", "cityline_account": "", "urbtix_account": "", "hkticketing_account": "", "kham_account": "", "ticket_account": "", "udn_account": "", "ticketplus_account": "", "facebook_password": "", "kktix_password": "", "fami_password": "", "urbtix_password": "", "cityline_password": "", "hkticketing_password": "", "kham_password": "", "ticket_password": "", "udn_password": "", "ticketplus_password": "", "disable_adjacent_seat": false, "hide_some_image": false, "block_facebook_network": false, "headless": false, "verbose": false, "auto_guess_options": true, "user_guess_string": "", "remote_url": "\"http://127.0.0.1:16888/\"", "auto_reload_page_interval": 0.1, "proxy_server_port": ""}}
|
|
@ -97,13 +97,19 @@ function begin()
|
||||||
|
|
||||||
function dom_ready()
|
function dom_ready()
|
||||||
{
|
{
|
||||||
|
let ret=false;
|
||||||
//console.log("checking...");
|
//console.log("checking...");
|
||||||
if($("#settings").length>0) {
|
if($("#settings").length>0) {
|
||||||
clearInterval(myInterval);
|
ret=true;
|
||||||
|
if(myInterval) clearInterval(myInterval);
|
||||||
begin();
|
begin();
|
||||||
}
|
}
|
||||||
|
console.log("dom_ready:"+ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
myInterval = setInterval(() => {
|
if(!dom_ready()) {
|
||||||
dom_ready();
|
myInterval = setInterval(() => {
|
||||||
}, 100);
|
dom_ready();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
|
@ -86,7 +86,7 @@ async function decrypt_text(event_id, session_id) {
|
||||||
const IV = '!@#$FETIXEVENTiv';
|
const IV = '!@#$FETIXEVENTiv';
|
||||||
|
|
||||||
let bundle = {
|
let bundle = {
|
||||||
act: 'decrypt',
|
action: 'decrypt',
|
||||||
data: {
|
data: {
|
||||||
'KEY':KEY,
|
'KEY':KEY,
|
||||||
'IV':IV,
|
'IV':IV,
|
||||||
|
@ -100,7 +100,7 @@ async function decrypt_text(event_id, session_id) {
|
||||||
//console.log(real_event_id);
|
//console.log(real_event_id);
|
||||||
|
|
||||||
bundle = {
|
bundle = {
|
||||||
act: 'decrypt',
|
action: 'decrypt',
|
||||||
data: {
|
data: {
|
||||||
'KEY':KEY,
|
'KEY':KEY,
|
||||||
'IV':IV,
|
'IV':IV,
|
||||||
|
|
|
@ -38,6 +38,80 @@ function assign_ticket_number(ticket_number)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var myInterval = null;
|
||||||
|
|
||||||
|
function get_ocr_image()
|
||||||
|
{
|
||||||
|
//console.log("get_ocr_image");
|
||||||
|
let image_data = "";
|
||||||
|
|
||||||
|
// PS: tixcraft have different domain to use the same content script.
|
||||||
|
const currentUrl = window.location.href;
|
||||||
|
const domain = currentUrl.split('/')[2];
|
||||||
|
|
||||||
|
let image_id = 'TicketForm_verifyCode-image';
|
||||||
|
let img = document.getElementById(image_id);
|
||||||
|
if(img!=null) {
|
||||||
|
let canvas = document.createElement('canvas');
|
||||||
|
let context = canvas.getContext('2d');
|
||||||
|
canvas.height = img.naturalHeight;
|
||||||
|
canvas.width = img.naturalWidth;
|
||||||
|
context.drawImage(img, 0, 0);
|
||||||
|
let img_data = canvas.toDataURL();
|
||||||
|
if(img_data) {
|
||||||
|
image_data = img_data.split(",")[1];
|
||||||
|
//console.log(image_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return image_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener((message) => {
|
||||||
|
//console.log('sent from background', message);
|
||||||
|
set_ocr_answer(message.answer);
|
||||||
|
});
|
||||||
|
|
||||||
|
function set_ocr_answer(answer)
|
||||||
|
{
|
||||||
|
console.log("answer:"+answer);
|
||||||
|
if(answer.length > 0) {
|
||||||
|
$('#TicketForm_verifyCode').val(answer);
|
||||||
|
$("button[type='submit']").click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function get_ocr_answer(api_url, image_data)
|
||||||
|
{
|
||||||
|
let bundle = {
|
||||||
|
action: 'ocr',
|
||||||
|
data: {
|
||||||
|
'url': api_url + 'ocr',
|
||||||
|
'image_data':image_data,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let bundle_string = JSON.stringify(bundle);
|
||||||
|
const return_answer = await chrome.runtime.sendMessage(bundle);
|
||||||
|
//console.log(return_answer);
|
||||||
|
|
||||||
|
// fail due to CORS error
|
||||||
|
//ocr(bundle.data.url, bundle.data.image_data, bundle.data.callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function orc_image_ready(api_url)
|
||||||
|
{
|
||||||
|
let ret=false;
|
||||||
|
let image_data = get_ocr_image();
|
||||||
|
if(image_data.length>0) {
|
||||||
|
ret=true;
|
||||||
|
if(myInterval) clearInterval(myInterval);
|
||||||
|
get_ocr_answer(api_url, image_data);
|
||||||
|
}
|
||||||
|
console.log("orc_image_ready:"+ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
storage.get('settings', function (items)
|
storage.get('settings', function (items)
|
||||||
{
|
{
|
||||||
if (items.settings)
|
if (items.settings)
|
||||||
|
@ -45,6 +119,21 @@ storage.get('settings', function (items)
|
||||||
settings = items.settings;
|
settings = items.settings;
|
||||||
//console.log("ticket_number:"+ settings.ticket_number);
|
//console.log("ticket_number:"+ settings.ticket_number);
|
||||||
assign_ticket_number(settings.ticket_number);
|
assign_ticket_number(settings.ticket_number);
|
||||||
|
if(settings.ocr_captcha.enable) {
|
||||||
|
let remote_url_string = "";
|
||||||
|
let remote_url_array = [];
|
||||||
|
if(settings.advanced.remote_url.length > 0) {
|
||||||
|
remote_url_array = JSON.parse('[' + settings.advanced.remote_url +']');
|
||||||
|
}
|
||||||
|
if(remote_url_array.length) {
|
||||||
|
remote_url_string = remote_url_array[0];
|
||||||
|
}
|
||||||
|
if(!orc_image_ready(remote_url_string)) {
|
||||||
|
myInterval = setInterval(() => {
|
||||||
|
orc_image_ready(remote_url_string);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('no settings found');
|
console.log('no settings found');
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
"declarativeNetRequest",
|
"declarativeNetRequest",
|
||||||
"declarativeNetRequestFeedback"
|
"declarativeNetRequestFeedback"
|
||||||
],
|
],
|
||||||
|
"host_permissions": [
|
||||||
|
"http://127.0.0.1:16888/*"
|
||||||
|
],
|
||||||
"web_accessible_resources": [
|
"web_accessible_resources": [
|
||||||
{
|
{
|
||||||
"resources": [ "data/*.json" ],
|
"resources": [ "data/*.json" ],
|
||||||
|
|
|
@ -1,58 +1,30 @@
|
||||||
const https_url="https://";
|
const https_url = "https://";
|
||||||
const http_url="https://";
|
const http_url = "https://";
|
||||||
|
|
||||||
class HeartBeatConnector
|
class HeartBeatConnector
|
||||||
{
|
{
|
||||||
constructor() {
|
constructor() {}
|
||||||
}
|
|
||||||
|
|
||||||
start() {
|
|
||||||
//console.log("start heart beat connector");
|
|
||||||
//load_font.loadFont();
|
|
||||||
|
|
||||||
|
start()
|
||||||
|
{
|
||||||
sync_status_from_parent();
|
sync_status_from_parent();
|
||||||
|
|
||||||
// Query the active tab before injecting the content script
|
|
||||||
/*
|
|
||||||
chrome.tabs.query(
|
|
||||||
{
|
|
||||||
active: true,
|
|
||||||
status: "complete",
|
|
||||||
currentWindow: true
|
|
||||||
}, (tabs) =>
|
|
||||||
{
|
|
||||||
if(tabs && tabs.length) {
|
|
||||||
//console.log(tabs);
|
|
||||||
//console.log(tabs[0]);
|
|
||||||
if (tabs[0].url.startsWith(https_url) || tabs[0].url.startsWith(http_url)) {
|
|
||||||
// Use the Scripting API to execute a script
|
|
||||||
chrome.scripting.executeScript(
|
|
||||||
{
|
|
||||||
target:
|
|
||||||
{
|
|
||||||
tabId: tabs[0].id
|
|
||||||
},
|
|
||||||
func: ack
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_status_to(flag)
|
function set_status_to(flag)
|
||||||
{
|
{
|
||||||
let nextState = 'ON';
|
let nextState = 'ON';
|
||||||
if(!flag) {
|
if (!flag)
|
||||||
|
{
|
||||||
nextState = 'OFF';
|
nextState = 'OFF';
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log(nextState);
|
//console.log(nextState);
|
||||||
chrome.action.setBadgeText({
|
chrome.action.setBadgeText(
|
||||||
|
{
|
||||||
text: nextState
|
text: nextState
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
chrome.storage.local.set(
|
chrome.storage.local.set(
|
||||||
{
|
{
|
||||||
|
@ -61,34 +33,59 @@ function set_status_to(flag)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function set_webserver_runing_to(flag)
|
||||||
|
{
|
||||||
|
chrome.storage.local.set(
|
||||||
|
{
|
||||||
|
webserver_runing: flag
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function sync_status_from_parent()
|
function sync_status_from_parent()
|
||||||
{
|
{
|
||||||
//console.log("sync_status_from_parent");
|
//console.log("sync_status_from_parent");
|
||||||
|
|
||||||
let data_url = chrome.runtime.getURL("data/status.json");
|
let data_url = chrome.runtime.getURL("data/status.json");
|
||||||
fetch(data_url)
|
fetch(data_url)
|
||||||
.then(response => {
|
.then(response =>
|
||||||
if (response.ok) {
|
{
|
||||||
return response.json()
|
if (response.ok)
|
||||||
} else if(response.status === 404) {
|
{
|
||||||
return Promise.reject('error 404')
|
set_webserver_runing_to(true);
|
||||||
} else {
|
return response.json()
|
||||||
return Promise.reject('some other error: ' + response.status)
|
|
||||||
}
|
}
|
||||||
})
|
else if (response.status === 404)
|
||||||
|
{
|
||||||
|
set_webserver_runing_to(false);
|
||||||
|
return Promise.reject('error 404')
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_webserver_runing_to(false);
|
||||||
|
return Promise.reject('some other error: ' + response.status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
.then((data) =>
|
.then((data) =>
|
||||||
{
|
{
|
||||||
console.log(data);
|
//console.log(data);
|
||||||
if(data) {
|
if (data)
|
||||||
|
{
|
||||||
set_status_to(data.status);
|
set_status_to(data.status);
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.catch(error => {
|
)
|
||||||
|
.catch(error =>
|
||||||
|
{
|
||||||
//console.log('error is', error)
|
//console.log('error is', error)
|
||||||
});
|
set_webserver_runing_to(false);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ack() {
|
function ack()
|
||||||
|
{
|
||||||
//console.log("act");
|
//console.log("act");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,22 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="ocr_captcha_enable">
|
||||||
|
<label class="form-check-label" for="ocr_captcha_enable">
|
||||||
|
OCR
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
<label for="remote_url" class="form-label">Remote URL</label>
|
||||||
|
<input class="form-control" id="remote_url" value="" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<button class="btn btn-primary" id="save_btn">Save</button>
|
<button class="btn btn-primary" id="save_btn">Save</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,6 +9,8 @@ const area_keyword = document.querySelector('#area_keyword');
|
||||||
const keyword_exclude = document.querySelector('#keyword_exclude');
|
const keyword_exclude = document.querySelector('#keyword_exclude');
|
||||||
const auto_reload_page_interval = document.querySelector('#auto_reload_page_interval');
|
const auto_reload_page_interval = document.querySelector('#auto_reload_page_interval');
|
||||||
const disable_adjacent_seat = document.querySelector('#disable_adjacent_seat');
|
const disable_adjacent_seat = document.querySelector('#disable_adjacent_seat');
|
||||||
|
const ocr_captcha_enable = document.querySelector('#ocr_captcha_enable');
|
||||||
|
const remote_url = document.querySelector('#remote_url');
|
||||||
|
|
||||||
var settings = null;
|
var settings = null;
|
||||||
|
|
||||||
|
@ -33,6 +35,15 @@ async function saveChanges()
|
||||||
settings.keyword_exclude = keyword_exclude.value;
|
settings.keyword_exclude = keyword_exclude.value;
|
||||||
settings.advanced.auto_reload_page_interval = auto_reload_page_interval.value;
|
settings.advanced.auto_reload_page_interval = auto_reload_page_interval.value;
|
||||||
settings.advanced.disable_adjacent_seat = disable_adjacent_seat.checked;
|
settings.advanced.disable_adjacent_seat = disable_adjacent_seat.checked;
|
||||||
|
settings.ocr_captcha.enable = ocr_captcha_enable.checked;
|
||||||
|
|
||||||
|
let remote_url_array = [];
|
||||||
|
remote_url_array.push(remote_url.value);
|
||||||
|
let remote_url_string = JSON.stringify(remote_url_array);
|
||||||
|
remote_url_string = remote_url_string.substring(0,remote_url_string.length-1);
|
||||||
|
remote_url_string = remote_url_string.substring(1);
|
||||||
|
//console.log("final remote_url_string:"+remote_url_string);
|
||||||
|
settings.advanced.remote_url = remote_url_string;
|
||||||
|
|
||||||
await storage.set(
|
await storage.set(
|
||||||
{
|
{
|
||||||
|
@ -61,6 +72,18 @@ function loadChanges()
|
||||||
keyword_exclude.value = settings.keyword_exclude;
|
keyword_exclude.value = settings.keyword_exclude;
|
||||||
auto_reload_page_interval.value = settings.advanced.auto_reload_page_interval;
|
auto_reload_page_interval.value = settings.advanced.auto_reload_page_interval;
|
||||||
disable_adjacent_seat.checked = settings.advanced.disable_adjacent_seat;
|
disable_adjacent_seat.checked = settings.advanced.disable_adjacent_seat;
|
||||||
|
ocr_captcha_enable.checked = settings.ocr_captcha.enable;
|
||||||
|
|
||||||
|
let remote_url_string = "";
|
||||||
|
let remote_url_array = [];
|
||||||
|
if(settings.advanced.remote_url.length > 0) {
|
||||||
|
remote_url_array = JSON.parse('[' + settings.advanced.remote_url +']');
|
||||||
|
}
|
||||||
|
if(remote_url_array.length) {
|
||||||
|
remote_url_string = remote_url_array[0];
|
||||||
|
}
|
||||||
|
remote_url.value = remote_url_string;
|
||||||
|
|
||||||
//message('Loaded saved settings.');
|
//message('Loaded saved settings.');
|
||||||
} else {
|
} else {
|
||||||
console.log('no settings found');
|
console.log('no settings found');
|
||||||
|
|
Loading…
Reference in New Issue