/** * summaly * https://github.com/misskey-dev/summaly */ import { URL } from 'node:url'; import tracer from 'trace-redirect'; export * from './iplugin.js'; import general from './general.js'; import { setAgent } from './utils/got.js'; import { plugins as builtinPlugins } from './plugins/index.js'; export const summalyDefaultOptions = { lang: null, followRedirects: true, plugins: [], }; /** * Summarize an web page */ export const summaly = async (url, options) => { if (options?.agent) setAgent(options.agent); const opts = Object.assign(summalyDefaultOptions, options); const plugins = builtinPlugins.concat(opts.plugins || []); let actualUrl = url; if (opts.followRedirects) { // .catch(() => url)にすればいいけど、jestにtrace-redirectを食わせるのが面倒なのでtry-catch try { actualUrl = await tracer(url); } catch (e) { actualUrl = url; } } const _url = new URL(actualUrl); // Find matching plugin const match = plugins.filter(plugin => plugin.test(_url))[0]; // Get summary const scrapingOptions = { lang: opts.lang, userAgent: opts.userAgent, responseTimeout: opts.responseTimeout, operationTimeout: opts.operationTimeout, contentLengthLimit: opts.contentLengthLimit, contentLengthRequired: opts.contentLengthRequired, }; // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition const summary = await (match ? match.summarize : general)(_url, scrapingOptions); if (summary == null) { throw new Error('failed summarize'); } return Object.assign(summary, { url: actualUrl, }); }; export default function (fastify, options, done) { fastify.get('/', async (req, reply) => { const url = req.query.url; // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (url == null) { return reply.status(400).send({ error: 'url is required', }); } try { const summary = await summaly(url, { lang: req.query.lang, followRedirects: false, ...options, }); return summary; } catch (e) { return reply.status(500).send({ error: e, }); } }); done(); }