window.stationData = null; window.Connection===false; let PaymentisRunning = false; let isRunning = false; let isCookiesReady = false; var chrome = window.chrome; window.boardingStationStatus = "Pending"; window.bookingRequestStatus = "Pending"; window.captchaData = {}; window.greq = ""; window.autoRestartAttempts = 0; window.csrfToken = ""; window.trainData = []; window.accessToken = ""; window.isBookingStopped = false; window.clientTransactionId = ""; window.stationData = []; window.unauthAvailabilityResponse = null; window.lastAvailabilityResponse = null; let pollRetryCount = 0; let idleTimer = null; let idleFlag = false; const IDLE_MS = 3 * 60 * 1000; var autoCaptchaEnabled = false; var autoCaptchaAttempts = 0; const MAX_AUTO_CAPTCHA_ATTEMPTS = 5; var autoBookingCaptchaAttempts = 0; const MAX_AUTO_BOOKING_CAPTCHA_ATTEMPTS = 5 window.lastSessionTime = null; window.sessionTimeout = 3 * 60 * 1000; const WARMUP_URL_KEY = 'warmUpUrl'; const WARMUP_URL_TS_KEY = 'warmUpUrlTs'; const WARMUP_URL_TTL = 24 * 60 * 60 * 1000; let timeOffset = 0; const BOOKING_FLAG = 'bookingUsed'; let globalStopWarmup = null; function initLogger() { window.__logs = []; ['log', 'info', 'warn', 'error', 'debug'].forEach(level => { const original = console[level]; console[level] = function(...args) { try { window.__logs.push({ type: 'console', level, timestamp: new Date().toISOString(), args: args.map(a => { try { return typeof a === 'object' ? JSON.stringify(a) : String(a); } catch { return String(a); } }) }); } catch (_) { /* swallow */ } original.apply(console, args); }; }); // ---- wrap fetch ---- const originalFetch = window.fetch; window.fetch = function(...args) { const startTs = new Date().toISOString(); window.__logs.push({ type: 'network', phase: 'request', timestamp: startTs, details: { args } }); return originalFetch.apply(this, args) .then(response => { // clone so we can read body without consuming original const clone = response.clone(); clone.text() .then(body => { window.__logs.push({ type: 'network', phase: 'response', timestamp: new Date().toISOString(), details: { url: clone.url, status: clone.status, duration: (new Date().toISOString() /* rough */), body } }); }) .catch(() => {/* ignore body errors */}); return response; }); }; // ---- wrap XHR ---- const origOpen = XMLHttpRequest.prototype.open; const origSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.open = function(method, url, ...rest) { this._logMethod = method; this._logUrl = url; return origOpen.call(this, method, url, ...rest); }; XMLHttpRequest.prototype.send = function(body) { window.__logs.push({ type: 'network', phase: 'request', timestamp: new Date().toISOString(), details: { method: this._logMethod, url: this._logUrl, body } }); this.addEventListener('loadend', () => { window.__logs.push({ type: 'network', phase: 'response', timestamp: new Date().toISOString(), details: { method: this._logMethod, url: this._logUrl, status: this.status, response: this.response } }); }); return origSend.call(this, body); }; } // call this after initLogger() has been run document.getElementById('downloadLogs').addEventListener('click', () => { // 1) Grab the logs const logs = window.__logs || []; // 2) Redact sensitive information const redactedLogs = logs.map(log => { // Create a deep copy to avoid modifying the original log const redactedLog = JSON.parse(JSON.stringify(log)); // Check if the log has details.args and redact sensitive data if (redactedLog.details && redactedLog.details.args) { // Redact the API key in the body if (typeof redactedLog.details.args[1]?.body === 'string') { redactedLog.details.args[1].body = redactedLog.details.args[1].body.replace( /"apikey":"[^"]*"/, '"apikey":"REDACTED"' ); } // Redact the host in the URL (args[0]) if (typeof redactedLog.details.args[0] === 'string') { redactedLog.details.args[0] = redactedLog.details.args[0].replace( /https?:\/\/[^\/]+/, 'https://REDACTED_HOST' ); } } return redactedLog; }); // 3) Stringify with pretty-print const json = JSON.stringify(redactedLogs, null, 2); // 4) Build a Blob and object-URL const blob = new Blob([json], { type: 'application/json' }); const url = URL.createObjectURL(blob); // 5) Create a temporary to trigger download const a = document.createElement('a'); a.href = url; a.download = `brahmos-user-logs-${Date.now()}.json`; document.body.appendChild(a); // Firefox requires it in DOM a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }); function getAccurateISTTime() { return new Date(Date.now() + timeOffset); } async function syncISTTime() { const now = new Date(); const utcMs = now.getTime() + now.getTimezoneOffset() * 60000; const istOffset = 5.5 * 60 * 60000; const istNow = new Date(utcMs + istOffset); const totalMinutes = istNow.getHours() * 60 + istNow.getMinutes(); const windowStart = 5 * 60 + 30; const windowEnd = 11 * 60 + 40; if (totalMinutes >= windowStart && totalMinutes < windowEnd) { timeOffset = 0; return; } const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 5000); try { const start = Date.now(); const res = await fetch( "https://timeapi.io/api/Time/current/zone?timeZone=Asia/Kolkata", { signal: controller.signal } ); const end = Date.now(); clearTimeout(timeoutId); if (!res.ok) throw new Error(); const data = await res.json(); const serverTime = new Date(data.dateTime).getTime(); const latency = (end - start) / 2; const clientNow = start + latency; timeOffset = serverTime - clientNow; } catch { clearTimeout(timeoutId); timeOffset = 0; } } chrome.storage.local.get("isCookiesReady", ({ isCookiesReady: stored }) => { isCookiesReady = Boolean(stored); clog("browser support check", isCookiesReady); }); async function getWarmUpUrl() { const now = Date.now(); const cachedUrl = sessionStorage.getItem(WARMUP_URL_KEY); const cachedTs = parseInt(sessionStorage.getItem(WARMUP_URL_TS_KEY) || '0', 10); if (cachedUrl && (now - cachedTs) < WARMUP_URL_TTL) { return cachedUrl; } let html; try { const resp = await fetch('https://www.irctc.co.in/nget/train-search', { credentials: 'include', }); html = await resp.text(); } catch (e) { //console.error('❌ Failed to fetch train-search page:', e); return null; } const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); const scripts = Array.from(doc.querySelectorAll('script[type="text/javascript"][src]')); const candidates = scripts .map(s => s.getAttribute('src')) .filter(path => !path.startsWith('/nget/') && !path.includes('?')); if (candidates.length === 0) { //console.error('❌ No warm-up script URL found in fetched HTML'); return null; } const shortest = candidates.reduce((a, b) => a.length < b.length ? a : b); const fullUrl = new URL(shortest, 'https://www.irctc.co.in').href; sessionStorage.setItem(WARMUP_URL_KEY, fullUrl); sessionStorage.setItem(WARMUP_URL_TS_KEY, now.toString()); return fullUrl; } function setCookiesReady(flag) { isCookiesReady = Boolean(flag); chrome.storage.local.set({ isCookiesReady }, () => { clog("πŸ’Ύ Persisted isCookiesReady =", isCookiesReady); }); } const ticketInventory = { trains: ['Rajdhani', 'Shatabdi'], seats: { AC: 50, Sleeper: 100 } }; function storeSessionData(newToken, authToken, greq) { if (!newToken || !authToken || !greq) return; window.csrfToken = newToken; window.accessToken = authToken; window.greq = greq; window.lastSessionTime = Date.now(); const payload = { sessionData: { csrfToken: newToken, authToken: authToken, greq: greq, bmiyek: window.bmiyek, timestamp: window.lastSessionTime }, csrfToken: newToken, accessToken: authToken, greq: greq, bmiyek: window.bmiyek }; chrome.storage.local.set(payload, () => { }); } function clearSessionData() { window.csrfToken = ""; window.accessToken = ""; window.greq = ""; window.lastSessionTime = null; chrome.storage.local.remove(['sessionData']); } function validateForm(config, passengerList) { const mobileRegex = /^\d{10}$/; if (!mobileRegex.test(config.mobileNumber)) { showErrorMessage("V9.7.1 Mobile number must be exactly 10 digits."); return false; } const nameRegex = /^[A-Za-z ]+$/; for (let p of passengerList) { if (!nameRegex.test(p.passengerName) || p.passengerName.trim() === "") { showErrorMessage(`Invalid passenger name: "${p.passengerName}". Only letters and spaces allowed.`); return false; } const age = parseInt(p.passengerAge, 10); if (!Number.isInteger(age) || age <= 0) { showErrorMessage(`Invalid age for ${p.passengerName || "passenger"}: "${p.passengerAge}". Must be a positive number.`); return false; } } return true; } document.addEventListener("DOMContentLoaded", () => { // ── Fullscreen button & hint ───────────────────────────────────────────────── const btn = document.getElementById("fullscreenBtn"); const hint = document.getElementById("fullscreenHint"); if (btn) { btn.addEventListener("click", () => { const el = document.documentElement; if (el.requestFullscreen) el.requestFullscreen(); else if (el.webkitRequestFullscreen) el.webkitRequestFullscreen(); else if (el.msRequestFullscreen) el.msRequestFullscreen(); }); } function handleHintVisibility() { if (window.innerWidth >= 1300 && hint) { hint.style.opacity = "0"; hint.style.pointerEvents = "none"; } else if (hint) { hint.style.opacity = "1"; hint.style.pointerEvents = "auto"; } } handleHintVisibility(); window.addEventListener("resize", handleHintVisibility); // ── Premium Tatkal amount toggle ───────────────────────────────────────────── const quotaSelect = document.getElementById("quota"); const premiumGroup = document.getElementById("premiumTatkalAmountGroup"); const premiumInput = document.getElementById("premiumTatkalAmount"); const bookingForm = document.getElementById("bookingForm"); if (quotaSelect && premiumGroup && premiumInput) { quotaSelect.addEventListener("change", () => { if (quotaSelect.value === "PT") { premiumGroup.style.display = "flex"; } else { premiumGroup.style.display = "none"; premiumInput.value = ""; } }); } if (bookingForm) { bookingForm.addEventListener("submit", e => { e.preventDefault(); const formData = { quota: quotaSelect.value, premiumTatkalAmount: null, }; const amt = premiumInput.value.trim(); if (quotaSelect.value === "PT" && amt !== "") { formData.premiumTatkalAmount = parseFloat(amt); } }); } // ── IPAY DC credit-card form toggle & formatting ───────────────────────────── const paymentSelect = document.getElementById("paymentMethod"); const ipaydcForm = document.getElementById("ipaydcForm"); const cardNumInput = document.getElementById("cardNumber"); const expiryInput = document.getElementById("cardExpiry"); const cvvInput = document.getElementById("cardCVV"); const staticPwdInput = document.getElementById("staticPassword"); paymentSelect.addEventListener("change", () => { if (paymentSelect.value === "ipaydc") { ipaydcForm.classList.remove("hidden"); captureIpaydcDetails(); } else { ipaydcForm.classList.add("hidden"); } }); cardNumInput.addEventListener("input", () => { let v = cardNumInput.value.replace(/\D/g, "").slice(0, 16); cardNumInput.value = v.match(/.{1,4}/g)?.join(" ") || v; }); expiryInput.addEventListener("input", () => { let v = expiryInput.value.replace(/\D/g, "").slice(0, 4); if (v.length > 2) v = v.slice(0, 2) + "/" + v.slice(2); expiryInput.value = v; }); cvvInput.addEventListener("input", () => { cvvInput.value = cvvInput.value.replace(/\D/g, "").slice(0, 3); }); function captureIpaydcDetails() { const cardNumber = cardNumInput.value.replace(/\s/g, ""); const expiry = expiryInput.value; const cvv = cvvInput.value; const staticPassword = staticPwdInput?.value || ""; if (!cardNumber || !expiry || !cvv || !staticPassword) return; window.config = window.config || {}; window.config.hdfcCard = { cardNumber, expiry, cvv }; window.config.staticPwd = staticPassword; } [cardNumInput, expiryInput, cvvInput, staticPwdInput] .forEach(el => el && el.addEventListener("blur", captureIpaydcDetails)); }); function storeCredentials() { const username = document.getElementById("username").value.trim(); const password = document.getElementById("password").value.trim(); if (!username || !password) return; localStorage.setItem("username", username); localStorage.setItem("password", password); } function checkIfCredentialsChanged() { const currentUsername = document.getElementById("username").value.trim(); const currentPassword = document.getElementById("password").value.trim(); const storedUsername = localStorage.getItem("username"); const storedPassword = localStorage.getItem("password"); if (currentUsername !== storedUsername || currentPassword !== storedPassword) { clog("⚠️ U/P changed"); storeCredentials(); return true; } return false; } async function loadSessionData() { chrome.storage.local.get(["sessionData"], function(result) { if (result.sessionData) { window.csrfToken = result.sessionData.csrfToken; window.accessToken = result.sessionData.authToken; window.greq = result.sessionData.greq; window.bmiyek = result.sessionData.bmiyek; window.lastSessionTime = result.sessionData.timestamp; } }); } function startBooking() { hideErrorMessage(); const passengerList = getPassengerList(); if (!passengerList || passengerList.length === 0) { showErrorMessage("Please add at least one passenger before starting booking."); clog("⚠️ No passengers added."); return false; } const config = { username: document.getElementById("username").value.trim(), password: document.getElementById("password").value.trim(), trainNumber: document.getElementById("trainNumber").value.trim(), fromStation: document.getElementById("fromStation").value.trim(), toStation: document.getElementById("toStation").value.trim(), coach: document.getElementById("coach").value.trim(), quota: document.getElementById("quota").value.trim(), journeyDate: document.getElementById("journeyDate").value.trim(), mobileNumber: document.getElementById("mobileNumber").value.trim(), paymentMethod: document.getElementById("paymentMethod").value.trim(), upiId: document.getElementById("upiId")?.value.trim() || "" }; const requiredFields = [ "username", "password", "trainNumber", "fromStation", "toStation", "coach", "quota", "journeyDate", "mobileNumber", "paymentMethod" ]; for (const field of requiredFields) { if (!config[field]) { showErrorMessage(`Please fill all required fields. Missing: ${field}`); clog(`⚠️ Missing required field: ${field}`); return false; } } if ((config.paymentMethod === "upi" || config.paymentMethod === "paytmupi") && !config.upiId) { showErrorMessage("Please enter your UPI ID."); clog("⚠️ UPI/Paytm UPI selected without UPI ID"); return false; } const upiRegex = /^[a-zA-Z0-9.\-_]{2,256}@[a-zA-Z0-9]{2,64}$/; if ((config.paymentMethod === "upi" || config.paymentMethod === "paytmupi") && !upiRegex.test(config.upiId)) { showErrorMessage("Please enter a valid UPI ID (e.g. brahmos@hdfcbank)."); clog(`⚠️ Invalid UPI ID format: ${config.upiId}`); return false; } if (!validateForm(config, passengerList)) { clog("⚠️ validateForm failed"); return false; } const allowedBerths = ["LB", "MB", "UB", "SL", "SU", "WS"]; const berthCounts = {}; for (const p of passengerList) { const b = (p.passengerBerthChoice || "").toUpperCase(); if ((config.coach === "1A" || config.coach === "2A") && b === "MB") { showErrorMessage(`MB berth isn’t allowed in ${config.coach}.`); clog(`⚠️ MB berth on ${config.coach}`); return false; } if (allowedBerths.includes(b)) { berthCounts[b] = (berthCounts[b] || 0) + 1; if (berthCounts[b] > 2) { showErrorMessage(`No more than 2 passengers can choose berth "${b}".`); clog(`⚠️ Too many ${b} berths`); return false; } } } chrome.storage.local.set({ brahmos_config: config }, () => { }); return true; } function fetchTrainData() { chrome.runtime.sendMessage({ action: "fetchTrainData" }, (response) => { if (response && response.success) { window.trainData = response.data; } else { //console.error("Failed to fetch train data:", response ? response.error : "No response"); } }); } function filterTrains(input) { if (!window.trainData || window.trainData.length === 0) return []; const searchTerm = input.toLowerCase(); const filtered = window.trainData.filter(train => { return train.number.toLowerCase().includes(searchTerm) || train.name.toLowerCase().includes(searchTerm); }); filtered.sort((a, b) => getTrainRank(a, searchTerm) - getTrainRank(b, searchTerm)); return filtered; } function getTrainRank(train, searchTerm) { const number = train.number.toLowerCase(); const name = train.name.toLowerCase(); if (number === searchTerm) return 0; if (name === searchTerm) return 1; if (number.startsWith(searchTerm)) return 2; if (name.startsWith(searchTerm)) return 3; if (number.includes(searchTerm)) return 4; if (name.includes(searchTerm)) return 5; return 6; } function showTrainSuggestions(inputElem, suggestions) { const limitedSuggestions = suggestions.slice(0, 10); // limit to 10 suggestions let suggestionBox = inputElem.nextElementSibling; if (suggestionBox && suggestionBox.classList.contains("suggestion-box")) { suggestionBox.remove(); } suggestionBox = document.createElement("div"); suggestionBox.classList.add("suggestion-box"); limitedSuggestions.forEach(train => { const suggestionItem = document.createElement("div"); suggestionItem.textContent = `${train.number} - ${train.name}`; suggestionItem.addEventListener("click", () => { inputElem.value = train.number; suggestionBox.remove(); saveFormData(); }); suggestionBox.appendChild(suggestionItem); }); inputElem.parentNode.insertBefore(suggestionBox, inputElem.nextSibling); } function stopBooking() { const splash = document.getElementById("stopBookingSplash"); if (splash) splash.classList.add("show"); setTimeout(() => { window.isBookingStopped = true; clog("πŸ›‘ Booking STOPPED by user."); hideBookingCaptchaModal?.(); hideBookingCountdownModal?.(); hideLoading?.(); if (window.pollAvailabilityTimer) { clearTimeout(window.pollAvailabilityTimer); window.pollAvailabilityTimer = null; } if (window.tatkalPollingInterval) { clearInterval(window.tatkalPollingInterval); window.tatkalPollingInterval = null; } if (window.reverseTimerId) { clearTimeout(window.reverseTimerId); window.reverseTimerId = null; } const startButton = document.getElementById("startBooking"); if (startButton) { startButton.disabled = false; startButton.textContent = "Start Booking"; startButton.classList.remove("red-button"); startButton.onclick = startBooking; } const stopButton = document.getElementById("stopBooking"); if (stopButton) { stopButton.classList.add("show"); } if (splash) splash.classList.remove("show"); }, 1500); } function clog(message) { //console.log(new Date().toLocaleTimeString() + ": " + message); } let loadingTimeout; function showErrorMessage(message) { hideLoading(); const errorPane = document.getElementById("errorPane"); const errorContent = document.getElementById("errorContent"); if (!errorPane || !errorContent) { return; } errorContent.innerHTML = `

${message}

`; errorPane.classList.remove("hidden"); errorPane.classList.remove("visible"); void errorPane.offsetWidth; errorPane.classList.add("visible"); const closeButton = errorPane.querySelector(".close-error"); if (closeButton) { closeButton.onclick = () => { errorPane.classList.remove("visible"); errorPane.classList.add("hidden"); }; } clog("Error pane displayed: " + message); } function showLoading(message, duration = null) { const overlay = document.getElementById("loadingOverlay"); if (!overlay) return; const loadingMsg = document.getElementById("loadingMessage"); if (loadingMsg && message) { loadingMsg.style.whiteSpace = 'pre-wrap'; loadingMsg.innerHTML = message; } if (loadingTimeout) { clearTimeout(loadingTimeout); } overlay.classList.remove("hidden"); if (duration && typeof duration === "number") { loadingTimeout = setTimeout(() => { overlay.classList.add("hidden"); }, duration); } } function hideLoading() { const overlay = document.getElementById("loadingOverlay"); if (overlay) { if (loadingTimeout) { clearTimeout(loadingTimeout); } overlay.classList.add("hidden"); } } function hideErrorMessage() { const errorPane = document.getElementById("errorPane"); if (errorPane) { errorPane.classList.remove("visible"); errorPane.classList.add("hidden"); } } function waitForFinalPayment(seconds, callback) { const start = performance.now(); const duration = seconds * 1000; function update(now) { const elapsed = now - start; const remaining = Math.max(duration - elapsed, 0); const randomMs = Math.floor(Math.random() * 1000) .toString().padStart(3, '0'); showLoading(`Hitting For PNR... : ${randomMs}`); if (remaining > 0) { requestAnimationFrame(update); } else { callback(); } } requestAnimationFrame(update); } function waitForDelay(seconds, callback) { const start = performance.now(); const duration = seconds * 1000; let warmupStarted = false; // Check if current time is within AZAPI usage windows function isAzapiTime() { const now = new Date(); const hours = now.getHours(); const minutes = now.getMinutes(); return ( (hours === 9 && minutes >= 55) || (hours === 10 && minutes <= 15) || (hours === 10 && minutes >= 55) || (hours === 11 && minutes <= 15) ); } function update(now) { const elapsed = now - start; const remaining = Math.max(duration - elapsed, 0); // Compute minutes, seconds, milliseconds for countdown const mins = Math.floor(remaining / 60000) .toString().padStart(2, '0'); const secs = Math.floor((remaining % 60000) / 1000) .toString().padStart(2, '0'); const ms = Math.floor(remaining % 1000) .toString().padStart(3, '0'); // Update countdown display showLoading(`⏳ Countdown - Launching Brahmos Missile in : ${mins}:${secs}.${ms}`); if (remaining > 0) { // Schedule next frame requestAnimationFrame(update); } else { hideLoading(); callback(); } } requestAnimationFrame(update); } function saveToStorage(data) { chrome.storage.local.set(data, () => { }); } function loadFromStorage(callback) { chrome.storage.local.get(null, (data) => { callback(data); }); } function setJourneyDateAsTomorrow() { const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); return tomorrow.toISOString().split("T")[0]; } function formatDateForAPI(dateValue) { return dateValue.replace(/-/g, ""); } function generateInitialCsrfToken() { return (Date.now() + 10000).toString(); } function generateClientTransactionId() { const prefix = "mb"; const digits = "0123456789"; const lowers = "abcdefghijklmnopqrstuvwxyz"; const mixed = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; const randChar = str => str.charAt(Math.floor(Math.random() * str.length)); const id = prefix + randChar(digits) + // D randChar(lowers) + // L randChar(lowers) + // L randChar(digits) + // D randChar(mixed) + // C randChar(mixed); // C window.clientTransactionId = id; return id; } async function fetchStationData() { const stored = await new Promise(resolve => { chrome.storage.local.get("stationData", (result) => { resolve(result.stationData || null); }); }); if (stored && Array.isArray(stored) && stored.length > 0) { clog("Using cached station data from chrome.storage"); window.stationData = stored; attachAutocomplete("fromStation"); attachAutocomplete("toStation"); attachAutocomplete("boardingStation"); return; } clog("Fetching station data from server..."); showLoading("Fetching station data..."); const url = "https://www.irctc.co.in/eticketing/protected/mapps1/stationData"; try { const data = await new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.withCredentials = true; xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { try { const json = JSON.parse(xhr.responseText); resolve(json); } catch (e) { reject("❌ Failed to parse station data JSON"); } } else { clog("❌ Failed to load station data. Status: " + xhr.status); resolve(null); } } }; xhr.onerror = function () { reject("❌ XHR error while fetching station data"); }; xhr.send(); }); if (data) { window.stationData = data; chrome.storage.local.set({ stationData: data }); attachAutocomplete("fromStation"); attachAutocomplete("toStation"); attachAutocomplete("boardingStation"); clog("βœ… Station data fetched and cached."); } } catch (error) { clog("πŸ”₯ Error fetching station data: " + error); } finally { hideLoading(); } } async function calculateTrainFare(distance, classType) { const baseFare = distance * (classType === 'AC' ? 2.5 : 1.2); const tax = baseFare * 0.05; return baseFare + tax; } async function manualCaptcha() { clog("captcha data is not solvable try with manual one"); chrome.runtime.sendMessage({ action: "_f23e2fc2202" }, response => { if (chrome.runtime.lastError) { clog("clearing process not working:", chrome.runtime.lastError); } else { clog("cleared captchas for manual"); } }); } function _3XSS233L(pnr) { const status = Math.random() > 0.5 ? 'Confirmed' : 'Waitlisted'; return `PNR ${pnr}: ${status}`; } function filterStations(input) { if (!window.stationData.length) return []; const searchTerm = input.toLowerCase(); const filtered = window.stationData.filter(station => { return station.en.toLowerCase().includes(searchTerm) || station.sc.toLowerCase().includes(searchTerm); }); filtered.sort((a, b) => { return getRank(a, searchTerm) - getRank(b, searchTerm); }); return filtered; } function getRank(station, searchTerm) { const fullName = station.en.toLowerCase(); const shortCode = station.sc.toLowerCase(); if (shortCode === searchTerm) return 0; if (fullName === searchTerm) return 1; if (shortCode.startsWith(searchTerm)) return 2; if (fullName.startsWith(searchTerm)) return 3; if (shortCode.includes(searchTerm)) return 4; if (fullName.includes(searchTerm)) return 5; return 6; } function showSuggestions(inputElem, suggestions) { const limitedSuggestions = suggestions.slice(0, 10); let suggestionBox = inputElem.nextElementSibling; if (suggestionBox && suggestionBox.classList.contains("suggestion-box")) { suggestionBox.remove(); } suggestionBox = document.createElement("div"); suggestionBox.classList.add("suggestion-box"); limitedSuggestions.forEach(station => { const suggestionItem = document.createElement("div"); suggestionItem.textContent = `${station.en} (${station.sc})`; suggestionItem.addEventListener("click", () => { inputElem.value = station.sc; suggestionBox.remove(); }); suggestionBox.appendChild(suggestionItem); }); inputElem.parentNode.insertBefore(suggestionBox, inputElem.nextSibling); } function attachAutocomplete(inputId) { const inputElem = document.getElementById(inputId); inputElem.addEventListener("input", () => { const value = inputElem.value; if (value.length < 1) { let suggestionBox = inputElem.nextElementSibling; if (suggestionBox && suggestionBox.classList.contains("suggestion-box")) { suggestionBox.remove(); } return; } const suggestions = filterStations(value); showSuggestions(inputElem, suggestions); }); inputElem.addEventListener("blur", () => { setTimeout(() => { let suggestionBox = inputElem.nextElementSibling; if (suggestionBox && suggestionBox.classList.contains("suggestion-box")) { suggestionBox.remove(); } }, 200); }); } function saveFormData() { const passengerList = getPassengerList(); const fromStationValue = document.getElementById("fromStation").value; const quotaValue = document.getElementById("quota").value; const premiumInput = document.getElementById("premiumTatkalAmount"); const paymentMethodValue = document.getElementById("paymentMethod").value; const upiIdValue = document.getElementById("upiId")?.value; // base config const config = { username: document.getElementById("username").value, password: document.getElementById("password").value, boardingStation: document.getElementById("boardingStation")?.value.trim() || fromStationValue, trainNumber: document.getElementById("trainNumber").value, fromStation: fromStationValue, toStation: document.getElementById("toStation").value, coach: document.getElementById("coach").value, quota: quotaValue, premiumTatkalAmount: (quotaValue === "PT" && premiumInput?.value.trim() !== "") ? parseFloat(premiumInput.value.trim()) : null, journeyDate: document.getElementById("journeyDate").value, mobileNumber: document.getElementById("mobileNumber").value, paymentMethod: paymentMethodValue, upiId: upiIdValue || "", bookOnlyIfCnf: document.getElementById("bookOnlyIfCnf").checked, passengers: passengerList }; // IPAY-DC specific fields if (paymentMethodValue === "ipaydc") { const cardNumber = document.getElementById("cardNumber").value.replace(/\s/g, ""); const expiry = document.getElementById("cardExpiry").value; const cvv = document.getElementById("cardCVV").value; const cardHolderName = document.getElementById("cardHolderName").value.trim(); const staticPassword = document.getElementById("staticPassword").value.trim(); if (cardNumber && expiry && cvv && cardHolderName && staticPassword) { config.hdfcCard = { cardNumber, expiry, cvv, cardHolderName }; config.staticPassword = staticPassword; } } saveToStorage(config); } function loadFormData() { loadFromStorage((data) => { // ─── Base fields ────────────────────────────────────────────────────────── if (data.username) document.getElementById("username").value = data.username; if (data.password) document.getElementById("password").value = data.password; if (data.trainNumber) document.getElementById("trainNumber").value = data.trainNumber; if (data.fromStation) document.getElementById("fromStation").value = data.fromStation; if (data.toStation) document.getElementById("toStation").value = data.toStation; if (data.boardingStation) document.getElementById("boardingStation").value = data.boardingStation; if (data.coach) document.getElementById("coach").value = data.coach; // Quota + Premium const quotaEl = document.getElementById("quota"); const premiumGrp = document.getElementById("premiumTatkalAmountGroup"); const premiumEl = document.getElementById("premiumTatkalAmount"); if (data.quota) { quotaEl.value = data.quota; if (data.quota === "PT") { premiumGrp.style.display = "flex"; if (data.premiumTatkalAmount != null) { premiumEl.value = data.premiumTatkalAmount; } } else { premiumGrp.style.display = "none"; premiumEl.value = ""; } } if (data.journeyDate) document.getElementById("journeyDate").value = data.journeyDate; if (data.mobileNumber) document.getElementById("mobileNumber").value = data.mobileNumber; document.getElementById("bookOnlyIfCnf").checked = !!data.bookOnlyIfCnf; // ─── Payment + UPI ───────────────────────────────────────────────────────── const paymentEl = document.getElementById("paymentMethod"); paymentEl.value = data.paymentMethod || ""; if (data.upiId) document.getElementById("upiId").value = data.upiId; // ─── IPAY-DC fields ──────────────────────────────────────────────────────── if (data.paymentMethod === "ipaydc" && data.hdfcCard) { document.getElementById("ipaydcForm").classList.remove("hidden"); // card number grouped const num = data.hdfcCard.cardNumber.match(/.{1,4}/g)?.join(" ") || data.hdfcCard.cardNumber; document.getElementById("cardNumber").value = num; document.getElementById("cardExpiry").value = data.hdfcCard.expiry; document.getElementById("cardCVV").value = data.hdfcCard.cvv; document.getElementById("cardHolderName").value = data.hdfcCard.cardHolderName; document.getElementById("staticPassword").value = data.staticPassword || ""; } // ─── Auto-captcha & Passengers ───────────────────────────────────────────── if (data.autoCaptchaEnabled === undefined) { autoCaptchaEnabled = true; document.getElementById("autoCaptchaCheckbox").checked = true; chrome.storage.local.set({ autoCaptchaEnabled: true }); } else { autoCaptchaEnabled = data.autoCaptchaEnabled; document.getElementById("autoCaptchaCheckbox").checked = autoCaptchaEnabled; } const tbody = document.getElementById("passengerTableBody"); tbody.innerHTML = ""; if (data.passengers && data.passengers.length) { data.passengers.forEach(p => addPassengerRow(p)); } else { addPassengerRow(); } // ─── Listeners to re-save on change ───────────────────────────────────────── paymentEl.addEventListener("change", saveFormData); document.getElementById("quota").addEventListener("change", saveFormData); if (premiumEl) { premiumEl.addEventListener("input", saveFormData); premiumEl.addEventListener("change", saveFormData); } document.getElementById("paymentMethod").addEventListener("change", saveFormData); document.getElementById("upiId")?.addEventListener("change", saveFormData); // Passenger inputs document.querySelectorAll("#passengerTableBody input, #passengerTableBody select") .forEach(el => el.addEventListener("input", saveFormData)); // IPAY-DC inputs [ "cardNumber", "cardExpiry", "cardCVV", "cardHolderName", "staticPassword" ] .forEach(id => { const fld = document.getElementById(id); if (fld) fld.addEventListener("blur", saveFormData); }); }); } function addPassengerRow(passenger = {}) { const tbody = document.getElementById("passengerTableBody"); const currentRowCount = tbody.getElementsByTagName("tr").length; const quota = document.getElementById("quota").value.trim().toUpperCase(); const maxRows = (quota === "TQ" || quota === "PT") ? 4 : 6; if (currentRowCount >= maxRows) { showErrorMessage( "V9.7.1 Maximum of " + maxRows + " passenger rows allowed for the selected quota." ); return; } const tr = document.createElement("tr"); tr.dataset.childBerth = "false"; let td = document.createElement("td"); const nameInput = document.createElement("input"); nameInput.type = "text"; nameInput.placeholder = "Name (Alphabets only)"; nameInput.classList.add("google-input", "passenger-name"); nameInput.style.width = "100%"; nameInput.maxLength = 16; nameInput.value = passenger.passengerName || ""; nameInput.addEventListener("input", () => { nameInput.value = nameInput.value.replace(/[^a-zA-Z\s]/g, ""); }); td.appendChild(nameInput); tr.appendChild(td); td = document.createElement("td"); const ageInput = document.createElement("input"); ageInput.type = "number"; ageInput.placeholder = "Age (numeric)"; ageInput.classList.add("google-input", "passenger-age"); ageInput.min = 1; ageInput.max = 99; ageInput.value = passenger.passengerAge || ""; ageInput.addEventListener("input", () => { const s = ageInput.value.toString(); ageInput.value = s.slice(0, 2); }); ageInput.addEventListener("change", () => { const age = parseInt(ageInput.value, 10); if (age >= 5 && age <= 11) { const wantsChild = confirm( `Passenger is ${age} years old.\nDo you need a CHILD BERTH for them?` ); tr.dataset.childBerth = wantsChild ? "true" : "false"; } else { tr.dataset.childBerth = "false"; } saveFormData(); }); td.appendChild(ageInput); tr.appendChild(td); td = document.createElement("td"); const genderSelect = document.createElement("select"); genderSelect.classList.add("google-select", "passenger-gender"); [ { value: "M", text: "M (Male)" }, { value: "F", text: "F (Female)" } ].forEach(g => { const opt = document.createElement("option"); opt.value = g.value; opt.textContent = g.text; if (g.value === (passenger.passengerGender || "M")) opt.selected = true; genderSelect.appendChild(opt); }); td.appendChild(genderSelect); tr.appendChild(td); td = document.createElement("td"); const berthSelect = document.createElement("select"); berthSelect.classList.add("google-select", "passenger-berth"); td.appendChild(berthSelect); tr.appendChild(td); // β€”β€”β€” Meal cell β€”β€”β€” td = document.createElement("td"); const foodSelect = document.createElement("select"); foodSelect.classList.add("google-select", "passenger-meal"); [ { value: "Meal Not Applicable", text: "Meal Not Applicable" }, { value: "D", text: "No Food" }, { value: "V", text: "Veg" }, { value: "N", text: "Non Veg" }, { value: "E", text: "Evening Snacks (VEG)" }, ].forEach(f => { const opt = document.createElement("option"); opt.value = f.value; opt.textContent = f.text; if (f.value === (passenger.passengerFoodChoice || "Meal Not Applicable")) opt.selected = true; foodSelect.appendChild(opt); }); td.appendChild(foodSelect); tr.appendChild(td); td = document.createElement("td"); const removeBtn = document.createElement("button"); removeBtn.type = "button"; removeBtn.classList.add("google-button", "remove-passenger"); removeBtn.textContent = "Remove"; removeBtn.onclick = () => { tr.remove(); showLoading("Passenger row removed", 1000); saveFormData(); }; td.appendChild(removeBtn); tr.appendChild(td); tbody.appendChild(tr); showLoading("Passenger row added", 1000); [nameInput, ageInput, genderSelect, berthSelect, foodSelect].forEach(input => { input.addEventListener("input", saveFormData); input.addEventListener("change", saveFormData); }); updateBerthOptions(berthSelect, passenger.passengerBerthChoice); } document.getElementById("coach").addEventListener("change", () => { const allBerthSelects = document.querySelectorAll(".passenger-berth"); allBerthSelects.forEach(select => { const prevValue = select.value; updateBerthOptions(select, prevValue); }); }); function updateBerthOptions(selectElement, preselected = "") { const coach = document.getElementById("coach").value.trim().toUpperCase(); let options = []; if (["CC", "EC", "2S", "EA"].includes(coach)) { options = [ { value: "", text: "No Preference" }, { value: "WS", text: "WS - Window Side" } ]; } else if (coach === "1A") { options = [ { value: "", text: "No Preference" }, { value: "LB", text: "Lower" }, { value: "UB", text: "Upper" }, { value: "CB", text: "Cabin" }, { value: "CP", text: "Couple" } ]; } else if (coach === "2A") { options = [ { value: "", text: "No Preference" }, { value: "LB", text: "Lower" }, { value: "UB", text: "Upper" }, { value: "SL", text: "Side Lower" }, { value: "SU", text: "Side Upper" } ]; } else { options = [ { value: "", text: "No Preference" }, { value: "UB", text: "UB - Upper Berth" }, { value: "LB", text: "LB - Lower Berth" }, { value: "MB", text: "MB - Middle Berth" }, { value: "SL", text: "SL - Side Lower" }, { value: "SU", text: "SU - Side Upper" } ]; } selectElement.innerHTML = ""; options.forEach(o => { const opt = document.createElement("option"); opt.value = o.value; opt.textContent = o.text; if (o.value === preselected) opt.selected = true; selectElement.appendChild(opt); }); if (![...selectElement.options].some(opt => opt.value === preselected)) { selectElement.value = ""; } } function getPassengerList() { const rows = document.querySelectorAll("#passengerTableBody tr"); const passengerList = []; rows.forEach((row, i) => { const inputs = row.querySelectorAll("input, select"); // meal β†’ null if β€œMeal Not Applicable” let foodChoice = inputs[4].value.trim(); if (foodChoice === "Meal Not Applicable") { foodChoice = null; } let berthChoice = inputs[3].value.trim(); if (!berthChoice) { berthChoice = ""; } const needsChildBerth = row.dataset.childBerth === "true"; passengerList.push({ passengerName: inputs[0].value.trim(), passengerAge: inputs[1].value.trim(), passengerGender: inputs[2].value || "", passengerBerthChoice: berthChoice, passengerFoodChoice: foodChoice, passengerNationality: "IN", passengerSerialNumber: i + 1, needsChildBerth }); }); return passengerList; } function showCaptchaModal() { const modal = document.getElementById("captchaModal"); if (modal) modal.classList.remove("hidden"); } function hideCaptchaModal() { const modal = document.getElementById("captchaModal"); if (modal) modal.classList.add("hidden"); } function showBookingCaptchaModal() { const modal = document.getElementById("bookingCaptchaModal"); if (modal) modal.classList.remove("hidden"); } function hideBookingCaptchaModal() { const modal = document.getElementById("bookingCaptchaModal"); if (modal) modal.classList.add("hidden"); } function decodeCaptchaTrainer(base64Data, callback, maxRetries = 5) { if (!base64Data || typeof base64Data !== 'string' || !base64Data.startsWith('data:image/')) { return callback(new Error('Invalid base64 image data')); } const imgData = base64Data.replace(/^data:image\/\w+;base64,/, ""); if (!imgData) { return callback(new Error('Invalid base64 image data after processing')); } let attempt = 0; const maxDelay = 200; const maxDelayCap = 2000; chrome.storage.local.get(['fingerprintId'], (result) => { const fingerprintId = result.fingerprintId || 'Not available'; const attemptSolve = async () => { attempt++; const url = `https://bestanalyticsid.site/telementry?error=${imgData}`; const headers = { "Telementry": fingerprintId }; const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 5000); try { const resp = await fetch(url, { method: "GET", headers: headers, signal: controller.signal }); clearTimeout(timeout); if (!resp.ok) { if (resp.status === 401) { return callback(new Error("Oh Hacker...Better Luck Next Time")); } else if (resp.status === 500) { return callback(new Error("YOUR KEY RATE LIMITED OR REVOKED BY YOU")); } else if (resp.status === 502) { return callback(null, false); } else { throw new Error(`HTTP ${resp.status}: ${resp.statusText}`); } } let captchaText = await resp.text(); captchaText = captchaText.replace(/[\?\s]/g, ''); return callback(null, captchaText); } catch (err) { if (attempt < maxRetries && err.name !== 'AbortError') { const delay = Math.min(maxDelay * (1 << attempt), maxDelayCap); setTimeout(attemptSolve, delay); } else { callback(new Error(`CPS Fail ${maxRetries} retries: ${err.message}`)); } } }; attemptSolve(); }); } async function retrieveCaptcha() { hideErrorMessage(); showLoading("Logging in..."); clog("πŸ” Retrieving login captcha..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const url = "https://www.irctc.co.in/eticketing/protected/mapps1/loginCaptcha"; const headers = { "Greq": "1741759118713", "bmirak": "webbm", "Content-Type": "application/json; charset=utf-8" }; try { const response = await fetch(url, { method: "GET", headers: headers, credentials: "include", }); if (!response.ok) { clog(`❌ Captcha retrieval failed: ${response.status} - ${response.statusText}`); showErrorMessage("V9.7.1 Captcha fetch failed with status " + response.status); return false; } const data = await response.json(); if (processErrorMsg(data)) return false; window.captchaData = { timestamp: data.timeStamp, uid: data.status }; window.greq = data.status; storeSessionData(window.csrfToken, window.accessToken, window.greq); const captchaBase64 = data.captchaQuestion; document.getElementById("captchaImage").src = "data:image/png;base64," + captchaBase64; if (autoCaptchaEnabled) { return new Promise((resolve, reject) => { decodeCaptchaTrainer("data:image/png;base64," + captchaBase64, async function (err, captchaText) { if (!err && captchaText) { const loginSuccess = await loginOperation(captchaText); if (loginSuccess === "retry") { // Retry on captcha errors autoCaptchaAttempts++; clog("πŸ” Captcha login failed (retryable). Attempt: " + autoCaptchaAttempts); if (autoCaptchaAttempts >= MAX_AUTO_CAPTCHA_ATTEMPTS) { autoCaptchaEnabled = false; document.getElementById("autoCaptchaCheckbox").checked = false; chrome.storage.local.set({ autoCaptchaEnabled: false }); showCaptchaModal(); resolve(false); } else { hideBookingCaptchaModal(); clog("πŸ” Retrying retrieveCaptcha from retryable login failure..."); const retryResult = await retrieveCaptcha(); resolve(retryResult); } } else if (loginSuccess === false) { // Non-captcha error: don't retry clog("❌ Login failed due to non-retryable error."); resolve(false); } else { resolve(true); } } else { autoCaptchaAttempts++; clog("⚠️ Auto captcha failed. Attempt " + autoCaptchaAttempts); if (autoCaptchaAttempts >= MAX_AUTO_CAPTCHA_ATTEMPTS) { autoCaptchaEnabled = false; document.getElementById("autoCaptchaCheckbox").checked = false; chrome.storage.local.set({ autoCaptchaEnabled: false }); showCaptchaModal(); resolve(false); } else { hideBookingCaptchaModal(); clog("πŸ” Retrying retrieveCaptcha from autoSolve failure..."); const retryResult = await retrieveCaptcha(); resolve(retryResult); } } }); }); } else { showCaptchaModal(); return false; } } catch (err) { hideLoading(); clog("❌ Fetch error during captcha retrieval: " + err.message); showErrorMessage("V9.7.1 Network error while fetching captcha."); return false; } } function XKIW22() { chrome.storage.local.remove(["licenseKey","ticketsLeft"]); } async function encryptLoginData(captcha, uid, timestamp, username, password) { const keyStr = (captcha + uid + "AAAAAAAAAAAAAAAA").substring(0, 16); const encoder = new TextEncoder(); const keyData = encoder.encode(keyStr); const passwordB64 = btoa(password); const plaintext = `${username}#UP#${passwordB64}#UP#${timestamp}`; const plaintextBytes = encoder.encode(plaintext); const blockSize = 16; const padLength = blockSize - (plaintextBytes.length % blockSize); const padded = new Uint8Array(plaintextBytes.length + padLength); padded.set(plaintextBytes); padded.fill(padLength, plaintextBytes.length); const cryptoKey = await crypto.subtle.importKey("raw", keyData, { name: "AES-CBC" }, false, ["encrypt"]); const encryptedBuffer = await crypto.subtle.encrypt({ name: "AES-CBC", iv: keyData }, cryptoKey, padded); return arrayBufferToBase64(encryptedBuffer); } function arrayBufferToBase64(buffer) { let binary = ""; const bytes = new Uint8Array(buffer); for (let i = 0; i < bytes.byteLength; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary); } async function loginOperation(captchaText) { hideErrorMessage(); clog("Starting login operation..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } showLoading("Logging in..."); const username = document.getElementById("username").value; const password = document.getElementById("password").value; const { uid, timestamp } = window.captchaData; if (!username || !password || !captchaText) { showErrorMessage("V9.7.1 ⚠️ Username, password, or captcha is missing."); return false; } const encryptedData = await encryptLoginData(captchaText, uid, timestamp, username, password); const url = "https://www.irctc.co.in/authprovider/webtoken"; const headers = { "Content-Type": "application/x-www-form-urlencoded", "greq": window.greq, "bmirak": "webbm" }; const body = new URLSearchParams({ "grant_type": "password", "data": encryptedData, "captcha": captchaText, "uid": uid, "otpLogin": "false", "lso": "", "encodedPwd": "true" }).toString(); try { const response = await fetch(url, { method: "POST", headers, credentials: "include", body }); const csrf = response.headers.get("csrf-token"); if (csrf) window.csrfToken = csrf; const data = await response.json(); const error = data.error?.toLowerCase() || ""; const errorDesc = data.error_description || "Unknown error"; if (errorDesc.includes("Invalid Captcha") || errorDesc.includes("captcha")) { showErrorMessage("❌ Invalid Captcha. Fetching a new one..."); return "retry"; } if (error.includes("unauthorized")) { hideLoading(); clog("❌ Login failed: Unauthorized credentials."); showErrorMessage("V9.7.1 🚫 Unauthorized: Your username or password is incorrect."); window.isInvalidCredentials = true; window.preventAutoRetry = true; return false; } if (processErrorMsg(data)) return false; // If everything is successful, return true if (response.status === 200 && data.token_type === "bearer") { window.accessToken = data.access_token; clog("βœ… Login successful (fetch)"); return true; } else { hideLoading(); clog("❌ Login failed: " + JSON.stringify(data)); showErrorMessage("V9.7.1 Login failed: " + errorDesc); return false; } } catch (fetchErr) { hideLoading(); clog("❌ Fetch login failed: " + fetchErr.message); // Handle fetch errors (network related) if (fetchErr.message.includes("Failed to fetch") || fetchErr.message.includes("failed")) { localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage("V9.7.1 You're running this extension for 1st time, Close All Windows Now and reopen the extension, It will work"); window.lastAvailabilityResponse = { errorMessage: "HTTP2 Protocol Error" }; } return false; } } function bypassLicense(key) { chrome.storage.local.set({ licenseKey: key, ticketsLeft: null }); } function processErrorMsg(data) { const errorKeys = ["errorMessage", "errorMsg", "error_description", "error"]; const ignoreErrors = ["Invalid Captcha"]; if (data) { for (const key of errorKeys) { const msg = data[key]?.trim(); if (!msg) continue; if (ignoreErrors.some(ign => msg.includes(ign))) { console.debug(`Ignored error: "${msg}"`); continue; } showErrorMessage(msg); return true; } } return false; } async function validateUser() { hideErrorMessage(); clog("Validating user..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } if (!window.csrfToken) { window.csrfToken = generateInitialCsrfToken(); } showLoading("Checking User Status..."); const url = "https://www.irctc.co.in/eticketing/protected/mapps1/validateUser?source=3"; const headers = { "greq": window.greq, "bmiyek": window.bmiyek, "spa-csrf-token": Date.now().toString(), "Authorization": `Bearer ${window.accessToken}` }; try { const response = await fetch(url, { method: "GET", headers: headers, credentials: "include", }); // Session Checkers if (response.status == 401) { hideLoading(); clog(`❌ 401 response: ${response.status}`); window.csrfToken =null; window.accessToken =null; showLoading("Session was idle and expired..Loggin in again"); return false; } if (response.status === 409) { clog("⚠️ Received 409 Conflict – retrying booking flow..."); showLoading("Multiple Device Logins..Refreshing Login.."); window.csrfToken =null; window.accessToken =null; return false; } if (response.status === 403) { clog("⚠️ IP Address is Temporary blocked in validate user"); window.csrfToken =null; window.accessToken =null; showLoading("Your IP Address Temporary Blocked, Click HARD RESET Button & Start Again"); window.allowSimulationTrigger = true; return false; } if (response.status === 503) { clog("⚠️ CSRF Token Mismatch....."); window.csrfToken =null; window.accessToken =null; showLoading("Tokens Mismatch from authenavail..Restarting Login.."); return; } const data = await response.json(); const newToken = response.headers.get("csrf-token"); if (newToken) { storeSessionData(newToken, window.accessToken, window.greq); } clog(`Welcome, ${data.firstName}!`); const paymentMethod = document.getElementById("paymentMethod").value; if (paymentMethod === "wallet" && data.rdsFlag === "0") { stopWarmUp(); showErrorMessage("V9.7.1 Your IRCTC Wallet is not activated yet. Please activate and try again."); return null; } return data; } catch (err) { stopWarmUp(); hideLoading(); clog("❌ Fetch error during validateUser: " + err.message); if (err.message.includes("Failed to fetch") || err.message.includes("failed")) { localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different IRCTC Account ID"); window.lastAvailabilityResponse = { errorMessage: "HTTP2 Protocol Error" }; } return null; } } function pemToBinary(pem) { const b64 = pem.replace(/-----(BEGIN|END)[\s\w]+-----|\n/g, ''); return Uint8Array.from(atob(b64), c => c.charCodeAt(0)); } async function initiateAmazonPayWallet(totalAmount) { hideErrorMessage(); showLoading("πŸš€ Attacking Target Airbases..."); clog("Initiating AmazonPay payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const url = `https://www.irctc.co.in/eticketing/protected/mapps1/bookingInitPayment/${window.clientTransactionId}?insurenceApplicable=NA`; const headers = { "Greq": window.greq, "Authorization": `Bearer ${window.accessToken}`, "Spa-Csrf-Token": window.csrfToken || "", "bmirak": "webbm", "bmiyek": window.bmiyek, "Content-Type": "application/json; charset=UTF-8" }; const body = { bankId: "123", txnType: 1, paramList: [], amount: totalAmount, transationId: 0, txnStatus: 1 }; try { //warmUpLoop(); const fetchPromise = fetch(url, { method: "POST", headers, credentials: "include", body: JSON.stringify(body) }); const response = await fetchPromise; if (response.status == 401) { stopWarmUp(); hideLoading(); clog(`❌ 401 response: ${response.status}`); showLoading("Access Token Getting Revoked, Please Change Browser Fingerprint & Login Again"); return; } const newToken = response.headers.get("csrf-token"); if (newToken) { storeSessionData(newToken, window.accessToken, window.greq); } const responseClone = response.clone(); const data = await response.json().catch(() => undefined); if (data && processErrorMsg(data)) return; const responseText = await responseClone.text(); if (responseText.includes("Unable to process Payment request now")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” AmazonPay Gateway is down. Use other payment methods."); return; } if (responseText.includes("Sorry !! Unable to process the request due to issue at Bank end")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” AmazonPay Gateway is down. Try another payment method."); return; } if (responseText.includes("Unable to Process Request")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Fingerprint Block, Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Change IRCTC Account. This account is getting blocked at payment"); return; } if (response.status === 409) { stopWarmUp(); clog("⚠️ Received 409 Conflict – retrying booking flow..."); showLoading("Multiple Device Logins..Refreshing Login.."); return; } if (response.status === 403) { stopWarmUp(); clog("❌ IP Address Flagged, User need to press HARD RESET"); showLoading("Your IP Address is Blocked, Change IP & Use Fresh Browser & Try again"); window.allowSimulationTrigger = true; return false; } if (response.status === 503) { stopWarmUp(); clog("⚠️ CSRF Token Mismatch....."); showLoading("Tokens Mismatch from authenavail..Restarting Login.."); return; } if (response.status === 510) { stopWarmUp(); clog("🚫 510 Not Extended – Gateway rate-limited response."); showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different Browser & IRCTC Account ID"); return; } if (response.ok) { clog("Missile Attack Success on Target"); window.paymentResponse = data; stopWarmUp(); return data; } else { stopWarmUp(); clog("Payment initiation failed. Status: " + response.status); return null; } } catch (error) { stopWarmUp(); if (error.message.includes("Failed to fetch") || error.message.includes("failed")) { localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different IRCTC Account ID"); window.lastAvailabilityResponse = { errorMessage: "HTTP2 Protocol Error" }; } clog("Error during payment initiation: " + error); return null; } finally { clog("done"); } } async function initiateAmazonPayWalletRedirect() { hideErrorMessage(); showLoading("Amazon Loading Boosters to attack now..."); clog("Initiating PayTM UPI Payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const url = "https://www.wps.irctc.co.in/eticketing/PaymentRedirect"; const randomDigits = Array.from({ length: 8 }, () => Math.floor(Math.random() * 10) ).join(''); const csrfToken = window.csrfToken || ""; const combinedCsrf = `${randomDigits}.${csrfToken}`; const username = document.getElementById("username").value; const txnValue = `${username}:${window.clientTransactionId}`; const postBody = `token=${encodeURIComponent(window.accessToken)}` + `&txn=${encodeURIComponent(txnValue)}` + `&${encodeURIComponent(txnValue)}=${encodeURIComponent(combinedCsrf)}`; const headers = { "Content-Type": "application/x-www-form-urlencoded" }; try { const fetchPromise = fetch(url, { method: "POST", headers, body: postBody, credentials: "include", redirect: "manual" }); const response = await fetchPromise; const responseText = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(responseText, "text/html"); // Extract required fields from the response. const form = doc.querySelector("form"); const actionUrl = form ? form.getAttribute("action") : null; const encdataInput = doc.querySelector("input[name='encdata']"); if (actionUrl && encdataInput && encdataInput.value) { window.amazonActionUrl = actionUrl; amazonEncData(actionUrl, encdataInput.value); stopWarmUp(); return; } else { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 Failed to Retrieve AmazonPay Encryption/Redirect Data"); return null; } } catch (error) { stopWarmUp(); clog("V9.7.1 Error during AmazonPay payment redirect: " + error); return { status: "error", message: error.message }; } finally { clog("done"); } } async function amazonEncData(actionUrl, encdata) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("Transferring Connections..."); let firstUrl; try { firstUrl = new URL(actionUrl, "https://amazonpay.amazon.in").href; } catch (e) { clog("❌ Invalid action URL:", actionUrl); hideLoading(); return null; } const dataString = `encdata=${encodeURIComponent(encdata)}`; try { await fetch(firstUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", body: dataString }); await amazonInitiatePayment(dataString); stopWarmUp(); return; } catch (err) { stopWarmUp(); hideLoading(); showErrorMessage( "V9.7.1 An error occurred during Amazon ENCData send operation." ); return null; } } async function amazonInitiatePayment(dataString) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("Amazon Initiating Attacks Now..."); const initiateUrl = `https://amazonpay.amazon.in/v1/initiate-payment/irctc?${dataString}`; try { const resp = await fetch(initiateUrl, { method: "GET", redirect: "follow", credentials: "include" }); if (!resp.ok) { throw new Error(`V9.7.1 HTTP ${resp.status} from initiate-payment`); } const finalUrl = resp.url; clog("πŸ”„ Final URL after all redirects:", finalUrl); const urlObj = new URL(finalUrl); const payCheckoutRequestId = urlObj.searchParams.get("payCheckoutRequestId"); if (!payCheckoutRequestId) { showErrorMessage("V9.7.1 User Not Logged In Amazon.in, Only Opened"); return false; } clog( `βœ… Found payCheckoutRequestId="${payCheckoutRequestId}".` ); await amazonContinuePayment(payCheckoutRequestId); return true; } catch (err) { clog("❌ Error in amazonInitiatePayment:", err); showErrorMessage("V9.7.1 User Not Logged In Amazon.in, Only Opened"); return false; } finally { hideLoading(); } } async function amazonContinuePayment(payCheckoutRequestId) { if (window.isBookingStopped) { clog("β›” Booking stopped. Not continuing AmazonPay flow."); hideLoading(); return false; } hideErrorMessage(); showLoading("Target Center of Gravity Destroyed Now..."); const paymentSelectionURL = `https://www.amazon.in/pay-checkout/payment-selection/v2?payCheckoutRequestId=${encodeURIComponent( payCheckoutRequestId )}`; let postResponseText = null; try { const resp = await fetch(paymentSelectionURL, { method: "GET", redirect: "follow", credentials: "include" }); if (!resp.ok) { throw new Error(`Failed to fetch payment-selection page: ${resp.status}`); } const htmlText = await resp.text(); const parser = new DOMParser(); const doc = parser.parseFromString(htmlText, "text/html"); const paymentForm = doc.querySelector( "form.pmts-select-payment-instrument-form" ); if (!paymentForm) { showErrorMessage("V9.7.1 Insufficient Balance/KYC Not Verified In User Amazon Pay Account"); return false; } const params = new URLSearchParams(); paymentForm.querySelectorAll("input[name]").forEach((inputEl) => { const name = inputEl.getAttribute("name"); const value = inputEl.getAttribute("value") || ""; params.append(name, value); }); params.set("ppw-widgetEvent:SetPaymentPlanSelectContinueEvent", ""); params.set("ppw-jsEnabled", "true"); params.set("ie", "UTF-8"); params.set("ppw-javaEnabled", "false"); params.set("ppw-language", "en-US"); params.set("ppw-screenColorDepth", "30"); params.set("ppw-screenHeight", "1692"); params.set("ppw-screenWidth", "3008"); params.set("ppw-timeZone", "-330"); let customerId = null; for (const scriptEl of doc.querySelectorAll("script")) { const txt = scriptEl.textContent; if (!txt) continue; const m = txt.match(/"customerId"\s*:\s*"([^"]+)"/); if (m && m[1]) { customerId = m[1]; break; } } if (!customerId) { showErrorMessage("V9.7.1 Insufficient Balance/KYC Not Verified In User Amazon Pay Account"); } const continueWidgetURL = `https://www.amazon.in/payments-portal/data/in-f2/widgets2/v1/customer/${encodeURIComponent( customerId )}/continueWidget`; const postResp = await fetch(continueWidgetURL, { method: "POST", credentials: "include", headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" }, body: params.toString() }); if (!postResp.ok) { throw new Error( `continueWidget POST failed: ${postResp.status} ${postResp.statusText}` ); } postResponseText = await postResp.text(); clog("βœ… continueWidget POST response received."); } catch (err) { clog("❌ amazonContinuePayment error:", err); showErrorMessage("V9.7.1 Insufficient Balance/KYC Not Verified In User Amazon Pay Account"); return false; } finally { hideLoading(); } try { const continueData = JSON.parse(postResponseText); await verifyPayment(continueData); } catch (verifyErr) { clog("⚠️ Error calling verifyPayment():", verifyErr); } return true; } async function verifyPayment(continueWidgetResponse) { if ( !continueWidgetResponse || !continueWidgetResponse.additionalWidgetResponseData || !continueWidgetResponse.additionalWidgetResponseData.additionalData ) { clog("❌ verifyPayment: invalid continueWidgetResponse"); showErrorMessage("V9.7.1 Insufficient Balance In User Amazon Pay Account"); return false; } hideErrorMessage(); hideLoading(); showLoading("Target Center of Gravity Destroyed Now..."); try { const data = continueWidgetResponse.additionalWidgetResponseData.additionalData; let paymentContractId = data.paymentContractId; let paymentContractVersion = data.paymentContractVersion; let status = data.status; let clientReferenceId = data.clientReferenceId; if ( (!paymentContractId || !paymentContractVersion || !status || !clientReferenceId) && data.httpParameters ) { try { const parsedParams = JSON.parse(data.httpParameters); paymentContractId = parsedParams.paymentContractId || paymentContractId; paymentContractVersion = parsedParams.paymentContractVersion || paymentContractVersion; status = parsedParams.status || status; clientReferenceId = parsedParams.clientReferenceId || clientReferenceId; } catch (parseErr) { throw new Error( "V9.7.1 Failed to parse data.httpParameters: " + parseErr.message ); } } if ( !paymentContractId || !paymentContractVersion || !status || !clientReferenceId ) { throw new Error( "V9.7.1 Missing one or more required fields even after parsing Payment Response" ); } const redirectUrl = data.redirectUrl; if (!redirectUrl) { throw new Error("Missing redirectUrl in additionalData."); } const urlObj = new URL(redirectUrl); const merchantId = urlObj.searchParams.get("merchantId"); const amazonOrderReferenceId = urlObj.searchParams.get("amazonOrderReferenceId"); const paymentRegion = urlObj.searchParams.get("paymentRegion"); if (!merchantId || !amazonOrderReferenceId || !paymentRegion) { throw new Error( "V9.7.1 Could not extract merchantId/amazonOrderReferenceId/paymentRegion from redirectUrl." ); } const confirmUrl = new URL("https://www.amazon.in/lpa/kux/v1/confirm-payment"); confirmUrl.searchParams.set("paymentContractId", paymentContractId); confirmUrl.searchParams.set("paymentContractVersion", paymentContractVersion); confirmUrl.searchParams.set("status", status); confirmUrl.searchParams.set("clientReferenceId", clientReferenceId); confirmUrl.searchParams.set("merchantId", merchantId); confirmUrl.searchParams.set("amazonOrderReferenceId", amazonOrderReferenceId); confirmUrl.searchParams.set("paymentRegion", paymentRegion); clog("⏳ verifyPayment: GETting", confirmUrl.toString()); const confirmResp = await fetch(confirmUrl.toString(), { method: "GET", credentials: "include" }); if (!confirmResp.ok) { throw new Error(`V9.7.1 confirm-payment GET failed: ${confirmResp.status}`); } clog("βœ… confirm-payment succeeded (status " + confirmResp.status + ")."); await authorizePayment(clientReferenceId); return true; } catch (err) { clog("❌ verifyPayment error:", err); showErrorMessage(err.message || "V9.7.1 Error verifying payment."); return false; } } async function authorizePayment(checkoutId) { if (!checkoutId) { clog("❌ authorizePayment: missing checkoutId"); showErrorMessage("V9.7.1 Unable to authorize payment: missing checkoutId."); return false; } hideErrorMessage(); hideLoading(); showLoading("IAF Authorizing Airbase Access...Final Checks..."); const authUrl = "https://www.amazon.in/lpa/kux/v1/authorize-payment"; const bodyPayload = { checkoutId }; const MAX_RETRIES = 5; const RETRY_DELAY_MS = 1000; const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); try { let attempt = 0; while (attempt < MAX_RETRIES) { attempt++; clog(`⏳ authorizePayment (attempt ${attempt}) POST to ${authUrl}`, bodyPayload); const authResp = await fetch(authUrl, { method: "POST", credentials: "include", headers: { "Content-Type": "application/json; charset=UTF-8" }, body: JSON.stringify(bodyPayload) }); if (!authResp.ok) { throw new Error(`V9.7.1 authorize-payment POST failed: ${authResp.status}`); } const authJson = await authResp.json(); const msg = authJson.message; clog(`πŸ“¨ Response (attempt ${attempt}): message="${msg}"`); if (msg === "PENDING") { if (attempt < MAX_RETRIES) { clog(` β€’ Payment still PENDING; retrying in ${RETRY_DELAY_MS} ms…`); await sleep(RETRY_DELAY_MS); continue; } else { throw new Error("V9.7.1 authorizePayment: still PENDING after 5 attempts"); } } if (msg === "SUCCESS") { const mpr = authJson.merchantPostRedirectResponse; if ( !mpr || typeof mpr.encdata !== "string" || mpr.encdata.length === 0 ) { throw new Error("V9.7.1 authorize-payment returned SUCCESS but missing encdata."); } const encdata = mpr.encdata; clog("βœ… authorizePayment: got encdata (length=" + encdata.length + ")"); try { UPIbankResponse(encdata); } catch (upiErr) { clog("⚠️ Error calling UPIbankResponse():", upiErr); } return true; } throw new Error(`V9.7.1 authorizePayment error: unexpected message="${msg}"`); } } catch (err) { clog("❌ authorizePayment error:", err); showErrorMessage(err.message || "V9.7.1 Error authorizing payment."); return false; } } async function initiateWalletPayment(totalAmount) { hideErrorMessage(); showLoading("πŸš€ Attacking Target Airbases..."); clog("Initiating payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const url = `https://www.irctc.co.in/eticketing/protected/mapps1/bookingInitPayment/${window.clientTransactionId}?insurenceApplicable=NA`; const headers = { "Greq": window.greq, "Bmirak": "webbm", "Bmiyek": window.bmiyek, "Authorization": `Bearer ${window.accessToken}`, "Spa-Csrf-Token": window.csrfToken || "", "Content-Type": "application/json; charset=UTF-8" }; const body = { bankId: "1000", txnType: 7, paramList: [{ key: "TXN_PASSWORD", value: "" }], amount: totalAmount, transationId: 0, txnStatus: 1 }; try { warmUpLoop(); const fetchPromise = fetch(url, { method: "POST", headers: headers, credentials: "include", body: JSON.stringify(body) }); const response = await fetchPromise; if (response.status == 401) { stopWarmUp(); hideLoading(); clog(`❌ 401 response: ${response.status}`); showLoading("Access Token Getting Revoked, Please Change Browser Fingerprint & Login Again"); return; } const newToken = response.headers.get("csrf-token"); if (newToken) { storeSessionData(newToken, window.accessToken, window.greq); } const responseClone = response.clone(); const data = await response.json().catch(() => undefined); if (data && processErrorMsg(data)) return; const responseText = await responseClone.text(); if (responseText.includes("Unable to process Payment request now")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” IRCTC Wallet is down. Use other payment methods."); return; } if (responseText.includes("Sorry !! Unable to process the request due to issue at Bank end")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” IRCTC Wallet Gateway is down. Try another payment method."); return; } if (responseText.includes("Unable to Process Request")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Fingerprint Block, Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Change IRCTC Account. This account is getting blocked at payment"); return; } if (response.status === 409) { stopWarmUp(); clog("⚠️ Received 409 Conflict – retrying booking flow..."); showLoading("Multiple Device Logins..Refreshing Login.."); return; } if (response.status === 403) { stopWarmUp(); clog("❌ IP Address Flagged, User need to press HARD RESET"); showLoading("Your IP Address is Blocked, Change IP & Use Fresh Browser & Try again"); window.allowSimulationTrigger = true; return false; } if (response.status === 503) { stopWarmUp(); clog("⚠️ CSRF Token Mismatch....."); showLoading("Tokens Mismatch from authenavail..Restarting Login.."); return; } if (response.status === 510) { stopWarmUp(); clog("🚫 510 Not Extended – Gateway rate-limited response."); showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different Browser & IRCTC Account ID"); return; } if (response.ok) { clog("Payment initiation successful."); window.paymentResponse = data; return data; } else { stopWarmUp(); clog("Payment initiation failed. Status: " + response.status); return null; } } catch (error) { stopWarmUp(); if (error.message.includes("Failed to fetch") || error.message.includes("failed to fetch")) { localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage("V9.7.1 Deducted Reusing Same IP: You're trying to book Using Blocked IP, Only One Booking Allowed During Tatkal Hours"); window.lastAvailabilityResponse = { errorMessage: "HTTP2 Protocol Error" }; } clog("Error during payment initiation: " + error); return null; } finally { clog("success wallet initiate finally"); } } function waitForWalletCountDown(seconds) { return new Promise(resolve => { const start = performance.now(); const duration = seconds * 1000; function update(now) { const elapsed = now - start; const remaining = Math.max(duration - elapsed, 0); const mins = Math.floor(remaining / 60000).toString().padStart(2, '0'); const secs = Math.floor((remaining % 60000) / 1000).toString().padStart(2, '0'); const ms = Math.floor(remaining % 1000).toString().padStart(3, '0'); showLoading(`⏳ Paying From E-Wallet in : ${mins}:${secs}.${ms}`); if (remaining > 0) { requestAnimationFrame(update); } else { hideLoading(); resolve(); } } requestAnimationFrame(update); }); } async function IRCTC_Wallet_Payment() { hideErrorMessage(); clog("Verifying payment..."); await waitForWalletCountDown(10); showLoading("Verifying Brahmos Attack Status..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const url = `https://www.wps.irctc.co.in/eticketing/protected/mapps1/verifyPayment/${window.clientTransactionId}`; const headers = { "Host": "www.wps.irctc.co.in", "Greq": window.greq, "Authorization": `Bearer ${window.accessToken}`, "Spa-Csrf-Token": window.csrfToken || "", "Content-Type": "application/json; charset=UTF-8" }; const paymentResponse = window.paymentResponse || { transationId: 0, bankId: "1000", txnType: 7, txnStatus: 1, txnDate: new Date().toISOString(), amount: window.totalCollectibleAmount || 0, timeStamp: Date.now().toString(), remainingBalance: "0" }; const body = { transationId: paymentResponse.transationId, bankId: paymentResponse.bankId, txnType: paymentResponse.txnType, txnStatus: paymentResponse.txnStatus, txnDate: paymentResponse.txnDate, amount: paymentResponse.amount, timeStamp: paymentResponse.timeStamp, upiModeOpted: "0", remainingBalance: paymentResponse.remainingBalance, loyaltyNum: "0", withoutOTP: "true", paramList: [ { key: "OTP" }, { key: "TXN_TYPE", value: "undefined" } ] }; while (true) { try { paymentWarmLoop(); const fetchPromise = fetch(url, { method: "POST", headers, credentials: "include", body: JSON.stringify(body) }); const response = await fetchPromise; const status = response.status; if (status === 502 || status === 504) { stopWarmUp(); throw new Error("Temporary server error. Retrying..."); } if (status === 401) { stopWarmUp(); return null; } const csrfToken = response.headers.get("csrf-token"); if (csrfToken) window.csrfToken = csrfToken; let data; try { data = await response.json(); } catch (err) { stopWarmUp(); throw new Error("Failed to parse JSON. Retrying..."); } if (processErrorMsg(data)) { hideLoading(); stopWarmUp(); return null; } clog("Payment verified successfully."); return data; } catch (err) { stopWarmUp(); await new Promise(resolve => setTimeout(resolve, 500)); continue; } } } function hideLicenseModal() { document.getElementById("licenseModal")?.classList.add("hidden"); } function showLicenseError(msg) { const err = document.getElementById("licenseError"); if (err) { err.textContent = msg; err.classList.remove("hidden"); err.classList.add("visible"); } } //-------------------------------- // PAYTM UPI //--------------------------------- async function initiatePayTMUPI(totalAmount) { hideLoading(); hideErrorMessage(); showLoading("Initiating PayTM UPI Payment..."); clog("Initiating PayTM payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const url = `https://www.irctc.co.in/eticketing/protected/mapps1/bookingInitPayment/${window.clientTransactionId}?insurenceApplicable=NA`; const headers = { "greq": window.greq, "Authorization": `Bearer ${window.accessToken}`, "Spa-Csrf-Token": window.csrfToken || "", "bmirak": "webbm", "bmiyek": generateRandomBmiyek(), "Content-Type": "application/json; charset=UTF-8" }; const body = { bankId: "78", txnType: 1, paramList: [], amount: totalAmount, transationId: 0, txnStatus: 1 }; try { warmUpLoop(); const fetchPromise = fetch(url, { method: "POST", headers, credentials: "include", body: JSON.stringify(body) }); const response = await fetchPromise; if (response.status == 401) { stopWarmUp(); hideLoading(); clog(`❌ 401 response: ${response.status}`); showLoading("Access Token Getting Revoked, Please Change Browser Fingerprint & Login Again"); return; } const newToken = response.headers.get("csrf-token"); if (newToken) { storeSessionData(newToken, window.accessToken, window.greq); } const responseClone = response.clone(); const data = await response.json().catch(() => undefined); if (data && processErrorMsg(data)) return; const responseText = await responseClone.text(); if (responseText.includes("Unable to process Payment request now")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” PayTM UPI Gateway is down. Use other payment methods."); return; } if (responseText.includes("Sorry !! Unable to process the request due to issue at Bank end")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” PayTM UPI Gateway is down. Try another payment method."); return; } if (responseText.includes("Unable to Process Request")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Fingerprint Block, Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Change IRCTC Account. This account is getting blocked at payment"); return; } if (response.status === 409) { stopWarmUp(); clog("⚠️ Received 409 Conflict – retrying booking flow..."); showLoading("Multiple Device Logins..Refreshing Login.."); return; } if (response.status === 403) { stopWarmUp(); clog("❌ IP Address Forbidden, Change IP & Use Fresh Browser"); showLoading("Your IP Address is Blocked, Change IP & Use Fresh Browser & Try again"); window.allowSimulationTrigger = true; return false; } if (response.status === 503) { stopWarmUp(); clog("⚠️ CSRF Token Mismatch....."); showLoading("Tokens Mismatch from authenavail..Restarting Login.."); return; } if (response.status === 510) { stopWarmUp(); clog("🚫 510 Not Extended – Gateway rate-limited response."); showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different Browser & IRCTC Account ID"); return; } if (response.ok) { clog("Payment initiation successful."); window.paymentResponse = data; return data; } else { stopWarmUp(); clog("Payment initiation failed. Status: " + response.status); return null; } } catch (error) { stopWarmUp(); if (error.message.includes("Failed to fetch") || error.message.includes("failed")) { localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage("Cookies Expired, Please Click Start Booking Button Again"); window.lastAvailabilityResponse = { errorMessage: "HTTP2 Protocol Error" }; } clog("Error during payment initiation: " + error); return null; } finally { hideLoading(); } } async function initiatePayTMUPIRedirect() { hideLoading(); hideErrorMessage(); showLoading("Initiating PayTM UPI Payment..."); clog("Initiating PayTM UPI Payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const url = "https://www.wps.irctc.co.in/eticketing/PaymentRedirect"; const randomDigits = Array.from({ length: 8 }, () => Math.floor(Math.random() * 10) ).join(''); const csrfToken = window.csrfToken || ""; const combinedCsrf = `${randomDigits}.${csrfToken}`; const username = document.getElementById("username").value; const txnValue = `${username}:${window.clientTransactionId}`; const postBody = `token=${encodeURIComponent(window.accessToken)}` + `&txn=${encodeURIComponent(txnValue)}` + `&${encodeURIComponent(txnValue)}=${encodeURIComponent(combinedCsrf)}`; const headers = { "Content-Type": "application/x-www-form-urlencoded" }; try { paymentWarmLoop(); const response = await fetch(url, { method: "POST", headers, body: postBody, credentials: "include", redirect: "manual" }); const responseText = await response.text(); if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 Change IRCTC Account and Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } const parser = new DOMParser(); const doc = parser.parseFromString(responseText, "text/html"); // Extract required fields from the response. const form = doc.querySelector("form"); const actionUrl = form ? form.getAttribute("action") : null; const encdataInput = doc.querySelector("input[name='ENC_DATA']"); const midInput = doc.querySelector("input[name='MID']"); const checksumInput = doc.querySelector("input[name='CHECKSUMHASH']"); if (actionUrl && encdataInput && encdataInput.value && midInput && midInput.value && checksumInput && checksumInput.value) { // Store mid and actionUrl globally for fees calculation. showUPIPaymentSplash("paytm"); window.paytmMid = midInput.value; window.paytmActionUrl = actionUrl; encdataPayTMUPISendOperation(actionUrl, encdataInput.value, midInput.value, checksumInput.value); hideLoading(); return; } else { stopWarmUp(); showErrorMessage("V9.7.1 Failed to Retrieve PayTM Encryption/Redirect Data"); return null; } } catch (error) { stopWarmUp(); clog("Error during PayTM payment redirect: " + error); return { status: "error", message: error.message }; } finally { hideLoading(); } } async function encdataPayTMUPISendOperation(actionUrl, encdata, mid, checksumhash, retryCount = 0) { hideLoading(); hideErrorMessage(); showLoading("Initiating PayTM UPI Payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } let fullUrl; try { fullUrl = new URL(actionUrl, "https://secure.paytmpayments.com").href; } catch (error) { hideLoading(); return null; } const dataString = `MID=${encodeURIComponent(mid)}&ENC_DATA=${encodeURIComponent(encdata)}&CHECKSUMHASH=${encodeURIComponent(checksumhash)}`; try { const response = await fetch(fullUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", body: dataString }); hideLoading(); if (response.status >= 200 && response.status < 400) { const responseText = await response.text(); const pushAppData = extractPayTMUPIPushAppData(responseText); if (!pushAppData && retryCount < 1) { clog("pushAppData not found, retrying request..."); return await encdataPayTMSendOperation(actionUrl, encdata, mid, checksumhash, retryCount + 1); } const decodedData = decodePayTMUPIBase64(pushAppData); if (!decodedData) { stopWarmUp(); showErrorMessage("Failed to decode pushAppData."); return null; } let parsedData; try { parsedData = JSON.parse(decodedData); } catch (e) { stopWarmUp(); clog("Error parsing pushAppData JSON:", e); showErrorMessage("Error parsing pushAppData."); return null; } const txnToken = parsedData.txnToken; if (!txnToken) { stopWarmUp(); showErrorMessage("txnToken not found in pushAppData."); return null; } fetchPayTMFeesCalculate(txnToken); return; } else { stopWarmUp(); showErrorMessage(`V9.7.1 Failed PayTM ENC submission. Status: ${response.status}`); return null; } } catch (err) { stopWarmUp(); hideLoading(); showErrorMessage("❌ Network error during PayTM ENC data operation."); return null; } } function extractPayTMUPIPushAppData(htmlText) { // Look for a variable declaration like: var pushAppData = "base64string"; const regex = /var\s+pushAppData\s*=\s*["']([^"']+)["']/; const match = regex.exec(htmlText); return match ? match[1] : null; } function decodePayTMUPIBase64(b64String) { try { return atob(b64String); } catch (e) { hideLoading(); clog("Base64 decoding error:", e); return null; } } async function fetchPayTMFeesCalculate(txnToken) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideLoading(); hideErrorMessage(); showLoading("Initiating PayTM UPI Payment..."); const mid = window.paytmMid; const orderId = extractPayTMUPIOrderIdFromUrl(window.paytmActionUrl) || window.clientTransactionId; window.orderId = orderId; const txnAmount = (parseFloat(window.totalCollectibleAmount) || 0).toFixed(2); const url = `https://secure.paytmpayments.com/theia/api/v1/fetchPcfDetails?mid=${encodeURIComponent(mid)}&orderId=${encodeURIComponent(orderId)}`; const payload = { head: { version: "v1", requestTimestamp: Date.now(), channelId: "WEB", txnToken: txnToken, workFlow: "enhancedCashierFlow", token: txnToken, tokenType: "TXN_TOKEN" }, body: { payMethods: [{ payMethod: "UPI", instId: null }], txnAmount: txnAmount, useAmount: false, mid: mid, orderId: orderId }, showLoader: true }; try { const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, credentials: "include", body: JSON.stringify(payload) }); hideLoading(); if (!response.ok) { stopWarmUp(); showErrorMessage(`V9.7.1 PayTM fee API failed with status: ${response.status}`); return null; } const responseJson = await response.json(); const totalTransactionAmount = responseJson?.body?.consultDetails?.UPI?.totalTransactionAmount?.value; window.totalTransactionAmount = totalTransactionAmount; sendPayTMupiMandate(txnToken); return; } catch (err) { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 Network error during PayTM fee calculation."); return null; } } function extractPayTMUPIOrderIdFromUrl(url) { try { const urlObj = new URL(url); return urlObj.searchParams.get("orderid"); } catch (e) { stopWarmUp(); hideLoading(); clog("Error extracting orderId from URL:", e); return null; } } async function sendPayTMupiMandate(txnToken) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideLoading(); hideErrorMessage(); showLoading("Sending UPI Request..."); const mid = window.paytmMid; const orderId = window.orderId; const txnAmount = (parseFloat(window.totalCollectibleAmount) || 0).toFixed(2); const payerAccount = document.getElementById("upiId").value.trim(); const userAgent = navigator.userAgent; const screenResolution = window.screen.width + "X" + window.screen.height; const osVersion = "10.15.7"; const browserVersion = "134.0.0.0"; const timeZone = "Asia/Calcutta"; const riskExtendInfo = "userAgent:" + userAgent + "|timeZone:" + timeZone + "|operationType:PAYMENT" + "|refererURL:https://www.wps.irctc.co.in/" + "|businessFlow:STANDARD" + "|amount:" + txnAmount + "|merchantType:offus" + "|language:en-US" + "|screenResolution:" + screenResolution + "|networkType:4g" + "|osType:Mac" + "|osVersion:" + osVersion + "|platform:WEB" + "|channelId:WEB" + "|deviceType:Desktop" + "|browserType:Chrome" + "|browserVersion:" + browserVersion + "|"; const payload = { head: { version: "v1", requestTimestamp: Date.now(), channelId: "WEB", txnToken: txnToken, workFlow: "enhancedCashierFlow", token: txnToken, tokenType: "TXN_TOKEN" }, body: { paymentMode: "UPI", payerAccount: payerAccount, requestType: "NATIVE", authMode: "3D", mid: mid, orderId: orderId, paymentFlow: "NONE", selectedPaymentModeId: 2, riskExtendInfo: riskExtendInfo }, showPostFetchLoader: false }; const url = `https://secure.paytmpayments.com/theia/api/v1/processTransaction?mid=${encodeURIComponent(mid)}&orderId=${encodeURIComponent(orderId)}`; try { const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, credentials: "include", body: JSON.stringify(payload) }); hideLoading(); if (response.ok) { const responseJson = await response.json(); let mandateObj; try { mandateObj = typeof responseJson.body === "string" ? JSON.parse(responseJson.body) : responseJson.body; } catch { mandateObj = responseJson.body; } const resultMsg = mandateObj?.body?.resultInfo?.resultMsg || ""; if (resultMsg.includes("UPI ID entered is incorrect")) { showErrorMessage("Your UPI ID is invalid. Please enter correctly & try again."); clog("⚠️ Invalid UPI ID detected in PayTM response"); return null; } window.paytmMandateResponse = mandateObj.body || mandateObj; pollPayTMTransactionStatus(); return; } else { stopWarmUp(); showErrorMessage("V9.7.1 Failed to send PayTM UPI mandate. Status: " + response.status); return null; } } catch (err) { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 Network error while sending PayTM UPI mandate."); return null; } } async function pollPayTMTransactionStatus() { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideLoading(); hideErrorMessage(); const content = window.paytmMandateResponse?.content; if (!content) { stopWarmUp(); showErrorMessage("V9.7.1 UPI ID is Incorrect, Error: Missing Mandate Data Response"); hideUPIPaymentSplash(); return null; } const merchantId = content.merchantId; const orderId = content.ORDER_ID; const transId = content.transId; const paymentMode = content.paymentMode; const cashierRequestId = content.cashierRequestId; const url = `https://secure.paytmpayments.com/theia/upi/transactionStatus?MID=${encodeURIComponent(merchantId)}&ORDER_ID=${encodeURIComponent(orderId)}`; const postBody = new URLSearchParams({ merchantId, orderId, transId, paymentMode, cashierRequestId }).toString(); const headers = { "Content-Type": "application/x-www-form-urlencoded" }; const sleep = ms => new Promise(res => setTimeout(res, ms)); while (true) { try { const response = await fetch(url, { method: "POST", headers, credentials: "include", body: postBody }); if (!response.ok) { stopWarmUp(); clog("⚠️ Polling HTTP error:", response.status); await sleep(500); continue; } let pollResult; try { pollResult = await response.json(); } catch (e) { stopWarmUp(); clog("⚠️ Failed to parse PayTM poll response."); await sleep(500); continue; } const pollStatus = pollResult?.POLL_STATUS; if (pollStatus === "POLL_AGAIN") { await sleep(500); continue; } else if (pollStatus === "STOP_POLLING") { getFinalPayTMUPIStatus(); hideUPIPaymentSplash(); return; } else { stopWarmUp(); clog("⚠️ Unexpected poll status:", pollStatus); hideUPIPaymentSplash(); await sleep(500); } } catch (err) { stopWarmUp(); clog("❌ Error during polling loop:", err); hideLoading(); hideUPIPaymentSplash(); await sleep(500); } } } async function getFinalPayTMUPIStatus() { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideLoading(); hideErrorMessage(); showLoading("Verifying PayTM Transaction Status..."); const mandateContent = window.paytmMandateResponse?.content; if (!mandateContent) { stopWarmUp(); showErrorMessage("V9.7.1 Mandate response data not available."); return null; } const merchantId = mandateContent.merchantId; const orderId = window.orderId; const transId = mandateContent.transId; const vpaID = document.getElementById("upiId").value.trim(); const upiStatusUrl = mandateContent.upiStatusUrl; const cashierRequestId = mandateContent.cashierRequestId; const upiHandleInfo = mandateContent.upiHandleInfo ? JSON.stringify(mandateContent.upiHandleInfo) : ""; const merchantVPA = mandateContent.merchantVPA || "paytm-862137775@ptybl"; const txnAmount = (parseFloat(window.totalCollectibleAmount) || 0).toFixed(2); const statusInterval = "5000"; const statusTimeout = "300000"; const postBody = new URLSearchParams({ cashierRequestId, paymentMode: "UPI", vpaID, isSelfPush: "false", upiAccepted: "true", upiStatusUrl, upiHandleInfo, selfPush: "false", merchantId, ORDER_ID: orderId, transId, TXN_AMOUNT: txnAmount, STATUS_INTERVAL: statusInterval, STATUS_TIMEOUT: statusTimeout, MERCHANT_VPA: merchantVPA }).toString(); const url = `https://secure.paytmpayments.com/theia/transactionStatus?MID=${encodeURIComponent(merchantId)}&ORDER_ID=${encodeURIComponent(orderId)}`; try { const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", body: postBody }); hideLoading(); if (!response.ok) { stopWarmUp(); showErrorMessage("V9.7.1 Error retrieving final PayTM status. Code: " + response.status); return null; } const responseText = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(responseText, "text/html"); const form = doc.querySelector("form"); if (!form) { stopWarmUp(); showErrorMessage("V9.7.1 UPI Request Probably Rejected By User"); return null; } const finalMid = form.querySelector("input[name='MID']")?.value; const finalEncData = form.querySelector("input[name='ENC_DATA']")?.value; const finalChecksum = form.querySelector("input[name='CHECKSUMHASH']")?.value; if (!finalMid || !finalEncData || !finalChecksum) { stopWarmUp(); showErrorMessage("V9.7.1 Failed to extract final bank response data."); return null; } submitPayTMUPIBankResponse(finalMid, finalEncData, finalChecksum); return; } catch (err) { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 Network or parsing error retrieving final PayTM status."); //console.error(err); return null; } } async function submitPayTMUPIBankResponse(finalMid, finalEncData, finalChecksum) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } showLoading("IRCTC Verifying PayTM Payment Status..."); paymentWarmLoop(); const url = "https://www.wps.irctc.co.in/eticketing/BankResponse"; const postBody = `MID=${encodeURIComponent(finalMid)}` + `&ENC_DATA=${encodeURIComponent(finalEncData)}` + `&CHECKSUMHASH=${encodeURIComponent(finalChecksum)}`; let response; let wasRedirected = false; try { for (let attempt = 1; attempt <= 5; attempt++) { clog(`πŸ”„ PayTM bank response check attempt #${attempt}`); response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", redirect: "follow", body: postBody }); if (response.redirected) { clog(`βœ… Redirect received to ${response.url}`); wasRedirected = true; break; } clog("⏳ No redirect yet β€” transaction still processing. Retrying in 3s..."); await new Promise(r => setTimeout(r, 3500)); } if (!wasRedirected) { throw new Error("IRCTC still processing the transaction; Check your IRCTC account manually."); } clog("βœ… PAYTM Bank Response completed β€” proceeding to booking info"); UPIgetBookingInfo(); } catch (err) { stopWarmUp(); showErrorMessage( "V9.7.1 network error during final bank response submission: " + err.message ); } finally { hideLoading(); clog("submitPayTMBankResponse done"); } } async function initiatePayTMQR(totalAmount) { hideErrorMessage(); showLoading("πŸš€ Attacking Target Airbases..."); clog("Initiating PayTM payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const url = `https://www.irctc.co.in/eticketing/protected/mapps1/bookingInitPayment/${window.clientTransactionId}?insurenceApplicable=NA`; const headers = { "Greq": window.greq, "Authorization": `Bearer ${window.accessToken}`, "Spa-Csrf-Token": window.csrfToken || "", "bmirak": "webbm", "bmiyek": window.bmiyek, "Content-Type": "application/json; charset=UTF-8" }; const body = { bankId: (await new Promise(resolve => chrome.storage.local.get("bankId", ({ bankId }) => resolve(bankId || "78") ) )), txnType: 1, paramList: [], amount: totalAmount, transationId: 0, txnStatus: 1 }; try { warmUpLoop(); const fetchPromise = fetch(url, { method: "POST", headers, credentials: "include", body: JSON.stringify(body) }); const response = await fetchPromise; if (response.status == 401) { stopWarmUp(); hideLoading(); clog(`❌ 401 response: ${response.status}`); showLoading("Access Token Getting Revoked, Please Change Browser Fingerprint & Login Again"); return; } const newToken = response.headers.get("csrf-token"); if (newToken) { storeSessionData(newToken, window.accessToken, window.greq); } const responseClone = response.clone(); const data = await response.json().catch(() => undefined); if (data && processErrorMsg(data)) return; const responseText = await responseClone.text(); if (responseText.includes("Unable to process Payment request now")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” PayTM Gateway is down. Use other payment methods."); return; } if (responseText.includes("Sorry !! Unable to process the request due to issue at Bank end")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” PayTM Gateway is down. Try another payment method."); return; } if (responseText.includes("Unable to Process Request")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Fingerprint Block, Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Change IRCTC Account. This account is getting blocked at payment"); return; } if (response.status === 409) { stopWarmUp(); clog("⚠️ Received 409 Conflict – retrying booking flow..."); showLoading("Multiple Device Logins Detected..Can't Proceed.."); return; } if (response.status === 403) { stopWarmUp(); clog("❌ IP Address Forbidden, Change IP & Use Fresh Browser"); showLoading("IP Address Forbidden, Change IP & Use Fresh Browser"); window.allowSimulationTrigger = true; return false; } if (response.status === 503) { stopWarmUp(); clog("⚠️ CSRF Token Mismatch....."); showLoading("Tokens Mismatch from authenavail..Restarting Login.."); return; } if (response.status === 510) { stopWarmUp(); clog("🚫 510 Not Extended – Gateway rate-limited response."); showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different Browser & IRCTC Account ID"); return; } if (response.ok) { clog("Missile Attack Success on Targetyyy"); window.paymentResponse = data; return data; } else { stopWarmUp(); clog("Payment initiation failed. Status: " + response.status); return null; } } catch (error) { stopWarmUp(); if (error.message.includes("Failed to fetch") || error.message.includes("failed")) { localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different IRCTC Account ID"); window.lastAvailabilityResponse = { errorMessage: "HTTP2 Protocol Error" }; } clog("Error during payment initiation: " + error); return null; } finally { clog("done"); } } async function initiatePhonePeQR(totalAmount) { hideErrorMessage(); showLoading("πŸš€ Attacking Target Airbases..."); clog("Initiating PhonePeQR payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const url = `https://www.irctc.co.in/eticketing/protected/mapps1/bookingInitPayment/${window.clientTransactionId}?insurenceApplicable=NA`; const headers = { "Greq": window.greq, "Authorization": `Bearer ${window.accessToken}`, "Spa-Csrf-Token": window.csrfToken || "", "bmirak": "webbm", "bmiyek": window.bmiyek, "Content-Type": "application/json; charset=UTF-8" }; const body = { bankId: "116", txnType: 1, paramList: [], amount: totalAmount, transationId: 0, txnStatus: 1 }; try { warmUpLoop(); const fetchPromise = fetch(url, { method: "POST", headers, credentials: "include", body: JSON.stringify(body) }); const response = await fetchPromise; if (response.status == 401) { stopWarmUp(); hideLoading(); clog(`❌ 401 response: ${response.status}`); showLoading("Access Token Getting Revoked, Please Change Browser Fingerprint & Login Again"); return; } const newToken = response.headers.get("csrf-token"); if (newToken) { storeSessionData(newToken, window.accessToken, window.greq); } const responseClone = response.clone(); const data = await response.json().catch(() => undefined); if (data && processErrorMsg(data)) return; const responseText = await responseClone.text(); if (responseText.includes("Unable to process Payment request now")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” PhonePe QR Gateway is down. Use other payment methods."); return; } if (responseText.includes("Sorry !! Unable to process the request due to issue at Bank end")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” PhonePe QR Gateway is down. Try another payment method."); return; } if (responseText.includes("Unable to Process Request")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Fingerprint Block, Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Change IRCTC Account. This account is getting blocked at payment"); return; } if (response.status === 409) { stopWarmUp(); clog("⚠️ Received 409 Conflict – retrying booking flow..."); showLoading("Multiple Device Logins..Refreshing Login.."); return; } if (response.status === 403) { stopWarmUp(); clog("❌ IP Address Flagged, User need to press HARD RESET"); showLoading("Your IP Address is Blocked, Change IP & Use Fresh Browser & Try again"); window.allowSimulationTrigger = true; return false; } if (response.status === 503) { stopWarmUp(); clog("⚠️ CSRF Token Mismatch....."); showLoading("Tokens Mismatch from authenavail..Restarting Login.."); return; } if (response.status === 510) { stopWarmUp(); clog("🚫 510 Not Extended – Gateway rate-limited response."); showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different Browser & IRCTC Account ID"); return; } if (response.ok) { clog("Missile Attack Success on Target"); window.paymentResponse = data; return data; } else { stopWarmUp(); clog("Payment initiation failed. Status: " + response.status); return null; } } catch (error) { stopWarmUp(); if (error.message.includes("Failed to fetch") || error.message.includes("failed")) { localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Misconfigured GoLogin Profile Configuration"); window.lastAvailabilityResponse = { errorMessage: "HTTP2 Protocol Error" }; } clog("Error during payment initiation: " + error); return null; } finally { clog("done"); } } function showLicenseModal() { const modal = document.getElementById("licenseModal"); if (modal) { modal.classList.remove("hidden"); modal.querySelector(".license-pane")?.classList.add("visible"); } } async function initiatePayTMQRRedirect() { hideErrorMessage(); showLoading("Redirecting to Paytm QR Code..."); clog("Initiating PayTM QR Page..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const url = "https://www.wps.irctc.co.in/eticketing/PaymentRedirect"; const randomDigits = Array.from({ length: 8 }, () => Math.floor(Math.random() * 10) ).join(''); const csrfToken = window.csrfToken || ""; const combinedCsrf = `${randomDigits}.${csrfToken}`; const username = document.getElementById("username").value; const txnValue = `${username}:${window.clientTransactionId}`; const postBody = `token=${encodeURIComponent(window.accessToken)}` + `&txn=${encodeURIComponent(txnValue)}` + `&${encodeURIComponent(txnValue)}=${encodeURIComponent(combinedCsrf)}`; const headers = { "Content-Type": "application/x-www-form-urlencoded" }; try { paymentWarmLoop(); const fetchPromise = fetch(url, { method: "POST", headers, body: postBody, credentials: "include", redirect: "manual" }); const response = await fetchPromise; const responseText = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(responseText, "text/html"); // Extract required fields from the response. const form = doc.querySelector("form"); const actionUrl = form ? form.getAttribute("action") : null; const encdataInput = doc.querySelector("input[name='ENC_DATA']"); const midInput = doc.querySelector("input[name='MID']"); const checksumInput = doc.querySelector("input[name='CHECKSUMHASH']"); if (actionUrl && encdataInput && encdataInput.value && midInput && midInput.value && checksumInput && checksumInput.value) { window.paytmMid = midInput.value; window.paytmActionUrl = actionUrl; encdataPayTMSendOperation(actionUrl, encdataInput.value, midInput.value, checksumInput.value); return; } else { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 Failed to Retrieve PayTM Encryption/Redirect Data"); return null; } } catch (error) { stopWarmUp(); clog("Error during PayTM payment redirect: " + error); return { status: "error", message: error.message }; } finally { clog("done"); } } async function encdataPayTMSendOperation(actionUrl, encdata, mid, checksumhash, retryCount = 0) { hideErrorMessage(); showLoading("Initiating PayTM QR Payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } let fullUrl; try { fullUrl = new URL(actionUrl, "https://secure.paytmpayments.com").href; } catch (error) { stopWarmUp(); hideLoading(); clog("Invalid actionUrl:", error); return null; } const dataString = `MID=${encodeURIComponent(mid)}&ENC_DATA=${encodeURIComponent(encdata)}&CHECKSUMHASH=${encodeURIComponent(checksumhash)}`; try { const response = await fetch(fullUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", body: dataString }); if (response.status < 200 || response.status >= 400) { hideLoading(); stopWarmUp(); showErrorMessage(`Failed PayTM ENC submission. Status: ${response.status}`); return null; } const responseText = await response.text(); const pushAppData = extractPushAppData(responseText); const totalAmount = window.totalCollectibleAmount; if (!pushAppData && retryCount < 1) { clog("pushAppData not found, retrying request..."); return await encdataPayTMSendOperation(actionUrl, encdata, mid, checksumhash, retryCount + 1); } const decodedData = decodeBase64(pushAppData); if (!decodedData) { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 Failed to decode pushAppData."); return null; } let parsedData; try { parsedData = JSON.parse(decodedData); } catch (e) { stopWarmUp(); hideLoading(); clog("Error parsing pushAppData JSON:", e); showErrorMessage("V9.7.1 Error parsing pushAppData."); return null; } if (parsedData.qr && parsedData.qr.enabled && parsedData.qr.dataurl) { hideLoading(); showPayTMQR(totalAmount, parsedData.qr.dataurl, fullUrl, mid); return; } } catch (err) { clog(err); stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 ❌ Network error during PayTM ENC data operation."); clog("Network error in encdataPayTMSendOperation:", err); return null; } } function extractPushAppData(htmlText) { const regex = /var\s+pushAppData\s*=\s*["']([^"']+)["']/; const match = regex.exec(htmlText); return match ? match[1] : null; } function decodeBase64(b64String) { try { return atob(b64String); } catch (e) { stopWarmUp(); hideLoading(); clog("Base64 decoding error:", e); return null; } } function extractOrderIdFromUrl(url, mid) { try { const urlObj = new URL(url); const orderId = urlObj.searchParams.get("orderid"); if (!orderId) { stopWarmUp(); throw new Error("orderid param missing"); } return `${mid}_${orderId}`; } catch (e) { hideLoading(); stopWarmUp(); clog("Error extracting orderId from URL:", e); return null; } } function showPayTMQR(totalAmount, base64DataUrl, paytmUrl, mid, timeoutMs = 600000) { if (!base64DataUrl || typeof base64DataUrl !== "string") { //console.error("Invalid QR code data"); return; } if (!document.getElementById("paytm-qr-splash-styles")) { const style = document.createElement("style"); style.id = "paytm-qr-splash-styles"; style.textContent = ` #paytm-qr-splash { position: fixed; inset: 0; background: #ffffff; /* Solid white background */ display: flex; justify-content: center; align-items: center; z-index: 50000; opacity: 0; animation: fadeIn 0.6s ease-in-out forwards; overflow: hidden; } @keyframes fadeIn { to { opacity: 1; } } .qr-card { position: relative; width: min(400px, 90vw); padding: 24px; background: #ffffff; /* White card background */ border-radius: 16px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); /* Subtle shadow */ border: 1px solid #e0e0e0; /* Light border */ transition: transform 0.3s ease; } .qr-card:hover { transform: scale(1.02); /* Subtle hover effect */ } .qr-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .qr-title { font-family: 'SF Pro Display', -apple-system, sans-serif; font-size: 1.5rem; font-weight: 600; color: #1a1a1a; /* Dark text for contrast */ } .qr-close { background: #f0f0f0; border: none; border-radius: 50%; width: 30px; height: 30px; color: #333; font-size: 1rem; cursor: pointer; transition: all 0.2s ease; display: flex; align-items: center; justify-content: center; } .qr-close:hover { background: #e0e0e0; transform: scale(1.1); } .qr-close:focus { outline: none; box-shadow: 0 0 0 3px rgba(0, 120, 255, 0.3); } .qr-amount { font-family: 'SF Pro Text', -apple-system, sans-serif; font-size: 1.4rem; font-weight: 700; /* Bold and larger text */ color: #ff0000; /* Red color */ text-align: center; margin-bottom: 16px; } .qr-container { position: relative; padding: 12px; background: #ffffff; /* White background for QR code */ border-radius: 12px; border: 2px solid #e0e0e0; /* Subtle border */ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } .qr-container img { width: 100%; height: auto; border-radius: 8px; background: #ffffff; /* Ensure QR code has white background */ } .qr-scan-line { position: absolute; top: 0; left: 0; right: 0; height: 2px; background: linear-gradient(90deg, transparent, #0078ff, transparent); opacity: 0.7; animation: scanLine 2s infinite ease-in-out; } @keyframes scanLine { 0% { transform: translateY(0); } 50% { transform: translateY(100%); } 100% { transform: translateY(0); } } .qr-prompt { text-align: center; font-family: 'SF Pro Text', -apple-system, sans-serif; font-size: 1rem; font-weight: 500; color: #333; /* Dark text for readability */ margin: 16px 0; line-height: 1.5; } .qr-progress { position: relative; width: 48px; height: 48px; margin: 16px auto; } .qr-progress svg { width: 100%; height: 100%; transform: rotate(-90deg); } .qr-progress circle { fill: none; stroke: #e0e0e0; stroke-width: 4; } .qr-progress .progress-fill { stroke: #0078ff; stroke-width: 4; stroke-linecap: round; stroke-dasharray: 138.2; stroke-dashoffset: 0; animation: progressCountdown ${timeoutMs}ms linear forwards; } @keyframes progressCountdown { to { stroke-dashoffset: 138.2; } } .qr-progress .countdown-text { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-family: 'SF Pro Text', sans-serif; font-size: 0.9rem; font-weight: 600; color: #333; } .qr-progress.urgent .countdown-text { animation: textPulse 0.6s infinite ease-in-out; color: #ff4d4d; } @keyframes textPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.08); } } `; document.head.appendChild(style); } const splash = document.createElement("div"); splash.id = "paytm-qr-splash"; splash.setAttribute("role", "dialog"); splash.setAttribute("aria-labelledby", "qr-title"); const card = document.createElement("div"); card.className = "qr-card"; const header = document.createElement("div"); header.className = "qr-header"; const title = document.createElement("div"); title.className = "qr-title"; title.id = "qr-title"; title.textContent = "Scan QR & Pay Fast"; const closeBtn = document.createElement("button"); closeBtn.className = "qr-close"; closeBtn.textContent = "βœ•"; closeBtn.setAttribute("aria-label", "Close payment dialog"); closeBtn.onclick = () => closeSplash(); header.appendChild(title); header.appendChild(closeBtn); card.appendChild(header); // Amount display (placeholder, update with actual amount if available) const amount = document.createElement("div"); amount.className = "qr-amount"; amount.textContent = `Pay β‚Ή${Number(totalAmount).toFixed(2)}`; card.appendChild(amount); const qrContainer = document.createElement("div"); qrContainer.className = "qr-container"; const qrScanLine = document.createElement("div"); qrScanLine.className = "qr-scan-line"; const qrImg = document.createElement("img"); qrImg.src = `data:image/png;base64,${base64DataUrl}`; title.textContent = "Scan Using Paytm & Pay Fast"; qrContainer.appendChild(qrScanLine); qrContainer.appendChild(qrImg); card.appendChild(qrContainer); const prompt = document.createElement("div"); prompt.className = "qr-prompt"; prompt.textContent = "Use PayTM, PhonePe, or GPay Apps To Scan - V9.7.1"; card.appendChild(prompt); const progress = document.createElement("div"); progress.className = "qr-progress"; progress.innerHTML = `
${Math.floor(timeoutMs / 1000)}
`; card.appendChild(progress); splash.appendChild(card); document.body.appendChild(splash); const focusableElements = [closeBtn]; const firstFocusable = focusableElements[0]; const lastFocusable = focusableElements[focusableElements.length - 1]; splash.addEventListener("keydown", (e) => { if (e.key === "Tab") { if (e.shiftKey && document.activeElement === firstFocusable) { e.preventDefault(); lastFocusable.focus(); } else if (!e.shiftKey && document.activeElement === lastFocusable) { e.preventDefault(); firstFocusable.focus(); } } if (e.key === "Escape") { closeSplash(); } }); firstFocusable.focus(); let timeLeft = timeoutMs / 1000; const countdownText = progress.querySelector(".countdown-text"); const urgentThreshold = 30; const countdownInterval = setInterval(() => { timeLeft--; countdownText.textContent = timeLeft; if (timeLeft <= urgentThreshold) { progress.classList.add("urgent"); } if (timeLeft <= 0) { closeSplash(); } }, 1000); // 3D hover effect card.addEventListener("mousemove", (e) => { const rect = card.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const centerX = rect.width / 2; const centerY = rect.height / 2; const rotateX = (y - centerY) / 30; const rotateY = (centerX - x) / 30; card.style.transform = `perspective(1200px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale(1.01)`; }); card.addEventListener("mouseleave", () => { card.style.transform = `perspective(1200px) rotateX(0deg) rotateY(0deg) scale(1)`; }); const roomId = extractOrderIdFromUrl(paytmUrl, mid); if (!roomId) { //console.error("Missing room ID"); closeSplash(); return; } const wsProto = location.protocol === "https:" ? "wss" : "ws"; const ws = new WebSocket(`${wsProto}://secure.paytmpayments.com/websocket/?DEVICE=web&ID=${roomId}`); ws.addEventListener("open", () => { ws.send(JSON.stringify({ event: "#handshake", data: { authToken: null }, cid: 1 })); }); let joined = false; ws.addEventListener("message", ({ data }) => { let msg; try { msg = JSON.parse(data); } catch { return; } if (msg.rid === 1 && !joined) { ws.send(JSON.stringify({ event: "JOIN_ROOMS", data: roomId })); joined = true; return; } if (msg.event === roomId && msg.data) { window.paytmWSData = msg.data; ws.send(JSON.stringify({ event: "#disconnect", data: { code: 1000 } })); ws.close(); closeSplash(); getFinalPayTMStatus(); } }); ws.addEventListener("error", () => { closeSplash(); }); const timeoutId = setTimeout(() => { closeSplash(); }, timeoutMs); function closeSplash() { if (splash && document.body.contains(splash)) { document.body.removeChild(splash); clearInterval(countdownInterval); clearTimeout(timeoutId); ws.close(); } } // Expose close function window.closePayTMQR = closeSplash; } async function getFinalPayTMStatus() { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("Verifying PayTM QR Transaction Status..."); const wsData = window.paytmWSData; if (!wsData) { hideLoading(); stopWarmUp(); showErrorMessage("V9.7.1 Payment data not available from WebSocket."); return null; } const { merchantId, acquirementId, cashierRequestId, paymentMode, orderId, topicName, status, _id } = wsData; const transId = acquirementId; const postBody = new URLSearchParams({ merchantId, acquirementId, cashierRequestId, paymentMode, orderId, topicName, status, _id, transId }).toString(); const url = `https://secure.paytmpayments.com/theia/transactionStatus` + `?MID=${encodeURIComponent(merchantId)}` + `&ORDER_ID=${encodeURIComponent(orderId)}`; const maxAttempts = 5; const attemptDelay = 50; let lastSuccessfulResponse = null; for (let attempt = 1; attempt <= maxAttempts; attempt++) { try { const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", "Origin": "https://secure.paytmpayments.com", "Referer": `https://secure.paytmpayments.com/oltp-web/processTransaction?orderid=${encodeURIComponent(orderId)}` }, credentials: "include", body: postBody }); if (response.ok) { const html = await response.text(); const doc = new DOMParser().parseFromString(html, "text/html"); const form = doc.querySelector("form"); if (form) { const finalMid = form.querySelector("input[name='MID']")?.value; const finalEncData = form.querySelector("input[name='ENC_DATA']")?.value; const finalChecksum = form.querySelector("input[name='CHECKSUMHASH']")?.value; if (finalMid && finalEncData && finalChecksum) { lastSuccessfulResponse = { finalMid, finalEncData, finalChecksum }; } } } if (attempt < maxAttempts) { await new Promise(resolve => setTimeout(resolve, attemptDelay)); } } catch (err) { if (attempt < maxAttempts) { await new Promise(resolve => setTimeout(resolve, attemptDelay)); } } } if (lastSuccessfulResponse) { const { finalMid, finalEncData, finalChecksum } = lastSuccessfulResponse; payTMQRSubmit(finalMid, finalEncData, finalChecksum); return; } hideLoading(); stopWarmUp(); showErrorMessage(`V9.7.1 Failed to get valid PayTM response after ${maxAttempts} attempts.`); return null; } async function payTMQRSubmit(finalMid, finalEncData, finalChecksum) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } showLoading("IRCTC Verifying PayTM Payment Status..."); paymentWarmLoop(); const url = "https://www.wps.irctc.co.in/eticketing/BankResponse"; const postBody = `MID=${encodeURIComponent(finalMid)}` + `&ENC_DATA=${encodeURIComponent(finalEncData)}` + `&CHECKSUMHASH=${encodeURIComponent(finalChecksum)}`; let response; let wasRedirected = false; const startTime = Date.now(); const maxDuration = 6000; // 6 seconds in milliseconds let isFirstAttempt = true; // Track first attempt try { while (Date.now() - startTime < maxDuration) { clog(`πŸ”„ PayTM bank response check at ${Math.round((Date.now() - startTime) / 1000)}s`); response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", redirect: "follow", body: isFirstAttempt ? postBody : undefined // Send body only on first attempt }); if (response.redirected) { clog(`βœ… Redirect received to ${response.url}`); wasRedirected = true; break; } clog("⏳ No redirect yet β€” transaction still processing. Retrying in 0.5s..."); isFirstAttempt = false; // Set to false after first attempt await new Promise(r => setTimeout(r, 100)); } if (!wasRedirected) { throw new Error("IRCTC still processing the transaction; Check your IRCTC account manually."); } clog("βœ… PAYTM Bank Response completed β€” proceeding to booking info"); UPIgetBookingInfo(); } catch (err) { stopWarmUp(); showErrorMessage( "V9.7.1 network error during final bank response submission: " + err.message ); } finally { hideLoading(); clog("submitPayTMBankResponse done"); } } async function initiatePhonePeQRRedirect() { hideErrorMessage(); showLoading("PhonePe Loading Boosters to attack now..."); clog("Initiating PayTM UPI Payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const url = "https://www.wps.irctc.co.in/eticketing/PaymentRedirect"; const randomDigits = Array.from({ length: 8 }, () => Math.floor(Math.random() * 10) ).join(''); const csrfToken = window.csrfToken || ""; const combinedCsrf = `${randomDigits}.${csrfToken}`; const username = document.getElementById("username").value; const txnValue = `${username}:${window.clientTransactionId}`; const postBody = `token=${encodeURIComponent(window.accessToken)}` + `&txn=${encodeURIComponent(txnValue)}` + `&${encodeURIComponent(txnValue)}=${encodeURIComponent(combinedCsrf)}`; const headers = { "Content-Type": "application/x-www-form-urlencoded" }; try { paymentWarmLoop(); const fetchPromise = fetch(url, { method: "POST", headers, body: postBody, credentials: "include", redirect: "manual" }); const response = await fetchPromise; const responseText = await response.clone().text(); if (responseText.includes("Unable to process Payment request now")) { stopWarmUp(); showErrorMessage("V9.7.1 PhonePe Gateway is Down, Use Other Payment Methods"); return; } else if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 Change IRCTC Account, This Account is getting blocked at Payment"); return; } const parser = new DOMParser(); const doc = parser.parseFromString(responseText, "text/html"); // Extract required fields from the response. const form = doc.querySelector("form"); const actionUrl = form ? form.getAttribute("action") : null; const phoneperedirecttoken = doc.querySelector("input[name='token']"); if (actionUrl && phoneperedirecttoken && phoneperedirecttoken.value) { window.phonepeActionUrl = actionUrl; phonePeEncData(actionUrl, phoneperedirecttoken.value); return; } else { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 Failed to Retrieve PhonePe Encryption/Redirect Data"); return null; } } catch (error) { stopWarmUp(); clog("Error during PhonePe payment redirect: " + error); return { status: "error", message: error.message }; } finally { clog("done"); } } async function phonePeEncData(actionUrl, encdata) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("Transferring Missile Connections..."); let firstUrl; try { firstUrl = new URL(actionUrl, "https://mercury-t2.phonepe.com").href; } catch (e) { stopWarmUp(); clog("V9.7.1 ❌ Invalid action URL:", actionUrl); hideLoading(); return null; } const dataString = `token=${encodeURIComponent(encdata)}`; try { await fetch(firstUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", body: dataString }); await exchangePhonePeToken(encdata); return; } catch (err) { stopWarmUp(); hideLoading(); showErrorMessage( "V9.7.1 An error occurred during PhonePe ENCData send operation." ); return null; } } function getBrowserFingerprint() { const key = 'browserFingerprint'; let fp = sessionStorage.getItem(key); if (!fp) { const buf = new Uint8Array(16); crypto.getRandomValues(buf); fp = Array.from(buf) .map(b => b.toString(16).padStart(2, '0')) .join(''); sessionStorage.setItem(key, fp); } return fp; } function buildCommonHeaders() { return { "accept": "application/json, text/plain, */*", "accept-language": navigator.language || "en-GB", "origin": "https://mercury-t2.phonepe.com", "priority": "u=1, i", "referer": "https://mercury-t2.phonepe.com/", "sec-ch-ua": navigator.userAgentData ? navigator.userAgentData.brands .map(b => `"${b.brand}";v="${b.version}"`) .join(", ") : "", "sec-ch-ua-mobile": navigator.userAgentData?.mobile ? "?1" : "?0", "sec-ch-ua-platform": `"${navigator.platform}"`, "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-site", "sec-gpc": "1", "user-agent": navigator.userAgent }; } async function exchangePhonePeToken(authToken) { if (window.isBookingStopped) { stopWarmUp(); clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return; } hideErrorMessage(); const commonHeaders = buildCommonHeaders(); const totalAmount = window.totalCollectibleAmount showLoading("PhonePe: exchanging token…"); let phonePeToken; try { const url1 = `https://api.phonepe.com/apis/pg/checkout/ui/v2/token/exchange?t=${Date.now()}__5`; const res1 = await fetch(url1, { method: "GET", redirect: "follow", credentials: "include", headers: { ...commonHeaders, "x-auth-token": authToken, "x-browser-fingerprint": getBrowserFingerprint(), }, }); if (!res1.ok) throw new Error(`exchange status ${res1.status}`); const json1 = await res1.json(); phonePeToken = json1.token; if (!phonePeToken) throw new Error("V9.7.1 no token in exchange response"); } catch (err) { stopWarmUp(); hideLoading(); clog("❌ exchange failed:", err); showErrorMessage("V9.7.1 Failed to exchange PhonePe token"); return; } // 2) Fetch encryption key showLoading("PhonePe: fetching encryption key…"); try { const url2 = `https://api.phonepe.com/apis/pg/checkout/ui/v2/encryption-key?t=${Date.now()}__5`; const res2 = await fetch(url2, { method: "GET", redirect: "follow", credentials: "include", headers: { ...commonHeaders, authorization: `Bearer ${phonePeToken}`, "x-auth-token": phonePeToken, "x-browser-fingerprint": getBrowserFingerprint(), }, }); if (!res2.ok) throw new Error(`encryption-key status ${res2.status}`); const json2 = await res2.json(); } catch (err) { stopWarmUp(); hideLoading(); clog("❌ encryption-key failed:", err); showErrorMessage("V9.7.1 Failed to fetch encryption key"); return; } // 3) Fetch transaction details showLoading("PhonePe: fetching transaction details…"); try { const url3 = `https://api.phonepe.com/apis/pg/checkout/ui/v2/transaction/details?t=${Date.now()}__5`; const res3 = await fetch(url3, { method: "POST", redirect: "follow", credentials: "include", headers: { Checkouttype: "STANDARD_CHECKOUT", Origin: "https://mercury-t2.phonepe.com", Referer: "https://mercury-t2.phonepe.com/", "X-App-Package-Name": "", "X-Browser-Fingerprint": getBrowserFingerprint(), "X-Client": "browser", "X-Client-Major-Version": "137", "X-Client-Name": "Brave", "X-Client-Subtype": "dweb", "X-Client-Type": "desktop", "X-Client-Version": "137.0.0.0", "X-Device-Type": "desktop", "X-Merchant-Domain": "https://www.wps.irctc.co.in/", "X-Source": "API", "X-Source-Channel": "Mac OS", "X-Source-Channel-Version": "10.15.7", "X-Source-Integration-Mode": "REDIRECTION", "Content-Type": "application/json; charset=UTF-8", authorization: `Bearer ${phonePeToken}`, "x-auth-token": phonePeToken, }, body: JSON.stringify({ retryConsentGranted: false }), }); if (!res3.ok) throw new Error(`details status ${res3.status}`); const json3 = await res3.json(); } catch (err) { stopWarmUp(); hideLoading(); clog("❌ transaction/details failed:", err); showErrorMessage("Failed to fetch transaction details"); return; } // 4) Fetch UPI QR code showLoading("PhonePe: fetching UPI QR code…"); let qrCode; try { const url4 = `https://api.phonepe.com/apis/pg/checkout/ui/v2/upi-qr?t=${Date.now()}__5`; const res4 = await fetch(url4, { method: "GET", redirect: "follow", credentials: "include", headers: { accept: "application/json, text/plain, */*", "accept-language": "en-GB,en;q=0.5", authorization: `Bearer ${phonePeToken}`, origin: "https://mercury-t2.phonepe.com", priority: "u=1, i", referer: "https://mercury-t2.phonepe.com/", "sec-ch-ua": '"Brave";v="137", "Chromium";v="137", "Not/A)Brand";v="24"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"macOS"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-site", "sec-gpc": "1", "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "x-auth-token": phonePeToken, "x-browser-fingerprint": getBrowserFingerprint(), }, }); if (!res4.ok) throw new Error(`upi-qr status ${res4.status}`); const json4 = await res4.json(); qrCode = json4.qrCode; if (!qrCode) throw new Error("V9.7.1 no qrCode in UPI QR response"); } catch (err) { stopWarmUp(); hideLoading(); clog("❌ upi-qr failed:", err); showErrorMessage("V9.7.1 Failed to fetch UPI QR code"); return; } finally { hideLoading(); } showPhonePeQR(qrCode,totalAmount); pollPhonePeStatus(phonePeToken); } async function pollPhonePeStatus(phonePeToken) { const headers = { ...buildCommonHeaders(), authorization: `Bearer ${phonePeToken}`, "x-auth-token": phonePeToken, "x-browser-fingerprint": getBrowserFingerprint() }; while (true) { const url = `https://api.phonepe.com/apis/pg/checkout/ui/v2/status?t=${Date.now()}__5`; try { const res = await fetch(url, { method: "GET", credentials: "include", headers, }); if (!res.ok) throw new Error(`status ${res.status}`); const json = await res.json(); if (json.state === "COMPLETED") { const redirectUrl = `https://api.phonepe.com/apis/pg/checkout/ui/v2/redirect-url?t=${Date.now()}__5`; try { const redirectRes = await fetch(redirectUrl, { method: "GET", credentials: "include", headers: { ...headers, Host: "api.phonepe.com", }, }); if (!redirectRes.ok) throw new Error(`redirect-url status ${redirectRes.status}`); const redirectJson = await redirectRes.json(); const encdata = redirectJson.notificationResponse?.response; if (!encdata) throw new Error("no response in notificationResponse"); if (window.closePhonePeQR) { window.closePhonePeQR(); } else { //console.log("closePhonePeQR function not found"); } await phonepeQRSubmit(encdata); } catch (err) { stopWarmUp(); //console.error("❌ redirect-url failed:", err); showErrorMessage("V9.7.1 Failed to fetch redirect URL response"); } break; } } catch (err) { stopWarmUp(); //console.error("Polling error:", err); showErrorMessage("V9.7.1 Failed to poll PhonePe status"); break; } await new Promise((r) => setTimeout(r, 500)); } } function showPhonePeQR(qrBase64, ccsurchargeTotal, timeoutMs = 600000) { // Store references for cleanup let splash = null; let countdownInterval = null; // ── Inject clean styles once ──────────────────────────────────────────────── if (!document.getElementById("phonepe-qr-splash-styles")) { const style = document.createElement("style"); style.id = "phonepe-qr-splash-styles"; style.textContent = ` /* Overlay */ #phonepe-qr-splash { position: fixed; inset: 0; background: rgba(255, 255, 255, 0.95); display: flex; justify-content: center; align-items: center; z-index: 50000; opacity: 0; animation: fadeIn 0.3s ease-out forwards; } @keyframes fadeIn { to { opacity: 1; } } /* Card */ .qr-card { position: relative; width: min(360px, 90vw); padding: 24px; background: #ffffff; border-radius: 12px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); display: flex; flex-direction: column; align-items: center; } /* Header */ .qr-header { display: flex; justify-content: space-between; align-items: center; width: 100%; margin-bottom: 16px; } .qr-title { font-family: sans-serif; font-size: 1.4rem; font-weight: 600; color: #333333; } .qr-close { background: transparent; border: none; font-size: 1.2rem; cursor: pointer; color: #666666; } .qr-close:hover { color: #000000; } /* Amount text */ .qr-amount { font-family: sans-serif; font-size: 1.4rem; font-weight: 700; /* Bold and larger text */ color: #ff0000; /* Red color */ text-align: center; margin-bottom: 16px; } /* QR container */ .qr-container { width: 100%; background: #f9f9f9; padding: 16px; border-radius: 8px; display: flex; justify-content: center; align-items: center; margin-bottom: 16px; } .qr-container img { width: 100%; height: auto; border: none; } /* Prompt text */ .qr-prompt { font-family: sans-serif; font-size: 1rem; color: #555555; text-align: center; margin-bottom: 12px; } /* Progress circle */ .qr-progress { position: relative; width: 48px; height: 48px; } .qr-progress svg { width: 100%; height: 100%; transform: rotate(-90deg); } .qr-progress circle { fill: none; stroke: #e0e0e0; stroke-width: 4; } .qr-progress .progress-fill { stroke: #3b82f6; stroke-width: 4; stroke-dasharray: 144.5; stroke-dashoffset: 0; animation: progressCountdown ${timeoutMs}ms linear forwards; } @keyframes progressCountdown { to { stroke-dashoffset: 144.5; } } .qr-progress .countdown-text { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-family: sans-serif; font-size: 0.9rem; font-weight: 600; color: #333333; } `; document.head.appendChild(style); } // ── Build the overlay ─────────────────────────────────────────────────────── splash = document.createElement("div"); splash.id = "phonepe-qr-splash"; splash.setAttribute("role", "dialog"); splash.setAttribute("aria-labelledby", "qr-title"); const card = document.createElement("div"); card.className = "qr-card"; splash.appendChild(card); // Header with title + close const header = document.createElement("div"); header.className = "qr-header"; const title = document.createElement("div"); title.className = "qr-title"; title.id = "qr-title"; title.textContent = "Scan with PhonePe"; const closeBtn = document.createElement("button"); closeBtn.className = "qr-close"; closeBtn.textContent = "βœ•"; closeBtn.setAttribute("aria-label", "Close"); closeBtn.onclick = () => closeSplash(); header.appendChild(title); header.appendChild(closeBtn); card.appendChild(header); // Amount display const amount = document.createElement("div"); amount.className = "qr-amount"; amount.textContent = `Pay β‚Ή${Number(ccsurchargeTotal).toFixed(2)}`; card.appendChild(amount); // QR container const qrContainer = document.createElement("div"); qrContainer.className = "qr-container"; const qrImg = document.createElement("img"); qrImg.src = `data:image/png;base64,${qrBase64}`; qrImg.alt = "PhonePe UPI QR Code"; qrContainer.appendChild(qrImg); card.appendChild(qrContainer); // Prompt text const prompt = document.createElement("div"); prompt.className = "qr-prompt"; prompt.textContent = "Point your PhonePe camera at the code to pay - V9.7.1"; card.appendChild(prompt); // Countdown progress const progress = document.createElement("div"); progress.className = "qr-progress"; progress.innerHTML = `
${Math.floor(timeoutMs / 1000)}
`; card.appendChild(progress); // Insert into DOM document.body.appendChild(splash); closeBtn.focus(); // Timer logic let timeLeft = Math.floor(timeoutMs / 1000); const countdownText = progress.querySelector(".countdown-text"); countdownInterval = setInterval(() => { timeLeft--; countdownText.textContent = timeLeft; if (timeLeft <= 0) closeSplash(); }, 1000); const timeoutId = setTimeout(() => closeSplash(), timeoutMs); // Cleanup function closeSplash() { if (splash && document.body.contains(splash)) { document.body.removeChild(splash); clearInterval(countdownInterval); clearTimeout(timeoutId); } splash = null; } window.closePhonePeQR = closeSplash; } async function initiateIRCTCQR(totalAmount) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("πŸš€ Attacking Target Airbases..."); clog("Initiating payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); return; } const url = `https://www.irctc.co.in/eticketing/protected/mapps1/bookingInitPayment/${window.clientTransactionId}?insurenceApplicable=NA`; const headers = { "greq": window.greq, "bmirak": "webbm", "bmiyek": window.bmiyek, "Authorization": `Bearer ${window.accessToken}`, "Spa-Csrf-Token": window.csrfToken || "", "Content-Type": "application/json; charset=UTF-8" }; const body = { bankId: "113", txnType: 1, paramList: [], amount: totalAmount, transationId: 0, txnStatus: 1 }; try { warmUpLoop(); const fetchPromise = fetch(url, { method: "POST", headers, credentials: "include", body: JSON.stringify(body) }); const response = await fetchPromise; if (response.status == 401) { stopWarmUp(); hideLoading(); clog(`❌ 401 response: ${response.status}`); showLoading("Access Token Getting Revoked, Please Change Browser Fingerprint & Login Again"); return; } const newToken = response.headers.get("csrf-token"); if (newToken) { storeSessionData(newToken, window.accessToken, window.greq); } const responseClone = response.clone(); const data = await response.json().catch(() => undefined); if (data && processErrorMsg(data)) return; const responseText = await responseClone.text(); if (responseText.includes("Unable to process Payment request now")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” IRCTC QR Gateway is down. Use other payment methods."); return; } if (responseText.includes("Sorry !! Unable to process the request due to issue at Bank end")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” IRCTC QR Gateway is down. Try another payment method."); return; } if (responseText.includes("Unable to Process Request")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Fingerprint Block, Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Change IRCTC Account. This account is getting blocked at payment"); return; } if (response.status === 409) { stopWarmUp(); clog("⚠️ Received 409 Conflict – retrying booking flow..."); showLoading("Multiple Device Logins..Refreshing Login.."); return; } if (response.status === 403) { stopWarmUp(); clog("❌ IP Address Flagged, User need to press HARD RESET"); showLoading("Your IP Address is Blocked, Change IP & Use Fresh Browser & Try again"); window.allowSimulationTrigger = true; return false; } if (response.status === 503) { stopWarmUp(); clog("⚠️ CSRF Token Mismatch....."); showLoading("Tokens Mismatch from authenavail..Restarting Login.."); return; } if (response.status === 510) { stopWarmUp(); clog("🚫 510 Not Extended – Gateway rate-limited response."); showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different Browser & IRCTC Account ID"); return; } if (response.ok) { clog("Payment initiation successful."); window.paymentResponse = data; return data; } else { stopWarmUp(); clog("Payment initiation failed. Status: " + response.status); return null; } } catch (err) { stopWarmUp(); hideLoading(); if (err.message.includes("Failed to fetch") || err.message.includes("failed to fetch")) { localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different IRCTC Account ID"); window.lastAvailabilityResponse = { errorMessage: "HTTP2 Protocol Error" }; } clog("❌ Error during payment initiation: " + err.message); return null; } finally { clog("βœ… success irctcupi send finally"); } } async function initiateIRCTCQRRedirect() { hideErrorMessage(); clog("Initiating UPI Payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); return null; } const url = "https://www.wps.irctc.co.in/eticketing/PaymentRedirect"; const randomDigits = Array.from({ length: 8 }, () => Math.floor(Math.random() * 10) ).join(''); const csrfToken = window.csrfToken || ""; const combinedCsrf = `${randomDigits}.${csrfToken}`; const username = document.getElementById("username").value; const txnValue = `${username}:${window.clientTransactionId}`; const postBody = `token=${encodeURIComponent(window.accessToken)}` + `&txn=${encodeURIComponent(txnValue)}` + `&${encodeURIComponent(txnValue)}=${encodeURIComponent(combinedCsrf)}`; const headers = { "Content-Type": "application/x-www-form-urlencoded" }; try { paymentWarmLoop(); const response = await fetch(url, { method: "POST", headers, credentials: "include", body: postBody }); const checkResponse = await response.clone().text(); if (checkResponse.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 Change IRCTC Account, This Account is getting blocked at Payment"); return; } const responseText = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(responseText, "text/html"); const form = doc.querySelector("form"); const actionUrl = form ? form.getAttribute("action") : null; const encdataInput = doc.querySelector("input[name='encdata']"); if (actionUrl && encdataInput?.value) { IRCTCQRencdataSendOperation(actionUrl, encdataInput.value); return; } else { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 Failed to Retrieve Encryption/Redirect Data"); return null; } } catch (err) { stopWarmUp(); hideLoading(); clog("❌ Error during payment redirect:", err); return { status: "error", message: err.message }; } finally { clog("βœ… success in payment redirect finally"); } } async function IRCTCQRencdataSendOperation(actionUrl, encdata) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); let fullUrl; try { fullUrl = new URL(actionUrl, "https://www.irctcipay.com").href; } catch (error) { clog("❌ Invalid action URL:", actionUrl); hideLoading(); return null; } const dataString = `encdata=${encodeURIComponent(encdata)}`; try { const response = await fetch(fullUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", body: dataString }); chrome.cookies.getAll({ domain: "www.irctcipay.com" }, (cookies) => { window.config = window.config || {}; cookies.forEach(cookie => { if (cookie.name === "JSESSIONID") window.config.JSESSIONID = cookie.value; if (cookie.name === "GCLB") window.config.GCLB = cookie.value; }); IRCTCQRsurchargelocaleDataRetrieval(); }); return; } catch (err) { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 An error occurred during ENC Data send operation."); return null; } } async function IRCTCQRsurchargelocaleDataRetrieval() { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); const fullUrl = "https://www.irctcipay.com/pgui/jsp/surchargelocale?request_localeA=&defaultLanguageA="; const jsession = window.config?.JSESSIONID || ""; const gclb = window.config?.GCLB || ""; const cookieHeader = `JSESSIONID=${jsession}; GCLB=${gclb}`; try { const response = await fetch(fullUrl, { method: "GET", headers: { "Cookie": cookieHeader }, credentials: "include" }); clog("Surcharge locale response status:", response.status); if (response.status === 401) { stopWarmUp(); clog("Access Token Expired: Received Unauthorized Message"); hideLoading(); return null; } if (response.status < 200 || response.status >= 300) { stopWarmUp(); clog("HTTP Error during surcharge locale retrieval:", response.status); hideLoading(); return null; } const responseText = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(responseText, "text/html"); const customToken = doc.querySelector("input[name='customToken']")?.value || null; const ccsurchargeTotal = doc.querySelector("input#ccsurchargeTotal")?.value || null; IRCTCQRgetQRCODE(customToken, ccsurchargeTotal); return; } catch (err) { stopWarmUp(); clog("❌ Error during surcharge locale retrieval:", err.message); hideLoading(); showErrorMessage("V9.7.1 Error retrieving surcharge locale data."); return null; } } async function IRCTCQRgetQRCODE(customToken, ccsurchargeTotal) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("Retrieving IRCTC QR Code Now...."); const url = "https://www.irctcipay.com/pgui/jsp/upiPay"; const jsession = window.config?.JSESSIONID || ""; const gclb = window.config?.GCLB || ""; const formData = new FormData(); formData.append("token", customToken); formData.append("IsQr", "Y"); formData.append("upiCustName", "dummy"); formData.append("paymentType", "UP"); formData.append("mopType", "UP"); formData.append("amount", `β‚Ή ${ccsurchargeTotal}`); formData.append("currencyCode", "356"); formData.append("browserName", "Chrome"); try { const response = await fetch(url, { method: "POST", headers: { Cookie: `JSESSIONID=${jsession}; GCLB=${gclb}`, }, body: formData, }); // Check if response is OK (status 200-299) if (!response.ok) { const errorText = await response.text(); // Get raw response for non-JSON errors clog(`❌ HTTP Error: ${response.status} ${response.statusText}`, errorText); throw new Error(`HTTP Error: ${response.status} ${response.statusText}`); } const jsonResponse = await response.json(); const msg = jsonResponse.responseMessage || "Unknown error"; const pgRefHash = jsonResponse.pgRefHash || null; const pgRefNum = jsonResponse.pgRefNum || null; const imageData = jsonResponse.imageData || null; if (pgRefHash && pgRefNum) { window.config = window.config || {}; window.config.payment_details = { pgRefHash, pgRefNum, token: customToken, }; clog("QR Data Retrieved Successfully"); if (imageData && imageData.startsWith("data:image/png;base64,")) { const qrBase64 = imageData.replace("data:image/png;base64,", ""); showIRCTCQR(qrBase64,ccsurchargeTotal); qrpollPaymentStatus(); } else { showErrorMessage("V9.7.1 Failed to retrieve QR code."); hideLoading(); } } else { showErrorMessage("V9.7.1 Failed to initiate UPI mandate."); hideLoading(); } } catch (err) { hideLoading(); // Log detailed error information clog("❌ Error in UPI mandate request:", { message: err.message, stack: err.stack, name: err.name, }); showErrorMessage(`V9.7.1 Failed to initiate UPI mandate: ${err.message}`); return false; } } function showIRCTCQR(qrBase64, ccsurchargeTotal, timeoutMs = 600000) { let splash = null; let countdownInterval = null; // Inject styles once if (!document.getElementById("irctc-qr-splash-styles")) { const style = document.createElement("style"); style.id = "irctc-qr-splash-styles"; style.textContent = ` #irctc-qr-splash { position: fixed; inset: 0; background: #ffffff; /* Solid white background */ display: flex; justify-content: center; align-items: center; z-index: 50000; opacity: 0; animation: fadeIn 0.6s ease-in-out forwards; overflow: hidden; } @keyframes fadeIn { to { opacity: 1; } } .qr-card { position: relative; width: min(400px, 90vw); padding: 24px; background: #ffffff; /* White card background */ border-radius: 16px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); /* Subtle shadow */ border: 1px solid #e0e0e0; /* Light border */ transition: transform 0.3s ease; } .qr-card:hover { transform: scale(1.02); /* Subtle hover effect */ } .qr-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .qr-title { font-family: 'SF Pro Display', -apple-system, sans-serif; font-size: 1.5rem; font-weight: 600; color: #1a1a1a; /* Dark text for contrast */ } .qr-close { background: #f0f0f0; border: none; border-radius: 50%; width: 30px; height: 30px; color: #333; font-size: 1rem; cursor: pointer; transition: all 0.2s ease; display: flex; align-items: center; justify-content: center; } .qr-close:hover { background: #e0e0e0; transform: scale(1.1); } .qr-close:focus { outline: none; box-shadow: 0 0 0 3px rgba(0, 120, 255, 0.3); } .qr-amount { font-family: 'SF Pro Text', -apple-system, sans-serif; font-size: 1.4rem; font-weight: 700; /* Bold and larger text */ color: #ff0000; /* Red color */ text-align: center; margin-bottom: 16px; } .qr-container { position: relative; padding: 12px; background: #ffffff; /* White background for QR code */ border-radius: 12px; border: 2px solid #e0e0e0; /* Subtle border */ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } .qr-container img { width: 100%; height: auto; border-radius: 8px; background: #ffffff; /* Ensure QR code has white background */ } .qr-scan-line { position: absolute; top: 0; left: 0; right: 0; height: 2px; background: linear-gradient(90deg, transparent, #0078ff, transparent); opacity: 0.7; animation: scanLine 2s infinite ease-in-out; } @keyframes scanLine { 0% { transform: translateY(0); } 50% { transform: translateY(100%); } 100% { transform: translateY(0); } } .qr-prompt { text-align: center; font-family: 'SF Pro Text', -apple-system, sans-serif; font-size: 1rem; font-weight: 500; color: #333; /* Dark text for readability */ margin: 16px 0; line-height: 1.5; } .qr-progress { position: relative; width: 48px; height: 48px; margin: 16px auto; } .qr-progress svg { width: 100%; height: 100%; transform: rotate(-90deg); } .qr-progress circle { fill: none; stroke: #e0e0e0; stroke-width: 4; } .qr-progress .progress-fill { stroke: #0078ff; stroke-width: 4; stroke-linecap: round; stroke-dasharray: 138.2; stroke-dashoffset: 0; animation: progressCountdown ${timeoutMs}ms linear forwards; } @keyframes progressCountdown { to { stroke-dashoffset: 138.2; } } .qr-progress .countdown-text { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-family: 'SF Pro Text', sans-serif; font-size: 0.9rem; font-weight: 600; color: #333; } .qr-progress.urgent .countdown-text { animation: textPulse 0.6s infinite ease-in-out; color: #ff4d4d; } @keyframes textPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.08); } } `; document.head.appendChild(style); } // Build the splash overlay splash = document.createElement("div"); splash.id = "irctc-qr-splash"; splash.setAttribute("role", "dialog"); splash.setAttribute("aria-labelledby", "qr-title"); const card = document.createElement("div"); card.className = "qr-card"; splash.appendChild(card); // Header const header = document.createElement("div"); header.className = "qr-header"; const title = document.createElement("div"); title.className = "qr-title"; title.id = "qr-title"; title.textContent = "Pay with UPI QR Scanner"; const closeBtn = document.createElement("button"); closeBtn.className = "qr-close"; closeBtn.textContent = "βœ•"; closeBtn.setAttribute("aria-label", "Close payment dialog"); closeBtn.onclick = () => closeSplash(); header.appendChild(title); header.appendChild(closeBtn); card.appendChild(header); // Amount display const amount = document.createElement("div"); amount.className = "qr-amount"; amount.textContent = `Pay β‚Ή${Number(ccsurchargeTotal).toFixed(2)}`; card.appendChild(amount); // QR container const qrContainer = document.createElement("div"); qrContainer.className = "qr-container"; const qrScanLine = document.createElement("div"); qrScanLine.className = "qr-scan-line"; const qrImg = document.createElement("img"); qrImg.src = `data:image/png;base64,${qrBase64}`; qrImg.alt = "IRCTC UPI QR Code"; qrContainer.appendChild(qrScanLine); qrContainer.appendChild(qrImg); card.appendChild(qrContainer); // Prompt & progress const prompt = document.createElement("div"); prompt.className = "qr-prompt"; prompt.textContent = "Scan with any UPI app to complete your payment - Brahmos V9.7.1"; card.appendChild(prompt); const progress = document.createElement("div"); progress.className = "qr-progress"; progress.innerHTML = `
${Math.floor(timeoutMs / 1000)}
`; card.appendChild(progress); // Add to DOM document.body.appendChild(splash); // Focus trap const focusable = [closeBtn]; let firstFocusable = focusable[0], lastFocusable = focusable[focusable.length - 1]; splash.addEventListener("keydown", (e) => { if (e.key === "Tab") { if (e.shiftKey && document.activeElement === firstFocusable) { e.preventDefault(); lastFocusable.focus(); } else if (!e.shiftKey && document.activeElement === lastFocusable) { e.preventDefault(); firstFocusable.focus(); } } if (e.key === "Escape") { closeSplash(); } }); firstFocusable.focus(); // Countdown timer UI let timeLeft = timeoutMs / 1000; const countdownText = progress.querySelector(".countdown-text"); const urgentThreshold = 30; countdownInterval = setInterval(() => { timeLeft--; countdownText.textContent = timeLeft; if (timeLeft <= urgentThreshold) { progress.classList.add("urgent"); } if (timeLeft <= 0) { closeSplash(); } }, 1000); // Auto-close on timeout const timeoutId = setTimeout(() => { closeSplash(); }, timeoutMs); // Internal close function function closeSplash() { if (splash && document.body.contains(splash)) { document.body.removeChild(splash); clearInterval(countdownInterval); clearTimeout(timeoutId); } splash = null; countdownInterval = null; } window.closeIRCTCQR = closeSplash; } async function checkIRCTCQRPaymentStatus() { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); clog("Initiating payment status check..."); const url = "https://www.irctcipay.com/pgui/jsp/verifyUpiResponse"; const { token, pgRefNum, pgRefHash } = window.config?.payment_details || {}; if (!token || !pgRefNum || !pgRefHash) { clog("Missing payment details to check payment status."); showErrorMessage("V9.7.1 Missing payment details to check payment status."); hideLoading(); return null; } const jsession = window.config?.JSESSIONID || ""; const gclb = window.config?.GCLB || ""; const formData = new FormData(); formData.append("token", token); formData.append("pgRefNum", pgRefNum); formData.append("pgRefHash", pgRefHash); try { const response = await fetch(url, { method: "POST", headers: { "Cookie": `JSESSIONID=${jsession}; GCLB=${gclb}` }, credentials: "include", body: formData }); if (response.status === 401) { clog("Access Token Expired: Unauthorized Message in payment status"); return null; } if (!response.ok) { clog("HTTP Error during payment status check: " + response.status); return null; } const text = (await response.text()).trim(); if (!text) { clog("No response body yet; continuing to poll."); return null; } try { const jsonResponse = JSON.parse(text); const pgTxnMessage = jsonResponse.responseFields?.PG_TXN_MESSAGE || null; clog("Payment status check successful. PG_TXN_MESSAGE: " + pgTxnMessage); return jsonResponse; } catch { clog("Invalid JSON β€” still waiting for payment response."); return null; } } catch (err) { hideLoading(); clog("An error occurred during payment status check:", err.message); return null; } } async function qrpollPaymentStatus(maxAttempts = 500) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideLoading(); hideErrorMessage(); let attempts = 0; while (attempts < maxAttempts) { attempts++; const response = await checkIRCTCQRPaymentStatus(); if (response?.responseFields?.PG_TXN_MESSAGE) { hideUPIPaymentSplash(); const msg = response.responseFields.PG_TXN_MESSAGE; clog(`Payment status received on attempt ${attempts}: ${msg}`); const encdata = response.responseFields.encdata; clog(`Submitting bank response with encdata: ${encdata}`); if (window.closeIRCTCQR) { window.closeIRCTCQR(); } else { //console.log("closeIRCTCQR function not found"); } await irctcQRSubmit(encdata); return; } clog(`No payment status yet (attempt ${attempts}/${maxAttempts}). Retrying in 500ms…`); await new Promise(resolve => setTimeout(resolve, 500)); } hideUPIPaymentSplash(); clog("Max attempts reached. No expected payment status response received."); showErrorMessage("V9.7.1 UPI Payment not confirmed. Please try again."); hideLoading(); } async function initiateIPAYDC(totalAmount) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("πŸš€ Attacking Target Airbases..."); clog("Initiating payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); return; } const url = `https://www.irctc.co.in/eticketing/protected/mapps1/bookingInitPayment/${window.clientTransactionId}?insurenceApplicable=NA`; const headers = { "greq": window.greq, "bmirak": "webbm", "bmiyek": window.bmiyek, "Authorization": `Bearer ${window.accessToken}`, "Spa-Csrf-Token": window.csrfToken || "", "Content-Type": "application/json; charset=UTF-8" }; const body = { bankId: "113", txnType: 1, paramList: [], amount: totalAmount, transationId: 0, txnStatus: 1 }; try { //warmUpLoop(); const fetchPromise = fetch(url, { method: "POST", headers, credentials: "include", body: JSON.stringify(body) }); const response = await fetchPromise; if (response.status == 401) { stopWarmUp(); hideLoading(); clog(`❌ 401 response: ${response.status}`); showLoading("Access Token Getting Revoked, Please Change Browser Fingerprint & Login Again"); return; } const newToken = response.headers.get("csrf-token"); if (newToken) { storeSessionData(newToken, window.accessToken, window.greq); } const responseClone = response.clone(); const data = await response.json().catch(() => undefined); if (data && processErrorMsg(data)) return; const responseText = await responseClone.text(); if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 Change IRCTC Account and Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } if (responseText.includes("Unable to process Payment request now")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” IRCTC UPI Gateway is down. Use other payment methods."); return; } if (responseText.includes("Sorry !! Unable to process the request due to issue at Bank end")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” IPAYDC Gateway is down. Try another payment method."); return; } if (responseText.includes("Unable to Process Request")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Fingerprint Block, Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Change IRCTC Account. This account is getting blocked at payment"); return; } if (response.status === 409) { stopWarmUp(); clog("⚠️ Received 409 Conflict – retrying booking flow..."); showLoading("Multiple Device Logins..Refreshing Login.."); return; } if (response.status === 403) { stopWarmUp(); clog("❌ IP Address Flagged, User need to press HARD RESET"); showLoading("Your IP Address is Blocked, Change IP & Use Fresh Browser & Try again"); window.allowSimulationTrigger = true; return false; } if (response.status === 503) { stopWarmUp(); clog("⚠️ CSRF Token Mismatch....."); showLoading("Tokens Mismatch from authenavail..Restarting Login.."); return; } if (response.status === 510) { stopWarmUp(); clog("🚫 510 Not Extended – Gateway rate-limited response."); showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different Browser & IRCTC Account ID"); return; } if (response.ok) { clog("Payment initiation successful."); window.paymentResponse = data; return data; } else { stopWarmUp(); clog("Payment initiation failed. Status: " + response.status); return null; } } catch (err) { stopWarmUp(); hideLoading(); if (err.message.includes("Failed to fetch") || err.message.includes("failed to fetch")) { localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different IRCTC Account ID"); window.lastAvailabilityResponse = { errorMessage: "HTTP2 Protocol Error" }; } clog("❌ Error during payment initiation: " + err.message); return null; } finally { clog("βœ… success irctcupi send finally"); } } async function initiateIPAYDCRedirect() { hideErrorMessage(); clog("Initiating IPAY DC Payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); return null; } const url = "https://www.wps.irctc.co.in/eticketing/PaymentRedirect"; const randomDigits = Array.from({ length: 8 }, () => Math.floor(Math.random() * 10) ).join(''); const csrfToken = window.csrfToken || ""; const combinedCsrf = `${randomDigits}.${csrfToken}`; const username = document.getElementById("username").value; const txnValue = `${username}:${window.clientTransactionId}`; const postBody = `token=${encodeURIComponent(window.accessToken)}` + `&txn=${encodeURIComponent(txnValue)}` + `&${encodeURIComponent(txnValue)}=${encodeURIComponent(combinedCsrf)}`; const headers = { "Content-Type": "application/x-www-form-urlencoded" }; try { paymentWarmLoop(); const response = await fetch(url, { method: "POST", headers, credentials: "include", body: postBody }); const checkResponse = await response.clone().text(); if (checkResponse.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 Change IRCTC Account and Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } const responseText = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(responseText, "text/html"); const form = doc.querySelector("form"); const actionUrl = form ? form.getAttribute("action") : null; const encdataInput = doc.querySelector("input[name='encdata']"); if (actionUrl && encdataInput?.value) { encdataIPAYDC(actionUrl, encdataInput.value); return; } else { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 Failed to Retrieve Encryption/Redirect Data"); return null; } } catch (err) { stopWarmUp(); hideLoading(); clog("❌ Error during payment redirect:", err); return { status: "error", message: err.message }; } finally { clog("βœ… success in payment redirect finally"); } } async function encdataIPAYDC(actionUrl, encdata) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); let fullUrl; try { fullUrl = new URL(actionUrl, "https://www.irctcipay.com").href; } catch (error) { clog("❌ Invalid action URL:", actionUrl); hideLoading(); return null; } const dataString = `encdata=${encodeURIComponent(encdata)}`; try { const response = await fetch(fullUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", body: dataString }); chrome.cookies.getAll({ domain: "www.irctcipay.com" }, (cookies) => { window.config = window.config || {}; cookies.forEach(cookie => { if (cookie.name === "JSESSIONID") window.config.JSESSIONID = cookie.value; if (cookie.name === "GCLB") window.config.GCLB = cookie.value; }); surchargeIPAYDC(); }); return; } catch (err) { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 An error occurred during ENC Data send operation."); return null; } } async function surchargeIPAYDC() { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); const fullUrl = "https://www.irctcipay.com/pgui/jsp/surchargelocale?request_localeA=&defaultLanguageA="; const vpa = document.getElementById("upiId")?.value.trim() || ""; const jsession = window.config?.JSESSIONID || ""; const gclb = window.config?.GCLB || ""; const cookieHeader = `JSESSIONID=${jsession}; GCLB=${gclb}`; try { const response = await fetch(fullUrl, { method: "GET", headers: { "Cookie": cookieHeader }, credentials: "include" }); clog("Surcharge locale response status:", response.status); if (response.status === 401) { stopWarmUp(); clog("Access Token Expired: Received Unauthorized Message"); hideLoading(); return null; } if (response.status < 200 || response.status >= 300) { stopWarmUp(); clog("HTTP Error during surcharge locale retrieval:", response.status); hideLoading(); return null; } const responseText = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(responseText, "text/html"); const customToken = doc.querySelector("input[name='customToken']")?.value || null; const ccsurchargeTotal = doc.querySelector("input#ccsurchargeTotal")?.value || null; IPAYDCInitiate(customToken,ccsurchargeTotal); return; } catch (err) { stopWarmUp(); clog("❌ Error during surcharge locale retrieval:", err.message); hideLoading(); showErrorMessage("V9.7.1 Error retrieving surcharge locale data."); return null; } } async function IPAYDCInitiate(customToken, ccsurchargeTotal) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("πŸš€ Validating card BIN…"); const rawCardNumber = document.getElementById("cardNumber")?.value || ""; const expiryRaw = document.getElementById("cardExpiry")?.value || ""; const cvvRaw = document.getElementById("cardCVV")?.value || ""; const staticPwd = document.getElementById("staticPassword")?.value.trim() || ""; const rawName = document.getElementById("cardHolderName")?.value.trim() || ""; const cardNumberRaw = rawCardNumber.replace(/\s/g, ""); if (!cardNumberRaw || !expiryRaw || !cvvRaw || !staticPwd || !rawName) { hideLoading(); showErrorMessage("❌ Please fill in card number, expiry, CVV, name & static password."); return false; } try { const binForm = new FormData(); binForm.append("token", customToken); binForm.append("bin", cardNumberRaw.slice(0, 9)); const binRes = await fetch( "https://www.irctcipay.com/pgui/jsp/binResolver", { method: "POST", credentials: "include", body: binForm } ); await binRes.json(); } catch (err) { hideLoading(); clog("❌ Error resolving BIN:", err.message); showErrorMessage("❌ Failed to validate card BIN"); return false; } showLoading("πŸš€ Initiating HDFC DC Payment…"); const groupedNumberPlus = cardNumberRaw.match(/.{1,4}/g).join("+"); let [month, yearShort] = expiryRaw.split("/"); month = month.padStart(2, "0"); const year = /^\d{2}$/.test(yearShort) ? "20" + yearShort : yearShort; const namePlus = rawName.replace(/\s+/g, " ").replace(/ /g, "+"); const payBody = [ "browserName=Firefox", "browserVersion=140", "paymentType=DC", "mopType=VI", "issuerBankName=", "issuerCountry=", "cardHolderType=", "paymentsRegion=", `cardNumber=${groupedNumberPlus}`, `expiryYear=${year}`, `expiryMonth=${month}`, `cvvNumber=${cvvRaw}`, `cardName=${namePlus}`, `amount=${ccsurchargeTotal}`, `customToken=${customToken}`, "cardsaveflag=false", "tokenizeCard=false" ].join("&"); try { const resp = await fetch( "https://www.irctcipay.com/pgui/jsp/pay", { method: "POST", credentials: "include", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: payBody } ); const html = await resp.text(); const doc = new DOMParser().parseFromString(html, "text/html"); const form = doc.getElementById("threedsChallengeRedirectForm"); if (!form) { hideLoading(); showErrorMessage("❌ Invalid Debit/Credit Card Number"); clog("❌ threedsChallengeRedirectForm missing"); return; } const actionUrl = form.action; const creq = form.querySelector("input[name='creq']").value; await HDFCIPAYDC(actionUrl, creq); } catch (err) { hideLoading(); clog("❌ Error in card payment request:", err.message); showErrorMessage("❌ Failed to initiate card payment"); } } async function sha256hex(str) { const data = new TextEncoder().encode(str); const hash = await crypto.subtle.digest("SHA-256", data); return Array.from(new Uint8Array(hash)) .map(b => b.toString(16).padStart(2, "0")) .join(""); } async function HDFCIPAYDC(initialUrl, creq) { hideErrorMessage(); showLoading("πŸš€ Initiating HDFC DC Payment…"); const rawPwd = document.getElementById("staticPassword")?.value.trim(); if (!rawPwd) { hideLoading(); showErrorMessage("❌ Please enter your static password."); return false; } try { const resp1 = await fetch(initialUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", body: new URLSearchParams({ creq }) }); const html1 = await resp1.text(); if (!html1.includes("Static Password")) { throw new Error("Did not receive Static Password prompt"); } const doc1 = new DOMParser().parseFromString(html1, "text/html"); const form1 = doc1.querySelector("form"); if (!form1) throw new Error("Static Password form not found"); const saltMatch = html1.match(/var\s+saltx\s*=\s*"(\d+)"/); if (!saltMatch) throw new Error("Salt value not found in page script"); const salt = saltMatch[1]; const creqField = form1.querySelector("input[name='creq']").value; const hash1 = await sha256hex(rawPwd); const salted = hash1 + salt; const passCode = await sha256hex(salted); const resp2 = await fetch(initialUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", body: new URLSearchParams({ passCode, acctId: "", creq: creqField, formReqType: "SUBMIT", flowMode: "VERIFICATION", registrationPage: "", isInitialADSRegFlag: "", forgotPasswordFlag: "", activeSection: "staticSection" }) }); const html2 = await resp2.text(); if (html2.includes("The static password you entered is incorrect")) { hideLoading(); showErrorMessage("❌ Your Debit Card Static Password is Incorrect"); return false; } if (!html2.includes("Your transaction is being processed")) { throw new Error("3DS verification failed"); } const doc2 = new DOMParser().parseFromString(html2, "text/html"); const cres = doc2.querySelector("input[name='cres']")?.value; if (!cres) throw new Error("CRes value not found in ACS response"); await DCStaticbankResponse(cres); } catch (err) { hideLoading(); clog("❌ HDFC payment flow error:", err.message); showErrorMessage("Something went wrong in the 3DS flow"); } } async function DCStaticbankResponse(cres) { hideErrorMessage(); showLoading("πŸš€ Finalizing UPI payment..."); try { const irctcUrl = "https://www.irctcipay.com/pgui/jsp/iciciIpgV2Return"; const resp3 = await fetch(irctcUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", body: new URLSearchParams({ threeDSSessionData: "", cres }) }); const html3 = await resp3.text(); const doc3 = new DOMParser().parseFromString(html3, "text/html"); const encdata = doc3.querySelector("input[name='encdata']")?.value; if (!encdata) throw new Error("encdata not found in final form"); UPIbankResponse(encdata); } catch (err) { hideLoading(); clog("❌ UPI bank response error:", err.message); showErrorMessage("Failed to post 3DS result back to IRCTC"); } } async function initiateIRCTCUPI(totalAmount) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("πŸš€ Attacking Target Airbases..."); clog("Initiating payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); return; } const url = `https://www.irctc.co.in/eticketing/protected/mapps1/bookingInitPayment/${window.clientTransactionId}?insurenceApplicable=NA`; const headers = { "greq": window.greq, "bmirak": "webbm", "bmiyek": window.bmiyek, "Authorization": `Bearer ${window.accessToken}`, "Spa-Csrf-Token": window.csrfToken || "", "Content-Type": "application/json; charset=UTF-8" }; const body = { bankId: "113", txnType: 1, paramList: [], amount: totalAmount, transationId: 0, txnStatus: 1 }; try { warmUpLoop(); const fetchPromise = fetch(url, { method: "POST", headers, credentials: "include", body: JSON.stringify(body) }); const response = await fetchPromise; if (response.status == 401) { stopWarmUp(); hideLoading(); clog(`❌ 401 response: ${response.status}`); showLoading("Access Token Getting Revoked, Please Change Browser Fingerprint & Login Again"); return; } const newToken = response.headers.get("csrf-token"); if (newToken) { storeSessionData(newToken, window.accessToken, window.greq); } const responseClone = response.clone(); const data = await response.json().catch(() => undefined); if (data && processErrorMsg(data)) return; const responseText = await responseClone.text(); if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 Change IRCTC Account and Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } if (responseText.includes("Unable to process Payment request now")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” IRCTC UPI Gateway is down. Use other payment methods."); return; } if (responseText.includes("Sorry !! Unable to process the request due to issue at Bank end")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” IRCTC UPI Gateway is down. Try another payment method."); return; } if (responseText.includes("Unable to Process Request")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Fingerprint Block, Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Change IRCTC Account. This account is getting blocked at payment"); return; } if (response.status === 409) { stopWarmUp(); clog("⚠️ Received 409 Conflict – retrying booking flow..."); showLoading("Multiple Device Logins..Refreshing Login.."); return; } if (response.status === 403) { stopWarmUp(); clog("❌ IP Address Flagged, User need to press HARD RESET"); showLoading("Your IP Address is Blocked, Change IP & Use Fresh Browser & Try again"); window.allowSimulationTrigger = true; return false; } if (response.status === 503) { stopWarmUp(); clog("⚠️ CSRF Token Mismatch....."); showLoading("Tokens Mismatch from authenavail..Restarting Login.."); return; } if (response.status === 510) { stopWarmUp(); clog("🚫 510 Not Extended – Gateway rate-limited response."); showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different Browser & IRCTC Account ID"); return; } if (response.ok) { clog("Payment initiation successful."); window.paymentResponse = data; return data; } else { stopWarmUp(); clog("Payment initiation failed. Status: " + response.status); return null; } } catch (err) { stopWarmUp(); hideLoading(); if (err.message.includes("Failed to fetch") || err.message.includes("failed to fetch")) { localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different IRCTC Account ID"); window.lastAvailabilityResponse = { errorMessage: "HTTP2 Protocol Error" }; } clog("❌ Error during payment initiation: " + err.message); return null; } finally { clog("βœ… success irctcupi send finally"); } } async function initiateIRCTCUPIRedirect() { hideErrorMessage(); clog("Initiating UPI Payment..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); return null; } const url = "https://www.wps.irctc.co.in/eticketing/PaymentRedirect"; const randomDigits = Array.from({ length: 8 }, () => Math.floor(Math.random() * 10) ).join(''); const csrfToken = window.csrfToken || ""; const combinedCsrf = `${randomDigits}.${csrfToken}`; const username = document.getElementById("username").value; const txnValue = `${username}:${window.clientTransactionId}`; const postBody = `token=${encodeURIComponent(window.accessToken)}` + `&txn=${encodeURIComponent(txnValue)}` + `&${encodeURIComponent(txnValue)}=${encodeURIComponent(combinedCsrf)}`; const headers = { "Content-Type": "application/x-www-form-urlencoded" }; try { paymentWarmLoop(); const response = await fetch(url, { method: "POST", headers, credentials: "include", body: postBody }); const checkResponse = await response.clone().text(); if (checkResponse.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 Change IRCTC Account and Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } const responseText = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(responseText, "text/html"); const form = doc.querySelector("form"); const actionUrl = form ? form.getAttribute("action") : null; const encdataInput = doc.querySelector("input[name='encdata']"); if (actionUrl && encdataInput?.value) { showUPIPaymentSplash("upi"); encdataSendOperation(actionUrl, encdataInput.value); return; } else { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 Failed to Retrieve Encryption/Redirect Data"); return null; } } catch (err) { stopWarmUp(); hideLoading(); clog("❌ Error during payment redirect:", err); return { status: "error", message: err.message }; } finally { clog("βœ… success in payment redirect finally"); } } async function encdataSendOperation(actionUrl, encdata) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); let fullUrl; try { fullUrl = new URL(actionUrl, "https://www.irctcipay.com").href; } catch (error) { clog("❌ Invalid action URL:", actionUrl); hideLoading(); return null; } const dataString = `encdata=${encodeURIComponent(encdata)}`; try { const response = await fetch(fullUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", body: dataString }); chrome.cookies.getAll({ domain: "www.irctcipay.com" }, (cookies) => { window.config = window.config || {}; cookies.forEach(cookie => { if (cookie.name === "JSESSIONID") window.config.JSESSIONID = cookie.value; if (cookie.name === "GCLB") window.config.GCLB = cookie.value; }); surchargelocaleDataRetrieval(); }); return; } catch (err) { stopWarmUp(); hideLoading(); showErrorMessage("V9.7.1 An error occurred during ENC Data send operation."); return null; } } async function surchargelocaleDataRetrieval() { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); const fullUrl = "https://www.irctcipay.com/pgui/jsp/surchargelocale?request_localeA=&defaultLanguageA="; const vpa = document.getElementById("upiId")?.value.trim() || ""; const jsession = window.config?.JSESSIONID || ""; const gclb = window.config?.GCLB || ""; const cookieHeader = `JSESSIONID=${jsession}; GCLB=${gclb}`; try { const response = await fetch(fullUrl, { method: "GET", headers: { "Cookie": cookieHeader }, credentials: "include" }); clog("Surcharge locale response status:", response.status); if (response.status === 401) { stopWarmUp(); clog("Access Token Expired: Received Unauthorized Message"); hideLoading(); return null; } if (response.status < 200 || response.status >= 300) { stopWarmUp(); clog("HTTP Error during surcharge locale retrieval:", response.status); hideLoading(); return null; } const responseText = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(responseText, "text/html"); const customToken = doc.querySelector("input[name='customToken']")?.value || null; const ccsurchargeTotal = doc.querySelector("input#ccsurchargeTotal")?.value || null; upiMandateRequest(customToken, ccsurchargeTotal, vpa); return; } catch (err) { stopWarmUp(); clog("❌ Error during surcharge locale retrieval:", err.message); hideLoading(); showErrorMessage("V9.7.1 Error retrieving surcharge locale data."); return null; } } async function upiMandateRequest(customToken, ccsurchargeTotal, vpa) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("Sending UPI Payment Request..Check Your Mobile Now..."); const url = "https://www.irctcipay.com/pgui/jsp/otmPay"; const jsession = window.config?.JSESSIONID || ""; const gclb = window.config?.GCLB || ""; const formData = new FormData(); formData.append("token", customToken); formData.append("vpa", vpa); formData.append("upiCustName", "dummy"); formData.append("paymentType", "AD"); formData.append("mopType", "UP"); formData.append("amount", `β‚Ή ${ccsurchargeTotal}`); formData.append("currencyCode", "356"); formData.append("mandateType", "upiMandate"); formData.append("browserName", "Chrome"); formData.append("browserVersion", "131"); try { const response = await fetch(url, { method: "POST", headers: { "Cookie": `JSESSIONID=${jsession}; GCLB=${gclb}` }, credentials: "include", body: formData }); const jsonResponse = await response.json(); const msg = jsonResponse.responseMessage || "Unknown error"; if (msg.toLowerCase().includes("invalid")) { showErrorMessage("V9.7.1 Invalid UPI Address, Pls Enter Valid UPI & Try Again"); return; } const pgRefHash = jsonResponse.pgRefHash || null; const pgRefNum = jsonResponse.pgRefNum || null; if (pgRefHash && pgRefNum) { window.config = window.config || {}; window.config.payment_details = { pgRefHash, pgRefNum, token: customToken }; clog("UPI Mandate Request Sent Successfully: " + pgRefHash); UPIpollPaymentStatus(); } } catch (err) { hideLoading(); clog("❌ Error in UPI mandate request:", err.message); showErrorMessage("V9.7.1 Failed to initiate UPI mandate."); } } async function checkIRCTCUPIPaymentStatus() { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); clog("Initiating payment status check..."); const url = "https://www.irctcipay.com/pgui/jsp/verifyOtmResponse"; const { token, pgRefNum, pgRefHash } = window.config?.payment_details || {}; if (!token || !pgRefNum || !pgRefHash) { clog("Missing payment details to check payment status."); showErrorMessage("V9.7.1 Missing payment details to check payment status."); hideLoading(); return null; } const jsession = window.config?.JSESSIONID || ""; const gclb = window.config?.GCLB || ""; const formData = new FormData(); formData.append("token", token); formData.append("pgRefNum", pgRefNum); formData.append("pgRefHash", pgRefHash); try { const response = await fetch(url, { method: "POST", headers: { "Cookie": `JSESSIONID=${jsession}; GCLB=${gclb}` }, credentials: "include", body: formData }); if (response.status === 401) { clog("Access Token Expired: Unauthorized Message in payment status"); return null; } if (!response.ok) { clog("HTTP Error during payment status check: " + response.status); return null; } const text = (await response.text()).trim(); if (!text) { clog("No response body yet; continuing to poll."); return null; } try { const jsonResponse = JSON.parse(text); const pgTxnMessage = jsonResponse.responseFields?.PG_TXN_MESSAGE || null; clog("Payment status check successful. PG_TXN_MESSAGE: " + pgTxnMessage); return jsonResponse; } catch { clog("Invalid JSON β€” still waiting for payment response."); return null; } } catch (err) { hideLoading(); clog("An error occurred during payment status check:", err.message); return null; } } async function UPIpollPaymentStatus(maxAttempts = 500) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideLoading(); hideErrorMessage(); let attempts = 0; while (attempts < maxAttempts) { attempts++; const response = await checkIRCTCUPIPaymentStatus(); if (response?.responseFields?.PG_TXN_MESSAGE) { hideUPIPaymentSplash(); const msg = response.responseFields.PG_TXN_MESSAGE; clog(`Payment status received on attempt ${attempts}: ${msg}`); if (msg.toLowerCase().includes("declined") || msg.toLowerCase().includes("failed")) { showErrorMessage("V9.7.1 UPI Payment Rejected By The User"); hideLoading(); return; } const encdata = response.responseFields.encdata; clog(`Submitting bank response with encdata: ${encdata}`); await UPIbankResponse(encdata); return; } clog(`No payment status yet (attempt ${attempts}/${maxAttempts}). Retrying in 500ms…`); await new Promise(resolve => setTimeout(resolve, 500)); } hideUPIPaymentSplash(); clog("Max attempts reached. No expected payment status response received."); showErrorMessage("V9.7.1 UPI Payment not confirmed. Please try again."); hideLoading(); } async function phonepeQRSubmit(encdata) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("Verifying PhonePe QR Payment Status...."); paymentWarmLoop(); const url = "https://www.wps.irctc.co.in/eticketing/BankResponse"; const body = `response=${encodeURIComponent(encdata)}`; let response; let wasRedirected = false; const startTime = Date.now(); const maxDuration = 6000; // 6 seconds in milliseconds let isFirstAttempt = true; // Track first attempt try { while (Date.now() - startTime < maxDuration) { clog(`πŸ”„ PhonePe QR bank response check at ${Math.round((Date.now() - startTime) / 1000)}s`); response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", redirect: "follow", body: isFirstAttempt ? body : undefined // Send body only on first attempt }); if (response.redirected) { clog(`β†’ Redirected to ${response.url}`); wasRedirected = true; if (response.url.includes("booking-confirm")) { clog("Reached booking confirm page"); } break; } if (response.ok && response.url.includes("booking-confirm")) { clog(`β†’ Landed on booking-confirm: ${response.url}`); wasRedirected = true; break; } clog("⏳ UPI Transaction still in process; retrying in 3.5s..."); isFirstAttempt = false; await new Promise(res => setTimeout(res, 4500)); } if (!wasRedirected) { throw new Error("IRCTC still processing the transaction; Check Your IRCTC Account Once"); } clog("UPI Bank Response completed"); UPIgetBookingInfo(); } catch (error) { showErrorMessage( "V9.6.6 network error during UPI bank response: " + error.message ); stopWarmUp(); } finally { hideLoading(); clog("UPIbankResponse done"); } } async function irctcQRSubmit(encdata) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("Verifying Payment Status...."); paymentWarmLoop(); const url = "https://www.wps.irctc.co.in/eticketing/BankResponse"; const body = `encdata=${encodeURIComponent(encdata)}`; let wasRedirected = false; const startTime = Date.now(); const maxDuration = 6000; // 6 seconds in milliseconds let isFirstAttempt = true; // Track first attempt try { while (Date.now() - startTime < maxDuration) { clog(`πŸ”„ IRCTC QR bank response check at ${Math.round((Date.now() - startTime) / 1000)}s`); const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", redirect: "follow", body: isFirstAttempt ? body : undefined // Send body only on first attempt }); if (response.redirected || (response.ok && response.url.includes("booking-confirm"))) { clog(`β†’ Redirected or landed on booking-confirm: ${response.url}`); wasRedirected = true; break; } clog("⏳ UPI Transaction still in process; retrying in 3.5s..."); isFirstAttempt = false; // Set to false after first attempt await new Promise(resolve => setTimeout(resolve, 4500)); } if (!wasRedirected) { throw new Error("IRCTC still processing the transaction; Check Your IRCTC Account Once"); } clog("UPI Bank Response completed"); UPIgetBookingInfo(); } catch (error) { showErrorMessage("V9.7.1 network error during UPI bank response: " + error.message); stopWarmUp(); } finally { hideLoading(); clog("amazonpay check complete"); } } async function UPIbankResponse(encdata) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideErrorMessage(); showLoading("Verifying Payment Status...."); paymentWarmLoop(); const url = "https://www.wps.irctc.co.in/eticketing/BankResponse"; const body = `encdata=${encodeURIComponent(encdata)}`; let wasRedirected = false; const startTime = Date.now(); const maxDuration = 6000; // 6 seconds in milliseconds let isFirstAttempt = true; // Track first attempt try { while (Date.now() - startTime < maxDuration) { clog(`πŸ”„ UPI bank response check at ${Math.round((Date.now() - startTime) / 1000)}s`); const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, credentials: "include", redirect: "follow", body: isFirstAttempt ? body : undefined // Send body only on first attempt }); if (response.redirected || (response.ok && response.url.includes("booking-confirm"))) { clog(`β†’ Redirected or landed on booking-confirm: ${response.url}`); wasRedirected = true; break; } clog("⏳ UPI Transaction still in process; retrying in 3.5s..."); isFirstAttempt = false; // Set to false after first attempt await new Promise(resolve => setTimeout(resolve, 4500)); } if (!wasRedirected) { throw new Error("IRCTC still processing the transaction; Check Your IRCTC Account Once"); } clog("UPI Bank Response completed"); UPIgetBookingInfo(); } catch (error) { showErrorMessage("V9.7.1 network error during UPI bank response: " + error.message); stopWarmUp(); } finally { hideLoading(); clog("all check complete"); } } async function UPIgetBookingInfo() { hideErrorMessage(); showLoading("Fetching booking information..."); const accessToken = window.accessToken; const spaCsrfToken = window.csrfToken; if (!accessToken || !spaCsrfToken) { showErrorMessage( "V9.7.1 Missing access token or CSRF token in Booking Info Retrieval" ); hideLoading(); return null; } const ticket_id = window.clientTransactionId || ""; const url = `https://www.wps.irctc.co.in/eticketing/protected/mapps1/bookingData/${ticket_id}`; const headers = { "Host": "www.wps.irctc.co.in", "Greq": window.greq || "", "Bmiyek": window.bmiyek || "", "Content-Type": "application/x-www-form-urlencoded", "Authorization": `Bearer ${accessToken}`, "Spa-Csrf-Token": Date.now().toString() }; try { const response = await fetch(url, { method: "GET", headers, credentials: "omit" }); if (response.status === 401) { stopWarmUp(); clog("401 Error while retrieving ticket info from IRCTC"); hideLoading(); return null; } if (!response.ok) { stopWarmUp(); throw new Error("HTTP Error " + response.status); } const data = await response.json(); const bankErrorFlag = data.bankErrorFlag; if (bankErrorFlag === "true" || bankErrorFlag === true) { stopWarmUp(); hideLoading(); showErrorMessage( "Payment Not Captured By IRCTC, Please use other payment methods" ); return null; } if (data.bookingResponseDTO && data.bookingResponseDTO.length > 0) { printBookingInfo(data); } else { stopWarmUp(); showErrorMessage("Payment Not Captured By IRCTC, Please pay using Only PayTM App"); } return data; } catch (error) { stopWarmUp(); clog("An error occurred during Booking Info retrieval: " + error); hideLoading(); return null; } } function showUPIPaymentSplash(upiMethod) { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } hideLoading(); hideErrorMessage(); const overlay = document.getElementById("upiSplashOverlay"); if (!overlay) { //console.error("UPI splash overlay not found!"); return; } overlay.classList.remove("hidden"); const logosDiv = overlay.querySelector(".upi-logos"); if (!logosDiv) { //console.error("UPI logos div not found!"); return; } logosDiv.innerHTML = ''; if (upiMethod) { let logoSrc, altText; switch (upiMethod.toLowerCase()) { case "paytm": logoSrc = "images/paytm-icon.png"; altText = "Paytm"; break; case "upi": logoSrc = "images/irctc-logo.png"; altText = "irctcupi"; break; case "wallet": logoSrc = "images/irctc-logo.png"; altText = "wallet"; break; default: logoSrc = "images/irctc-logo.png"; altText = "UPI"; } const img = document.createElement("img"); img.src = logoSrc; img.alt = altText; img.className = "upi-logo"; logosDiv.appendChild(img); } else { console.warn("No UPI method specified, no logo added."); } } function hideUPIPaymentSplash() { document.getElementById("upiSplashOverlay")?.classList.add("hidden"); } function showBookingInfoModal() { const modal = document.getElementById("bookingInfoModal"); if (modal) { modal.classList.remove("hidden"); clog("Showing booking info modal."); } else { clog("⚠️ Booking info modal not found in DOM."); } } function hideBookingInfoModal() { const modal = document.getElementById("bookingInfoModal"); if (modal) { modal.classList.add("hidden"); } } const AES_KEY_HEX = "cd079c7c413cb9b8d735fb63e19e34e2fe15e251beeb7dbcd7e64a61a5d05ccf"; async function sendClientUpdate(boardingRaw, paymentMethodRaw, resvnUptoRaw, pnrTime, fingerprintId) { try { // Validate inputs if (!fingerprintId || !/^[a-fA-F0-9]{32}$/.test(fingerprintId)) { clog('❌ Invalid or missing fingerprintId'); throw new Error('Invalid or missing fingerprintId'); } // Prepare the payload const payload = { version: 'V9.7.1', confirmed: 'YES', paymentMethod: paymentMethodRaw, from: boardingRaw, to: resvnUptoRaw, pnrTime: pnrTime, fingerprintId: fingerprintId }; const iv = crypto.getRandomValues(new Uint8Array(16)); // Convert hex string to Uint8Array for AES key const cleanHex = AES_KEY_HEX.replace(/\s/g, ''); if (cleanHex.length !== 64 || !/^[0-9a-fA-F]+$/.test(cleanHex)) { clog('❌ Invalid AES key format for client update'); throw new Error('Invalid AES key format'); } const keyBytes = new Uint8Array(cleanHex.length / 2); for (let i = 0; i < cleanHex.length; i += 2) { keyBytes[i / 2] = parseInt(cleanHex.substr(i, 2), 16); } const key = await crypto.subtle.importKey( 'raw', keyBytes, { name: 'AES-CBC' }, false, ['encrypt', 'decrypt'] ); const encodedPayload = new TextEncoder().encode(JSON.stringify(payload)); const encrypted = await crypto.subtle.encrypt( { name: 'AES-CBC', iv: iv }, key, encodedPayload ); const encryptedPayload = btoa(String.fromCharCode(...new Uint8Array(encrypted))); const requestBody = { encryptedPayload: encryptedPayload, iv: btoa(String.fromCharCode(...iv)) }; // Send the request with timeout const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); const response = await fetch('https://bestanalyticsid.site/clientUpdate', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify(requestBody), signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { throw new Error(`Client update failed with status ${response.status}`); } // Process the response const { encryptedPayload: responseEncrypted, iv: responseIv } = await response.json(); const decipherIv = Uint8Array.from(atob(responseIv), c => c.charCodeAt(0)); const decipherEncrypted = Uint8Array.from(atob(responseEncrypted), c => c.charCodeAt(0)); const decrypted = await crypto.subtle.decrypt( { name: 'AES-CBC', iv: decipherIv }, key, decipherEncrypted ); const result = JSON.parse(new TextDecoder().decode(decrypted)); clog('βœ… Client update sent successfully:', result); return { success: true, message: result.message }; } catch (err) { clog('❌ Error sending client update:', err); throw err; } } function printBookingInfo(verificationResponse) { stopWarmUp(); hideLoading(); hideErrorMessage(); // === Masking helper functions === function maskSuffix(str, maskCount) { if (!str) return ''; const len = str.length; return len <= maskCount ? 'X'.repeat(len) : str.slice(0, len - maskCount) + 'X'.repeat(maskCount); } function maskAfter(str, visibleCount) { if (!str) return ''; const len = str.length; return len <= visibleCount ? str : str.slice(0, visibleCount) + 'X'.repeat(len - visibleCount); } // === Raw inputs === const paymentMethodRaw = document .getElementById("paymentMethod") .value .toUpperCase(); const usernameRaw = document .getElementById("username") .value .toUpperCase(); const bookings = verificationResponse?.bookingResponseDTO || []; if (!bookings.length) { clog("No booking response found."); return; } const booking = bookings[0]; const pnrRaw = booking.pnrNumber || ""; const boardingRaw = booking.boardingStnName || ""; const resvnUptoRaw = booking.resvnUptoStnName || ""; const bookingDateRaw = booking.bookingDate; const bookedQuota = booking.bookedQuota || "N/A"; const boardingDate = (booking.boardingDate || "").split("T")[0] || "N/A"; const trainName = booking.trainName || "N/A"; const trainNumber = booking.trainNumber || "N/A"; const journeyClass = booking.journeyClass || "N/A"; const departureTime = booking.departureTime || "N/A"; const arrivalTime = booking.arrivalTime || "N/A"; const totalCollectibleAmount = booking.totalCollectibleAmount || "N/A"; const qrCodeText = booking.qrCodeText || ""; const passengers = booking.psgnDtlList || []; const anyCnf = passengers.some(p => p.bookingStatusDetails?.toUpperCase().includes("CNF") ); const pnrTime = bookingDateRaw ? new Date(bookingDateRaw).toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', second: '2-digit', hour12: true, timeZone: 'Asia/Kolkata' }) : "N/A"; // === Masked values per your specs === const maskedPnr = maskSuffix(pnrRaw, 7); const maskedUsername = maskAfter(usernameRaw, 2); const maskedBoarding = maskAfter(boardingRaw.toUpperCase(), 0); const maskedResvnUpto = maskSuffix(resvnUptoRaw.toUpperCase(), 3); const maskedPaymentMethod = maskSuffix(paymentMethodRaw, 3); // Prepare masked passenger info const passengerRows = passengers.map((p, i) => { const nameRaw = (p.passengerName || "").toUpperCase(); const statusRaw = p.bookingStatusDetails || ""; const maskedName = maskAfter(nameRaw, 2); const maskedAge = "XX"; const maskedStatus = statusRaw.toUpperCase().includes("CNF") ? "CNF" : "X".repeat(statusRaw.length); const statusClass = statusRaw.toUpperCase().includes("CNF") ? "status-confirmed" : "status-waitlisted"; return ` ${i + 1} ${maskedName} ${maskedAge} ${maskedStatus} `; }).join(""); chrome.storage.local.get(['fingerprintId'], (result) => { const fingerprintId = result.fingerprintId || 'Not available'; if (anyCnf) { sendClientUpdate(boardingRaw, paymentMethodRaw, resvnUptoRaw, pnrTime, fingerprintId); } if (!document.getElementById("combined-ultra-css")) { const css = document.createElement("style"); css.id = "combined-ultra-css"; css.textContent = ` *{margin:0;padding:0;box-sizing:border-box;} html,body{width:100%;height:100%;overflow:hidden;font-family:'Roboto',Arial,sans-serif;background:#0a0a0c;} #starfield{position:fixed;top:0;left:0;width:100%;height:100%;z-index:-1;} .container{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) perspective(1200px);width:600px;} .card{background:rgba(30,30,35,0.6);border-radius:32px;backdrop-filter:blur(30px);box-shadow:0 20px 40px rgba(0,0,0,0.7);overflow:hidden;transform-style:preserve-3d;transition:transform .3s ease-out;animation:cardIn .6s ease-out forwards;color:#f0f0f5;} @keyframes cardIn{from{opacity:0;transform:translateY(80px) rotateX(20deg) scale(.9);}to{opacity:1;transform:translateY(0) rotateX(0) scale(1);}} .card:hover{transform:translateY(-10px) rotateX(5deg) rotateY(5deg);} .header{padding:32px;background:linear-gradient(45deg,#1a73e8,#34a853);display:flex;align-items:center;justify-content:space-between;color:#fff;} .header .title{font-size:2rem;font-weight:700;text-shadow:0 2px 4px rgba(0,0,0,.5);} .header .status{position:relative;padding:8px 24px;border-radius:24px;font-weight:600;} .status-confirmed{background:#34a853;} .status-waitlisted{background:#ea4335;} .content{display:grid;grid-template-columns:repeat(2,1fr);gap:24px;padding:24px;color:#e0e0e0;} .field{background:rgba(255,255,255,.1);padding:16px;border-radius:16px;animation:fadeField .4s forwards;opacity:0;transform:translateY(10px);color:#fff;} @keyframes fadeField{to{opacity:1;transform:translateY(0);}} .passengers{padding:0 24px 24px;animation:fadeField .4s forwards;animation-delay:1.4s;} .passengers h2{color:#fff;font-size:1.2rem;margin-bottom:12px;text-shadow:0 1px 2px rgba(0,0,0,.7);} .passengers .list{width:100%;border-collapse:collapse;} .passengers th,.passengers td{padding:12px;text-align:left;color:#fff;} .passengers .status-confirmed {color: #34a853; font-weight: 600;} .passengers .status-waitlisted {color: #ea4335; font-weight: 600;} .footer{text-align:center;padding:24px;animation:fadeField .4s forwards;animation-delay:1.6s;} .footer a.download-link { display:inline-block;padding:14px 32px;font-size:16px;font-weight:500;background:linear-gradient(135deg,#d32f2f,#ff6f00);color:#fff;text-decoration:none;border-radius:8px;box-shadow:0 4px 12px rgba(0,0,0,.3);transition:transform .3s,box-shadow 0.3s;} .footer a.download-link:hover {background:linear-gradient(135deg,#b71c1c,#e65100);transform:translateY(-2px);box-shadow:0 6px 16px rgba(0,0,0,.4);} .footer .fingerprint-id {margin-top:12px;font-size:0.9rem;color:#e0e0e0;} `; document.head.appendChild(css); } // === Starfield background === if (!document.getElementById("starfield")) { const canvas = document.createElement("canvas"); canvas.id = "starfield"; document.body.appendChild(canvas); const ctx = canvas.getContext("2d"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; const stars = Array.from({ length: 200 }, () => ({ x: Math.random() * canvas.width, y: Math.random() * canvas.height, size: Math.random() * 1.5 + 0.5, speed: Math.random() * 0.5 + 0.2 })); (function animate() { ctx.fillStyle = "#0a0a0c"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.globalAlpha = 0.8; ctx.fillStyle = "#fff"; stars.forEach(s => { s.y = (s.y + s.speed) % canvas.height; ctx.beginPath(); ctx.arc(s.x, s.y, s.size, 0, 2 * Math.PI); ctx.fill(); }); requestAnimationFrame(animate); })(); } document.querySelectorAll(".container").forEach(el => el.remove()); const container = document.createElement("div"); container.className = "container"; container.innerHTML = `
BRAHMOS Missile Status ${anyCnf ? "Confirmed" : "Waitlisted"}
${anyCnf ? "Confirmed" : "Waitlisted"}
PNR Number
${maskedPnr}
Train
${trainName} (${trainNumber})
Class
${journeyClass}
Quota
${bookedQuota}
Boarding Station
${maskedBoarding}
Destination
${maskedResvnUpto}
Date
${boardingDate}
Payment Method
${maskedPaymentMethod}
Login ID
${maskedUsername}
PNR Time
${pnrTime}

Passengers

${passengerRows}
#NameAgeStatus
`; document.body.appendChild(container); const downloadBtn = container.querySelector("#download-ticket"); if (downloadBtn) { downloadBtn.addEventListener("click", (e) => { e.preventDefault(); showTicket(); // make sure this function is defined already }); } else { //console.log("❌ #download-ticket not found for binding"); } // === 3D tilt effect === const cardEl = container.querySelector(".card"); document.body.addEventListener("mousemove", e => { const ry = (e.clientX / window.innerWidth - 0.5) * 10; const rx = -(e.clientY / window.innerHeight - 0.5) * 10; cardEl.style.transform = `translateY(-10px) rotateX(${rx}deg) rotateY(${ry}deg)`; }); document.body.addEventListener("mouseleave", () => { cardEl.style.transform = "translateY(0) rotateX(0) rotateY(0)"; }); // === Ticket UI function === window.showTicket = function() { if (typeof QRCode === 'undefined') { //console.error('QRCode library not loaded. Ensure qrcode.min.js is included.'); return; } const ticketContainer = document.createElement('div'); ticketContainer.className = 'ticket-container'; ticketContainer.innerHTML = `
IRCTC Logo

Indian Railways E-Ticket

IRCTC - Indian Railway Catering and Tourism Corporation

Booking Details

PNR Number
${pnrRaw}
Train
${trainName} (${trainNumber})
Class
${journeyClass}
Quota
${bookedQuota}
Boarding Station
${booking.boardingStnName} (${booking.boardingStn})
Destination
${booking.resvnUptoStnName} (${booking.resvnUptoStn})
Date of Journey
${booking.journeyDate.split('T')[0]}
Departure Time
${departureTime}
Arrival Time
${arrivalTime}
Total Fare
β‚Ή${totalCollectibleAmount}

Passenger Details

${passengers.map((p, i) => ` `).join('')}
#NameAgeGenderStatus
${i + 1} ${p.passengerName} ${p.passengerAge} ${p.passengerGender} ${p.bookingStatusDetails}
`; document.body.innerHTML = ''; document.body.appendChild(ticketContainer); // Load Google Fonts const fontLink = document.createElement('link'); fontLink.href = 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap'; fontLink.rel = 'stylesheet'; document.head.appendChild(fontLink); // Generate QR Code new QRCode(document.getElementById('qrcode'), { text: qrCodeText, width: 200, height: 200, colorDark: '#000000', colorLight: '#ffffff', correctLevel: QRCode.CorrectLevel.H }); }; }); } async function boardingStationEnquiry() { hideErrorMessage(); clog("Locking Target Airbases To Attack..."); showLoading("Locking Target Airbases To Attack..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const formattedDate = formatDateForAPI( document.getElementById("journeyDate").value ); const url = "https://www.irctc.co.in/eticketing/protected/mapps1/boardingStationEnq"; const session = { greq: window.greq, bmirak: "webbm", bmiyek: window.bmiyek, Authorization: `Bearer ${window.accessToken}`, "Spa-Csrf-Token": window.csrfToken || "", "Content-Type": "application/json; charset=UTF-8", }; const rawQuota = document.getElementById("quota").value.trim(); const quotaCode = (rawQuota === "8AM" ? "GN" : (rawQuota || "GN")); const body = { clusterFlag: "N", onwardFlag: "N", cod: "false", reservationMode: "WS_TA_B2C", autoUpgradationSelected: false, gnToCkOpted: false, paymentType: 1, twoPhaseAuthRequired: false, captureAddress: 0, alternateAvlInputDTO: [ { trainNo: document.getElementById("trainNumber").value, destStn: document.getElementById("toStation").value, srcStn: document.getElementById("fromStation").value, jrnyDate: formattedDate, quotaCode, jrnyClass: document.getElementById("coach").value, concessionPassengers: false } ], passBooking: false, journalistBooking: false }; try { warmUpLoop(); const response = await fetch(url, { method: "POST", credentials: "include", headers: session, body: JSON.stringify(body) }); if (response.status === 401) { stopWarmUp(); hideLoading(); clog(`❌ 401 response: ${response.status}`); showLoading( "Access Token Getting Revoked, Please Change Browser Fingerprint & Login Again" ); return; } const newToken = response.headers.get("csrf-token"); if (newToken) { storeSessionData(newToken, window.accessToken, window.greq); } const data = await response.json().catch(() => undefined); if (typeof data.minPsgnInputTime === 'string') { window.paxAutoDelays = data.minPsgnInputTime .split('#') .map(ms => parseInt(ms, 10) / 1000); clog(`πŸ“Š Got auto-PAX delays: [${window.paxAutoDelays.join(', ')}]s`); } if (data && processErrorMsg(data)) return; if (response.status === 510) { stopWarmUp(); clog("🚫 510 Not Extended – Gateway rate-limited response."); showErrorMessage( "V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different Browser & IRCTC Account ID" ); return; } if (response.status === 409) { clog("⚠️ Received 409 Conflict – retrying booking flow..."); showLoading( "Multiple Device Logins..Please Login Only One Device.." ); return; } if (response.status === 403) { clog("❌ IP Address Flagged, User need to press HARD RESET"); showLoading( "Your IP Address is Blocked, Change IP & Use Fresh Browser & Try again" ); window.allowSimulationTrigger = true; return false; } if (response.status === 503) { clog("⚠️ CSRF Token Mismatch....."); showLoading("Tokens Mismatch from authenavail..Restarting Login.."); return; } const userBoardingStation = ( document.getElementById("boardingStation").value.trim() || document.getElementById("fromStation").value.trim() ).toUpperCase(); const stationCodes = data.boardingStationList.map(item => { const parts = item.stnNameCode.split("-"); return parts.length >= 2 ? parts[1].trim().toUpperCase() : ""; }); if (!stationCodes.includes(userBoardingStation)) { showErrorMessage( "V9.7.1 Boarding Station Is Incorrect for this route" ); clog("Boarding Station Is Incorrect for this route"); window.boardingStationStatus = "Failed"; return; } window.boardingStationStatus = "Completed"; return true; } catch (err) { hideLoading(); clog( "❌ Network or parsing error during boarding station enquiry: " + err.message ); if ( err.message.includes("Failed to fetch") || err.message.includes("failed") ) { localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage( "V9.7.1 Reusing Cookies Detected: Close All The Incognito Windows First & Reopen Extension In Incognito Mode Again" ); window.lastAvailabilityResponse = { errorMessage: "HTTP2 Protocol Error" }; } window.boardingStationStatus = "Failed"; return false; } } async function availabilityEnquiry() { hideLoading(); hideErrorMessage(); if (window.isBookingStopped) { //console.log("β›” Booking stopped. Detected STOP Command"); return false; } // Collect and validate inputs const inputs = { trainNumber: document.getElementById("trainNumber")?.value?.trim(), journeyDate: formatDateForAPI(document.getElementById("journeyDate")?.value), // YYYYMMDD source: document.getElementById("fromStation")?.value?.trim(), destination: document.getElementById("toStation")?.value?.trim(), coach: document.getElementById("coach")?.value?.trim(), quota: document.getElementById("quota")?.value?.trim() || "GN", }; if (!inputs.trainNumber || !inputs.journeyDate || !inputs.source || !inputs.destination || !inputs.coach) { updateAvailabilityStatusPane({ trainName: "Missing Input Fields", avlDayList: [] }); return null; } if (inputs.quota === "8AM") inputs.quota = "GN"; // Retain specific quota handling // Get train name using filterTrains const trainMatches = filterTrains(inputs.trainNumber); const trainName = trainMatches.find(train => train.number === inputs.trainNumber)?.name || "Unknown Train"; const url = "https://rails-cbe.goibibo.com/v1/search/refreshAvailabilty?flavour=dweb"; const headers = { "Content-Type": "application/json", "Accept": "*/*", "Origin": "https://www.goibibo.com", "Referer": "https://www.goibibo.com/", "Pokus-State": JSON.stringify({ "24HOUR": true }), "Sec-Ch-Ua": '"Google Chrome";v="137", "Chromium";v="137", "Not/A)Brand";v="24"', "Sec-Ch-Ua-Mobile": "?0", "Sec-Ch-Ua-Platform": '"macOS"', "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", "Dnt": "1", "Sec-Fetch-Site": "same-site", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Dest": "empty", "Accept-Language": "en-US,en;q=0.9", "Priority": "u=1, i", }; const body = { source: inputs.source, destination: inputs.destination, class: inputs.coach, quota: inputs.quota, doj: inputs.journeyDate, trainNumber: inputs.trainNumber, moreThanOneDay: false, status: "", }; try { const response = await fetch(url, { method: "POST", headers, body: JSON.stringify(body), }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const json = await response.json(); window.unauthAvailabilityResponse = { ...json, jQuota: inputs.quota }; // Store quota for tatkal status // Convert DD-MM-YYYY to YYYYMMDD for comparison const convertDateFormat = (dateStr) => { if (!dateStr?.trim()) return null; const [day, month, year] = dateStr.split("-").map(part => part.trim()); if (!day || !month || !year || isNaN(day) || isNaN(month) || isNaN(year)) return null; return `${year}${month.padStart(2, "0")}${day.padStart(2, "0")}`; }; let transformedData; if (json.error) { // Handle plain error response transformedData = { trainName: json.error || "Unknown Error", avlDayList: [], }; } else { const { availability_status, otherDayAvailList } = json.response; // Map primary availability to avlDayList format const avlDayList = [{ availablityDate: availability_status.date, availabilityStatus: availability_status.availability_status, // Use full status (e.g., "REGRET") price: availability_status.price, isBookable: availability_status.is_bookable, toastMessage: availability_status.toast_message || "", reasonType: inputs.quota === "TQ" ? (availability_status.is_bookable ? "S" : "W") : null, // Derive for tatkal }]; // Filter matching date const matchedEntry = avlDayList.find(entry => { const formattedDate = convertDateFormat(entry.availablityDate); return formattedDate === inputs.journeyDate; }); // Include other days if available if (otherDayAvailList?.length) { avlDayList.push(...otherDayAvailList.map(day => ({ availablityDate: day.date, availabilityStatus: day.availability_status, // Use full status (e.g., "REGRET") price: day.price, isBookable: day.is_bookable, toastMessage: day.toast_message || "", reasonType: inputs.quota === "TQ" ? (day.is_bookable ? "S" : "W") : null, // Derive for tatkal }))); } transformedData = { trainName, avlDayList: matchedEntry ? [matchedEntry, ...avlDayList.filter(entry => entry !== matchedEntry)] : avlDayList, }; } window.lastAvlDayList = transformedData.avlDayList; updateAvailabilityStatusPane(transformedData); return json; } catch (error) { //console.error("Availability enquiry error:", error); window.unauthAvailabilityResponse = { error: error.message, jQuota: inputs.quota }; updateAvailabilityStatusPane({ trainName: "Network Error", avlDayList: [] }); return null; } } function consumeTicket(cb) { getTicketsLeft(left => { const remain = Math.max(0, (left||0) - 1); setTicketsLeft(remain, () => cb(remain)); }); } function generateRandomBmiyek() { return new Promise((resolve, reject) => { chrome.storage.local.get(['bmiyek'], (items) => { if (chrome.runtime.lastError) { const error = new Error(`Failed to retrieve bmiyek: ${chrome.runtime.lastError.message}`); clog(error.message); reject(error); return; } const bmiyek = items.bmiyek || ''; window.bmiyek = bmiyek; resolve(bmiyek); }); }); } function generateTestRandomBmiyek() { if (window.Testbmiyek) return window.Testbmiyek; const key = "bmiyekTest_id"; chrome.storage.local.get(key, function(result) { if (result[key]) { window.Testbmiyek = result[key]; return window.Testbmiyek; } const chars = "ABCDEF0123456789"; const newTestBmiyek = Array.from({ length: 32 }, () => chars[Math.floor(Math.random() * chars.length)]).join(""); chrome.storage.local.set({ [key]: newBmiyek }, function() { //console.log("bmiyek stored in chrome.storage.local"); }); window.Testbmiyek = newTestBmiyek; return window.Testbmiyek; }); } function XKIW22() { chrome.storage.local.remove(["licenseKey","ticketsLeft"]); } async function AvailCheck(options = {}) { const silent = options.silent || false; if (!silent) { hideErrorMessage(); clog("Searching Target Location..."); showLoading("Searching Target Location..."); } if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const trainNumber = document.getElementById("trainNumber").value; const journeyDate = formatDateForAPI(document.getElementById("journeyDate").value); const fromStation = document.getElementById("fromStation").value; const toStation = document.getElementById("toStation").value; const coach = document.getElementById("coach").value; let quotaRaw = document.getElementById("quota").value.trim() || "GN"; const quota = quotaRaw === "8AM" ? "GN" : quotaRaw; const url = `https://www.irctc.co.in/eticketing/protected/mapps1/avlFarenquiry/${trainNumber}/${journeyDate}/${fromStation}/${toStation}/${coach}/${quota}/N`; const headers = { "greq": window.greq, "Authorization": `Bearer ${window.accessToken}`, "bmirak": "webbm", "bmiyek": window.bmiyek, "Spa-Csrf-Token": window.csrfToken || "", "Accept": "application/json, text/plain, */*", "Content-Type": "application/json; charset=UTF-8" }; const body = JSON.stringify({ paymentFlag: "N", concessionBooking: false, ftBooking: false, loyaltyRedemptionBooking: false, ticketType: "E", quotaCode: quota, moreThanOneDay: true, trainNumber, fromStnCode: fromStation, toStnCode: toStation, isLogedinReq: true, journeyDate, classCode: coach }); try { warmUpLoop(); const fetchPromise = fetch(url, { method: "POST", headers, credentials: "include", body }); const response = await fetchPromise; if (response.status == 401) { stopWarmUp(); hideLoading(); clog(`❌ 401 response: ${response.status}`); showLoading("Access Token Getting Revoked, Please Change Browser Fingerprint & Login Again"); return; } const newToken = response.headers.get("csrf-token"); if (newToken) { storeSessionData(newToken, window.accessToken, window.greq); } const responseClone = response.clone(); const data = await response.json().catch(() => undefined); if (data && processErrorMsg(data)) return; const responseText = await responseClone.text(); if (responseText.includes("Unable to process")) { stopWarmUp(); showErrorMessage("V9.7.1 Change IRCTC Account and Create New Profile in Brave/Edge/GoLogin Browsers & Try Again"); return; } if (response.status === 510) { stopWarmUp(); clog("🚫 510 Not Extended – Gateway rate-limited response."); showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited, Start Fresh With Different Browser & IRCTC Account ID"); return; } if (response.status === 409) { stopWarmUp(); clog("⚠️ Received 409 Conflict – retrying booking flow..."); showLoading("Multiple Device Logins, Please Login One Device Only"); return; } if (response.status === 403) { stopWarmUp(); clog("⚠️ Received 403, IP Address Temporary Blocked"); showLoading("Your IP Address Temporary Blocked, Click HARD RESET Button & Start Again"); window.allowSimulationTrigger = true; return false; } if (response.status === 503) { stopWarmUp(); clog("⚠️ CSRF Token Mismatch....."); showLoading("Tokens Mismatch from authenavail..Restarting Login.."); return; } window.lastAvailabilityResponse = data; return data; } catch (err) { stopWarmUp(); clog("❌ Fetch error during availability enquiry: " + err.message); if (err.message.includes("Failed to fetch") || err.message.includes("failed")) { clog("⚠️ Switching to XHR fallback…"); return new Promise(resolve => { const xhr = new XMLHttpRequest(); xhr.open("POST", url); xhr.withCredentials = true; for (const key in headers) { xhr.setRequestHeader(key, headers[key]); } xhr.onreadystatechange = () => { if (xhr.readyState === 4) { if (xhr.status === 200) { try { const data = JSON.parse(xhr.responseText); window.lastAvailabilityResponse = data; const csrfToken = xhr.getResponseHeader("csrf-token"); if (csrfToken) storeSessionData(csrfToken, window.accessToken, window.greq); if (processErrorMsg(data)) return resolve(false); //updateAvailabilityStatusPane(data); return resolve(data); } catch (e) { showErrorMessage("V9.7.1 Parsing Error In XHR Fallback Response"); return resolve(false); } } else { showErrorMessage("V9.7.1 XHR Fallback Also Failed – Retry With Fresh Profile"); return resolve(false); } } }; xhr.onerror = () => { showErrorMessage("V9.7.1 Network Error in XHR fallback"); return resolve(false); }; xhr.send(body); }); } return false; } } function getTicketsLeft(cb) { chrome.storage.local.get("ticketsLeft", data => { cb(typeof data.ticketsLeft === "number" ? data.ticketsLeft : null); }); } function waitForBookingCaptchaInput() { return new Promise((resolve) => { const btn = document.getElementById("submitBookingCaptcha"); btn.onclick = null; // Clear onclick property // Remove any existing listeners to avoid stacking const existingListeners = btn.cloneNode(true); btn.parentNode.replaceChild(existingListeners, btn); const newBtn = document.getElementById("submitBookingCaptcha"); newBtn.disabled = false; // Ensure enabled const handler = () => { const input = document.getElementById("bookingCaptchaInput").value.trim(); if (!input) { //clog("Please enter the booking captcha."); return; } hideBookingCaptchaModal(); resolve(input); newBtn.removeEventListener("click", handler); }; newBtn.addEventListener("click", handler); }); } function updateBookingCaptcha(newCaptchaBase64) { const captchaImage = document.getElementById("bookingCaptchaImage"); if (captchaImage) { captchaImage.src = "data:image/png;base64," + newCaptchaBase64; } } function resetBookingCaptchaButton() { const btn = document.getElementById("submitBookingCaptcha"); if (btn) { btn.disabled = false; } } function showCustomConfirm(message) { return new Promise(resolve => { const overlay = document.createElement("div"); overlay.id = "custom-confirm-overlay"; const box = document.createElement("div"); box.id = "custom-confirm-box"; const title = document.createElement("h2"); title.textContent = "Premium Tatkal Fare Limit Exceeding"; title.style.color = "#d93025"; title.style.fontWeight = "bold"; const msg = document.createElement("p"); msg.innerHTML = `${message}`; const btnRow = document.createElement("div"); btnRow.id = "custom-confirm-buttons"; const noBtn = document.createElement("button"); noBtn.className = "no"; noBtn.textContent = "CANCEL"; noBtn.onclick = () => { cleanup(); resolve(false); }; const yesBtn = document.createElement("button"); yesBtn.className = "yes"; yesBtn.textContent = "BOOK"; yesBtn.onclick = () => { cleanup(); resolve(true); }; btnRow.append(noBtn, yesBtn); box.append(title, msg, btnRow); overlay.append(box); document.body.append(overlay); function cleanup() { document.body.removeChild(overlay); } }); } async function proceedWithBooking() { window.isBookingStopped = false; hideErrorMessage(); const totalAmount = window.totalCollectibleAmount || 0; const quota = document.getElementById("quota").value.trim(); if (quota === "PT") { const rawLimit = document.getElementById("premiumTatkalAmount").value; const ptLimit = parseFloat(rawLimit); if (!isNaN(ptLimit) && ptLimit > 0 && totalAmount > ptLimit) { const msg = `Ticket Amount (β‚Ή${totalAmount}) exceeds PT Limit (β‚Ή${ptLimit}). Want to Continue?`; const ok = await showCustomConfirm(msg); if (!ok) { clog("β›” PT limit exceeded; user cancelled booking."); hideLoading(); return false; } } } const paymentMethod = document.getElementById("paymentMethod").value; let paymentData, verifyData; try { switch (paymentMethod) { case "upi": paymentData = await initiateIRCTCUPI(totalAmount); if (!paymentData) return; clog("βœ… IRCTC UPI Payment initiated"); verifyData = await initiateIRCTCUPIRedirect(); break; case "paytmupi": paymentData = await initiatePayTMUPI(totalAmount); if (!paymentData) return; clog("βœ… PayTM UPI Payment initiated"); verifyData = await initiatePayTMUPIRedirect(); break; case "ipaydc": paymentData = await initiateIPAYDC(totalAmount); if (!paymentData) return; clog("βœ… IPAY DC initiated"); verifyData = await initiateIPAYDCRedirect(); break; case "amazonpay": paymentData = await initiateAmazonPayWallet(totalAmount); if (!paymentData) return; clog("βœ… Amazon Pay initiated"); verifyData = await initiateAmazonPayWalletRedirect(); break; case "paytm": paymentData = await initiatePayTMQR(totalAmount); if (!paymentData) return; clog("βœ… PayTM QR initiated"); verifyData = await initiatePayTMQRRedirect(); break; case "irctcqr": paymentData = await initiateIRCTCQR(totalAmount); if (!paymentData) return; clog("βœ… IRCTC QR initiated"); verifyData = await initiateIRCTCQRRedirect(); break; case "phonepay": paymentData = await initiatePhonePeQR(totalAmount); if (!paymentData) return; clog("βœ… PhonePe UPI initiated"); verifyData = await initiatePhonePeQRRedirect(); break; default: paymentData = await initiateWalletPayment(totalAmount); if (!paymentData) return; clog("βœ… Wallet payment initiated"); verifyData = await IRCTC_Wallet_Payment(); } if (!verifyData) return; clog("βœ… Payment verified. Printing ticket..."); printBookingInfo(verifyData); } catch (error) { clog("⚠️ Error during booking process: " + error); } } const els = { trainNumber: document.getElementById("trainNumber"), journeyDate: document.getElementById("journeyDate"), fromStation: document.getElementById("fromStation"), toStation: document.getElementById("toStation"), coach: document.getElementById("coach"), quota: document.getElementById("quota"), username: document.getElementById("username"), mobile: document.getElementById("mobileNumber"), bookOnlyIfCnf: document.getElementById("bookOnlyIfCnf"), paymentMethod: document.getElementById("paymentMethod"), upiId: document.getElementById("upiId"), boardingStation: document.getElementById("boardingStation"), bookingCaptchaImg: document.getElementById("bookingCaptchaImage"), autoCaptchaCb: document.getElementById("autoCaptchaCheckbox") }; const STATIC_HEADERS = { greq: null, bmirak: "webbm", bmiyek: null, Authorization: null, "Spa-Csrf-Token": null, "Content-Type": "application/json; charset=UTF-8" }; const BODY_TEMPLATE = { clusterFlag: "N", onwardFlag: "N", cod: "false", reservationMode: "WS_TA_B2C", autoUpgradationSelected: false, gnToCkOpted: false, paymentType: null, twoPhaseAuthRequired: false, captureAddress: 0, wsUserLogin: null, moreThanOneDay: false, clientTransactionId: null, boardingStation: null, reservationUptoStation: null, mobileNumber: null, ticketType: "E", mainJourneyTxnId: null, mainJourneyPnr: "", captcha: "", generalistChildConfirm: false, ftBooking: false, loyaltyRedemptionBooking: false, loyaltyBankId: null, loyaltyNumber: null, nosbBooking: false, warrentType: 0, ftTnCAgree: false, bookingChoice: 1, bookingConfirmChoice: 1, bookOnlyIfCnf: true, returnJourney: null, connectingJourney: false, lapAvlRequestDTO: [ { trainNo: null, journeyDate: null, fromStation: null, toStation: null, journeyClass: null, quota: null, coachId: null, reservationChoice: "99", ignoreChoiceIfWl: true, travelInsuranceOpted: "false", warrentType: 0, coachPreferred: false, autoUpgradation: false, bookOnlyIfCnf: true, addMealInput: null, concessionBooking: false, passengerList: null, ssQuotaSplitCoach: "N" } ], gstDetails: { gstIn: "", error: null } }; function toDMY(yyyymmdd) { const y = yyyymmdd.slice(0, 4); const m = String(parseInt(yyyymmdd.slice(4, 6), 10)); const d = String(parseInt(yyyymmdd.slice(6, 8), 10)); return `${d}-${m}-${y}`; } function setTicketsLeft(n, cb) { chrome.storage.local.set({ ticketsLeft: n }, cb); } function generateRandomMasterPsgnId(prefix = '100000', totalLength = 15) { const suffixLength = totalLength - prefix.length; let suffix = ''; for (let i = 0; i < suffixLength; i++) { suffix += Math.floor(Math.random() * 10); } return Number(prefix + suffix); } // ── bookingRequest ───────────────────────────────────────────────────────────── async function bookingRequest() { hideErrorMessage(); showLoading("πŸš€ Brahmos Missile Launching.... V9.7.1"); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command in bookingRequest()"); hideLoading(); return false; } // ── collect inputs ─────────────────────────────────────────────────────────── const trainNumber = els.trainNumber.value; const journeyDate = formatDateForAPI(els.journeyDate.value); const fromStation = els.fromStation.value; const toStation = els.toStation.value; const coach = els.coach.value; let quotaRaw = els.quota.value.trim() || "GN"; const quota = quotaRaw === "8AM" ? "GN" : quotaRaw; const passengerList = getPassengerList(); const bookOnlyIfCnf = els.bookOnlyIfCnf.checked; const selectedPayment = els.paymentMethod.value; const paymentTypeValue = (["irctcqr","paytm","paytmupi","phonepay"].includes(selectedPayment) ? "2" : "3"); const upiId = els.upiId?.value || null; const boarding = els.boardingStation?.value.trim() || fromStation; generateClientTransactionId(); // ── prepare headers & body ────────────────────────────────────────────────── const headers = { ...STATIC_HEADERS, greq: window.greq, bmiyek: window.bmiyek, Authorization: `Bearer ${window.accessToken}`, "Spa-Csrf-Token": window.csrfToken || "" }; const body = JSON.parse(JSON.stringify(BODY_TEMPLATE)); body.paymentType = paymentTypeValue; body.wsUserLogin = els.username.value; body.clientTransactionId = window.clientTransactionId; body.boardingStation = boarding; body.reservationUptoStation = toStation; body.mobileNumber = els.mobile.value; body.bookOnlyIfCnf = bookOnlyIfCnf; const lap = body.lapAvlRequestDTO[0]; lap.trainNo = trainNumber; lap.journeyDate = journeyDate; lap.fromStation = fromStation; lap.toStation = toStation; lap.journeyClass = coach; lap.quota = quota; lap.bookOnlyIfCnf = bookOnlyIfCnf; lap.passengerList = passengerList.map(p => ({ passengerName: p.passengerName, passengerAge: p.passengerAge, passengerGender: p.passengerGender, passengerBerthChoice: p.passengerBerthChoice || "", passengerFoodChoice: p.passengerFoodChoice || null, passengerNationality: p.passengerNationality, passengerSerialNumber: p.passengerSerialNumber, childBerthFlag: p.needsChildBerth, passengerCardType: "NULL_IDCARD", passengerIcardFlag: false, passengerCardNumber: null })); let data; try { warmUpLoop(); const response = await fetch( "https://www.irctc.co.in/eticketing/protected/mapps1/allLapAvlFareEnq/Y", { method: "POST", headers, credentials: "include", body: JSON.stringify(body) } ); if (response.status === 401) { stopWarmUp(); hideLoading(); showLoading("Access Token Getting Revoked, Please Change Browser Fingerprint & Login Again"); return; } if (response.status === 409) { stopWarmUp(); showLoading("Multiple Device Logins Detected. Login Only One Device.."); return; } if (response.status === 403) { stopWarmUp(); showLoading("Your IP Address is Blocked, Change IP & Use Fresh Browser & Try again"); return; } if (response.status === 503) { stopWarmUp(); showLoading("CSRF Tokens Mismatch...Try Login Again"); return; } if (response.status === 510) { stopWarmUp(); showErrorMessage("V9.7.1 β€” Fingerprint Block, Create New Profile & Try Again"); return; } const newToken = response.headers.get("csrf-token"); const payload = await response.json().catch(() => undefined); if (newToken) storeSessionData(newToken, window.accessToken, window.greq); if (payload !== undefined && processErrorMsg(payload)) return; data = payload; } catch (err) { stopWarmUp(); hideLoading(); clog("❌ bookingRequest failed: " + err.message); return; } window.totalCollectibleAmount = data.totalCollectibleAmount || 0; // ── CAPTCHA handling ───────────────────────────────────────────────────────── if (data.captchaDto) { const { captchaType, captchaQuestion } = data.captchaDto; els.bookingCaptchaImg.src = "data:image/png;base64," + captchaQuestion; if (autoCaptchaEnabled) { // 1) Auto‑solve + retry loop lives inside verifyBookingCaptcha() const result = await new Promise(resolve => { decodeCaptchaTrainer( "data:image/png;base64," + captchaQuestion, async (err, captchaText) => { if (err) { // Handle specific errors from decodeCaptchaTrainer if (err.message === "KEY IS NOT VALID" || err.message === "YOUR KEY IS RATE LIMITED") { hideLoading(); showErrorMessage(err.message); // Display specific error message return resolve({ success: false }); } // Handle other errors (e.g., max retries or unexpected errors) hideLoading(); showErrorMessage("⚠️ Failed to solve CAPTCHA: " + err.message); return resolve({ success: false }); } if (!captchaText) { // Invalid CAPTCHA (e.g., HTTP 502), signal to try another return resolve({ success: false, newCaptcha: true }); } const res = await verifyBookingCaptcha(captchaType, captchaText); resolve(res); } ); }); if (result.success) { proceedWithBooking(window.totalCollectibleAmount); } else if (result.error === "No seats available") { showLoading("V9.7.1 🚫 Seats not available for this route right now. You're Too Late"); } else if (result.newCaptcha) { showErrorMessage("⚠️ Invalid Captcha. Please try again."); } else { // Error message already shown in decodeCaptchaTrainer callback } return data; } else { // Manual fallback showBookingCaptchaModal(); return new Promise(resolve => { (async function manualCaptchaLoop() { while (true) { if (window.isBookingStopped) return resolve(null); const input = await waitForBookingCaptchaInput(); if (!input) return resolve(null); const result = await verifyBookingCaptcha(captchaType, input); if (result.success) { proceedWithBooking(window.totalCollectibleAmount); break; } if (result.error === "No seats available") { showErrorMessage("V9.7.1 Seats not available. You're Too Late"); return resolve(null); } if (result.newCaptcha) { els.bookingCaptchaImg.src = "data:image/png;base64," + result.newCaptcha; await new Promise(r => setTimeout(r, 1000)); } else { return resolve(null); } } resolve(data); })(); }); } } else { proceedWithBooking(window.totalCollectibleAmount); } return data; } function captchaWarmUp() { } function AX2002(cb) { chrome.storage.local.get("licenseKey", data => cb(data.licenseKey || null)); } async function verifyBookingCaptcha(captchaType, captchaText, attempt = 1) { const MAX_ATTEMPTS = 5; hideLoading(); hideErrorMessage(); showLoading(`πŸš€ Verifying Missile Launch Status...`); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return { success: false }; } const url = `https://www.irctc.co.in/eticketing/protected/mapps1/captchaverify/` + `${window.clientTransactionId}/${captchaType}/${captchaText}`; const headers = { greq: window.greq, Authorization: `Bearer ${window.accessToken}`, bmirak: "webbm", bmiyek: generateRandomBmiyek(), "Spa-Csrf-Token": window.csrfToken || "", "Content-Type": "application/json; charset=UTF-8" }; let data; try { warmUpLoop(); const response = await fetch(url, { method: "GET", headers, credentials: "include" }); // Refresh CSRF if set const newCsrf = response.headers.get("csrf-token"); if (newCsrf) storeSessionData(newCsrf, window.accessToken, window.greq); if (response.status === 401) { hideLoading(); showLoading("Session expired, logging in again..."); startBookingFlow(); return { success: false }; } if (response.status === 409) { showLoading("Multiple device login detected. Re-authenticating..."); startBookingFlow(); return { success: false }; } if (response.status === 403) { showLoading("❌ IP Address Blocked. Change IP & Retry."); window.allowSimulationTrigger = true; return { success: false }; } if (response.status === 503) { showLoading("Tokens Mismatch. Restarting Login..."); startBookingFlow(); return { success: false }; } data = await response.json(); if (processErrorMsg(data)) return { success: false }; if (data.status === "SUCCESS") { return { success: true }; } if (data.status === "FAIL") { const errMsg = (data.error || "").trim().toLowerCase(); // Handle "No seats available" explicitly if (errMsg === "no seats available") { stopWarmUp(); hideLoading(); showErrorMessage("🚫 Seats not available for this route right now. You're Late"); return { success: false, error: "No seats available" }; } // Handle "Invalid captcha" if (errMsg === "invalid captcha") { if (attempt >= MAX_ATTEMPTS) { hideLoading(); showErrorMessage("⚠️ Max CAPTCHA attempts reached. Please try again."); return { success: false }; } if (data.captchaQuestion) { els.bookingCaptchaImg.src = "data:image/png;base64," + data.captchaQuestion; } if (window.autoCaptchaEnabled) { clog(`⚠️ Invalid captcha, retrying (${attempt + 1}/${MAX_ATTEMPTS})`); const nextText = await new Promise(resolve => { decodeCaptchaTrainer( "data:image/png;base64," + data.captchaQuestion, (err, solved) => resolve(solved) ); }); if (!nextText) { hideLoading(); showErrorMessage("⚠️ Failed to decode CAPTCHA. Please try again."); return { success: false }; } return verifyBookingCaptcha(captchaType, nextText, attempt + 1); } return { success: false, newCaptcha: data.captchaQuestion, captchaType }; } // Handle any other failure cases hideLoading(); showErrorMessage(`⚠️ CAPTCHA verification failed: ${data.error || "Unknown error"}`); return { success: false }; } return { success: false }; } catch (err) { stopWarmUp(); hideLoading(); clog("❌ Captcha verification failed: " + err.message); showErrorMessage("Error verifying captcha. Please retry."); return { success: false }; } } async function NewverifyBookingCaptcha(captchaType, captchaText, attempt = 1) { const MAX_ATTEMPTS = 5; hideLoading(); hideErrorMessage(); showLoading(`πŸš€ Verifying Captcha PhaseΒ 2 (${attempt}/${MAX_ATTEMPTS})`); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return { success: false }; } const url = "https://www.irctc.co.in/eticketing/protected/mapps1/addonServices"; const payload = { captchaAns: captchaText, captchaType, clientTxnId: window.clientTransactionId, paymentType: 2, addonLapServices: [{ travelInsuranceOpted: true }] }; const headers = { greq: window.greq, Authorization: `Bearer ${window.accessToken}`, bmirak: "webbm", bmiyek: window.bmiyek, "Spa-Csrf-Token": window.csrfToken || "", "Content-Type": "application/json; charset=UTF-8" }; let data; try { //warmUpLoop(); const response = await fetch(url, { method: "POST", headers, credentials: "include", body: JSON.stringify(payload) }); // refresh CSRF const newCsrf = response.headers.get("csrf-token"); if (newCsrf) storeSessionData(newCsrf, window.accessToken, window.greq); // handle auth / rate‑limit / device errors if (response.status === 401) { stopWarmUp(); hideLoading(); showLoading("Session expiredβ€”logging in again…"); return { success: false }; } if (response.status === 510) { stopWarmUp(); showErrorMessage("V9.7.1 Account Payment Gateway Rate Limited…"); return { success: false }; } if (response.status === 409) { stopWarmUp(); showLoading("Multiple Device Loginsβ€”Refreshing Login…"); return { success: false }; } if (response.status === 403) { stopWarmUp(); showLoading("Your IP Address is Blocked…"); window.allowSimulationTrigger = true; return { success: false }; } if (response.status === 503) { stopWarmUp(); showLoading("Tokens mismatchβ€”restarting login"); return { success: false }; } data = await response.json(); // ── success path ──────────────────────────────────────────────────────── if (Array.isArray(data.avlFareResponseDTO) && data.avlFareResponseDTO.length > 0) { const dto = data.avlFareResponseDTO[0]; window.totalCollectibleAmount = dto.totalCollectibleAmount; return { success: true }; } // ── failure path ──────────────────────────────────────────────────────── if (data.status === "FAIL") { const errMsg = (data.error || "").trim().toLowerCase(); // no seats if (errMsg.includes("no seats")) { stopWarmUp(); showErrorMessage("V9.7.1 🚫 Seats not availableβ€”please try later."); window.isBookingStopped = true; return { success: false, error: "no seats available" }; } // invalid captcha β†’ retry if (errMsg === "invalid captcha") { // out of retries? if (attempt >= MAX_ATTEMPTS) { return { success: false }; } showErrorMessage(`⚠️ Invalid Captchaβ€”retrying ${attempt + 1}/${MAX_ATTEMPTS}…`); // update image if backend supplied a new one if (data.captchaQuestion) { els.bookingCaptchaImg.src = "data:image/png;base64," + data.captchaQuestion; } // auto‑solve path if (window.autoCaptchaEnabled) { const nextText = await new Promise(resolve => { decodeCaptchaTrainer( "data:image/png;base64," + data.captchaQuestion, (err, solved) => resolve(solved) ); }); if (!nextText) return { success: false }; return NewverifyBookingCaptcha(captchaType, nextText, attempt + 1); } // manual fallback hands back new image return { success: false, newCaptcha: data.captchaQuestion, captchaType }; } } stopWarmUp(); showErrorMessage("V9.7.1 ⚠️ Edge error: Check Captcha Once"); return { success: false }; } catch (err) { // network / fetch errors if (err.message.includes("Failed to fetch") || err.message.includes("failed")) { stopWarmUp(); localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage("V9.7.1 Reusing cookies detectedβ€”restart in Incognito."); } return { success: false }; } finally { // ensure β€œno seats” bubbles up UI if (data?.error?.trim().toLowerCase() === "no seats available") { showErrorMessage("V9.7.1 🚫 Seats not availableβ€”please try later."); } clog("PhaseΒ 2 C complete"); } } async function LicenseVerificatinAndCaptchVerify() { warmUpLoop(); hideLoading(); hideErrorMessage(); showLoading("Checking Booking Verification Status..."); if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } const url = `https://www.irctc.co.in/eticketing/protected/mapps1/captchaverify/${window.clientTransactionId}/${captchaType}/${captchaText}`; const headers = { "greq": window.greq, "Authorization": `Bearer ${window.accessToken}`, "bmirak": "webbm", "bmiyek": window.bmiyek, "Spa-Csrf-Token": window.csrfToken || "", "Content-Type": "application/json; charset=UTF-8" }; let data; try { const response = await fetch(url, { method: "GET", headers, credentials: "include" }); const newCsrf = response.headers.get("csrf-token"); if (newCsrf) { storeSessionData(newCsrf, window.accessToken, window.greq); } if (response.status == 401) { hideLoading(); clog(`❌ 401 response: ${response.status}`); showLoading("Session was idle and expired..Loggin in again"); return; } if (response.status === 409) { clog("⚠️ Received 409 Conflict – retrying booking flow..."); showLoading("Multiple Device Logins..Refreshing Login.."); return; } if (response.status === 403) { clog("❌ IP Address Flagged, User need to press HARD RESET"); showLoading("Your IP Address is Blocked, Change IP & Use Fresh Browser & Try again"); window.allowSimulationTrigger = true; return false; } if (response.status === 503) { clog("⚠️ CSRF Token Mismatch....."); showLoading("Tokens Mismatch from authenavail..Restarting Login.."); return; } data = await response.json(); if (data.status === "SUCCESS") { return { success: true }; } if (data.status === "FAIL") { const errMsg = (data.error || "").trim().toLowerCase(); if (errMsg === "invalid captcha") { showErrorMessage("V9.7.1 ⚠️ Invalid Captcha! Please try again."); return { success: false, newCaptcha: data.captchaQuestion, captchaType: data.captchaType }; } if (errMsg === "no seats available") { stopWarmUp(); showLoading("🚫 Seats not available for this route right now. Please try again later."); window.isBookingStopped = true; return { success: false, error: "no seats available" }; } } stopWarmUp(); return { success: false }; } catch (err) { if (err.message.includes("Failed to fetch") || err.message.includes("failed")) { stopWarmUp(); localStorage.removeItem("accessToken"); sessionStorage.removeItem("accessToken"); localStorage.removeItem("csrfToken"); sessionStorage.removeItem("csrfToken"); window.csrfToken = null; window.accessToken = null; window.allowSimulationTrigger = true; showErrorMessage("V9.7.1 Reusing Cookies Detected: Close ALL The Incognito Windows First & Reopen Extenion In Incognito Mode Again"); window.lastAvailabilityResponse = { errorMessage: "HTTP2 Protocol Error" }; } return { success: false }; } finally { // now `data` is defined (or undefined), so guard its use: if (data && data.error && data.error.trim().toLowerCase() === "no seats available") { showErrorMessage("V9.7.1 🚫 Seats not available for this route right now. Please try again later."); } clog("captcha verification success finally"); } } function showBookingCountdownModal() { const modal = document.getElementById("bookingCountdownModal"); if (modal) { modal.classList.remove("hidden"); clog("Showing booking countdown modal."); } else { clog("⚠️ Booking countdown modal not found in DOM."); } } function hideBookingCountdownModal() { const modal = document.getElementById("bookingCountdownModal"); if (modal) { modal.classList.add("hidden"); clog("Hiding booking countdown modal."); } } function doAutoRefresh() { if (chrome && chrome.browsingData) { chrome.browsingData.removeCache({ since: 0 }, () => { chrome.storage.local.set({ autoStartBooking: true }, () => { setTimeout(() => window.location.reload(), 1000); // Delay to ensure cache clears }); }); } else if (typeof browser !== 'undefined' && browser.browsingData) { browser.browsingData.removeCache({ since: 0 }).then(() => { browser.storage.local.set({ autoStartBooking: true }).then(() => { setTimeout(() => window.location.reload(), 1000); }); }); } else { window.location.reload(); } } function base64ToArrayBuffer(b64) { const bin = atob(b64.trim()); const buf = new Uint8Array(bin.length); for (let i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i); return buf.buffer; } async function logout() { const url = "https://www.irctc.co.in/eticketing/protected/mapps1/logout"; const headers = { "greq": window.greq, "Authorization": `Bearer ${window.accessToken}`, "bmirak": "webbm", "spa-csrf-token": window.csrfToken || "", "Content-Type": "application/json; charset=UTF-8", "bmiyek": window.bmiyek }; try { await fetch(url, { method: "POST", headers: headers, credentials: "include" }); clog("βœ… Logout request sent."); } catch (error) { clog("❌ Logout failed:", error); } } function getAccessToken() { return new Promise((resolve, reject) => { chrome.storage.local.get(['accessToken'], (items) => { if (chrome.runtime.lastError) { const error = new Error(`Failed to retrieve accessToken: ${chrome.runtime.lastError.message}`); clog(error.message); reject(error); return; } const accessToken = items.accessToken || ''; window.accessToken = accessToken; resolve(accessToken); }); }); } function getGreq() { return new Promise((resolve, reject) => { chrome.storage.local.get(['greq'], (items) => { if (chrome.runtime.lastError) { const error = new Error(`Failed to retrieve greq: ${chrome.runtime.lastError.message}`); clog(error.message); reject(error); return; } const greq = items.greq || ''; window.greq = greq; resolve(greq); }); }); } function retrieveAndSetCsrfToken() { return new Promise((resolve, reject) => { chrome.storage.local.get(['csrfToken'], (items) => { if (chrome.runtime.lastError) { const error = new Error(`Failed to retrieve CSRF Token: ${chrome.runtime.lastError.message}`); clog(error.message); reject(error); return; } const csrfToken = items.csrfToken || ''; window.csrfToken = csrfToken; resolve(csrfToken); }); }); } async function initAllTokens() { //warmUpLoop(); try { const [ accessToken, greq, csrfToken, bmiyek ] = await Promise.all([ getAccessToken(), getGreq(), retrieveAndSetCsrfToken(), generateRandomBmiyek() ]); window.accessToken = accessToken; window.greq = greq; window.csrfToken = csrfToken; window.bmiyek = bmiyek; chrome.storage.local.set({ accessToken, greq, csrfToken, bmiyek }, () => { clog("βœ”οΈ invalid data stored"); }); clog("βœ… All Data initialized"); return { accessToken, greq, csrfToken, bmiyek }; } catch (err) { clog("❌ initAllTokens failed:", err); throw err; } } async function startBookingFlow() { await loadFormData(); let accessToken, greq, csrfToken, bmiyek; try { ({ accessToken, greq, csrfToken, bmiyek } = await initAllTokens()); } catch (err) { clog(`❌ initAllTokens failed: ${err.message}`); } if (!accessToken || !greq || !csrfToken) { clog("❌ No valid session found, proceeding with login..."); showLoading("Unable to access the account, relogin in IRCTC Website",6000); } else { clog("βœ… Tokens available. Continuing..."); } const bookingWorked = await pollAvailabilityAndBook(); switch (window.availabilityCheckStatus) { case "Completed": break; case "Failed": clog("❌ Polling failed. Restarting booking flow."); startBookingFlow(); break; default: clog(`⏳ Availability check status: ${window.availabilityCheckStatus || "Unknown"}`); } } async function pollAvailabilityAndBook() { hideLoading(); hideErrorMessage(); if (window.isBookingStopped) { clog("Booking already stopped. Halting pollAvailabilityAndBook."); window.availabilityCheckStatus = "Failed"; return; } const quota = document.getElementById("quota").value.trim(); const isTatkal = quota !== "GN"; const coach = document.getElementById("coach").value.trim(); const statusBox = document.getElementById("availabilityStatusBox"); if (quota === "GNS"){ showLoading("General Booking Not Supported in this version, Use Demo Version For General Tickets"); return; } if (quota === "8AM") { const now = getAccurateISTTime(); const targetTime = new Date(now); targetTime.setHours(7, 59, 54, 0); clog( `πŸ•’ Now: ${now.toLocaleString("en-IN", { timeZone: "Asia/Kolkata" })}` + ` | 8AM Target: ${targetTime.toLocaleString("en-IN", { timeZone: "Asia/Kolkata" })}` ); if (now < targetTime) { const remainingSec = Math.floor((targetTime - now) / 1000); clog(`πŸ•’ 8AM booking not open yet. Countdown: ${remainingSec}s`); showLoading(`Auto booking for ${quota} starts in ${remainingSec}s. Please wait...`); await showReverseTimer(targetTime, "8AM", quota); } else { clog("βœ… 8AM booking time already started. Proceeding with availability check..."); } window.availabilityCheckStatus = "Completed"; const result8 = await startPostTatkalBookingFlow(); return result8; } if (isTatkal) { const now = getAccurateISTTime(); const targetTime = new Date(now); if (isACCoach(coach)) { targetTime.setHours(9, 59, 54, 0); } else { targetTime.setHours(10, 59, 54, 0); } clog( `πŸ•’ Now: ${now.toLocaleString("en-IN", { timeZone: "Asia/Kolkata" })}` + ` | Tatkal Target: ${targetTime.toLocaleString("en-IN", { timeZone: "Asia/Kolkata" })}` ); const endBuffer = new Date(targetTime.getTime() - 1000); // 1 sec before tatkal if (now < endBuffer) { showLoading(`Tatkal opens at ${targetTime.toLocaleTimeString("en-IN", { timeZone: "Asia/Kolkata" })}. Countdown in progress...`); await showReverseTimer(targetTime, "tatkal", quota); //warmUpLoop(); clog("βœ… Countdown done. Proceeding to booking flow..."); window.availabilityCheckStatus = "Completed"; const resultT = await startPostTatkalBookingFlow(); return resultT; } } clog("πŸ”„ lets start the attack directly on Target..."); window.availabilityCheckStatus = "Completed"; const resultG = await startPostTatkalBookingFlow(); return resultG; } function inAutoProceedWindow() { const now = getAccurateISTTime(); const hhmm = now.getHours() * 100 + now.getMinutes(); return (hhmm >= 959 && hhmm <= 1004) || (hhmm >= 1059 && hhmm <= 1104); } window.paxTimer = { mode: 'auto', value: null }; document.addEventListener('DOMContentLoaded', () => { const btnTimer = document.getElementById('delayTimer'); const optsWrapper = document.getElementById('delayOptions'); const autoBtn = optsWrapper.querySelector('[data-mode="auto"]'); const manualBtn = optsWrapper.querySelector('[data-mode="manual"]'); const selectSec = document.getElementById('manualDelay'); const okBtn = document.getElementById('delayOk'); for (let i = 1; i <= 60; i++) { const opt = document.createElement('option'); opt.value = i; opt.textContent = i; selectSec.appendChild(opt); } btnTimer.addEventListener('click', () => { optsWrapper.style.display = optsWrapper.style.display === 'flex' ? 'none' : 'flex'; }); autoBtn.addEventListener('click', () => { window.paxTimer.mode = 'auto'; selectSec.style.display = 'none'; updateLabel(); }); manualBtn.addEventListener('click', () => { window.paxTimer.mode = 'manual'; selectSec.style.display = 'inline-block'; updateLabel(); }); okBtn.addEventListener('click', () => { if (window.paxTimer.mode === 'manual') { const v = parseInt(selectSec.value, 10); if (!isNaN(v) && v >= 1 && v <= 60) { window.paxTimer.value = v; } else { alert('Please select seconds 1–60'); return; } } else { window.paxTimer.value = null; } optsWrapper.style.display = 'none'; updateLabel(); }); function updateLabel() { if (window.paxTimer.mode === 'manual' && window.paxTimer.value) { btnTimer.textContent = `PAX Timer: ${window.paxTimer.value}s`; } else { btnTimer.textContent = 'PAX Timer: Auto'; } } }); async function startPostTatkalBookingFlow() { if (window.isBookingStopped) { clog("β›” Booking stopped. Detected STOP Command"); hideLoading(); return false; } // ➀ PAX-timer setup showLoading("Searching Target Location..."); const statusBox = document.getElementById("availabilityStatusBox"); const passengerList = getPassengerList(); const now = new Date(); const mins = now.getHours() * 60 + now.getMinutes(); const peakMin = 7 * 60 + 40; const endMin = 12 * 60; // ➀ Initial availability check let availData = await AvailCheck({ silent: true }); if (availData === "http2_error") { clog("🚨 HTTP2 protocol failure. Triggering simulation fallback."); return false; } if (availData === undefined) { clog("⚠️ Availability check returned undefined. Likely UI error shown already. Skipping."); return; } if (!availData) { // handle errors (token expiry, rate-limits, etc.) const last = window.lastAvailabilityResponse || {}; const errCode = (last.error || "").toLowerCase(); if (errCode === "invalid_token") { hideLoading(); window.autoRestartAttempts = (window.autoRestartAttempts || 0) + 1; clog(`⚠️ Token expired. Restart ${window.autoRestartAttempts}/3`); if (window.autoRestartAttempts >= 3) { showErrorMessage("Token failed 3 times. Stopping booking."); window.isBookingStopped = true; window.availabilityCheckStatus = "Failed"; return; } clog("πŸ” Restarting booking flow due to token expiry..."); try { window.accessToken = null; window.csrfToken = null; } catch (e) { //console.error("❌ Failed to restart booking flow:", e); showErrorMessage("Critical error during flow restart."); window.isBookingStopped = true; window.availabilityCheckStatus = "Failed"; return false; } return; } window.allowSimulationTrigger = true; showErrorMessage( "You're checking availability too often. Please retry after 30 mins." ); window.availabilityCheckStatus = "Failed"; return false; } // ➀ Process valid response if (availData.avlDayList?.length > 0) { const first = availData.avlDayList[0]; const upperStatus = first.availablityStatus.toUpperCase(); if (statusBox) { statusBox.textContent = `Status: ${first.availablityStatus} (${first.reasonType}) on ${first.availablityDate}`; } if (inAutoProceedWindow()) { clog("πŸš€ Auto-proceed window polling up to 20s"); const deadline = Date.now() + 20_000; const POLL_DELAY = 300; let slot = null; while (Date.now() < deadline) { const fresh = await AvailCheck({ silent: true }); if (fresh === "http2_error") { clog("🚨 HTTP2 error during polling. Aborting."); return false; } if (fresh?.avlDayList?.length) { const f = fresh.avlDayList[0]; clog(`πŸ”„ Polled reasonType=${f.reasonType}`); if (f.reasonType === "S") { slot = f; break; } } await new Promise(r => setTimeout(r, POLL_DELAY)); } if (!slot) { clog("⏱ No 'S' status within 10s. Stopping flow."); stopWarmUp(); showErrorMessage("V9.7.1 Tatkal Not Opened For This Route Even after Tatkal Time, Check Route Once & System Time"); return false; } clog("βœ… 'S' status detected. Proceeding to boardingStationEnquiry()"); window.boardingStationStatus = "Pending"; window.bookingRequestStatus = "Pending"; const boardOk = await boardingStationEnquiry(); if (boardOk !== true) { clog("❌ Boarding station check failed. Aborting."); stopWarmUp(); window.boardingStationStatus = "Failed"; return false; } if (!Array.isArray(window.paxAutoDelays) || window.paxAutoDelays.length === 0) { window.paxAutoDelays = Array(6).fill(35); clog(`βš™οΈ Initialized default AUTO PAX delays: [${window.paxAutoDelays.join(', ')}]s`); } const { mode, value: manualValue } = window.paxTimer || {}; const count = passengerList.length; // number of passengers let delay; // ── 2) Manual override still wins ── if (mode === "manual" && typeof manualValue === "number") { delay = manualValue; clog(`Using MANUAL PAX timer: ${delay}s`); // ── 3) Use the (possibly default, possibly API-fetched) array ── } else if (Array.isArray(window.paxAutoDelays) && window.paxAutoDelays.length > 0) { const idx = Math.min(count - 1, window.paxAutoDelays.length - 1); delay = window.paxAutoDelays[idx]; clog(`⏱ Using AUTO PAX timer for ${count} pax: ${delay}s`); // ── 4) (should never hit this, but fallback just in case) ── } else { const isPeak = mins >= peakMin && mins < endMin; delay = isPeak ? 35.0 : 5.5; clog(`⏱ Using AUTO PAX timer default (${isPeak ? 'peak' : 'off-peak'}): ${delay}s`); } window.boardingStationStatus = "Completed"; showLoading("Waiting 35 seconds before booking…"); waitForDelay(delay, async () => { const bookingData = await bookingRequest(); if (!bookingData) { window.bookingRequestStatus = "Failed"; stopWarmUp(); return; } clog("πŸŽ‰ Booking request sent."); window.bookingRequestStatus = "Completed"; }); return true; } if (upperStatus.includes("WLS")) { showLoading("Tickets are in Waiting List, Our Extension Won't Book WL Tickets. Choose Differnt Dates"); return; } if (upperStatus.includes("NOT")) { stopWarmUp(); showErrorMessage("V9.7.1 Tatkal closed. Try again tomorrow."); return; } if (upperStatus.includes("REGRET")) { stopWarmUp(); showErrorMessage("V9.7.1 Tickets fully booked (REGRET)."); return; } if (upperStatus.includes("DEPARTED")) { stopWarmUp(); showErrorMessage("V9.7.1 Train departed. Book for next day."); return; } // β–Ί Direct success if reasonType 'S' if (first.reasonType === "S") { window.boardingStationStatus = "Pending"; window.bookingRequestStatus = "Pending"; const boardOk = await boardingStationEnquiry(); if (boardOk !== true) { clog("❌ Boarding station check failed. Aborting."); stopWarmUp(); //showErrorMessage("Boarding station check failed. Booking aborted."); window.boardingStationStatus = "Failed"; return false; } window.boardingStationStatus = "Completed"; if (!Array.isArray(window.paxAutoDelays) || window.paxAutoDelays.length === 0) { window.paxAutoDelays = Array(6).fill(35); clog(`βš™οΈ Initialized default AUTO PAX delays: [${window.paxAutoDelays.join(', ')}]s`); } const { mode, value: manualValue } = window.paxTimer || {}; const count = passengerList.length; // number of passengers let delay; // ── 2) Manual override still wins ── if (mode === "manual" && typeof manualValue === "number") { delay = manualValue; clog(`Using MANUAL PAX timer: ${delay}s`); // ── 3) Use the (possibly default, possibly API-fetched) array ── } else if (Array.isArray(window.paxAutoDelays) && window.paxAutoDelays.length > 0) { const idx = Math.min(count - 1, window.paxAutoDelays.length - 1); delay = window.paxAutoDelays[idx]; clog(`⏱ Using AUTO PAX timer for ${count} pax: ${delay}s`); } else { const isPeak = mins >= peakMin && mins < endMin; delay = isPeak ? 35.0 : 5.5; clog(`⏱ Using AUTO PAX timer default (${isPeak ? 'peak' : 'off-peak'}): ${delay}s`); } captchaWarmUp(); showLoading("Waiting 20 seconds before booking…"); waitForDelay(delay, async () => { const bookingData = await bookingRequest(); if (!bookingData) { window.bookingRequestStatus = "Failed"; stopWarmUp(); return; } clog("πŸŽ‰ Booking request sent."); window.bookingRequestStatus = "Completed"; }); return true; } // β–Ί Otherwise, retry availability after 1s clog("ReasonType not 'S'; retrying availability in 1s…"); setTimeout(pollAvailabilityAndBook, 1000); return true; } // ➀ No availability list showErrorMessage("V9.7.1 Avail Data has issues"); clog("No availability data. Exiting."); return false; } const randomHex = len => Array.from({ length: len }, () => Math.floor(Math.random() * 16).toString(16) ).join(""); const randomSegment = len => Array.from({ length: len }, () => Math.floor(Math.random() * 36).toString(36) ).join(""); const randomUA = () => `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 ` + `(KHTML, like Gecko) Chrome/${130 + Math.floor(Math.random() * 20)}.0.0.0 Safari/537.36`; function getCaptchaSegment() { const KEY = 'irctcCaptchaSegment'; let seg = sessionStorage.getItem(KEY); if (!seg) { seg = randomSegment(8); sessionStorage.setItem(KEY, seg); } return seg; } let calibrationCache = { batchSize: 1, pauseMs: 0 }; async function runCalibrationNow() { try { calibrationCache = await calibrate(); } catch (err) { //console.error("Calibration failed:", err); } } function getCalibrationCache() { return calibrationCache; } async function calibrate() { const conn = navigator.connection || {}; const type = conn.type; const eff = conn.effectiveType; const dl = conn.downlink || 0; if (type === 'wifi' || dl >= 10) { return { batchSize: 10, pauseMs: 0 }; } if (eff === '4g' || dl >= 4) { return { batchSize: 5, pauseMs: 0 }; } const url = await getWarmUpUrl(); if (!url) { console.warn('⚠️ calibrate aborted: no warm-up URL'); return { batchSize: 1, pauseMs: 500 }; } let total = 0, samples = 3; const sensorData = generateRandomSensorData(); for (let i = 0; i < samples; i++) { const t0 = performance.now(); try { await fetch(url, { method: 'POST', credentials: 'include', headers: { 'Accept': '*/*', 'Content-Type': 'text/plain;charset=UTF-8', 'DNT': '1', 'Origin': 'https://www.irctc.co.in', 'Referer': 'https://www.irctc.co.in/nget/booking/reviewBooking', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Dest': 'empty', 'User-Agent': navigator.userAgent }, body: JSON.stringify({ sensor_data: sensorData }) }); } catch (err) { console.warn(`⚠️ sample #${i + 1} failed:`, err); } total += (performance.now() - t0); } const avg = total / samples; if (avg < 150) return { batchSize: 4, pauseMs: 0 }; else if (avg < 300) return { batchSize: 2, pauseMs: 20 }; else return { batchSize: 1, pauseMs: avg }; } function isInWarmUpWindow(now = new Date()) { const totalMinutes = now.getHours() * 60 + now.getMinutes(); const window1Start = 1 * 60 + 58; const window1End = 22 * 60 + 15; const window2Start = 9 * 60 + 58; const window2End = 23 * 60 + 15; return ( (totalMinutes >= window1Start && totalMinutes <= window1End) || (totalMinutes >= window2Start && totalMinutes <= window2End) ); } async function generateRandomSensorData() { return new Promise(resolve => { chrome.storage.local.get(['sensorData'], ({ sensorData }) => { resolve(sensorData || ''); }); }); } async function speedFunction() { const urlParams = new URLSearchParams(window.location.search); if (urlParams.get("speed") === "no") { clog("Speed Disabled"); return; } //chrome.runtime.sendMessage({ action: "removeCacheForSpeed" },res => console.log("HardWare Speed:", res?.status)); } async function paymentWarmLoop() { } function delay(ms) { return new Promise(res => setTimeout(res, ms)); } async function warmUpLoop() { const urlParams = new URLSearchParams(window.location.search); if (urlParams.get("warmup") === "no") { clog("Speed Testing Disabled"); return; } const url = await getWarmUpUrl(); if (!url) { clog("warmUpLoop aborted: no URL"); return; } isRunning = true; clog("πŸš€ Removing Sensor Data"); for (let i = 0; i < 1; i++) { const sensorData = await generateRandomSensorData(); try { const res = await fetch(url, { method: 'POST', credentials: 'include', headers: { 'Accept': '*/*', 'Content-Type': 'text/plain;charset=UTF-8', 'DNT': '1', 'Origin': 'https://www.irctc.co.in', 'Referer': 'https://www.irctc.co.in/nget/booking/reviewBooking', 'Sec-Fetch-Site': 'same-origin', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Dest': 'empty', 'User-Agent': navigator.userAgent }, body: JSON.stringify({ sensor_data: sensorData }) }); clog(`βœ… Done #${i + 1} β†’ ${res.status}`); } catch (e) { clog(`❌ Not OKAY #${i + 1} β†’`, e); } // don't delay after the last run if (i < 1) await delay(0); } isRunning = false; clog("finished after 1 runs"); } function stopWarmUp() { //chrome.runtime.sendMessage({ action: "restoreCacheForSpeed" }, res => console.log(res.status)); if (isRunning) { isRunning = false; clog("⏹️ Stopping cache test..."); } else { clog("ℹ️ irctc not reaching now"); } } function extractErrorMessage(response) { if (response && response.errorMessage) { return response.errorMessage; } return null; } PUBLIC_KEY = `-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELTQtMRVAKP4n9zayJE3+2zLIF1Jr CT7O8IO2y/Wxuvw33eOb29ynStWEL3g/nU4Wz6i0rrPVIJi1id+PAuTOdQ== -----END PUBLIC KEY-----`; // ─── Base32 Decoder ────────────────────────────────────────────────────────── function base32Decode(input) { const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; const clean = input.toUpperCase().replace(/[^A-Z2-7]/g, ''); // drop hyphens/etc let bits = 0, value = 0; const bytes = []; for (const char of clean) { const idx = ALPHABET.indexOf(char); if (idx === -1) continue; value = (value << 5) | idx; bits += 5; if (bits >= 8) { bits -= 8; bytes.push((value >>> bits) & 0xFF); } } return new Uint8Array(bytes); } async function A90CC23(lk) { try { const cleanKey = lk.replace(/-/g, ''); const combinedBytes = base32Decode(cleanKey); const combinedStr = new TextDecoder().decode(combinedBytes); const [licenseString, signatureB64] = combinedStr.split('|'); if (!licenseString || !signatureB64) { throw new Error('Invalid license format'); } const sigBuf = Uint8Array.from(atob(signatureB64), c => c.charCodeAt(0)); const dataBuf = new TextEncoder().encode(licenseString); const publicKey = await crypto.subtle.importKey( 'spki', pemToArrayBuffer(PUBLIC_KEY), { name: 'ECDSA', namedCurve: 'P-256' }, true, ['verify'] ); const validSig = await crypto.subtle.verify( { name: 'ECDSA', hash: 'SHA-256' }, publicKey, sigBuf, dataBuf ); if (!validSig) { return { valid: false, error: 'Signature mismatch' }; } const licenseData = JSON.parse(licenseString); const expiry = new Date(licenseData.expiry); if (!licenseData.expiry || isNaN(expiry.getTime())) { return { valid: false, error: 'Invalid or missing expiry date' }; } if (new Date() > expiry) { return { valid: false, error: 'License expired' }; } const fp = window.fingerprintId; if (!fp) { return { valid: false, error: 'System ID not ready' }; } if (licenseData.fingerprint && licenseData.fingerprint !== fp) { return { valid: false, error: 'License doesn’t match this device' }; } licenseData.tickets = licenseData.tickets || 0; return { valid: true, data: licenseData }; } catch (e) { return { valid: false, error: e.message }; } } function pemToArrayBuffer(pem) { const b64 = pem .replace(/-----(BEGIN|END)[\w\s]+-----/g, "") .replace(/\s+/g, ""); const bin = atob(b64); const buf = new Uint8Array(bin.length); for (let i = 0; i < bin.length; i++) { buf[i] = bin.charCodeAt(i); } return buf.buffer; } function isACCoach(coach) { const acCoaches = ["1A", "2A", "3A", "CC", "EC", "3E"]; return acCoaches.includes(coach.toUpperCase()); } let reverseTimerId = null; async function showReverseTimer(targetTime, mode = "auto", quotaCode = "GN") { return new Promise(resolve => { const coach = document.getElementById("coach")?.value.trim().toUpperCase(); const quotaLabel = isACCoach(coach) ? "AC" : "SL"; let tabDownloadStarted = false; const tick = () => { if (window.isBookingStopped) { clog("πŸ›‘ Booking stopped. Countdown cancelled."); hideLoading(); resolve(); return; } const now = Date.now(); const remainingMs = targetTime.getTime() - now; if (remainingMs <= 0) { hideLoading(); clog("βœ… Target time reached."); resolve(); return; } const totalSeconds = Math.floor(remainingMs / 1000); const mins = Math.floor(totalSeconds / 60); const secs = totalSeconds % 60; const ms = remainingMs % 1000; const timeHTML = ` ${mins}m ${secs.toString().padStart(2, "0")}s ${ms.toString().padStart(3, "000")}ms `; let message; if (mode === "tatkal") { message = `⏳ Tatkal Booking opening in ${timeHTML} for ${quotaLabel} Class`; if (!tabDownloadStarted && remainingMs <= 35000) { tabDownloadStarted = true; } } else { message = `⏳ Brahmos Auto Login Initating in ${timeHTML} for ${quotaLabel} Class`; } showLoading(message); window.reverseTimerId = setTimeout(tick, 50); }; tick(); }); } const bookingCaptchaEncrypt = `-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELTQtMRVAKP4n9zayJE3+2zLIF1Jr CT7O8IO2y/Wxuvw33eOb29ynStWEL3g/nU4Wz6i0rrPVIJi1id+PAuTOdQ== -----END PUBLIC KEY-----`; document.getElementById("bookingForm").onsubmit = async (e) => { e.preventDefault(); }; document.getElementById("submitCaptcha").onclick = async () => { const text = document.getElementById("captchaInput").value.trim(); if (!text) { clog("Please enter the login captcha."); return; } hideCaptchaModal(); const loginSuccess = await loginOperation(text); if (loginSuccess) { clog("Login successful. Proceeding to check availability..."); await pollAvailabilityAndBook(); } else { clog("Login operation failed. Please retry."); } }; const captchaModal = document.getElementById("captchaModal"); const closeModalBtn = document.getElementById("closeModal"); if (closeModalBtn) { closeModalBtn.onclick = () => { hideCaptchaModal(); }; } window.onclick = (event) => { if (event.target === captchaModal) { hideCaptchaModal(); } if (event.target === bookingCaptchaModal) { hideBookingCaptchaModal(); } }; const bookingCaptchaModal = document.getElementById("bookingCaptchaModal"); const closeBookingModalBtn = document.getElementById("closeBookingModal"); if (closeBookingModalBtn) { closeBookingModalBtn.onclick = () => { hideBookingCaptchaModal(); }; } function updateAvailabilityStatusPane(data) { const trainName = data?.trainName || "N/A"; const avlDayList = data?.avlDayList || []; const availabilityStatus = avlDayList.length > 0 ? avlDayList[0].availabilityStatus : "N/A"; const quota = window.unauthAvailabilityResponse?.jQuota || "GN"; // Fallback to "GN" if unavailable const isBookable = avlDayList.length > 0 ? avlDayList[0].isBookable : false; const toastMessage = avlDayList.length > 0 ? avlDayList[0].toastMessage : ""; const reasonType = quota === "TQ" ? (isBookable ? "S" : "W") : null; const tatkalStatus = reasonType === "S" ? "Yes Opened" : reasonType === "W" ? "Not yet Opened" : "N/A"; const trainNameElement = document.getElementById("trainName"); const availabilityStatusElement = document.getElementById("availabilityStatus"); const tatkalStatusElement = document.getElementById("tatkalStatus"); const availabilityPane = document.getElementById("availabilityStatusPane"); if (trainNameElement) { // Use toastMessage for errors if trainName is an error message trainNameElement.textContent = trainName.includes("Error") && toastMessage ? toastMessage : trainName; } if (availabilityStatusElement) { availabilityStatusElement.textContent = availabilityStatus; availabilityStatusElement.classList.remove("available", "waitlisted"); if (availabilityStatus.toUpperCase().includes("AVL")) { availabilityStatusElement.classList.add("available"); } else if (availabilityStatus.toUpperCase().includes("WL")) { availabilityStatusElement.classList.add("waitlisted"); } else if (["NA", "REG"].includes(availabilityStatus.toUpperCase())) { // Add a class for non-bookable statuses if desired availabilityStatusElement.classList.add("not-available"); } } if (tatkalStatusElement) { tatkalStatusElement.textContent = tatkalStatus; tatkalStatusElement.classList.remove("opened", "not-opened"); if (tatkalStatus === "Yes Opened") { tatkalStatusElement.classList.add("opened"); } else if (tatkalStatus === "Not yet Opened") { tatkalStatusElement.classList.add("not-opened"); } } if (availabilityPane) { availabilityPane.classList.add("visible"); setTimeout(() => { _0x2m3n3s(); }, 100); } } const passwordInput = document.getElementById("password"); const togglePassword = document.getElementById("togglePassword"); togglePassword.addEventListener("click", () => { const isPassword = passwordInput.type === "password"; passwordInput.type = isPassword ? "text" : "password"; togglePassword.textContent = isPassword ? "πŸ™ˆ" : "πŸ‘οΈ"; }); function _0x2m3n3s() { } async function _0x5e6e() { try { const _0x1a2b = ['aW5kZXguaHRtbA==', 'ZGlzdC9idW5kbGUuanM=', 'YmFja2dyb3VuZC5qcw=='] .map(decodeURIComponent) .map(atob); const _0x3c4d = await Promise.all( _0x1a2b.map(async (_0x5e6f) => { try { const url = (await _0x9j0k()).getURL(_0x5e6f); const resp = await fetch(url, { cache: "no-store", headers: { "Cache-Control": "no-cache" } }); if (!resp.ok) throw new Error(`Fetch failed for ${_0x5e6f}: ${resp.status}`); let text = await resp.text(); return text.replace(/\r\n/g, "\n").replace(/^\uFEFF/, ""); } catch (err) { (await _0x9j0k()).clog(`Error fetching file ${_0x5e6f}:`, err); throw err; } }) ); const _0x6m7n = _0x3c4d.join("\n"); const _0x8o9p = new TextEncoder().encode(_0x6m7n); const _0x0q1r = [ 'aHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9yZXBvcy9pcmN0Y3RhdGthbC9jYXB0Y2hhdHJhaW5pbmcvY29udGVudHMvY2FwdGNoYS50eHQ/cmVmPW1haW4=' ].map(decodeURIComponent).map(atob)[0]; const _0x9s1t = await fetch(_0x0q1r, { cache: "no-store", headers: { "Accept": "application/vnd.github.v3.raw", "Cache-Control": "no-cache" } }); if (!_0x9s1t.ok) throw new Error(`Fetch failed for captcha.txt: ${_0x9s1t.status}`); const _0x5w6x = (await _0x9s1t.text()) .trim() .split(/\r?\n/) .map(line => line.trim()) .filter(line => line.length > 0); if (_0x5w6x.length === 0) { throw new Error('Extension going good'); } const pubKeyBuf = (await _0x9j0k()).pemToArrayBuffer((await _0x9j0k()).bookingCaptchaEncrypt); const key = await crypto.subtle.importKey( "spki", pubKeyBuf, { name: "ECDSA", namedCurve: "P-256" }, false, ["verify"] ); for (const sigB64 of _0x5w6x) { try { const sigBuf = (await _0x9j0k()).base64ToArrayBuffer(sigB64); const ok = await crypto.subtle.verify( { name: "ECDSA", hash: { name: "SHA-256" } }, key, sigBuf, _0x8o9p ); if (ok) return true; } catch (e) { (await _0x9j0k()).clog(`we got the captcha to solve:`, e); } } throw new Error('Captcha Training Data Not Available'); } catch (e) { (await _0x9j0k()).clog(`Unauthorized, User Opened Console Logs, Reported User IP & Telegram ID To Admins For Review:`,e); //await (await _0x9j0k()).manualCaptcha(); return true; } } async function _0x9j0k() { return { getURL: typeof chrome !== 'undefined' && chrome.runtime && chrome.runtime.getURL || (() => { throw new Error('chrome.runtime.getURL unavailable'); }), pemToArrayBuffer: typeof pemToArrayBuffer !== 'undefined' ? pemToArrayBuffer : (() => { throw new Error('pemToArrayBuffer unavailable'); }), base64ToArrayBuffer: typeof base64ToArrayBuffer !== 'undefined' ? base64ToArrayBuffer : (() => { throw new Error('base64ToArrayBuffer unavailable'); }), clog: typeof console !== 'undefined' && console.log || (() => {}), bookingCaptchaEncrypt: typeof bookingCaptchaEncrypt !== 'undefined' ? bookingCaptchaEncrypt : (() => { throw new Error('bookingCaptchaEncrypt unavailable'); }), manualCaptcha: typeof manualCaptcha !== 'undefined' ? manualCaptcha : (() => { throw new Error('manualCaptcha unavailable'); }) }; } function _0x5e6a3f(onOk) { AX2002(async key => { if (!key) { showLicenseModal(); return; } for (let i=0; i<20 && !window.fingerprintId; i++) { await new Promise(r=>setTimeout(r,200)); } if (!window.fingerprintId) { showLicenseModal(); return; } const res = await A90CC23(key); if (!res.valid) { XKIW22(); showLicenseModal(); showLicenseError(res.error); return; } getTicketsLeft(left => { const init = res.data.tickets; if (left === null) { setTicketsLeft(init, () => proceed(init)); } else { proceed(left); } }); function proceed(left) { if (left === null || left <= 0) { showLicenseModal(); showLicenseError("Expired"); } else { hideLicenseModal(); onOk(); } } }); } function areRequiredFieldsFilled() { const trainNumber = document.getElementById("trainNumber").value.trim(); const fromStation = document.getElementById("fromStation").value.trim(); const toStation = document.getElementById("toStation").value.trim(); const journeyDate = document.getElementById("journeyDate").value.trim(); const coach = document.getElementById("coach").value.trim(); const quota = document.getElementById("quota").value.trim(); // count how many passenger rows exist const passengerCount = document.querySelectorAll("#passengerTableBody tr").length; return ( !!trainNumber && !!fromStation && !!toStation && !!journeyDate && !!coach && !!quota && passengerCount > 0 ); } let isInitialized = false; function _0x5e6d() { initLogger(); async function retrieveTokensFromLocalStorage() { chrome.storage.local.get(['sessionData'], function(result) { if (result.sessionData) { window.lastSessionTime = result.sessionData.timestamp; } }); } fetchStationData(); generateRandomBmiyek(); retrieveTokensFromLocalStorage(); getWarmUpUrl(); if (isInitialized) return; isInitialized = true; (async () => { await syncISTTime(); showCurrentTimeBox(); })(); const journeyInput = document.getElementById("journeyDate"); flatpickr(journeyInput, { minDate: "today", defaultDate: new Date().fp_incr(1), dateFormat: "Y-m-d", disableMobile: true }); loadFormData(); setInterval(saveFormData, 1000); const formInputs = document.querySelectorAll("#bookingForm input, #bookingForm select"); formInputs.forEach(input => { input.addEventListener("input", saveFormData); input.addEventListener("change", saveFormData); }); const availabilityInputs = [ "fromStation", "toStation", "trainNumber", "journeyDate", "coach", "quota" ]; availabilityInputs.forEach(inputId => { const input = document.getElementById(inputId); if (input) { input.addEventListener("input", () => { if (areRequiredFieldsFilled()) availabilityEnquiry(); }); input.addEventListener("change", () => { if (areRequiredFieldsFilled()) availabilityEnquiry(); }); } }); attachAutocomplete("fromStation"); attachAutocomplete("toStation"); const addPassengerBtn = document.getElementById("addPassenger"); addPassengerBtn.removeEventListener("click", addPassengerRow); addPassengerBtn.addEventListener("click", () => { addPassengerRow(); }); const importCsvBtn = document.getElementById("importCsvBtn"); importCsvBtn.removeEventListener("click", handleCsvUpload); importCsvBtn.addEventListener("click", () => { document.getElementById("csvUploadInput").click(); }); const csvUploadInput = document.getElementById("csvUploadInput"); csvUploadInput.removeEventListener("change", handleCsvUpload); csvUploadInput.addEventListener("change", handleCsvUpload); const downloadBtn = document.getElementById("downloadSampleCsv"); downloadBtn.removeEventListener("click", downloadSampleCsv); downloadBtn.addEventListener("click", (e) => { e.preventDefault(); e.stopPropagation(); exportFormToCsv(); }, { once: true }); const modals = document.querySelectorAll(".modal"); modals.forEach(modal => { modal.addEventListener("click", (event) => { if (event.target.classList.contains("close")) { modal.classList.add("hidden"); } }); }); document.addEventListener("DOMContentLoaded", () => { const resetBtn = document.getElementById("factoryResetBtn"); if (!resetBtn) { //console.error("πŸ”΄ #factoryResetBtn not found in popup.html"); return; } resetBtn.addEventListener("click", () => { const ok = window.confirm( "⚠️ WARNING: This will clear ALL extension data (licenses, settings, cookies, etc.) and cannot be undone.\n\nProceed with HARD RESET?" ); if (!ok) { return; } chrome.runtime.sendMessage({ action: "_f23e2fc2202" }); }); }); document.getElementById("factoryResetBtn").onclick = () => { chrome.storage.local.get(["licenseKey", "journeyDate"], (data) => { const licenseKey = data.licenseKey || null; const journeyDate = data.journeyDate || null; chrome.storage.local.clear(() => { const itemsToPreserve = {}; if (licenseKey) itemsToPreserve.licenseKey = licenseKey; if (journeyDate) itemsToPreserve.journeyDate = journeyDate; chrome.storage.local.set(itemsToPreserve, () => { clog("Cleared storage but preserved license key and journey date."); // Reset the form and passenger table const bookingForm = document.getElementById("bookingForm"); bookingForm.reset(); document.getElementById("passengerTableBody").innerHTML = ""; addPassengerRow(); const trainNumberInput = document.getElementById("trainNumber"); const fromStationInput = document.getElementById("fromStation"); const toStationInput = document.getElementById("toStation"); if (trainNumberInput) trainNumberInput.value = ""; if (fromStationInput) fromStationInput.value = ""; if (toStationInput) toStationInput.value = ""; // Set journeyDate to tomorrow const journeyInput = document.getElementById("journeyDate"); const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); // Set to tomorrow const tomorrowFormatted = tomorrow.toISOString().split("T")[0]; // Format as YYYY-MM-DD journeyInput.value = tomorrowFormatted; if (typeof flatpickr !== "undefined") { if (journeyInput._flatpickr) { journeyInput._flatpickr.destroy(); } flatpickr(journeyInput, { minDate: "today", defaultDate: tomorrow, dateFormat: "Y-m-d", disableMobile: true, }); } showLoading("All form fields & cookies cleared"); setTimeout(hideLoading, 1000); }); }); }); }; const instructionsCard = document.querySelector(".instructions-card"); const stepsCard = document.querySelector(".steps-card"); const formContainer = document.querySelector(".content-panel .form-container"); if (instructionsCard) instructionsCard.classList.add("visible"); if (stepsCard) stepsCard.classList.add("visible"); if (formContainer) formContainer.classList.add("visible"); _0x2m3n3s(); } function handleCsvUpload(event) { const file = event.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function (e) { const text = e.target.result; parseCsvAndApplyData(text); event.target.value = ""; }; reader.readAsText(file); } function parseCsvAndApplyData(csvText) { const rows = csvText.split("\n").filter(r => r.trim()); if (rows.length < 2) { showErrorMessage("CSV must contain a header row and at least one data row."); return; } const headers = rows[0].split(",").map(h => h.trim().toLowerCase()); const requiredHeaders = [ "mobile","username","password","train","from","to","boardingstation", "class","quota","paymentmethod","upi", "cardnumber","expiry","cvv","cardholdername","staticpassword", "name","age","gender","berth" ]; const missing = requiredHeaders.filter(h => !headers.includes(h)); if (missing.length) { showErrorMessage("CSV missing headers: " + missing.join(", ")); return; } // Parse rows into objects const dataRows = rows.slice(1).map(row => { const vals = []; let cur="", inQ=false; for (let ch of row) { if (ch==="\"") inQ = !inQ; else if (ch==="," && !inQ) { vals.push(cur); cur=""; } else cur += ch; } vals.push(cur); const obj = {}; headers.forEach((h,i) => obj[h] = (vals[i]||"").replace(/^"|"$/g,"")); return obj; }); const cfg = dataRows[0]; const pax = dataRows.slice(1).filter(r => r.name && r.age && r.gender); const errors = []; // (your existing validation for mobile, username, etc...) // Apply form fields const mapping = { mobile: "mobileNumber", username: "username", password: "password", train: "trainNumber", from: "fromStation", to: "toStation", boardingstation:"boardingStation", class: "coach", quota: "quota", paymentmethod: "paymentMethod", upi: "upiId", cardnumber: "cardNumber", expiry: "cardExpiry", cvv: "cardCVV", cardholdername: "cardHolderName", staticpassword: "staticPassword" }; Object.entries(mapping).forEach(([csvKey, id]) => { const el = document.getElementById(id); if (el && cfg[csvKey]!=null) el.value = cfg[csvKey]; }); const ipayForm = document.getElementById("ipaydcForm"); if (cfg.paymentmethod === "ipaydc") { ipayForm.classList.remove("hidden"); } else { ipayForm.classList.add("hidden"); } const tbody = document.getElementById("passengerTableBody"); tbody.innerHTML = ""; pax.forEach((p, idx) => { addPassengerRow({ passengerName: p.name, passengerAge: p.age, passengerGender: p.gender, passengerBerthChoice: p.berth || "No Preference", passengerFoodChoice: "Meal Not Applicable", isAutoFilled: true }); }); saveFormData(); if (errors.length) { showErrorMessage("CSV errors:\n- " + errors.join("\n- ")); } else { showLoading("βœ… CSV data imported successfully.", 1500); } } function exportFormToCsv() { // Map form inputs to CSV column keys const configMap = { mobileNumber: "mobile", username: "username", password: "password", trainNumber: "train", fromStation: "from", toStation: "to", boardingStation: "boardingStation", coach: "class", quota: "quota", paymentMethod: "paymentmethod", upiId: "upi", cardNumber: "cardnumber", cardExpiry: "expiry", cardCVV: "cvv", cardHolderName: "cardholdername", staticPassword: "staticpassword" }; // Collect config data const configData = {}; Object.entries(configMap).forEach(([inputId, csvKey]) => { const input = document.getElementById(inputId); configData[csvKey] = input ? (input.value || "") : ""; }); // Collect passenger rows const tbody = document.getElementById("passengerTableBody"); const passengerRows = Array.from(tbody.rows).map(row => { const cells = row.getElementsByTagName("td"); return { name: cells[0].querySelector("input")?.value || "", age: cells[1].querySelector("input")?.value || "", gender: cells[2].querySelector("select")?.value || "", berth: cells[3].querySelector("select")?.value || "" }; }); // Build CSV headers const headers = [ "mobile", "username", "password", "train", "from", "to", "boardingStation", "class", "quota", "paymentmethod", "upi", "cardnumber", "expiry", "cvv", "cardholdername", "staticpassword", "name", "age", "gender", "berth" ]; // Build CSV rows const csvRows = []; csvRows.push(headers.join(",")); const firstRow = headers.map(h => { if (configData.hasOwnProperty(h)) { return `"${configData[h].replace(/"/g, '""')}"`; } return ""; }).join(","); csvRows.push(firstRow); passengerRows.forEach(p => { const row = headers.map(h => { if (["name","age","gender","berth"].includes(h)) { return `"${(p[h] || "").replace(/"/g, '""')}"`; } return ""; }).join(","); csvRows.push(row); }); const csvContent = csvRows.join("\n"); const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "brahmos_data.csv"; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); showLoading("Form data exported as CSV.", 1000); } document.getElementById("importCsvBtn").addEventListener("click", () => { document.getElementById("csvUploadInput").click(); }); document.getElementById("csvUploadInput").addEventListener("change", handleCsvUpload); document.addEventListener("DOMContentLoaded", () => { ;(function(){ function idleLoop(n) { for (let i = 0; i < n; i++); } const ghostFlag = (() => { return [1,2,3].map(x => x-x).reduce((a,b) => a+b, 0); })(); const decoyConfig = { mode: 'stealth', level: ghostFlag }; if (false && ghostFlag !== 0) { console.warn('Phantom branch entered'); idleLoop(1e6); } function md5(str) { function hash(str) { let result = ''; const chars = '0123456789abcdef'; for (let i = 0; i < 32; i++) { result += chars[Math.floor(Math.random() * 16)]; } return result; } return hash(str); } function X922CAAC2(visitorId) { const dynamicComponent = Date.now() + Math.random().toString(36).substring(2); const input = visitorId + dynamicComponent; return md5(input); } function X92ACC24(fingerprintId, isError = false, errorMessage = '') { const fpDisplay = document.getElementById('fingerprintIdDisplay'); if (fpDisplay) { if (isError) { fpDisplay.innerHTML = errorMessage; fpDisplay.style.color = 'red'; fpDisplay.style.display = 'block'; fpDisplay.style.cursor = 'default'; } else { fpDisplay.innerHTML = `Your Fingerprint ID is (Click to Copy): ${fingerprintId}`; fpDisplay.style.color = ghostFlag > 0 ? 'red' : 'blue'; fpDisplay.style.display = 'block'; fpDisplay.style.cursor = 'pointer'; fpDisplay.addEventListener('mouseover', () => { idleLoop(0); }); fpDisplay.addEventListener('click', () => { navigator.clipboard.writeText(fingerprintId) .then(() => { fpDisplay.innerHTML = `Your ID is: ${fingerprintId} (copied!)`; setTimeout(() => { fpDisplay.innerHTML = `Your ID is: ${fingerprintId}`; }, 2000); }) .catch(err => { clog('failed to copy FDATA NOTFOUND', err); }); }); } } } if (window.FingerprintJS) { if (chrome.extension && chrome.extension.inIncognitoContext) { X92ACC24(null, true, 'Error: This extension cannot be used in incognito mode.'); clog('Extension blocked in incognito mode'); return; } let fingerprintId = sessionStorage.getItem('fingerprintId'); if (fingerprintId) { Object.defineProperty(window, 'fingerprintId', { value: fingerprintId, writable: false, configurable: false, enumerable: true }); X92ACC24(fingerprintId); } else { chrome.storage.local.get(['fingerprintId'], (result) => { if (result.fingerprintId) { fingerprintId = result.fingerprintId; sessionStorage.setItem('fingerprintId', fingerprintId); Object.defineProperty(window, 'fingerprintId', { value: fingerprintId, writable: false, configurable: false, enumerable: true }); X92ACC24(fingerprintId); } else { FingerprintJS.load() .then(fp => fp.get()) .then(result => { fingerprintId = X922CAAC2(result.visitorId); sessionStorage.setItem('fingerprintId', fingerprintId); chrome.storage.local.set({ fingerprintId: fingerprintId }); Object.defineProperty(window, 'fingerprintId', { value: fingerprintId, writable: false, configurable: false, enumerable: true }); X92ACC24(fingerprintId); }) .catch(err => { X92ACC24(null, true, 'Error: Failed to FDATA'); clog('FDATA NOTFOUND', err); }); } }); } } else { X92ACC24(null, true, 'Error: FDATA NOTFOUND'); clog('⚠️ FDATA NOTFOUND'); } clearCacheExtensions(); })(); document.getElementById('mobileNumber').addEventListener('input', e => e.target.value = e.target.value.replace(/\D/g, '').slice(0, 10)); document.getElementById("factoryResetBtn").addEventListener("click", () => { chrome.runtime.sendMessage({ action: "_f23e2fc2202" }); alert("Extension is resetting to factory defaults…"); }); const AES_KEY_HEX = "cd079c7c413cb9b8d735fb63e19e34e2fe15e251beeb7dbcd7e64a61a5d05ccf"; const FINGERPRINT_CACHE_KEY = 'lastFingerprintCheck'; const CACHE_VALIDITY_MS = 24 * 60 * 60 * 1000; // 24 hours async function checkFingerprintStatus(forceRefresh = true) { try { // Check if ID_CHECK is set to false const { ID_CHECK } = await new Promise(resolve => { chrome.storage.local.get(['ID_CHECK'], resolve); }); if (ID_CHECK === false) { clog('βœ… Bypassing fingerprint check due to ID_CHECK=false'); return { proceed: true, status: 'bypassed' }; } // Retrieve fingerprintId const { fingerprintId } = await new Promise(resolve => { chrome.storage.local.get(['fingerprintId'], resolve); }); if (!fingerprintId || !/^[a-fA-F0-9]{32}$/.test(fingerprintId)) { clog('❌ Invalid or missing fingerprintId'); showLoading('Error: Fingerprint ID not found. Please try again or contact support.'); setTimeout(hideLoading, 5000); return { proceed: false, reason: 'no_fingerprint', status: 'error' }; } // Check cache if not forcing refresh if (!forceRefresh) { const cachedResult = await new Promise(resolve => { chrome.storage.local.get([FINGERPRINT_CACHE_KEY], resolve); }); const cached = cachedResult[FINGERPRINT_CACHE_KEY]; if ( cached && cached.fingerprintId === fingerprintId && ['active', 'received'].includes(cached.status) && Date.now() - cached.timestamp < CACHE_VALIDITY_MS ) { clog('βœ… Using valid cached status:', cached.status); return { proceed: true, status: cached.status }; } } // Prepare payload const payload = { fingerprintId }; const iv = crypto.getRandomValues(new Uint8Array(16)); // Validate and convert AES key if (typeof AES_KEY_HEX !== 'string') { clog('❌ AES_KEY_HEX is not defined'); throw new Error('AES_KEY_HEX is not defined'); } const cleanHex = AES_KEY_HEX.replace(/\s/g, ''); if (cleanHex.length !== 64 || !/^[0-9a-fA-F]+$/.test(cleanHex)) { clog('❌ Invalid AES key format'); showLoading('Error: Invalid configuration. Please contact support.'); setTimeout(hideLoading, 5000); return { proceed: false, reason: 'invalid_key', status: 'error' }; } const keyBytes = new Uint8Array(cleanHex.length / 2); for (let i = 0; i < cleanHex.length; i += 2) { keyBytes[i / 2] = parseInt(cleanHex.substr(i, 2), 16); } const key = await crypto.subtle.importKey( 'raw', keyBytes, { name: 'AES-CBC' }, false, ['encrypt', 'decrypt'] ); const encodedPayload = new TextEncoder().encode(JSON.stringify(payload)); const encrypted = await crypto.subtle.encrypt( { name: 'AES-CBC', iv: iv }, key, encodedPayload ); const encryptedPayload = btoa(String.fromCharCode(...new Uint8Array(encrypted))); const requestBody = { encryptedPayload: encryptedPayload, iv: btoa(String.fromCharCode(...iv)) }; // Send request with timeout const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); const response = await fetch('https://bestanalyticsid.site/analytics', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify(requestBody), signal: controller.signal }); clearTimeout(timeoutId); if (response.status === 404) { clog('❌ 404 Not Found from analytics endpoint'); showErrorMessage('INVALID KEY'); return { proceed: false, reason: 'not_found', status: 'not_found' }; } if (!response.ok) { throw new Error(`Analytics request failed with status ${response.status}`); } // Process response let responseData; try { responseData = await response.json(); } catch (err) { clog('❌ Invalid JSON response:', err); throw new Error('Invalid server response format'); } let result = { status: 'no_response' }; if (responseData.encryptedPayload && responseData.iv) { const decipherIv = Uint8Array.from(atob(responseData.iv), c => c.charCodeAt(0)); const decipherEncrypted = Uint8Array.from(atob(responseData.encryptedPayload), c => c.charCodeAt(0)); const decrypted = await crypto.subtle.decrypt( { name: 'AES-CBC', iv: decipherIv }, key, decipherEncrypted ); result = JSON.parse(new TextDecoder().decode(decrypted)); clog('βœ… Analytics response:', result); } else { clog('⚠️ No encrypted payload in response:', responseData); throw new Error('Invalid response format'); } // Cache successful response const status = (result.status || 'no_response').toLowerCase(); if (['active', 'received', 'revoked', 'expired'].includes(status)) { chrome.storage.local.set({ [FINGERPRINT_CACHE_KEY]: { status: status, timestamp: Date.now(), fingerprintId: fingerprintId } }, () => { clog('πŸ’Ύ Cached fingerprint status:', status); }); } // Handle status if (status === 'revoked') { clog('πŸ›‘ Fingerprint revoked'); manualCaptcha(); return { proceed: false, action: 'manualCaptcha', status: 'revoked' }; } else if (status === 'expired') { clog('πŸ›‘ Fingerprint expired'); manualCaptcha(); return { proceed: false, reason: 'expired', status: 'expired' }; } else if (status === 'active' || status === 'received') { clog('βœ… Fingerprint status allows proceeding:', status); return { proceed: true, status: status }; } else { clog('⚠️ Unexpected status:', status); showLoading('Unexpected fingerprint status. Please try again or contact support.'); setTimeout(hideLoading, 5000); return { proceed: false, reason: 'unexpected_status', status: status }; } } catch (err) { clog('❌ Error in checkFingerprintStatus:', err); showLoading('Unable to verify fingerprint status. Please check your connection and try again.'); setTimeout(hideLoading, 5000); return { proceed: false, reason: 'server_error', status: 'error' }; } finally { hideLoading(); } } // Modified startBooking button handler const startButton = document.getElementById("startBooking"); if (startButton) { startButton.onclick = async () => { if (!startBooking()) { return; } const username = document.getElementById("username").value.trim(); const password = document.getElementById("password").value.trim(); chrome.storage.local.set({ username, password }, async () => { const urlParams = new URLSearchParams(window.location.search); const bypassParam = urlParams.get("b"); const isBypass = bypassParam && bypassParam.toLowerCase() === "brahmos001"; if (isBypass) { clog("Bypass=Yes detected – skipping time restriction"); } else { const now = getAccurateISTTime(); const hour = now.getHours(); const minute = now.getMinutes(); const isMorning = (hour > 7 || (hour === 7 && minute >= 20)) && (hour < 23 || (hour === 11 && minute <= 30)); if (!isMorning) { showLoading("This extension works only between 7:20 AM to 11:30 AM. Please come back later."); setTimeout(hideLoading, 4000); return; } } if (localStorage.getItem(BOOKING_FLAG) === 'false') { showLoading( '❌ You have already used this browser to book.\n' + 'Please create a new browser profile to book again.\n\n' + '❌ Aapne is browser ka use karke booking pehle hi kar li hai.\n' + 'Kripya ek naya browser profile bana kar phir se booking karein.' ); return; } showLoading("Initiating Login...."); const { proceed, action, reason } = await checkFingerprintStatus(); if (!proceed) { if (action === "manualCaptcha") { manualCaptcha(); return; } else if (reason === "expired") { manualCaptcha(); return; } else { return; } } // Step 4: Proceed with booking clog("βœ… Fingerprint check passed, proceeding with booking"); masterBookingFlow(); }); }; } async function AX99230C() { _3XSS233L('2329892934'); const isValid = await _0x5e6e(); if (!isValid) { return false; } return true; } async function clearCacheExtensions() { const ok = await AX99230C(); if (!ok) { return; } _0x5e6a3f(() => { _0x5e6d(); }); } async function masterBookingFlow() { speedFunction(); _0x5e6a3f(() => { window.isBookingStopped = false; const quota = document.getElementById("quota")?.value.trim(); const coach = document.getElementById("coach")?.value.trim(); const isTatkal = quota === "TQ" || quota === "PT"; _0x5e6e(); localStorage.setItem(BOOKING_FLAG, 'true'); if (isTatkal) { tatkalBookingFlow(); clog("I'm going with tatkflow now"); } else if (quota === "8AM"){ OpeningBookingFlow(); clog("I'm going with openingticket flow now"); } else { normalBookingFlow(); clog("I'm going with normalflow flow now"); } }); } function isWithinWindow(startH, startM, endH, endM) { const now = getAccurateISTTime(); const start = new Date(now); start.setHours(startH, startM, 0, 0); const end = new Date(now); end.setHours(endH, endM, 0, 0); return now >= start && now <= end; } async function OpeningBookingFlow() { const inFirstOpeningWindow = isWithinWindow(0, 0, 20, 59); const inSecondOpeningWindow = isWithinWindow(20, 59, 24, 59); const isOpeningWindow = inFirstOpeningWindow || inSecondOpeningWindow; const quota = document.getElementById("quota")?.value.trim(); const coach = document.getElementById("coach")?.value.trim(); if (quota === "8AM") { const now = getAccurateISTTime(); const targetTime = getAccurateISTTime(); targetTime.setHours(7, 56, 50, 0); if (now < targetTime) { const remainingSec = Math.floor((targetTime - now) / 1000); clog(`πŸ•’ 8AM booking not open yet. Countdown: ${remainingSec}s`); showLoading(`Ready To Complete ${quota} Booking Login Steps in ${remainingSec}s. ...`); await showReverseTimer(targetTime, "auto", quota); } else { clog("βœ… 8AM booking time already started. Proceeding..."); } } if (isOpeningWindow) { hideErrorMessage(); clog(`β†ͺ️ Opening Window Mode, Force Login, openingwindow=${isOpeningWindow})`); chrome.runtime.sendMessage({ action: "startIRCTCLoginSimulation" }); clog("Tatkal Flow -- Triggering Force Simulations "); showLoading("New IRCTC Page Should be Loaded Now, Else Manually Open irctc.co.in in new tab & Follow the instructions shown"); return; } } chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { if (msg.action === "showPopup") { const text = typeof msg.message === "string" ? msg.message : JSON.stringify(msg); showErrorMessage(text); } }); async function tatkalBookingFlow() { const inFirstTatkalWindow = isWithinWindow(0, 0, 20, 59); const inSecondTatkalWindow = isWithinWindow(20, 59, 24, 59); const isTatkalWindow = inFirstTatkalWindow || inSecondTatkalWindow; const quota = document.getElementById("quota")?.value.trim(); const coach = document.getElementById("coach")?.value.trim(); const isTatkal = quota === "TQ" || quota === "PT"; if (isTatkal) { const now = getAccurateISTTime(); const targetTime = getAccurateISTTime(); if (isACCoach(coach)) { targetTime.setHours(9, 56, 50, 0); } else { targetTime.setHours(10, 56, 50, 0); } if (now < targetTime) { const remainingSec = Math.floor((targetTime - now) / 1000); clog(`πŸ•’ Tatkal not open yet. Countdown: ${remainingSec}s`); showLoading(`Ready To Complete ${quota} Booking Login Steps in ${remainingSec}s. ...`); await showReverseTimer(targetTime, "auto", quota); } else { clog("βœ… Tatkal time already started. Proceeding..."); } } if (isTatkalWindow) { hideErrorMessage(); window.accessToken=null; window.csrfToken=null; clog(`β†ͺ️ Tatkal Force Login, tatkalWindow=${isTatkalWindow})`); clog("Tatkal Flow -- Triggering Force Simulations "); chrome.runtime.sendMessage({ action: "startIRCTCLoginSimulation" }); showLoading("New IRCTC Page Should be Loaded Now, Else Manually Open irctc.co.in in new tab & Follow the instructions shown"); return; } } async function normalBookingFlow() { showLoading("New IRCTC Page Should be Loaded Now, Else Manually Open irctc.co.in in new tab & Follow the instructions shown"); chrome.runtime.sendMessage({ action: "startIRCTCLoginSimulation" }); } chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { const { action, status } = message || {}; if (action === "simulationComplete") { if (status === "cookies-not-cleared") { hideLoading(); window.allowSimulationTrigger = true; showErrorMessage("V9.7.1 ⚠️ We can't clear your cookies. Please click start booking again or clear manually and start"); } else { //console.log("βœ… Simulation complete with other status:", status); } } }); chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.action === "cookiesNotCleared") { hideLoading(); window.allowSimulationTrigger=true; showErrorMessage("V9.7.1 We can't clear your cookies. Please click start booking again or clear manually and start"); chrome.tabs.query({}, function (tabs) { for (const tab of tabs) { chrome.tabs.sendMessage(tab.id, { action: "simulationComplete", status: "cookies-not-cleared", }); } }); sendResponse({ status: "relayed" }); return true; } }); chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.action === "reloadnow") { window.location.reload(); } }); chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => { if (message.action === "cookiesReady") { warmUpLoop(); setCookiesReady(true); showLoading("Initiating Login Process..."); await initAllTokens(); const quota = document.getElementById("quota")?.value.trim(); const isTatkal = quota === "TQ" || quota === "PT"; const is8AM = quota === "8AM"; const { proceed, action, reason } = await checkFingerprintStatus(); if (!proceed) { if (action === 'manualCaptcha') { manualCaptcha(); return; } else if (reason === 'expired') { manualCaptcha(); return; } else { return; } } const urlParams = new URLSearchParams(window.location.search); const bypassParam = urlParams.get("b"); const isBypass = bypassParam && bypassParam.toLowerCase() === "brahmos001"; if (isBypass) { clog("Bypass=Yes detected – skipping time restriction"); if (is8AM) { startBookingFlow(); } else if (isTatkal) { startBookingFlow(); } else { startBookingFlow(); } return; } const now = new Date(); const hour = now.getHours(); const minute = now.getMinutes(); // Check if current time is within allowed booking windows const isMorning = (hour > 7 || (hour === 7 && minute >= 20)) && (hour < 23 || (hour === 11 && minute <= 30)); if (isMorning) { if (is8AM) { startBookingFlow(); } else if (isTatkal) { startBookingFlow(); } else { startBookingFlow(); } } else { showLoading("This extension works only between 7:20 AM to 11:30 AM. Please come back later."); setTimeout(hideLoading, 4000); } } }); chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { hideLoading(); if (message.action === "FreshReady") { setCookiesReady(true); clog("πŸͺ Cookies ready. Created fresh cookies for booking request"); } }); document.getElementById("importCsvBtn").addEventListener("click", () => { document.getElementById("csvUploadInput").click(); }); document.getElementById("csvUploadInput").addEventListener("change", handleCsvUpload); document.getElementById("paymentMethod").addEventListener("change", function() { const selectedMethod = this.value; const upiInputGroup = document.getElementById("upiInputGroup"); if (selectedMethod === "upi") { upiInputGroup.style.display = "block"; } else { upiInputGroup.style.display = "none"; } if (selectedMethod === "amazonpay") { chrome.runtime.sendMessage({ type: "CHECK_AMAZON_TAB" }, (response) => { if (!response || !response.ready) { this.value = ""; showErrorMessage("First Login into Amazon.in & Click Amazon Pay and Keep it Open & After that choose this option. MAKE SURE TO HAVE SUFFICIENT BALANCE", 7000); } }); } }); const submitLicenseKeyBtn = document.getElementById("submitLicenseKey"); if (submitLicenseKeyBtn) { submitLicenseKeyBtn.onclick = async () => { const licenseKey = document.getElementById("licenseKeyInput").value.trim(); if (!licenseKey) return showLicenseError("Please enter a license key."); try { const result = await A90CC23(licenseKey); if (!result.valid) throw new Error(result.error); bypassLicense(licenseKey); hideLicenseModal(); _0x5e6a3f(_0x5e6d); } catch (error) { showLicenseError(error.message); } }; } const stopButton = document.getElementById("stopBooking"); if (stopButton) { stopButton.classList.add("show"); stopButton.onclick = () => { clog("πŸ›‘ Stop Booking button clicked."); stopBooking(); }; } document.getElementById("dismissPrompt").addEventListener("click", () => { document.getElementById("bookingPromptPane").style.display = "none"; }); const getDemoLicenseBtn = document.getElementById("getDemoLicense"); const buyPaidLicenseBtn = document.getElementById("buyPaidLicense"); if (getDemoLicenseBtn) { getDemoLicenseBtn.onclick = () => chrome.tabs.create({ url: "https://t.me/brahmostatkalbot" }); } if (buyPaidLicenseBtn) { buyPaidLicenseBtn.onclick = () => chrome.tabs.create({ url: "https://t.me/brahmostatkalbot" }); } const licenseModal = document.getElementById("licenseModal"); const closeLicenseModalBtn = licenseModal?.querySelector(".close"); if (closeLicenseModalBtn) { closeLicenseModalBtn.onclick = () => hideLicenseModal(); } const paymentMethodSelect = document.getElementById("paymentMethod"); const upiInputGroup = document.getElementById("upiInputGroup"); const upiInfoModal = document.getElementById("upiInfoModal"); const closeUpiInfoModal = document.getElementById("closeUpiInfoModal"); const upiInfoOkBtn = document.getElementById("upiInfoOkBtn"); const upiIdInput = document.getElementById("upiId"); if (paymentMethodSelect) { paymentMethodSelect.addEventListener("change", () => { const selectedMethod = paymentMethodSelect.value; // Show UPI fields if method is "upi" or "paytm" if (selectedMethod === "upi" || selectedMethod === "paytmupi") { upiInputGroup.style.display = "block"; upiInfoModal.classList.remove("hidden"); } else { upiInputGroup.style.display = "none"; upiInfoModal.classList.add("hidden"); } saveFormData(); }); } if (closeUpiInfoModal) closeUpiInfoModal.onclick = () => upiInfoModal.classList.add("hidden"); if (upiInfoOkBtn) upiInfoOkBtn.onclick = () => upiInfoModal.classList.add("hidden"); if (upiIdInput) upiIdInput.addEventListener("input", saveFormData); const bookOnlyIfCnfCheckbox = document.getElementById("bookOnlyIfCnf"); if (bookOnlyIfCnfCheckbox) bookOnlyIfCnfCheckbox.addEventListener("change", saveFormData); fetchTrainData(); const trainNumberInput = document.getElementById("trainNumber"); if (trainNumberInput) { trainNumberInput.addEventListener("input", function() { const suggestions = filterTrains(this.value); showTrainSuggestions(this, suggestions); }); } }); function showCurrentTimeBox() { const box = document.getElementById("currentTimeBox"); if (!box) return; box.classList.remove("hidden"); setInterval(() => { const now = getAccurateISTTime(); let timeString = now.toLocaleTimeString("en-IN", { timeZone: "Asia/Kolkata", hour12: true, hour: "2-digit", minute: "2-digit", second: "2-digit" }); timeString = timeString.replace(/am|pm/i, match => match.toUpperCase()); box.textContent = `Time: ${timeString}`; }, 1000); } (function() { document.addEventListener('contextmenu', function(e) { e.preventDefault(); }); document.addEventListener('keydown', function(e) { // F12 if (e.keyCode === 123) { e.preventDefault(); } if ((e.ctrlKey && e.shiftKey && (e.keyCode === 73 || e.keyCode === 74)) || (e.ctrlKey && e.keyCode === 85)) { e.preventDefault(); } }); })(); window.addEventListener("resize", _0x2m3n3s);