Spaces:
Running
Running
Download pack.js from CyberMax-tools/stoopshake: direct link, hf CLI and curl.
- Browser
- Download file 8.35 kB
-
https://huggingface.co/spaces/CyberMax-tools/stoopshake/resolve/main/pack.js
- Command line
-
hf download hf://spaces/CyberMax-tools/stoopshake/pack.js
-
curl -L -o pack.js https://huggingface.co/spaces/CyberMax-tools/stoopshake/resolve/main/pack.js
8.35 kB
| // CyberMax game Skin Pack (Stoopshake: the Dice & Table Pack): a one-time cosmetic unlock for ONE game (separate from the Fun Pass, which covers every | |
| // game's archive + themes). Buy: counted redirect data.cybermaxtools.com/buy/st-<game>-skins-pack?s=game-<game> | |
| // -> Stripe Payment Link; or the Gumroad listing (licence key). After checkout data.cybermaxtools.com/unlock/<game>-skins | |
| // checks the order (or the Gumroad licence key) and returns to the game with ?unlock=skins#cmx-pro=<code>. | |
| // capture() must run BEFORE funpass.init() so the Fun Pass never mistakes a skin-pack code for a pass code. | |
| // Cosmetic only: skins never change the game, scores or the daily course. (c) 2026 CyberMax. | |
| import { count, store, toast } from './cmx.js'; | |
| const DATA = 'https://data.cybermaxtools.com'; | |
| const CODE = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; | |
| let cfg = { game: '', name: '', price: '$1.99', gumroad: '', skins: 0 }; | |
| let state = null; | |
| const subs = []; | |
| const key = () => `cmx-skins:${cfg.game}`; | |
| export const owned = () => !!(state && state.code); | |
| export function onChange(fn) { subs.push(fn); } | |
| const emit = () => subs.forEach((f) => { try { f(owned()); } catch { /* game hook */ } }); | |
| // Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified here | |
| // with WebCrypto and this public key, so an unlock needs no Worker call. Expired, foreign-signed or unverifiable keys fall | |
| // back to the online check of the order code inside them, as before. | |
| const CMX_PUB = 'u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk'; | |
| const b64d = (s) => { s = s.replace(/-/g, '+').replace(/_/g, '/'); while (s.length % 4) s += '='; return Uint8Array.from(atob(s), (c) => c.charCodeAt(0)); }; | |
| async function cmxKeyOk(k, app, online) { | |
| const [tag, body, sig] = k.split('.'); | |
| let p; | |
| try { p = JSON.parse(new TextDecoder().decode(b64d(body))); } catch { return false; } | |
| if (!p || p.a !== app) return false; | |
| try { | |
| const key = await crypto.subtle.importKey('raw', b64d(CMX_PUB), { name: 'Ed25519' }, false, ['verify']); | |
| if (await crypto.subtle.verify({ name: 'Ed25519' }, key, b64d(sig), new TextEncoder().encode(tag + '.' + body)) && (!p.x || p.x * 1000 > Date.now())) return true; | |
| } catch { /* no Ed25519 here: online check below */ } | |
| return p.c ? online(p.c) : false; | |
| } | |
| async function check(code) { | |
| if (/^cmxk1\./.test(code)) return cmxKeyOk(code, `${cfg.game}-skins`, checkOnline); | |
| return checkOnline(code); | |
| } | |
| async function checkOnline(code) { | |
| try { | |
| const r = await fetch(`${DATA}/unlock/${cfg.game}-skins?json=1&session_id=${encodeURIComponent(code)}`); | |
| const j = await r.json(); | |
| return j && typeof j.pro === 'boolean' ? j.pro : null; | |
| } catch { return null; } | |
| } | |
| export async function unlock(code) { | |
| const ok = await check(code); | |
| if (ok) { | |
| state = store(key(), { code, at: new Date().toISOString() }); | |
| count(cfg.game, 'pro', 'skins-unlocked'); | |
| toast(`${cfg.name} Dice & Table Pack is on. New dice, tables and win emotes are yours!`, 3500); | |
| emit(); render(); | |
| } else if (ok === false) toast('That code is not a Dice & Table Pack order for this game.', 3500); | |
| else toast('Could not reach the unlock check. Try again in a minute.', 3500); | |
| return ok; | |
| } | |
| /** Call first: game id, display name, skin count, Gumroad URL. Reads ?unlock=skins#cmx-pro=<code> after checkout. */ | |
| export function capture(options) { | |
| cfg = { ...cfg, ...options }; | |
| state = store(key()); | |
| const q = new URLSearchParams(location.search); | |
| const m = /[#&]cmx-key=([^&]+)/.exec(location.hash || '') || /[#&]cmx-pro=([^&]+)/.exec(location.hash || ''); | |
| if (q.get('unlock') === 'skins' && m) { | |
| const code = decodeURIComponent(m[1]); | |
| q.delete('unlock'); | |
| history.replaceState(null, '', location.pathname + (q.toString() ? `?${q}` : '')); | |
| if (CODE.test(code)) unlock(code); | |
| } | |
| } | |
| const buyUrl = (from) => `${DATA}/buy/st-${cfg.game}-skins-pack?s=game-${cfg.game}${from ? `-${from}` : ''}`; | |
| function dialog() { | |
| let d = document.getElementById('skinpack'); | |
| if (!d) { | |
| d = document.createElement('dialog'); d.id = 'skinpack'; d.className = 'funpass'; | |
| document.body.appendChild(d); | |
| d.addEventListener('click', (e) => { if (e.target === d || e.target.closest('[data-close]')) d.close(); }); | |
| } | |
| return d; | |
| } | |
| function render() { | |
| const d = dialog(); | |
| const prev = (cfg.preview || []).map((s) => `<span class="sp-dot" style="background:${s}"></span>`).join(''); | |
| if (owned()) { | |
| d.innerHTML = `<div class="fp"><button class="fp-x" data-close aria-label="Close">×</button><p class="fp-kick">${cfg.name} Dice & Table Pack</p><h2>Your Dice & Table Pack is on. Thank you!</h2> | |
| <p>Pick dice, tables and emotes under STYLE on the home screen.</p><p class="fp-small">Your code (paste it on another device):</p><code class="fp-code">${state.code}</code></div>`; | |
| return; | |
| } | |
| d.innerHTML = `<div class="fp"><button class="fp-x" data-close aria-label="Close">×</button><p class="fp-kick">${cfg.name} Dice & Table Pack</p> | |
| <h2>${cfg.title || 'Dice & Table Pack'}, ${cfg.price} once</h2><p class="sp-row">${prev}</p> | |
| <ul class="fp-perks">${(cfg.perks || []).map((p) => `<li>${p}</li>`).join('')}<li>Cosmetic only: same dice odds and chips for everyone</li><li>Pay once, keep forever, on any device with your code</li></ul> | |
| <p class="fp-row"><a class="btn pass" href="${buyUrl('')}" rel="nofollow" data-buy>Get the Dice & Table Pack: ${cfg.price}</a>${cfg.gumroad ? ` <a class="btn ghost sm" href="${cfg.gumroad}" rel="nofollow noopener" target="_blank" data-gum>or on Gumroad</a>` : ''}</p> | |
| <p class="fp-small">Secure Stripe checkout · the skins turn on as soon as you pay · 14-day promise: if it doesn't work as described, we fix it or refund you (<a href="https://cybermaxtools.com/terms#payments" target="_blank" rel="noopener">terms</a>). The <b>Fun Pass</b> is a separate pass for every game's archive and themes.</p> | |
| <details><summary>Already bought it?</summary><form class="fp-form"><input aria-label="Order code" autocomplete="off" placeholder="Receipt code (cs_live_…) or Gumroad licence key"><button class="btn sm" type="submit">Turn on</button></form></details></div>`; | |
| d.querySelector('.fp-form').addEventListener('submit', (e) => { | |
| e.preventDefault(); | |
| const c = e.target.querySelector('input').value.trim(); | |
| if (CODE.test(c)) unlock(c); else toast('Paste the code from your receipt page (cs_live_…) or your Gumroad licence key.', 3500); | |
| }); | |
| d.querySelector('[data-buy]').addEventListener('click', () => count(cfg.game, 'cta', 'skins-buy')); | |
| d.querySelector('[data-gum]')?.addEventListener('click', () => count(cfg.game, 'cta', 'skins-gumroad')); | |
| } | |
| export function open(from = 'button') { | |
| render(); | |
| const d = dialog(); | |
| if (d.showModal) d.showModal(); else d.setAttribute('open', ''); | |
| count(cfg.game, 'cta', `skins-open-${from}`); | |
| } | |
| // Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to the | |
| // Stripe/Polar checkout (static map https://cybermaxtools.com/store/buy-direct.json); the click is counted by a beacon. | |
| (() => { | |
| if (typeof document === 'undefined' || window.__cmxBd) return; | |
| window.__cmxBd = 1; | |
| let MAP = null; | |
| try { MAP = JSON.parse(sessionStorage.getItem('cmx-bd') || 'null'); } catch { /* none */ } | |
| if (!MAP) fetch('https://cybermaxtools.com/store/buy-direct.json').then((r) => r.json()).then((j) => { MAP = j; try { sessionStorage.setItem('cmx-bd', JSON.stringify(j)); } catch { /* full */ } }).catch(() => {}); | |
| document.addEventListener('click', (e) => { | |
| const a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]'); | |
| if (!a || !MAP || !MAP.offers) return; | |
| try { | |
| const u = new URL(a.href); | |
| const k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname); | |
| const t = k && MAP.offers[k[1]]; | |
| if (!t) return; | |
| const s = String(u.searchParams.get('s') || 'unknown').toLowerCase().replace(/[^a-z0-9-]/g, '').slice(0, 80) || 'unknown'; | |
| a.href = t.split(MAP.ph).join(s); | |
| if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? '&' : '?') + 'b=1'); | |
| } catch { /* keep the counted link */ } | |
| }, true); | |
| })(); | |