mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-10-27 12:28:25 +08:00
* chore(deps-dev): bump eslint-plugin-unicorn from 74.0.0 to 75.0.0 Bumps [eslint-plugin-unicorn](https://github.com/sindresorhus/eslint-plugin-unicorn) from 74.0.0 to 75.0.0. - [Release notes](https://github.com/sindresorhus/eslint-plugin-unicorn/releases) - [Commits](https://github.com/sindresorhus/eslint-plugin-unicorn/compare/v74.0.0...v75.0.0) --- updated-dependencies: - dependency-name: eslint-plugin-unicorn dependency-version: 75.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> * style: fix unicorn-js/prefer-combined-guards * style: fix prefer-smaller-scope * style: fix prefer-continue * style: fix prefer-early-return * style: fix prefer-iterator-helpers * style: add v75 recommended preset --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Tony <TonyRL@users.noreply.github.com>
206 lines
6.4 KiB
JavaScript
206 lines
6.4 KiB
JavaScript
import remarkParse from 'remark-parse';
|
|
import { unified } from 'unified';
|
|
|
|
// @TODO maybe we could use label or some other better ways to distinguish bug/feature issues
|
|
const matchTitle = ['路由地址', 'Routes'];
|
|
const maintainerURL = 'https://raw.githubusercontent.com/DIYgod/RSSHub/gh-pages/build/maintainers.json';
|
|
const successTag = 'bug ping: pinged';
|
|
const parseFailTag = 'bug ping: parsing failed';
|
|
const failTag = 'bug ping: not found';
|
|
const deprecatedRoute = 'route: deprecated';
|
|
const route = 'route';
|
|
|
|
// DnD (do-not-disturb) usernames, add yours here to avoid being notified
|
|
// oxlint-disable-next-line unicorn/no-useless-collection-argument
|
|
const dndUsernames = new Set([]);
|
|
|
|
/**
|
|
* @param {string} body
|
|
* @param {typeof import('@actions/core')} core
|
|
* @returns {Promise<string[] | null>}
|
|
*/
|
|
async function parseBodyRoutes(body, core) {
|
|
const ast = await unified().use(remarkParse).parse(body);
|
|
|
|
// Is this a bug report?
|
|
const title = ast.children[0].children[0].value.trim();
|
|
core.debug(`title: ${title}`);
|
|
if (matchTitle.every((ele) => ele.localeCompare(title) !== 0)) {
|
|
return null;
|
|
}
|
|
|
|
let routes = ast.children[1].value.trim();
|
|
core.debug(`routes: ${JSON.stringify(routes)}`);
|
|
if (routes.localeCompare('NOROUTE') === 0) {
|
|
return null;
|
|
}
|
|
|
|
if (routes) {
|
|
routes = routes.split(/\r?\n/).filter(Boolean);
|
|
const dedup = [...new Set(routes)];
|
|
if (dedup.length !== routes.length) {
|
|
core.warning('Duplication detected.');
|
|
}
|
|
core.debug(dedup);
|
|
return dedup;
|
|
}
|
|
|
|
throw new Error('unable to parse the issue body: route does not exist');
|
|
}
|
|
|
|
/**
|
|
* @param {string[]} routes
|
|
* @param {typeof import('@actions/core')} core
|
|
* @returns {Promise<(string[] | undefined)[]>}
|
|
*/
|
|
async function getMaintainersByRoutes(routes, core) {
|
|
const response = await fetch(maintainerURL);
|
|
const maintainers = await response.json();
|
|
|
|
return routes.map((e) => {
|
|
const m = maintainers[e];
|
|
if (m === undefined) {
|
|
core.warning(`Route ${e} not found`);
|
|
}
|
|
|
|
return m;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {{ github: ReturnType<typeof import('@actions/github').getOctokit>, context: typeof import('@actions/github').context, core: typeof import('@actions/core') }} githubScript
|
|
* @returns {Promise<void>}
|
|
*/
|
|
export default async function callMaintainer({ github, context, core }) {
|
|
const body = context.payload.issue.body;
|
|
const issueFacts = {
|
|
issue_number: context.issue.number,
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
};
|
|
|
|
/** @param {string[]} labels */
|
|
const addLabels = async (labels) => {
|
|
try {
|
|
await github.rest.issues.addLabels({
|
|
...issueFacts,
|
|
labels,
|
|
});
|
|
} catch (error) {
|
|
core.warning(error);
|
|
}
|
|
};
|
|
/** @param {'open' | 'closed'} state */
|
|
const updateIssueState = async (state) => {
|
|
try {
|
|
await github.rest.issues.update({
|
|
...issueFacts,
|
|
state,
|
|
});
|
|
} catch (error) {
|
|
core.warning(error);
|
|
}
|
|
};
|
|
|
|
if (context.payload.issue.state === 'closed' && context.payload.issue.state_reason !== 'not_planned') {
|
|
await updateIssueState('open');
|
|
}
|
|
|
|
let routes;
|
|
try {
|
|
routes = await parseBodyRoutes(body, core);
|
|
} catch (error) {
|
|
core.warning(error);
|
|
}
|
|
|
|
if (routes === null) {
|
|
return; // Not a bug report, or NOROUTE
|
|
}
|
|
|
|
if (routes === undefined) {
|
|
await addLabels([parseFailTag]);
|
|
return;
|
|
}
|
|
|
|
const maintainers = await getMaintainersByRoutes(routes, core);
|
|
|
|
let successCount = 0;
|
|
let emptyCount = 0;
|
|
let failedCount = 0;
|
|
let comments = '##### Searching for maintainers: \n\n';
|
|
|
|
for (const [i, route] of routes.entries()) {
|
|
const main = maintainers[i];
|
|
if (main === undefined) {
|
|
comments += `- \`${route}\`: **Route not found**\n`;
|
|
failedCount += 1;
|
|
continue;
|
|
}
|
|
|
|
if (main.length === 0) {
|
|
comments += `- \`${route}\`: No maintainer listed, possibly a v1 or misconfigured route\n`;
|
|
emptyCount += 1;
|
|
continue;
|
|
}
|
|
|
|
if (main.length === 0) {
|
|
continue;
|
|
}
|
|
const pingStr = main
|
|
.map((e) => {
|
|
if (dndUsernames.has(e)) {
|
|
return `\`@${e}\``; // Wrap in an inline code block to make sure no mention will be sent
|
|
}
|
|
return `@${e}`;
|
|
})
|
|
.join(' ');
|
|
comments += `- \`${route}\`: ${pingStr}\n`;
|
|
successCount += 1;
|
|
}
|
|
|
|
const labels = [''];
|
|
|
|
if (failedCount > 0) {
|
|
labels.push(failTag);
|
|
} else {
|
|
labels.push(successTag);
|
|
}
|
|
|
|
if (emptyCount > 0) {
|
|
labels.push(deprecatedRoute);
|
|
}
|
|
|
|
if (successCount > 0) {
|
|
labels.push(route);
|
|
}
|
|
|
|
// Write labels (status, affected route count)
|
|
await addLabels(labels);
|
|
|
|
const commentBody = `${comments}
|
|
> To maintainers: if you are not willing to be disturbed, list your username in \`scripts/workflow/test-issue/call-maintainer.js\`. In this way, your username will be wrapped in an inline code block when tagged so you will not be notified.
|
|
|
|
If all routes can not be found, the issue will be closed automatically. Please use \`NOROUTE\` for a route-irrelevant issue or leave a comment if it is a mistake.
|
|
如果所有路由都无法匹配,issue 将会被自动关闭。如果 issue 和路由无关,请使用 \`NOROUTE\` 关键词,或者留下评论。我们会重新审核。
|
|
`;
|
|
|
|
// Reply to the issue and notify the maintainers (if any), reusing the existing comment if the issue was edited
|
|
try {
|
|
const existing = await github.paginate(github.rest.issues.listComments, issueFacts);
|
|
const comment = existing.find((c) => c.user.type === 'Bot' && c.body.startsWith('##### Searching for maintainers:'));
|
|
if (comment) {
|
|
if (comment.body !== commentBody) {
|
|
await github.rest.issues.updateComment({ ...issueFacts, comment_id: comment.id, body: commentBody });
|
|
}
|
|
} else {
|
|
await github.rest.issues.createComment({ ...issueFacts, body: commentBody });
|
|
}
|
|
} catch (error) {
|
|
core.warning(error);
|
|
}
|
|
|
|
if (failedCount && emptyCount === 0 && successCount === 0) {
|
|
await updateIssueState('closed');
|
|
}
|
|
}
|