import { URL } from "node:url"; import { getJson, getResponse } from "../misc/fetch.js"; import config from "../config/index.js"; import { XMLParser } from "fast-xml-parser"; export default async function(query) { const hostMetaUrl = queryToHostMetaUrl(query); const webFingerTemplate = await hostMetaToWebFingerTemplate(hostMetaUrl) ?? queryToWebFingerTemplate(query); const url = genWebFingerUrl(query, webFingerTemplate); return await getJson(url, "application/jrd+json, application/json"); } async function hostMetaToWebFingerTemplate(url) { try { const res = await getResponse({ url, method: "GET", headers: Object.assign({ "User-Agent": config.userAgent, Accept: "application/xrd+xml" }, {}), timeout: 10000 }); const options = { ignoreAttributes: false, isArray: (_name, jpath)=>jpath === 'XRD.Link' }; const parser = new XMLParser(options); const hostMeta = parser.parse(await res.text()); const template = hostMeta['XRD']['Link'].filter((p)=>p['@_rel'] === 'lrdd')[0]['@_template']; return template.indexOf('{uri}') < 0 ? null : template; } catch { return null; } } function queryToWebFingerTemplate(query) { if (query.match(/^https?:\/\//)) { const u = new URL(query); return `${u.protocol}//${u.hostname}/.well-known/webfinger?resource={uri}`; } const m = query.match(/^([^@]+)@(.*)/); if (m) { const hostname = m[2]; return `https://${hostname}/.well-known/webfinger?resource={uri}`; } throw new Error(`Invalid query (${query})`); } function queryToHostMetaUrl(query) { if (query.match(/^https?:\/\//)) { const u = new URL(query); return `${u.protocol}//${u.hostname}/.well-known/host-meta`; } const m = query.match(/^([^@]+)@(.*)/); if (m) { const hostname = m[2]; return `https://${hostname}/.well-known/host-meta`; } throw new Error(`Invalid query (${query})`); } function genWebFingerUrl(query, webFingerTemplate) { if (webFingerTemplate.indexOf('{uri}') < 0) throw new Error(`Invalid webFingerUrl: ${webFingerTemplate}`); if (query.match(/^https?:\/\//)) { return webFingerTemplate.replace('{uri}', encodeURIComponent(query)); } const m = query.match(/^([^@]+)@(.*)/); if (m) { return webFingerTemplate.replace('{uri}', encodeURIComponent(`acct:${query}`)); } throw new Error(`Invalid query (${query})`); }