UNPKG

rsshub

Version:
173 lines (171 loc) • 6.49 kB
import "./esm-shims-CzJ_djXG.mjs"; import { t as config } from "./config-C37vj7VH.mjs"; import "./dist-BInvbO1W.mjs"; import "./logger-Czu8UMNd.mjs"; import { t as ofetch_default } from "./ofetch-BIyrKU3Y.mjs"; import { t as parseDate } from "./parse-date-BrP7mxXf.mjs"; import markdownit from "markdown-it"; //#region lib/routes/github/comments.ts const md = markdownit({ html: true }); const rootUrl = "https://github.com"; const apiUrl = "https://api.github.com"; const typeDict = { issue: { title: "Issue" }, issues: { title: "Issue" }, pull: { title: "Pull request" } }; const route = { path: "/comments/:user/:repo/:number?", categories: ["programming"], example: "/github/comments/DIYgod/RSSHub/8116", parameters: { user: "User / Org name", repo: "Repo name", number: "Issue or pull number (if omitted: all)" }, radar: [{ source: ["github.com/:user/:repo/:type", "github.com/:user/:repo/:type/:number"], target: "/comments/:user/:repo/:number?" }], name: "Issue / Pull Request comments", maintainers: ["TonyRL", "FliegendeWurst"], handler }; async function handler(ctx) { const user = ctx.req.param("user"); const repo = ctx.req.param("repo"); const number = ctx.req.param("number") && Number.isNaN(Number.parseInt(ctx.req.param("number"))) ? 1 : Number.parseInt(ctx.req.param("number")); const limit = ctx.req.query("limit") ? Number.parseInt(ctx.req.query("limit")) : 100; const headers = config.github && config.github.access_token ? { Accept: "application/vnd.github.v3+json", Authorization: `token ${config.github.access_token}` } : { Accept: "application/vnd.github.v3+json" }; return await (Number.isNaN(number) ? allIssues(ctx, user, repo, limit, headers) : singleIssue(ctx, user, repo, number, limit, headers)); } async function allIssues(ctx, user, repo, limit, headers) { const response = await ofetch_default.raw(`${apiUrl}/repos/${user}/${repo}/issues/comments`, { headers, query: { sort: "updated", direction: "desc", per_page: limit } }); const items = response._data.map((item) => { const actor = item.actor?.login ?? item.user?.login ?? "ghost"; const issue = item.issue_url.split("/").at(-1); return { title: `${actor} commented on ${user}/${repo}: ${typeDict[item.html_url.split("/").at(-2)].title} #${issue}`, author: actor, pubDate: parseDate(item.created_at), link: item.html_url, description: item.body ? md.render(item.body) : null }; }); const rateLimit = { limit: Number.parseInt(response.headers.get("x-ratelimit-limit")), remaining: Number.parseInt(response.headers.get("x-ratelimit-remaining")), reset: parseDate(Number.parseInt(response.headers.get("x-ratelimit-reset")) * 1e3), resoure: response.headers.get("x-ratelimit-resource"), used: Number.parseInt(response.headers.get("x-ratelimit-used")) }; const ret = { title: `${user}/${repo}: Issue & Pull request comments`, link: `${rootUrl}/${user}/${repo}`, item: items }; ctx.set("json", { ...ret, rateLimit }); return ret; } async function singleIssue(ctx, user, repo, number, limit, headers) { const response = await ofetch_default.raw(`${apiUrl}/repos/${user}/${repo}/issues/${number}`, { headers }); const issue = response._data; const type = issue.pull_request ? "pull" : "issue"; let timelineResponse = await ofetch_default.raw(issue.timeline_url, { headers, query: { per_page: limit } }); const items = []; const lastUrl = timelineResponse.headers.get("link")?.match(/<(\S+?)>; rel="last"/)?.[1]; if (lastUrl) timelineResponse = await ofetch_default.raw(lastUrl, { headers }); else items.push({ title: `${issue.user.login} created ${user}/${repo}: ${typeDict[type].title} #${issue.number}`, description: issue.body ? md.render(issue.body) : null, author: issue.user.login, pubDate: parseDate(issue.created_at), link: `${issue.html_url}#issue-${issue.id}` }); const timeline = timelineResponse._data; for (const item of timeline) { const actor = item.actor?.login ?? item.user?.login ?? "ghost"; switch (item.event) { case "closed": items.push({ title: `${actor} ${item.event} ${user}/${repo}: ${typeDict[type].title} #${issue.number}`, author: actor, pubDate: parseDate(item.created_at), link: item.url }); break; case "commented": items.push({ title: `${actor} ${item.event} on ${user}/${repo}: ${typeDict[type].title} #${issue.number}`, description: md.render(item.body), author: actor, pubDate: parseDate(item.created_at), link: item.html_url }); break; case "cross-referenced": items.push({ title: `${actor} ${item.event} on ${user}/${repo}: ${typeDict[type].title} #${issue.number}`, description: `${actor} mentioned this issue in <a href='${item.source.issue.html_url}'><b>${item.source.issue.title}</b> #${item.source.issue.number}</a>`, author: actor, pubDate: parseDate(item.created_at), guid: `${actor} ${item.event} on ${user}/${repo}: ${typeDict[type].title} #${issue.number} on ${item.created_at}`, link: `${actor} ${item.event} on ${user}/${repo}: ${typeDict[type].title} #${issue.number} on ${item.created_at}` }); break; case "renamed": items.push({ title: `${actor} ${item.event} on ${user}/${repo}: ${typeDict[type].title} #${issue.number}`, description: `${actor} changed the title <del>${item.rename.from}</del> ${item.rename.to}`, author: actor, pubDate: parseDate(item.created_at), link: item.url }); break; case "reviewed": items.push({ title: `${item.user.login} ${item.event} on ${user}/${repo}: ${typeDict[type].title} #${issue.number}`, description: item.body ? md.render(item.body) : item.state.replace("_", " "), author: item.user.login, pubDate: parseDate(item.submitted_at), link: item.html_url }); break; default: break; } } const ret = { title: `${user}/${repo}: ${typeDict[type].title} #${number} - ${issue.title}`, link: issue.html_url, item: items }; ctx.set("json", { ...ret, rateLimit: { limit: Number.parseInt(response.headers.get("x-ratelimit-limit")), remaining: Number.parseInt(response.headers.get("x-ratelimit-remaining")), reset: parseDate(Number.parseInt(response.headers.get("x-ratelimit-reset")) * 1e3), resoure: response.headers.get("x-ratelimit-resource"), used: Number.parseInt(response.headers.get("x-ratelimit-used")) } }); return ret; } //#endregion export { route };