#!/usr/bin/env python3 """Rewrite SatsSpin shim fetch patch: re-entrancy-proof via global original fetch.""" import io, re P = "/opt/casino/dist/shim.js" src = io.open(P, encoding="utf-8").read() old_patch = """ // 1. Patch fetch to inject Authorization header. var _fetch = window.fetch; window.fetch = function (url, opts) { opts = opts || {}; opts.headers = opts.headers || {}; if (TOKEN && !opts.headers['Authorization']) { opts.headers['Authorization'] = 'Bearer ' + TOKEN; } return _fetch.call(this, url, opts).then(function (r) { if (r.status === 401) { TOKEN = ''; USER_ID = ''; localStorage.removeItem('satsspin_token'); } return r; }); }; """ new_patch = """ // 1. Patch fetch to inject Authorization header. Re-entrancy-proof: // the ORIGINAL native fetch is captured once on window — even if this // script somehow executes twice, both wrappers call the same original. if (!window.__ssOriginalFetch) { window.__ssOriginalFetch = window.fetch.bind(window); } var _fetch = window.__ssOriginalFetch; window.fetch = function (url, opts) { opts = opts || {}; opts.headers = opts.headers || {}; if (TOKEN && !opts.headers['Authorization']) { opts.headers['Authorization'] = 'Bearer ' + TOKEN; } return _fetch(url, opts).then(function (r) { if (r.status === 401) { TOKEN = ''; USER_ID = ''; localStorage.removeItem('satsspin_token'); } return r; }); }; """ assert old_patch in src, "old fetch patch not found" src = src.replace(old_patch, new_patch, 1) io.open(P, "w", encoding="utf-8").write(src) # cache-bust the script tag in app.html A = "/opt/casino/dist/app.html" app = io.open(A, encoding="utf-8").read() app = app.replace('', '') io.open(A, "w", encoding="utf-8").write(app) print("SHIM REWRITTEN + CACHE-BUSTED")