yes
tcmts.dev.devenv.yes · #lntlxghk · mjs file
// Saying yes on the PDS's own sign-in and consent pages, in headless Chrome: what a person does when tcm sends them to
// sign in. As $BROWSER, it opens the URL it's given; visitor.mjs uses sayYes for a visitor signing in on the registry.
import fs from 'node:fs'
import puppeteer from 'puppeteer-core'
export const CHROME = process.env.CHROME ?? ['/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', '/usr/bin/google-chrome', '/usr/bin/chromium'].find((p) => fs.existsSync(p))
const env = () => JSON.parse(fs.readFileSync(new URL('./env.json', import.meta.url), 'utf8'))
const shots = new URL('./shots/', import.meta.url).pathname
fs.mkdirSync(shots, { recursive: true })
/** On the PDS's authorize page: sign in with the account's password, say yes, and wait until it's sent back. */
export async function sayYes(p, tag) {
const pds = env().pds
await p.waitForSelector('input[name=password]', { timeout: 30_000 })
const id = await p.$eval('input[name=identifier]', (e) => e.value)
const who = env().accounts[id.replace(/^@/, '')]
if (!who) throw new Error(`no password for ${id}`)
await p.type('input[name=password]', who.password)
await p.click('button[type=submit]')
// the consent page: what it asks for, as the PDS says it
const accept = () => [...document.querySelectorAll('button')].some((b) => /^(Accept|Authorize|Allow)/i.test(b.textContent.trim()))
await p.waitForFunction(accept, { timeout: 30_000 })
fs.writeFileSync(`${shots}${tag}-consent.txt`, await p.evaluate(() => document.body.innerText))
await p.screenshot({ path: `${shots}${tag}-consent.png`, fullPage: true })
await p.evaluate(() => [...document.querySelectorAll('button')].find((b) => /^(Accept|Authorize|Allow)/i.test(b.textContent.trim())).click())
await p.waitForFunction((pds) => !location.href.startsWith(pds), { timeout: 30_000 }, pds)
}
if (import.meta.url === `file://${fs.realpathSync(process.argv[1])}`) {
const b = await puppeteer.launch({ executablePath: CHROME, headless: true })
try {
const p = await b.newPage()
await p.goto(process.argv[2], { waitUntil: 'networkidle0' })
await sayYes(p, `cli-${Date.now()}`)
await new Promise((r) => setTimeout(r, 1000))
} finally {
await b.close()
}
}
used by