2024-04-14, update settings to new UI.

master
Your Name 2024-05-01 22:26:41 +08:00
parent 0ec59c62b6
commit 5bc3607e88
12 changed files with 1060 additions and 202 deletions

View File

@ -44,7 +44,7 @@ except Exception as exc:
print(exc) print(exc)
pass pass
CONST_APP_VERSION = "MaxBot (2024.04.13)" CONST_APP_VERSION = "MaxBot (2024.04.14)"
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_CONFIG_FILE = "settings.json"

View File

@ -24,7 +24,7 @@ import webbrowser
import util import util
CONST_APP_VERSION = "MaxBot (2024.04.13)" CONST_APP_VERSION = "MaxBot (2024.04.14)"
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

@ -32,7 +32,7 @@ except Exception as exc:
print(exc) print(exc)
pass pass
CONST_APP_VERSION = "MaxBot (2024.04.13)" CONST_APP_VERSION = "MaxBot (2024.04.14)"
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_CONFIG_FILE = "settings.json"

View File

@ -1,8 +1,8 @@
{ {
"homepage": "https://tixcraft.com", "homepage": "about:blank",
"browser": "chrome", "browser": "chrome",
"language": "\u7e41\u9ad4\u4e2d\u6587", "language": "English",
"ticket_number": 2, "ticket_number": "2",
"ocr_captcha": { "ocr_captcha": {
"enable": true, "enable": true,
"beta": true, "beta": true,
@ -12,13 +12,13 @@
"webdriver_type": "undetected_chromedriver", "webdriver_type": "undetected_chromedriver",
"date_auto_select": { "date_auto_select": {
"enable": true, "enable": true,
"date_keyword": "", "date_keyword": "\"\"",
"mode": "random" "mode": "random"
}, },
"area_auto_select": { "area_auto_select": {
"enable": true, "enable": true,
"mode": "random", "mode": "random",
"area_keyword": "" "area_keyword": "\"\""
}, },
"keyword_exclude": "\"\u8f2a\u6905\",\"\u8eab\u969c\",\"\u8eab\u5fc3 \u969c\u7919\",\"Restricted View\",\"\u71c8\u67f1\u906e\u853d\",\"\u8996\u7dda\u4e0d\u5b8c\u6574\"", "keyword_exclude": "\"\u8f2a\u6905\",\"\u8eab\u969c\",\"\u8eab\u5fc3 \u969c\u7919\",\"Restricted View\",\"\u71c8\u67f1\u906e\u853d\",\"\u8996\u7dda\u4e0d\u5b8c\u6574\"",
"kktix": { "kktix": {
@ -74,12 +74,12 @@
"headless": false, "headless": false,
"verbose": false, "verbose": false,
"auto_guess_options": true, "auto_guess_options": true,
"user_guess_string": "", "user_guess_string": "\"\"",
"remote_url": "\"http://127.0.0.1:16888/\"", "remote_url": "\"http://127.0.0.1:16888/\"",
"auto_reload_page_interval": 0.1, "auto_reload_page_interval": "0.1",
"reset_browser_interval": 0, "reset_browser_interval": "0",
"kktix_status_api": false, "kktix_status_api": false,
"max_dwell_time": 60, "max_dwell_time": "60",
"proxy_server_port": "", "proxy_server_port": "",
"window_size": "480,1024", "window_size": "480,1024",
"idle_keyword": "", "idle_keyword": "",

601
settings.py Normal file
View File

@ -0,0 +1,601 @@
#!/usr/bin/env python3
#encoding=utf-8
import asyncio
import base64
import json
import os
import platform
import subprocess
import sys
import threading
import time
import webbrowser
from datetime import datetime
import tornado
from tornado.web import Application
from tornado.web import StaticFileHandler
import util
from typing import (
Dict,
Any,
Union,
Optional,
Awaitable,
Tuple,
List,
Callable,
Iterable,
Generator,
Type,
TypeVar,
cast,
overload,
)
try:
import ddddocr
except Exception as exc:
pass
CONST_APP_VERSION = "MaxBot (2024.04.14)"
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_SERVER_PORT = 16888
CONST_FROM_TOP_TO_BOTTOM = "from top to bottom"
CONST_FROM_BOTTOM_TO_TOP = "from bottom to top"
CONST_CENTER = "center"
CONST_RANDOM = "random"
CONST_SELECT_ORDER_DEFAULT = CONST_RANDOM
CONST_EXCLUDE_DEFAULT = "\"輪椅\",\"身障\",\"身心 障礙\",\"Restricted View\",\"燈柱遮蔽\",\"視線不完整\""
CONST_CAPTCHA_SOUND_FILENAME_DEFAULT = "ding-dong.wav"
CONST_HOMEPAGE_DEFAULT = "about:blank"
CONST_OCR_CAPTCH_IMAGE_SOURCE_NON_BROWSER = "NonBrowser"
CONST_OCR_CAPTCH_IMAGE_SOURCE_CANVAS = "canvas"
CONST_WEBDRIVER_TYPE_SELENIUM = "selenium"
CONST_WEBDRIVER_TYPE_UC = "undetected_chromedriver"
CONST_WEBDRIVER_TYPE_DP = "DrissionPage"
CONST_WEBDRIVER_TYPE_NODRIVER = "nodriver"
CONST_SUPPORTED_SITES = ["https://kktix.com"
,"https://tixcraft.com (拓元)"
,"https://ticketmaster.sg"
#,"https://ticketmaster.com"
,"https://teamear.tixcraft.com/ (添翼)"
,"https://www.indievox.com/ (獨立音樂)"
,"https://www.famiticket.com.tw (全網)"
,"https://ticket.ibon.com.tw/"
,"https://kham.com.tw/ (寬宏)"
,"https://ticket.com.tw/ (年代)"
,"https://tickets.udnfunlife.com/ (udn售票網)"
,"https://ticketplus.com.tw/ (遠大)"
,"===[香港或南半球的系統]==="
,"http://www.urbtix.hk/ (城市)"
,"https://www.cityline.com/ (買飛)"
,"https://hotshow.hkticketing.com/ (快達票)"
,"https://ticketing.galaxymacau.com/ (澳門銀河)"
,"http://premier.ticketek.com.au"
]
translate={}
URL_DONATE = 'https://max-everyday.com/about/#donate'
URL_HELP = 'https://max-everyday.com/2018/03/tixcraft-bot/'
URL_RELEASE = 'https://github.com/max32002/tixcraft_bot/releases'
URL_FB = 'https://www.facebook.com/maxbot.ticket'
URL_CHROME_DRIVER = 'https://chromedriver.chromium.org/'
URL_FIREFOX_DRIVER = 'https://github.com/mozilla/geckodriver/releases'
URL_EDGE_DRIVER = 'https://developer.microsoft.com/zh-tw/microsoft-edge/tools/webdriver/'
def get_default_config():
config_dict={}
config_dict["homepage"] = CONST_HOMEPAGE_DEFAULT
config_dict["browser"] = "chrome"
config_dict["language"] = "English"
config_dict["ticket_number"] = 2
config_dict["ocr_captcha"] = {}
config_dict["ocr_captcha"]["enable"] = True
config_dict["ocr_captcha"]["beta"] = True
config_dict["ocr_captcha"]["force_submit"] = True
config_dict["ocr_captcha"]["image_source"] = CONST_OCR_CAPTCH_IMAGE_SOURCE_CANVAS
config_dict["webdriver_type"] = CONST_WEBDRIVER_TYPE_UC
config_dict["date_auto_select"] = {}
config_dict["date_auto_select"]["enable"] = True
config_dict["date_auto_select"]["date_keyword"] = ""
config_dict["date_auto_select"]["mode"] = CONST_SELECT_ORDER_DEFAULT
config_dict["area_auto_select"] = {}
config_dict["area_auto_select"]["enable"] = True
config_dict["area_auto_select"]["mode"] = CONST_SELECT_ORDER_DEFAULT
config_dict["area_auto_select"]["area_keyword"] = ""
config_dict["keyword_exclude"] = CONST_EXCLUDE_DEFAULT
config_dict['kktix']={}
config_dict["kktix"]["auto_press_next_step_button"] = True
config_dict["kktix"]["auto_fill_ticket_number"] = True
config_dict['tixcraft']={}
config_dict["tixcraft"]["pass_date_is_sold_out"] = True
config_dict["tixcraft"]["auto_reload_coming_soon_page"] = True
config_dict['advanced']={}
config_dict['advanced']['play_sound']={}
config_dict["advanced"]["play_sound"]["ticket"] = True
config_dict["advanced"]["play_sound"]["order"] = True
config_dict["advanced"]["play_sound"]["filename"] = CONST_CAPTCHA_SOUND_FILENAME_DEFAULT
config_dict["advanced"]["tixcraft_sid"] = ""
config_dict["advanced"]["ibonqware"] = ""
config_dict["advanced"]["facebook_account"] = ""
config_dict["advanced"]["kktix_account"] = ""
config_dict["advanced"]["fami_account"] = ""
config_dict["advanced"]["cityline_account"] = ""
config_dict["advanced"]["urbtix_account"] = ""
config_dict["advanced"]["hkticketing_account"] = ""
config_dict["advanced"]["kham_account"] = ""
config_dict["advanced"]["ticket_account"] = ""
config_dict["advanced"]["udn_account"] = ""
config_dict["advanced"]["ticketplus_account"] = ""
config_dict["advanced"]["facebook_password"] = ""
config_dict["advanced"]["kktix_password"] = ""
config_dict["advanced"]["fami_password"] = ""
config_dict["advanced"]["urbtix_password"] = ""
config_dict["advanced"]["cityline_password"] = ""
config_dict["advanced"]["hkticketing_password"] = ""
config_dict["advanced"]["kham_password"] = ""
config_dict["advanced"]["ticket_password"] = ""
config_dict["advanced"]["udn_password"] = ""
config_dict["advanced"]["ticketplus_password"] = ""
config_dict["advanced"]["facebook_password_plaintext"] = ""
config_dict["advanced"]["kktix_password_plaintext"] = ""
config_dict["advanced"]["fami_password_plaintext"] = ""
config_dict["advanced"]["urbtix_password_plaintext"] = ""
config_dict["advanced"]["cityline_password_plaintext"] = ""
config_dict["advanced"]["hkticketing_password_plaintext"] = ""
config_dict["advanced"]["kham_password_plaintext"] = ""
config_dict["advanced"]["ticket_password_plaintext"] = ""
config_dict["advanced"]["udn_password_plaintext"] = ""
config_dict["advanced"]["ticketplus_password_plaintext"] = ""
config_dict["advanced"]["chrome_extension"] = True
config_dict["advanced"]["disable_adjacent_seat"] = False
config_dict["advanced"]["hide_some_image"] = False
config_dict["advanced"]["block_facebook_network"] = False
config_dict["advanced"]["headless"] = False
config_dict["advanced"]["verbose"] = False
config_dict["advanced"]["auto_guess_options"] = True
config_dict["advanced"]["user_guess_string"] = ""
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"]["reset_browser_interval"] = 0
config_dict["advanced"]["kktix_status_api"] = False
config_dict["advanced"]["max_dwell_time"] = 60
config_dict["advanced"]["proxy_server_port"] = ""
config_dict["advanced"]["window_size"] = "480,1024"
config_dict["advanced"]["idle_keyword"] = ""
config_dict["advanced"]["resume_keyword"] = ""
config_dict["advanced"]["idle_keyword_second"] = ""
config_dict["advanced"]["resume_keyword_second"] = ""
return config_dict
def read_last_url_from_file():
text = ""
if os.path.exists(CONST_MAXBOT_LAST_URL_FILE):
try:
with open(CONST_MAXBOT_LAST_URL_FILE, "r") as text_file:
text = text_file.readline()
except Exception as e:
pass
return text
def load_json():
app_root = util.get_app_root()
# overwrite config path.
config_filepath = os.path.join(app_root, CONST_MAXBOT_CONFIG_FILE)
config_dict = None
if os.path.isfile(config_filepath):
try:
with open(config_filepath) as json_data:
config_dict = json.load(json_data)
except Exception as e:
pass
else:
config_dict = get_default_config()
return config_filepath, config_dict
def reset_json():
app_root = util.get_app_root()
config_filepath = os.path.join(app_root, CONST_MAXBOT_CONFIG_FILE)
if os.path.exists(str(config_filepath)):
try:
os.unlink(str(config_filepath))
except Exception as exc:
print(exc)
pass
config_dict = get_default_config()
return config_filepath, config_dict
def decrypt_password(config_dict):
config_dict["advanced"]["facebook_password"] = util.decryptMe(config_dict["advanced"]["facebook_password"])
config_dict["advanced"]["kktix_password"] = util.decryptMe(config_dict["advanced"]["kktix_password"])
config_dict["advanced"]["fami_password"] = util.decryptMe(config_dict["advanced"]["fami_password"])
config_dict["advanced"]["cityline_password"] = util.decryptMe(config_dict["advanced"]["cityline_password"])
config_dict["advanced"]["urbtix_password"] = util.decryptMe(config_dict["advanced"]["urbtix_password"])
config_dict["advanced"]["hkticketing_password"] = util.decryptMe(config_dict["advanced"]["hkticketing_password"])
config_dict["advanced"]["kham_password"] = util.decryptMe(config_dict["advanced"]["kham_password"])
config_dict["advanced"]["ticket_password"] = util.decryptMe(config_dict["advanced"]["ticket_password"])
config_dict["advanced"]["udn_password"] = util.decryptMe(config_dict["advanced"]["udn_password"])
config_dict["advanced"]["ticketplus_password"] = util.decryptMe(config_dict["advanced"]["ticketplus_password"])
return config_dict
def encrypt_password(config_dict):
config_dict["advanced"]["facebook_password"] = util.encryptMe(config_dict["advanced"]["facebook_password"])
config_dict["advanced"]["kktix_password"] = util.encryptMe(config_dict["advanced"]["kktix_password"])
config_dict["advanced"]["fami_password"] = util.encryptMe(config_dict["advanced"]["fami_password"])
config_dict["advanced"]["cityline_password"] = util.encryptMe(config_dict["advanced"]["cityline_password"])
config_dict["advanced"]["urbtix_password"] = util.encryptMe(config_dict["advanced"]["urbtix_password"])
config_dict["advanced"]["hkticketing_password"] = util.encryptMe(config_dict["advanced"]["hkticketing_password"])
config_dict["advanced"]["kham_password"] = util.encryptMe(config_dict["advanced"]["kham_password"])
config_dict["advanced"]["ticket_password"] = util.encryptMe(config_dict["advanced"]["ticket_password"])
config_dict["advanced"]["udn_password"] = util.encryptMe(config_dict["advanced"]["udn_password"])
config_dict["advanced"]["ticketplus_password"] = util.encryptMe(config_dict["advanced"]["ticketplus_password"])
return config_dict
def maxbot_idle():
app_root = util.get_app_root()
idle_filepath = os.path.join(app_root, CONST_MAXBOT_INT28_FILE)
try:
with open(CONST_MAXBOT_INT28_FILE, "w") as text_file:
text_file.write("")
except Exception as e:
pass
def maxbot_resume():
app_root = util.get_app_root()
idle_filepath = os.path.join(app_root, CONST_MAXBOT_INT28_FILE)
for i in range(3):
util.force_remove_file(idle_filepath)
def launch_maxbot():
global launch_counter
if "launch_counter" in globals():
launch_counter += 1
else:
launch_counter = 0
#webdriver_type = ""
webdriver_type = CONST_WEBDRIVER_TYPE_NODRIVER
#webdriver_type = combo_webdriver_type.get().strip()
script_name = "chrome_tixcraft"
if webdriver_type == CONST_WEBDRIVER_TYPE_NODRIVER:
script_name = "nodriver_tixcraft"
#global txt_window_size
#window_size = txt_window_size.get().strip()
window_size = "480,1024"
if len(window_size) > 0:
if "," in window_size:
size_array = window_size.split(",")
target_width = int(size_array[0])
target_left = target_width * launch_counter
#print("target_left:", target_left)
if target_left >= 1440:
launch_counter = 0
window_size = window_size + "," + str(launch_counter)
#print("window_size:", window_size)
threading.Thread(target=util.launch_maxbot, args=(script_name,"","","","",window_size,)).start()
def change_maxbot_status_by_keyword():
config_filepath, config_dict = load_json()
system_clock_data = datetime.now()
current_time = system_clock_data.strftime('%H:%M:%S')
#print('Current Time is:', current_time)
#print("idle_keyword", config_dict["advanced"]["idle_keyword"])
if len(config_dict["advanced"]["idle_keyword"]) > 0:
is_matched = util.is_text_match_keyword(config_dict["advanced"]["idle_keyword"], current_time)
if is_matched:
#print("match to idle:", current_time)
maxbot_idle()
if len(config_dict["advanced"]["resume_keyword"]) > 0:
is_matched = util.is_text_match_keyword(config_dict["advanced"]["resume_keyword"], current_time)
if is_matched:
#print("match to resume:", current_time)
maxbot_resume()
current_time = system_clock_data.strftime('%S')
if len(config_dict["advanced"]["idle_keyword_second"]) > 0:
is_matched = util.is_text_match_keyword(config_dict["advanced"]["idle_keyword_second"], current_time)
if is_matched:
#print("match to idle:", current_time)
maxbot_idle()
if len(config_dict["advanced"]["resume_keyword_second"]) > 0:
is_matched = util.is_text_match_keyword(config_dict["advanced"]["resume_keyword_second"], current_time)
if is_matched:
#print("match to resume:", current_time)
maxbot_resume()
def clean_extension_status():
Root_Dir = util.get_app_root()
webdriver_path = os.path.join(Root_Dir, "webdriver")
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, CONST_MAXBOT_EXTENSION_STATUS_JSON)
if os.path.exists(target_path):
try:
os.unlink(target_path)
except Exception as exc:
print(exc)
pass
def sync_status_to_extension(status):
Root_Dir = util.get_app_root()
webdriver_path = os.path.join(Root_Dir, "webdriver")
target_path = os.path.join(webdriver_path, CONST_MAXBOT_EXTENSION_NAME)
target_path = os.path.join(target_path, "data")
if os.path.exists(target_path):
target_path = os.path.join(target_path, CONST_MAXBOT_EXTENSION_STATUS_JSON)
#print("save as to:", target_path)
status_json={}
status_json["status"]=status
#print("dump json to path:", target_path)
try:
with open(target_path, 'w') as outfile:
json.dump(status_json, outfile)
except Exception as e:
pass
def clean_tmp_file():
remove_file_list = [CONST_MAXBOT_LAST_URL_FILE
,CONST_MAXBOT_INT28_FILE
,CONST_MAXBOT_ANSWER_ONLINE_FILE
,CONST_MAXBOT_QUESTION_FILE
]
for filepath in remove_file_list:
util.force_remove_file(filepath)
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 ShutdownHandler(tornado.web.RequestHandler):
def get(self):
global GLOBAL_SERVER_SHUTDOWN
GLOBAL_SERVER_SHUTDOWN = True
self.write({"showdown": GLOBAL_SERVER_SHUTDOWN})
class StatusHandler(tornado.web.RequestHandler):
def get(self):
is_paused = False
if os.path.exists(CONST_MAXBOT_INT28_FILE):
is_paused = True
url = read_last_url_from_file()
self.write({"status": not is_paused, "last_url": url})
class PauseHandler(tornado.web.RequestHandler):
def get(self):
maxbot_idle()
self.write({"pause": True})
class ResumeHandler(tornado.web.RequestHandler):
def get(self):
maxbot_resume()
self.write({"resume": True})
class RunHandler(tornado.web.RequestHandler):
def get(self):
print('run button pressed.')
launch_maxbot()
self.write({"run": True})
class LoadJsonHandler(tornado.web.RequestHandler):
def get(self):
config_filepath, config_dict = load_json()
config_dict = decrypt_password(config_dict)
self.write(config_dict)
class ResetJsonHandler(tornado.web.RequestHandler):
def get(self):
config_filepath, config_dict = reset_json()
self.write(config_dict)
class SaveJsonHandler(tornado.web.RequestHandler):
def post(self):
_body = None
is_pass_check = True
error_message = ""
error_code = 0
if is_pass_check:
is_pass_check = False
try :
_body = json.loads(self.request.body)
is_pass_check = True
except Exception:
error_message = "wrong json format"
error_code = 1002
pass
if is_pass_check:
app_root = util.get_app_root()
config_filepath = os.path.join(app_root, CONST_MAXBOT_CONFIG_FILE)
config_dict = encrypt_password(_body)
util.save_json(config_dict, config_filepath)
if not is_pass_check:
self.set_status(401)
self.write(dict(error=dict(message=error_message,code=error_code)))
self.finish()
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})
class QueryHandler(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)
async def main_server():
ocr = None
try:
ocr = ddddocr.DdddOcr(show_ad=False, beta=True)
except Exception as exc:
print(exc)
pass
app = Application([
("/version", VersionHandler),
("/shutdown", ShutdownHandler),
# status api
("/status", StatusHandler),
("/pause", PauseHandler),
("/resume", ResumeHandler),
("/run", RunHandler),
# json api
("/load", LoadJsonHandler),
("/save", SaveJsonHandler),
("/reset", ResetJsonHandler),
("/ocr", OcrHandler),
("/query", QueryHandler),
("/question", QuestionHandler),
('/(.*)', StaticFileHandler, {"path": os.path.join(".", 'www/')}),
])
app.ocr = ocr;
app.version = CONST_APP_VERSION;
app.listen(CONST_SERVER_PORT)
print("server running on port:", CONST_SERVER_PORT)
url="http://127.0.0.1:" + str(CONST_SERVER_PORT) + "/settings.html"
print("goto url:", url)
webbrowser.open_new(url)
await asyncio.Event().wait()
def web_server():
is_port_binded = util.is_connectable(CONST_SERVER_PORT)
#print("is_port_binded:", is_port_binded)
if not is_port_binded:
asyncio.run(main_server())
else:
print("port:", CONST_SERVER_PORT, " is in used.")
def settgins_gui_timer():
while True:
change_maxbot_status_by_keyword()
time.sleep(0.4)
if GLOBAL_SERVER_SHUTDOWN:
break
if __name__ == "__main__":
global GLOBAL_SERVER_SHUTDOWN
GLOBAL_SERVER_SHUTDOWN = False
threading.Thread(target=settgins_gui_timer, daemon=True).start()
threading.Thread(target=web_server, daemon=True).start()
clean_tmp_file()
clean_extension_status()
print("To exit web server press Ctrl + C.")
while True:
time.sleep(0.4)
if GLOBAL_SERVER_SHUTDOWN:
break
print("Bye bye, see you next time.")

View File

@ -34,7 +34,7 @@ try:
except Exception as exc: except Exception as exc:
pass pass
CONST_APP_VERSION = "MaxBot (2024.04.13)" CONST_APP_VERSION = "MaxBot (2024.04.14)"
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_CONFIG_FILE = "settings.json"

View File

@ -141,6 +141,12 @@ def format_config_keyword_for_json(user_input):
def is_text_match_keyword(keyword_string, text): def is_text_match_keyword(keyword_string, text):
is_match_keyword = True is_match_keyword = True
if len(keyword_string) > 0 and len(text) > 0: if len(keyword_string) > 0 and len(text) > 0:
# directly input text into arrray field.
if len(keyword_string) > 0:
if not '"' in keyword_string:
keyword_string = '"' + keyword_string + '"'
is_match_keyword = False is_match_keyword = False
keyword_array = [] keyword_array = []
try: try:

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_sound": {"ticket": true, "order": 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": "", "facebook_password_plaintext": "", "kktix_password_plaintext": "", "fami_password_plaintext": "", "urbtix_password_plaintext": "", "cityline_password_plaintext": "", "hkticketing_password_plaintext": "", "kham_password_plaintext": "", "ticket_password_plaintext": "", "udn_password_plaintext": "", "ticketplus_password_plaintext": "", "chrome_extension": true, "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, "reset_browser_interval": 0, "kktix_status_api": false, "max_dwell_time": 60, "proxy_server_port": "", "window_size": "480,1024,0", "idle_keyword": "", "resume_keyword": "", "idle_keyword_second": "", "resume_keyword_second": ""}, "domain_filter": ["*.doubleclick.net/*", "*.googlesyndication.com/*", "*.ssp.hinet.net/*", "*a.amnet.tw/*", "*adx.c.appier.net/*", "*cdn.cookielaw.org/*", "*cdnjs.cloudflare.com/ajax/libs/clipboard.js/*", "*clarity.ms/*", "*cloudfront.com/*", "*cms.analytics.yahoo.com/*", "*e2elog.fetnet.net/*", "*fundingchoicesmessages.google.com/*", "*ghtinc.com/*", "*google-analytics.com/*", "*googletagmanager.com/*", "*googletagservices.com/*", "*img.uniicreative.com/*", "*lndata.com/*", "*match.adsrvr.org/*", "*onead.onevision.com.tw/*", "*play.google.com/log?*", "*popin.cc/*", "*rollbar.com/*", "*sb.scorecardresearch.com/*", "*tagtoo.co/*", "*ticketmaster.sg/js/adblock*", "*ticketmaster.sg/js/adblock.js*", "*tixcraft.com/js/analytics.js*", "*tixcraft.com/js/common.js*", "*tixcraft.com/js/custom.js*", "*treasuredata.com/*", "*www.youtube.com/youtubei/v1/player/heartbeat*"]} {"homepage": "about:blank", "browser": "chrome", "language": "English", "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_sound": {"ticket": true, "order": 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": "", "facebook_password_plaintext": "", "kktix_password_plaintext": "", "fami_password_plaintext": "", "urbtix_password_plaintext": "", "cityline_password_plaintext": "", "hkticketing_password_plaintext": "", "kham_password_plaintext": "", "ticket_password_plaintext": "", "udn_password_plaintext": "", "ticketplus_password_plaintext": "", "chrome_extension": true, "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", "reset_browser_interval": "0", "kktix_status_api": false, "max_dwell_time": "60", "proxy_server_port": "", "window_size": "480,1024,0", "idle_keyword": "", "resume_keyword": "", "idle_keyword_second": "", "resume_keyword_second": ""}, "domain_filter": ["*.doubleclick.net/*", "*.googlesyndication.com/*", "*.ssp.hinet.net/*", "*a.amnet.tw/*", "*anymind360.com/*", "*adx.c.appier.net/*", "*cdn.cookielaw.org/*", "*cdnjs.cloudflare.com/ajax/libs/clipboard.js/*", "*clarity.ms/*", "*cloudfront.com/*", "*cms.analytics.yahoo.com/*", "*e2elog.fetnet.net/*", "*fundingchoicesmessages.google.com/*", "*ghtinc.com/*", "*google-analytics.com/*", "*googletagmanager.com/*", "*googletagservices.com/*", "*img.uniicreative.com/*", "*lndata.com/*", "*match.adsrvr.org/*", "*onead.onevision.com.tw/*", "*play.google.com/log?*", "*popin.cc/*", "*rollbar.com/*", "*sb.scorecardresearch.com/*", "*tagtoo.co/*", "*ticketmaster.sg/js/adblock*", "*ticketmaster.sg/js/adblock.js*", "*tixcraft.com/js/analytics.js*", "*tixcraft.com/js/common.js*", "*tixcraft.com/js/custom.js*", "*treasuredata.com/*", "*www.youtube.com/youtubei/v1/player/heartbeat*"]}

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_sound": {"ticket": true, "order": 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": "", "facebook_password_plaintext": "", "kktix_password_plaintext": "", "fami_password_plaintext": "", "urbtix_password_plaintext": "", "cityline_password_plaintext": "", "hkticketing_password_plaintext": "", "kham_password_plaintext": "", "ticket_password_plaintext": "", "udn_password_plaintext": "", "ticketplus_password_plaintext": "", "chrome_extension": true, "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, "reset_browser_interval": 0, "kktix_status_api": false, "max_dwell_time": 60, "proxy_server_port": "", "window_size": "480,1024,0", "idle_keyword": "", "resume_keyword": "", "idle_keyword_second": "", "resume_keyword_second": ""}} {"homepage": "about:blank", "browser": "chrome", "language": "English", "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_sound": {"ticket": true, "order": 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": "", "facebook_password_plaintext": "", "kktix_password_plaintext": "", "fami_password_plaintext": "", "urbtix_password_plaintext": "", "cityline_password_plaintext": "", "hkticketing_password_plaintext": "", "kham_password_plaintext": "", "ticket_password_plaintext": "", "udn_password_plaintext": "", "ticketplus_password_plaintext": "", "chrome_extension": true, "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", "reset_browser_interval": "0", "kktix_status_api": false, "max_dwell_time": "60", "proxy_server_port": "", "window_size": "480,1024,0", "idle_keyword": "", "resume_keyword": "", "idle_keyword_second": "", "resume_keyword_second": ""}}

View File

@ -15,3 +15,49 @@ textarea {
.disappear { .disappear {
display: none; display: none;
} }
.bd-callout {
padding: 1.25rem;
margin-top: 1.25rem;
margin-bottom: 1.25rem;
color: var(--bd-callout-color, inherit);
background-color: var(--bd-callout-bg, var(--bs-gray-100));
border-left: 0.25rem solid var(--bd-callout-border, var(--bs-gray-300))
}
.bd-callout h4 {
margin-bottom: .25rem
}
.bd-callout code {
font-size: var(--bs-body-font-size);
}
.bd-callout>:last-child {
margin-bottom: 0
}
.bd-callout+.bd-callout {
margin-top: -.25rem
}
.bd-callout .highlight {
background-color: rgba(0,0,0,0.05)
}
.bd-callout-info {
--bd-callout-color: var(--bs-info-text-emphasis);
--bd-callout-border: var(--bs-info-border-subtle)
}
.bd-callout-warning {
--bd-callout-color: var(--bs-warning-text-emphasis);
--bd-callout-bg: var(--bs-warning-bg-subtle);
--bd-callout-border: var(--bs-warning-border-subtle)
}
.bd-callout-danger {
--bd-callout-color: var(--bs-danger-text-emphasis);
--bd-callout-bg: var(--bs-danger-bg-subtle);
--bd-callout-border: var(--bs-danger-border-subtle)
}

View File

@ -54,17 +54,24 @@
<p>MaxBot 的出發點是讓一般民眾與代購黃牛或懂得寫程式的人有類似的基準點或類似的起跑線上,用魔法對抗魔法,當某一天大家都是透過機器人來搶票時,當機器人數量已多到影響一般民眾購票的權利時,售票業者才比較有可能會對未來熱門演唱會改採「實名制」+「抽籤制」,讓更多民眾可以公平地購買到門票,就可以跟「人海戰術」與「搶票機器人」說 bye-bye 。</p> <p>MaxBot 的出發點是讓一般民眾與代購黃牛或懂得寫程式的人有類似的基準點或類似的起跑線上,用魔法對抗魔法,當某一天大家都是透過機器人來搶票時,當機器人數量已多到影響一般民眾購票的權利時,售票業者才比較有可能會對未來熱門演唱會改採「實名制」+「抽籤制」,讓更多民眾可以公平地購買到門票,就可以跟「人海戰術」與「搶票機器人」說 bye-bye 。</p>
<p>台灣藝文活動的文創法第十條中的「不正方式」由於沒有明確定義,代表的是所有軟體都涉嫌違反。故在此呼籲大家,勿以身試法</p> <p>MaxBot 系統裡出現的「搶票」指的是「非台灣的藝文活動或車票」</p>
<p>以下文章出現的「搶票」指的是「非台灣的藝文活動或車票」。</p> <p></p>
<div class="bd-callout bd-callout-info">
台灣藝文活動的<strong>文創法第十條</strong>中的「<code>不正方式</code>」由於沒有明確定義,代表的是所有軟體都涉嫌違反。故在此呼籲大家,勿以身試法。
</div>
<hr/> <hr/>
<h2>法律聲明</h2> <h3>法律聲明</h3>
<p>作者沒有意圖要他人購得的票券進行加價轉售或是使用在違法的事情上,他人的行為並不在作者的意識支配範圍之內,作者不對他人的非法行為負責。</p>
<p>使用此儲存庫或與之相關的任何程式碼,即表示您同意<a href="https://github.com/max32002/tixcraft_bot/blob/master/LEGAL_NOTICE.md" target="_blank">法律聲明</a>。作者不對該儲存庫的使用負責與背書,也不對其他使用者所做的任何副本、分叉、重新上傳或與 MaxBot 相關的任何其他內容負責。 這是作者唯一的帳戶和儲存庫。 為了防止假冒或不負責任的行為,請遵守此儲存庫使用的 GNU GPL 授權。</p> <p>使用此儲存庫或與之相關的任何程式碼,即表示您同意<a href="https://github.com/max32002/tixcraft_bot/blob/master/LEGAL_NOTICE.md" target="_blank">法律聲明</a>。作者不對該儲存庫的使用負責與背書,也不對其他使用者所做的任何副本、分叉、重新上傳或與 MaxBot 相關的任何其他內容負責。 這是作者唯一的帳戶和儲存庫。 為了防止假冒或不負責任的行為,請遵守此儲存庫使用的 GNU GPL 授權。</p>
<div class="bd-callout bd-callout-info">
作者沒有意圖要他人購得的票券進行加價轉售或是使用在違法的事情上,他人的行為並不在作者的意識支配範圍之內,作者不對他人的非法行為負責。
</div>
</div> </div>
<!-- tab 2 --> <!-- tab 2 -->
@ -73,6 +80,33 @@
<label for="homepage" class="col-sm-2 col-form-label">網址</label> <label for="homepage" class="col-sm-2 col-form-label">網址</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input class="form-control" id="homepage" value="" /> <input class="form-control" id="homepage" value="" />
<div class="accordion mt-1" id="accordionExample">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseSites" aria-expanded="true" aria-controls="collapseSites">
部份支援的網站清單
</button>
</h2>
<div id="collapseSites" class="accordion-collapse collapse">
<div class="accordion-body">
<ul>
<li>拓元</li>
<li>KKTIX</li>
<li>ibon</li>
<li>Fami</li>
<li>UND</li>
<li>年代</li>
<li>寬宏</li>
<li>cityline</li>
<li>hkticketing</li>
<li>urbtix</li>
</ul>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
@ -170,9 +204,10 @@
<label for="keyword_exclude" class="col-sm-2 col-form-label">排除關鍵字</label> <label for="keyword_exclude" class="col-sm-2 col-form-label">排除關鍵字</label>
<div class="col-sm-10"> <div class="col-sm-10">
<textarea class="form-control" id="keyword_exclude" rows="3"></textarea> <textarea class="form-control" id="keyword_exclude" rows="3"></textarea>
<p> <div class="bd-callout bd-callout-info">
每組關鍵字需要用「雙引號」包起來, 用「逗號」分隔, 在關鍵字中使用「空格」為 AND 邏輯。完全不輸入或是加入 「,""」 代表符合所有關鍵字 <strong>提示:</strong>
</p> 每組關鍵字需要用「<code>雙引號</code>」包起來, 用「<code>逗號</code>」分隔, 在關鍵字中使用「<code>空格</code>」為 AND 邏輯。完全不輸入或是加入 「<code>,""</code>」 代表符合所有關鍵字。
</div>
</div> </div>
</div> </div>
</div> </div>
@ -184,8 +219,8 @@
<label for="browser" class="col-sm-2 col-form-label">瀏覽器</label> <label for="browser" class="col-sm-2 col-form-label">瀏覽器</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select id="browser" class="form-select" aria-label="Default select"> <select id="browser" class="form-select" aria-label="Default select">
<option value="chrome">Chrome</option> <option value="chrome">Google Chrome</option>
<option value="edge">Edge</option> <option value="edge">Microsoft Edge</option>
<option value="brave">Brave</option> <option value="brave">Brave</option>
<option value="firefox">Firefox</option> <option value="firefox">Firefox</option>
<option value="safari">Safari</option> <option value="safari">Safari</option>
@ -197,34 +232,14 @@
<label for="webdriver_type" class="col-sm-2 col-form-label">WebDriver類別</label> <label for="webdriver_type" class="col-sm-2 col-form-label">WebDriver類別</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select id="webdriver_type" class="form-select" aria-label="Default select"> <select id="webdriver_type" class="form-select" aria-label="Default select">
<option value="selenium">selenium</option> <option value="selenium">Selenium</option>
<option value="undetected_chromedriver">undetected chromedriver</option> <option value="undetected_chromedriver">Undetected Chromedriver</option>
<option value="nodriver">NODRIVER</option> <option value="nodriver">NODRIVER</option>
<!-- option value="DrissionPage">DrissionPage</option --> <!-- option value="DrissionPage">DrissionPage</option -->
</select> </select>
</div> </div>
</div> </div>
<div class="row mb-3">
<label for="area_select_mode" class="col-sm-2 col-form-label">區域排序方式</label>
<div class="col-sm-10">
<select id="area_select_mode" class="form-select" aria-label="Default select">
<option value="from top to bottom">
from top to bottom
</option>
<option value="from bottom to top">
from bottom to top
</option>
<option value="center">
center
</option>
<option value="random">
random
</option>
</select>
</div>
</div>
<div class="row mb-3"> <div class="row mb-3">
<label class="col-sm-2 col-form-label form-check-label" for="play_ticket_sound">有票時播放音效</label> <label class="col-sm-2 col-form-label form-check-label" for="play_ticket_sound">有票時播放音效</label>
<div class="col-sm-10"> <div class="col-sm-10">
@ -396,7 +411,7 @@
<span class="input-group-text" id="inputGroup-sizing-default">帳號</span> <span class="input-group-text" id="inputGroup-sizing-default">帳號</span>
<input type="text" id="facebook_account" value="" class="form-control"> <input type="text" id="facebook_account" value="" class="form-control">
<span class="input-group-text" id="inputGroup-sizing-default">密碼</span> <span class="input-group-text" id="inputGroup-sizing-default">密碼</span>
<input type="text" id="facebook_password" value="" class="form-control"> <input type="password" id="facebook_password" value="" class="form-control">
</div> </div>
</div> </div>
</div> </div>
@ -408,7 +423,7 @@
<span class="input-group-text" id="inputGroup-sizing-default">帳號</span> <span class="input-group-text" id="inputGroup-sizing-default">帳號</span>
<input type="text" id="kktix_account" value="" class="form-control"> <input type="text" id="kktix_account" value="" class="form-control">
<span class="input-group-text" id="inputGroup-sizing-default">密碼</span> <span class="input-group-text" id="inputGroup-sizing-default">密碼</span>
<input type="text" id="kktix_password" value="" class="form-control"> <input type="password" id="kktix_password" value="" class="form-control">
</div> </div>
</div> </div>
</div> </div>
@ -420,7 +435,7 @@
<span class="input-group-text" id="inputGroup-sizing-default">帳號</span> <span class="input-group-text" id="inputGroup-sizing-default">帳號</span>
<input type="text" id="fami_account" value="" class="form-control"> <input type="text" id="fami_account" value="" class="form-control">
<span class="input-group-text" id="inputGroup-sizing-default">密碼</span> <span class="input-group-text" id="inputGroup-sizing-default">密碼</span>
<input type="text" id="fami_password" value="" class="form-control"> <input type="password" id="fami_password" value="" class="form-control">
</div> </div>
</div> </div>
</div> </div>
@ -432,7 +447,7 @@
<span class="input-group-text" id="inputGroup-sizing-default">帳號</span> <span class="input-group-text" id="inputGroup-sizing-default">帳號</span>
<input type="text" id="kham_account" value="" class="form-control"> <input type="text" id="kham_account" value="" class="form-control">
<span class="input-group-text" id="inputGroup-sizing-default">密碼</span> <span class="input-group-text" id="inputGroup-sizing-default">密碼</span>
<input type="text" id="kham_password" value="" class="form-control"> <input type="password" id="kham_password" value="" class="form-control">
</div> </div>
</div> </div>
</div> </div>
@ -444,7 +459,7 @@
<span class="input-group-text" id="inputGroup-sizing-default">帳號</span> <span class="input-group-text" id="inputGroup-sizing-default">帳號</span>
<input type="text" id="ticket_account" value="" class="form-control"> <input type="text" id="ticket_account" value="" class="form-control">
<span class="input-group-text" id="inputGroup-sizing-default">密碼</span> <span class="input-group-text" id="inputGroup-sizing-default">密碼</span>
<input type="text" id="ticket_password" value="" class="form-control"> <input type="password" id="ticket_password" value="" class="form-control">
</div> </div>
</div> </div>
</div> </div>
@ -456,7 +471,7 @@
<span class="input-group-text" id="inputGroup-sizing-default">帳號</span> <span class="input-group-text" id="inputGroup-sizing-default">帳號</span>
<input type="text" id="udn_account" value="" class="form-control"> <input type="text" id="udn_account" value="" class="form-control">
<span class="input-group-text" id="inputGroup-sizing-default">密碼</span> <span class="input-group-text" id="inputGroup-sizing-default">密碼</span>
<input type="text" id="udn_password" value="" class="form-control"> <input type="password" id="udn_password" value="" class="form-control">
</div> </div>
</div> </div>
</div> </div>
@ -468,7 +483,7 @@
<span class="input-group-text" id="inputGroup-sizing-default">帳號</span> <span class="input-group-text" id="inputGroup-sizing-default">帳號</span>
<input type="text" id="ticketplus_account" value="" class="form-control"> <input type="text" id="ticketplus_account" value="" class="form-control">
<span class="input-group-text" id="inputGroup-sizing-default">密碼</span> <span class="input-group-text" id="inputGroup-sizing-default">密碼</span>
<input type="text" id="ticketplus_password" value="" class="form-control"> <input type="password" id="ticketplus_password" value="" class="form-control">
</div> </div>
</div> </div>
</div> </div>
@ -490,7 +505,7 @@
<span class="input-group-text" id="inputGroup-sizing-default">帳號</span> <span class="input-group-text" id="inputGroup-sizing-default">帳號</span>
<input type="text" id="urbtix_account" value="" class="form-control"> <input type="text" id="urbtix_account" value="" class="form-control">
<span class="input-group-text" id="inputGroup-sizing-default">密碼</span> <span class="input-group-text" id="inputGroup-sizing-default">密碼</span>
<input type="text" id="urbtix_password" value="" class="form-control"> <input type="password" id="urbtix_password" value="" class="form-control">
</div> </div>
</div> </div>
</div> </div>
@ -502,8 +517,13 @@
<span class="input-group-text" id="inputGroup-sizing-default">帳號</span> <span class="input-group-text" id="inputGroup-sizing-default">帳號</span>
<input type="text" id="hkticketing_account" value="" class="form-control"> <input type="text" id="hkticketing_account" value="" class="form-control">
<span class="input-group-text" id="inputGroup-sizing-default">密碼</span> <span class="input-group-text" id="inputGroup-sizing-default">密碼</span>
<input type="text" id="hkticketing_password" value="" class="form-control"> <input type="password" id="hkticketing_password" value="" class="form-control">
</div> </div>
<div class="bd-callout bd-callout-info">
<strong>提示:</strong>
將密碼保存到設定檔中可能會讓您的密碼被盜。
</div>
</div> </div>
</div> </div>
@ -570,24 +590,23 @@
<div class="col-12"> <div class="col-12">
<button class="btn btn-primary" id="run_btn">搶票</button> <button class="btn btn-primary" id="run_btn">搶票</button>
<button class="btn btn-primary" id="save_btn">存檔</button> <button class="btn btn-primary" id="save_btn">存檔</button>
<button class="btn btn-primary" id="exit_btn">結束</button> <button class="btn btn-primary" id="reset_btn">重設為預設值</button>
<button class="btn btn-danger" id="exit_btn">結束</button>
</div> </div>
</div> </div>
<div class="modal" id="saveModal" tabindex="-1" role="dialog"> <div class="modal" id="message_modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title">MaxBot 存檔</h5> <h2 class="modal-title fs-5" id="message_modal_title">MaxBot</h2>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p>存檔完成</p> <p id="message_detail"></p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">關閉</button> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">關閉</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,11 +1,13 @@
//const storage = chrome.storage.local;
// action bar
const run_button = document.querySelector('#run_btn'); const run_button = document.querySelector('#run_btn');
const save_button = document.querySelector('#save_btn'); const save_button = document.querySelector('#save_btn');
const reset_button = document.querySelector('#reset_btn');
const exit_button = document.querySelector('#exit_btn'); const exit_button = document.querySelector('#exit_btn');
const pause_button = document.querySelector('#pause_btn'); const pause_button = document.querySelector('#pause_btn');
const resume_button = document.querySelector('#resume_btn'); const resume_button = document.querySelector('#resume_btn');
// preference
const homepage = document.querySelector('#homepage'); const homepage = document.querySelector('#homepage');
const ticket_number = document.querySelector('#ticket_number'); const ticket_number = document.querySelector('#ticket_number');
const date_select_mode = document.querySelector('#date_select_mode'); const date_select_mode = document.querySelector('#date_select_mode');
@ -14,19 +16,40 @@ const area_select_mode = document.querySelector('#area_select_mode');
const area_keyword = document.querySelector('#area_keyword'); const area_keyword = document.querySelector('#area_keyword');
const keyword_exclude = document.querySelector('#keyword_exclude'); const keyword_exclude = document.querySelector('#keyword_exclude');
// advance
const browser = document.querySelector('#browser');
const webdriver_type = document.querySelector('#webdriver_type');
const play_ticket_sound = document.querySelector('#play_ticket_sound');
const play_order_sound = document.querySelector('#play_order_sound');
const play_sound_filename = document.querySelector('#play_sound_filename');
const auto_reload_page_interval = document.querySelector('#auto_reload_page_interval'); const auto_reload_page_interval = document.querySelector('#auto_reload_page_interval');
const auto_press_next_step_button = document.querySelector('#auto_press_next_step_button'); const auto_press_next_step_button = document.querySelector('#auto_press_next_step_button');
const kktix_status_api = document.querySelector('#kktix_status_api'); const kktix_status_api = document.querySelector('#kktix_status_api');
const max_dwell_time = document.querySelector('#max_dwell_time'); const max_dwell_time = document.querySelector('#max_dwell_time');
const reset_browser_interval = document.querySelector('#reset_browser_interval');
const proxy_server_port = document.querySelector('#proxy_server_port');
const window_size = document.querySelector('#window_size');
const chrome_extension = document.querySelector('#chrome_extension');
const disable_adjacent_seat = document.querySelector('#disable_adjacent_seat'); const disable_adjacent_seat = document.querySelector('#disable_adjacent_seat');
const hide_some_image = document.querySelector('#hide_some_image');
const block_facebook_network = document.querySelector('#block_facebook_network');
const headless = document.querySelector('#headless');
const verbose = document.querySelector('#verbose');
const ocr_captcha_enable = document.querySelector('#ocr_captcha_enable'); const ocr_captcha_enable = document.querySelector('#ocr_captcha_enable');
const ocr_captcha_use_public_server = document.querySelector('#ocr_captcha_use_public_server'); const ocr_captcha_use_public_server = document.querySelector('#ocr_captcha_use_public_server');
const ocr_captcha_image_source = document.querySelector('#ocr_captcha_image_source');
const ocr_captcha_force_submit = document.querySelector('#ocr_captcha_force_submit');
const remote_url = document.querySelector('#remote_url'); const remote_url = document.querySelector('#remote_url');
const user_guess_string = document.querySelector('#user_guess_string');
const PUBLIC_SERVER_URL = "http://maxbot.dropboxlike.com:16888/"; const PUBLIC_SERVER_URL = "http://maxbot.dropboxlike.com:16888/";
// dictionary
const user_guess_string = document.querySelector('#user_guess_string');
// auto fill
const tixcraft_sid = document.querySelector('#tixcraft_sid'); const tixcraft_sid = document.querySelector('#tixcraft_sid');
const ibonqware = document.querySelector('#ibonqware'); const ibonqware = document.querySelector('#ibonqware');
const facebook_account = document.querySelector('#facebook_account'); const facebook_account = document.querySelector('#facebook_account');
@ -50,6 +73,7 @@ const ticketplus_password = document.querySelector('#ticketplus_password');
const urbtix_password = document.querySelector('#urbtix_password'); const urbtix_password = document.querySelector('#urbtix_password');
const hkticketing_password = document.querySelector('#hkticketing_password'); const hkticketing_password = document.querySelector('#hkticketing_password');
// runtime
const idle_keyword = document.querySelector('#idle_keyword'); const idle_keyword = document.querySelector('#idle_keyword');
const resume_keyword = document.querySelector('#resume_keyword'); const resume_keyword = document.querySelector('#resume_keyword');
const idle_keyword_second = document.querySelector('#idle_keyword_second'); const idle_keyword_second = document.querySelector('#idle_keyword_second');
@ -57,18 +81,121 @@ const resume_keyword_second = document.querySelector('#resume_keyword_second');
var settings = null; var settings = null;
load_changes(); maxbot_load_api();
run_button.addEventListener('click', maxbot_launch); function load_settins_to_form(settings)
save_button.addEventListener('click', maxbot_save); {
exit_button.addEventListener('click', maxbot_shutdown); if (settings)
pause_button.addEventListener('click', maxbot_pause_api); {
resume_button.addEventListener('click', maxbot_resume_api); //console.log("ticket_number:"+ settings.ticket_number);
// preference
homepage.value = settings.homepage;
ticket_number.value = settings.ticket_number;
date_select_mode.value = settings.date_auto_select.mode;
date_keyword.value = settings.date_auto_select.date_keyword;
if(date_keyword.value=='""') {
date_keyword.value='';
}
ocr_captcha_use_public_server.addEventListener('change', checkUsePublicServer); area_select_mode.value = settings.area_auto_select.mode;
area_keyword.value = settings.area_auto_select.area_keyword;
if(area_keyword.value=='""') {
area_keyword.value='';
}
keyword_exclude.value = settings.keyword_exclude;
// advanced
browser.value = settings.browser;
webdriver_type.value = settings.webdriver_type;
play_ticket_sound.checked = settings.advanced.play_sound.ticket;
play_order_sound.checked = settings.advanced.play_sound.order;
play_sound_filename.value = settings.advanced.play_sound.filename;
function load_changes() auto_reload_page_interval.value = settings.advanced.auto_reload_page_interval;
auto_press_next_step_button.checked = settings.kktix.auto_press_next_step_button;
kktix_status_api.checked = settings.advanced.kktix_status_api;
max_dwell_time.value = settings.advanced.max_dwell_time;
reset_browser_interval.value = settings.advanced.reset_browser_interval;
proxy_server_port.value = settings.advanced.proxy_server_port;
window_size.value = settings.advanced.window_size;
chrome_extension.checked = settings.advanced.chrome_extension;
disable_adjacent_seat.checked = settings.advanced.disable_adjacent_seat;
hide_some_image.checked = settings.advanced.hide_some_image;
block_facebook_network.checked = settings.advanced.block_facebook_network;
headless.checked = settings.advanced.headless;
verbose.checked = settings.advanced.verbose;
ocr_captcha_enable.checked = settings.ocr_captcha.enable;
ocr_captcha_image_source.value = settings.ocr_captcha.image_source;
ocr_captcha_force_submit.checked = settings.ocr_captcha.force_submit;
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;
// dictionary
user_guess_string.value = settings.advanced.user_guess_string;
if(user_guess_string.value=='""') {
user_guess_string.value='';
}
// auto fill
tixcraft_sid.value = settings.advanced.tixcraft_sid;
ibonqware.value = settings.advanced.ibonqware;
facebook_account.value = settings.advanced.facebook_account;
kktix_account.value = settings.advanced.kktix_account;
fami_account.value = settings.advanced.fami_account;
kham_account.value = settings.advanced.kham_account;
ticket_account.value = settings.advanced.ticket_account;
udn_account.value = settings.advanced.udn_account;
ticketplus_account.value = settings.advanced.ticketplus_account;
cityline_account.value = settings.advanced.cityline_account;
urbtix_account.value = settings.advanced.urbtix_account;
hkticketing_account.value = settings.advanced.hkticketing_account;
facebook_password.value = settings.advanced.facebook_password;
kktix_password.value = settings.advanced.kktix_password;
fami_password.value = settings.advanced.fami_password;
kham_password.value = settings.advanced.kham_password;
ticket_password.value = settings.advanced.ticket_password;
udn_password.value = settings.advanced.udn_password;
ticketplus_password.value = settings.advanced.ticketplus_password;
urbtix_password.value = settings.advanced.urbtix_password;
hkticketing_password.value = settings.advanced.hkticketing_password;
// runtime
idle_keyword.value = settings.advanced.idle_keyword;
if(idle_keyword.value=='""') {
idle_keyword.value='';
}
resume_keyword.value = settings.advanced.resume_keyword;
if(resume_keyword.value=='""') {
resume_keyword.value='';
}
idle_keyword_second.value = settings.advanced.idle_keyword_second;
if(idle_keyword_second.value=='""') {
idle_keyword_second.value='';
}
resume_keyword_second.value = settings.advanced.resume_keyword_second;
if(resume_keyword_second.value=='""') {
resume_keyword_second.value='';
}
} else {
console.log('no settings found');
}
}
function maxbot_load_api()
{ {
let api_url = "http://127.0.0.1:16888/load"; let api_url = "http://127.0.0.1:16888/load";
$.get( api_url, function() { $.get( api_url, function() {
@ -78,92 +205,7 @@ function load_changes()
//alert( "second success" ); //alert( "second success" );
//console.log(data); //console.log(data);
settings = data; settings = data;
if (settings) load_settins_to_form(data);
{
//console.log("ticket_number:"+ settings.ticket_number);
homepage.value = settings.homepage;
ticket_number.value = settings.ticket_number;
date_select_mode.value = settings.date_auto_select.mode;
date_keyword.value = settings.date_auto_select.date_keyword;
if(date_keyword.value=='""') {
date_keyword.value='';
}
area_select_mode.value = settings.area_auto_select.mode;
area_keyword.value = settings.area_auto_select.area_keyword;
if(area_keyword.value=='""') {
area_keyword.value='';
}
user_guess_string.value = settings.advanced.user_guess_string;
if(user_guess_string.value=='""') {
user_guess_string.value='';
}
keyword_exclude.value = settings.keyword_exclude;
auto_reload_page_interval.value = settings.advanced.auto_reload_page_interval;
auto_press_next_step_button.checked = settings.kktix.auto_press_next_step_button;
kktix_status_api.checked = settings.advanced.kktix_status_api;
max_dwell_time.value = settings.advanced.max_dwell_time;
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;
tixcraft_sid.value = settings.advanced.tixcraft_sid;
ibonqware.value = settings.advanced.ibonqware;
facebook_account.value = settings.advanced.facebook_account;
kktix_account.value = settings.advanced.kktix_account;
fami_account.value = settings.advanced.fami_account;
kham_account.value = settings.advanced.kham_account;
ticket_account.value = settings.advanced.ticket_account;
udn_account.value = settings.advanced.udn_account;
ticketplus_account.value = settings.advanced.ticketplus_account;
cityline_account.value = settings.advanced.cityline_account;
urbtix_account.value = settings.advanced.urbtix_account;
hkticketing_account.value = settings.advanced.hkticketing_account;
facebook_password.value = settings.advanced.facebook_password;
kktix_password.value = settings.advanced.kktix_password;
fami_password.value = settings.advanced.fami_password;
kham_password.value = settings.advanced.kham_password;
ticket_password.value = settings.advanced.ticket_password;
udn_password.value = settings.advanced.udn_password;
ticketplus_password.value = settings.advanced.ticketplus_password;
urbtix_password.value = settings.advanced.urbtix_password;
hkticketing_password.value = settings.advanced.hkticketing_password;
idle_keyword.value = settings.advanced.idle_keyword;
if(idle_keyword.value=='""') {
idle_keyword.value='';
}
resume_keyword.value = settings.advanced.resume_keyword;
if(resume_keyword.value=='""') {
resume_keyword.value='';
}
idle_keyword_second.value = settings.advanced.idle_keyword_second;
if(idle_keyword_second.value=='""') {
idle_keyword_second.value='';
}
resume_keyword_second.value = settings.advanced.resume_keyword_second;
if(resume_keyword_second.value=='""') {
resume_keyword_second.value='';
}
//message('Loaded saved settings.');
} else {
console.log('no settings found');
}
}) })
.fail(function() { .fail(function() {
//alert( "error" ); //alert( "error" );
@ -171,8 +213,26 @@ function load_changes()
.always(function() { .always(function() {
//alert( "finished" ); //alert( "finished" );
}); });
}
function maxbot_reset_api()
{
let api_url = "http://127.0.0.1:16888/reset";
$.get( api_url, function() {
//alert( "success" );
})
.done(function(data) {
//alert( "second success" );
//console.log(data);
settings = data;
load_settins_to_form(data);
})
.fail(function() {
//alert( "error" );
})
.always(function() {
//alert( "finished" );
});
} }
async function checkUsePublicServer() async function checkUsePublicServer()
@ -185,7 +245,14 @@ async function checkUsePublicServer()
} }
let messageClearTimer; let messageClearTimer;
function message(msg) function message(msg)
{
$("#message_detail").html("存檔完成");
$("#message_modal").modal("show");
}
function message_old(msg)
{ {
clearTimeout(messageClearTimer); clearTimeout(messageClearTimer);
const message = document.querySelector('#message'); const message = document.querySelector('#message');
@ -196,8 +263,14 @@ function message(msg)
}, 3000); }, 3000);
} }
function maxbot_launch() function maxbot_launch()
{
save_changes_to_dict(true);
maxbot_save_api(maxbot_run_api());
check_unsaved_fields();
}
function maxbot_run_api()
{ {
let api_url = "http://127.0.0.1:16888/run"; let api_url = "http://127.0.0.1:16888/run";
$.get( api_url, function() { $.get( api_url, function() {
@ -214,7 +287,7 @@ function maxbot_launch()
}); });
} }
function maxbot_shutdown() function maxbot_shutdown_api()
{ {
let api_url = "http://127.0.0.1:16888/shutdown"; let api_url = "http://127.0.0.1:16888/shutdown";
$.get( api_url, function() { $.get( api_url, function() {
@ -232,15 +305,17 @@ function maxbot_shutdown()
}); });
} }
function save_changes_to_dict() function save_changes_to_dict(silent_flag)
{ {
const ticket_number_value = ticket_number.value; const ticket_number_value = ticket_number.value;
//console.log(ticket_number_value); //console.log(ticket_number_value);
if (!ticket_number_value) if (!ticket_number_value)
{ {
message('Error: No ticket_number specified'); message('提示: 請指定張數');
} else { } else {
if(settings) { if(settings) {
// preference
settings.homepage = homepage.value; settings.homepage = homepage.value;
settings.ticket_number = ticket_number_value; settings.ticket_number = ticket_number_value;
settings.date_auto_select.mode = date_select_mode.value; settings.date_auto_select.mode = date_select_mode.value;
@ -259,20 +334,36 @@ function save_changes_to_dict()
} }
settings.area_auto_select.area_keyword = area_keyword_string; settings.area_auto_select.area_keyword = area_keyword_string;
let user_guess_string_string = user_guess_string.value;
if(user_guess_string_string.indexOf('"')==-1) {
user_guess_string_string = '"' + user_guess_string_string + '"';
}
settings.advanced.user_guess_string = user_guess_string_string;
settings.keyword_exclude = keyword_exclude.value; settings.keyword_exclude = keyword_exclude.value;
// advanced
settings.browser = browser.value;
settings.webdriver_type = webdriver_type.value;
settings.advanced.play_sound.ticket = play_ticket_sound.checked;
settings.advanced.play_sound.order = play_order_sound.checked;
settings.advanced.play_sound.filename = play_sound_filename.value;
settings.advanced.auto_reload_page_interval = auto_reload_page_interval.value; settings.advanced.auto_reload_page_interval = auto_reload_page_interval.value;
settings.kktix.auto_press_next_step_button = auto_press_next_step_button.checked; settings.kktix.auto_press_next_step_button = auto_press_next_step_button.checked;
settings.advanced.kktix_status_api = kktix_status_api.checked; settings.advanced.kktix_status_api = kktix_status_api.checked;
settings.advanced.max_dwell_time = max_dwell_time.value; settings.advanced.max_dwell_time = max_dwell_time.value;
settings.advanced.reset_browser_interval = reset_browser_interval.value;
settings.advanced.proxy_server_port = proxy_server_port.value;
settings.advanced.window_size = window_size.value;
settings.advanced.chrome_extension = chrome_extension.checked;
settings.advanced.disable_adjacent_seat = disable_adjacent_seat.checked; settings.advanced.disable_adjacent_seat = disable_adjacent_seat.checked;
settings.advanced.hide_some_image = hide_some_image.checked;
settings.advanced.block_facebook_network = block_facebook_network.checked;
settings.advanced.headless = headless.checked;
settings.advanced.verbose = verbose.checked;
settings.ocr_captcha.enable = ocr_captcha_enable.checked; settings.ocr_captcha.enable = ocr_captcha_enable.checked;
settings.ocr_captcha.image_source = ocr_captcha_image_source.value;
settings.ocr_captcha.force_submit = ocr_captcha_force_submit.checked;
let remote_url_array = []; let remote_url_array = [];
remote_url_array.push(remote_url.value); remote_url_array.push(remote_url.value);
@ -282,40 +373,50 @@ function save_changes_to_dict()
//console.log("final remote_url_string:"+remote_url_string); //console.log("final remote_url_string:"+remote_url_string);
settings.advanced.remote_url = remote_url_string; settings.advanced.remote_url = remote_url_string;
settings.tixcraft_sid = tixcraft_sid.value; // dictionary
settings.ibonqware = ibonqware.value; let user_guess_string_string = user_guess_string.value;
settings.facebook_account = facebook_account.value; if(user_guess_string_string.indexOf('"')==-1) {
settings.kktix_account = kktix_account.value; user_guess_string_string = '"' + user_guess_string_string + '"';
settings.fami_account = fami_account.value; }
settings.kham_account = kham_account.value; settings.advanced.user_guess_string = user_guess_string_string;
settings.ticket_account = ticket_account.value;
settings.udn_account = udn_account.value;
settings.ticketplus_account = ticketplus_account.value;
settings.cityline_account = cityline_account.value;
settings.urbtix_account = urbtix_account.value;
settings.hkticketing_account = hkticketing_account.value;
settings.facebook_password = facebook_password.value; // auto fill
settings.kktix_password = kktix_password.value; settings.advanced.tixcraft_sid = tixcraft_sid.value;
settings.fami_password = fami_password.value; settings.advanced.ibonqware = ibonqware.value;
settings.kham_password = kham_password.value; settings.advanced.facebook_account = facebook_account.value;
settings.ticket_password = ticket_password.value; settings.advanced.kktix_account = kktix_account.value;
settings.udn_password = udn_password.value; settings.advanced.fami_account = fami_account.value;
settings.ticketplus_password = ticketplus_password.value; settings.advanced.kham_account = kham_account.value;
settings.urbtix_password = urbtix_password.value; settings.advanced.ticket_account = ticket_account.value;
settings.hkticketing_password = hkticketing_password.value; settings.advanced.udn_account = udn_account.value;
settings.advanced.ticketplus_account = ticketplus_account.value;
settings.advanced.cityline_account = cityline_account.value;
settings.advanced.urbtix_account = urbtix_account.value;
settings.advanced.hkticketing_account = hkticketing_account.value;
settings.advanced.facebook_password = facebook_password.value;
settings.advanced.kktix_password = kktix_password.value;
settings.advanced.fami_password = fami_password.value;
settings.advanced.kham_password = kham_password.value;
settings.advanced.ticket_password = ticket_password.value;
settings.advanced.udn_password = udn_password.value;
settings.advanced.ticketplus_password = ticketplus_password.value;
settings.advanced.urbtix_password = urbtix_password.value;
settings.advanced.hkticketing_password = hkticketing_password.value;
// runtime
settings.advanced.idle_keyword = idle_keyword.value; settings.advanced.idle_keyword = idle_keyword.value;
settings.advanced.resume_keyword = resume_keyword.value; settings.advanced.resume_keyword = resume_keyword.value;
settings.advanced.idle_keyword_second = idle_keyword_second.value; settings.advanced.idle_keyword_second = idle_keyword_second.value;
settings.advanced.resume_keyword_second = resume_keyword_second.value; settings.advanced.resume_keyword_second = resume_keyword_second.value;
} }
message('Settings saved'); if(!silent_flag) {
message('已存檔');
}
} }
} }
function maxbot_save_api() function maxbot_save_api(callback)
{ {
let api_url = "http://127.0.0.1:16888/save"; let api_url = "http://127.0.0.1:16888/save";
if(settings) { if(settings) {
@ -324,6 +425,7 @@ function maxbot_save_api()
}) })
.done(function(data) { .done(function(data) {
//alert( "second success" ); //alert( "second success" );
if(callback) callback;
}) })
.fail(function() { .fail(function() {
//alert( "error" ); //alert( "error" );
@ -373,9 +475,77 @@ function maxbot_resume_api()
} }
function maxbot_save() function maxbot_save()
{ {
//$('#saveModal').modal('show') save_changes_to_dict(false);
save_changes_to_dict();
maxbot_save_api(); maxbot_save_api();
check_unsaved_fields();
}
function check_unsaved_fields()
{
if(settings) {
const field_list_basic = ["homepage","ticket_number","browser","webdriver_type"];
field_list_basic.forEach(f => {
const field = document.querySelector('#'+f);
if(field.value != settings[f]) {
$("#"+f).addClass("is-invalid");
} else {
$("#"+f).removeClass("is-invalid");
}
});
const field_list_advance = [
"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",
"hkticketing_password",
"kham_password",
"ticket_password",
"udn_password",
"ticketplus_password",
"user_guess_string",
"remote_url",
"auto_reload_page_interval",
"reset_browser_interval",
"max_dwell_time",
"proxy_server_port",
"window_size",
"idle_keyword",
"resume_keyword",
"idle_keyword_second",
"resume_keyword_second"
];
field_list_advance.forEach(f => {
const field = document.querySelector('#'+f);
let formated_saved_value = settings["advanced"][f];
if(formated_saved_value=='""') formated_saved_value="";
//console.log(f);
//console.log(field.value);
//console.log(formated_saved_value);
let compare_resule = (field.value != formated_saved_value);
if(!compare_resule) {
if(field.value.indexOf('"') > -1) {
compare_resule = (field.value != '"' + formated_saved_value + '"');
}
}
if(compare_resule) {
$("#"+f).addClass("is-invalid");
} else {
$("#"+f).removeClass("is-invalid");
}
});
}
} }
function maxbot_status_api() function maxbot_status_api()
@ -411,13 +581,29 @@ function maxbot_status_api()
function update_system_time() function update_system_time()
{ {
var currentdate = new Date(); var currentdate = new Date();
var datetime = currentdate.getHours() + ":" var datetime = ("0" + currentdate.getHours()).slice(-2) + ":"
+ currentdate.getMinutes() + ":" + ("0" + currentdate.getMinutes()).slice(-2) + ":"
+ currentdate.getSeconds(); + ("0" + currentdate.getSeconds()).slice(-2);
$("#system_time").html(datetime); $("#system_time").html(datetime);
} }
var status_interval= setInterval(() => { var status_interval= setInterval(() => {
maxbot_status_api(); maxbot_status_api();
update_system_time(); update_system_time();
}, 200); }, 500);
run_button.addEventListener('click', maxbot_launch);
save_button.addEventListener('click', maxbot_save);
reset_button.addEventListener('click', maxbot_reset_api);
exit_button.addEventListener('click', maxbot_shutdown_api);
pause_button.addEventListener('click', maxbot_pause_api);
resume_button.addEventListener('click', maxbot_resume_api);
ocr_captcha_use_public_server.addEventListener('change', checkUsePublicServer);
const onchange_tag_list = ["input","select","textarea"];
onchange_tag_list.forEach((tag) => {
const input_items = document.querySelectorAll(tag);
input_items.forEach((userItem) => {
userItem.addEventListener('change', check_unsaved_fields);
});
});