aboutsummaryrefslogtreecommitdiffstats
path: root/db/models/orders.js
diff options
context:
space:
mode:
Diffstat (limited to 'db/models/orders.js')
0 files changed, 0 insertions, 0 deletions
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96































































































                                                                                                                                                                                                                      
// Notifications: a custom-emoji reaction (NIP-30, ":peepoClap:" with an
// emoji tag) reads "reacted" plus its picture — it showed the bare
// :peepoClap: text, because the row kept the content and not the tag.
// A row saved before that is healed when the relay hands the reaction again.
// Run: bun tools/notif-custom-emoji-test.js
import puppeteer from './puppeteer.js';
import { cacheKeyFor } from '../src/wallet.js';
import { generateSecretKey, getPublicKey, finalizeEvent } from 'nostr-tools/pure';
import { privateKeyFromSeedWords } from 'nostr-tools/nip06';
import { buildHtml } from '../build.js';
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
let ok = true;
const check = (n, c, d = '') => { console.log(` ${c ? '✓' : '✗'} ${n}${d ? ' — ' + d : ''}`); if (!c) ok = false; };
const A = generateSecretKey(), B = generateSecretKey();
const now = Math.floor(Date.now() / 1000);
const PNG = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==', 'base64');
const html = await buildHtml({ minify: true, pwa: false });
const server = Bun.serve({ port: 5313, fetch: (req) => {
  const path = new URL(req.url).pathname;
  if (path.endsWith('.png')) return new Response(PNG, { headers: { 'content-type': 'image/png' } });
  if (path.startsWith('/punks') || path === '/verify-worker.js') return new Response(Bun.file('dist' + path));
  return new Response(html, { headers: { 'content-type': 'text/html' } });
} });
const browser = await puppeteer.launch({ executablePath: '/usr/bin/google-chrome', headless: 'new', args: ['--no-sandbox'] });
const page = await browser.newPage();
const errs = [];
page.on('pageerror', (e) => errs.push(String(e)));
const click = (t) => page.evaluate((x) => { const e = [...document.querySelectorAll('button')].find((n) => n.textContent.trim().toLowerCase().includes(x)); if (e) { e.click(); return true; } return false; }, t);
const waitText = async (x, ms = 25000) => { for (let i = 0; i < ms / 250; i++) { if ((await page.evaluate(() => document.body.innerText)).toLowerCase().includes(x)) return true; await sleep(250); } return false; };

try {
  await page.setViewport({ width: 390, height: 844 });
  await page.goto('http://localhost:5313/', { waitUntil: 'domcontentloaded' });
  await page.evaluate(() => localStorage.setItem('btc-wallet-network', 'regtest'));
  await page.reload({ waitUntil: 'domcontentloaded' }); await sleep(400);
  await click('create a new wallet'); await sleep(600);
  await page.waitForSelector('.words .w .t');
  const mn = (await page.$$eval('.words .w .t', (l) => l.map((e) => e.textContent.trim()))).join(' ');
  await click('skip verification');
  await waitText('receive', 20000);
  const base = cacheKeyFor(mn + '\n');
  const ME = getPublicKey(privateKeyFromSeedWords(mn));
  const target = 't'.repeat(64);
  const react = (sk, code, ts) => finalizeEvent({ kind: 7, created_at: ts, content: ':' + code + ':',
    tags: [['e', target], ['p', ME], ['emoji', code, 'http://localhost:5313/' + code + '.png']] }, sk);
  const OLD = react(A, 'peepoClap', now - 120); // saved by the old code, as text
  const NEW = react(B, 'aVeryLongShortcodeName', now - 60); // new: arrives from the relay
  await page.evaluateOnNewDocument((evs) => {
    const Real = window.WebSocket;
    window.WebSocket = function (...a) {
      const ws = new Real(...a);
      const send = ws.send.bind(ws);
      ws.send = (data) => {
        try {
          const m = JSON.parse(data);
          if (m[0] === 'REQ') {
            const fs = m.slice(2);
            const hit = evs.filter((ev) => fs.some((f) => (f.kinds || []).includes(7) && (f['#p'] || []).length));
            setTimeout(() => {
              for (const e of hit) ws.dispatchEvent(new MessageEvent('message', { data: JSON.stringify(['EVENT', m[1], e]) }));
              ws.dispatchEvent(new MessageEvent('message', { data: JSON.stringify(['EOSE', m[1]]) }));
            }, 0);
            return;
          }
          if (m[0] === 'EVENT') return;
        } catch {}
        return send(data);
      };
      return ws;
    };
    window.WebSocket.prototype = Real.prototype; Object.assign(window.WebSocket, Real);
  }, [OLD, NEW]);
  await page.evaluate(([k, me, old, target]) => {
    const st = JSON.parse(localStorage.getItem(k + ':messages') || '{}');
    st.notifs = [{ id: old.id, what: 'react', actor: old.pubkey, target, hint: [], emoji: ':peepoClap:', ts: old.created_at }];
    st.notifsPk = me; st.notifsV = 2;
    localStorage.setItem(k + ':messages', JSON.stringify(st));
  }, [base, ME, OLD, target]);
  await page.reload({ waitUntil: 'domcontentloaded' });
  await waitText('receive', 20000);
  await page.evaluate(() => document.querySelector('.app-nav-button[aria-label="Notifications"]')?.click());
  let imgs = [];
  for (let i = 0; i < 60; i++) {
    imgs = await page.evaluate(() => [...document.querySelectorAll('.alert-row img.cemoji')].map((e) => e.getAttribute('alt')));
    if (imgs.length >= 2) break;
    await sleep(250);
  }
  console.log('\n[custom-emoji reactions in Notifications]');
  check('a reaction arriving now shows its picture, whole name kept', imgs.includes(':aVeryLongShortcodeName:'), JSON.stringify(imgs));
  check('a row saved as text gets its picture once the relay hands it again', imgs.includes(':peepoClap:'), JSON.stringify(imgs));
  const txt = await page.evaluate(() => [...document.querySelectorAll('.alert-row')].map((r) => r.innerText).join(' | '));
  check('no bare :shortcode: text left', !/:peepoClap:|:aVeryLong/.test(txt), txt.slice(0, 200));
  check('no page errors', errs.length === 0, errs.slice(0, 2).join(' | '));
} finally { await browser.close(); server.stop(true); }
console.log(ok ? '\n✅ custom-emoji reactions show their pictures' : '\n❌ failed');
process.exit(ok ? 0 : 1);