From 7175ab0fddfcfc892aac60d271bbcad1661d4063 Mon Sep 17 00:00:00 2001 From: Franklin Yu Date: Mon, 3 Jun 2024 08:37:26 -0700 Subject: [PATCH] feat(route): add Bugzilla (#15798) --- lib/routes/bugzilla/bug.ts | 58 ++++++++++++++++++++++++++++++++ lib/routes/bugzilla/namespace.ts | 11 ++++++ 2 files changed, 69 insertions(+) create mode 100644 lib/routes/bugzilla/bug.ts create mode 100644 lib/routes/bugzilla/namespace.ts diff --git a/lib/routes/bugzilla/bug.ts b/lib/routes/bugzilla/bug.ts new file mode 100644 index 00000000000000..202ccb64802387 --- /dev/null +++ b/lib/routes/bugzilla/bug.ts @@ -0,0 +1,58 @@ +import { load } from 'cheerio'; +import { Context } from 'hono'; +import InvalidParameterError from '@/errors/types/invalid-parameter'; +import { Data, DataItem, Route } from '@/types'; +import ofetch from '@/utils/ofetch'; +import { parseDate } from '@/utils/parse-date'; + +const INSTANCES = new Map([ + ['apache', 'bz.apache.org/bugzilla'], + ['apache.ooo', 'bz.apache.org/ooo'], // Apache OpenOffice + ['apache.SpamAssassin', 'bz.apache.org/SpamAssassin'], + ['mozilla', 'bugzilla.mozilla.org'], + ['webkit', 'bugs.webkit.org'], +]); + +async function handler(ctx: Context): Promise { + const { site, bugId } = ctx.req.param(); + if (!INSTANCES.has(site)) { + throw new InvalidParameterError(`unknown site: ${site}`); + } + const link = `https://${INSTANCES.get(site)}/show_bug.cgi?id=${bugId}`; + const $ = load(await ofetch(`${link}&ctype=xml`)); + const items = $('long_desc').map((index, rawItem) => { + const $ = load(rawItem, null, false); + return { + title: `comment #${$('commentid').text()}`, + link: `${link}#c${index}`, + description: $('thetext').text(), + pubDate: parseDate($('bug_when').text()), + author: $('who').attr('name'), + } as DataItem; + }); + return { title: $('short_desc').text(), link, item: items.toArray() }; +} + +function markdownFrom(instances: Map, separator: string = ', '): string { + return [...instances.entries()].map(([k, v]) => `[\`${k}\`](https://${v})`).join(separator); +} + +export const route: Route = { + path: '/bug/:site/:bugId', + name: 'bugs', + maintainers: ['FranklinYu'], + handler, + example: '/bug/webkit/251528', + parameters: { + site: 'site identifier', + bugId: 'numeric identifier of the bug in the site', + }, + description: `Supported site identifiers: ${markdownFrom(INSTANCES)}.`, + categories: ['programming'], + + // Radar is infeasible, because it needs access to URL parameters. + zh: { + name: 'bugs', + description: `支持的站点标识符:${markdownFrom(INSTANCES, '、')}。`, + }, +}; diff --git a/lib/routes/bugzilla/namespace.ts b/lib/routes/bugzilla/namespace.ts new file mode 100644 index 00000000000000..70ac839cb0f7d8 --- /dev/null +++ b/lib/routes/bugzilla/namespace.ts @@ -0,0 +1,11 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: 'Bugzilla', + url: 'bugzilla.org', + description: 'Bugzilla instances hosted by organizations.', + zh: { + name: 'Bugzilla', + description: '各组织自建的Bugzilla实例。', + }, +};