1(function () { 2 console.log("BDN Prosperstack: Script loaded and monitoring for buttons..."); 3 const CLIENT_ID = "acct_l7PMT7JDhrIem4NhpPsKML55"; 4 const SRC = "https://cdn.prosperstack.com/flow/latest/flow.min.js"; 5 const BUTTON_SELECTOR = ".pelcro-dashboard-sub-cancel-button"; 6 const DEBUG = false; 7 8 function loadProsperStack() { 9 console.log("LOAD Prosperstack"); 10 if (window.ProsperStack?.flow) { 11 return Promise.resolve(window.ProsperStack.flow); 12 } 13 14 if (window.__psLoad) { 15 return window.__psLoad; 16 } 17 18 window.__psLoad = new Promise((resolve, reject) => { 19 const s = document.createElement("script"); 20 s.src = SRC; 21 s.async = true; 22 s.onload = function () { 23 if (window.ProsperStack?.flow) { 24 resolve(window.ProsperStack.flow); 25 } else { 26 reject(new Error("ProsperStack flow failed to load")); 27 } 28 }; 29 s.onerror = reject; 30 document.head.appendChild(s); 31 }); 32 33 return window.__psLoad; 34 } 35 36 function getPelcroUser() { 37 return window.Pelcro?.user?.read?.() || null; 38 } 39 40 function buildPayload(subscriptionId) { 41 const user = getPelcroUser(); 42 if (!user || !subscriptionId) return null; 43 44 const sub = (user.subscriptions || []).find(function (s) { 45 return String(s?.id) === String(subscriptionId); 46 }); 47 48 if (!sub) return null; 49 50 const name = 51 user.name || 52 user.full_name || 53 [user.first_name, user.last_name].filter(Boolean).join(" "); 54 55 const internalId = String(user.id || "").trim(); 56 const trimmedName = String(name || "").trim(); 57 const email = String(user.email || "").trim(); 58 59 if (!internalId || !trimmedName || !email) return null; 60 61 return { 62 clientId: CLIENT_ID, 63 subscriber: { 64 internalId: internalId, 65 name: trimmedName, 66 email: email, 67 }, 68 subscription: { 69 platformId: String(sub.id), 70 properties: { 71 pelcro_status: sub.status, 72 pelcro_plan_nickname: sub.plan?.nickname, 73 pelcro_plan_interval: sub.plan?.interval, 74 pelcro_plan_interval_count: sub.plan?.interval_count, 75 pelcro_product_name: sub.plan?.product?.name, 76 pelcro_current_period_end: sub.current_period_end, 77 }, 78 }, 79 }; 80 } 81 82 function cloneAndReplaceButton(btn) { 83 const cleanBtn = btn.cloneNode(true); 84 cleanBtn.dataset.psBound = "true"; 85 cleanBtn.dataset.psFallbackReady = "true"; 86 btn.replaceWith(cleanBtn); 87 return cleanBtn; 88 } 89 90 function restoreOriginalBehavior(btn) { 91 if (!btn || btn.dataset.psFallbackReady !== "true") return btn; 92 93 const restoredBtn = btn.cloneNode(true); 94 delete restoredBtn.dataset.psBound; 95 delete restoredBtn.dataset.psFallbackReady; 96 restoredBtn.dataset.psRestoreBypass = "true"; 97 98 btn.replaceWith(restoredBtn); 99 100 setTimeout(function () { 101 delete restoredBtn.dataset.psRestoreBypass; 102 }, 0); 103 104 return restoredBtn; 105 } 106 107 async function handleCancelClick(e, btn) { 108 const subscriptionId = btn.getAttribute("data-key"); 109 const payload = buildPayload(subscriptionId); 110 111 // DEBUG MODE: log and allow normal behavior 112 if (DEBUG) { 113 console.log("ProsperStack DEBUG payload:", payload); 114 return true; // do not block default behavior 115 } 116 117 // Normal mode: intercept 118 e.preventDefault(); 119 e.stopPropagation(); 120 e.stopImmediatePropagation(); 121 122 if (!subscriptionId) { 123 const restoredBtn = restoreOriginalBehavior(btn); 124 restoredBtn.click(); 125 return false; 126 } 127 128 if (!payload) {
129 console.error("Could not construct valid ProsperStack payload"); 130 const restoredBtn = restoreOriginalBehavior(btn); 131 restoredBtn.click(); 132 return false; 133 } 134 135 try { 136 const flow = await loadProsperStack(); 137 if (!flow) { 138 const restoredBtn = restoreOriginalBehavior(btn); 139 restoredBtn.click(); 140 return false; 141 } 142 143 flow(payload, { displayMode: "modal" }); 144 return true; 145 } catch (err) { 146 console.error("ProsperStack launch failed", err); 147 const restoredBtn = restoreOriginalBehavior(btn); 148 restoredBtn.click(); 149 return false; 150 } 151 } 152 153 function wireButton(btn) { 154 if (!btn || btn.dataset.psBound === "true") return btn; 155 156 const cleanBtn = cloneAndReplaceButton(btn); 157 158 cleanBtn.addEventListener("click", function (e) { 159 if (cleanBtn.dataset.psRestoreBypass === "true") { 160 return; 161 } 162 163 handleCancelClick(e, cleanBtn); 164 }); 165 166 return cleanBtn; 167 } 168 169 function wireAllButtons() { 170 document.querySelectorAll(BUTTON_SELECTOR).forEach(wireButton); 171 } 172 173 function startObserver() { 174 const observer = new MutationObserver(function () { 175 wireAllButtons(); 176 }); 177 178 observer.observe(document.body, { 179 childList: true, 180 subtree: true, 181 }); 182 } 183 184 wireAllButtons(); 185 186 if (document.body) { 187 startObserver(); 188 } else { 189 document.addEventListener("DOMContentLoaded", startObserver, { 190 once: true, 191 }); 192 } 193 194 document.addEventListener( 195 "click", 196 function (e) { 197 const btn = e.target.closest(BUTTON_SELECTOR); 198 if (!btn) return; 199 if (btn.dataset.psRestoreBypass === "true") return; 200 if (btn.dataset.psBound === "true") return; 201 202 handleCancelClick(e, btn); 203 }, 204 true, 205 ); 206})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.