// ==UserScript==
// @name BCA SQTF Auto War Controller
// @namespace http://tampermonkey.net/
// @version 1.3
// @description BCA SQTF automation controller
// @match https://pub.lasmana.com/bca.html
// @match https://webform.bca.co.id/marketers/sqtf/2026/reg*
// @grant GM_getValue
// @grant GM_setValue
// @grant unsafeWindow
// ==/UserScript==
(() => {
"use strict";
// ==================================================
// STORAGE
// ==================================================
const KEY = {
card: "noKartu",
email: "email",
day: "tanggal",
month: "bulan",
year: "tahun",
schedule: "startTimes",
enabled: "enabled",
awaitingResult: "awaitingResult",
retryPending: "retryPending"
};
const get = (key, def="") =>
GM_getValue(key, def);
const set = (key, value) =>
GM_setValue(key, value);
// ==================================================
// CONFIG
// ==================================================
function getConfig(){
return {
card: get(KEY.card),
email: get(KEY.email),
day: get(KEY.day, "01"),
month: get(KEY.month, "01"),
year: get(KEY.year, "1990"),
schedule: get(
KEY.schedule,
"10:00,14:00"
)
};
}
// ==================================================
// UI
// ==================================================
const panel = document.createElement("div");
panel.id = "bca-panel";
panel.innerHTML = `
๐ฐ BCA SQTF
Status: OFF
`;
const style = document.createElement("style");
style.textContent = `
#bca-panel {
position:fixed;
top:20px;
right:20px;
width:280px;
padding:15px;
background:white;
border:2px solid #0050a4;
border-radius:12px;
z-index:999999;
font-family:Arial;
box-shadow:0 5px 20px #0005;
}
.bca-title {
font-size:18px;
font-weight:bold;
margin-bottom:10px;
}
#bca-panel label {
display:block;
font-weight:bold;
margin-top:6px;
}
#bca-panel input {
width:100%;
box-sizing:border-box;
padding:6px;
}
.row {
display:flex;
gap:5px;
}
.row div {
flex:1;
}
#bca-panel button {
width:100%;
margin-top:7px;
padding:8px;
cursor:pointer;
}
`;
document.head.appendChild(style);
document.body.appendChild(panel);
const $ = id =>
document.getElementById(id);
// ==================================================
// LOAD CONFIG TO UI
// ==================================================
function loadUI(){
const c = getConfig();
$("cfg-card").value =
c.card;
$("cfg-email").value =
c.email;
$("cfg-day").value =
c.day;
$("cfg-month").value =
c.month;
$("cfg-year").value =
c.year;
$("cfg-schedule").value =
c.schedule;
}
loadUI();
function status(msg){
$("bca-status").innerHTML =
msg;
}
// ==================================================
// SAVE CONFIG
// ==================================================
$("btn-save").onclick = () => {
set(
KEY.card,
$("cfg-card").value
);
set(
KEY.email,
$("cfg-email").value
);
set(
KEY.day,
$("cfg-day").value
);
set(
KEY.month,
$("cfg-month").value
);
set(
KEY.year,
$("cfg-year").value
);
set(
KEY.schedule,
$("cfg-schedule").value
);
status(
"๐พ Config saved"
);
};
// ==================================================
// FORM HELPER
// ==================================================
function setInputValue(
element,
value
){
if(!element)
return;
const setter =
Object.getOwnPropertyDescriptor(
HTMLInputElement.prototype,
"value"
).set;
setter.call(
element,
value
);
element.dispatchEvent(
new Event(
"input",
{
bubbles:true
}
)
);
element.dispatchEvent(
new Event(
"change",
{
bubbles:true
}
)
);
}
// ==================================================
// FILL BCA FORM
// ==================================================
function fillForm(){
const c = getConfig();
const card =
document.querySelector(
'input[placeholder*="No. Kartu"]'
);
if(!card){
console.log(
"[BCA] card input not found"
);
return false;
}
setInputValue(
card,
c.card
);
const email =
document.querySelector(
'input[placeholder*="Email"]'
);
setInputValue(
email,
c.email
);
const selects =
document.querySelectorAll(
"select"
);
if(selects.length >= 3){
selects[0].value =
c.day;
selects[0].dispatchEvent(
new Event(
"change",
{
bubbles:true
}
)
);
selects[1].value =
c.month;
selects[1].dispatchEvent(
new Event(
"change",
{
bubbles:true
}
)
);
selects[2].value =
c.year;
selects[2].dispatchEvent(
new Event(
"change",
{
bubbles:true
}
)
);
}
console.log(
"[BCA] form filled"
);
return true;
}
// ==================================================
// FIND REGISTER BUTTON
// ==================================================
function findRegisterButton(){
const elements =
[
...document.querySelectorAll(
"button,input,a,div"
)
];
return elements.find(
el => {
const text =
(
el.innerText ||
el.value ||
""
)
.trim()
.toLowerCase();
return (
text.includes(
"registrasi"
)
||
text.includes(
"register"
)
||
text.includes(
"submit"
)
||
text.includes(
"lanjut"
)
||
text.includes(
"daftar"
)
);
}
);
}
// ==================================================
// SUBMIT RESULT WATCHER
// ==================================================
const RESULT_TEXT = {
success: "registrasi berhasil",
retry: [
"registrasi baru dibuka",
"mohon coba beberapa saat lagi"
]
};
let resultObserver = null;
let resultPollTimer = null;
let resultWatcherActive = false;
function containsRetryText(text){
const normalizedText = String(text)
.replace(/\s+/g, " ")
.toLowerCase();
return RESULT_TEXT.retry.some(
message => normalizedText.includes(message)
);
}
function getPageText(pageDocument = document){
let text = pageDocument.body?.innerText || "";
for(
const frame of
pageDocument.querySelectorAll("iframe")
){
try{
if(frame.contentDocument){
text += " " + getPageText(
frame.contentDocument
);
}
}
catch(error){
console.debug(
"[BCA] cross-origin iframe skipped",
error
);
}
}
return text;
}
function getSubmitResult(){
const text = (
getPageText()
)
.replace(/\s+/g, " ")
.toLowerCase();
if(text.includes(RESULT_TEXT.success))
return "success";
if(containsRetryText(text))
return "retry";
return null;
}
function stopResultWatcher(){
resultWatcherActive = false;
if(resultObserver){
resultObserver.disconnect();
resultObserver = null;
}
if(resultPollTimer){
clearInterval(resultPollTimer);
resultPollTimer = null;
}
}
function handleSubmitResult(result){
if(!result)
return;
stopResultWatcher();
if(result === "success"){
set(KEY.awaitingResult, false);
set(KEY.retryPending, false);
stopAutomation();
status("โ
Registrasi Berhasil - STOPPED");
console.log("[BCA] registrasi berhasil");
return;
}
set(KEY.awaitingResult, false);
set(KEY.retryPending, true);
set(KEY.enabled, true);
status("๐ Registrasi belum dibuka - refreshing...");
console.log(
"[BCA] registrasi belum dibuka, force refresh"
);
setTimeout(
() => location.reload(),
100
);
}
function checkSubmitResult(){
const result = getSubmitResult();
if(result)
handleSubmitResult(result);
}
function startResultWatcher(){
stopResultWatcher();
resultWatcherActive = true;
resultObserver = new MutationObserver(
checkSubmitResult
);
resultObserver.observe(
document.documentElement,
{
childList: true,
subtree: true,
characterData: true
}
);
resultPollTimer = setInterval(
checkSubmitResult,
200
);
checkSubmitResult();
console.log("[BCA] submit result watcher ON");
}
function installAlertWatcher(targetWindow){
if(!targetWindow || !targetWindow.alert)
return;
const originalAlert = targetWindow.alert;
targetWindow.alert = function(message){
const result = originalAlert.apply(
this,
arguments
);
if(
resultWatcherActive
&&
containsRetryText(message)
){
handleSubmitResult("retry");
}
return result;
};
}
installAlertWatcher(window);
if(
typeof unsafeWindow !== "undefined"
&&
unsafeWindow !== window
){
installAlertWatcher(unsafeWindow);
}
function stopAutomation(){
stopResultWatcher();
GM_setValue(
KEY.enabled,
false
);
set(KEY.awaitingResult, false);
set(KEY.retryPending, false);
if(scheduleTimer){
clearInterval(scheduleTimer);
}
if(warTimer){
clearInterval(warTimer);
}
status(
"โ
SUBMITTED - STOPPED"
);
console.log(
"[BCA] automation stopped"
);
}
// ==================================================
// CLICK REGISTER
// ==================================================
function clickRegister(){
const btn =
document.querySelector(
"#btnsubmit"
);
if(!btn){
console.log(
"Submit button tidak ditemukan"
);
return false;
}
console.log(
"Click submit..."
);
set(KEY.awaitingResult, true);
set(KEY.retryPending, false);
set(KEY.enabled, false);
if(scheduleTimer)
clearInterval(scheduleTimer);
if(warTimer)
clearInterval(warTimer);
startResultWatcher();
status(
"โณ Submit sent - waiting result..."
);
btn.click();
return true;
}
// ==================================================
// TEST
// ==================================================
$("btn-test").onclick = () => {
if(
fillForm()
){
setTimeout(
() => {
clickRegister();
},
500
);
status(
"๐งช Test submit executed"
);
}
else{
status(
"โ Form not found"
);
}
};
// ==================================================
// TIME
// ==================================================
function secondsNow(){
const d =
new Date();
return (
d.getHours()*3600
+
d.getMinutes()*60
+
d.getSeconds()
);
}
function getTargets(){
return get(
KEY.schedule,
"10:00,14:00"
)
.split(",")
.map(
t => {
const p =
t.trim()
.split(":")
.map(Number);
return (
(p[0] || 0) * 3600
+
(p[1] || 0) * 60
+
(p[2] || 0)
);
}
);
}
// ==================================================
// WAR LOOP
// ==================================================
let warTimer = null;
function startWar(){
status(
"๐ Searching form..."
);
warTimer =
setInterval(
() => {
if(
fillForm()
){
clearInterval(
warTimer
);
status(
"๐ข Filling done"
);
setTimeout(
() => {
clickRegister();
},
300
);
}
else{
console.log(
"[BCA] refresh"
);
location.reload();
}
},
500
);
}
// ==================================================
// SCHEDULER
// ==================================================
let scheduleTimer = null;
function waitLaunch(){
scheduleTimer =
setInterval(
() => {
const now =
secondsNow();
const targets =
getTargets();
console.log(
"[TIME]",
now,
targets
);
const hit =
targets.some(
t =>
now >= t
&&
now <= t + 30
);
if(hit){
clearInterval(
scheduleTimer
);
startWar();
}
},
100
);
}
// ==================================================
// START STOP
// ==================================================
$("btn-start").onclick = () => {
set(
KEY.enabled,
true
);
status(
"โณ Waiting launch time"
);
waitLaunch();
};
$("btn-stop").onclick = () => {
set(
KEY.enabled,
false
);
set(KEY.awaitingResult, false);
set(KEY.retryPending, false);
stopResultWatcher();
if(
scheduleTimer
)
clearInterval(
scheduleTimer
);
if(
warTimer
)
clearInterval(
warTimer
);
status(
"๐ด OFF"
);
};
// ==================================================
// AUTO RESUME
// ==================================================
const wasAwaitingResult = get(
KEY.awaitingResult,
false
);
const initialResult = wasAwaitingResult
? getSubmitResult()
: null;
if(initialResult){
handleSubmitResult(initialResult);
}
else if(
wasAwaitingResult
){
status(
"โณ Waiting submit result..."
);
startResultWatcher();
}
else if(
get(KEY.enabled, false)
&&
get(KEY.retryPending, false)
){
set(KEY.retryPending, false);
status(
"๐ Retry after refresh"
);
startWar();
}
else if(
get(KEY.enabled, false)
){
status(
"โณ Waiting launch time"
);
waitLaunch();
}
})();