← back to Delivery Address Skill

scripts/lib.js

83 lines

// Shared helpers for delivery-address scripts. Zero deps beyond playwright.
const fs = require('fs');
const path = require('path');

const PLATFORMS = {
  ubereats: {
    home: 'https://www.ubereats.com/',
    login: 'https://auth.uber.com/v2/?next_url=https%3A%2F%2Fwww.ubereats.com%2Flogin-redirect',
    match: 'uber.com',
    emailField: '#PHONE_NUMBER_or_EMAIL_ADDRESS',
    emailSubmit: '#forward-button',
  },
  doordash: {
    home: 'https://www.doordash.com/',
    login: 'https://identity.doordash.com/auth',
    match: 'doordash.com',
    emailField: 'input[type="email"]',
    emailSubmit: 'button[type="submit"]',
  },
  instacart: {
    home: 'https://www.instacart.com/',
    login: 'https://www.instacart.com/login',
    match: 'instacart.com',
    emailField: 'input[type="email"]',
    emailSubmit: 'button[type="submit"]',
  },
};

function parseArgs(argv) {
  const args = {};
  for (let i = 2; i < argv.length; i++) {
    const m = argv[i].match(/^--([a-z-]+)$/);
    if (m) { args[m[1]] = argv[i + 1]; i++; }
  }
  return args;
}

function loadConfig() {
  const p = path.join(__dirname, '..', 'config.json');
  return fs.existsSync(p) ? JSON.parse(fs.readFileSync(p, 'utf8')) : {};
}

function platform(name) {
  const p = PLATFORMS[name];
  if (!p) { console.error(`Unknown platform "${name}". One of: ${Object.keys(PLATFORMS).join(', ')}`); process.exit(2); }
  return p;
}

function sessionDir(cfg, args) {
  const dir = args['session-dir'] || cfg.session_dir ||
    path.join(__dirname, '..', 'sessions', `${(args.user || cfg.user_email || 'user').replace(/[@.]/g, '_')}-${args.platform || 'session'}`);
  fs.mkdirSync(dir, { recursive: true });
  return dir;
}

// HARD RULE: select the tab by URL substring, never pages()[0] — other
// automations share the browser (Tesla tab hijacked slot 0 on 2026-08-02).
async function findTab(port, match) {
  const { chromium } = require('playwright');
  const browser = await chromium.connectOverCDP(`http://127.0.0.1:${port}`);
  const pages = browser.contexts()[0].pages();
  const page = pages.find(p => p.url().includes(match));
  if (!page) {
    console.error(`NO TAB matching "${match}". Open tabs: ${pages.map(p => p.url()).join(' | ')}`);
    process.exit(2);
  }
  return { browser, page };
}

async function dumpState(page, dir, label) {
  const shot = path.join(dir, `${label}-${Date.now()}.png`);
  await page.screenshot({ path: shot }).catch(() => {});
  console.log('URL:', page.url());
  console.log('SHOT:', shot);
  console.log(await page.evaluate(() => document.body.innerText.slice(0, 1000)));
  const inputs = await page.evaluate(() =>
    Array.from(document.querySelectorAll('input')).map(i =>
      ({ t: i.type, ph: i.placeholder, val: i.value ? '<set>' : '', vis: !!i.offsetParent })));
  console.log('INPUTS:', JSON.stringify(inputs.filter(i => i.vis)));
}

module.exports = { PLATFORMS, parseArgs, loadConfig, platform, sessionDir, findTab, dumpState };