{"version":3,"sources":["push-core.mjs"],"sourcesContent":["// PUSH NOTIFICATIONS: the rules both ends must agree on (the owner's decisions, Oct 8).\n//\n// Byte-identical in public/ and functions/lib/ (generate-version-hash.js holds them equal). The page reads it to draw\n// Settings → Notifications and to decide whether this device is one to ask on; the functions read it to validate what\n// Settings sends and to decide whether an event is worth a notification. Pure, so tests/push.test.mjs can pin it.\n//\n// Plain Web Push with the game's own VAPID keys (functions/notify.js), never Firebase Cloud Messaging.\n\n// THE KINDS, WITH THEIR DEFAULTS. Off means a player gets nothing of that kind on any device; the master switch in\n// Settings is per device and lives in the browser's own subscription, not here.\nexport const PUSH_KINDS = Object.freeze({\n  outbid:    Object.freeze({ def: true,  label: 'Someone outbids you on an auction' }),\n  auction:   Object.freeze({ def: true,  label: 'An auction you are in ends' }),\n  sold:      Object.freeze({ def: true,  label: 'Someone buys your world' }),\n  friendReq: Object.freeze({ def: true,  label: 'Friend requests, and requests accepted' }),\n  friendOn:  Object.freeze({ def: false, label: 'A friend starts playing (once a day each)' }),\n  visitor:   Object.freeze({ def: true,  label: 'A friend or builder lands on your world' }),\n  builder:   Object.freeze({ def: true,  label: 'You are made a builder on a world' }),\n  support:   Object.freeze({ def: true,  label: 'Kubicor support replies to you' }),\n  invite:    Object.freeze({ def: true,  label: 'Someone joins with your invite' }),\n  // A VENDING MACHINE TRADED while its owner was away (the owner's decisions, Oct 11): one push an hour at most, the\n  // sales and purchases in it summed (functions/machines.js). In the game the same trade is a toast (shopNotice).\n  shop:      Object.freeze({ def: true,  label: 'Your vending machines sell or buy (once an hour at most)' }),\n  // A GIFT OF TOKENS (the owner's note, Oct 11: gift purchases): a friend's gift landed on your balance, or a gift you\n  // sent had to become a code (functions/payments.js). In the game the same news is a toast (app.js noteGiftNotice).\n  gift:      Object.freeze({ def: true,  label: 'Someone sends you tokens as a gift' }),\n  // A FRIEND SHARES WHERE THEY ARE (the owner's request, Oct 12, decision 4: \"away friends get a push\"): its tap opens the\n  // game straight into the Scout on the spot (locShareUrl). In the game the same invite is a toast (app.js noteLocInvites),\n  // from the invite the share leaves on the friend's own user document (functions/loc-share.js). No email.\n  locShare:  Object.freeze({ def: true,  label: 'A friend shares their location with you' }),\n  // YOUR VESSEL WAS MOVED (vessels phase 3, Oct 12: \"the owner is told\"): a station or a ship round an asteroid or a comet\n  // whose pass ended is parked round the nearest world (functions/ships.js). In the game it is a toast (vesselNotice).\n  vessel:    Object.freeze({ def: true,  label: 'Your station or ship is moved off a passing asteroid or comet' }),\n  // A TRAVEL WINDOW OPENS (the owner's Travel Routes picks, Oct 28, B5): the card's Remind me, sent when the trip it named is at its\n  // cheapest (functions/travel-remind.js). In the game the card's window clock says the same.\n  window:    Object.freeze({ def: true,  label: 'A travel window you asked about opens' }),\n  // MESSAGES (the owner's Chat and DMs picks, Oct 27, C25): a DM or a group invite, a group line that names you, and every\n  // group line (off until asked for); at most one a conversation every ten minutes (functions/chat.js), never for a request.\n  // Its tap opens the game with that conversation (chatUrl). In the game the same line is a toast (app.js chatToast).\n  chatDm:      Object.freeze({ def: true,  label: 'Messages to you, and group invites' }),\n  chatMention: Object.freeze({ def: true,  label: 'Group lines that name you (@name)' }),\n  chatGroup:   Object.freeze({ def: false, label: 'Every line in your groups' }),\n});\nexport const PUSH_KIND_IDS = Object.freeze(Object.keys(PUSH_KINDS));\n// A visit is announced the first time that player lands on that world, ever, or every time (at most once an hour each).\nexport const VISITOR_MODES = Object.freeze(['first', 'every']);\nexport const VISITOR_DEFAULT = 'first';\nexport const VISIT_EVERY_MS = 3600e3;\n// A friend's first session of the day, and a session is a return after this long away.\nexport const SESSION_GAP_MS = 30 * 60e3;\nexport const MAX_DEVICES = 10;           // subscriptions kept per account; the oldest goes when an eleventh arrives\n\n// The stored preferences, read with every default filled in. Anything unrecognised is ignored rather than trusted.\nexport function prefsOf(raw) {\n  const r = (raw && typeof raw === 'object') ? raw : {};\n  const out = {};\n  for (const k of PUSH_KIND_IDS) out[k] = typeof r[k] === 'boolean' ? r[k] : PUSH_KINDS[k].def;\n  out.visitorMode = VISITOR_MODES.includes(r.visitorMode) ? r.visitorMode : VISITOR_DEFAULT;\n  return out;\n}\n// What is wrong with a change Settings sends, or null. Only known kinds, only booleans, and the one choice.\nexport function prefsProblem(p) {\n  if (!p || typeof p !== 'object' || Array.isArray(p)) return 'Send the preferences as an object.';\n  const keys = Object.keys(p);\n  if (!keys.length || keys.length > PUSH_KIND_IDS.length + 1) return 'Nothing to change.';\n  for (const k of keys) {\n    if (k === 'visitorMode') { if (!VISITOR_MODES.includes(p[k])) return 'Visitors: first time only, or every time.'; continue; }\n    if (!PUSH_KINDS[k]) return 'Not a kind of notification: ' + String(k).slice(0, 20);\n    if (typeof p[k] !== 'boolean') return 'Each kind is on or off.';\n  }\n  return null;\n}\nexport const mergePrefs = (current, patch) => prefsOf({ ...prefsOf(current), ...(patch || {}) });\n\n// WHERE THIS PAGE IS RUNNING: an installed app, a phone or tablet's browser, or a desktop browser. Asked of the\n// browser's own reports; iPadOS calls itself a Mac, and gives itself away by its touch points.\nexport function deviceKind({ ua = '', maxTouchPoints = 0, standalone = false } = {}) {\n  if (standalone) return 'app';\n  const s = String(ua);\n  if (/Android|iPhone|iPad|iPod|Mobile|Silk|Kindle|Opera Mini|IEMobile/i.test(s)) return 'mobile';\n  if (/Macintosh/.test(s) && Number(maxTouchPoints) > 1) return 'mobile';\n  return 'desktop';\n}\n// The game asks to notify only where it can do so properly: a desktop browser or the installed app. A phone's browser\n// tab is asked to install instead (the first setup step).\nexport const offersPush = (kind) => kind === 'desktop' || kind === 'app';\nexport const wantsInstallStep = (kind) => kind === 'mobile';\n// Which instructions the install step shows.\nexport function installGuide(ua, maxTouchPoints = 0) {\n  const s = String(ua || '');\n  if (/iPhone|iPad|iPod/i.test(s) || (/Macintosh/.test(s) && Number(maxTouchPoints) > 1)) return 'ios';\n  if (/Android/i.test(s)) return 'android';\n  return 'other';\n}\n\n// THE PUSH SERVICES A SUBSCRIPTION MAY POINT AT. The server POSTs to whatever endpoint is stored, so an endpoint is\n// accepted only on the hosts the browsers' own push services use: anything else would let a caller aim the\n// functions at an address of their choosing.\nconst PUSH_HOSTS = [/^fcm\\.googleapis\\.com$/, /^android\\.googleapis\\.com$/, /^([a-z0-9-]+\\.)*push\\.services\\.mozilla\\.com$/,\n                    /^([a-z0-9-]+\\.)*notify\\.windows\\.com$/, /^([a-z0-9-]+\\.)*push\\.apple\\.com$/];\nexport function endpointOk(url) {\n  if (typeof url !== 'string' || url.length > 1024) return false;\n  let u; try { u = new URL(url); } catch (e) { return false; }\n  return u.protocol === 'https:' && !u.port && !u.username && PUSH_HOSTS.some((re) => re.test(u.hostname));\n}\nconst B64U = /^[A-Za-z0-9_-]+=*$/;\n// A browser subscription as PushSubscription.toJSON() gives it, checked. Null, or { endpoint, keys }.\nexport function subscriptionOf(sub) {\n  if (!sub || typeof sub !== 'object') return null;\n  const k = sub.keys || {};\n  if (!endpointOk(sub.endpoint)) return null;\n  if (typeof k.p256dh !== 'string' || k.p256dh.length < 40 || k.p256dh.length > 140 || !B64U.test(k.p256dh)) return null;\n  if (typeof k.auth !== 'string' || k.auth.length < 8 || k.auth.length > 64 || !B64U.test(k.auth)) return null;\n  return { endpoint: sub.endpoint, keys: { p256dh: k.p256dh, auth: k.auth } };\n}\n// A device's name in the list, as the page describes itself: \"Chrome on Mac\", \"Safari on iPhone (app)\".\nexport function deviceLabel(ua, kind) {\n  const s = String(ua || '');\n  const browser = /Edg\\//.test(s) ? 'Edge' : /OPR\\//.test(s) ? 'Opera' : /Firefox\\//.test(s) ? 'Firefox'\n    : /SamsungBrowser/.test(s) ? 'Samsung Internet' : /Chrome\\/|CriOS/.test(s) ? 'Chrome' : /Safari\\//.test(s) ? 'Safari' : 'Browser';\n  const os = /iPhone/.test(s) ? 'iPhone' : /iPad/.test(s) || (/Macintosh/.test(s) && kind !== 'desktop') ? 'iPad'\n    : /Android/.test(s) ? 'Android' : /Mac OS X|Macintosh/.test(s) ? 'Mac' : /Windows/.test(s) ? 'Windows'\n    : /CrOS/.test(s) ? 'ChromeOS' : /Linux/.test(s) ? 'Linux' : 'this device';\n  return browser + ' on ' + os + (kind === 'app' ? ' (app)' : '');\n}\nexport const cleanLabel = (s) => String(s || '').replace(/[\\u0000-\\u001f<>]/g, '').trim().slice(0, 60) || 'A device';\n\n// WHERE A NOTIFICATION TAKES YOU, as a path on this site. Built here and read back here, so the server cannot write a\n// link the page does not know how to open.\nconst ADDR = /^[0-9]+[ab]?(\\.[0-9]+[ab]?)*$/;\nexport const worldUrl = (addr) => ADDR.test(String(addr || '')) ? '/?pos=' + addr : '/';\nexport const marketUrl = (addr) => ADDR.test(String(addr || '')) ? '/?tab=marketplace&mkt=' + addr : '/?tab=marketplace';\nexport const FRIENDS_URL = '/?tab=friends';\nexport const SUPPORT_URL = '/?tab=support';\n// A FRIEND'S SHARED LOCATION (loc-share.mjs): the world it is on, which a new window opens in Scout as any ?pos link does,\n// and the invite, which tells the game that this Scout is that invite's (so its Travel & land lands on the shared spot).\nconst LOC_SHARE_ID = /^[A-Za-z0-9]{16,40}$/;\nexport const locShareUrl = (id, addr) => !LOC_SHARE_ID.test(String(id || '')) ? '/'\n  : '/?' + (ADDR.test(String(addr || '')) ? 'pos=' + addr + '&' : '') + 'locshare=' + id;\n// A path on this site, or the front page: never another origin, never a scheme.\nexport const safePath = (url) => (typeof url === 'string' && /^\\/(?![\\/\\\\])[\\x21-\\x7e]{0,300}$/.test(url)) ? url : '/';\n// …and what a path means to an open game: the world to scout, or the panel to open.\nexport function routeOf(url) {\n  const path = safePath(url), at = path.indexOf('?');\n  let q; try { q = new URLSearchParams(at < 0 ? '' : path.slice(at + 1)); } catch (e) { return { kind: 'home' }; }\n  const pos = q.get('pos'), tab = q.get('tab'), mkt = q.get('mkt'), ls = q.get('locshare'), chat = q.get('chat');\n  if (ls && LOC_SHARE_ID.test(ls)) return { kind: 'locShare', id: ls, addr: pos && ADDR.test(pos) ? pos : null };\n  if (chat && /^(d_[A-Za-z0-9]{10,64}_[A-Za-z0-9]{10,64}|g_[A-Za-z0-9]{16,40})$/.test(chat)) return { kind: 'chat', cid: chat };   // a message's (chat-rules chatUrl)\n  if (pos && ADDR.test(pos)) return { kind: 'world', addr: pos };\n  if (tab === 'marketplace') return { kind: 'market', addr: mkt && ADDR.test(mkt) ? mkt : null };\n  if (tab === 'friends') return { kind: 'friends' };\n  if (tab === 'support') return { kind: 'support' };\n  return { kind: 'home' };\n}\n// The tag a notification replaces itself by: the same event, told twice, is one notification.\nconst cleanTag = (s) => String(s).replace(/[^A-Za-z0-9_.-]/g, '_').slice(0, 64);\nexport const pushTag = (kind, key) => cleanTag(String(kind) + '-' + String(key == null ? '' : key));\n// What goes over the wire: short, plain, and only a path on this site.\nexport function pushPayload(kind, { title, body, url, tag } = {}) {\n  const clip = (s, n) => String(s == null ? '' : s).replace(/[\\u0000-\\u001f]/g, ' ').slice(0, n);\n  return { kind: String(kind), title: clip(title, 80) || 'Kubicor', body: clip(body, 240), url: safePath(url),\n           tag: cleanTag(tag || kind) };\n}\n// The world as a notification names it: its name, else its address.\nexport const worldName = (name, addr) => String(name || '').trim().slice(0, 40) || String(addr || 'a world');\n// \"ends in 3h 20m\".\nexport function timeLeft(ms) {\n  const m = Math.max(0, Math.round((Number(ms) || 0) / 60e3));\n  if (m < 1) return 'under a minute';\n  if (m < 60) return m + 'm';\n  const h = Math.floor(m / 60);\n  if (h < 24) return h + 'h' + (m % 60 ? ' ' + (m % 60) + 'm' : '');\n  const d = Math.floor(h / 24);\n  return d + 'd' + (h % 24 ? ' ' + (h % 24) + 'h' : '');\n}\n\n// A FRIEND STARTED PLAYING: the first play report after a gap, and not twice in one (UTC) day for the same player.\n// `lastActiveMs` is when they were last counted playing; `toldDay` the day this was last announced.\nexport const friendOnDue = (lastActiveMs, toldDay, nowMs) =>\n  (!(lastActiveMs > 0) || nowMs - lastActiveMs >= SESSION_GAP_MS) && toldDay !== new Date(nowMs).toISOString().slice(0, 10);\n// A VISIT: whether this landing is announced, given the record of that player on that world (null for never) and the\n// owner's choice. A landing is always recorded, so \"first time only\" means the first time ever, notified or not.\nexport function visitAnnounced(seen, mode, nowMs) {\n  if (!seen) return true;\n  if (mode !== 'every') return false;\n  return !(seen.lastNotifiedMs > 0) || nowMs - seen.lastNotifiedMs >= VISIT_EVERY_MS;\n}\n// Kinds the open game already tells its player about by itself (the outbid notice, the support reply, the friends\n// listener): a push for one of those, arriving while the game is in front, is not shown a second time. A shared location\n// is toasted from the invite on the player's own document (app.js noteLocInvites), with its Scout and Not now.\nexport const SHOWN_IN_GAME = Object.freeze(['outbid', 'support', 'friendReq', 'shop', 'gift', 'locShare', 'chatDm', 'chatMention', 'chatGroup']);   // (messages: the game's own toasts, chatToast)\n"],"mappings":"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","names":[],"file":"push-core.mjs"}