2024-01-05, support captcha on extension.

master
unknown 2024-01-11 17:28:47 +08:00
parent a60d3fd899
commit f2e0c654f8
15 changed files with 630 additions and 479 deletions

0
MAXBOT_ONLINE_ANSWER.txt Normal file
View File

View File

@ -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:

View File

@ -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"

View File

@ -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": ""}}

View File

@ -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
@ -855,7 +855,7 @@ def btn_save_act(language_code, slience_mode=False):
config_dict["date_auto_select"]["enable"] = bool(chk_state_date_auto_select.get()) config_dict["date_auto_select"]["enable"] = bool(chk_state_date_auto_select.get())
config_dict["date_auto_select"]["mode"] = combo_date_auto_select_mode.get().strip() config_dict["date_auto_select"]["mode"] = combo_date_auto_select_mode.get().strip()
date_keyword = txt_date_keyword.get("1.0",END).strip() date_keyword = txt_date_keyword.get("1.0",END).strip()
date_keyword = format_config_keyword_for_json(date_keyword) date_keyword = format_config_keyword_for_json(date_keyword)
config_dict["date_auto_select"]["date_keyword"] = date_keyword config_dict["date_auto_select"]["date_keyword"] = date_keyword
@ -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
@ -2256,7 +2313,7 @@ def AutofillTab(root, config_dict, language_code, UI_PADDING_X):
txt_cityline_password.grid(column=2, row=group_row_count, sticky = W) txt_cityline_password.grid(column=2, row=group_row_count, sticky = W)
group_row_count +=1 group_row_count +=1
global lbl_urbtix_account global lbl_urbtix_account
lbl_urbtix_account = Label(frame_group_header, text=translate[language_code]['urbtix_account']) lbl_urbtix_account = Label(frame_group_header, text=translate[language_code]['urbtix_account'])
lbl_urbtix_account.grid(column=0, row=group_row_count, sticky = E) lbl_urbtix_account.grid(column=0, row=group_row_count, sticky = E)
@ -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()

File diff suppressed because one or more lines are too long

View File

@ -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);
}); });

View File

@ -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": ""}}

View File

@ -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);
}

View File

@ -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,

View File

@ -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');
} }

View File

@ -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" ],

View File

@ -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");
} }

View File

@ -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>

View File

@ -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');