├── ding.wav ├── ding-dong.wav ├── sound_clap.mp3 ├── icon_chrome_4.gif ├── icon_copy_2.gif ├── icon_play_1.gif ├── icon_query_5.gif ├── sound_victory.mp3 ├── webdriver ├── Maxbotplus_1.0.0 │ ├── js │ │ ├── ticket_home.js │ │ ├── kham_event_home.js │ │ ├── checkbox.js │ │ ├── tixcraft_home.js │ │ ├── ticket_event_home.js │ │ ├── ticket_date.js │ │ ├── ticket_area.js │ │ ├── kktix_home.js │ │ ├── kham_home.js │ │ ├── kham_date.js │ │ ├── tixcraft_detail.js │ │ ├── ibon_ticket_next.js │ │ ├── cityline_event_detail.js │ │ ├── cityline_shows_buy_front.js │ │ ├── cityline_msg_background.js │ │ ├── hkticketing_queue_background.js │ │ ├── ibon_area_front.js │ │ ├── kktix_events.js │ │ ├── hkticketing_queue_front.js │ │ ├── ibon_verification.js │ │ ├── kham_area.js │ │ ├── common.js │ │ ├── ticketplus_activity.js │ │ ├── ticketmaster_area.js │ │ ├── cityline_msg_front.js │ │ ├── tixcraft_game.js │ │ ├── cityline_performance.js │ │ ├── ticketplus_order.js │ │ ├── tixcraft_area.js │ │ ├── ibon_area.js │ │ ├── ibon_detail.js │ │ ├── ibon_ticket.js │ │ ├── ticket_ticket.js │ │ ├── kktix_registrations_reload.js │ │ ├── tixcraft_ticket.js │ │ └── kktix_registrations_assign.js │ ├── icons │ │ ├── maxbot-128.png │ │ ├── maxbot-16.png │ │ ├── maxbot-32.png │ │ ├── maxbot-48.png │ │ └── maxbot-64.png │ ├── css │ │ └── options.css │ ├── modules │ │ └── heartbeatconnect.js │ ├── data │ │ └── settings.json │ ├── options.js │ ├── options.html │ └── manifest.json └── Maxblockplus_1.0.0 │ ├── icons │ ├── maxblock-128.png │ ├── maxblock-16.png │ ├── maxblock-32.png │ ├── maxblock-48.png │ └── maxblock-64.png │ ├── dist │ └── glyphicon │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ └── glyphicon.css │ ├── css │ └── options.css │ ├── manifest.json │ ├── options.html │ ├── background.js │ ├── data │ └── settings.json │ └── options.js ├── maxbot_logo2_single.ppm ├── config_launcher.json ├── pip-req.txt ├── NonBrowser.py ├── settings.json ├── LEGAL_NOTICE.md ├── demo_video.md └── README.md /ding.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/ding.wav -------------------------------------------------------------------------------- /ding-dong.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/ding-dong.wav -------------------------------------------------------------------------------- /sound_clap.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/sound_clap.mp3 -------------------------------------------------------------------------------- /icon_chrome_4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/icon_chrome_4.gif -------------------------------------------------------------------------------- /icon_copy_2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/icon_copy_2.gif -------------------------------------------------------------------------------- /icon_play_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/icon_play_1.gif -------------------------------------------------------------------------------- /icon_query_5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/icon_query_5.gif -------------------------------------------------------------------------------- /sound_victory.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/sound_victory.mp3 -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ticket_home.js: -------------------------------------------------------------------------------- 1 | $("#footer").remove(); 2 | $("footer").remove(); 3 | -------------------------------------------------------------------------------- /maxbot_logo2_single.ppm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/maxbot_logo2_single.ppm -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/kham_event_home.js: -------------------------------------------------------------------------------- 1 | $("body > div.buynow > a button[onclick].red").click(); 2 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/checkbox.js: -------------------------------------------------------------------------------- 1 | $('input[type=checkbox]').each(function() { 2 | $(this).prop('checked', true); 3 | }); 4 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/icons/maxbot-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxbotplus_1.0.0/icons/maxbot-128.png -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/icons/maxbot-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxbotplus_1.0.0/icons/maxbot-16.png -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/icons/maxbot-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxbotplus_1.0.0/icons/maxbot-32.png -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/icons/maxbot-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxbotplus_1.0.0/icons/maxbot-48.png -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/icons/maxbot-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxbotplus_1.0.0/icons/maxbot-64.png -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/icons/maxblock-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxblockplus_1.0.0/icons/maxblock-128.png -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/icons/maxblock-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxblockplus_1.0.0/icons/maxblock-16.png -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/icons/maxblock-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxblockplus_1.0.0/icons/maxblock-32.png -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/icons/maxblock-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxblockplus_1.0.0/icons/maxblock-48.png -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/icons/maxblock-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxblockplus_1.0.0/icons/maxblock-64.png -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/tixcraft_home.js: -------------------------------------------------------------------------------- 1 | $("#newsHome").remove(); 2 | $("footer").remove(); 3 | $("#topAlert").remove(); 4 | $("div.darkBg > div.container > div.row").remove(); -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ticket_event_home.js: -------------------------------------------------------------------------------- 1 | $a_btn=$("#portfolio").find("a[onclick]"); 2 | if($a_btn.length>0) { 3 | $click_event=$a_btn.attr("onclick"); 4 | $a_btn.click(); 5 | } 6 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ticket_date.js: -------------------------------------------------------------------------------- 1 | $a_btn=$("#portfolio").find("div.description > table.table > tbody > tr > td > button[onclick]"); 2 | if($a_btn.length==1) { 3 | $a_btn.click(); 4 | } 5 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ticket_area.js: -------------------------------------------------------------------------------- 1 | // price row. 2 | $("ul.area-list > span > li:not(:has(a))").remove(); 3 | // description row. 4 | $("ul.area-list > li:not(:has(a))").remove(); 5 | $("footer").remove(); -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/dist/glyphicon/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxblockplus_1.0.0/dist/glyphicon/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/css/options.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 36px; 3 | } 4 | 5 | textarea { 6 | font-family: monospace; 7 | } 8 | 9 | .message { 10 | height: 20px; 11 | background: #eee; 12 | padding: 5px; 13 | } -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/dist/glyphicon/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxblockplus_1.0.0/dist/glyphicon/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/dist/glyphicon/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipf37200/tixcraft_bot_1/HEAD/webdriver/Maxblockplus_1.0.0/dist/glyphicon/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/kktix_home.js: -------------------------------------------------------------------------------- 1 | $("div.headlines").remove(); 2 | $("section.app-intro").remove(); 3 | $("section.copywriting").remove(); 4 | $("section.partner-venues").remove(); 5 | $("footer").remove(); 6 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/css/options.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 36px; 3 | } 4 | 5 | textarea { 6 | font-family: monospace; 7 | } 8 | 9 | .message { 10 | height: 20px; 11 | background: #eee; 12 | padding: 5px; 13 | } -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/kham_home.js: -------------------------------------------------------------------------------- 1 | $("div#dialog-message").remove(); 2 | $("div#ad3").remove(); 3 | $("div#buyTicket").remove(); 4 | $("div#marquee").remove(); 5 | $("div.footer").remove(); 6 | $(".popoutBG").remove(); 7 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/kham_date.js: -------------------------------------------------------------------------------- 1 | $("div#DIV_REMARK").remove(); 2 | $("div.footer").remove(); 3 | 4 | $a_btn=$("#content").find("table.eventTABLE > tbody > tr > td > a > button[onclick]"); 5 | if($a_btn.length==1) { 6 | $a_btn.click(); 7 | } 8 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/tixcraft_detail.js: -------------------------------------------------------------------------------- 1 | const currentUrl = window.location.href; 2 | const event_code = currentUrl.split('/')[5]; 3 | //console.log(currentUrl); 4 | //console.log(event_code); 5 | if(event_code){ 6 | const domain = currentUrl.split('/')[2]; 7 | const new_url = "https://"+ domain +"/activity/game/"+ event_code; 8 | location.href=new_url; 9 | } 10 | -------------------------------------------------------------------------------- /config_launcher.json: -------------------------------------------------------------------------------- 1 | { 2 | "list": [ 3 | "settings.json", 4 | "", 5 | "", 6 | "", 7 | "", 8 | "", 9 | "", 10 | "", 11 | "", 12 | "", 13 | "", 14 | "", 15 | "", 16 | "", 17 | "" 18 | ], 19 | "advanced": { 20 | "language": "\u7e41\u9ad4\u4e2d\u6587" 21 | } 22 | } -------------------------------------------------------------------------------- /pip-req.txt: -------------------------------------------------------------------------------- 1 | certifi 2 | chardet 3 | chromedriver-autoinstaller-max 4 | cryptography 5 | ddddocr 6 | idna 7 | looseversion 8 | nodriver 9 | numpy 10 | Pillow 11 | playsound==1.2.2 12 | pyperclip 13 | selenium 14 | tornado 15 | undetected-chromedriver 16 | urllib3 17 | #PS: nodriver need python 3.9+ 18 | # nodriver max modified version: 19 | # python -m pip install git+https://github.com/max32002/nodriver -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ibon_ticket_next.js: -------------------------------------------------------------------------------- 1 | var myInterval = null; 2 | 3 | function dom_ready() 4 | { 5 | let ret=false; 6 | if($("#done").length>0) { 7 | $("#done").remove(); 8 | ret=true; 9 | if(myInterval) clearInterval(myInterval); 10 | (function () { 11 | $("div#ticket-wrap a[onclick]").click(); 12 | })(); 13 | } 14 | //console.log("dom_ready:"+ret); 15 | return ret; 16 | } 17 | 18 | if(!dom_ready()) { 19 | myInterval = setInterval(() => { 20 | dom_ready(); 21 | }, 100); 22 | } 23 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/cityline_event_detail.js: -------------------------------------------------------------------------------- 1 | $("#eventLargeCoverUrl").remove(); 2 | $("#s_footer").remove(); 3 | $("footer").remove(); 4 | 5 | function dom_ready() { 6 | let eventId = getUrlParameter('event'); 7 | //let selectedPerfId = 71202; 8 | var url = contextPath + "/[activityCode]/performance?event=[eventId]&perfId=[perfId]"; 9 | url = url.replace("[activityCode]",activityCode) 10 | .replace("[eventId]", eventId) 11 | .replace("[perfId]",selectedPerfId) 12 | //console.log(url); 13 | //location.href = url; 14 | } 15 | 16 | // not able to redirt, must click reCAPTCAH button. 17 | // dom_ready(); 18 | 19 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/cityline_shows_buy_front.js: -------------------------------------------------------------------------------- 1 | var myInterval = null; 2 | 3 | function dom_ready() 4 | { 5 | let ret=false; 6 | if($("#buyTicketBtn").length>0) { 7 | ret=true; 8 | if(myInterval) clearInterval(myInterval); 9 | 10 | (function () { 11 | console.log($("#buyTicketBtn").length); 12 | if($("#buyTicketBtn").length) { 13 | console.log("clicking"); 14 | $("#buyTicketBtn").trigger("click"); 15 | //go(); 16 | } 17 | })(); 18 | 19 | } 20 | console.log("dom_ready:"+ret); 21 | return ret; 22 | } 23 | 24 | if(!dom_ready()) { 25 | myInterval = setInterval(() => { 26 | dom_ready(); 27 | }, 100); 28 | } 29 | 30 | 31 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/cityline_msg_background.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | 4 | function cityline_msg_start(status) 5 | { 6 | if(settings) { 7 | let settings_div=""; 8 | $("body").append(settings_div); 9 | let status_div=""; 10 | $("body").append(status_div); 11 | //console.log("dom append"); 12 | } 13 | } 14 | 15 | storage.get('settings', function (items) 16 | { 17 | if (items.settings) 18 | { 19 | settings = items.settings; 20 | } 21 | }); 22 | 23 | storage.get('status', function (items) 24 | { 25 | if (items.status && items.status=='ON') 26 | { 27 | cityline_msg_start(items.status); 28 | } else { 29 | console.log('no status found'); 30 | } 31 | }); 32 | 33 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/hkticketing_queue_background.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | 4 | function hkticketing_msg_start(status) 5 | { 6 | if(settings) { 7 | let settings_div=""; 8 | $("body").append(settings_div); 9 | let status_div=""; 10 | $("body").append(status_div); 11 | console.log("dom append"); 12 | } 13 | } 14 | 15 | storage.get('settings', function (items) 16 | { 17 | if (items.settings) 18 | { 19 | settings = items.settings; 20 | } 21 | }); 22 | 23 | storage.get('status', function (items) 24 | { 25 | if (items.status && items.status=='ON') 26 | { 27 | hkticketing_msg_start(items.status); 28 | } else { 29 | console.log('no status found'); 30 | } 31 | }); 32 | 33 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ibon_area_front.js: -------------------------------------------------------------------------------- 1 | var myInterval = null; 2 | 3 | function dom_ready() 4 | { 5 | let ret=false; 6 | if($("#maxbot").length>0) { 7 | let target_id = $("#maxbot").text(); 8 | //console.log(target_id); 9 | $("#maxbot").remove(); 10 | ret=true; 11 | if(myInterval) clearInterval(myInterval); 12 | (function () { 13 | if(target_id) { 14 | console.log(target_id); 15 | console.log($("#"+target_id).text()); 16 | //https://orders.ibon.com.tw/application/UTK02/UTK0201_000.aspx?PERFORMANCE_ID=B06PV2MC&PRODUCT_ID=B06PS1OC 17 | //https://orders.ibon.com.tw/application/UTK02/UTK0202_.aspx?PERFORMANCE_ID=B06PV2MC&GROUP_ID=&PERFORMANCE_PRICE_AREA_ID=B06PV2PH 18 | $("#"+target_id).trigger("click"); 19 | onTicketArea(target_id); 20 | } 21 | })(); 22 | } 23 | //console.log("dom_ready:"+ret); 24 | return ret; 25 | } 26 | 27 | if(!dom_ready()) { 28 | myInterval = setInterval(() => { 29 | dom_ready(); 30 | }, 100); 31 | } 32 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/kktix_events.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | 3 | $("div.description").remove(); 4 | $("footer").remove(); 5 | 6 | function kktix_event_redirect() 7 | { 8 | const currentUrl = window.location.href; 9 | let event_code = currentUrl.split('/')[4]; 10 | if(event_code.indexOf('?') > -1) { 11 | event_code = event_code.split('?')[0]; 12 | } 13 | //console.log(currentUrl); 14 | //console.log(event_code); 15 | if(event_code){ 16 | let button_count = $("div.tickets > a.btn-point").length; 17 | //console.log("length:"+button_count); 18 | if (button_count == 1) { 19 | let new_url = "https://kktix.com/events/"+ event_code +"/registrations/new"; 20 | location.href=new_url; 21 | } else { 22 | // do nothing. 23 | } 24 | } 25 | } 26 | 27 | storage.get('status', function (items) 28 | { 29 | if (items.status && items.status=='ON') 30 | { 31 | kktix_event_redirect(); 32 | } else { 33 | console.log('no status found'); 34 | } 35 | }); 36 | -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Max Yao", 3 | "name": "MaxBlock Plus", 4 | "description": "Help you block net request to load pages faster.", 5 | "icons": { 6 | "16": "icons/maxblock-16.png", 7 | "32": "icons/maxblock-32.png", 8 | "48": "icons/maxblock-48.png", 9 | "64": "icons/maxblock-64.png", 10 | "128": "icons/maxblock-128.png" 11 | }, 12 | "manifest_version": 3, 13 | "background": { 14 | "service_worker": "background.js", 15 | "type": "module" 16 | }, 17 | "permissions": [ 18 | "storage", 19 | "declarativeNetRequest", 20 | "declarativeNetRequestFeedback" 21 | ], 22 | "options_page": "options.html", 23 | "web_accessible_resources": [ 24 | { 25 | "resources": [ 26 | "data/*.json" 27 | ], 28 | "extension_ids": [ 29 | "*" 30 | ], 31 | "matches": [ 32 | "*://*/*" 33 | ] 34 | } 35 | ], 36 | "action": { 37 | "default_icon": "icons/maxblock-128.png", 38 | "default_title": "MaxBlock" 39 | }, 40 | "version": "1.0.0" 41 | } -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/hkticketing_queue_front.js: -------------------------------------------------------------------------------- 1 | function begin() 2 | { 3 | const settings_div = document.querySelector('#settings'); 4 | const status_div = document.querySelector('#status'); 5 | let settings = JSON.parse(settings_div.innerHTML); 6 | let status = status_div.innerHTML; 7 | //console.log("msg"); 8 | //console.log(settings); 9 | //console.log(status); 10 | 11 | let auto_reload_page_interval = 0.0; 12 | if(settings) { 13 | auto_reload_page_interval = settings.advanced.auto_reload_page_interval; 14 | } 15 | 16 | // too short to cause error. 17 | if(auto_reload_page_interval < 0.5) { 18 | auto_reload_page_interval = 0.5; 19 | } 20 | 21 | if(status=='ON') { 22 | setInterval(() => { 23 | //var busyFor = 0; 24 | reload(); 25 | }, auto_reload_page_interval * 1000); 26 | } 27 | } 28 | 29 | function dom_ready() 30 | { 31 | //console.log("checking..."); 32 | const settings_div = document.querySelector('#settings'); 33 | if(settings_div) { 34 | clearInterval(myInterval); 35 | begin(); 36 | } 37 | } 38 | 39 | myInterval = setInterval(() => { 40 | dom_ready(); 41 | }, 100); 42 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ibon_verification.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | 4 | function ibon_verification_main() { 5 | let user_guess_string_array = []; 6 | if(settings) { 7 | if(settings.advanced.user_guess_string.length > 0) { 8 | if(settings.advanced.user_guess_string!='""') { 9 | user_guess_string_array = JSON.parse('[' + settings.advanced.user_guess_string +']'); 10 | } 11 | } 12 | } 13 | 14 | let target_row=null; 15 | let all_row = $("div.editor-box > div > div.form-group > input[type='text']"); 16 | if (all_row.length > 0 && user_guess_string_array.length > 0) 17 | { 18 | //console.log("input count:" + all_row.length); 19 | let travel_index=0; 20 | all_row.each(function () 21 | { 22 | let current_index = all_row.index(this); 23 | //console.log("current_index:" + current_index); 24 | if(current_index+1 <= user_guess_string_array.length) { 25 | //console.log("input data:" + user_guess_string_array[current_index]); 26 | $(this).val(user_guess_string_array[current_index]); 27 | } 28 | }); 29 | } 30 | } 31 | 32 | storage.get('settings', function (items) 33 | { 34 | if (items.settings) 35 | { 36 | settings = items.settings; 37 | } 38 | }); 39 | 40 | storage.get('status', function (items) 41 | { 42 | if (items.status && items.status=='ON') 43 | { 44 | ibon_verification_main(); 45 | } else { 46 | console.log('no status found'); 47 | } 48 | }); 49 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/kham_area.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | var myInterval = null; 4 | 5 | // price row. 6 | $("#salesTable > tbody > tr.Soldout").remove(); 7 | $("div.footer").remove(); 8 | 9 | function kham_clean_exclude(settings) 10 | { 11 | console.log("kham_clean_exclude"); 12 | 13 | let exclude_keyword_array = []; 14 | if(settings) { 15 | if(settings.keyword_exclude.length > 0) { 16 | if(settings.keyword_exclude != '""') { 17 | exclude_keyword_array = JSON.parse('[' + settings.keyword_exclude +']'); 18 | } 19 | } 20 | } 21 | 22 | for (let i = 0; i < exclude_keyword_array.length; i++) { 23 | $("#salesTable > tbody > tr").each(function () 24 | { 25 | let html_text=$(this).text(); 26 | let is_match_keyword=false; 27 | if(html_text.indexOf(exclude_keyword_array[i])>-1) { 28 | is_match_keyword=true; 29 | } 30 | if(is_match_keyword) { 31 | $(this).remove(); 32 | } 33 | } 34 | ); 35 | } 36 | } 37 | 38 | function kktix_area_main() { 39 | if(settings) { 40 | kham_clean_exclude(settings); 41 | } 42 | } 43 | 44 | storage.get('settings', function (items) 45 | { 46 | if (items.settings) 47 | { 48 | settings = items.settings; 49 | } 50 | }); 51 | 52 | storage.get('status', function (items) 53 | { 54 | if (items.status && items.status=='ON') 55 | { 56 | kktix_area_main(); 57 | } else { 58 | //console.log('maxbot status is not ON'); 59 | } 60 | }); 61 | 62 | 63 | -------------------------------------------------------------------------------- /NonBrowser.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import json 3 | from io import BytesIO 4 | 5 | import requests 6 | from PIL import Image 7 | 8 | 9 | class NonBrowser(): 10 | def __init__(self, domain_name = "tixcraft.com") -> None: 11 | self.Session = requests.session() 12 | self.Set_Domain(domain_name) 13 | 14 | def Set_cookies(self, cookies:dict): 15 | ret = False 16 | if not cookies is None: 17 | for cookie in cookies: 18 | self.Session.cookies.set(cookie["name"],cookie["value"]) 19 | ret = True 20 | return ret 21 | 22 | def Get_cookies(self): 23 | return self.Session.cookies.get_dict() 24 | 25 | def set_headers(self, header:str): 26 | self.Session.headers = header 27 | 28 | def Set_Domain(self, domain_name, captcha_url="ticket/captcha", refresh_url="ticket/captcha?refresh=1"): 29 | self.url = "https://%s/%s" % (domain_name, captcha_url) 30 | self.refresh_url = "https://%s/%s" % (domain_name, refresh_url) 31 | 32 | def Request_Captcha(self): 33 | img = Image.open(BytesIO(self.Session.get(self.url, stream = True).content)) 34 | output_buffer = BytesIO() 35 | img.save(output_buffer, format='JPEG') 36 | binary_data = output_buffer.getvalue() 37 | base64_data = base64.b64encode(binary_data) 38 | return base64_data 39 | 40 | def Request_Refresh_Captcha(self) -> str: 41 | try: 42 | result = self.Session.get(self.refresh_url, stream = True) 43 | if result.status_code == 200: 44 | json_data = json.loads(result.text) 45 | return json_data.get("url","") 46 | else: 47 | return "" 48 | except Exception as e: 49 | return "" -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Extension Options 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |

MaxBlock Settings

15 |
16 | 17 |
18 | Input example: *.example.com/* 19 |
20 |
21 |
22 | 23 |
24 | 25 |
26 |
27 |
28 | 29 |
30 | 31 | 32 | 33 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
34 | 35 | Domain Filter
43 | 44 |
45 |
46 |
47 |
48 | 49 |
50 |
51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/modules/heartbeatconnect.js: -------------------------------------------------------------------------------- 1 | const https_url = "https://"; 2 | const http_url = "https://"; 3 | 4 | class HeartBeatConnector 5 | { 6 | constructor() {} 7 | 8 | start() 9 | { 10 | sync_status_from_parent(); 11 | } 12 | } 13 | 14 | function set_status_to(flag) 15 | { 16 | let nextState = 'ON'; 17 | if (!flag) 18 | { 19 | nextState = 'OFF'; 20 | } 21 | 22 | //console.log(nextState); 23 | chrome.action.setBadgeText( 24 | { 25 | text: nextState 26 | } 27 | ); 28 | 29 | chrome.storage.local.set( 30 | { 31 | status: nextState 32 | } 33 | ); 34 | } 35 | 36 | function set_webserver_runing_to(flag) 37 | { 38 | chrome.storage.local.set( 39 | { 40 | webserver_runing: flag 41 | } 42 | ); 43 | } 44 | 45 | function sync_status_from_parent() 46 | { 47 | //console.log("sync_status_from_parent"); 48 | 49 | let data_url = chrome.runtime.getURL("data/status.json"); 50 | fetch(data_url) 51 | .then(response => 52 | { 53 | if (response.ok) 54 | { 55 | set_webserver_runing_to(true); 56 | return response.json() 57 | } 58 | else if (response.status === 404) 59 | { 60 | set_webserver_runing_to(false); 61 | return Promise.reject('error 404') 62 | } 63 | else 64 | { 65 | set_webserver_runing_to(false); 66 | return Promise.reject('some other error: ' + response.status) 67 | } 68 | } 69 | ) 70 | .then((data) => 71 | { 72 | //console.log(data); 73 | if (data) 74 | { 75 | set_status_to(data.status); 76 | } 77 | } 78 | ) 79 | .catch(error => 80 | { 81 | //console.log('error is', error) 82 | set_webserver_runing_to(false); 83 | } 84 | ); 85 | } 86 | 87 | function ack() 88 | { 89 | //console.log("act"); 90 | } 91 | 92 | export default new HeartBeatConnector(); 93 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/common.js: -------------------------------------------------------------------------------- 1 | function get_target_area_with_order(settings, matched_block) 2 | { 3 | //console.log(settings); 4 | let target_area = null; 5 | 6 | if(matched_block.length) { 7 | let last_index = matched_block.length-1 8 | let center_index = 0; 9 | let random_index = 0; 10 | if(matched_block.length>1) { 11 | center_index = parseInt(last_index/2); 12 | random_index = getRandom(0,last_index) 13 | } 14 | if(settings.area_auto_select.mode=="from top to bottom") 15 | target_area = matched_block[0]; 16 | if(settings.area_auto_select.mode=="from bottom to top") 17 | target_area = matched_block[last_index]; 18 | if(settings.area_auto_select.mode=="center") 19 | target_area = matched_block[center_index]; 20 | if(settings.area_auto_select.mode=="random") 21 | target_area = matched_block[random_index]; 22 | } 23 | return target_area; 24 | } 25 | 26 | function get_target_date_with_order(settings, matched_block) 27 | { 28 | //console.log(settings); 29 | let target_area = null; 30 | 31 | if(matched_block.length) { 32 | let last_index = matched_block.length-1 33 | let center_index = 0; 34 | let random_index = 0; 35 | if(matched_block.length>1) { 36 | center_index = parseInt(last_index/2); 37 | random_index = getRandom(0,last_index) 38 | } 39 | if(settings.date_auto_select.mode=="from top to bottom") 40 | target_area = matched_block[0]; 41 | if(settings.date_auto_select.mode=="from bottom to top") 42 | target_area = matched_block[last_index]; 43 | if(settings.date_auto_select.mode=="center") 44 | target_area = matched_block[center_index]; 45 | if(settings.date_auto_select.mode=="random") 46 | target_area = matched_block[random_index]; 47 | } 48 | 49 | return target_area; 50 | } 51 | 52 | function getRandom(min,max){ 53 | return Math.floor(Math.random()*(max-min+1))+min; 54 | }; -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ticketplus_activity.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var settings = null; 3 | var maxbot_status = null; 4 | 5 | async function ajax_return_done(data, event_id) 6 | { 7 | //console.log(data); 8 | if(settings) { 9 | if(data.sessions) { 10 | // if, only one event, auto redirect. 11 | if(data.sessions.length==1) { 12 | let session_id=data.sessions[0].sessionId; 13 | if(session_id) { 14 | let new_url = "https://ticketplus.com.tw/order/"+ event_id +"/" + session_id; 15 | location.href = new_url; 16 | } 17 | } 18 | } 19 | } 20 | } 21 | 22 | async function wait_function_ready() { 23 | const currentUrl = window.location.href; 24 | const event_id = currentUrl.split('/')[4]; 25 | if(event_id){ 26 | let api_url = "https://apis.ticketplus.com.tw/config/api/v1/getS3?path=event/"+event_id+"/sessions.json"; 27 | //console.log("calling api:" + api_url); 28 | $.get( api_url, function() { 29 | //alert( "success" ); 30 | }) 31 | .done(function(data) { 32 | //alert( "second success" ); 33 | if(data) { 34 | ajax_return_done(data, event_id); 35 | } 36 | }) 37 | .fail(function() { 38 | //alert( "error" ); 39 | }) 40 | .always(function() { 41 | //alert( "finished" ); 42 | }); 43 | } 44 | } 45 | 46 | chrome.storage.local.get('settings', function (items) 47 | { 48 | if (items.settings) 49 | { 50 | settings = items.settings; 51 | } else { 52 | console.log('no status found'); 53 | } 54 | }); 55 | 56 | chrome.storage.local.get('status', function (items) 57 | { 58 | if (items.status) 59 | { 60 | maxbot_status = items.status; 61 | //console.log("maxbot_status:" + maxbot_status) 62 | if(maxbot_status =='ON') wait_function_ready(); 63 | } else { 64 | console.log('no status found'); 65 | } 66 | }); 67 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/data/settings.json: -------------------------------------------------------------------------------- 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.0, "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": ""}} -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ticketmaster_area.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | 4 | $("footer").remove(); 5 | 6 | function ticketmaster_assign_ticket_number(settings) 7 | { 8 | let ticket_options = $("#ticketPriceList select:first option"); 9 | if (ticket_options.length) 10 | { 11 | let is_ticket_number_assign = false; 12 | if (settings.ticket_number > 0) 13 | { 14 | ticket_options.each(function () 15 | { 16 | if ($(this).val() == settings.ticket_number) 17 | { 18 | $(this).prop('selected', true); 19 | is_ticket_number_assign = true; 20 | return false; 21 | } 22 | }); 23 | } 24 | if (!is_ticket_number_assign) 25 | { 26 | ticket_options.last().prop('selected', true); 27 | } 28 | $("#autoMode").click(); 29 | } 30 | } 31 | 32 | var myInterval = null; 33 | 34 | function ticketmaster_select_box_ready(settings) 35 | { 36 | let ret = false; 37 | let form_select = $("table#ticketPriceList tbody tr td select.form-select"); 38 | if (form_select.length > 0) 39 | { 40 | ret = true; 41 | if (myInterval) 42 | clearInterval(myInterval); 43 | ticketmaster_assign_ticket_number(settings); 44 | } 45 | //console.log("select_box_ready:"+ret); 46 | return ret; 47 | } 48 | 49 | storage.get('settings', function (items) 50 | { 51 | if (items.settings) 52 | { 53 | settings = items.settings; 54 | } 55 | else 56 | { 57 | console.log('no settings found'); 58 | } 59 | } 60 | ); 61 | 62 | storage.get('status', function (items) 63 | { 64 | if (items.status && items.status == 'ON') 65 | { 66 | //console.log("ticket_number:"+ settings.ticket_number); 67 | if (settings.ticket_number > 0) 68 | { 69 | if (!ticketmaster_select_box_ready(settings)) 70 | { 71 | myInterval = setInterval(() => 72 | { 73 | ticketmaster_select_box_ready(settings); 74 | }, 100); 75 | } 76 | } 77 | 78 | } 79 | else 80 | { 81 | console.log('no status found'); 82 | } 83 | } 84 | ); 85 | -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/background.js: -------------------------------------------------------------------------------- 1 | /* 2 | * extension process crashes or your extension is manually stopped at 3 | * chrome://serviceworker-internals 4 | */ 5 | 'use strict'; 6 | 7 | chrome.declarativeNetRequest.onRuleMatchedDebug.addListener((e) => { 8 | const msg = `Navigation blocked to ${e.request.url} on tab ${e.request.tabId}.`; 9 | //console.log(msg); 10 | }); 11 | 12 | function reload_rule_from_setting(settings) 13 | { 14 | if(!settings.hasOwnProperty("domain_filter")) { 15 | settings.domain_filter = []; 16 | } 17 | initializeDynamicRules(settings.domain_filter); 18 | } 19 | 20 | chrome.runtime.onInstalled.addListener(function(){ 21 | fetch("data/settings.json") 22 | .then((resp) => resp.json()) 23 | .then((settings) => 24 | { 25 | reload_rule_from_setting(settings); 26 | 27 | chrome.storage.local.set( 28 | { 29 | settings: settings, 30 | }); 31 | console.log("dump settings.json to extension storage"); 32 | } 33 | ).catch(error => 34 | { 35 | console.log('error is', error) 36 | } 37 | ); 38 | }); 39 | 40 | function initializeDynamicRules(domain_filter) 41 | { 42 | const base_rule = { 43 | "id" : 1, 44 | "priority": 1, 45 | "action" : { "type" : "block" }, 46 | "condition" : { 47 | "urlFilter": "", 48 | "resourceTypes" : ["main_frame", "sub_frame", "script", "image", "font", "xmlhttprequest", "media", "stylesheet"] 49 | }}; 50 | 51 | let formated_rules = []; 52 | 53 | for(let i=0; i { 83 | let request_json = request; 84 | let result_json={"answer": "pong from background"}; 85 | if(request_json.action=="update_role") { 86 | reload_rule_from_setting(request_json.data.settings); 87 | result_json={"answer": "updating"}; 88 | sendResponse(result_json); 89 | } 90 | }); 91 | -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/data/settings.json: -------------------------------------------------------------------------------- 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.0, "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*"]} -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/cityline_msg_front.js: -------------------------------------------------------------------------------- 1 | function begin() 2 | { 3 | let settings = JSON.parse($("#settings").html()); 4 | let status = $("#status").html(); 5 | //console.log("msg"); 6 | //console.log(settings); 7 | //console.log(status); 8 | 9 | $("#settings").remove(); 10 | $("#status").remove(); 11 | 12 | let auto_reload_page_interval = 0.0; 13 | if(settings) { 14 | auto_reload_page_interval = settings.advanced.auto_reload_page_interval; 15 | } 16 | 17 | // too short to cause error. 18 | if(auto_reload_page_interval < 0.1) { 19 | auto_reload_page_interval = 0.1; 20 | } 21 | 22 | if(status=='ON') { 23 | let target_interval = auto_reload_page_interval * 1000; 24 | setInterval(() => { 25 | $(".eventposter").off(); 26 | $(".btn_cta").prop('disabled', false); 27 | if(location.href.indexOf('?loc=') > -1) { 28 | if(location.href.indexOf('%2F') > -1) { 29 | const myArray = url.split("lang=TW"); 30 | if(myArray.length >=3) { 31 | if(myArray[1]=="utsvInternet") { 32 | let new_url = "https://event.cityline.com/utsvInternet/"+myArray[1]+"/home?lang=TW"; 33 | location.href = new_url; 34 | } 35 | } 36 | } 37 | if (typeof setRetryUrl !== "undefined") { 38 | setRetryUrl(window.location.href); 39 | } 40 | if (typeof goEvent !== "undefined") { 41 | let is_need_goEvent = false; 42 | if(location.href.indexOf('home?') > -1) is_need_goEvent = true; 43 | if(location.href.indexOf('?loc=') > -1) is_need_goEvent = true; 44 | if(location.href.indexOf('lang=') > -1) is_need_goEvent = true; 45 | if(is_need_goEvent) { 46 | //goEvent(); 47 | remainTime = 0; 48 | } 49 | } else { 50 | //$("#btn-retry-en-1").prop('disabled', false).trigger("click"); 51 | } 52 | }, target_interval); 53 | } 54 | 55 | } 56 | 57 | function dom_ready() 58 | { 59 | //console.log("checking..."); 60 | if($("#settings").length>0) { 61 | clearInterval(myInterval); 62 | begin(); 63 | } 64 | } 65 | 66 | myInterval = setInterval(() => { 67 | dom_ready(); 68 | }, 100); 69 | 70 | 71 | function getHtmlDocName() { 72 | var pathname = location.pathname; 73 | var pathParts = pathname.split('/'); 74 | if(pathParts.length >= 3) return pathParts[2]; 75 | return null; 76 | } 77 | 78 | if(getHtmlDocName()==null) { 79 | history.back(); 80 | } 81 | if (typeof goEvent !== "undefined") { 82 | let is_need_back = true; 83 | if(location.href.indexOf('home?') > -1) is_need_back = false; 84 | if(location.href.indexOf('?loc=') > -1) is_need_back = false; 85 | if(location.href.indexOf('lang=') > -1) is_need_back = false; 86 | if (is_need_back) { 87 | history.back(); 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "homepage": "https://tixcraft.com", 3 | "browser": "chrome", 4 | "language": "\u7e41\u9ad4\u4e2d\u6587", 5 | "ticket_number": 2, 6 | "ocr_captcha": { 7 | "enable": true, 8 | "beta": true, 9 | "force_submit": true, 10 | "image_source": "canvas" 11 | }, 12 | "webdriver_type": "undetected_chromedriver", 13 | "date_auto_select": { 14 | "enable": true, 15 | "date_keyword": "", 16 | "mode": "random" 17 | }, 18 | "area_auto_select": { 19 | "enable": true, 20 | "mode": "random", 21 | "area_keyword": "" 22 | }, 23 | "keyword_exclude": "\"\u8f2a\u6905\",\"\u8eab\u969c\",\"\u8eab\u5fc3 \u969c\u7919\",\"Restricted View\",\"\u71c8\u67f1\u906e\u853d\",\"\u8996\u7dda\u4e0d\u5b8c\u6574\"", 24 | "kktix": { 25 | "auto_press_next_step_button": true, 26 | "auto_fill_ticket_number": true 27 | }, 28 | "tixcraft": { 29 | "pass_date_is_sold_out": true, 30 | "auto_reload_coming_soon_page": true 31 | }, 32 | "advanced": { 33 | "play_sound": { 34 | "ticket": true, 35 | "order": true, 36 | "filename": "ding-dong.wav" 37 | }, 38 | "tixcraft_sid": "", 39 | "ibonqware": "", 40 | "facebook_account": "", 41 | "kktix_account": "", 42 | "fami_account": "", 43 | "cityline_account": "", 44 | "urbtix_account": "", 45 | "hkticketing_account": "", 46 | "kham_account": "", 47 | "ticket_account": "", 48 | "udn_account": "", 49 | "ticketplus_account": "", 50 | "facebook_password": "", 51 | "kktix_password": "", 52 | "fami_password": "", 53 | "urbtix_password": "", 54 | "cityline_password": "", 55 | "hkticketing_password": "", 56 | "kham_password": "", 57 | "ticket_password": "", 58 | "udn_password": "", 59 | "ticketplus_password": "", 60 | "facebook_password_plaintext": "", 61 | "kktix_password_plaintext": "", 62 | "fami_password_plaintext": "", 63 | "urbtix_password_plaintext": "", 64 | "cityline_password_plaintext": "", 65 | "hkticketing_password_plaintext": "", 66 | "kham_password_plaintext": "", 67 | "ticket_password_plaintext": "", 68 | "udn_password_plaintext": "", 69 | "ticketplus_password_plaintext": "", 70 | "chrome_extension": true, 71 | "disable_adjacent_seat": false, 72 | "hide_some_image": false, 73 | "block_facebook_network": false, 74 | "headless": false, 75 | "verbose": false, 76 | "auto_guess_options": true, 77 | "user_guess_string": "", 78 | "remote_url": "\"http://127.0.0.1:16888/\"", 79 | "auto_reload_page_interval": 0.0, 80 | "reset_browser_interval": 0, 81 | "kktix_status_api": false, 82 | "max_dwell_time": 60, 83 | "proxy_server_port": "", 84 | "window_size": "480,1024", 85 | "idle_keyword": "", 86 | "resume_keyword": "", 87 | "idle_keyword_second": "", 88 | "resume_keyword_second": "" 89 | } 90 | } -------------------------------------------------------------------------------- /LEGAL_NOTICE.md: -------------------------------------------------------------------------------- 1 | ## Legal Notice 2 | 3 | This repository is _not_ associated with or endorsed by providers of the APIs contained in this GitHub repository. This project is intended **for educational purposes only**. This is just a little personal project. Sites may contact me to improve their security or request the removal of their site from this repository. 4 | 5 | Please note the following: 6 | 7 | ## Legal Notice 8 | 9 | ### **Affiliation Disclaimer** 10 | This repository is not associated with or endorsed by the providers of the APIs contained in this repository. The project is intended for educational purposes only. The APIs, services, trademarks, and other intellectual property mentioned in this repository are the property of their respective owners, with no claim of ownership or affiliation by this project. 11 | 12 | ### **Liability Limitation** 13 | Under no circumstances shall the author of this repository be liable for any direct, indirect, incidental, special, consequential, or punitive damages, including but not limited to, loss of profits, data, or use, arising out of or in connection with the repository, regardless of whether such damages were foreseeable and whether the author was advised of the possibility of such damages. 14 | 15 | ### **No Warranties** 16 | The repository is provided on an "as is" and "as available" basis without any warranties of any kind, either express or implied, including but not limited to, implied warranties of merchantability, fitness for a particular purpose, or non-infringement. 17 | 18 | ### **User Responsibility** 19 | Users assume all risk for their use of this repository and are solely responsible for any damage or loss, including but not limited to financial loss, of any kind, to any party, that results from the use or misuse of the repository and its contents. 20 | 21 | ### **Legal Compliance** 22 | Users are responsible for ensuring their use of the repository and its contents complies with all local, state, national, and international laws and regulations. 23 | 24 | ### **Indemnification** 25 | Users agree to indemnify, defend, and hold harmless the author from any claims, liabilities, damages, losses, or expenses, including legal fees, arising out of or in any way connected with their use of this repository, violation of these terms, or infringement of any intellectual property or other rights of any person or entity. 26 | 27 | ### **No Endorsement** 28 | The inclusion of third-party content does not imply endorsement or recommendation of such content by the author. 29 | 30 | ### **Governing Law and Jurisdiction** 31 | Any disputes arising out of or related to the use of this repository shall be governed by the laws of the author's jurisdiction, without regard to its conflict of law principles. 32 | 33 | ### **Severability** 34 | If any provision of this notice is found to be unlawful, void, or unenforceable, then that provision shall be deemed severable from this notice and shall not affect the validity and enforceability of any remaining provisions. 35 | 36 | ### **Acknowledgment of Understanding** 37 | By using this repository, users acknowledge that they have read, understood, and agree to be bound by these terms. 38 | 39 | ### **Updates and Changes** 40 | The author reserves the right to modify, update, or remove any content, information, or features in this repository at any time without prior notice. Users are responsible for regularly reviewing the content and any changes made to this repository. 41 | 42 | ### **Unforeseen Consequences** 43 | The author of this repository is not responsible for any consequences, damages, or losses arising from the use or misuse of this repository or the content provided by the third-party APIs. Users are solely responsible for their actions and any repercussions that may follow. 44 | 45 | ### **Educational Purpose** 46 | Please note that this project and its content are provided strictly for educational purposes. Users acknowledge that they are using the APIs and models at their own risk and agree to comply with any applicable laws and regulations. 47 | -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/options.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | 3 | const submitButton = document.querySelector('#save_btn'); 4 | const addButton = document.querySelector('#add_btn'); 5 | const clearAllButton = document.querySelector('#clear_all_btn'); 6 | const new_domain = document.querySelector('#new_domain'); 7 | 8 | var settings = null; 9 | 10 | loadChanges(); 11 | 12 | submitButton.addEventListener('click', saveChanges); 13 | addButton.addEventListener('click', addDomainClick); 14 | clearAllButton.addEventListener('click', clearAllClick); 15 | 16 | async function saveChanges() 17 | { 18 | if(settings) { 19 | let domain_filter =[]; 20 | $("#block_domain_list a").each(function () 21 | { 22 | domain_filter.push($(this).attr('data-domain')); 23 | }); 24 | //console.log(domain_filter); 25 | settings.domain_filter = domain_filter; 26 | 27 | let bundle = { 28 | action: 'update_role', 29 | data: { 30 | 'settings': settings 31 | } 32 | }; 33 | const return_answer = await chrome.runtime.sendMessage(bundle); 34 | console.log(return_answer); 35 | 36 | await storage.set( 37 | { 38 | settings: settings 39 | } 40 | ); 41 | } 42 | message('Settings saved'); 43 | } 44 | 45 | function loadChanges() 46 | { 47 | storage.get('settings', function (items) 48 | { 49 | //console.log(items); 50 | if (items.settings) 51 | { 52 | settings = items.settings 53 | //message('Loaded saved settings.'); 54 | if(!settings.hasOwnProperty("domain_filter")) { 55 | settings.domain_filter = []; 56 | } 57 | 58 | for (let i = 0; i < settings.domain_filter.length; i++) { 59 | addDomainRow(settings.domain_filter[i]); 60 | } 61 | 62 | bind_remove_onclick_event(); 63 | } else { 64 | console.log('no settings found'); 65 | settings = {}; 66 | settings.domain_filter = []; 67 | } 68 | 69 | } 70 | ); 71 | } 72 | 73 | function format_domain_to_tr(user_input_domain) 74 | { 75 | let domain_item = ""; 76 | domain_item += ''; 77 | domain_item += ''; 78 | domain_item += ''; 79 | domain_item += ''; 80 | domain_item += ''; 81 | //domain_item += ''; 82 | //domain_item += ''; 83 | domain_item += ''; 84 | domain_item += user_input_domain; 85 | domain_item += ''; 86 | domain_item += ''; 87 | return domain_item; 88 | } 89 | 90 | function addDomainRow(user_input_domain) 91 | { 92 | if(user_input_domain.length > 0) { 93 | let domain_item = format_domain_to_tr(user_input_domain); 94 | $(domain_item).appendTo($("#block_domain_list")); 95 | } 96 | } 97 | 98 | function clearAllClick() 99 | { 100 | $("#block_domain_list").html(""); 101 | } 102 | 103 | function bind_remove_onclick_event() 104 | { 105 | $("#block_domain_list a").click(function(event) 106 | { 107 | //console.log($(this).html()); 108 | $(this).parent().parent().remove(); 109 | }); 110 | } 111 | 112 | function addDomainClick() 113 | { 114 | let text = new_domain.value; 115 | if(text.length > 0) { 116 | let eachLine = text.split('\n'); 117 | for(let i = 0, l = eachLine.length; i < l; i++) { 118 | addDomainRow(eachLine[i]); 119 | } 120 | 121 | // reset 122 | new_domain.value = ""; 123 | } else { 124 | new_domain.focus(); 125 | } 126 | 127 | bind_remove_onclick_event(); 128 | } 129 | 130 | let messageClearTimer; 131 | function message(msg) 132 | { 133 | clearTimeout(messageClearTimer); 134 | const message = document.querySelector('#message'); 135 | message.innerText = msg; 136 | messageClearTimer = setTimeout(function () 137 | { 138 | message.innerText = ''; 139 | }, 3000); 140 | } 141 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/tixcraft_game.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | var myInterval = null; 4 | 5 | $("div.masthead-wrap").remove(); 6 | 7 | function date_clean() 8 | { 9 | remove_list=['Currently Unavailable', 10 | 'Sale ended on 20', 11 | 'Sold out', 12 | '暫停販售', 13 | ':00 截止', 14 | '已售完', 15 | '00に発売終了', 16 | '販売一時中止', 17 | '完売した' 18 | ]; 19 | for (let i = 0; i < remove_list.length; i++) { 20 | $("#gameList td:contains('"+ remove_list[i] +"')").each(function () 21 | { 22 | $(this).parent().remove(); 23 | }); 24 | } 25 | } 26 | 27 | function date_keyword(settings) 28 | { 29 | let date_keyword_array = []; 30 | if(settings) { 31 | if(settings.date_auto_select.date_keyword.length > 0) { 32 | if(settings.date_auto_select.date_keyword!='""') { 33 | date_keyword_array = JSON.parse('[' + settings.date_auto_select.date_keyword +']'); 34 | } 35 | } 36 | } 37 | //console.log(date_keyword_array); 38 | let target_date=null; 39 | if(date_keyword_array.length) { 40 | for (let i = 0; i < date_keyword_array.length; i++) { 41 | let query_string = "#gameList td:contains('"+ date_keyword_array[i] +"')"; 42 | if(date_keyword_array[i]=="") { 43 | query_string = "#gameList td" 44 | } 45 | let matched_block=[]; 46 | $(query_string).each(function () 47 | { 48 | matched_block.push($(this)); 49 | }); 50 | target_date = get_target_date_with_order(settings, matched_block); 51 | if (target_date) { 52 | console.log("match keyword:" + date_keyword_array[i]); 53 | break; 54 | } 55 | } 56 | } else { 57 | let query_string = "#gameList td"; 58 | let matched_block=[]; 59 | $(query_string).each(function () 60 | { 61 | matched_block.push($(this)); 62 | }); 63 | target_date = get_target_area_with_order(settings, matched_block); 64 | } 65 | 66 | if (target_date) { 67 | let button_tag = "button"; 68 | const currentUrl = window.location.href; 69 | const domain = currentUrl.split('/')[2]; 70 | if(domain=="ticketmaster.sg") { 71 | button_tag = "a"; 72 | } 73 | 74 | let link = target_date.parent().find(button_tag).attr("data-href"); 75 | if (link) { 76 | //console.log("link: " + link); 77 | clearInterval(myInterval); 78 | window.location.href = link; 79 | } 80 | } else { 81 | //console.log("not target_date found.") 82 | } 83 | } 84 | 85 | function date_main(settings) 86 | { 87 | myInterval = setInterval(() => { 88 | //console.log("date_mode:"+ settings.date_auto_select.mode); 89 | //console.log("date_keyword:"+ settings.date_auto_select.date_keyword); 90 | date_keyword(settings); 91 | }, 200); 92 | } 93 | 94 | function date_auto_reload() 95 | { 96 | let reload=false; 97 | 98 | let button_tag = "button"; 99 | const currentUrl = window.location.href; 100 | const domain = currentUrl.split('/')[2]; 101 | if(domain=="ticketmaster.sg") { 102 | button_tag = "a"; 103 | } 104 | 105 | const query_string = "#gameList "+button_tag; 106 | if ($(query_string).length) { 107 | date_clean(); 108 | if ($(query_string).length) { 109 | if (settings) 110 | { 111 | date_main(settings); 112 | } 113 | } else { 114 | reload=true; 115 | } 116 | } else { 117 | reload=true; 118 | } 119 | 120 | if(reload) { 121 | let auto_reload_page_interval = 0.0; 122 | if(settings) { 123 | auto_reload_page_interval = settings.advanced.auto_reload_page_interval; 124 | } 125 | const rootElement = document.documentElement; 126 | rootElement.remove(); 127 | if(auto_reload_page_interval == 0) { 128 | //console.log('Start to reload now.'); 129 | location.reload(); 130 | } else { 131 | console.log('We are going to reload after few seconeds.'); 132 | setTimeout(function () { 133 | location.reload(); 134 | }, auto_reload_page_interval * 1000); 135 | } 136 | } 137 | } 138 | 139 | storage.get('settings', function (items) 140 | { 141 | if (items.settings) 142 | { 143 | settings = items.settings; 144 | } 145 | }); 146 | 147 | storage.get('status', function (items) 148 | { 149 | if (items.status && items.status=='ON') 150 | { 151 | date_auto_reload(); 152 | } else { 153 | console.log('no status found'); 154 | } 155 | }); 156 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/cityline_performance.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | 4 | function cityline_clean_exclude(settings) 5 | { 6 | let exclude_keyword_array = []; 7 | if(settings) { 8 | if(settings.keyword_exclude.length > 0) { 9 | if(settings.keyword_exclude != '""') { 10 | exclude_keyword_array = JSON.parse('[' + settings.keyword_exclude +']'); 11 | } 12 | } 13 | } 14 | 15 | let query_string = "div.price > div.form-check"; 16 | for (let i = 0; i < exclude_keyword_array.length; i++) { 17 | $(query_string).each(function () 18 | { 19 | let html_text=$(this).text(); 20 | let is_match_keyword=false; 21 | if(html_text.indexOf(exclude_keyword_array[i])>-1) { 22 | is_match_keyword=true; 23 | } 24 | if(is_match_keyword) { 25 | $(this).remove(); 26 | } 27 | } 28 | ); 29 | } 30 | } 31 | 32 | function cityline_area_keyword(settings) 33 | { 34 | let area_keyword_array = []; 35 | if(settings) { 36 | if(settings.area_auto_select.area_keyword.length > 0) { 37 | if(settings.area_auto_select.area_keyword!='""') { 38 | area_keyword_array = JSON.parse('[' + settings.area_auto_select.area_keyword +']'); 39 | } 40 | } 41 | } 42 | 43 | //console.log(area_keyword_array); 44 | let target_area = null; 45 | let matched_block=[]; 46 | let query_string = "div.price > div.form-check"; 47 | if(area_keyword_array.length) { 48 | for (let i = 0; i < area_keyword_array.length; i++) { 49 | $(query_string).each(function () 50 | { 51 | let html_text=$(this).text(); 52 | //console.log("html_text:"+html_text); 53 | if(html_text.indexOf('售罄')>-1) { 54 | // do nothing. 55 | } else { 56 | if(html_text.indexOf(area_keyword_array[i])>-1) { 57 | matched_block.push($(this)); 58 | } 59 | } 60 | target_area = get_target_area_with_order(settings, matched_block); 61 | }); 62 | 63 | if (matched_block.length) { 64 | console.log("match keyword:" + area_keyword_array[i]); 65 | break; 66 | } 67 | } 68 | } else { 69 | $(query_string).each(function () 70 | { 71 | let html_text=$(this).text(); 72 | //console.log("html_text:"+html_text); 73 | if(html_text.indexOf('售罄')>-1) { 74 | // do nothing. 75 | } else { 76 | matched_block.push($(this)); 77 | } 78 | }); 79 | target_area = get_target_area_with_order(settings, matched_block); 80 | } 81 | 82 | if (target_area) { 83 | target_area.find("input").click(); 84 | } else { 85 | console.log("not target_area found.") 86 | } 87 | } 88 | 89 | function cityline_performance() 90 | { 91 | cityline_clean_exclude(settings); 92 | //console.log("cityline_performance"); 93 | if(settings) { 94 | cityline_area_keyword(settings); 95 | 96 | //$("#ticketType0").val(settings.ticket_number); 97 | let target_row=$("#ticketType0"); 98 | let ticket_options = target_row.find("option"); 99 | if (ticket_options.length) 100 | { 101 | let is_ticket_number_assign = false; 102 | if (settings.ticket_number > 0) 103 | { 104 | ticket_options.each(function () 105 | { 106 | if ($(this).val() == settings.ticket_number) 107 | { 108 | $(this).prop('selected', true); 109 | is_ticket_number_assign = true; 110 | return false; 111 | } 112 | }); 113 | } 114 | if (!is_ticket_number_assign) 115 | { 116 | ticket_options.last().prop('selected', true); 117 | } 118 | } 119 | 120 | if(settings.advanced.disable_adjacent_seat) { 121 | $('input[type=checkbox]:checked').each(function() { 122 | $(this).click(); 123 | }); 124 | } 125 | 126 | if($("#ticketType0").val()+"" != "0") { 127 | $('#expressPurchaseBtn').click(); 128 | } 129 | } 130 | $("#commonWarningMessageModal").hide(); 131 | 132 | setTimeout(() => { 133 | cityline_performance() 134 | }, "500"); 135 | } 136 | 137 | storage.get('settings', function (items) 138 | { 139 | if (items.settings) 140 | { 141 | settings = items.settings; 142 | } 143 | }); 144 | 145 | storage.get('status', function (items) 146 | { 147 | if (items.status && items.status=='ON') 148 | { 149 | cityline_performance(); 150 | } else { 151 | console.log('no status found'); 152 | } 153 | }); 154 | 155 | $("#s_footer").remove(); 156 | $("footer").remove(); 157 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ticketplus_order.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var settings = null; 3 | var maxbot_status = null; 4 | 5 | var retry_count =0; 6 | 7 | function get_event_status_entry(real_event_id, real_session_id) { 8 | //console.log("start to get_event_status"); 9 | 10 | if (maxbot_status =='ON') 11 | { 12 | get_event_status_core(real_event_id, real_session_id); 13 | } else { 14 | console.log('no status found'); 15 | } 16 | } 17 | 18 | function ajax_return_done(data, real_event_id, real_session_id) { 19 | //console.log("ajax return done") 20 | let reload=false; 21 | //console.log(data.result); 22 | if(data.result.session[0].status=="pending" || data.result.session[0].status=="soldout" || data.result.session[0].status=="unavailable") { 23 | reload=true; 24 | } 25 | 26 | //console.log("is_match_reload_status:"+is_match_reload_status); 27 | if(reload) { 28 | let auto_reload_page_interval = 0.0; 29 | if(settings) { 30 | auto_reload_page_interval = settings.advanced.auto_reload_page_interval; 31 | } 32 | // PS: ticketplus not able to release memory soon. 33 | if (auto_reload_page_interval < 0.7) { 34 | auto_reload_page_interval = 0.7; 35 | } 36 | 37 | if(auto_reload_page_interval == 0) { 38 | //console.log('Start to reload now.'); 39 | location.reload(); 40 | } else { 41 | console.log('We are going to reload after few seconeds.'); 42 | setTimeout(function () { 43 | //location.reload(); 44 | location.href=location.href; 45 | }, auto_reload_page_interval * 1000); 46 | } 47 | } else { 48 | if(data.result.session[0].status=="onsale") { 49 | //console.log("bingo ^_^, onsale") 50 | //$(function() { 51 | // console.log("hello ^_^, onsale"); 52 | //let $captcha = $("input[required='required']"); 53 | //console.log($captcha.length); 54 | //}); 55 | } 56 | } 57 | 58 | } 59 | 60 | function get_event_status_core(real_event_id, real_session_id) { 61 | let timestamp = new Date().getTime(); 62 | timestamp = (timestamp/1000).toFixed()*1000; 63 | //console.log(timestamp); 64 | 65 | let api_url = "https://apis.ticketplus.com.tw/config/api/v1/get?eventId="+ real_event_id +"&sessionId="+real_session_id+"&_="+timestamp; 66 | //console.log("calling api:" + api_url); 67 | $.get( api_url, function() { 68 | //alert( "success" ); 69 | }) 70 | .done(function(data) { 71 | //alert( "second success" ); 72 | if(data) { 73 | ajax_return_done(data, real_event_id, real_session_id); 74 | } 75 | }) 76 | .fail(function() { 77 | //alert( "error" ); 78 | }) 79 | .always(function() { 80 | //alert( "finished" ); 81 | }); 82 | } 83 | 84 | async function decrypt_text(event_id, session_id) { 85 | //console.log("start to decrypt_text"); 86 | let KEY = 'ILOVEFETIXFETIX!'; 87 | const IV = '!@#$FETIXEVENTiv'; 88 | 89 | let bundle = { 90 | action: 'decrypt', 91 | data: { 92 | 'key': KEY, 93 | 'iv': IV, 94 | 'text': event_id 95 | } 96 | }; 97 | let bundle_string = JSON.stringify(bundle); 98 | const event_answer = await chrome.runtime.sendMessage(bundle); 99 | //console.log(event_answer); 100 | if(event_answer) { 101 | const real_event_id = event_answer.answer; 102 | //console.log(real_event_id); 103 | bundle = { 104 | action: 'decrypt', 105 | data: { 106 | 'key': KEY, 107 | 'iv': IV, 108 | 'text': session_id 109 | } 110 | }; 111 | let session_answer = await chrome.runtime.sendMessage(bundle); 112 | let real_session_id = session_answer.answer; 113 | //console.log(real_session_id); 114 | get_event_status_entry(real_event_id, real_session_id); 115 | } else { 116 | console.log("decrypt fail"); 117 | } 118 | } 119 | 120 | async function wait_function_ready() { 121 | const currentUrl = window.location.href; 122 | const event_id = currentUrl.split('/')[4]; 123 | const session_id = currentUrl.split('/')[5]; 124 | //console.log(event_id); 125 | //console.log(session_id); 126 | if(event_id && session_id){ 127 | decrypt_text(event_id, session_id) 128 | } 129 | } 130 | 131 | chrome.storage.local.get('settings', function (items) 132 | { 133 | if (items.settings) 134 | { 135 | settings = items.settings; 136 | } else { 137 | console.log('no status found'); 138 | } 139 | }); 140 | 141 | chrome.storage.local.get('status', function (items) 142 | { 143 | if (items.status) 144 | { 145 | maxbot_status = items.status; 146 | //console.log("maxbot_status:" + maxbot_status) 147 | if(maxbot_status =='ON') wait_function_ready(); 148 | } else { 149 | console.log('no status found'); 150 | } 151 | }); 152 | -------------------------------------------------------------------------------- /demo_video.md: -------------------------------------------------------------------------------- 1 | # Demo (示範影片) 2 | 3 | ### 2024-04-02 4 | (2024-04-12) cityline 撞牆心得 5 | 6 | https://youtu.be/cLFWyI1BLyw 7 | 8 | ### 2024-04-01 9 | Cityline 自動輸入張數,票價,日期 10 | 11 | https://youtu.be/o32TJ6jcS1M 12 | 13 | ### 2024-03-17 14 | (2024-03-31) 為什麼我太太搶到8張(他就一個帳號+一台破電腦)? 15 | 16 | https://youtu.be/d3JxIk4hLsw 17 | 18 | ### 2024-03-09: 19 | 增加瀏覽器視窗大小的設定值, 方便視窗多開 20 | 21 | https://youtu.be/zPgP43w-ceg 22 | 23 | ### 2024-03-08 24 | KKIX 加購粉絲福利 25 | 26 | https://youtu.be/Hc2wW_sWiAo 27 | 28 | ### 2024-03-22 29 | MaxBot 售票系統架構猜測與搶票建議 30 | 31 | https://youtu.be/alpy9HX6aRw 32 | 33 | ### 2024-01-17: 34 | 調整ibon驗證問題的輸入 35 | 36 | https://youtu.be/z3mM_Ljui2U 37 | 38 | ### 2024-01-15: 39 | MaxBot Plus 1.0.6 擴充功能 for ticktmaster.sg 40 | 41 | https://youtu.be/V8S_E7ayAGU 42 | 43 | ### 2024-01-15: 44 | 增加關鍵字對狀態做開關的切換 45 | 46 | https://youtu.be/u3YQCZZu6kE 47 | 48 | ### 2024-01-10: 49 | MaxBot Plus 擴充功能 刷hkticketing 50 | 51 | https://youtu.be/zOzFYJsqWME 52 | 53 | ### 2024-01-01: 54 | MaxBot Plus 擴充功能 刷cityline 55 | 56 | https://youtu.be/rRl_EETv_b0 57 | 58 | ### 2023-12-10: 59 | KKTIX 搶車票 60 | 61 | https://youtu.be/csUJ6kRSynY 62 | 63 | ### 2023-11-04: 64 | 支援新的排序方式:中間選項(center) 65 | 66 | ticketmaster 支援區域自動點擊 67 | 68 | https://youtu.be/9fqiQHJmIeM 69 | 70 | ### 2023-10-20: 71 | FamiTicket 支援新購票頁面 72 | 73 | https://youtu.be/EWfdK29P-aw 74 | 75 | ### 2023-10-10: 76 | 支援設定代理伺服器(Proxy), 還沒支援 account:password 模式. 77 | 78 | https://youtu.be/sao9k_PnC0w 79 | 80 | ### 2023-07-09: 81 | 日期關鍵字支援多組與順位 82 | 83 | https://youtu.be/IgX4viS1Eq0 84 | 85 | ### 2023-07-04: 86 | ticketmaster 支援無區域地圖的購票表單 87 | 88 | https://youtu.be/Jj2vca2kNZE 89 | 90 | ### 2023-06-25: 91 | hkticketing 本地端字典檔自動輸入信用卡前6碼 92 | 93 | https://youtu.be/BlIRYkd296Y 94 | 95 | ### 2023-05-27: 96 | ibon 在自動選擇區域時, 支援檢查剩餘張數要大於等於要搶的張數. 97 | 98 | https://youtu.be/gsAXIRI7uj0 99 | 100 | ### 2023-05-23: 101 | ibon 允許不連續座位 102 | 103 | https://youtu.be/A9EU7vgWBiQ 104 | 105 | ### 2023-05-22: 106 | 遠大售票系統 107 | 108 | https://youtu.be/mlc7_5O_nwg 109 | 110 | ### 2023-05-22: 111 | 年代售票系統 / 新的關鍵字格式 112 | 113 | https://youtu.be/gJo8rGQsyzY 114 | 115 | ### 2023-05-22: 116 | HKTicketing 快達票 117 | 118 | https://youtu.be/U-Rx5RIMFOg 119 | 120 | ### 2023-04-24: 121 | 優化KKTIX 推論驗證問題/示範多開. 122 | 123 | https://youtu.be/Wn1qLz-Re8c 124 | 125 | ### 2023-03-27: 126 | kktix無票時刷新頁面,暫停搶票程式 127 | 128 | https://www.youtube.com/watch?v=4trNmMDntwM 129 | 130 | ### 2023-03-02: 131 | 澳門銀河購票無延遲 132 | 133 | https://youtu.be/mFxzzWU4ksU 134 | 135 | ### 2023-02-25: 136 | ibon只搶限定的票價 137 | 138 | https://youtu.be/ZtnAh-VY5qs 139 | 140 | ### 2023-02-25: 141 | 透過cookie的ibonqware登入ibon 142 | 143 | https://youtu.be/QnaCRQjAlng 144 | 145 | ### 2023-02-24: 146 | KKTix,多設定檔管理 147 | 148 | https://youtu.be/QgLAHkJbhqQ 149 | 150 | ### 2023-02-22: 151 | 拓元,透過 cookie SID登入 152 | 153 | https://youtu.be/fkx0HGqTpTg 154 | 155 | ### 2023-02-19: 156 | 拓元,從驗證問題猜測答案 157 | 158 | https://youtu.be/5rOi56dNEs8 159 | 160 | ### 2023-02-16: 161 | 拓元,從字典檔輸入驗證答案 162 | 163 | https://youtu.be/TuacFXzuvlM 164 | 165 | ### 2023-02-10: 166 | 自動登入/區域關鍵字增加開關 167 | 168 | https://youtu.be/Ft2WIWglZ5E 169 | 170 | ### 2023-02-08: 171 | Edge瀏覽器WebDriver下載與設定 172 | 173 | https://youtu.be/TzbBAEVVtoM 174 | 175 | ### 2023-02-08: 176 | 重新支援hkticketing 177 | 178 | https://youtu.be/pk-7gIztB2Y 179 | 180 | ### 2023-02-03: 181 | 優化KKTIX 推論驗證問題 182 | 183 | https://youtu.be/I4OOTlgpsOA 184 | 185 | ### 2023-01-29: 186 | 支援galaxymacau(澳門銀河) 187 | 188 | https://youtu.be/yt7SkRvBujU 189 | 190 | ### 2023-01-22: 191 | hkticketing(快達票) 192 | 193 | https://youtu.be/pZJlcMjayco 194 | 195 | ### 2023-01-14: 196 | 優化KKTIX "演出日期"的驗證問題 197 | 198 | https://youtu.be/ChmGZMaV2w8 199 | 200 | ### 2023-01-14: 201 | indievox 猜測驗證碼 / 視窗多開 202 | 203 | https://youtu.be/O84H1wNO2_w 204 | 205 | ### 2023-01-11: 206 | tixcraft 自動輸入驗證碼 207 | 208 | https://youtu.be/t1k0CvmBNhQ (macOS) 209 | 210 | https://youtu.be/6JdEdcW8LtY (Windows) 211 | 212 | ### 2023-01-07: 213 | 輸入驗證問題答案為"同意" 214 | 215 | https://youtu.be/UgemzrsCC-M 216 | 217 | ### 2023-01-05: 218 | 不等 cityline 的 10秒,直接重導網址 219 | 220 | https://youtu.be/wGU4GJJ-ufw 221 | 222 | ### 2023-01-02: 223 | KKITX自動猜測驗證問題 224 | 225 | https://youtu.be/7CtSVBGwx9I (macOS) 226 | 227 | https://youtu.be/BcyfkXF2AJU (Windows) 228 | 229 | ### 2023-01-02: 230 | 支援 ibon 售票系統 231 | 232 | https://youtu.be/VaYc5GKk1Rk 233 | 234 | ### 2023-01-01: 235 | 支援新版本的 cityline 236 | 237 | https://youtu.be/R5LY7pJgAzI (macOS) 238 | 239 | https://youtu.be/2UNaAEjysvk (Windows) 240 | 241 | ### 2023-01-01: 242 | 支援新版本的 urbtix 243 | 244 | https://youtu.be/_6jxqVC39x8 (macOS) 245 | 246 | https://youtu.be/PWKBZ8aG9Rg (Windows) 247 | 248 | ### 2022-11-24: 249 | KKTix 支援避開「剩餘 1」的區域的功能。增加關鍵字#2 的欄位。 250 | 251 | https://youtu.be/nupJlwRNOIA 252 | 253 | ### 2022-11-18: 254 | 增加 adblock plus 的功能。輸入驗證碼時,會播放音效,在清票時很有幫功,不需要一直緊盯著螢幕。 255 | 256 | https://youtu.be/Atujl8MPHQI 257 | 258 | ### 2022-11-06: 259 | 優化kktix/拓元的關鍵字比對,修改為不區分逗號、空格與大小寫。 260 | 261 | https://youtu.be/v9mI02kVaNw 262 | 263 | ### 2022-10-22: 264 | 優化kktix/拓元的價格的關鍵字比對。 265 | 266 | https://youtu.be/NZzQcDQkrNI 267 | 268 | ### 2022-10-21: 269 | 針對kktix 活動增加第二個關鍵字欄位。 270 | 271 | https://youtu.be/x-OdqvUupiA 272 | 273 | ### 2022-01-26: 274 | FamiTicket 275 | 276 | https://youtu.be/ZV-G91FHVik 277 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/tixcraft_area.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | 4 | $("ul.area-list > li:not(:has(a))").remove(); 5 | $("#selectseat div div img").remove(); 6 | $("footer").remove(); 7 | 8 | function tixcraft_clean_exclude(settings) 9 | { 10 | let exclude_keyword_array = []; 11 | if(settings) { 12 | if(settings.keyword_exclude.length > 0) { 13 | if(settings.keyword_exclude != '""') { 14 | exclude_keyword_array = JSON.parse('[' + settings.keyword_exclude +']'); 15 | } 16 | } 17 | } 18 | 19 | for (let i = 0; i < exclude_keyword_array.length; i++) { 20 | $("ul.area-list > li > a:contains('"+ exclude_keyword_array[i] +"')").each(function () 21 | { 22 | $(this).parent().remove(); 23 | } 24 | ); 25 | } 26 | } 27 | 28 | function tixcraft_area_keyword(settings) 29 | { 30 | let area_keyword_array = []; 31 | if(settings) { 32 | if(settings.area_auto_select.area_keyword.length > 0) { 33 | if(settings.area_auto_select.area_keyword!='""') { 34 | area_keyword_array = JSON.parse('[' + settings.area_auto_select.area_keyword +']'); 35 | } 36 | } 37 | } 38 | // console.log(area_keyword_array); 39 | let target_area=null; 40 | if(area_keyword_array.length) { 41 | for (let i = 0; i < area_keyword_array.length; i++) { 42 | let query_string = "ul.area-list > li > a:contains('"+ area_keyword_array[i] +"')"; 43 | if(area_keyword_array[i]=="") { 44 | query_string = "ul.area-list > li > a" 45 | } 46 | let matched_block=[]; 47 | $(query_string).each(function () 48 | { 49 | matched_block.push($(this)); 50 | }); 51 | target_area = get_target_area_with_order(settings, matched_block); 52 | if (target_area.length) { 53 | console.log("match keyword:" + area_keyword_array[i]); 54 | break; 55 | } 56 | } 57 | } else { 58 | let query_string = "ul.area-list > li > a"; 59 | let matched_block=[]; 60 | $(query_string).each(function () 61 | { 62 | matched_block.push($(this)); 63 | }); 64 | target_area = get_target_area_with_order(settings, matched_block); 65 | } 66 | 67 | if (target_area) { 68 | let link_id = target_area.attr("id"); 69 | //console.log("link_id: " + link_id); 70 | if(link_id) { 71 | let body = document.body.innerHTML; 72 | let areaUrlList = null; 73 | if(body.indexOf('var areaUrlList =')>-1) { 74 | const javasrit_right = body.split('var areaUrlList =')[1]; 75 | let areaUrlHtml = ""; 76 | if(javasrit_right) { 77 | areaUrlHtml = javasrit_right.split("};")[0]; 78 | } 79 | if(areaUrlHtml.length > 0) { 80 | areaUrlHtml = areaUrlHtml + "}"; 81 | areaUrlList = JSON.parse(areaUrlHtml); 82 | } 83 | //console.log(areaUrlHtml); 84 | } 85 | 86 | let new_url = null; 87 | if(areaUrlList) { 88 | let new_url = areaUrlList[link_id]; 89 | if (new_url) { 90 | //console.log(new_url); 91 | window.location.href = new_url 92 | } 93 | } 94 | } 95 | } else { 96 | console.log("not target_area found.") 97 | } 98 | } 99 | 100 | function tixcraft_area_main(settings) { 101 | if(settings) { 102 | //console.log("area_mode:"+ settings.area_auto_select.mode); 103 | //console.log("area_keyword:"+ settings.area_auto_select.area_keyword); 104 | //console.log("keyword_exclude:"+ settings.keyword_exclude); 105 | tixcraft_clean_exclude(settings); 106 | tixcraft_area_keyword(settings); 107 | } 108 | } 109 | 110 | function area_auto_reload() 111 | { 112 | let reload=false; 113 | if ($("ul.area-list > li:has(a)").length) { 114 | if (settings) 115 | { 116 | tixcraft_area_main(settings); 117 | } 118 | } else { 119 | reload=true; 120 | } 121 | 122 | if(reload) { 123 | let auto_reload_page_interval = 0.0; 124 | if(settings) { 125 | auto_reload_page_interval = settings.advanced.auto_reload_page_interval; 126 | } 127 | const rootElement = document.documentElement; 128 | rootElement.remove(); 129 | if(auto_reload_page_interval == 0) { 130 | //console.log('Start to reload now.'); 131 | location.reload(); 132 | } else { 133 | console.log('We are going to reload after few seconeds.'); 134 | setTimeout(function () { 135 | location.reload(); 136 | }, auto_reload_page_interval * 1000); 137 | } 138 | } 139 | } 140 | 141 | storage.get('settings', function (items) 142 | { 143 | if (items.settings) 144 | { 145 | settings = items.settings; 146 | } 147 | }); 148 | 149 | storage.get('status', function (items) 150 | { 151 | if (items.status && items.status=='ON') 152 | { 153 | area_auto_reload(); 154 | } else { 155 | console.log('no status found'); 156 | } 157 | }); 158 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ibon_area.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | 4 | //console.log("start ibon area"); 5 | 6 | // price row. 7 | $("table.table > tbody > tr.disabled").remove(); 8 | $("table.table > tbody > tr.sold-out").remove(); 9 | $("div.map > div > img").remove(); 10 | $("footer").remove(); 11 | 12 | var $tr=$("table.table > tbody > tr[onclick]"); 13 | //console.log("$tr.length:"+$tr.length); 14 | if($tr.length==1) { 15 | //console.log("$tr.html:"+$tr.html()); 16 | $tr.click(); 17 | } 18 | 19 | function ibon_area_ready(settings) { 20 | let area_keyword_array = []; 21 | if(settings) { 22 | if(settings.area_auto_select.area_keyword.length > 0) { 23 | if(settings.area_auto_select.area_keyword!='""') { 24 | area_keyword_array = JSON.parse('[' + settings.area_auto_select.area_keyword +']'); 25 | } 26 | } 27 | } 28 | //let target_area = []; 29 | 30 | let target_row=null; 31 | let all_row = $("table.table > tbody > tr[onclick]"); 32 | if (all_row.length > 0) 33 | { 34 | if (all_row.length == 1) { 35 | // single select. 36 | target_row=all_row; 37 | } else { 38 | // multi select. 39 | try { 40 | all_row.each(function () 41 | { 42 | //console.log(all_row.index(this)); 43 | let is_match_keyword = false; 44 | 45 | if(area_keyword_array.length) { 46 | let html_text=$(this).text(); 47 | //console.log("html:"+html_text); 48 | 49 | // TOOD: multi item matched, need sort. 50 | for (let i = 0; i < area_keyword_array.length; i++) { 51 | // target_area = get_target_area_with_order(settings, matched_block); 52 | //console.log("area_keyword:"+area_keyword_array[i]); 53 | 54 | if(area_keyword_array[i].indexOf(" ")>-1) { 55 | // TODO: muti keywords with AND logic. 56 | } else { 57 | // single keyword. 58 | if(html_text.indexOf(area_keyword_array[i])>-1) { 59 | is_match_keyword = true; 60 | target_row=$(this); 61 | break; 62 | } 63 | } 64 | } 65 | } else { 66 | if(all_row.index(this)==0) { 67 | is_match_keyword = true; 68 | target_row=$(this); 69 | } 70 | } 71 | 72 | //console.log("is_match_keyword:"+is_match_keyword); 73 | if(is_match_keyword) { 74 | throw {}; 75 | } 76 | }); 77 | } catch { } 78 | } 79 | if(target_row) { 80 | //console.log("found target, clicking"); 81 | // click fail on sandbox world. 82 | //target_row.click(); 83 | let done_div=""; 84 | $("body").append(done_div); 85 | } 86 | } else { 87 | location.reload(); 88 | } 89 | } 90 | 91 | function ibon_area_clean_exclude(settings) 92 | { 93 | let exclude_keyword_array = []; 94 | if(settings) { 95 | if(settings.keyword_exclude.length > 0) { 96 | if(settings.keyword_exclude != '""') { 97 | exclude_keyword_array = JSON.parse('[' + settings.keyword_exclude +']'); 98 | } 99 | } 100 | } 101 | for (let i = 0; i < exclude_keyword_array.length; i++) { 102 | $("table.table > tbody > tr").each(function () 103 | { 104 | let html_text=$(this).text(); 105 | //console.log("html:"+html_text); 106 | if(html_text.indexOf(exclude_keyword_array[i])>-1) { 107 | $(this).remove(); 108 | } 109 | }); 110 | } 111 | } 112 | 113 | 114 | function ibon_area_main() { 115 | let reload=false; 116 | let $tr=$("table.table > tbody > tr[onclick]"); 117 | if($tr.length==0) { 118 | reload=true; 119 | } 120 | if(reload) { 121 | let auto_reload_page_interval = 0.0; 122 | if(settings) { 123 | auto_reload_page_interval = settings.advanced.auto_reload_page_interval; 124 | } 125 | if(auto_reload_page_interval == 0) { 126 | //console.log('Start to reload now.'); 127 | location.reload(); 128 | } else { 129 | console.log('We are going to reload after few seconeds.'); 130 | setTimeout(function () { 131 | location.reload(); 132 | }, auto_reload_page_interval * 1000); 133 | } 134 | } else { 135 | ibon_area_clean_exclude(settings); 136 | ibon_area_ready(settings); 137 | } 138 | } 139 | 140 | 141 | storage.get('settings', function (items) 142 | { 143 | if (items.settings) 144 | { 145 | settings = items.settings; 146 | } 147 | }); 148 | 149 | storage.get('status', function (items) 150 | { 151 | if (items.status && items.status=='ON') 152 | { 153 | ibon_area_main(); 154 | } else { 155 | console.log('no status found'); 156 | } 157 | }); 158 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ibon_detail.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | 4 | function ibon_detail_ajax_done(game_info) 5 | { 6 | let date_keyword_array = []; 7 | if(settings) { 8 | if(settings.date_auto_select.date_keyword.length > 0) { 9 | date_keyword_array = JSON.parse('[' + settings.date_auto_select.date_keyword +']'); 10 | } 11 | } 12 | 13 | let reload=false; 14 | let target_href = ""; 15 | 16 | //console.log(game_info.Item); 17 | if(game_info.Item.GIHtmls.length) { 18 | // one of game able to buy. 19 | let one_can_buy = false; 20 | 21 | for (let i = 0; i < game_info.Item.GIHtmls.length; i++) { 22 | let rs = game_info.Item.GIHtmls[i]; 23 | if(game_info.Item.GIHtmls.length==1) { 24 | // single row. 25 | if(rs.Href==null) { 26 | reload=true; 27 | } else { 28 | if(rs.CanBuy==false) { 29 | reload=true; 30 | } else { 31 | one_can_buy = true; 32 | target_href = rs.Href; 33 | } 34 | } 35 | if(reload) { 36 | break; 37 | } 38 | } else { 39 | // multi rows. 40 | if(settings) { 41 | let is_match_row = false; 42 | if(date_keyword_array.length) { 43 | for (let j = 0; j < date_keyword_array.length; j++) { 44 | // TOOD: multi item matched, need sort. 45 | // target_area = get_target_area_with_order(settings, matched_block); 46 | 47 | if(rs.ShowSaleDate.indexOf(date_keyword_array[j])>-1) { 48 | is_match_row = true; 49 | } 50 | if(rs.GameInfoName.indexOf(date_keyword_array[j])>-1) { 51 | is_match_row = true; 52 | } 53 | if(is_match_row) { 54 | break; 55 | } 56 | } 57 | } else { 58 | // empty keyword. 59 | is_match_row = true; 60 | } 61 | if(is_match_row) { 62 | if(rs.Href!=null) { 63 | if(rs.CanBuy!=false) { 64 | one_can_buy = true; 65 | target_href = rs.Href; 66 | break; 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | 74 | if(!reload) { 75 | if(one_can_buy == false) reload=true; 76 | } 77 | 78 | } 79 | 80 | //console.log("reload:"+reload); 81 | //console.log("target_href:"+target_href); 82 | if(reload) { 83 | let auto_reload_page_interval = 0.0; 84 | if(settings) { 85 | auto_reload_page_interval = settings.advanced.auto_reload_page_interval; 86 | } 87 | if(auto_reload_page_interval == 0) { 88 | //console.log('Start to reload now.'); 89 | location.reload(); 90 | } else { 91 | console.log('We are going to reload after few seconeds.'); 92 | setTimeout(function () { 93 | location.reload(); 94 | }, auto_reload_page_interval * 1000); 95 | } 96 | } 97 | else { 98 | // goto target event. 99 | //console.log(target_href); 100 | if(target_href.length > 0) { 101 | location.href= "https://ticket.ibon.com.tw/" + target_href; 102 | } 103 | } 104 | } 105 | 106 | function ibon_event_status_check() 107 | { 108 | const currentUrl = window.location.href; 109 | const event_code = currentUrl.split('/')[5]; 110 | //console.log(currentUrl); 111 | //console.log(event_code); 112 | if(event_code){ 113 | let api_url = "https://ticketapi.ibon.com.tw/api/ActivityInfo/GetGameInfoList"; 114 | dataJSON = { 115 | id: parseInt(event_code, 10), 116 | hasDeadline: true, 117 | SystemBrowseType: 0 118 | } 119 | $.ajax({ 120 | url: api_url, 121 | data: JSON.stringify(dataJSON), 122 | type: "POST", 123 | dataType: "json", 124 | xhrFields: { 125 | withCredentials: true 126 | }, 127 | headers: { 128 | "x-xsrf-token": getCookie("XSRF-TOKEN") 129 | }, 130 | contentType: "application/json", 131 | success: function(returnData){ 132 | ibon_detail_ajax_done(returnData); 133 | //console.log(returnData); 134 | }, 135 | error: function(xhr, ajaxOptions, thrownError){ 136 | //console.log(xhr.status); 137 | //console.log(thrownError); 138 | } 139 | }); 140 | } 141 | } 142 | 143 | storage.get('settings', function (items) 144 | { 145 | if (items.settings) 146 | { 147 | settings = items.settings; 148 | } 149 | }); 150 | 151 | storage.get('status', function (items) 152 | { 153 | if (items.status && items.status=='ON') 154 | { 155 | console.log("start to ibon detail."); 156 | //console.log(document.cookie); 157 | //console.log(getCookie("XSRF-TOKEN")); 158 | ibon_event_status_check(); 159 | } else { 160 | console.log('no status found'); 161 | } 162 | }); 163 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ibon_ticket.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | 4 | $("footer").remove(); 5 | 6 | function ibon_assign_ticket_number(ticket_number) 7 | { 8 | let $main_table = $("table.table"); 9 | if ($main_table.length > 0) 10 | { 11 | console.log("found main table"); 12 | let $ticket_options = $main_table.find("select:first option"); 13 | if ($ticket_options.length) 14 | { 15 | let is_ticket_number_assign = false; 16 | if (ticket_number > 0) 17 | { 18 | console.log("target ticket_number:"+ticket_number); 19 | $ticket_options.each(function () 20 | { 21 | if ($(this).val() == ticket_number) 22 | { 23 | $(this).prop('selected', true); 24 | is_ticket_number_assign = true; 25 | return false; 26 | } 27 | } 28 | ); 29 | } 30 | console.log("is_ticket_number_assign:"+is_ticket_number_assign); 31 | if (!is_ticket_number_assign) 32 | { 33 | $ticket_options.last().prop('selected', true); 34 | } 35 | } 36 | } 37 | } 38 | 39 | function ibon_assign_adjacent_seat(flag) { 40 | //console.log("disable_adjacent_seat flag:"+flag); 41 | if(flag) { 42 | $('input[type=checkbox]').each(function() { 43 | $(this).prop('checked', true); 44 | }); 45 | } 46 | } 47 | 48 | function ibon_focus_on_captcha() 49 | { 50 | $("div.editor-box > div > input[type='text']").focus(); 51 | } 52 | 53 | var myInterval = null; 54 | 55 | function ibon_get_ocr_image() 56 | { 57 | //console.log("get_ocr_image"); 58 | let image_data = ""; 59 | 60 | // PS: tixcraft have different domain to use the same content script. 61 | const currentUrl = window.location.href; 62 | const domain = currentUrl.split('/')[2]; 63 | 64 | let image_id = 'chk_pic'; 65 | let img = document.getElementById(image_id); 66 | if(img!=null) { 67 | let canvas = document.createElement('canvas'); 68 | let context = canvas.getContext('2d'); 69 | canvas.height = img.naturalHeight; 70 | canvas.width = img.naturalWidth; 71 | context.drawImage(img, 0, 0); 72 | let img_data = canvas.toDataURL(); 73 | if(img_data) { 74 | image_data = img_data.split(",")[1]; 75 | //console.log(image_data); 76 | } 77 | } 78 | return image_data; 79 | } 80 | 81 | chrome.runtime.onMessage.addListener((message) => { 82 | //console.log('sent from background', message); 83 | ibon_set_ocr_answer(message.answer); 84 | }); 85 | 86 | function ibon_set_ocr_answer(answer) 87 | { 88 | console.log("answer:"+answer); 89 | if(answer.length > 0) { 90 | $("div.editor-box > div > input[type='text']").val(answer); 91 | //console.log($("div#ticket-wrap a[onclick]").length); 92 | //$("div#ticket-wrap a[onclick]").click(); 93 | //$("#aspnetForm").submit(); 94 | let done_div=""; 95 | $("body").append(done_div); 96 | 97 | } 98 | } 99 | 100 | async function ibon_get_ocr_answer(api_url, image_data) 101 | { 102 | let bundle = { 103 | action: 'ocr', 104 | data: { 105 | 'url': api_url + 'ocr', 106 | 'image_data':image_data, 107 | } 108 | }; 109 | 110 | let bundle_string = JSON.stringify(bundle); 111 | const return_answer = await chrome.runtime.sendMessage(bundle); 112 | //console.log(return_answer); 113 | } 114 | 115 | function ibon_orc_image_ready(api_url) 116 | { 117 | let ret=false; 118 | let image_data = ibon_get_ocr_image(); 119 | if(image_data.length>0) { 120 | ret=true; 121 | if(myInterval) clearInterval(myInterval); 122 | ibon_get_ocr_answer(api_url, image_data); 123 | } 124 | //console.log("ibon_orc_image_ready:"+ret); 125 | return ret; 126 | } 127 | 128 | storage.get('settings', function (items) 129 | { 130 | if (items.settings) 131 | { 132 | settings = items.settings; 133 | } else { 134 | console.log('no settings found'); 135 | } 136 | }); 137 | 138 | 139 | storage.get('settings', function (items) 140 | { 141 | if (items.settings) 142 | { 143 | settings = items.settings; 144 | } 145 | }); 146 | 147 | function get_remote_url(settings) 148 | { 149 | let remote_url_string = ""; 150 | if(settings) { 151 | let remote_url_array = []; 152 | if(settings.advanced.remote_url.length > 0) { 153 | remote_url_array = JSON.parse('[' + settings.advanced.remote_url +']'); 154 | } 155 | if(remote_url_array.length) { 156 | remote_url_string = remote_url_array[0]; 157 | } 158 | } 159 | return remote_url_string; 160 | } 161 | 162 | storage.get('status', function (items) 163 | { 164 | if (items.status && items.status=='ON') 165 | { 166 | //console.log("ticket_number:"+ settings.ticket_number); 167 | ibon_assign_ticket_number(settings.ticket_number); 168 | ibon_assign_adjacent_seat(settings.advanced.disable_adjacent_seat); 169 | 170 | // ocr 171 | if(settings.ocr_captcha.enable) { 172 | let remote_url_string = get_remote_url(settings); 173 | if(!ibon_orc_image_ready(remote_url_string)) { 174 | myInterval = setInterval(() => { 175 | ibon_orc_image_ready(remote_url_string); 176 | }, 100); 177 | } 178 | } else { 179 | // no orc, just focus; 180 | ibon_focus_on_captcha(); 181 | } 182 | } else { 183 | console.log('no status found'); 184 | } 185 | }); 186 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/ticket_ticket.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | 4 | $("footer").remove(); 5 | 6 | function ticket_assign_adjacent_seat(flag) { 7 | //console.log("disable_adjacent_seat flag:"+flag); 8 | if(flag) { 9 | $('input[type=checkbox]').each(function() { 10 | $(this).prop('checked', true); 11 | }); 12 | } 13 | } 14 | 15 | function ticket_focus_on_captcha() 16 | { 17 | $("div.login-form input[autocomplete='off']").focus(); 18 | } 19 | 20 | var myInterval = null; 21 | 22 | function ticket_get_ocr_image() 23 | { 24 | //console.log("get_ocr_image"); 25 | let image_data = ""; 26 | 27 | // PS: tixcraft have different domain to use the same content script. 28 | const currentUrl = window.location.href; 29 | const domain = currentUrl.split('/')[2]; 30 | 31 | let image_id = 'chk_pic'; 32 | let img = document.getElementById(image_id); 33 | if(img!=null) { 34 | let canvas = document.createElement('canvas'); 35 | let context = canvas.getContext('2d'); 36 | canvas.height = img.naturalHeight; 37 | canvas.width = img.naturalWidth; 38 | context.drawImage(img, 0, 0); 39 | let img_data = canvas.toDataURL(); 40 | if(img_data) { 41 | image_data = img_data.split(",")[1]; 42 | //console.log(image_data); 43 | } 44 | } 45 | return image_data; 46 | } 47 | 48 | chrome.runtime.onMessage.addListener((message) => { 49 | //console.log('sent from background', message); 50 | ticket_set_ocr_answer(message.answer); 51 | }); 52 | 53 | function ticket_set_ocr_answer(answer) 54 | { 55 | //console.log("answer:"+answer); 56 | if(answer.length > 0) { 57 | const currentUrl = window.location.href; 58 | const domain = currentUrl.split('/')[2]; 59 | const scrip_page = currentUrl.split('/')[5]; 60 | 61 | if(answer.length == 4) { 62 | answer = answer.toUpperCase(); 63 | let query_string = "div.form-group input[autocomplete='off']"; 64 | if(domain.indexOf('kham') > -1) { 65 | query_string = ".step2Login input[maxlength='4']"; 66 | } 67 | $(query_string).val(answer); 68 | //console.log($(query_string).length); 69 | //$("div#ticket-wrap a[onclick]").click(); 70 | //$("#aspnetForm").submit(); 71 | let done_div=""; 72 | $("body").append(done_div); 73 | } else { 74 | let query_string = "div.form-group a img"; 75 | if(domain.indexOf('kham') > -1) { 76 | query_string = ".step2Login a img"; 77 | } 78 | let onclick_event = $(query_string).attr("onclick"); 79 | let onclick_url = onclick_event.split('?')[1]; 80 | let ocr_type = get_url_parameter("TYPE", onclick_url); 81 | //console.log("get new captcha:", onclick_event); 82 | if(ocr_type && ocr_type.length > 0) { 83 | let new_image_src = "/pic.aspx?TYPE="+ ocr_type +"&ts=" + new Date().getTime(); 84 | $("#chk_pic").attr("src", new_image_src); 85 | 86 | let remote_url_string = get_remote_url(settings); 87 | myInterval = setInterval(() => { 88 | ticket_orc_image_ready(remote_url_string); 89 | }, 400); 90 | } 91 | } 92 | 93 | } 94 | } 95 | 96 | async function ticket_get_ocr_answer(api_url, image_data) 97 | { 98 | let bundle = { 99 | action: 'ocr', 100 | data: { 101 | 'url': api_url + 'ocr', 102 | 'image_data':image_data, 103 | } 104 | }; 105 | 106 | let bundle_string = JSON.stringify(bundle); 107 | const return_answer = await chrome.runtime.sendMessage(bundle); 108 | //console.log(return_answer); 109 | } 110 | 111 | function ticket_orc_image_ready(api_url) 112 | { 113 | let ret=false; 114 | let image_data = ticket_get_ocr_image(); 115 | if(image_data.length>0) { 116 | ret=true; 117 | if(myInterval) clearInterval(myInterval); 118 | ticket_get_ocr_answer(api_url, image_data); 119 | } 120 | //console.log("ticket_orc_image_ready:"+ret); 121 | return ret; 122 | } 123 | 124 | storage.get('settings', function (items) 125 | { 126 | if (items.settings) 127 | { 128 | settings = items.settings; 129 | } else { 130 | console.log('no settings found'); 131 | } 132 | }); 133 | 134 | 135 | storage.get('settings', function (items) 136 | { 137 | if (items.settings) 138 | { 139 | settings = items.settings; 140 | } 141 | }); 142 | 143 | function get_remote_url(settings) 144 | { 145 | let remote_url_string = ""; 146 | if(settings) { 147 | let remote_url_array = []; 148 | if(settings.advanced.remote_url.length > 0) { 149 | remote_url_array = JSON.parse('[' + settings.advanced.remote_url +']'); 150 | } 151 | if(remote_url_array.length) { 152 | remote_url_string = remote_url_array[0]; 153 | } 154 | } 155 | return remote_url_string; 156 | } 157 | 158 | function ticket_assign_ticket(settings) 159 | { 160 | if(settings) { 161 | $('div.qty-select input[type="text"]').val(settings.ticket_number); 162 | } 163 | } 164 | 165 | storage.get('status', function (items) 166 | { 167 | if (items.status && items.status=='ON') 168 | { 169 | //console.log("ticket_number:"+ settings.ticket_number); 170 | //ticket_assign_adjacent_seat(settings.advanced.disable_adjacent_seat); 171 | 172 | ticket_assign_ticket(settings); 173 | 174 | // ocr 175 | if(settings.ocr_captcha.enable) { 176 | let remote_url_string = get_remote_url(settings); 177 | if(!ticket_orc_image_ready(remote_url_string)) { 178 | myInterval = setInterval(() => { 179 | ticket_orc_image_ready(remote_url_string); 180 | }, 100); 181 | } 182 | } else { 183 | // no orc, just focus; 184 | ticket_focus_on_captcha(); 185 | } 186 | } else { 187 | console.log('no status found'); 188 | } 189 | }); 190 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Max蛋黃酥上車機器人 2 | MaxBot是一個免費、開放原始碼的蛋黃酥/公車訂位機器人。祝您搶購成功。 3 | 4 | 搶票機制,就是在比誰的網路快、電腦配備好、手速快,或是在比誰的機器人跑的快。 5 | 6 | 售票系統完全無法阻擋機器人進行搶票,也無法透過驗證碼確定為真人,因此售票系統的「驗證碼」機制只是讓一般民眾更難公平地購買到預期的門票。 7 | 8 | 目前售票系統還有另一個問題,就是可以透過「人海戰術」來提升買到票的機率,因此建議大家可以麻煩親朋好友去註冊售票系統的帳號。注意,在借用他人帳號前,一定要告知當事人用途,並徵詢同意與授權。 9 | 10 | MaxBot 的出發點是讓一般民眾與代購黃牛或懂得寫程式的人有類似的基準點或類似的起跑線上,用魔法對抗魔法,當某一天大家都是透過機器人來搶票時,當機器人數量已多到影響一般民眾購票的權利時,售票業者才比較有可能會對未來熱門演唱會改採「實名制」+「抽籤制」,讓更多民眾可以公平地購買到門票,就可以跟「人海戰術」與「搶票機器人」說 bye-bye 。 11 | 12 | 台灣藝文活動的文創法第十條中的「不正方式」由於沒有明確定義,代表的是所有軟體都涉嫌違反。故在此呼籲大家,勿以身試法。 13 | 14 | 以下文章出現的「搶票」指的是「非台灣的藝文活動或車票」。 15 | 16 | MaxBot is a FREE and open source bot program. Good luck getting your expected food or bus seat. 17 | 18 | # LEGAL NOTICE 19 | (法律聲明) 20 | 21 | 作者沒有意圖要他人購得的票券進行加價轉售或是使用在違法的事情上,他人的行為並不在作者的意識支配範圍之內,作者不對他人的相關的非法行為負責。 22 | 23 | 使用此儲存庫或與之相關的任何程式碼,即表示您同意[法律聲明](https://github.com/max32002/tixcraft_bot/blob/master/LEGAL_NOTICE.md)。作者不對該儲存庫的使用負責與背書,也不對其他使用者所做的任何副本、分叉、重新上傳或與 MaxBot 相關的任何其他內容負責。 這是作者唯一的帳戶和儲存庫。 為了防止假冒或不負責任的行為,請遵守此儲存庫使用的 GNU GPL 授權。 24 | 25 | # Download 26 | (搶票程式下載) 27 | 28 | https://github.com/max32002/tixcraft_bot/releases 29 | 30 | 下載說明: 31 | * 目前有打包的「執行檔」,只有Windows 平台,其他作業系統需要使用原始碼來執行。當然Windows 平台也可以用原始碼執行MaxBot. 32 | * 如果你是要用「原始碼」執行MaxBot, 在透過git clone 或在github按下載原始碼的 zip檔,你的python 版本可以使用3.7 / 3.8 / 3.9 / 3.10 這4個版號。 33 | * 如果有辦法的話,建議使用原始碼來執行MaxBot,執行上的「效率」與「相容性」的問題會較少。 34 | 35 | # Demo 36 | (示範影片) 37 | 38 | https://github.com/max32002/tixcraft_bot/blob/master/demo_video.md 39 | 40 | # How to Use 41 | (如何使用教學) 42 | 43 | * tixcraft / indievox / ticketmaster: https://max-everyday.com/2018/03/tixcraft-bot/ 44 | * kktix: https://max-everyday.com/2018/12/kktix-bot/ 45 | * cityline: https://max-everyday.com/2019/03/cityline-bot/ 46 | * urbtix: https://max-everyday.com/2019/02/urbtix-bot/ 47 | * hkticketing / galaxymacau: https://max-everyday.com/2023/01/hkticketing-bot/ 48 | 49 | # How to Execute Source Code 50 | (透過原始碼的執行方法) 51 | 52 | 透過原始碼執行MaxBot教學影片: 53 | https://youtu.be/HpVG91j0lbI 54 | 55 | 使用原始碼的解法,第一步是先取得原始碼後,開啟 Terminal 視窗來下指令,應該是4行指令就可以了。 56 | 57 | 請參看看文章: 如何用虛擬主機搶拓元的門票,這篇文章是以虛擬主機來示範,在 Windows / macOS / Linux 平台裡的 python 操作方式幾乎相同。 58 | 59 | 詳細的文字說明: 60 | https://max-everyday.com/2023/11/buy-ticket-by-vm/ 61 | 62 | ### Step 1: 取得source code: 63 | 64 | git clone https://github.com/max32002/tixcraft_bot.git 65 | 66 | ### Step 2: 進入 clone 的資料夾: tixcraft_bot: 67 | 68 | cd tixcraft_bot 69 | 70 | ### Step 3: 安裝第三方套件: 71 | 72 | python3 -m pip install -r pip-req.txt 73 | 74 | ### Step 4: 執行設定介面主桯式: 75 | 76 | python3 settings.py 77 | 78 | 如果不使用設定介面,直接執行主程式: 79 | 80 | python3 chrome_tixcraft.py 81 | 82 | 如果不使用設定介面,直接執行主程式並套用特定的設定檔: 83 | 84 | python3 chrome_tixcraft.py --input settings.json 85 | 86 | 如果遇到MaxBot 改版, 請重新操作上面4個步驟一次, 即可取得新的版本. 87 | 88 | 如果MaxBot 沒改版, 第二次要再執行的話, 使用 Step 2 + Step 4, 這2行指令, 就可以執行 MaxBot. 89 | 90 | 如果你是 ARM CPU 應該會在 Step 3 就顯示錯誤訊息, 解法: 91 | https://github.com/max32002/tixcraft_bot/issues/82#issuecomment-1878986084 92 | 93 | 不管是 macOS 還是 Windows 預設都是沒有 git 這個指令,如果 Step 1 執行後, 沒有檔案被下載, 請先安裝 git 到你的作業系統。或是使用github 網頁裡的 Download 功能把python 腳本下載。 94 | 95 | 如果你選擇下載 github 上的 zip 檔, 在 Step 2 進入目錄的指令可能會遇到問題, 因為「直接解壓縮」後的目錄名稱並不是 tixcraft_bot 而是 tixcraft_bot-master, 你在進入的資料夾名稱, 需要調整為你實際解壓縮後的目錄名稱。 96 | 97 | 透過瀏覽器下載 github 上的 zip 檔, 在 Windows / macOS / Linux 平台, 預設的路徑在「下載」(~/Download) 的資料夾, 你在執行的 Terminal 視窗的路徑, 與你解壓縮的路徑可能不同, 直接執行上面的指令, 會無法進入到預期的資料夾內。 98 | 99 | ### Q: 取得source code後跑出來fatal: destination path 'tixcraft_bot' already exists and is not an empty directory.想問是什麼意思? 100 | 101 | A: 執行 git clone 2次, 重覆取得 source code, 才會有這個問題, 如果 tixcraft_bot 目錄已經存在, 直接 cd tixcraft_bot 就可以了。 102 | 如果你想把已下載的刪除, 可以直把把 tixcraft_bot 目錄刪掉即可。 103 | 如果你想更新 source code, 可以重新下載, 或是先 cd tixcraft_bot 目錄後, 再執行 git pull , 可以更新 source code 為新的版本。 104 | 105 | 106 | PS: 107 | * 請先確定你的python 執行環境下已安裝 selenium 及相關的套件,請參考 pip-req.txt 檔案內容。 108 | * 透過 python3 執行 settings.py 就可以有 GUI 的設定介面。 109 | * 如果你是使用 macOS 並且執行環境沒有 python3,請 python 官方網站([https://www.python.org/downloads/](https://www.python.org/downloads/))來安裝 python3. 110 | * 如果你是使用 Firefox, ChromeDriver 的元件是叫 geckodriver,下載點在:https://github.com/mozilla/geckodriver/releases ,與 ChromeDriver 的處理方式是一樣,如果是 mac 電腦,要在元件按右鍵開啟,做一次授權的動作,mac 有2個版本,-macos.tar.gz 與 -macos-aarch64.tar.gz ,如果是 intel CPU 的版本,請服用前面沒有 aarch64 的版本。 111 | 112 | PS:搶票程式可以多開chrome瀏覽器,如果你電腦效能高。 113 | 114 | PS:「掛機模式」的選項,指人不需要在電腦前,驗證碼會猜到對為止。 115 | 116 | ### Q: 是只有使用虛擬主機才要用程式碼執行搶票機器人嗎? 117 | 118 | A: 除了 Window 有打包的執行檔之外, macOS / Linux 只能使用原始碼來執行, 當然 Windows 也可以用原始碼來執行. 119 | 120 | # File Description 121 | (檔案說明) 122 | * chrome_tixcraft.py : 搶票機器人主程式, 用來自動化網頁的操作。 123 | * config_launcher.py : 設定檔管理, 方便對多個設定檔案搶票。 124 | * kktix_status.py : kktix 售票狀態監控,可以在有票時提發出提醒。 125 | * settings.py : 編輯 settings.json 的 GUI 介面。提供圖片OCR功能給chrome擴充功能。支援定時啟用/停用MaxBot。 126 | 127 | # Introduce the Implement 128 | (實作方法) 129 | 130 | https://stackoverflow.max-everyday.com/2018/03/selenium-chrome-webdriver/ 131 | 132 | # Execute Suggestion 133 | (搶票建議) 134 | 135 | please run this source code with high performance hardware computer and high speed + stable network. 136 | 137 | 門票的「限量」是很殘酷的,建議不要用破舊的電腦或連線不穩的手機網路來搶票,因為只要比別人慢個 0.1 秒,票可能就沒了。為了要搶到限量的票真心建議去一下網咖或找一個網路連線穩定且快的地方並使用硬體不差的電腦來搶票。 138 | 139 | # TODO about Cpatcha 140 | (關於驗證碼) 141 | 142 | 目前自動輸入驗證碼用的元件是: 143 | 144 | https://github.com/sml2h3/ddddocr 145 | 146 | 附註: 147 | * macOS 新的電腦 arm 系列, 暫時沒有提供自動輸入驗證碼功能, 使用上的限制和 ddddocr 相同. 暫時的解法是透過Rosetta來模擬 Intel CPU 環境. 請參考: https://github.com/max32002/tixcraft_bot/issues/82 148 | * macOS 舊款intel CPU 的電腦裡的 python 版本要降到低於等於 3.9版 或 3.10版, 例如: 149 | https://www.python.org/downloads/release/python-31011/ 150 | * 猜測驗證碼時比較容易出錯的是字英 f 和 t,還有 q 和 g, v 和 u 還有 w. 151 | 152 | 想自動輸入驗證碼,可以參考看看:實作基於CNN的台鐵訂票驗證碼辨識以及透過模仿及資料增強的訓練集產生器 (Simple captcha solver based on CNN and a training set generator by imitating the style of captcha and data augmentation) 153 | 154 | https://github.com/JasonLiTW/simple-railway-captcha-solver 155 | 156 | # Common Problems 157 | (搶票常見問題整理) 158 | 159 | 詳全文:https://max-everyday.com/2023/02/common-problem-when-you-buy-ticket/ 160 | 161 | ## 整理大家在搶票時常遇到的問題: 162 | * 使用搶票程式有違法嗎? 163 | * 沒講清楚成功後的報酬 164 | * 買到太多票 165 | * 如何處理多的票? 166 | * 使用搶票程式會讓自己的帳號被鎖住嗎? 167 | * 如何恢復拓元的「購票權限」? 168 | * 網頁刷新速度有推薦幾秒刷新一次嗎? 169 | * 拓元的搶票,要多少的網路頻寬才夠? 170 | * 使用VPN/代理伺服器(Proxy)來搶票會有用嗎? 171 | * 同一個IP短時間重試被系統視為惡意程式而封鎖怎麼辦? 172 | * Firefox和chrome搶票上有差距嗎?我看大家基本上都用chrome 很少用Firefox. 173 | * 為什麼要設計搶票的機制? 174 | * 為什麼網頁會有驗證碼? 175 | * 你的硬體設備該不該升級? 176 | * 想組一台新的電腦,是不是可以給我一些建議呢? 177 | 178 | # Extension Privacy 179 | (MaxBot Plus擴充功能隱私權政策) 180 | 181 | ## 產品如何收集、使用及分享使用者資料 182 | 183 | * 擴充取得會取得特定網頁內容, 並且自動輸入張數。 184 | * 擴充功能會移除特定網頁內容裡已售完的網頁區塊。 185 | * 擴充功能會取得特定網址資訊, 並置換為下一個新的網址。 186 | * 擴充取得會取得特定網頁內容, 判斷為需要重新整理時, 自動刷新頁面。 187 | 188 | ## 使用者資料的所有分享對象。 189 | 190 | * 擴充功能沒有分享使用者資料。 191 | 192 | ## 擴充功能主要功能: 193 | 194 | * 特定的訂票網頁內容, 並且自動輸入張數。 195 | * 移除特定的訂票網頁內容裡已售完的網頁區塊。 196 | * 特定的訂票網址, 自動置換為下一步的新網址。 197 | * 當訂票網頁內容已經無票或沒有符合的關鍵字時, 自動刷新網頁。 198 | * 特定網頁支援驗證碼功能, 需要同時開啟 MaxBot 主程式。 199 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/options.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | 3 | const submitButton = document.querySelector('#save_btn'); 4 | const ticket_number = document.querySelector('#ticket_number'); 5 | const date_select_mode = document.querySelector('#date_select_mode'); 6 | const date_keyword = document.querySelector('#date_keyword'); 7 | const area_select_mode = document.querySelector('#area_select_mode'); 8 | const area_keyword = document.querySelector('#area_keyword'); 9 | const keyword_exclude = document.querySelector('#keyword_exclude'); 10 | const auto_reload_page_interval = document.querySelector('#auto_reload_page_interval'); 11 | const auto_press_next_step_button = document.querySelector('#auto_press_next_step_button'); 12 | const kktix_status_api = document.querySelector('#kktix_status_api'); 13 | const max_dwell_time = document.querySelector('#max_dwell_time'); 14 | const disable_adjacent_seat = document.querySelector('#disable_adjacent_seat'); 15 | const ocr_captcha_enable = document.querySelector('#ocr_captcha_enable'); 16 | const ocr_captcha_use_public_server = document.querySelector('#ocr_captcha_use_public_server'); 17 | const remote_url = document.querySelector('#remote_url'); 18 | const user_guess_string = document.querySelector('#user_guess_string'); 19 | 20 | const PUBLIC_SERVER_URL = "http://maxbot.dropboxlike.com:16888/"; 21 | 22 | var settings = null; 23 | 24 | loadChanges(); 25 | 26 | submitButton.addEventListener('click', saveChanges); 27 | ocr_captcha_use_public_server.addEventListener('change', checkUsePublicServer); 28 | 29 | async function saveChanges() 30 | { 31 | const ticket_number_value = ticket_number.value; 32 | //console.log(ticket_number_value); 33 | if (!ticket_number_value) 34 | { 35 | message('Error: No ticket_number specified'); 36 | } else { 37 | if(settings) { 38 | settings.ticket_number = ticket_number_value; 39 | settings.date_auto_select.mode = date_select_mode.value; 40 | 41 | let date_keyword_string = date_keyword.value; 42 | if(date_keyword_string.indexOf('"')==-1) { 43 | date_keyword_string = '"' + date_keyword_string + '"'; 44 | } 45 | settings.date_auto_select.date_keyword = date_keyword_string; 46 | 47 | settings.area_auto_select.mode = area_select_mode.value; 48 | 49 | let area_keyword_string = area_keyword.value; 50 | if(area_keyword_string.indexOf('"')==-1) { 51 | area_keyword_string = '"' + area_keyword_string + '"'; 52 | } 53 | settings.area_auto_select.area_keyword = area_keyword_string; 54 | 55 | let user_guess_string_string = user_guess_string.value; 56 | if(user_guess_string_string.indexOf('"')==-1) { 57 | user_guess_string_string = '"' + user_guess_string_string + '"'; 58 | } 59 | settings.advanced.user_guess_string = user_guess_string_string; 60 | 61 | settings.keyword_exclude = keyword_exclude.value; 62 | 63 | settings.advanced.auto_reload_page_interval = auto_reload_page_interval.value; 64 | settings.kktix.auto_press_next_step_button = auto_press_next_step_button.checked; 65 | settings.advanced.kktix_status_api = kktix_status_api.checked; 66 | settings.advanced.max_dwell_time = max_dwell_time.value; 67 | settings.advanced.disable_adjacent_seat = disable_adjacent_seat.checked; 68 | settings.ocr_captcha.enable = ocr_captcha_enable.checked; 69 | 70 | let remote_url_array = []; 71 | remote_url_array.push(remote_url.value); 72 | let remote_url_string = JSON.stringify(remote_url_array); 73 | remote_url_string = remote_url_string.substring(0,remote_url_string.length-1); 74 | remote_url_string = remote_url_string.substring(1); 75 | //console.log("final remote_url_string:"+remote_url_string); 76 | settings.advanced.remote_url = remote_url_string; 77 | 78 | await storage.set( 79 | { 80 | settings: settings 81 | } 82 | ); 83 | } 84 | message('Settings saved'); 85 | } 86 | } 87 | 88 | function loadChanges() 89 | { 90 | storage.get('settings', function (items) 91 | { 92 | //console.log(items); 93 | if (items.settings) 94 | { 95 | settings = items.settings; 96 | //console.log("ticket_number:"+ settings.ticket_number); 97 | ticket_number.value = settings.ticket_number; 98 | date_select_mode.value = settings.date_auto_select.mode; 99 | date_keyword.value = settings.date_auto_select.date_keyword; 100 | if(date_keyword.value=='""') { 101 | date_keyword.value=''; 102 | } 103 | 104 | area_select_mode.value = settings.area_auto_select.mode; 105 | area_keyword.value = settings.area_auto_select.area_keyword; 106 | if(area_keyword.value=='""') { 107 | area_keyword.value=''; 108 | } 109 | 110 | user_guess_string.value = settings.advanced.user_guess_string; 111 | if(user_guess_string.value=='""') { 112 | user_guess_string.value=''; 113 | } 114 | 115 | keyword_exclude.value = settings.keyword_exclude; 116 | auto_reload_page_interval.value = settings.advanced.auto_reload_page_interval; 117 | auto_press_next_step_button.checked = settings.kktix.auto_press_next_step_button; 118 | kktix_status_api.checked = settings.advanced.kktix_status_api; 119 | max_dwell_time.value = settings.advanced.max_dwell_time; 120 | disable_adjacent_seat.checked = settings.advanced.disable_adjacent_seat; 121 | ocr_captcha_enable.checked = settings.ocr_captcha.enable; 122 | 123 | let remote_url_string = ""; 124 | let remote_url_array = []; 125 | if(settings.advanced.remote_url.length > 0) { 126 | remote_url_array = JSON.parse('[' + settings.advanced.remote_url +']'); 127 | } 128 | if(remote_url_array.length) { 129 | remote_url_string = remote_url_array[0]; 130 | } 131 | remote_url.value = remote_url_string; 132 | 133 | //message('Loaded saved settings.'); 134 | } else { 135 | console.log('no settings found'); 136 | } 137 | 138 | } 139 | ); 140 | } 141 | 142 | async function checkUsePublicServer() 143 | { 144 | if(ocr_captcha_enable.checked) { 145 | remote_url.value = PUBLIC_SERVER_URL; 146 | } else { 147 | 148 | } 149 | } 150 | 151 | let messageClearTimer; 152 | function message(msg) 153 | { 154 | clearTimeout(messageClearTimer); 155 | const message = document.querySelector('#message'); 156 | message.innerText = msg; 157 | messageClearTimer = setTimeout(function () 158 | { 159 | message.innerText = ''; 160 | }, 3000); 161 | } 162 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/kktix_registrations_reload.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | var myInterval = null; 4 | 5 | function kktix_clean_exclude(settings) 6 | { 7 | let exclude_keyword_array = []; 8 | if(settings) { 9 | if(settings.keyword_exclude.length > 0) { 10 | if(settings.keyword_exclude != '""') { 11 | exclude_keyword_array = JSON.parse('[' + settings.keyword_exclude +']'); 12 | } 13 | } 14 | } 15 | 16 | for (let i = 0; i < exclude_keyword_array.length; i++) { 17 | $("div.ticket-unit").each(function () 18 | { 19 | let html_text=$(this).text(); 20 | let is_match_keyword=false; 21 | if(html_text.indexOf(exclude_keyword_array[i])>-1) { 22 | is_match_keyword=true; 23 | } 24 | if(is_match_keyword) { 25 | $(this).remove(); 26 | } 27 | } 28 | ); 29 | } 30 | } 31 | 32 | function clean_sold_out_row(register_info, base_info) 33 | { 34 | //console.log("clean_sold_out_row"); 35 | 36 | let match_target = false; 37 | for (var key in register_info.inventory.ticketInventory) { 38 | if(register_info.inventory.ticketInventory[key]) { 39 | //console.log("key:"+key); 40 | if($("#ticket_"+key).length) { 41 | match_target = true; 42 | break; 43 | } 44 | 45 | } 46 | } 47 | //console.log("match_target:"+match_target); 48 | if(match_target) { 49 | $("footer").remove(); 50 | $("div.banner-wrapper").remove(); 51 | $("div.ticket-img-wrapper").remove(); 52 | 53 | $("span.ticket-quantity[ng-if=\"!purchasableAndSelectable\"]").each(function () 54 | { 55 | $(this).parent().parent().parent().remove(); 56 | }); 57 | clearInterval(myInterval); 58 | 59 | if(settings) { 60 | let settings_div=""; 61 | $("body").append(settings_div); 62 | let register_info_div=""; 63 | $("body").append(register_info_div); 64 | let base_info_div=""; 65 | $("body").append(base_info_div); 66 | kktix_clean_exclude(settings); 67 | //kktix_area_keyword(settings, register_info); 68 | } 69 | } 70 | } 71 | 72 | function kktix_ajax_return_base_info(base_info, register_info) 73 | { 74 | //console.log(base_info.eventData.order_qualifications); 75 | $(function() { 76 | myInterval = setInterval(() => { 77 | clean_sold_out_row(register_info, base_info); 78 | }, 200); 79 | }); 80 | } 81 | 82 | function kktix_ajax_return_register_info(register_info) 83 | { 84 | let reload=false; 85 | //console.log(register_info.inventory.registerStatus); 86 | // IN_STOCK 87 | if(register_info.inventory.registerStatus=='OUT_OF_STOCK') {reload=true;} 88 | if(register_info.inventory.registerStatus=='COMING_SOON') {reload=true;} 89 | if(register_info.inventory.registerStatus=='SOLD_OUT') {reload=true;} 90 | //console.log(reload); 91 | if(reload) { 92 | let auto_reload_page_interval = 0.0; 93 | if(settings) { 94 | auto_reload_page_interval = settings.advanced.auto_reload_page_interval; 95 | } 96 | // memory not able to release soon. 97 | if (auto_reload_page_interval < 0.23) { 98 | auto_reload_page_interval = 0.23; 99 | } 100 | const rootElement = document.documentElement; 101 | rootElement.remove(); 102 | register_info=null; 103 | settings = null; 104 | myInterval = null; 105 | for (var key in window) { 106 | key=null; 107 | delete key; 108 | } 109 | if(auto_reload_page_interval == 0) { 110 | //console.log('Start to reload now.'); 111 | window.location.reload(); 112 | } else { 113 | //console.log('We are going to reload after few seconeds.'); 114 | setTimeout(function () { 115 | window.location.reload(); 116 | }, auto_reload_page_interval * 1000); 117 | } 118 | } 119 | else { 120 | kktix_event_base_info(register_info); 121 | kktix_force_auto_reload_by_timer(); 122 | } 123 | } 124 | 125 | function kktix_event_base_info(register_info) 126 | { 127 | const currentUrl = window.location.href; 128 | const event_code = currentUrl.split('/')[4]; 129 | //console.log(currentUrl); 130 | //console.log(event_code); 131 | if(event_code){ 132 | let api_url = "https://kktix.com/g/events/"+ event_code +"/base_info"; 133 | $.get( api_url, function() { 134 | //alert( "success" ); 135 | }) 136 | .done(function(data) { 137 | //alert( "second success" ); 138 | kktix_ajax_return_base_info(data, register_info); 139 | }) 140 | .fail(function() { 141 | //alert( "error" ); 142 | }) 143 | .always(function() { 144 | //alert( "finished" ); 145 | }); 146 | } 147 | } 148 | 149 | function kktix_event_register_info() 150 | { 151 | const currentUrl = window.location.href; 152 | const event_code = currentUrl.split('/')[4]; 153 | //console.log(currentUrl); 154 | //console.log(event_code); 155 | if(event_code){ 156 | let api_url = "https://kktix.com/g/events/"+ event_code +"/register_info"; 157 | $.get( api_url, function() { 158 | //alert( "success" ); 159 | }) 160 | .done(function(data) { 161 | //alert( "second success" ); 162 | kktix_ajax_return_register_info(data); 163 | }) 164 | .fail(function() { 165 | //alert( "error" ); 166 | }) 167 | .always(function() { 168 | //alert( "finished" ); 169 | }); 170 | } 171 | } 172 | 173 | function kktix_force_auto_reload_by_timer() 174 | { 175 | if(settings) { 176 | //console.log("auto reload for kktix"); 177 | if(settings.advanced.kktix_account.length > 0) { 178 | let max_dwell_time = 120; 179 | if(settings) { 180 | max_dwell_time = settings.advanced.max_dwell_time; 181 | } 182 | if(max_dwell_time <= 10) { 183 | max_dwell_time = 10; 184 | } 185 | console.log('We are going to force reload after few seconeds.'); 186 | setTimeout(function () { 187 | location.reload(); 188 | }, max_dwell_time * 1000); 189 | } 190 | } 191 | } 192 | 193 | storage.get('settings', function (items) 194 | { 195 | if (items.settings) 196 | { 197 | settings = items.settings; 198 | } 199 | }); 200 | 201 | storage.get('status', function (items) 202 | { 203 | if (items.status && items.status=='ON') 204 | { 205 | let kktix_status_api = false; 206 | if(settings) { 207 | kktix_status_api = settings.advanced.kktix_status_api; 208 | } 209 | if(kktix_status_api) { 210 | kktix_event_register_info(); 211 | } else { 212 | kktix_force_auto_reload_by_timer(); 213 | } 214 | } else { 215 | //console.log('maxbot status is not ON'); 216 | } 217 | }); 218 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/tixcraft_ticket.js: -------------------------------------------------------------------------------- 1 | const storage = chrome.storage.local; 2 | var settings = null; 3 | 4 | $('input[type=checkbox]').each(function () 5 | { 6 | $(this).prop('checked', true); 7 | } 8 | ); 9 | $("img[style='width: 100%; padding: 0;']").remove(); 10 | $("footer").remove(); 11 | 12 | function tixcraft_ticket_clean_exclude(settings) 13 | { 14 | let exclude_keyword_array = []; 15 | if(settings) { 16 | if(settings.keyword_exclude.length > 0) { 17 | if(settings.keyword_exclude!='""') { 18 | exclude_keyword_array = JSON.parse('[' + settings.keyword_exclude +']'); 19 | } 20 | } 21 | } 22 | for (let i = 0; i < exclude_keyword_array.length; i++) { 23 | $("#ticketPriceList > tbody > tr").each(function () 24 | { 25 | let html_text=$(this).text(); 26 | //console.log("html:"+html_text); 27 | if(html_text.indexOf(exclude_keyword_array[i])>-1) { 28 | $(this).remove(); 29 | } 30 | }); 31 | } 32 | } 33 | 34 | function tixcraft_assign_ticket_number(settings) 35 | { 36 | let area_keyword_array = []; 37 | if(settings) { 38 | if(settings.area_auto_select.area_keyword.length > 0) { 39 | if(settings.area_auto_select.area_keyword!='""') { 40 | area_keyword_array = JSON.parse('[' + settings.area_auto_select.area_keyword +']'); 41 | } 42 | } 43 | } 44 | //let target_area = []; 45 | 46 | let target_row=null; 47 | let all_row = $("#ticketPriceList > tbody > tr"); 48 | if (all_row.length > 0) 49 | { 50 | if (all_row.length == 1) { 51 | // single select. 52 | target_row=all_row; 53 | } else { 54 | // single select. 55 | all_row.each(function () 56 | { 57 | //console.log(all_row.index(this)); 58 | let is_match_keyword = false; 59 | if(area_keyword_array.length) { 60 | let html_text=$(this).text(); 61 | //console.log("html:"+html_text); 62 | 63 | // TOOD: multi item matched, need sort. 64 | for (let i = 0; i < area_keyword_array.length; i++) { 65 | // target_area = get_target_area_with_order(settings, matched_block); 66 | console.log("area_keyword:"+area_keyword_array[i]); 67 | 68 | if(area_keyword_array[i].indexOf(" ")>-1) { 69 | // TODO: muti keywords with AND logic. 70 | } else { 71 | if(html_text.indexOf(area_keyword_array[i])>-1) { 72 | is_match_keyword = true; 73 | target_row=$(this); 74 | break; 75 | } 76 | } 77 | } 78 | } else { 79 | if(all_row.index(this)==0) { 80 | is_match_keyword = true; 81 | target_row=$(this); 82 | } 83 | } 84 | //console.log("is_match_keyword:"+is_match_keyword); 85 | if(is_match_keyword) { 86 | return; 87 | } 88 | }); 89 | } 90 | 91 | let ticket_options = target_row.find("option"); 92 | if (ticket_options.length) 93 | { 94 | let is_ticket_number_assign = false; 95 | if (settings.ticket_number > 0) 96 | { 97 | ticket_options.each(function () 98 | { 99 | if ($(this).val() == settings.ticket_number) 100 | { 101 | $(this).prop('selected', true); 102 | is_ticket_number_assign = true; 103 | return false; 104 | } 105 | }); 106 | } 107 | if (!is_ticket_number_assign) 108 | { 109 | ticket_options.last().prop('selected', true); 110 | } 111 | } 112 | } 113 | } 114 | 115 | var myInterval = null; 116 | 117 | function get_ocr_image() 118 | { 119 | //console.log("get_ocr_image"); 120 | let image_data = ""; 121 | 122 | // PS: tixcraft have different domain to use the same content script. 123 | const currentUrl = window.location.href; 124 | const domain = currentUrl.split('/')[2]; 125 | 126 | let image_id = 'TicketForm_verifyCode-image'; 127 | let img = document.getElementById(image_id); 128 | if(img!=null) { 129 | let canvas = document.createElement('canvas'); 130 | let context = canvas.getContext('2d'); 131 | canvas.height = img.naturalHeight; 132 | canvas.width = img.naturalWidth; 133 | context.drawImage(img, 0, 0); 134 | let img_data = canvas.toDataURL(); 135 | if(img_data) { 136 | image_data = img_data.split(",")[1]; 137 | //console.log(image_data); 138 | } 139 | } 140 | return image_data; 141 | } 142 | 143 | var last_captcha_answer=""; 144 | chrome.runtime.onMessage.addListener((message) => { 145 | //console.log('sent from background', message); 146 | if(message.answer.length==4) { 147 | tixcraft_set_ocr_answer(message.answer); 148 | last_captcha_answer=message.answer; 149 | } else { 150 | // renew captcha. 151 | if(last_captcha_answer!=message.answer) { 152 | last_captcha_answer=message.answer; 153 | console.log("renew captcha"); 154 | $('#TicketForm_verifyCode').click(); 155 | } 156 | } 157 | }); 158 | 159 | function tixcraft_set_ocr_answer(answer) 160 | { 161 | //console.log("answer:"+answer); 162 | if(answer.length > 0) { 163 | $('#TicketForm_verifyCode').val(answer); 164 | $("button[type='submit']").click(); 165 | } 166 | } 167 | 168 | async function tixcraft_get_ocr_answer(api_url, image_data) 169 | { 170 | let bundle = { 171 | action: 'ocr', 172 | data: { 173 | 'url': api_url + 'ocr', 174 | 'image_data':image_data, 175 | } 176 | }; 177 | 178 | const return_answer = await chrome.runtime.sendMessage(bundle); 179 | //console.log(return_answer); 180 | 181 | // fail due to CORS error 182 | //ocr(bundle.data.url, bundle.data.image_data, bundle.data.callback); 183 | } 184 | 185 | function tixcraft_orc_image_ready(api_url) 186 | { 187 | let ret=false; 188 | let image_data = get_ocr_image(); 189 | if(image_data.length>0) { 190 | ret=true; 191 | if(myInterval) clearInterval(myInterval); 192 | tixcraft_get_ocr_answer(api_url, image_data); 193 | } 194 | //console.log("orc_image_ready:"+ret); 195 | return ret; 196 | } 197 | 198 | storage.get('settings', function (items) 199 | { 200 | if (items.settings) 201 | { 202 | settings = items.settings; 203 | } else { 204 | console.log('no settings found'); 205 | } 206 | }); 207 | 208 | function get_remote_url(settings) 209 | { 210 | let remote_url_string = ""; 211 | if(settings) { 212 | let remote_url_array = []; 213 | if(settings.advanced.remote_url.length > 0) { 214 | remote_url_array = JSON.parse('[' + settings.advanced.remote_url +']'); 215 | } 216 | if(remote_url_array.length) { 217 | remote_url_string = remote_url_array[0]; 218 | } 219 | } 220 | return remote_url_string; 221 | } 222 | 223 | storage.get('status', function (items) 224 | { 225 | if (items.status && items.status=='ON') 226 | { 227 | tixcraft_ticket_clean_exclude(settings); 228 | 229 | //console.log("ticket_number:"+ settings.ticket_number); 230 | tixcraft_assign_ticket_number(settings); 231 | 232 | // ocr 233 | if(settings.ocr_captcha.enable) { 234 | let remote_url_string = get_remote_url(settings); 235 | if(!tixcraft_orc_image_ready(remote_url_string)) { 236 | myInterval = setInterval(() => { 237 | tixcraft_orc_image_ready(remote_url_string); 238 | }, 100); 239 | } 240 | } 241 | 242 | } else { 243 | console.log('no status found'); 244 | } 245 | }); 246 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/options.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Extension Options 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |

MaxBot Settings

13 |
14 | 25 |
26 | 27 |
28 |
29 | 30 |
31 | 66 |
67 |
68 |
69 | 70 |
71 | 85 |
86 |
87 |
88 | 89 |
90 | 91 |
92 |
93 |
94 | 95 |
96 | 110 |
111 |
112 |
113 | 114 |
115 | 116 |
117 |
118 |
119 | 120 |
121 | 122 |
123 |
124 |
125 | 126 |
127 |
128 | 129 |
130 | 131 |
132 |
133 | 134 |
135 | 136 |
137 | 138 |
139 |
140 |
141 | 142 |
143 | 144 |
145 |
146 |
147 | 148 |
149 | 150 |
151 |
152 |
153 | 154 |
155 | 156 |
157 |
158 |
159 | 160 |
161 | 162 |
163 |
164 |
165 | 166 |
167 | 168 |
169 |
170 |
171 | 172 |
173 | 174 |
175 |
176 |
177 | 178 |
179 |
180 | 181 |
182 | 183 |
184 |
185 |
186 |
187 |
188 | 189 |
190 |
191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/js/kktix_registrations_assign.js: -------------------------------------------------------------------------------- 1 | var myInterval = null; 2 | var checkboxInterval = null; 3 | //console.log("assign appear"); 4 | 5 | function kktix_verification_conditions(settings) 6 | { 7 | let is_text_sent = false; 8 | let user_guess_string_array = []; 9 | if(settings) { 10 | if(settings.advanced.user_guess_string.length > 0) { 11 | if(settings.advanced.user_guess_string!='""') { 12 | user_guess_string_array = JSON.parse('[' + settings.advanced.user_guess_string +']'); 13 | } 14 | } 15 | } 16 | 17 | let target_row=null; 18 | let all_row = $("div.control-group > div.controls > label > input[type='text']"); 19 | if (all_row.length > 0 && user_guess_string_array.length > 0) 20 | { 21 | //console.log("input count:" + all_row.length); 22 | let travel_index=0; 23 | all_row.each(function () 24 | { 25 | let current_index = all_row.index(this); 26 | //console.log("current_index:" + current_index); 27 | if(current_index+1 <= user_guess_string_array.length) { 28 | //console.log("input data:" + user_guess_string_array[current_index]); 29 | $(this).val(user_guess_string_array[current_index]); 30 | is_text_sent = true; 31 | } 32 | }); 33 | } 34 | 35 | return is_text_sent; 36 | } 37 | 38 | function kktix_agree() 39 | { 40 | $('input[type=checkbox]:not(:checked)').each(function() { 41 | $(this).click(); 42 | if(checkboxInterval) clearInterval(checkboxInterval); 43 | }); 44 | } 45 | 46 | function kktix_area_keyword(settings, base_info, register_info) 47 | { 48 | let area_keyword_array = []; 49 | if(settings) { 50 | if(settings.area_auto_select.area_keyword.length > 0) { 51 | if(settings.area_auto_select.area_keyword!='""') { 52 | area_keyword_array = JSON.parse('[' + settings.area_auto_select.area_keyword +']'); 53 | } 54 | } 55 | } 56 | // console.log(area_keyword_array); 57 | let target_area = null; 58 | let matched_block=[]; 59 | let query_string = "div.ticket-unit"; 60 | if(area_keyword_array.length) { 61 | for (let i = 0; i < area_keyword_array.length; i++) { 62 | $(query_string).each(function () 63 | { 64 | let html_text=$(this).text(); 65 | if(html_text.indexOf(area_keyword_array[i])>-1) { 66 | matched_block.push($(this)); 67 | } 68 | target_area = get_target_area_with_order(settings, matched_block); 69 | }); 70 | 71 | if (matched_block.length) { 72 | console.log("match keyword:" + area_keyword_array[i]); 73 | break; 74 | } 75 | } 76 | } else { 77 | $(query_string).each(function () 78 | { 79 | matched_block.push($(this)); 80 | }); 81 | target_area = get_target_area_with_order(settings, matched_block); 82 | } 83 | 84 | if (target_area) { 85 | let first_node = target_area.find(":first-child"); 86 | let link_id = first_node.attr("id"); 87 | //console.log("link_id: " + link_id); 88 | if(link_id) { 89 | let seat_inventory_key=link_id.split("_")[1]; 90 | //console.log("seat_inventory_key:"+seat_inventory_key); 91 | let seat_inventory_number=register_info.inventory.seatInventory[seat_inventory_key]; 92 | let ticket_number = settings.ticket_number; 93 | if(seat_inventory_number0) { 98 | /* 99 | // trigger events by jQuery. 100 | let target_input = target_area.find("input"); 101 | target_input.click(); 102 | target_input.prop("value", ticket_number); 103 | let down = $.Event('keydown'); 104 | down.key=""+ticket_number; 105 | target_input.trigger(down); 106 | 107 | let up = $.Event('keyup'); 108 | up.key=""+ticket_number; 109 | target_input.trigger(up); 110 | */ 111 | 112 | //console.log(base_info); 113 | let is_verification_conditions_popup = false; 114 | if(base_info && base_info.eventData.hasOwnProperty("order_qualifications")) { 115 | //console.log(base_info.eventData.order_qualifications.length); 116 | for (let i = 0; i < base_info.eventData.order_qualifications.length; i++) { 117 | let rs = base_info.eventData.order_qualifications[i]; 118 | //console.log(rs); 119 | for(let j=0; j < rs.conditions.length; j++) { 120 | let rs_j = JSON.parse(rs.conditions[j]); 121 | //console.log(rs_j); 122 | if(rs_j.hasOwnProperty("ticket_ids")) { 123 | //console.log(rs_j.ticket_ids.length); 124 | for(let k=0; k < rs_j.ticket_ids.length; k++) { 125 | let rs_k = rs_j.ticket_ids[k] 126 | //console.log(rs_k); 127 | if(""+rs_k==seat_inventory_key) { 128 | is_verification_conditions_popup = true; 129 | } 130 | } 131 | } 132 | 133 | } 134 | } 135 | } 136 | 137 | let add_button = target_area.find('button[ng-click="quantityBtnClick(1)"]'); 138 | for(let i=0; i button'); 157 | if($next_btn) { 158 | if($next_btn.length>1) { 159 | $next_btn.last().click(); 160 | } else { 161 | $next_btn.click(); 162 | } 163 | hide_other_row = true; 164 | } 165 | } 166 | 167 | // due to racing with web driver. 168 | if(hide_other_row) { 169 | for (let i = 0; i < matched_block.length; i++) { 170 | if(target_area!=matched_block[i]) 171 | { 172 | matched_block[i].remove(); 173 | } 174 | } 175 | } 176 | } 177 | } 178 | } else { 179 | console.log("not target_area found.") 180 | } 181 | } 182 | 183 | function begin() 184 | { 185 | let settings = JSON.parse($("#settings").html()); 186 | let base_info = JSON.parse($("#base_info").html()); 187 | let register_info = JSON.parse($("#register_info").html()); 188 | $("#settings").remove(); 189 | $("#base_info").remove(); 190 | $("#register_info").remove(); 191 | //console.log(settings); 192 | //console.log(register_info); 193 | 194 | kktix_area_keyword(settings, base_info, register_info); 195 | } 196 | 197 | function dom_ready() 198 | { 199 | let ret=false; 200 | //console.log("checking..."); 201 | if($("#settings").length>0) { 202 | ret=true; 203 | if(myInterval) clearInterval(myInterval); 204 | begin(); 205 | } 206 | //console.log("dom_ready:"+ret); 207 | return ret; 208 | } 209 | 210 | const rootElement = document.documentElement; 211 | if(rootElement) { 212 | if(!dom_ready()) { 213 | myInterval = setInterval(() => { 214 | dom_ready(); 215 | }, 200); 216 | 217 | checkboxInterval= setInterval(() => { 218 | //console.log("kktix_agree") 219 | kktix_agree(); 220 | }, 200); 221 | } 222 | $("footer").remove(); 223 | $("div.banner-wrapper div.img-wrapper img").remove(); 224 | } 225 | 226 | 227 | -------------------------------------------------------------------------------- /webdriver/Maxbotplus_1.0.0/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Max Yao", 3 | "name": "MaxBot Plus", 4 | "description": "Quick way to get expected tickets on some specific websites.", 5 | "icons": { 6 | "16": "icons/maxbot-16.png", 7 | "32": "icons/maxbot-32.png", 8 | "48": "icons/maxbot-48.png", 9 | "64": "icons/maxbot-64.png", 10 | "128": "icons/maxbot-128.png" 11 | }, 12 | "manifest_version": 3, 13 | "background": { 14 | "service_worker": "background.js", 15 | "type": "module" 16 | }, 17 | "permissions": [ 18 | "storage", 19 | "declarativeNetRequest", 20 | "declarativeNetRequestFeedback" 21 | ], 22 | "host_permissions": [ 23 | "http://maxbot.dropboxlike.com:16888/*", 24 | "http://127.0.0.1:16888/*" 25 | ], 26 | "web_accessible_resources": [ 27 | { 28 | "resources": [ 29 | "data/*.json" 30 | ], 31 | "extension_ids": [ 32 | "*" 33 | ], 34 | "matches": [ 35 | "*://*/*" 36 | ] 37 | } 38 | ], 39 | "options_page": "options.html", 40 | "action": { 41 | "default_icon": "icons/maxbot-128.png", 42 | "default_title": "MaxBot" 43 | }, 44 | "content_scripts": [ 45 | { 46 | "matches": [ 47 | "https://tixcraft.com/", 48 | "https://www.indievox.com/", 49 | "https://indievox.com/", 50 | "https://ticketmaster.sg/" 51 | ], 52 | "run_at": "document_end", 53 | "js": [ 54 | "jquery.min.js", 55 | "js/tixcraft_home.js" 56 | ] 57 | }, 58 | { 59 | "matches": [ 60 | "https://tixcraft.com/activity/detail/*", 61 | "https://www.indievox.com/activity/detail/*", 62 | "https://indievox.com/activity/detail/*", 63 | "https://ticketmaster.sg/activity/detail/*" 64 | ], 65 | "run_at": "document_start", 66 | "js": [ 67 | "jquery.min.js", 68 | "js/tixcraft_detail.js" 69 | ] 70 | }, 71 | { 72 | "matches": [ 73 | "https://tixcraft.com/activity/game/*", 74 | "https://www.indievox.com/activity/game/*", 75 | "https://indievox.com/activity/game/*", 76 | "https://ticketmaster.sg/activity/game/*" 77 | ], 78 | "run_at": "document_end", 79 | "js": [ 80 | "jquery.min.js", 81 | "js/common.js", 82 | "js/tixcraft_game.js" 83 | ] 84 | }, 85 | { 86 | "matches": [ 87 | "https://ticketmaster.sg/ticket/area/*" 88 | ], 89 | "run_at": "document_end", 90 | "js": [ 91 | "jquery.min.js", 92 | "js/ticketmaster_area.js" 93 | ] 94 | }, 95 | { 96 | "matches": [ 97 | "https://tixcraft.com/ticket/area/*", 98 | "https://www.indievox.com/ticket/area/*", 99 | "https://indievox.com/ticket/area/*" 100 | ], 101 | "run_at": "document_end", 102 | "js": [ 103 | "jquery.min.js", 104 | "js/common.js", 105 | "js/tixcraft_area.js" 106 | ] 107 | }, 108 | { 109 | "matches": [ 110 | "https://tixcraft.com/ticket/ticket/*", 111 | "https://www.indievox.com/ticket/ticket/*", 112 | "https://indievox.com/ticket/ticket/*", 113 | "https://ticketmaster.sg/ticket/ticket/*", 114 | "https://ticketmaster.sg/ticket/check-captcha/*" 115 | ], 116 | "run_at": "document_end", 117 | "js": [ 118 | "jquery.min.js", 119 | "js/common.js", 120 | "js/tixcraft_ticket.js" 121 | ] 122 | }, 123 | { 124 | "matches": [ 125 | "https://ticket.com.tw/application/utk01/utk0101_.aspx", 126 | "https://ticket.com.tw/application/UTK01/utk0101_.aspx" 127 | ], 128 | "run_at": "document_end", 129 | "js": [ 130 | "jquery.min.js", 131 | "js/ticket_home.js" 132 | ] 133 | }, 134 | { 135 | "matches": [ 136 | "https://ticket.com.tw/application/utk02/UTK0201_.aspx?PRODUCT_ID=*", 137 | "https://ticket.com.tw/application/UTK02/UTK0201_.aspx?PRODUCT_ID=*" 138 | ], 139 | "run_at": "document_end", 140 | "world": "MAIN", 141 | "js": [ 142 | "jquery.min.js", 143 | "js/ticket_event_home.js" 144 | ] 145 | }, 146 | { 147 | "matches": [ 148 | "https://ticket.com.tw/application/utk02/UTK0201_00.aspx?PRODUCT_ID=*", 149 | "https://ticket.com.tw/application/UTK02/UTK0201_00.aspx?PRODUCT_ID=*" 150 | ], 151 | "run_at": "document_end", 152 | "world": "MAIN", 153 | "js": [ 154 | "jquery.min.js", 155 | "js/ticket_date.js" 156 | ] 157 | }, 158 | { 159 | "matches": [ 160 | "https://ticket.com.tw/application/utk02/UTK0204_.aspx?*", 161 | "https://ticket.com.tw/application/UTK02/UTK0204_.aspx?*" 162 | ], 163 | "run_at": "document_end", 164 | "js": [ 165 | "jquery.min.js", 166 | "js/ticket_area.js" 167 | ] 168 | }, 169 | { 170 | "matches": [ 171 | "https://ticket.com.tw/application/UTK02/UTK0205_.aspx?*", 172 | "https://ticket.com.tw/application/utk02/UTK0202_.aspx?*", 173 | "https://ticket.com.tw/application/UTK02/UTK0205_.aspx?*", 174 | "https://ticket.com.tw/application/utk02/UTK0202_.aspx?*", 175 | "https://kham.com.tw/application/UTK02/UTK0205_.aspx?*", 176 | "https://kham.com.tw/application/utk02/UTK0205_.aspx?*", 177 | "https://kham.com.tw/application/UTK02/UTK0202_.aspx?*", 178 | "https://kham.com.tw/application/utk02/UTK0202_.aspx?*" 179 | ], 180 | "run_at": "document_end", 181 | "js": [ 182 | "jquery.min.js", 183 | "js/ticket_ticket.js" 184 | ] 185 | }, 186 | { 187 | "matches": [ 188 | "https://kham.com.tw/application/utk01/UTK0101_03.aspx", 189 | "https://kham.com.tw/application/UTK01/UTK0101_03.aspx" 190 | ], 191 | "run_at": "document_end", 192 | "js": [ 193 | "jquery.min.js", 194 | "js/kham_home.js" 195 | ] 196 | }, 197 | { 198 | "matches": [ 199 | "https://kham.com.tw/application/utk02/UTK0201_.aspx?PRODUCT_ID=*", 200 | "https://kham.com.tw/application/UTK02/UTK0201_.aspx?PRODUCT_ID=*" 201 | ], 202 | "run_at": "document_end", 203 | "world": "MAIN", 204 | "js": [ 205 | "jquery.min.js", 206 | "js/kham_event_home.js" 207 | ] 208 | }, 209 | { 210 | "matches": [ 211 | "https://kham.com.tw/application/utk02/UTK0201_00.aspx?PRODUCT_ID=*", 212 | "https://kham.com.tw/application/UTK02/UTK0201_00.aspx?PRODUCT_ID=*" 213 | ], 214 | "run_at": "document_end", 215 | "world": "MAIN", 216 | "js": [ 217 | "jquery.min.js", 218 | "js/kham_date.js" 219 | ] 220 | }, 221 | { 222 | "matches": [ 223 | "https://kham.com.tw/application/utk02/UTK0204_.aspx?*", 224 | "https://kham.com.tw/application/UTK02/UTK0204_.aspx?*", 225 | "https://kham.com.tw/application/utk02/UTK0201_000.aspx?PERFORMANCE_ID=*&PRODUCT_ID=*", 226 | "https://kham.com.tw/application/UTK02/UTK0201_000.aspx?PERFORMANCE_ID=*&PRODUCT_ID=*" 227 | ], 228 | "run_at": "document_end", 229 | "js": [ 230 | "jquery.min.js", 231 | "js/kham_area.js" 232 | ] 233 | }, 234 | { 235 | "matches": [ 236 | "https://ticket.ibon.com.tw/ActivityInfo/Details/*" 237 | ], 238 | "run_at": "document_start", 239 | "js": [ 240 | "jquery.min.js", 241 | "js/ibon_detail.js" 242 | ] 243 | }, 244 | { 245 | "matches": [ 246 | "https://orders.ibon.com.tw/application/utk02/UTK0201_000.aspx?*", 247 | "https://orders.ibon.com.tw/application/UTK02/UTK0201_000.aspx?*" 248 | ], 249 | "run_at": "document_end", 250 | "js": [ 251 | "jquery.min.js", 252 | "js/ibon_area.js" 253 | ] 254 | }, 255 | { 256 | "matches": [ 257 | "https://orders.ibon.com.tw/application/utk02/UTK0201_000.aspx?*", 258 | "https://orders.ibon.com.tw/application/UTK02/UTK0201_000.aspx?*" 259 | ], 260 | "run_at": "document_end", 261 | "world": "MAIN", 262 | "js": [ 263 | "jquery.min.js", 264 | "js/ibon_area_front.js" 265 | ] 266 | }, 267 | { 268 | "matches": [ 269 | "https://orders.ibon.com.tw/application/utk02/UTK0201_001.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*", 270 | "https://orders.ibon.com.tw/application/UTK02/UTK0201_001.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*", 271 | "https://orders.ibon.com.tw/application/utk02/UTK0202_.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*", 272 | "https://orders.ibon.com.tw/application/UTK02/UTK0202_.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*" 273 | ], 274 | "run_at": "document_end", 275 | "js": [ 276 | "jquery.min.js", 277 | "js/ibon_ticket.js" 278 | ] 279 | }, 280 | { 281 | "matches": [ 282 | "https://orders.ibon.com.tw/application/utkK02/UTK0201_001.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*", 283 | "https://orders.ibon.com.tw/application/UTK02/UTK0201_001.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*", 284 | "https://orders.ibon.com.tw/application/utk02/UTK0202_.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*", 285 | "https://orders.ibon.com.tw/application/UTK02/UTK0202_.aspx?PERFORMANCE_ID=*PERFORMANCE_PRICE_AREA_ID=*" 286 | ], 287 | "run_at": "document_end", 288 | "world": "MAIN", 289 | "js": [ 290 | "jquery.min.js", 291 | "js/ibon_ticket_next.js" 292 | ] 293 | }, 294 | { 295 | "matches": [ 296 | "https://orders.ibon.com.tw/application/utk02/UTK0201_0.aspx?*PERFORMANCE_ID=*PRODUCT_ID=*", 297 | "https://orders.ibon.com.tw/application/UTK02/UTK0201_0.aspx?*PERFORMANCE_ID=*PRODUCT_ID=*", 298 | "https://orders.ibon.com.tw/application/utk02/UTK0201_0.aspx?*PRODUCT_ID=*PERFORMANCE_ID=*", 299 | "https://orders.ibon.com.tw/application/UTK02/UTK0201_0.aspx?*PRODUCT_ID=*PERFORMANCE_ID=*" 300 | ], 301 | "run_at": "document_end", 302 | "js": [ 303 | "jquery.min.js", 304 | "js/ibon_verification.js" 305 | ] 306 | }, 307 | { 308 | "matches": [ 309 | "https://queue.hkticketing.com/hotshow.html", 310 | "https://busy.hkticketing.com/" 311 | ], 312 | "run_at": "document_end", 313 | "js": [ 314 | "jquery.min.js", 315 | "js/hkticketing_queue_background.js" 316 | ] 317 | }, 318 | { 319 | "matches": [ 320 | "https://queue.hkticketing.com/hotshow.html", 321 | "https://busy.hkticketing.com/" 322 | ], 323 | "run_at": "document_end", 324 | "world": "MAIN", 325 | "js": [ 326 | "js/hkticketing_queue_front.js" 327 | ] 328 | }, 329 | { 330 | "matches": [ 331 | "https://msg.cityline.com/*.html*", 332 | "https://*.cityline.com/utsvInternet/*/home?lang=TW", 333 | "https://event.cityline.com/", 334 | "https://event.cityline.com/queue?loc=*" 335 | ], 336 | "run_at": "document_end", 337 | "js": [ 338 | "jquery.min.js", 339 | "js/cityline_msg_background.js" 340 | ] 341 | }, 342 | { 343 | "matches": [ 344 | "https://msg.cityline.com/*.html*", 345 | "https://*.cityline.com/utsvInternet/*/home?lang=TW", 346 | "https://event.cityline.com/", 347 | "https://event.cityline.com/queue?loc=*" 348 | ], 349 | "run_at": "document_end", 350 | "world": "MAIN", 351 | "js": [ 352 | "jquery.min.js", 353 | "js/cityline_msg_front.js" 354 | ] 355 | }, 356 | { 357 | "matches": [ 358 | "https://*.cityline.com/utsvInternet/*/eventDetail?event=*", 359 | "https://*.cityline.com/utsvlnternet/*/login?lang=TW" 360 | ], 361 | "run_at": "document_end", 362 | "world": "MAIN", 363 | "js": [ 364 | "js/cityline_event_detail.js" 365 | ] 366 | }, 367 | { 368 | "matches": [ 369 | "https://shows.cityline.com/tc/*", 370 | "https://shows.cityline.com/en/*", 371 | "https://priority.cityline.com/tc/*", 372 | "https://priority.cityline.com/en/*", 373 | "https://sports.cityline.com/tc/*", 374 | "https://sports.cityline.com/en/*", 375 | "https://cultural.cityline.com/tc/*", 376 | "https://cultural.cityline.com/en/*" 377 | ], 378 | "run_at": "document_end", 379 | "world": "MAIN", 380 | "js": [ 381 | "jquery.min.js", 382 | "js/cityline_shows_buy_front.js" 383 | ] 384 | }, 385 | { 386 | "matches": [ 387 | "https://venue.cityline.com/utsvInternet/*/performance?*" 388 | ], 389 | "run_at": "document_end", 390 | "js": [ 391 | "jquery.min.js", 392 | "js/common.js", 393 | "js/cityline_performance.js" 394 | ] 395 | }, 396 | { 397 | "matches": [ 398 | "https://ticketplus.com.tw/activity/*" 399 | ], 400 | "run_at": "document_end", 401 | "js": [ 402 | "jquery.min.js", 403 | "js/ticketplus_activity.js" 404 | ] 405 | }, 406 | { 407 | "matches": [ 408 | "https://ticketplus.com.tw/order/*" 409 | ], 410 | "run_at": "document_start", 411 | "js": [ 412 | "jquery.min.js", 413 | "js/ticketplus_order.js" 414 | ] 415 | }, 416 | { 417 | "matches": [ 418 | "https://kktix.com/" 419 | ], 420 | "run_at": "document_end", 421 | "js": [ 422 | "jquery.min.js", 423 | "js/kktix_home.js" 424 | ] 425 | }, 426 | { 427 | "matches": [ 428 | "https://*.kktix.cc/events/*" 429 | ], 430 | "run_at": "document_end", 431 | "js": [ 432 | "jquery.min.js", 433 | "js/kktix_events.js" 434 | ] 435 | }, 436 | { 437 | "matches": [ 438 | "https://kktix.com/events/*/registrations/new" 439 | ], 440 | "world": "MAIN", 441 | "run_at": "document_end", 442 | "js": [ 443 | "js/common.js", 444 | "js/kktix_registrations_assign.js" 445 | ] 446 | }, 447 | { 448 | "matches": [ 449 | "https://kktix.com/events/*/registrations/new" 450 | ], 451 | "run_at": "document_start", 452 | "js": [ 453 | "jquery.min.js", 454 | "js/kktix_registrations_reload.js" 455 | ] 456 | } 457 | ], 458 | "version": "1.0.25" 459 | } 460 | -------------------------------------------------------------------------------- /webdriver/Maxblockplus_1.0.0/dist/glyphicon/glyphicon.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family:'Glyphicons Halflings'; 3 | src:url(./fonts/glyphicons-halflings-regular.eot?#iefix) format(embedded-opentype), 4 | url(./fonts/glyphicons-halflings-regular.woff2) format(woff2), 5 | url(./fonts/glyphicons-halflings-regular.woff) format(woff); 6 | } 7 | 8 | .glyphicon { 9 | position:relative; 10 | top:1px; 11 | display:inline-block; 12 | font-family:'Glyphicons Halflings'; 13 | font-style:normal; 14 | font-weight:400; 15 | line-height:1; 16 | -webkit-font-smoothing:antialiased; 17 | -moz-osx-font-smoothing:grayscale; 18 | } 19 | 20 | .glyphicon-asterisk:before { 21 | content:"\2a"; 22 | } 23 | 24 | .glyphicon-plus:before { 25 | content:"\2b"; 26 | } 27 | 28 | .glyphicon-eur:before,.glyphicon-euro:before { 29 | content:"\20ac"; 30 | } 31 | 32 | .glyphicon-minus:before { 33 | content:"\2212"; 34 | } 35 | 36 | .glyphicon-cloud:before { 37 | content:"\2601"; 38 | } 39 | 40 | .glyphicon-envelope:before { 41 | content:"\2709"; 42 | } 43 | 44 | .glyphicon-pencil:before { 45 | content:"\270f"; 46 | } 47 | 48 | .glyphicon-glass:before { 49 | content:"\e001"; 50 | } 51 | 52 | .glyphicon-music:before { 53 | content:"\e002"; 54 | } 55 | 56 | .glyphicon-search:before { 57 | content:"\e003"; 58 | } 59 | 60 | .glyphicon-heart:before { 61 | content:"\e005"; 62 | } 63 | 64 | .glyphicon-star:before { 65 | content:"\e006"; 66 | } 67 | 68 | .glyphicon-star-empty:before { 69 | content:"\e007"; 70 | } 71 | 72 | .glyphicon-user:before { 73 | content:"\e008"; 74 | } 75 | 76 | .glyphicon-film:before { 77 | content:"\e009"; 78 | } 79 | 80 | .glyphicon-th-large:before { 81 | content:"\e010"; 82 | } 83 | 84 | .glyphicon-th:before { 85 | content:"\e011"; 86 | } 87 | 88 | .glyphicon-th-list:before { 89 | content:"\e012"; 90 | } 91 | 92 | .glyphicon-ok:before { 93 | content:"\e013"; 94 | } 95 | 96 | .glyphicon-remove:before { 97 | content:"\e014"; 98 | } 99 | 100 | .glyphicon-zoom-in:before { 101 | content:"\e015"; 102 | } 103 | 104 | .glyphicon-zoom-out:before { 105 | content:"\e016"; 106 | } 107 | 108 | .glyphicon-off:before { 109 | content:"\e017"; 110 | } 111 | 112 | .glyphicon-signal:before { 113 | content:"\e018"; 114 | } 115 | 116 | .glyphicon-cog:before { 117 | content:"\e019"; 118 | } 119 | 120 | .glyphicon-trash:before { 121 | content:"\e020"; 122 | } 123 | 124 | .glyphicon-home:before { 125 | content:"\e021"; 126 | } 127 | 128 | .glyphicon-file:before { 129 | content:"\e022"; 130 | } 131 | 132 | .glyphicon-time:before { 133 | content:"\e023"; 134 | } 135 | 136 | .glyphicon-road:before { 137 | content:"\e024"; 138 | } 139 | 140 | .glyphicon-download-alt:before { 141 | content:"\e025"; 142 | } 143 | 144 | .glyphicon-download:before { 145 | content:"\e026"; 146 | } 147 | 148 | .glyphicon-upload:before { 149 | content:"\e027"; 150 | } 151 | 152 | .glyphicon-inbox:before { 153 | content:"\e028"; 154 | } 155 | 156 | .glyphicon-play-circle:before { 157 | content:"\e029"; 158 | } 159 | 160 | .glyphicon-repeat:before { 161 | content:"\e030"; 162 | } 163 | 164 | .glyphicon-refresh:before { 165 | content:"\e031"; 166 | } 167 | 168 | .glyphicon-list-alt:before { 169 | content:"\e032"; 170 | } 171 | 172 | .glyphicon-lock:before { 173 | content:"\e033"; 174 | } 175 | 176 | .glyphicon-flag:before { 177 | content:"\e034"; 178 | } 179 | 180 | .glyphicon-headphones:before { 181 | content:"\e035"; 182 | } 183 | 184 | .glyphicon-volume-off:before { 185 | content:"\e036"; 186 | } 187 | 188 | .glyphicon-volume-down:before { 189 | content:"\e037"; 190 | } 191 | 192 | .glyphicon-volume-up:before { 193 | content:"\e038"; 194 | } 195 | 196 | .glyphicon-qrcode:before { 197 | content:"\e039"; 198 | } 199 | 200 | .glyphicon-barcode:before { 201 | content:"\e040"; 202 | } 203 | 204 | .glyphicon-tag:before { 205 | content:"\e041"; 206 | } 207 | 208 | .glyphicon-tags:before { 209 | content:"\e042"; 210 | } 211 | 212 | .glyphicon-book:before { 213 | content:"\e043"; 214 | } 215 | 216 | .glyphicon-bookmark:before { 217 | content:"\e044"; 218 | } 219 | 220 | .glyphicon-print:before { 221 | content:"\e045"; 222 | } 223 | 224 | .glyphicon-camera:before { 225 | content:"\e046"; 226 | } 227 | 228 | .glyphicon-font:before { 229 | content:"\e047"; 230 | } 231 | 232 | .glyphicon-bold:before { 233 | content:"\e048"; 234 | } 235 | 236 | .glyphicon-italic:before { 237 | content:"\e049"; 238 | } 239 | 240 | .glyphicon-text-height:before { 241 | content:"\e050"; 242 | } 243 | 244 | .glyphicon-text-width:before { 245 | content:"\e051"; 246 | } 247 | 248 | .glyphicon-align-left:before { 249 | content:"\e052"; 250 | } 251 | 252 | .glyphicon-align-center:before { 253 | content:"\e053"; 254 | } 255 | 256 | .glyphicon-align-right:before { 257 | content:"\e054"; 258 | } 259 | 260 | .glyphicon-align-justify:before { 261 | content:"\e055"; 262 | } 263 | 264 | .glyphicon-list:before { 265 | content:"\e056"; 266 | } 267 | 268 | .glyphicon-indent-left:before { 269 | content:"\e057"; 270 | } 271 | 272 | .glyphicon-indent-right:before { 273 | content:"\e058"; 274 | } 275 | 276 | .glyphicon-facetime-video:before { 277 | content:"\e059"; 278 | } 279 | 280 | .glyphicon-picture:before { 281 | content:"\e060"; 282 | } 283 | 284 | .glyphicon-map-marker:before { 285 | content:"\e062"; 286 | } 287 | 288 | .glyphicon-adjust:before { 289 | content:"\e063"; 290 | } 291 | 292 | .glyphicon-tint:before { 293 | content:"\e064"; 294 | } 295 | 296 | .glyphicon-edit:before { 297 | content:"\e065"; 298 | } 299 | 300 | .glyphicon-share:before { 301 | content:"\e066"; 302 | } 303 | 304 | .glyphicon-check:before { 305 | content:"\e067"; 306 | } 307 | 308 | .glyphicon-move:before { 309 | content:"\e068"; 310 | } 311 | 312 | .glyphicon-step-backward:before { 313 | content:"\e069"; 314 | } 315 | 316 | .glyphicon-fast-backward:before { 317 | content:"\e070"; 318 | } 319 | 320 | .glyphicon-backward:before { 321 | content:"\e071"; 322 | } 323 | 324 | .glyphicon-play:before { 325 | content:"\e072"; 326 | } 327 | 328 | .glyphicon-pause:before { 329 | content:"\e073"; 330 | } 331 | 332 | .glyphicon-stop:before { 333 | content:"\e074"; 334 | } 335 | 336 | .glyphicon-forward:before { 337 | content:"\e075"; 338 | } 339 | 340 | .glyphicon-fast-forward:before { 341 | content:"\e076"; 342 | } 343 | 344 | .glyphicon-step-forward:before { 345 | content:"\e077"; 346 | } 347 | 348 | .glyphicon-eject:before { 349 | content:"\e078"; 350 | } 351 | 352 | .glyphicon-chevron-left:before { 353 | content:"\e079"; 354 | } 355 | 356 | .glyphicon-chevron-right:before { 357 | content:"\e080"; 358 | } 359 | 360 | .glyphicon-plus-sign:before { 361 | content:"\e081"; 362 | } 363 | 364 | .glyphicon-minus-sign:before { 365 | content:"\e082"; 366 | } 367 | 368 | .glyphicon-remove-sign:before { 369 | content:"\e083"; 370 | } 371 | 372 | .glyphicon-ok-sign:before { 373 | content:"\e084"; 374 | } 375 | 376 | .glyphicon-question-sign:before { 377 | content:"\e085"; 378 | } 379 | 380 | .glyphicon-info-sign:before { 381 | content:"\e086"; 382 | } 383 | 384 | .glyphicon-screenshot:before { 385 | content:"\e087"; 386 | } 387 | 388 | .glyphicon-remove-circle:before { 389 | content:"\e088"; 390 | } 391 | 392 | .glyphicon-ok-circle:before { 393 | content:"\e089"; 394 | } 395 | 396 | .glyphicon-ban-circle:before { 397 | content:"\e090"; 398 | } 399 | 400 | .glyphicon-arrow-left:before { 401 | content:"\e091"; 402 | } 403 | 404 | .glyphicon-arrow-right:before { 405 | content:"\e092"; 406 | } 407 | 408 | .glyphicon-arrow-up:before { 409 | content:"\e093"; 410 | } 411 | 412 | .glyphicon-arrow-down:before { 413 | content:"\e094"; 414 | } 415 | 416 | .glyphicon-share-alt:before { 417 | content:"\e095"; 418 | } 419 | 420 | .glyphicon-resize-full:before { 421 | content:"\e096"; 422 | } 423 | 424 | .glyphicon-resize-small:before { 425 | content:"\e097"; 426 | } 427 | 428 | .glyphicon-exclamation-sign:before { 429 | content:"\e101"; 430 | } 431 | 432 | .glyphicon-gift:before { 433 | content:"\e102"; 434 | } 435 | 436 | .glyphicon-leaf:before { 437 | content:"\e103"; 438 | } 439 | 440 | .glyphicon-fire:before { 441 | content:"\e104"; 442 | } 443 | 444 | .glyphicon-eye-open:before { 445 | content:"\e105"; 446 | } 447 | 448 | .glyphicon-eye-close:before { 449 | content:"\e106"; 450 | } 451 | 452 | .glyphicon-warning-sign:before { 453 | content:"\e107"; 454 | } 455 | 456 | .glyphicon-plane:before { 457 | content:"\e108"; 458 | } 459 | 460 | .glyphicon-calendar:before { 461 | content:"\e109"; 462 | } 463 | 464 | .glyphicon-random:before { 465 | content:"\e110"; 466 | } 467 | 468 | .glyphicon-comment:before { 469 | content:"\e111"; 470 | } 471 | 472 | .glyphicon-magnet:before { 473 | content:"\e112"; 474 | } 475 | 476 | .glyphicon-chevron-up:before { 477 | content:"\e113"; 478 | } 479 | 480 | .glyphicon-chevron-down:before { 481 | content:"\e114"; 482 | } 483 | 484 | .glyphicon-retweet:before { 485 | content:"\e115"; 486 | } 487 | 488 | .glyphicon-shopping-cart:before { 489 | content:"\e116"; 490 | } 491 | 492 | .glyphicon-folder-close:before { 493 | content:"\e117"; 494 | } 495 | 496 | .glyphicon-folder-open:before { 497 | content:"\e118"; 498 | } 499 | 500 | .glyphicon-resize-vertical:before { 501 | content:"\e119"; 502 | } 503 | 504 | .glyphicon-resize-horizontal:before { 505 | content:"\e120"; 506 | } 507 | 508 | .glyphicon-hdd:before { 509 | content:"\e121"; 510 | } 511 | 512 | .glyphicon-bullhorn:before { 513 | content:"\e122"; 514 | } 515 | 516 | .glyphicon-bell:before { 517 | content:"\e123"; 518 | } 519 | 520 | .glyphicon-certificate:before { 521 | content:"\e124"; 522 | } 523 | 524 | .glyphicon-thumbs-up:before { 525 | content:"\e125"; 526 | } 527 | 528 | .glyphicon-thumbs-down:before { 529 | content:"\e126"; 530 | } 531 | 532 | .glyphicon-hand-right:before { 533 | content:"\e127"; 534 | } 535 | 536 | .glyphicon-hand-left:before { 537 | content:"\e128"; 538 | } 539 | 540 | .glyphicon-hand-up:before { 541 | content:"\e129"; 542 | } 543 | 544 | .glyphicon-hand-down:before { 545 | content:"\e130"; 546 | } 547 | 548 | .glyphicon-circle-arrow-right:before { 549 | content:"\e131"; 550 | } 551 | 552 | .glyphicon-circle-arrow-left:before { 553 | content:"\e132"; 554 | } 555 | 556 | .glyphicon-circle-arrow-up:before { 557 | content:"\e133"; 558 | } 559 | 560 | .glyphicon-circle-arrow-down:before { 561 | content:"\e134"; 562 | } 563 | 564 | .glyphicon-globe:before { 565 | content:"\e135"; 566 | } 567 | 568 | .glyphicon-wrench:before { 569 | content:"\e136"; 570 | } 571 | 572 | .glyphicon-tasks:before { 573 | content:"\e137"; 574 | } 575 | 576 | .glyphicon-filter:before { 577 | content:"\e138"; 578 | } 579 | 580 | .glyphicon-briefcase:before { 581 | content:"\e139"; 582 | } 583 | 584 | .glyphicon-fullscreen:before { 585 | content:"\e140"; 586 | } 587 | 588 | .glyphicon-dashboard:before { 589 | content:"\e141"; 590 | } 591 | 592 | .glyphicon-paperclip:before { 593 | content:"\e142"; 594 | } 595 | 596 | .glyphicon-heart-empty:before { 597 | content:"\e143"; 598 | } 599 | 600 | .glyphicon-link:before { 601 | content:"\e144"; 602 | } 603 | 604 | .glyphicon-phone:before { 605 | content:"\e145"; 606 | } 607 | 608 | .glyphicon-pushpin:before { 609 | content:"\e146"; 610 | } 611 | 612 | .glyphicon-usd:before { 613 | content:"\e148"; 614 | } 615 | 616 | .glyphicon-gbp:before { 617 | content:"\e149"; 618 | } 619 | 620 | .glyphicon-sort:before { 621 | content:"\e150"; 622 | } 623 | 624 | .glyphicon-sort-by-alphabet:before { 625 | content:"\e151"; 626 | } 627 | 628 | .glyphicon-sort-by-alphabet-alt:before { 629 | content:"\e152"; 630 | } 631 | 632 | .glyphicon-sort-by-order:before { 633 | content:"\e153"; 634 | } 635 | 636 | .glyphicon-sort-by-order-alt:before { 637 | content:"\e154"; 638 | } 639 | 640 | .glyphicon-sort-by-attributes:before { 641 | content:"\e155"; 642 | } 643 | 644 | .glyphicon-sort-by-attributes-alt:before { 645 | content:"\e156"; 646 | } 647 | 648 | .glyphicon-unchecked:before { 649 | content:"\e157"; 650 | } 651 | 652 | .glyphicon-expand:before { 653 | content:"\e158"; 654 | } 655 | 656 | .glyphicon-collapse-down:before { 657 | content:"\e159"; 658 | } 659 | 660 | .glyphicon-collapse-up:before { 661 | content:"\e160"; 662 | } 663 | 664 | .glyphicon-log-in:before { 665 | content:"\e161"; 666 | } 667 | 668 | .glyphicon-flash:before { 669 | content:"\e162"; 670 | } 671 | 672 | .glyphicon-log-out:before { 673 | content:"\e163"; 674 | } 675 | 676 | .glyphicon-new-window:before { 677 | content:"\e164"; 678 | } 679 | 680 | .glyphicon-record:before { 681 | content:"\e165"; 682 | } 683 | 684 | .glyphicon-save:before { 685 | content:"\e166"; 686 | } 687 | 688 | .glyphicon-open:before { 689 | content:"\e167"; 690 | } 691 | 692 | .glyphicon-saved:before { 693 | content:"\e168"; 694 | } 695 | 696 | .glyphicon-import:before { 697 | content:"\e169"; 698 | } 699 | 700 | .glyphicon-export:before { 701 | content:"\e170"; 702 | } 703 | 704 | .glyphicon-send:before { 705 | content:"\e171"; 706 | } 707 | 708 | .glyphicon-floppy-disk:before { 709 | content:"\e172"; 710 | } 711 | 712 | .glyphicon-floppy-saved:before { 713 | content:"\e173"; 714 | } 715 | 716 | .glyphicon-floppy-remove:before { 717 | content:"\e174"; 718 | } 719 | 720 | .glyphicon-floppy-save:before { 721 | content:"\e175"; 722 | } 723 | 724 | .glyphicon-floppy-open:before { 725 | content:"\e176"; 726 | } 727 | 728 | .glyphicon-credit-card:before { 729 | content:"\e177"; 730 | } 731 | 732 | .glyphicon-transfer:before { 733 | content:"\e178"; 734 | } 735 | 736 | .glyphicon-cutlery:before { 737 | content:"\e179"; 738 | } 739 | 740 | .glyphicon-header:before { 741 | content:"\e180"; 742 | } 743 | 744 | .glyphicon-compressed:before { 745 | content:"\e181"; 746 | } 747 | 748 | .glyphicon-earphone:before { 749 | content:"\e182"; 750 | } 751 | 752 | .glyphicon-phone-alt:before { 753 | content:"\e183"; 754 | } 755 | 756 | .glyphicon-tower:before { 757 | content:"\e184"; 758 | } 759 | 760 | .glyphicon-stats:before { 761 | content:"\e185"; 762 | } 763 | 764 | .glyphicon-sd-video:before { 765 | content:"\e186"; 766 | } 767 | 768 | .glyphicon-hd-video:before { 769 | content:"\e187"; 770 | } 771 | 772 | .glyphicon-subtitles:before { 773 | content:"\e188"; 774 | } 775 | 776 | .glyphicon-sound-stereo:before { 777 | content:"\e189"; 778 | } 779 | 780 | .glyphicon-sound-dolby:before { 781 | content:"\e190"; 782 | } 783 | 784 | .glyphicon-sound-5-1:before { 785 | content:"\e191"; 786 | } 787 | 788 | .glyphicon-sound-6-1:before { 789 | content:"\e192"; 790 | } 791 | 792 | .glyphicon-sound-7-1:before { 793 | content:"\e193"; 794 | } 795 | 796 | .glyphicon-copyright-mark:before { 797 | content:"\e194"; 798 | } 799 | 800 | .glyphicon-registration-mark:before { 801 | content:"\e195"; 802 | } 803 | 804 | .glyphicon-cloud-download:before { 805 | content:"\e197"; 806 | } 807 | 808 | .glyphicon-cloud-upload:before { 809 | content:"\e198"; 810 | } 811 | 812 | .glyphicon-tree-conifer:before { 813 | content:"\e199"; 814 | } 815 | 816 | .glyphicon-tree-deciduous:before { 817 | content:"\e200"; 818 | } 819 | 820 | .glyphicon-cd:before { 821 | content:"\e201"; 822 | } 823 | 824 | .glyphicon-save-file:before { 825 | content:"\e202"; 826 | } 827 | 828 | .glyphicon-open-file:before { 829 | content:"\e203"; 830 | } 831 | 832 | .glyphicon-level-up:before { 833 | content:"\e204"; 834 | } 835 | 836 | .glyphicon-copy:before { 837 | content:"\e205"; 838 | } 839 | 840 | .glyphicon-paste:before { 841 | content:"\e206"; 842 | } 843 | 844 | .glyphicon-alert:before { 845 | content:"\e209"; 846 | } 847 | 848 | .glyphicon-equalizer:before { 849 | content:"\e210"; 850 | } 851 | 852 | .glyphicon-king:before { 853 | content:"\e211"; 854 | } 855 | 856 | .glyphicon-queen:before { 857 | content:"\e212"; 858 | } 859 | 860 | .glyphicon-pawn:before { 861 | content:"\e213"; 862 | } 863 | 864 | .glyphicon-bishop:before { 865 | content:"\e214"; 866 | } 867 | 868 | .glyphicon-knight:before { 869 | content:"\e215"; 870 | } 871 | 872 | .glyphicon-baby-formula:before { 873 | content:"\e216"; 874 | } 875 | 876 | .glyphicon-tent:before { 877 | content:"\26fa"; 878 | } 879 | 880 | .glyphicon-blackboard:before { 881 | content:"\e218"; 882 | } 883 | 884 | .glyphicon-bed:before { 885 | content:"\e219"; 886 | } 887 | 888 | .glyphicon-apple:before { 889 | content:"\f8ff"; 890 | } 891 | 892 | .glyphicon-erase:before { 893 | content:"\e221"; 894 | } 895 | 896 | .glyphicon-hourglass:before { 897 | content:"\231b"; 898 | } 899 | 900 | .glyphicon-lamp:before { 901 | content:"\e223"; 902 | } 903 | 904 | .glyphicon-duplicate:before { 905 | content:"\e224"; 906 | } 907 | 908 | .glyphicon-piggy-bank:before { 909 | content:"\e225"; 910 | } 911 | 912 | .glyphicon-scissors:before { 913 | content:"\e226"; 914 | } 915 | 916 | .glyphicon-scale:before { 917 | content:"\e230"; 918 | } 919 | 920 | .glyphicon-ice-lolly:before { 921 | content:"\e231"; 922 | } 923 | 924 | .glyphicon-ice-lolly-tasted:before { 925 | content:"\e232"; 926 | } 927 | 928 | .glyphicon-education:before { 929 | content:"\e233"; 930 | } 931 | 932 | .glyphicon-option-horizontal:before { 933 | content:"\e234"; 934 | } 935 | 936 | .glyphicon-option-vertical:before { 937 | content:"\e235"; 938 | } 939 | 940 | .glyphicon-menu-hamburger:before { 941 | content:"\e236"; 942 | } 943 | 944 | .glyphicon-modal-window:before { 945 | content:"\e237"; 946 | } 947 | 948 | .glyphicon-oil:before { 949 | content:"\e238"; 950 | } 951 | 952 | .glyphicon-grain:before { 953 | content:"\e239"; 954 | } 955 | 956 | .glyphicon-sunglasses:before { 957 | content:"\e240"; 958 | } 959 | 960 | .glyphicon-text-size:before { 961 | content:"\e241"; 962 | } 963 | 964 | .glyphicon-text-color:before { 965 | content:"\e242"; 966 | } 967 | 968 | .glyphicon-text-background:before { 969 | content:"\e243"; 970 | } 971 | 972 | .glyphicon-object-align-top:before { 973 | content:"\e244"; 974 | } 975 | 976 | .glyphicon-object-align-bottom:before { 977 | content:"\e245"; 978 | } 979 | 980 | .glyphicon-object-align-horizontal:before { 981 | content:"\e246"; 982 | } 983 | 984 | .glyphicon-object-align-left:before { 985 | content:"\e247"; 986 | } 987 | 988 | .glyphicon-object-align-vertical:before { 989 | content:"\e248"; 990 | } 991 | 992 | .glyphicon-object-align-right:before { 993 | content:"\e249"; 994 | } 995 | 996 | .glyphicon-triangle-right:before { 997 | content:"\e250"; 998 | } 999 | 1000 | .glyphicon-triangle-left:before { 1001 | content:"\e251"; 1002 | } 1003 | 1004 | .glyphicon-triangle-bottom:before { 1005 | content:"\e252"; 1006 | } 1007 | 1008 | .glyphicon-triangle-top:before { 1009 | content:"\e253"; 1010 | } 1011 | 1012 | .glyphicon-console:before { 1013 | content:"\e254"; 1014 | } 1015 | 1016 | .glyphicon-superscript:before { 1017 | content:"\e255"; 1018 | } 1019 | 1020 | .glyphicon-subscript:before { 1021 | content:"\e256"; 1022 | } 1023 | 1024 | .glyphicon-menu-left:before { 1025 | content:"\e257"; 1026 | } 1027 | 1028 | .glyphicon-menu-right:before { 1029 | content:"\e258"; 1030 | } 1031 | 1032 | .glyphicon-menu-down:before { 1033 | content:"\e259"; 1034 | } 1035 | 1036 | .glyphicon-menu-up:before { 1037 | content:"\e260"; 1038 | } 1039 | --------------------------------------------------------------------------------