From 448d4d01aad919aa95f60ba1ff05a3e521c71bd1 Mon Sep 17 00:00:00 2001 From: tegrak Date: Mon, 29 Aug 2022 11:45:58 +0900 Subject: [PATCH 01/38] ignore confirm in fn_chkPeople() --- content.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/content.js b/content.js index d261bcc..27202eb 100644 --- a/content.js +++ b/content.js @@ -219,4 +219,17 @@ const saveCheckboxState = () => { createCheckbox(); setCheckboxEvent(); + + //인원 확인 컨펌 무시 + var s = document.createElement('script'); + s.innerHTML = + "const origin_confirm = confirm;" + + "confirm = function(message){" + + "console.log('confirm: ' + message);" + + "if (message.indexOf('맞습니까') != -1) {" + + "return true;" + + "}" + + "return origin_confirm(message);" + + "};"; + document.body.appendChild(s); })(); From 6899ab136b6f823e345e59146ab0898d194f20e7 Mon Sep 17 00:00:00 2001 From: tegrak Date: Wed, 31 Aug 2022 11:36:02 +0900 Subject: [PATCH 02/38] check all button --- content.css | 36 +++-- content.js | 402 +++++++++++++++++++++++++++------------------------- 2 files changed, 234 insertions(+), 204 deletions(-) diff --git a/content.css b/content.css index 4974556..710f3b6 100644 --- a/content.css +++ b/content.css @@ -1,13 +1,27 @@ .ktx-macro-button { - width: 175px; - height: 38px; - line-height: 38px; - text-align: center; - background: #f46b45; - background: -webkit-linear-gradient(to bottom, #eea849, #f46b45); - background: linear-gradient(to bottom, #eea849, #f46b45); - color: #ffffff; - font-size: 13px; - border: 1px solid #f76707; - cursor: pointer; + width: 175px; + height: 38px; + line-height: 38px; + text-align: center; + background: #f46b45; + background: -webkit-linear-gradient(to bottom, #eea849, #f46b45); + background: linear-gradient(to bottom, #eea849, #f46b45); + color: #ffffff; + font-size: 13px; + border: 1px solid #f76707; + cursor: pointer; +} + +.check-all-button { + width: 175px; + height: 38px; + line-height: 38px; + text-align: center; + background: #f46b45; + background: -webkit-linear-gradient(to bottom, #eea849, #f46b45); + background: linear-gradient(to bottom, #eea849, #f46b45); + color: #ffffff; + font-size: 13px; + border: 1px solid #f76707; + cursor: pointer; } \ No newline at end of file diff --git a/content.js b/content.js index 27202eb..e21c611 100644 --- a/content.js +++ b/content.js @@ -3,233 +3,249 @@ const MAIN_URI = "https://www.letskorail.com/ebizprd/EbizPrdTicketPr21111_i1.do" const LOGIN_PAGE_URI = "https://www.letskorail.com/korail/com/login.do"; const createCheckbox = () => { - const $rows = document.querySelectorAll("#tableResult > tbody > tr"); - - if (!$rows.length) { - return; - } - - $rows.forEach($row => { - $row - .querySelector("td:nth-child(5)") - .insertAdjacentHTML("beforeend", getCheckboxTemplate(uid++)); - $row - .querySelector("td:nth-child(6)") - .insertAdjacentHTML("beforeend", getCheckboxTemplate(uid++)); - $row - .querySelector("td:nth-child(10)") - .insertAdjacentHTML("beforeend", getCheckboxTemplate(uid++)); - }); + const $rows = document.querySelectorAll("#tableResult > tbody > tr"); + + if (!$rows.length) { + return; + } + + $rows.forEach($row => { + $row + .querySelector("td:nth-child(5)") + .insertAdjacentHTML("beforeend", getCheckboxTemplate(uid++)); + $row + .querySelector("td:nth-child(6)") + .insertAdjacentHTML("beforeend", getCheckboxTemplate(uid++)); + $row + .querySelector("td:nth-child(10)") + .insertAdjacentHTML("beforeend", getCheckboxTemplate(uid++)); + }); }; const isChecked = uid => { - const checkedItemsStr = localStorage.getItem("checkedItems"); - const checkedItems = checkedItemsStr ? checkedItemsStr.split(",") : []; + const checkedItemsStr = localStorage.getItem("checkedItems"); + const checkedItems = checkedItemsStr ? checkedItemsStr.split(",") : []; - if (!checkedItems.length) { - return false; - } + if (!checkedItems.length) { + return false; + } - return checkedItems.includes(String(uid)); + return checkedItems.includes(String(uid)); }; const isLogin = () => !!document.querySelectorAll(".gnb_list > .log_nm").length; const getCheckboxTemplate = uid => { - if (!uid) { - return; - } - - return ` -
- -
- `; + if (!uid) { + return; + } + + return ` +
+ +
+ `; }; const setCheckboxEvent = () => { - const $checkboxes = document.querySelectorAll(".ktx-macro-checkbox"); + const $checkboxes = document.querySelectorAll(".ktx-macro-checkbox"); - for (let i = 0; i < $checkboxes.length; i++) { - $checkboxes[i].addEventListener("click", () => { - saveCheckboxState(); - }); - } + for (let i = 0; i < $checkboxes.length; i++) { + $checkboxes[i].addEventListener("click", () => { + saveCheckboxState(); + }); + } }; const setEscapeEvent = () => { - window.addEventListener("keydown", e => { - if (e.key === "Escape") { - macroStop(); - } - }); + window.addEventListener("keydown", e => { + if (e.key === "Escape") { + macroStop(); + } + }); }; const macroStart = () => { - if (!isLogin()) { - if (confirm("로그인이 필요합니다.\n로그인 페이지로 이동하시겠습니까?")) { - location.href = LOGIN_PAGE_URI; - } - return; - } - - if (!localStorage.getItem("checkedItems")) { - alert("선택 된 항목이 없습니다.\n1개 이상 선택해주세요."); - return; - } - - alert( - "자동 예매를 시작합니다.\n" + - "예매 성공 후 20분내에 결제하지 않을 경우 자동으로 예매가 취소됩니다.\n" + - "자동 예매 종료는 '자동 예매 정지' 혹은 esc키를 눌러주세요." - ); - - localStorage.setItem("macro", "on"); - - reload(); + if (!isLogin()) { + if (confirm("로그인이 필요합니다.\n로그인 페이지로 이동하시겠습니까?")) { + location.href = LOGIN_PAGE_URI; + } + return; + } + + if (!localStorage.getItem("checkedItems")) { + alert("선택 된 항목이 없습니다.\n1개 이상 선택해주세요."); + return; + } + + alert( + "자동 예매를 시작합니다.\n" + + "예매 성공 후 20분내에 결제하지 않을 경우 자동으로 예매가 취소됩니다.\n" + + "자동 예매 종료는 '자동 예매 정지' 혹은 esc키를 눌러주세요." + ); + + localStorage.setItem("macro", "on"); + + reload(); }; const macroStop = () => { - alert("자동 예매를 종료합니다."); - localStorage.removeItem("macro"); - localStorage.removeItem("checkedItems"); + alert("자동 예매를 종료합니다."); + localStorage.removeItem("macro"); + localStorage.removeItem("checkedItems"); - reload(); + reload(); }; const macro = () => { - let uid = 0; - let $row; - const $rows = document.querySelectorAll("#tableResult > tbody > tr"); - const len = $rows.length; - - if (!len) { - return; - } - - for (let i = 0; i < len; i++) { - $row = $rows[i]; - - if (isChecked(++uid)) { - $row.querySelector("td:nth-child(5)").style.backgroundColor = "#f03e3e"; - const $button = - $row - .querySelector("td:nth-child(5)") - .querySelector('[src="/docs/2007/img/common/icon_apm_bl.gif"]') || - $row - .querySelector("td:nth-child(5)") - .querySelector('[src="/docs/2007/img/common/icon_apm_rd.gif"]'); - - if ($button) { - $button.closest("a").click(); - localStorage.removeItem("macro"); - chrome.extension.sendMessage({ type: "successTicketing" }); - break; - } - } - - if (isChecked(++uid)) { - $row.querySelector("td:nth-child(6)").style.backgroundColor = "#f03e3e"; - const $button = - $row - .querySelector("td:nth-child(6)") - .querySelector('[src="/docs/2007/img/common/icon_apm_bl.gif"]') || - $row - .querySelector("td:nth-child(6)") - .querySelector('[src="/docs/2007/img/common/icon_apm_rd.gif"]'); - - if ($button) { - $button.closest("a").click(); - localStorage.removeItem("macro"); - chrome.extension.sendMessage({ type: "successTicketing" }); - break; - } - } - - if (isChecked(++uid)) { - $row.querySelector("td:nth-child(10)").style.backgroundColor = "#f03e3e"; - const $button = $row.querySelector("td:nth-child(10)") - .querySelector('[src="/docs/2007/img/common/icon_wait.gif"]'); - - if ($button) { - $button.closest("a").click(); - localStorage.removeItem("macro"); - chrome.extension.sendMessage({ type: "successTicketing" }); - break; - } - } - } - - setTimeout(reload, 1000); + let uid = 0; + let $row; + const $rows = document.querySelectorAll("#tableResult > tbody > tr"); + const len = $rows.length; + + if (!len) { + return; + } + + for (let i = 0; i < len; i++) { + $row = $rows[i]; + + if (isChecked(++uid)) { + $row.querySelector("td:nth-child(5)").style.backgroundColor = "#f03e3e"; + const $button = + $row + .querySelector("td:nth-child(5)") + .querySelector('[src="/docs/2007/img/common/icon_apm_bl.gif"]') || + $row + .querySelector("td:nth-child(5)") + .querySelector('[src="/docs/2007/img/common/icon_apm_rd.gif"]'); + + if ($button) { + $button.closest("a").click(); + localStorage.removeItem("macro"); + chrome.extension.sendMessage({ type: "successTicketing" }); + break; + } + } + + if (isChecked(++uid)) { + $row.querySelector("td:nth-child(6)").style.backgroundColor = "#f03e3e"; + const $button = + $row + .querySelector("td:nth-child(6)") + .querySelector('[src="/docs/2007/img/common/icon_apm_bl.gif"]') || + $row + .querySelector("td:nth-child(6)") + .querySelector('[src="/docs/2007/img/common/icon_apm_rd.gif"]'); + + if ($button) { + $button.closest("a").click(); + localStorage.removeItem("macro"); + chrome.extension.sendMessage({ type: "successTicketing" }); + break; + } + } + + if (isChecked(++uid)) { + $row.querySelector("td:nth-child(10)").style.backgroundColor = "#f03e3e"; + const $button = $row.querySelector("td:nth-child(10)") + .querySelector('[src="/docs/2007/img/common/icon_wait.gif"]'); + + if ($button) { + $button.closest("a").click(); + localStorage.removeItem("macro"); + chrome.extension.sendMessage({ type: "successTicketing" }); + break; + } + } + } + + setTimeout(reload, 1000); }; const reload = () => { - document.querySelector(".btn_inq > a").click(); + document.querySelector(".btn_inq > a").click(); }; const saveCheckboxState = () => { - let checkedItems = []; - const $checkboxes = document.querySelectorAll(".ktx-macro-checkbox"); - - for (let i = 0; i < $checkboxes.length; i++) { - if ($checkboxes[i].checked) { - checkedItems.push($checkboxes[i].value); - } - } - - if (checkedItems.length) { - localStorage.setItem("checkedItems", checkedItems.join(",")); - } else { - localStorage.removeItem("checkedItems"); - } + let checkedItems = []; + const $checkboxes = document.querySelectorAll(".ktx-macro-checkbox"); + + for (let i = 0; i < $checkboxes.length; i++) { + if ($checkboxes[i].checked) { + checkedItems.push($checkboxes[i].value); + } + } + + if (checkedItems.length) { + localStorage.setItem("checkedItems", checkedItems.join(",")); + } else { + localStorage.removeItem("checkedItems"); + } +}; + +const checkAllCheckbox = () => { + var i; + var list = document.querySelectorAll(".ktx-macro-checkbox"); + for (i = 0; i < list.length; i++) { + list[i].checked = true; + } + saveCheckboxState(); }; (() => { - if ( - !document.querySelector(".btn_inq") || - !location.href.startsWith(MAIN_URI) - ) { - return; - } - - const isStarted = localStorage.getItem("macro") === "on"; - - if (isStarted) { - macro(); - setEscapeEvent(); - } else { - localStorage.removeItem("checkedItems"); - } - - document.querySelector(".btn_inq").insertAdjacentHTML( - "beforeend", - ` - - ` - ); - - document - .querySelector(".ktx-macro-button") - .addEventListener("click", isStarted ? macroStop : macroStart); - - createCheckbox(); - setCheckboxEvent(); - - //인원 확인 컨펌 무시 - var s = document.createElement('script'); - s.innerHTML = - "const origin_confirm = confirm;" + - "confirm = function(message){" + - "console.log('confirm: ' + message);" + - "if (message.indexOf('맞습니까') != -1) {" + - "return true;" + - "}" + - "return origin_confirm(message);" + - "};"; - document.body.appendChild(s); + if ( + !document.querySelector(".btn_inq") || + !location.href.startsWith(MAIN_URI) + ) { + return; + } + + const isStarted = localStorage.getItem("macro") === "on"; + + if (isStarted) { + macro(); + setEscapeEvent(); + } else { + localStorage.removeItem("checkedItems"); + } + + document.querySelector(".btn_inq").insertAdjacentHTML( + "beforeend", + ` + + + ` + ); + + document + .querySelector(".ktx-macro-button") + .addEventListener("click", isStarted ? macroStop : macroStart); + + document + .querySelector(".check-all-button") + .addEventListener("click", checkAllCheckbox); + + createCheckbox(); + setCheckboxEvent(); + + //인원 확인 컨펌 무시 + var s = document.createElement('script'); + s.innerHTML = + "const origin_confirm = confirm;" + + "confirm = function(message){" + + "console.log('confirm: ' + message);" + + "if (message.indexOf('맞습니까') != -1) {" + + "return true;" + + "}" + + "return origin_confirm(message);" + + "};"; + document.body.appendChild(s); })(); From a58675e6d2e62f81677e8e2c31fc27ffcd55349c Mon Sep 17 00:00:00 2001 From: tegrak Date: Wed, 31 Aug 2022 11:39:03 +0900 Subject: [PATCH 03/38] adjust size of check-all-button --- content.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/content.css b/content.css index 710f3b6..f72acd3 100644 --- a/content.css +++ b/content.css @@ -13,7 +13,8 @@ } .check-all-button { - width: 175px; + padding-left: 10px; + padding-right: 10px; height: 38px; line-height: 38px; text-align: center; From e3fb34e885886ac031388c62f91d90a87a569b58 Mon Sep 17 00:00:00 2001 From: tegrak Date: Wed, 31 Aug 2022 12:26:09 +0900 Subject: [PATCH 04/38] prevent reloading while ticketing --- content.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/content.js b/content.js index e21c611..8f6bf0b 100644 --- a/content.js +++ b/content.js @@ -105,6 +105,7 @@ const macro = () => { let $row; const $rows = document.querySelectorAll("#tableResult > tbody > tr"); const len = $rows.length; + var succeeded = false; if (!len) { return; @@ -127,6 +128,7 @@ const macro = () => { $button.closest("a").click(); localStorage.removeItem("macro"); chrome.extension.sendMessage({ type: "successTicketing" }); + succeeded = true; break; } } @@ -145,6 +147,7 @@ const macro = () => { $button.closest("a").click(); localStorage.removeItem("macro"); chrome.extension.sendMessage({ type: "successTicketing" }); + succeeded = true; break; } } @@ -158,12 +161,14 @@ const macro = () => { $button.closest("a").click(); localStorage.removeItem("macro"); chrome.extension.sendMessage({ type: "successTicketing" }); + succeeded = true; break; } } } - setTimeout(reload, 1000); + if (!succeeded) + setTimeout(reload, 1000); }; const reload = () => { From 79957fdf2cf38f69175cde88dc556820f3297f6d Mon Sep 17 00:00:00 2001 From: tegrak Date: Wed, 31 Aug 2022 13:54:13 +0900 Subject: [PATCH 05/38] auto close popup --- content.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/content.js b/content.js index 8f6bf0b..d5aa213 100644 --- a/content.js +++ b/content.js @@ -1,6 +1,7 @@ let uid = 1; const MAIN_URI = "https://www.letskorail.com/ebizprd/EbizPrdTicketPr21111_i1.do"; const LOGIN_PAGE_URI = "https://www.letskorail.com/korail/com/login.do"; +const POPUP_URI = "https://www.letskorail.com/docs/pz/pz_msg_pop1.jsp"; const createCheckbox = () => { const $rows = document.querySelectorAll("#tableResult > tbody > tr"); @@ -202,6 +203,21 @@ const checkAllCheckbox = () => { }; (() => { + if (location.href.startsWith(POPUP_URI) && document.querySelector(".btn_blue_ang")) { + var s = document.createElement('script'); + s.innerHTML = ` + window.onload = function () { + var btn_blue_ang = document.querySelector('.btn_blue_ang'); + if (btn_blue_ang.text.indexOf('예매 계속 진행하기') != -1) { + console.log('close popup'); + setTimeout(f_close, 1000); + } + }; + `; + document.body.appendChild(s); + return; + } + if ( !document.querySelector(".btn_inq") || !location.href.startsWith(MAIN_URI) From 63983021b08a4b53d40ee820c7e169573394e87f Mon Sep 17 00:00:00 2001 From: tegrak Date: Wed, 31 Aug 2022 14:17:54 +0900 Subject: [PATCH 06/38] remove window.onload when closing popup --- content.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/content.js b/content.js index d5aa213..04baa00 100644 --- a/content.js +++ b/content.js @@ -206,12 +206,10 @@ const checkAllCheckbox = () => { if (location.href.startsWith(POPUP_URI) && document.querySelector(".btn_blue_ang")) { var s = document.createElement('script'); s.innerHTML = ` - window.onload = function () { - var btn_blue_ang = document.querySelector('.btn_blue_ang'); - if (btn_blue_ang.text.indexOf('예매 계속 진행하기') != -1) { - console.log('close popup'); - setTimeout(f_close, 1000); - } + var btn_blue_ang = document.querySelector('.btn_blue_ang'); + if (btn_blue_ang.text.indexOf('예매 계속 진행하기') != -1) { + console.log('close popup'); + setTimeout(f_close, 1000); }; `; document.body.appendChild(s); From 7fe6e5eb4f4d06913c5f4ba8f1194f88a5f696ef Mon Sep 17 00:00:00 2001 From: TEGRAK Date: Thu, 1 Sep 2022 00:29:56 +0900 Subject: [PATCH 07/38] add ignoreConfirmPeople() add ignoreDailyPopup() --- content.js | 48 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/content.js b/content.js index 04baa00..081f5b2 100644 --- a/content.js +++ b/content.js @@ -176,6 +176,34 @@ const reload = () => { document.querySelector(".btn_inq > a").click(); }; +//인원 확인 컨펌 무시 +const ignoreConfirmPeople = () => { + var s = document.createElement('script'); + s.innerHTML = ` + const origin_confirm = confirm; + confirm = function (message) { + console.log('confirm: ' + message); + if (message.indexOf('맞습니까') != -1) { + return true; + } + return origin_confirm(message); + } + `; + document.body.appendChild(s); +} + +//일일 팝업 무시 +const ignoreDailyPopup = () => { + var s = document.createElement('script'); + s.innerHTML = `; + if (typeof('openGwangjuShuttleDialog') != 'undefined') { + console.log('disable openGwangjuShuttleDialog'); + openGwangjuShuttleDialog = function () {}; + } + `; + document.body.appendChild(s); +} + const saveCheckboxState = () => { let checkedItems = []; const $checkboxes = document.querySelectorAll(".ktx-macro-checkbox"); @@ -203,7 +231,10 @@ const checkAllCheckbox = () => { }; (() => { - if (location.href.startsWith(POPUP_URI) && document.querySelector(".btn_blue_ang")) { + if (location.href.startsWith(POPUP_URI)) { + if (!document.querySelector(".btn_blue_ang")) + return; + var s = document.createElement('script'); s.innerHTML = ` var btn_blue_ang = document.querySelector('.btn_blue_ang'); @@ -254,17 +285,6 @@ const checkAllCheckbox = () => { createCheckbox(); setCheckboxEvent(); - - //인원 확인 컨펌 무시 - var s = document.createElement('script'); - s.innerHTML = - "const origin_confirm = confirm;" + - "confirm = function(message){" + - "console.log('confirm: ' + message);" + - "if (message.indexOf('맞습니까') != -1) {" + - "return true;" + - "}" + - "return origin_confirm(message);" + - "};"; - document.body.appendChild(s); + ignoreConfirmPeople(); + ignoreDailyPopup(); })(); From 00bd3d3754807f809f8da03bdfad4a336d23e22c Mon Sep 17 00:00:00 2001 From: tegrak Date: Thu, 1 Sep 2022 01:12:59 +0900 Subject: [PATCH 08/38] add ignoreNonestopPopup() and fix ignoreDailyPopup() --- content.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/content.js b/content.js index 081f5b2..739c5bd 100644 --- a/content.js +++ b/content.js @@ -176,6 +176,23 @@ const reload = () => { document.querySelector(".btn_inq > a").click(); }; +//nonstop 팝업 무시 +const ignoreNonstopPopup = () => { + var s = document.createElement('script'); + s.innerHTML = ` + if (typeof(Nopeople2) == 'function') { + console.log('disable Nopeople2'); + const originNopeople2 = Nopeople2; + Nopeople2 = function (intPsrm, intIdxNo, iAddInfo4, callback) { + console.log('remove h_nonstop_msg. ' + train[intIdxNo].h_nonstop_msg); + train[intIdxNo].h_nonstop_msg = ''; + return originNopeople2(intPsrm, intIdxNo, iAddInfo4, callback); + } + } + `; + document.body.appendChild(s); +} + //인원 확인 컨펌 무시 const ignoreConfirmPeople = () => { var s = document.createElement('script'); @@ -196,7 +213,7 @@ const ignoreConfirmPeople = () => { const ignoreDailyPopup = () => { var s = document.createElement('script'); s.innerHTML = `; - if (typeof('openGwangjuShuttleDialog') != 'undefined') { + if (typeof(openGwangjuShuttleDialog) == 'function') { console.log('disable openGwangjuShuttleDialog'); openGwangjuShuttleDialog = function () {}; } @@ -285,6 +302,7 @@ const checkAllCheckbox = () => { createCheckbox(); setCheckboxEvent(); + ignoreNonstopPopup(); ignoreConfirmPeople(); ignoreDailyPopup(); })(); From f46741bc38c32f13fc0ab35e72726ef53c27e357 Mon Sep 17 00:00:00 2001 From: tegrak Date: Thu, 1 Sep 2022 17:01:27 +0900 Subject: [PATCH 09/38] force reload when the page is freezed --- manifest.json | 56 ++++++++++++++++++++++++++++----------------------- reload.js | 18 +++++++++++++++++ 2 files changed, 49 insertions(+), 25 deletions(-) create mode 100644 reload.js diff --git a/manifest.json b/manifest.json index b5f3c2e..9ffef5e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,27 +1,33 @@ { - "manifest_version": 2, - "name": "KTX Macro", - "description": "KTX 매진 좌석 예약 도구", - "version": "1.4.0", - "permissions": ["https://www.letskorail.com/"], - "icons": { - "96": "icon96.png" - }, - "content_scripts": [ - { - "all_frames": true, - "js": ["content.js"], - "css": ["content.css"], - "matches": ["https://www.letskorail.com/*"], - "run_at": "document_end" - } - ], - "background": { - "page": "background.html" - }, - "web_accessible_resources": ["inject.js", "assets/tada.mp3"], - "browser_action": { - "default_title": "telegram", - "default_popup": "popup.html" - } + "manifest_version": 2, + "name": "KTX Macro", + "description": "KTX 매진 좌석 예약 도구", + "version": "1.4.0", + "permissions": ["https://www.letskorail.com/"], + "icons": { + "96": "icon96.png" + }, + "content_scripts": [ + { + "all_frames": true, + "js": ["content.js"], + "css": ["content.css"], + "matches": ["https://www.letskorail.com/*"], + "run_at": "document_end" + }, + { + "all_frames": true, + "js": ["reload.js"], + "matches": ["https://www.letskorail.com/*"], + "run_at": "document_start" + } + ], + "background": { + "page": "background.html" + }, + "web_accessible_resources": ["inject.js", "assets/tada.mp3"], + "browser_action": { + "default_title": "telegram", + "default_popup": "popup.html" + } } diff --git a/reload.js b/reload.js new file mode 100644 index 0000000..69573e6 --- /dev/null +++ b/reload.js @@ -0,0 +1,18 @@ +const TARGET_URL = "https://www.letskorail.com/ebizprd/EbizPrdTicketPr21111_i1.do"; +const PAGE_TIMEOUT = 15000; + +(() => { + if (!location.href.startsWith(TARGET_URL)) + return; + + const isStarted = localStorage.getItem("macro") === "on"; + if (isStarted) { + console.log('reload in ' + (PAGE_TIMEOUT / 1000) + ' seconds'); + window.setTimeout( + function () { + location.reload(); + }, + PAGE_TIMEOUT + ); + } +})(); \ No newline at end of file From bdad57bf11e470578e9275a2bdfc454366fe1948 Mon Sep 17 00:00:00 2001 From: tegrak Date: Fri, 2 Sep 2022 09:59:13 +0900 Subject: [PATCH 10/38] add closeNonstopPopup() --- content.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/content.js b/content.js index 739c5bd..9bba6f6 100644 --- a/content.js +++ b/content.js @@ -176,6 +176,23 @@ const reload = () => { document.querySelector(".btn_inq > a").click(); }; +//nonstop 팝업 자동 닫기 +const closeNonstopPopup = () => { + + if (!document.querySelector(".btn_blue_ang")) + return; + + var s = document.createElement('script'); + s.innerHTML = ` + var btn_blue_ang = document.querySelector('.btn_blue_ang'); + if (btn_blue_ang.text.indexOf('예매 계속 진행하기') != -1) { + console.log('close popup'); + setTimeout(f_close, 1000); + }; + `; + document.body.appendChild(s); +}; + //nonstop 팝업 무시 const ignoreNonstopPopup = () => { var s = document.createElement('script'); From 89b4c3d650d12fcab12705aeff12a3c3d5cbd35c Mon Sep 17 00:00:00 2001 From: tegrak Date: Fri, 2 Sep 2022 11:32:27 +0900 Subject: [PATCH 11/38] create content_header.js move global variables and definitions to header able to get tab id from background.js --- background.js | 3 +++ content.js | 5 ----- content_header.js | 23 +++++++++++++++++++++++ manifest.json | 10 +++++----- reload.js | 3 --- 5 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 content_header.js diff --git a/background.js b/background.js index 530ce8c..57be55a 100644 --- a/background.js +++ b/background.js @@ -31,4 +31,7 @@ chrome.extension.onMessage.addListener((message, sender, sendResponse) => { sendTelegramMessage(); sendResponse(true); } + else if (message && message.type == 'tabId') { + sendResponse(sender.tab.id); + } }); diff --git a/content.js b/content.js index 9bba6f6..1f3bad9 100644 --- a/content.js +++ b/content.js @@ -1,8 +1,3 @@ -let uid = 1; -const MAIN_URI = "https://www.letskorail.com/ebizprd/EbizPrdTicketPr21111_i1.do"; -const LOGIN_PAGE_URI = "https://www.letskorail.com/korail/com/login.do"; -const POPUP_URI = "https://www.letskorail.com/docs/pz/pz_msg_pop1.jsp"; - const createCheckbox = () => { const $rows = document.querySelectorAll("#tableResult > tbody > tr"); diff --git a/content_header.js b/content_header.js new file mode 100644 index 0000000..b05df91 --- /dev/null +++ b/content_header.js @@ -0,0 +1,23 @@ +let tabId = 0; +let uid = 1; + +const MAIN_URI = "https://www.letskorail.com/ebizprd/EbizPrdTicketPr21111_i1.do"; +const LOGIN_PAGE_URI = "https://www.letskorail.com/korail/com/login.do"; +const POPUP_URI = "https://www.letskorail.com/docs/pz/pz_msg_pop1.jsp"; +const PAGE_TIMEOUT = 15000; + +const getTabStorageKey = (key) => { + return String(key) + String(tabId); +}; + +const getTabStorageItem = (key) => { + return localStorage.getItem(getTabStorageKey(key)); +}; + +const setTabStorageItem = (key, value) => { + localStorage.setItem(getTabStorageKey(key), value); +}; + +const removeTabStorageItem = (key) => { + localStorage.removeItem(getTabStorageKey(key)); +}; \ No newline at end of file diff --git a/manifest.json b/manifest.json index 9ffef5e..52a1a0e 100644 --- a/manifest.json +++ b/manifest.json @@ -10,16 +10,16 @@ "content_scripts": [ { "all_frames": true, - "js": ["content.js"], - "css": ["content.css"], + "js": ["content_header.js", "reload.js"], "matches": ["https://www.letskorail.com/*"], - "run_at": "document_end" + "run_at": "document_start" }, { "all_frames": true, - "js": ["reload.js"], + "js": ["content.js"], + "css": ["content.css"], "matches": ["https://www.letskorail.com/*"], - "run_at": "document_start" + "run_at": "document_end" } ], "background": { diff --git a/reload.js b/reload.js index 69573e6..b526b24 100644 --- a/reload.js +++ b/reload.js @@ -1,6 +1,3 @@ -const TARGET_URL = "https://www.letskorail.com/ebizprd/EbizPrdTicketPr21111_i1.do"; -const PAGE_TIMEOUT = 15000; - (() => { if (!location.href.startsWith(TARGET_URL)) return; From 49dfb76147cd10e8ff66ba7e7e3e14525a6e3e00 Mon Sep 17 00:00:00 2001 From: tegrak Date: Fri, 2 Sep 2022 11:43:43 +0900 Subject: [PATCH 12/38] store macro localStorage per tab --- content.js | 67 ++++++++++++++++++++++++++---------------------------- reload.js | 8 +++---- 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/content.js b/content.js index 1f3bad9..2e4a83b 100644 --- a/content.js +++ b/content.js @@ -19,7 +19,7 @@ const createCheckbox = () => { }; const isChecked = uid => { - const checkedItemsStr = localStorage.getItem("checkedItems"); + const checkedItemsStr = getTabStorageItem("checkedItems"); const checkedItems = checkedItemsStr ? checkedItemsStr.split(",") : []; if (!checkedItems.length) { @@ -72,7 +72,7 @@ const macroStart = () => { return; } - if (!localStorage.getItem("checkedItems")) { + if (!getTabStorageItem("checkedItems")) { alert("선택 된 항목이 없습니다.\n1개 이상 선택해주세요."); return; } @@ -83,15 +83,15 @@ const macroStart = () => { "자동 예매 종료는 '자동 예매 정지' 혹은 esc키를 눌러주세요." ); - localStorage.setItem("macro", "on"); + setTabStorageItem("macro", "on"); reload(); }; const macroStop = () => { alert("자동 예매를 종료합니다."); - localStorage.removeItem("macro"); - localStorage.removeItem("checkedItems"); + removeTabStorageItem("macro"); + removeTabStorageItem("checkedItems"); reload(); }; @@ -122,7 +122,7 @@ const macro = () => { if ($button) { $button.closest("a").click(); - localStorage.removeItem("macro"); + removeTabStorageItem("macro"); chrome.extension.sendMessage({ type: "successTicketing" }); succeeded = true; break; @@ -141,7 +141,7 @@ const macro = () => { if ($button) { $button.closest("a").click(); - localStorage.removeItem("macro"); + removeTabStorageItem("macro"); chrome.extension.sendMessage({ type: "successTicketing" }); succeeded = true; break; @@ -155,7 +155,7 @@ const macro = () => { if ($button) { $button.closest("a").click(); - localStorage.removeItem("macro"); + removeTabStorageItem("macro"); chrome.extension.sendMessage({ type: "successTicketing" }); succeeded = true; break; @@ -244,9 +244,9 @@ const saveCheckboxState = () => { } if (checkedItems.length) { - localStorage.setItem("checkedItems", checkedItems.join(",")); + setTabStorageItem("checkedItems", checkedItems.join(",")); } else { - localStorage.removeItem("checkedItems"); + removeTabStorageItem("checkedItems"); } }; @@ -259,37 +259,16 @@ const checkAllCheckbox = () => { saveCheckboxState(); }; -(() => { - if (location.href.startsWith(POPUP_URI)) { - if (!document.querySelector(".btn_blue_ang")) - return; - - var s = document.createElement('script'); - s.innerHTML = ` - var btn_blue_ang = document.querySelector('.btn_blue_ang'); - if (btn_blue_ang.text.indexOf('예매 계속 진행하기') != -1) { - console.log('close popup'); - setTimeout(f_close, 1000); - }; - `; - document.body.appendChild(s); - return; - } +const initialize = () => { + console.log("tabId: " + tabId); - if ( - !document.querySelector(".btn_inq") || - !location.href.startsWith(MAIN_URI) - ) { - return; - } - - const isStarted = localStorage.getItem("macro") === "on"; + const isStarted = getTabStorageItem("macro") == "on"; if (isStarted) { macro(); setEscapeEvent(); } else { - localStorage.removeItem("checkedItems"); + removeTabStorageItem("checkedItems"); } document.querySelector(".btn_inq").insertAdjacentHTML( @@ -317,4 +296,22 @@ const checkAllCheckbox = () => { ignoreNonstopPopup(); ignoreConfirmPeople(); ignoreDailyPopup(); +}; + +(() => { + if (location.href.startsWith(POPUP_URI)) { + closeNonstopPopup(); + return; + } + else if (!location.href.startsWith(MAIN_URI) || !document.querySelector(".btn_inq")) { + return; + } + + chrome.extension.sendMessage( + {type: 'tabId'}, + function (result) { + tabId = result; + initialize(); + } + ); })(); diff --git a/reload.js b/reload.js index b526b24..f8707b9 100644 --- a/reload.js +++ b/reload.js @@ -1,8 +1,6 @@ -(() => { - if (!location.href.startsWith(TARGET_URL)) - return; - - const isStarted = localStorage.getItem("macro") === "on"; +const initialize_reload = (tabId) => { + const isStarted = getTabStorageItem("macro") === "on"; + getTabStorageItem('macro'); if (isStarted) { console.log('reload in ' + (PAGE_TIMEOUT / 1000) + ' seconds'); window.setTimeout( From 78069f829088066ec7433f02b75c49bd4217acbd Mon Sep 17 00:00:00 2001 From: tegrak Date: Fri, 2 Sep 2022 11:47:02 +0900 Subject: [PATCH 13/38] reload.js: fix missing codes --- reload.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/reload.js b/reload.js index f8707b9..6c5beaa 100644 --- a/reload.js +++ b/reload.js @@ -10,4 +10,17 @@ const initialize_reload = (tabId) => { PAGE_TIMEOUT ); } +}; + +(() => { + if (!location.href.startsWith(MAIN_URI)) + return; + + chrome.extension.sendMessage( + {type: 'tabId'}, + function (result) { + tabId = result; + initialize_reload(); + } + ); })(); \ No newline at end of file From 4595eae7c7772dc698e78e98499cf4f34177d834 Mon Sep 17 00:00:00 2001 From: tegrak Date: Fri, 2 Sep 2022 12:30:01 +0900 Subject: [PATCH 14/38] reload.js: remove unused param --- reload.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reload.js b/reload.js index 6c5beaa..0d29054 100644 --- a/reload.js +++ b/reload.js @@ -1,4 +1,4 @@ -const initialize_reload = (tabId) => { +const initialize_reload = () => { const isStarted = getTabStorageItem("macro") === "on"; getTabStorageItem('macro'); if (isStarted) { From e5558b03e0f02b963372a6a41d030d58ed848d81 Mon Sep 17 00:00:00 2001 From: tegrak Date: Fri, 2 Sep 2022 12:30:48 +0900 Subject: [PATCH 15/38] content_header: use sessionStorage replace localStrage not use tabId for key --- content_header.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content_header.js b/content_header.js index b05df91..975069c 100644 --- a/content_header.js +++ b/content_header.js @@ -7,17 +7,17 @@ const POPUP_URI = "https://www.letskorail.com/docs/pz/pz_msg_pop1.jsp"; const PAGE_TIMEOUT = 15000; const getTabStorageKey = (key) => { - return String(key) + String(tabId); + return String(key);// + String(tabId); }; const getTabStorageItem = (key) => { - return localStorage.getItem(getTabStorageKey(key)); + return sessionStorage.getItem(getTabStorageKey(key)); }; const setTabStorageItem = (key, value) => { - localStorage.setItem(getTabStorageKey(key), value); + sessionStorage.setItem(getTabStorageKey(key), value); }; const removeTabStorageItem = (key) => { - localStorage.removeItem(getTabStorageKey(key)); + sessionStorage.removeItem(getTabStorageKey(key)); }; \ No newline at end of file From e494461b19cdaaa91afd03b0db039d088a83b404 Mon Sep 17 00:00:00 2001 From: tegrak Date: Fri, 2 Sep 2022 12:38:23 +0900 Subject: [PATCH 16/38] Revert "content_header: use sessionStorage" This reverts commit e5558b03e0f02b963372a6a41d030d58ed848d81. --- content_header.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content_header.js b/content_header.js index 975069c..b05df91 100644 --- a/content_header.js +++ b/content_header.js @@ -7,17 +7,17 @@ const POPUP_URI = "https://www.letskorail.com/docs/pz/pz_msg_pop1.jsp"; const PAGE_TIMEOUT = 15000; const getTabStorageKey = (key) => { - return String(key);// + String(tabId); + return String(key) + String(tabId); }; const getTabStorageItem = (key) => { - return sessionStorage.getItem(getTabStorageKey(key)); + return localStorage.getItem(getTabStorageKey(key)); }; const setTabStorageItem = (key, value) => { - sessionStorage.setItem(getTabStorageKey(key), value); + localStorage.setItem(getTabStorageKey(key), value); }; const removeTabStorageItem = (key) => { - sessionStorage.removeItem(getTabStorageKey(key)); + localStorage.removeItem(getTabStorageKey(key)); }; \ No newline at end of file From 8a3e1e1f51c8d8438dd6f1e51e139d6db06e1088 Mon Sep 17 00:00:00 2001 From: tegrak Date: Fri, 2 Sep 2022 12:41:47 +0900 Subject: [PATCH 17/38] reload.js: remove unused code. --- reload.js | 1 - 1 file changed, 1 deletion(-) diff --git a/reload.js b/reload.js index 0d29054..a92d2ea 100644 --- a/reload.js +++ b/reload.js @@ -1,6 +1,5 @@ const initialize_reload = () => { const isStarted = getTabStorageItem("macro") === "on"; - getTabStorageItem('macro'); if (isStarted) { console.log('reload in ' + (PAGE_TIMEOUT / 1000) + ' seconds'); window.setTimeout( From 75693aafb6fa72e535cdcb7597a4a7c0f7f42630 Mon Sep 17 00:00:00 2001 From: tegrak Date: Fri, 2 Sep 2022 17:51:02 +0900 Subject: [PATCH 18/38] manage macro tabs able to run multiple macro remove localStorage items of closed tabs --- background.js | 37 +++++++++++++++++++++++++++++++++++++ content_header.js | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/background.js b/background.js index 57be55a..1ecdc74 100644 --- a/background.js +++ b/background.js @@ -1,3 +1,5 @@ +let tabs = []; + const playSound = () => { if (typeof (audio) != "undefined" && audio) { audio.pause(); @@ -25,6 +27,32 @@ const sendTelegramMessage = () => { fetch(url); } +function addTab(tabid) { + if (tabs.indexOf(tabid) === -1) + tabs.push(tabid); +} + +function removeTab(tabid) { + console.log('remove tab tabs: ' + tabs + ', tabid: ' + tabid); + var index = tabs.indexOf(tabid); + if (index != -1) + tabs.splice(index, 1); +} + +function checkTabs() { + var tabid; + for (tabid of tabs) { + chrome.tabs.get(tabid, function (tab) { + if (chrome.runtime.lastError) { + console.log(chrome.runtime.lastError); + } + if (!tab) { + removeTab(tabid); + } + }); + } +}; + chrome.extension.onMessage.addListener((message, sender, sendResponse) => { if (message && message.type == 'successTicketing') { playSound(); @@ -32,6 +60,15 @@ chrome.extension.onMessage.addListener((message, sender, sendResponse) => { sendResponse(true); } else if (message && message.type == 'tabId') { + addTab(sender.tab.id); sendResponse(sender.tab.id); } + else if (message && message.type == 'tabs') { + checkTabs(); + sendResponse(tabs); + } }); + +chrome.tabs.onRemoved.addListener(function (tabid, removed) { + removeTab(tabid); +}); \ No newline at end of file diff --git a/content_header.js b/content_header.js index b05df91..61f9e11 100644 --- a/content_header.js +++ b/content_header.js @@ -10,6 +10,37 @@ const getTabStorageKey = (key) => { return String(key) + String(tabId); }; +const getTabIdFromTabStorageKey = (key) => { + for (var i = 0; i < key.length; i++) { + if (!isNaN(key[i])) + return Number(key.substring(i)); + } + return 0; +}; + +const removeUnusedTabStorage = (tabs) => { + var tabid; + var key; + console.log('tabs: ' + tabs); + + for (key in localStorage) { + if (!key.startsWith('macro') && !key.startsWith('checkedItems')) + continue; + + tabid = getTabIdFromTabStorageKey(key); + + console.log( + 'key: ' + key + ', ' + + 'tabid: ' + tabid + ', ' + + 'indexOf: ' + tabs.indexOf(tabid)); + + if (tabs.indexOf(tabid) === -1) { + console.log('removeItem: ' + key); + localStorage.removeItem(key); + } + } +}; + const getTabStorageItem = (key) => { return localStorage.getItem(getTabStorageKey(key)); }; @@ -20,4 +51,9 @@ const setTabStorageItem = (key, value) => { const removeTabStorageItem = (key) => { localStorage.removeItem(getTabStorageKey(key)); -}; \ No newline at end of file +}; + +(() => { + //console.log("content_header"); + chrome.extension.sendMessage({type: 'tabs'}, removeUnusedTabStorage); +})(); \ No newline at end of file From 245c4b474589a4868a93c2aecc215ca41e25f1d7 Mon Sep 17 00:00:00 2001 From: tegrak Date: Mon, 5 Sep 2022 12:17:16 +0900 Subject: [PATCH 19/38] header checkbox check all rows of same column --- content.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/content.js b/content.js index 2e4a83b..38ccd5e 100644 --- a/content.js +++ b/content.js @@ -1,3 +1,49 @@ +const CHECKBOX_COLUMN = [5, 6, 10]; + +const createHeaderCheckbox = () => { + const row = document.querySelector("#tableResult > thead > tr"); + var child; + + for (var col of CHECKBOX_COLUMN) { + child = row.querySelector(`th:nth-child(${col})`); + child.insertAdjacentHTML("beforeend", + ` +
+ +
+ ` + ); + } + +}; + +const setHeaderCheckboxEvent = () => { + const header = document.querySelector("#tableResult > thead > tr"); + + for (var col of CHECKBOX_COLUMN) { + header.querySelector(`th:nth-child(${col}) .ktx-macro-header-checkbox`) + .addEventListener('change', changeHeaderCheckbox); + } +}; + +const changeHeaderCheckbox = (event) => { + const rows = document.querySelectorAll("#tableResult > tbody > tr"); + const child_num = event.target.value; + + if (!rows || !rows.length) { + return; + } + + rows.forEach(row => { + row.querySelector(`td:nth-child(${child_num}) .ktx-macro-checkbox`) + .checked = event.target.checked; + }); + saveCheckboxState(); +}; + const createCheckbox = () => { const $rows = document.querySelectorAll("#tableResult > tbody > tr"); @@ -291,7 +337,9 @@ const initialize = () => { .querySelector(".check-all-button") .addEventListener("click", checkAllCheckbox); + createHeaderCheckbox(); createCheckbox(); + setHeaderCheckboxEvent(); setCheckboxEvent(); ignoreNonstopPopup(); ignoreConfirmPeople(); From 100c14901a474816c607010010dacf2d4c98cce9 Mon Sep 17 00:00:00 2001 From: tegrak Date: Mon, 5 Sep 2022 12:26:59 +0900 Subject: [PATCH 20/38] fix indent --- content.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/content.js b/content.js index 38ccd5e..6d2073c 100644 --- a/content.js +++ b/content.js @@ -196,8 +196,10 @@ const macro = () => { if (isChecked(++uid)) { $row.querySelector("td:nth-child(10)").style.backgroundColor = "#f03e3e"; - const $button = $row.querySelector("td:nth-child(10)") - .querySelector('[src="/docs/2007/img/common/icon_wait.gif"]'); + const $button = + $row + .querySelector("td:nth-child(10)") + .querySelector('[src="/docs/2007/img/common/icon_wait.gif"]'); if ($button) { $button.closest("a").click(); From a2e45bda95afef83da5d6c72c0a7d4e49748c164 Mon Sep 17 00:00:00 2001 From: tegrak Date: Mon, 5 Sep 2022 13:57:51 +0900 Subject: [PATCH 21/38] clear reload timeout before execute macro() --- content.js | 5 +++++ content_header.js | 1 + reload.js | 3 ++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/content.js b/content.js index 6d2073c..0564367 100644 --- a/content.js +++ b/content.js @@ -313,6 +313,11 @@ const initialize = () => { const isStarted = getTabStorageItem("macro") == "on"; if (isStarted) { + if (reloadTimeoutID) { + console.log('stop realod timer ' + reloadTimeoutID); + window.clearTimeout(reloadTimeoutID); + reloadTimeoutID = null; + } macro(); setEscapeEvent(); } else { diff --git a/content_header.js b/content_header.js index 61f9e11..58d97d6 100644 --- a/content_header.js +++ b/content_header.js @@ -1,5 +1,6 @@ let tabId = 0; let uid = 1; +let reloadTimeoutID = null; const MAIN_URI = "https://www.letskorail.com/ebizprd/EbizPrdTicketPr21111_i1.do"; const LOGIN_PAGE_URI = "https://www.letskorail.com/korail/com/login.do"; diff --git a/reload.js b/reload.js index a92d2ea..14c634f 100644 --- a/reload.js +++ b/reload.js @@ -2,8 +2,9 @@ const initialize_reload = () => { const isStarted = getTabStorageItem("macro") === "on"; if (isStarted) { console.log('reload in ' + (PAGE_TIMEOUT / 1000) + ' seconds'); - window.setTimeout( + reloadTimeoutID = window.setTimeout( function () { + console.log('force reload'); location.reload(); }, PAGE_TIMEOUT From 4fe28a8b001ad0f548659f834d25b3089bc74f2b Mon Sep 17 00:00:00 2001 From: tegrak Date: Mon, 5 Sep 2022 14:17:46 +0900 Subject: [PATCH 22/38] fix spelling --- content.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content.js b/content.js index 0564367..f1d789c 100644 --- a/content.js +++ b/content.js @@ -314,7 +314,7 @@ const initialize = () => { if (isStarted) { if (reloadTimeoutID) { - console.log('stop realod timer ' + reloadTimeoutID); + console.log('stop reload timer ' + reloadTimeoutID); window.clearTimeout(reloadTimeoutID); reloadTimeoutID = null; } From 20ac0bd5c85123b5c1e4df8b632d168947dcb89a Mon Sep 17 00:00:00 2001 From: tegrak Date: Mon, 5 Sep 2022 14:34:06 +0900 Subject: [PATCH 23/38] header checkbox: set column to data attribute use data-column instead of value --- content.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content.js b/content.js index f1d789c..b5ec278 100644 --- a/content.js +++ b/content.js @@ -10,7 +10,7 @@ const createHeaderCheckbox = () => { `
@@ -31,7 +31,7 @@ const setHeaderCheckboxEvent = () => { const changeHeaderCheckbox = (event) => { const rows = document.querySelectorAll("#tableResult > tbody > tr"); - const child_num = event.target.value; + const child_num = event.target.dataset.column; if (!rows || !rows.length) { return; From 1a08565b5dd86f7793d2c0a693d649b97ecf825f Mon Sep 17 00:00:00 2001 From: tegrak Date: Mon, 5 Sep 2022 16:05:23 +0900 Subject: [PATCH 24/38] enable multi select mode with shift key --- content.js | 99 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 81 insertions(+), 18 deletions(-) diff --git a/content.js b/content.js index b5ec278..2bbdd59 100644 --- a/content.js +++ b/content.js @@ -1,4 +1,17 @@ const CHECKBOX_COLUMN = [5, 6, 10]; +let checkboxLastClickPos = {"row": -1, "column": -1}; + +const getTableResult = () => { + return document.querySelectorAll("#tableResult > tbody > tr"); +}; + +const getTableResultColumn = (row, column) => { + return getTableResult()[row].querySelector(`td:nth-child(${column})`); +}; + +const getTableResultCheckbox = (objRow, column) => { + return objRow.querySelector(`td:nth-child(${column}) .ktx-macro-checkbox`); +}; const createHeaderCheckbox = () => { const row = document.querySelector("#tableResult > thead > tr"); @@ -37,7 +50,7 @@ const changeHeaderCheckbox = (event) => { return; } - rows.forEach(row => { + rows.forEach((row) => { row.querySelector(`td:nth-child(${child_num}) .ktx-macro-checkbox`) .checked = event.target.checked; }); @@ -45,22 +58,18 @@ const changeHeaderCheckbox = (event) => { }; const createCheckbox = () => { - const $rows = document.querySelectorAll("#tableResult > tbody > tr"); + const rows = document.querySelectorAll("#tableResult > tbody > tr"); - if (!$rows.length) { + if (!rows.length) { return; } - $rows.forEach($row => { - $row - .querySelector("td:nth-child(5)") - .insertAdjacentHTML("beforeend", getCheckboxTemplate(uid++)); - $row - .querySelector("td:nth-child(6)") - .insertAdjacentHTML("beforeend", getCheckboxTemplate(uid++)); - $row - .querySelector("td:nth-child(10)") - .insertAdjacentHTML("beforeend", getCheckboxTemplate(uid++)); + rows.forEach((o, row) => { + for (var col of CHECKBOX_COLUMN) { + o.querySelector(`td:nth-child(${col})`) + .insertAdjacentHTML("beforeend", + getCheckboxTemplate(uid++, row, col)); + } }); }; @@ -77,7 +86,7 @@ const isChecked = uid => { const isLogin = () => !!document.querySelectorAll(".gnb_list > .log_nm").length; -const getCheckboxTemplate = uid => { +const getCheckboxTemplate = (uid, row, column) => { if (!uid) { return; } @@ -85,7 +94,14 @@ const getCheckboxTemplate = uid => { return `
@@ -96,9 +112,7 @@ const setCheckboxEvent = () => { const $checkboxes = document.querySelectorAll(".ktx-macro-checkbox"); for (let i = 0; i < $checkboxes.length; i++) { - $checkboxes[i].addEventListener("click", () => { - saveCheckboxState(); - }); + $checkboxes[i].addEventListener("click", clickCheckbox); } }; @@ -281,6 +295,55 @@ const ignoreDailyPopup = () => { document.body.appendChild(s); } +const clickCheckbox = (event) => { + var multi_check = false; + const curr_row = Number(event.target.dataset.row); + const curr_col = Number(event.target.dataset.column); + const prev_row = Number(checkboxLastClickPos.row); + const prev_col = Number(checkboxLastClickPos.column); + //console.log('checkbox row=' + event.target.dataset.row + ' column=' + event.target.dataset.column); + do { + if (!event.shiftKey || event.ctrlKey || event.altKey) + break; + if (prev_row == -1 || prev_col == -1) + break; + if (curr_col != prev_col) + break; + if (curr_row == prev_row) + break; + + const objRows = getTableResult(); + var objCol; + var start, end; + multi_check = true; + + if (curr_row > prev_row) { + start = prev_row; + end = curr_row - 1; + } + else { + start = curr_row + 1; + end = prev_row; + } + + for (var i = start; i <= end; i++) { + //console.log('row=' + i + ', column=' + event.target.dataset.column); + objCol = getTableResultCheckbox(objRows[i], curr_col); + objCol.checked = event.target.checked; + } + } + while (0); + + if (!multi_check) { + checkboxLastClickPos.row = curr_row; + checkboxLastClickPos.column = curr_col; + if (prev_row != -1 && prev_col != -1) + getTableResultColumn(prev_row, prev_col).style.backgroundColor = ""; + getTableResultColumn(curr_row, curr_col).style.backgroundColor = "#ccccff"; + } + saveCheckboxState(); +}; + const saveCheckboxState = () => { let checkedItems = []; const $checkboxes = document.querySelectorAll(".ktx-macro-checkbox"); From 3d2fbe43fa1a6eaf1ff154b0d11b379b46f30e15 Mon Sep 17 00:00:00 2001 From: tegrak Date: Wed, 7 Sep 2022 15:24:44 +0900 Subject: [PATCH 25/38] fix unnecessary character --- content.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content.js b/content.js index 2bbdd59..dd21cf6 100644 --- a/content.js +++ b/content.js @@ -286,7 +286,7 @@ const ignoreConfirmPeople = () => { //일일 팝업 무시 const ignoreDailyPopup = () => { var s = document.createElement('script'); - s.innerHTML = `; + s.innerHTML = ` if (typeof(openGwangjuShuttleDialog) == 'function') { console.log('disable openGwangjuShuttleDialog'); openGwangjuShuttleDialog = function () {}; From 082e7a4fe46d79e064ee91305a1fafac403eac0b Mon Sep 17 00:00:00 2001 From: tegrak Date: Wed, 12 Oct 2022 17:20:17 +0900 Subject: [PATCH 26/38] start migrating Manifest V3 --- background.js | 67 +++++++++++++++-------------- content.js | 50 +++++++++++++++++----- content_header.js | 2 +- inject.js | 39 +++++++++++++++++ inject_click.js | 7 ++++ manifest.json | 14 ++++--- popup.js | 104 ++++++++++++++++++++++++++-------------------- reload.js | 2 +- 8 files changed, 188 insertions(+), 97 deletions(-) create mode 100644 inject_click.js diff --git a/background.js b/background.js index 1ecdc74..8561cb0 100644 --- a/background.js +++ b/background.js @@ -1,30 +1,28 @@ let tabs = []; const playSound = () => { - if (typeof (audio) != "undefined" && audio) { - audio.pause(); - document.body.removeChild(audio); - audio = null; - } - audio = document.createElement('audio'); - document.body.appendChild(audio); - audio.autoplay = true; - audio.src = chrome.extension.getURL('tada.mp3'); - audio.play(); + if (typeof (audio) != "undefined" && audio) { + audio.pause(); + document.body.removeChild(audio); + audio = null; + } + audio = document.createElement('audio'); + document.body.appendChild(audio); + audio.autoplay = true; + audio.src = chrome.runtime.getURL('tada.mp3'); + audio.play(); }; const sendTelegramMessage = () => { - const botToken = localStorage.getItem('KTX_MACRO::bot-token'); - const chatId = localStorage.getItem('KTX_MACRO::chat-id'); - - if (!botToken || !chatId) { - return; - } - - const msg = encodeURI('예약을 시도하였습니다. 예약을 확인해주세요.'); - const url = `https://api.telegram.org/bot${botToken}/sendmessage?chat_id=${chatId}&text=${msg}`; + chrome.storage.local.get( + ['ktx-macro-bot-token', 'ktx-macro-chat-id'], + function (result) { + const msg = encodeURI('예약을 시도하였습니다. 예약을 확인해주세요.'); + const url = `https://api.telegram.org/bot${result['ktx-macro-bot-token']}/sendmessage?chat_id=${result['ktx-macro-chat-id']}&text=${msg}`; - fetch(url); + fetch(url); + } + ); } function addTab(tabid) { @@ -53,20 +51,21 @@ function checkTabs() { } }; -chrome.extension.onMessage.addListener((message, sender, sendResponse) => { - if (message && message.type == 'successTicketing') { - playSound(); - sendTelegramMessage(); - sendResponse(true); - } - else if (message && message.type == 'tabId') { - addTab(sender.tab.id); - sendResponse(sender.tab.id); - } - else if (message && message.type == 'tabs') { - checkTabs(); - sendResponse(tabs); - } +chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + //console.log('message: ' + message); + if (message && message.type == 'successTicketing') { + //playSound(); + sendTelegramMessage(); + sendResponse(true); + } + else if (message && message.type == 'tabId') { + addTab(sender.tab.id); + sendResponse(sender.tab.id); + } + else if (message && message.type == 'tabs') { + checkTabs(); + sendResponse(tabs); + } }); chrome.tabs.onRemoved.addListener(function (tabid, removed) { diff --git a/content.js b/content.js index dd21cf6..169f91d 100644 --- a/content.js +++ b/content.js @@ -181,9 +181,10 @@ const macro = () => { .querySelector('[src="/docs/2007/img/common/icon_apm_rd.gif"]'); if ($button) { - $button.closest("a").click(); + new Audio(chrome.runtime.getURL("tada.mp3")).play(); removeTabStorageItem("macro"); - chrome.extension.sendMessage({ type: "successTicketing" }); + chrome.runtime.sendMessage({ type: "successTicketing" }); + inject_click($button.closest("a")); succeeded = true; break; } @@ -200,9 +201,10 @@ const macro = () => { .querySelector('[src="/docs/2007/img/common/icon_apm_rd.gif"]'); if ($button) { - $button.closest("a").click(); + new Audio(chrome.runtime.getURL("tada.mp3")).play(); removeTabStorageItem("macro"); - chrome.extension.sendMessage({ type: "successTicketing" }); + chrome.runtime.sendMessage({ type: "successTicketing" }); + inject_click($button.closest("a")); succeeded = true; break; } @@ -216,9 +218,10 @@ const macro = () => { .querySelector('[src="/docs/2007/img/common/icon_wait.gif"]'); if ($button) { - $button.closest("a").click(); + new Audio(chrome.runtime.getURL("tada.mp3")).play(); removeTabStorageItem("macro"); - chrome.extension.sendMessage({ type: "successTicketing" }); + chrome.runtime.sendMessage({ type: "successTicketing" }); + inject_click($button.closest("a")); succeeded = true; break; } @@ -230,7 +233,20 @@ const macro = () => { }; const reload = () => { - document.querySelector(".btn_inq > a").click(); + inject_click(document.querySelector(".btn_inq > a")); +}; + +const inject_click = (obj) => { + console.log('inject_click: ' + obj); + var s = document.createElement('script'); + obj.id = 'ktx-macro-click'; + + s.src = chrome.runtime.getURL('inject_click.js'); + s.onload = function () { + obj.removeAttribute('id'); + this.remove(); + }; + (document.head || document.documentElement).appendChild(s); }; //nonstop 팝업 자동 닫기 @@ -370,6 +386,17 @@ const checkAllCheckbox = () => { saveCheckboxState(); }; +const inject = () => { + var s= document.createElement('script'); + s.src = chrome.runtime.getURL('inject.js'); + s.setAttribute('value', 'passed?'); + s.onload = function () { + console.log('inject onload'); + this.remove(); + }; + (document.head || document.documentElement).appendChild(s); +}; + const initialize = () => { console.log("tabId: " + tabId); @@ -411,9 +438,10 @@ const initialize = () => { createCheckbox(); setHeaderCheckboxEvent(); setCheckboxEvent(); - ignoreNonstopPopup(); - ignoreConfirmPeople(); - ignoreDailyPopup(); + //ignoreNonstopPopup(); + //ignoreConfirmPeople(); + //ignoreDailyPopup(); + inject(); }; (() => { @@ -425,7 +453,7 @@ const initialize = () => { return; } - chrome.extension.sendMessage( + chrome.runtime.sendMessage( {type: 'tabId'}, function (result) { tabId = result; diff --git a/content_header.js b/content_header.js index 58d97d6..dadf87c 100644 --- a/content_header.js +++ b/content_header.js @@ -56,5 +56,5 @@ const removeTabStorageItem = (key) => { (() => { //console.log("content_header"); - chrome.extension.sendMessage({type: 'tabs'}, removeUnusedTabStorage); + chrome.runtime.sendMessage({type: 'tabs'}, removeUnusedTabStorage); })(); \ No newline at end of file diff --git a/inject.js b/inject.js index e69de29..b2d8527 100644 --- a/inject.js +++ b/inject.js @@ -0,0 +1,39 @@ +console.log('inject.js'); +console.log('value: ' + document.currentScript.getAttribute('value')); + +//nonstop 팝업 무시 +function ignoreNonstopPopup() { + if (typeof(Nopeople2) == 'function') { + console.log('disable Nopeople2'); + const originNopeople2 = Nopeople2; + Nopeople2 = function (intPsrm, intIdxNo, iAddInfo4, callback) { + console.log('remove h_nonstop_msg. ' + train[intIdxNo].h_nonstop_msg); + train[intIdxNo].h_nonstop_msg = ''; + return originNopeople2(intPsrm, intIdxNo, iAddInfo4, callback); + } + } +} + +//인원 확인 컨펌 무시 +function ignoreConfirmPeople() { + const origin_confirm = confirm; + confirm = function (message) { + console.log('confirm: ' + message); + if (message.indexOf('맞습니까') != -1) { + return true; + } + return origin; + } +} + +//일일 팝업 무시 +function ignoreDailyPopup() { + if (typeof(openGwangjuShuttleDialog) == 'function') { + console.log('disable openGwangjuShuttleDialog'); + openGwangjuShuttleDialog = function () {}; + } +} + +ignoreNonstopPopup(); +ignoreConfirmPeople(); +ignoreDailyPopup(); \ No newline at end of file diff --git a/inject_click.js b/inject_click.js new file mode 100644 index 0000000..79c77d4 --- /dev/null +++ b/inject_click.js @@ -0,0 +1,7 @@ +console.log('inject_click.js'); + +var obj = document.getElementById('ktx-macro-click'); +//if (obj.href.includes('inqSchedule')) +// obj.click(); +obj.click(); +obj.removeAttribute('id'); \ No newline at end of file diff --git a/manifest.json b/manifest.json index 52a1a0e..0976030 100644 --- a/manifest.json +++ b/manifest.json @@ -1,9 +1,10 @@ { - "manifest_version": 2, + "manifest_version": 3, "name": "KTX Macro", "description": "KTX 매진 좌석 예약 도구", "version": "1.4.0", - "permissions": ["https://www.letskorail.com/"], + "permissions": ["scripting", "storage"], + "host_permissions": ["https://www.letskorail.com/"], "icons": { "96": "icon96.png" }, @@ -23,10 +24,13 @@ } ], "background": { - "page": "background.html" + "service_worker": "background.js" }, - "web_accessible_resources": ["inject.js", "assets/tada.mp3"], - "browser_action": { + "web_accessible_resources": [{ + "resources": ["inject.js", "inject_click.js", "tada.mp3"], + "matches": ["https://www.letskorail.com/*"] + }], + "action": { "default_title": "telegram", "default_popup": "popup.html" } diff --git a/popup.js b/popup.js index 9b2ec08..bf87ed7 100644 --- a/popup.js +++ b/popup.js @@ -1,47 +1,61 @@ (() => { - const MESSAGE_RESET = '초기화 되었습니다.'; - const MESSAGE_CONNECTION_SUCCESS = '연동되었습니다.'; - const MESSAGE_CONNECTION_FAIL = '연동에 실패하였습니다.
입력하신 정보를 다시 확인해주세요.'; - - const init = () => { - document.getElementById('bot-token').value = localStorage.getItem('KTX_MACRO::bot-token'); - document.getElementById('chat-id').value = localStorage.getItem('KTX_MACRO::chat-id'); - } - - const save = () => { - const botToken = document.getElementById('bot-token').value; - const chatId = document.getElementById('chat-id').value; - - const msg = encodeURI('KTX Macro: 예약 알림이 연동되었습니다.'); - const url = `https://api.telegram.org/bot${botToken}/sendMessage?chat_id=${chatId}&text=${msg}`; - - fetch(url).then(response => { - if (response.status === 200) { - localStorage.setItem('KTX_MACRO::bot-token', botToken); - localStorage.setItem('KTX_MACRO::chat-id', chatId); - setMessage(MESSAGE_CONNECTION_SUCCESS); - } else { - setMessage(MESSAGE_CONNECTION_FAIL); - } - }).catch(err => { - setMessage(MESSAGE_CONNECTION_FAIL); - console.error(err) - }); - } - - const reset = () => { - document.getElementById('bot-token').value = ''; - document.getElementById('chat-id').value = ''; - localStorage.removeItem('KTX_MACRO::bot-token'); - localStorage.removeItem('KTX_MACRO::chat-id'); - setMessage(MESSAGE_RESET); - } - - const setMessage = message => { - document.getElementById('message').innerHTML = message; - } - - init(); - document.getElementById('button-save').addEventListener('click', save); - document.getElementById('button-reset').addEventListener('click', reset); + const MESSAGE_RESET = '초기화 되었습니다.'; + const MESSAGE_CONNECTION_SUCCESS = '연동되었습니다.'; + const MESSAGE_CONNECTION_FAIL = '연동에 실패하였습니다.
입력하신 정보를 다시 확인해주세요.'; + + const init = () => { + chrome.storage.local.get( + ['ktx-macro-bot-token', 'ktx-macro-chat-id'], + function (result) { + if (result['ktx-macro-bot-token'] && result['ktx-macro-chat-id']) { + document.getElementById('bot-token').value = result['ktx-macro-bot-token']; + document.getElementById('chat-id').value = result['ktx-macro-chat-id']; + } + } + ); + } + + const save = () => { + const botToken = document.getElementById('bot-token').value; + const chatId = document.getElementById('chat-id').value; + + const msg = encodeURI('KTX Macro: 예약 알림이 연동되었습니다.'); + const url = `https://api.telegram.org/bot${botToken}/sendMessage?chat_id=${chatId}&text=${msg}`; + + fetch(url).then(response => { + if (response.status === 200) { + chrome.storage.local.set( + { + 'ktx-macro-bot-token': botToken, + 'ktx-macro-chat-id': chatId + }, + function() { + setMessage(MESSAGE_CONNECTION_SUCCESS); + } + ); + + } else { + setMessage(MESSAGE_CONNECTION_FAIL); + } + }).catch(err => { + setMessage(MESSAGE_CONNECTION_FAIL); + console.error(err) + }); + } + + const reset = () => { + document.getElementById('bot-token').value = ''; + document.getElementById('chat-id').value = ''; + chrome.storage.local.remove('ktx-macro-bot-token'); + chrome.storage.local.remove('ktx-macro-chat-id'); + setMessage(MESSAGE_RESET); + } + + const setMessage = message => { + document.getElementById('message').innerHTML = message; + } + + init(); + document.getElementById('button-save').addEventListener('click', save); + document.getElementById('button-reset').addEventListener('click', reset); })(); \ No newline at end of file diff --git a/reload.js b/reload.js index 14c634f..b2f22e2 100644 --- a/reload.js +++ b/reload.js @@ -16,7 +16,7 @@ const initialize_reload = () => { if (!location.href.startsWith(MAIN_URI)) return; - chrome.extension.sendMessage( + chrome.runtime.sendMessage( {type: 'tabId'}, function (result) { tabId = result; From 5edcc99e6e91dffdc03accc6fd5fcff554824355 Mon Sep 17 00:00:00 2001 From: tegrak Date: Thu, 13 Oct 2022 10:28:49 +0900 Subject: [PATCH 27/38] inject_nonstop_popup.js: auto close nonstop popup for Manifest V3 --- content.js | 13 ++++++++++++- manifest.json | 7 ++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/content.js b/content.js index 169f91d..e384b40 100644 --- a/content.js +++ b/content.js @@ -397,6 +397,17 @@ const inject = () => { (document.head || document.documentElement).appendChild(s); }; +const inject_nonstop_popup = () => { + var s= document.createElement('script'); + s.src = chrome.runtime.getURL('inject_nonstop_popup.js'); + s.onload = function () { + console.log('inject_nonstop_popup onload'); + this.remove(); + }; + (document.head || document.documentElement).appendChild(s); +}; + + const initialize = () => { console.log("tabId: " + tabId); @@ -446,7 +457,7 @@ const initialize = () => { (() => { if (location.href.startsWith(POPUP_URI)) { - closeNonstopPopup(); + inject_nonstop_popup(); return; } else if (!location.href.startsWith(MAIN_URI) || !document.querySelector(".btn_inq")) { diff --git a/manifest.json b/manifest.json index 0976030..1723eff 100644 --- a/manifest.json +++ b/manifest.json @@ -27,7 +27,12 @@ "service_worker": "background.js" }, "web_accessible_resources": [{ - "resources": ["inject.js", "inject_click.js", "tada.mp3"], + "resources": [ + "inject.js", + "inject_click.js", + "inject_nonstop_popup.js", + "tada.mp3" + ], "matches": ["https://www.letskorail.com/*"] }], "action": { From 62cdb6b58e1a9f34cef8cf0e7932576f541a16c4 Mon Sep 17 00:00:00 2001 From: tegrak Date: Fri, 14 Oct 2022 11:22:47 +0900 Subject: [PATCH 28/38] add missing inject_nonstop_popup.js --- inject_nonstop_popup.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 inject_nonstop_popup.js diff --git a/inject_nonstop_popup.js b/inject_nonstop_popup.js new file mode 100644 index 0000000..00d8d00 --- /dev/null +++ b/inject_nonstop_popup.js @@ -0,0 +1,10 @@ +//nonstop 팝업 자동 닫기 +function closeNonstopPopup() { + var btn_blue_ang = document.querySelector('.btn_blue_ang'); + if (btn_blue_ang.text.indexOf('예매 계속 진행하기') != -1) { + console.log('close popup'); + setTimeout(f_close, 1000); + }; +} + +closeNonstopPopup(); \ No newline at end of file From ee7e15aa3d5f45614931cc5af078961bad9f3dfb Mon Sep 17 00:00:00 2001 From: tegrak Date: Fri, 14 Oct 2022 11:31:23 +0900 Subject: [PATCH 29/38] content.js: delete removing an element id in inject_click() --- content.js | 1 - 1 file changed, 1 deletion(-) diff --git a/content.js b/content.js index e384b40..8880a98 100644 --- a/content.js +++ b/content.js @@ -243,7 +243,6 @@ const inject_click = (obj) => { s.src = chrome.runtime.getURL('inject_click.js'); s.onload = function () { - obj.removeAttribute('id'); this.remove(); }; (document.head || document.documentElement).appendChild(s); From 77b55a2f99fa5d7bb25770919bf6385e803cc800 Mon Sep 17 00:00:00 2001 From: tegrak Date: Wed, 28 Dec 2022 14:19:18 +0900 Subject: [PATCH 30/38] inject_click.js: check obj --- inject_click.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/inject_click.js b/inject_click.js index 79c77d4..5bef37b 100644 --- a/inject_click.js +++ b/inject_click.js @@ -3,5 +3,7 @@ console.log('inject_click.js'); var obj = document.getElementById('ktx-macro-click'); //if (obj.href.includes('inqSchedule')) // obj.click(); -obj.click(); -obj.removeAttribute('id'); \ No newline at end of file +if (obj) { + obj.click(); + obj.removeAttribute('id'); +} \ No newline at end of file From a514cba554ff1dc9ca8f9f07fa29674ca2e9e668 Mon Sep 17 00:00:00 2001 From: tegrak Date: Wed, 28 Dec 2022 14:22:41 +0900 Subject: [PATCH 31/38] tabs to local strage remove tabs variable in background.js because of sw inactive --- background.js | 34 ++++++++++++++++------------------ content.js | 1 + content_header.js | 23 ++++++++++++++++++++++- 3 files changed, 39 insertions(+), 19 deletions(-) diff --git a/background.js b/background.js index 8561cb0..55d583d 100644 --- a/background.js +++ b/background.js @@ -1,5 +1,3 @@ -let tabs = []; - const playSound = () => { if (typeof (audio) != "undefined" && audio) { audio.pause(); @@ -25,19 +23,24 @@ const sendTelegramMessage = () => { ); } -function addTab(tabid) { - if (tabs.indexOf(tabid) === -1) - tabs.push(tabid); -} +function removeMacroTab(tabid) { + chrome.storage.local.get(["ktx-macro-tabs"], + function (result) { + let tabs = result["ktx-macro-tabs"]; + console.log('remove tab tabs: ' + tabs + ', tabid: ' + tabid); + if (!tabs) + tabs = []; -function removeTab(tabid) { - console.log('remove tab tabs: ' + tabs + ', tabid: ' + tabid); - var index = tabs.indexOf(tabid); - if (index != -1) - tabs.splice(index, 1); + var index = tabs.indexOf(tabid); + if (index != -1) { + tabs.splice(index, 1); + chrome.storage.local.set({"ktx-macro-tabs": tabs}); + } + } + ); } -function checkTabs() { +function checkMacroTabs() { var tabid; for (tabid of tabs) { chrome.tabs.get(tabid, function (tab) { @@ -59,15 +62,10 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { sendResponse(true); } else if (message && message.type == 'tabId') { - addTab(sender.tab.id); sendResponse(sender.tab.id); } - else if (message && message.type == 'tabs') { - checkTabs(); - sendResponse(tabs); - } }); chrome.tabs.onRemoved.addListener(function (tabid, removed) { - removeTab(tabid); + removeMacroTab(tabid); }); \ No newline at end of file diff --git a/content.js b/content.js index 8880a98..08ea9db 100644 --- a/content.js +++ b/content.js @@ -467,6 +467,7 @@ const initialize = () => { {type: 'tabId'}, function (result) { tabId = result; + addMacroTab(tabId); initialize(); } ); diff --git a/content_header.js b/content_header.js index dadf87c..7f151ec 100644 --- a/content_header.js +++ b/content_header.js @@ -54,7 +54,28 @@ const removeTabStorageItem = (key) => { localStorage.removeItem(getTabStorageKey(key)); }; +function addMacroTab(tabid) { + chrome.storage.local.get(["ktx-macro-tabs"], + function (result) { + let tabs = result["ktx-macro-tabs"]; + if (!tabs) + tabs = []; + if (tabs.indexOf(tabid) === -1) { + tabs.push(tabid); + console.log("tabs: " + tabs); + chrome.storage.local.set({"ktx-macro-tabs": tabs}); + } + } + ); +}; + (() => { //console.log("content_header"); - chrome.runtime.sendMessage({type: 'tabs'}, removeUnusedTabStorage); + chrome.storage.local.get(["ktx-macro-tabs"], + function (result) { + let tabs = result["ktx-macro-tabs"]; + console.log("tabs: " + tabs); + removeUnusedTabStorage(tabs); + } + ); })(); \ No newline at end of file From 3ef52c48c61815b45486466650117f0194b77d95 Mon Sep 17 00:00:00 2001 From: tegrak Date: Mon, 2 Jan 2023 15:36:42 +0900 Subject: [PATCH 32/38] enable windows events that blocked by korail --- content.js | 2 ++ content_header.js | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/content.js b/content.js index 08ea9db..90be5cb 100644 --- a/content.js +++ b/content.js @@ -463,6 +463,8 @@ const initialize = () => { return; } + disableEventListners(); + chrome.runtime.sendMessage( {type: 'tabId'}, function (result) { diff --git a/content_header.js b/content_header.js index 7f151ec..133e388 100644 --- a/content_header.js +++ b/content_header.js @@ -69,6 +69,18 @@ function addMacroTab(tabid) { ); }; +const disableEventListners = () => { + const events = ["selectstart", "mousedown", "contextmenu", "copy", "keydown"]; + events.forEach(function(item) { + window.addEventListener(item, stopEventPropagation, true); + }); + +}; + +const stopEventPropagation = (event) => { + event.stopPropagation(); +}; + (() => { //console.log("content_header"); chrome.storage.local.get(["ktx-macro-tabs"], From 48d3ef9ce4147044237bbbbe47b0bf2d112309d9 Mon Sep 17 00:00:00 2001 From: tegrak Date: Mon, 2 Jan 2023 15:38:12 +0900 Subject: [PATCH 33/38] content_header.js: make function addMacroTab() to const --- content_header.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content_header.js b/content_header.js index 133e388..26d5584 100644 --- a/content_header.js +++ b/content_header.js @@ -54,7 +54,7 @@ const removeTabStorageItem = (key) => { localStorage.removeItem(getTabStorageKey(key)); }; -function addMacroTab(tabid) { +const addMacroTab = (tabid) => { chrome.storage.local.get(["ktx-macro-tabs"], function (result) { let tabs = result["ktx-macro-tabs"]; From 803c590bd89bb97f880fdcc8fd27695dc650bc90 Mon Sep 17 00:00:00 2001 From: tegrak Date: Mon, 2 Jan 2023 15:40:56 +0900 Subject: [PATCH 34/38] background.js: make functions to const --- background.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/background.js b/background.js index 55d583d..f4746d3 100644 --- a/background.js +++ b/background.js @@ -23,7 +23,7 @@ const sendTelegramMessage = () => { ); } -function removeMacroTab(tabid) { +const removeMacroTab = (tabid) => { chrome.storage.local.get(["ktx-macro-tabs"], function (result) { let tabs = result["ktx-macro-tabs"]; @@ -40,7 +40,7 @@ function removeMacroTab(tabid) { ); } -function checkMacroTabs() { +const checkMacroTabs = () => { var tabid; for (tabid of tabs) { chrome.tabs.get(tabid, function (tab) { From 8968b158315618ecaf94c2f0ae443092c501ed63 Mon Sep 17 00:00:00 2001 From: tegrak Date: Mon, 2 Jan 2023 16:29:21 +0900 Subject: [PATCH 35/38] check array type of ktx-macro-tabs --- background.js | 2 +- content_header.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/background.js b/background.js index f4746d3..e557d32 100644 --- a/background.js +++ b/background.js @@ -28,7 +28,7 @@ const removeMacroTab = (tabid) => { function (result) { let tabs = result["ktx-macro-tabs"]; console.log('remove tab tabs: ' + tabs + ', tabid: ' + tabid); - if (!tabs) + if (typeof(tabs) != "object" || !Array.isArray(tabs)) tabs = []; var index = tabs.indexOf(tabid); diff --git a/content_header.js b/content_header.js index 26d5584..ce762be 100644 --- a/content_header.js +++ b/content_header.js @@ -58,7 +58,7 @@ const addMacroTab = (tabid) => { chrome.storage.local.get(["ktx-macro-tabs"], function (result) { let tabs = result["ktx-macro-tabs"]; - if (!tabs) + if (typeof(tabs) != "object" || !Array.isArray(tabs)) tabs = []; if (tabs.indexOf(tabid) === -1) { tabs.push(tabid); From f4d8d0560163e1a977f79bc045687e00f7fcb96a Mon Sep 17 00:00:00 2001 From: tegrak Date: Tue, 3 Jan 2023 12:12:24 +0900 Subject: [PATCH 36/38] enable macro on family reservation --- content.js | 104 +++++++++++++++++----------------------------- content_header.js | 10 ++++- 2 files changed, 46 insertions(+), 68 deletions(-) diff --git a/content.js b/content.js index 90be5cb..e6ab271 100644 --- a/content.js +++ b/content.js @@ -1,8 +1,8 @@ -const CHECKBOX_COLUMN = [5, 6, 10]; +let CHECKBOX_COLUMN = [5, 6, 10]; let checkboxLastClickPos = {"row": -1, "column": -1}; const getTableResult = () => { - return document.querySelectorAll("#tableResult > tbody > tr"); + return document.querySelectorAll("#divResult > .tbl_h > tbody > tr"); }; const getTableResultColumn = (row, column) => { @@ -14,7 +14,7 @@ const getTableResultCheckbox = (objRow, column) => { }; const createHeaderCheckbox = () => { - const row = document.querySelector("#tableResult > thead > tr"); + const row = document.querySelector("#divResult > .tbl_h > thead > tr"); var child; for (var col of CHECKBOX_COLUMN) { @@ -34,7 +34,7 @@ const createHeaderCheckbox = () => { }; const setHeaderCheckboxEvent = () => { - const header = document.querySelector("#tableResult > thead > tr"); + const header = document.querySelector("#divResult > .tbl_h > thead > tr"); for (var col of CHECKBOX_COLUMN) { header.querySelector(`th:nth-child(${col}) .ktx-macro-header-checkbox`) @@ -43,7 +43,7 @@ const setHeaderCheckboxEvent = () => { }; const changeHeaderCheckbox = (event) => { - const rows = document.querySelectorAll("#tableResult > tbody > tr"); + const rows = document.querySelectorAll("#divResult > .tbl_h > tbody > tr"); const child_num = event.target.dataset.column; if (!rows || !rows.length) { @@ -58,7 +58,7 @@ const changeHeaderCheckbox = (event) => { }; const createCheckbox = () => { - const rows = document.querySelectorAll("#tableResult > tbody > tr"); + const rows = document.querySelectorAll("#divResult > .tbl_h > tbody > tr"); if (!rows.length) { return; @@ -159,71 +159,35 @@ const macroStop = () => { const macro = () => { let uid = 0; let $row; - const $rows = document.querySelectorAll("#tableResult > tbody > tr"); + const $rows = document.querySelectorAll("#divResult > .tbl_h > tbody > tr"); const len = $rows.length; - var succeeded = false; + let succeeded = false; + let $td, $a; if (!len) { return; } - for (let i = 0; i < len; i++) { + for (let i = 0; i < len && !succeeded; i++) { $row = $rows[i]; - - if (isChecked(++uid)) { - $row.querySelector("td:nth-child(5)").style.backgroundColor = "#f03e3e"; - const $button = - $row - .querySelector("td:nth-child(5)") - .querySelector('[src="/docs/2007/img/common/icon_apm_bl.gif"]') || - $row - .querySelector("td:nth-child(5)") - .querySelector('[src="/docs/2007/img/common/icon_apm_rd.gif"]'); - - if ($button) { - new Audio(chrome.runtime.getURL("tada.mp3")).play(); - removeTabStorageItem("macro"); - chrome.runtime.sendMessage({ type: "successTicketing" }); - inject_click($button.closest("a")); - succeeded = true; - break; - } - } - - if (isChecked(++uid)) { - $row.querySelector("td:nth-child(6)").style.backgroundColor = "#f03e3e"; - const $button = - $row - .querySelector("td:nth-child(6)") - .querySelector('[src="/docs/2007/img/common/icon_apm_bl.gif"]') || - $row - .querySelector("td:nth-child(6)") - .querySelector('[src="/docs/2007/img/common/icon_apm_rd.gif"]'); - - if ($button) { - new Audio(chrome.runtime.getURL("tada.mp3")).play(); - removeTabStorageItem("macro"); - chrome.runtime.sendMessage({ type: "successTicketing" }); - inject_click($button.closest("a")); - succeeded = true; - break; - } - } - - if (isChecked(++uid)) { - $row.querySelector("td:nth-child(10)").style.backgroundColor = "#f03e3e"; - const $button = - $row - .querySelector("td:nth-child(10)") - .querySelector('[src="/docs/2007/img/common/icon_wait.gif"]'); - - if ($button) { - new Audio(chrome.runtime.getURL("tada.mp3")).play(); - removeTabStorageItem("macro"); - chrome.runtime.sendMessage({ type: "successTicketing" }); - inject_click($button.closest("a")); - succeeded = true; - break; + for (let col of CHECKBOX_COLUMN) { + if (isChecked(++uid)) { + $td = $row.querySelector(`td:nth-child(${col})`); + $td.style.backgroundColor = "#f03e3e"; + $a = $td.querySelector(`a:nth-child(1)`); + const $button = + $td.querySelector('[src="/docs/2007/img/common/icon_apm_bl.gif"]') || + $td.querySelector('[src="/docs/2007/img/common/icon_apm_rd.gif"]'); + + if ($a) { + new Audio(chrome.runtime.getURL("tada.mp3")).play(); + removeTabStorageItem("macro"); + chrome.runtime.sendMessage({ type: "successTicketing" }); + //inject_click($button.closest("a")); + inject_click($a); + succeeded = true; + break; + } } } } @@ -455,16 +419,22 @@ const initialize = () => { }; (() => { + disableEventListners(); + if (location.href.startsWith(POPUP_URI)) { inject_nonstop_popup(); return; } - else if (!location.href.startsWith(MAIN_URI) || !document.querySelector(".btn_inq")) { + else if (location.href.startsWith(MAIN_URI) && document.querySelector(".btn_inq")) { + CHECKBOX_COLUMN = [5, 6, 10]; + } + else if (location.href.startsWith(FAMILY_URI) && document.querySelector(".btn_inq")) { + CHECKBOX_COLUMN = [5]; + } + else { return; } - disableEventListners(); - chrome.runtime.sendMessage( {type: 'tabId'}, function (result) { diff --git a/content_header.js b/content_header.js index ce762be..096b39f 100644 --- a/content_header.js +++ b/content_header.js @@ -3,6 +3,7 @@ let uid = 1; let reloadTimeoutID = null; const MAIN_URI = "https://www.letskorail.com/ebizprd/EbizPrdTicketPr21111_i1.do"; +const FAMILY_URI = "https://www.letskorail.com/ebizprd/EbizPrdTicketPr21151_i1.do"; const LOGIN_PAGE_URI = "https://www.letskorail.com/korail/com/login.do"; const POPUP_URI = "https://www.letskorail.com/docs/pz/pz_msg_pop1.jsp"; const PAGE_TIMEOUT = 15000; @@ -70,10 +71,12 @@ const addMacroTab = (tabid) => { }; const disableEventListners = () => { - const events = ["selectstart", "mousedown", "contextmenu", "copy", "keydown"]; + //const events = ["selectstart", "mousedown", "contextmenu", "copy", "keydown"]; + const events = ["selectstart", "mousedown", "mousemove", "contextmenu", "copy"]; events.forEach(function(item) { window.addEventListener(item, stopEventPropagation, true); }); + window.addEventListener("keydown", stopKeydownPropogation, true); }; @@ -81,6 +84,11 @@ const stopEventPropagation = (event) => { event.stopPropagation(); }; +const stopKeydownPropogation = (event) => { + if (event.keyCode == 17 || event.ctrlKey) + event.stopPropagation(); +}; + (() => { //console.log("content_header"); chrome.storage.local.get(["ktx-macro-tabs"], From 97169f108a2f9c215a099d746cec2842a911e63b Mon Sep 17 00:00:00 2001 From: tegrak Date: Tue, 3 Jan 2023 14:28:23 +0900 Subject: [PATCH 37/38] reload.js: auto reloading on family reservation page --- reload.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reload.js b/reload.js index b2f22e2..d24d619 100644 --- a/reload.js +++ b/reload.js @@ -13,7 +13,7 @@ const initialize_reload = () => { }; (() => { - if (!location.href.startsWith(MAIN_URI)) + if (!location.href.startsWith(MAIN_URI) && !location.href.startsWith(FAMILY_URI)) return; chrome.runtime.sendMessage( From 8a1725f29f7d38828fd0537b07e243243c209ba6 Mon Sep 17 00:00:00 2001 From: tegrak Date: Fri, 26 Jan 2024 10:38:29 +0900 Subject: [PATCH 38/38] content.js: find the button with RESERVE_BUTTON but button is not used for now. --- content.js | 72 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/content.js b/content.js index e6ab271..94fb889 100644 --- a/content.js +++ b/content.js @@ -1,4 +1,8 @@ let CHECKBOX_COLUMN = [5, 6, 10]; +const MAIN_PAGE = 0; +const FAMILY_PAGE = 1; +let RESERVE_BUTTON = {}; +let PAGE = MAIN_PAGE; let checkboxLastClickPos = {"row": -1, "column": -1}; const getTableResult = () => { @@ -171,29 +175,39 @@ const macro = () => { for (let i = 0; i < len && !succeeded; i++) { $row = $rows[i]; for (let col of CHECKBOX_COLUMN) { - if (isChecked(++uid)) { - $td = $row.querySelector(`td:nth-child(${col})`); - $td.style.backgroundColor = "#f03e3e"; - $a = $td.querySelector(`a:nth-child(1)`); - const $button = - $td.querySelector('[src="/docs/2007/img/common/icon_apm_bl.gif"]') || - $td.querySelector('[src="/docs/2007/img/common/icon_apm_rd.gif"]'); - - if ($a) { - new Audio(chrome.runtime.getURL("tada.mp3")).play(); - removeTabStorageItem("macro"); - chrome.runtime.sendMessage({ type: "successTicketing" }); - //inject_click($button.closest("a")); - inject_click($a); - succeeded = true; + if (!isChecked(++uid)) { + continue; + } + $td = $row.querySelector(`td:nth-child(${col})`); + $td.style.backgroundColor = "#f03e3e"; + $a = $td.querySelector(`a:nth-child(1)`); + let $button; + for (let img of RESERVE_BUTTON[col]) { + //console.log(img); + //src starts with img + $button = $td.querySelector('[src^="' + img + '"]'); + if ($button) { break; } } + + if ($a) { + new Audio(chrome.runtime.getURL("tada.mp3")).play(); + removeTabStorageItem("macro"); + chrome.runtime.sendMessage({ type: "successTicketing" }); + //inject_click($button.closest("a")); + inject_click($a); + succeeded = true; + break; + } + } + if (succeeded) { + break; } } if (!succeeded) - setTimeout(reload, 1000); + setTimeout(reload, 1200); }; const reload = () => { @@ -425,11 +439,31 @@ const initialize = () => { inject_nonstop_popup(); return; } - else if (location.href.startsWith(MAIN_URI) && document.querySelector(".btn_inq")) { - CHECKBOX_COLUMN = [5, 6, 10]; + else if (!document.querySelector(".btn_inq")) { + return; } - else if (location.href.startsWith(FAMILY_URI) && document.querySelector(".btn_inq")) { + + if (location.href.startsWith(MAIN_URI)) { + PAGE = MAIN_PAGE; + CHECKBOX_COLUMN = [5, 6, 10]; + RESERVE_BUTTON[5] = [ + "/docs/2007/img/common/icon_apm_bl.gif", + "/docs/2007/img/common/icon_apm_rd.gif" + ]; + RESERVE_BUTTON[6] = [ + "/docs/2007/img/common/icon_apm_bl.gif", + "/docs/2007/img/common/icon_apm_rd.gif" + ]; + RESERVE_BUTTON[10] = [ + "/docs/2007/img/common/icon_wait.gif" + ]; + } + else if (location.href.startsWith(FAMILY_URI)) { + PAGE = FAMILY_PAGE; CHECKBOX_COLUMN = [5]; + RESERVE_BUTTON[5] = [ + "/docs/2007/img/persent/btn" + ]; } else { return;