Files
zkldi_Tachi/github-bot/src/main.ts
T
2024-04-25 12:00:30 +01:00

152 lines
3.7 KiB
TypeScript

/* eslint-disable no-console */
import { ProcessEnv } from "./config";
import { App, createNodeMiddleware } from "@octokit/app";
import express from "express";
import fetch from "node-fetch";
import { URLSearchParams } from "url";
import type { Repository } from "@octokit/webhooks-types";
const app = new App({
appId: ProcessEnv.appId,
privateKey: ProcessEnv.privateKey,
webhooks: {
secret: ProcessEnv.webhookSecret,
},
oauth: {
clientId: ProcessEnv.clientID,
clientSecret: ProcessEnv.clientSecret,
},
});
/**
* Create a response that contains a link to the seeds diff viewer.
*/
function mkSeedDiffViewMsg(repo: string, sha: string, compareRepo: string, compareSHA: string) {
const params = new URLSearchParams({
repo: ConvertGitHubURL(repo),
sha,
compareRepo: ConvertGitHubURL(compareRepo),
compareSHA,
});
return `\nA commit has changed the database-seeds. [View the seeds diff here.](https://boku.tachi.ac/utils/seeds?${params.toString()})`;
}
function ConvertGitHubURL(url: string) {
return url.replace("https://api.github.com/repos/", "GitHub:");
}
async function sendMsg(message: string, octokit: any, repo: Repository, issue: number) {
await octokit.request("POST /repos/{owner}/{repo}/issues/{issue_number}/comments", {
owner: repo.owner.login,
repo: repo.name,
issue_number: issue,
body: message,
});
}
app.webhooks.on(["pull_request.opened", "pull_request.edited"], async ({ octokit, payload }) => {
try {
const filesChanged = (await fetch(
`https://api.github.com/repos/zkldi/Tachi/pulls/${payload.number}/files`
).then((r) => r.json())) as Array<{ filename: string }>;
// if any file modified in this pr is a collection
if (filesChanged.some((k) => k.filename.startsWith("database-seeds/collections"))) {
// post a link to the diff viewer in the PR comments.
await sendMsg(
mkSeedDiffViewMsg(
payload.pull_request.base.repo.url,
payload.pull_request.base.sha,
payload.pull_request.head.repo.url,
payload.pull_request.head.sha
),
octokit,
payload.repository,
payload.pull_request.number
);
}
} catch (err) {
await sendMsg(
`I failed horribly figuring out whether this was a seeds diff or not. I'm sorry!
*****
Reason
\`\`\`
${err}
\`\`\`
*****
${mkSeedDiffViewMsg(
payload.pull_request.base.repo.url,
payload.pull_request.base.sha,
payload.pull_request.head.repo.url,
payload.pull_request.head.sha
)}`,
octokit,
payload.repository,
payload.pull_request.number
);
}
});
app.webhooks.on(["issue_comment.created"], async ({ octokit, payload }) => {
const body = payload.comment.body.trim();
if (body.startsWith("+bot")) {
const cmd = body
.split("\n")[0]!
.split(/\s+/u)[1]
?.replace(/[^a-z]/u, "");
switch (cmd) {
case "ping": {
await sendMsg("pong!", octokit, payload.repository, payload.issue.number);
break;
}
case "diff": {
const pr = (
await octokit.request("GET /repos/{owner}/{repo}/pulls/{pull_number}", {
owner: payload.repository.owner.login,
repo: payload.repository.name,
pull_number: payload.issue.number,
})
).data;
await sendMsg(
mkSeedDiffViewMsg(
pr.base.repo.url,
pr.base.sha,
pr.head.repo?.url ?? "unknown-url",
pr.head.sha
),
octokit,
payload.repository,
pr.number
);
break;
}
default:
await sendMsg(
`No idea what to do with command \`${cmd}\`, sorry!`,
octokit,
payload.repository,
payload.issue.number
);
}
}
});
const serverMiddleware = createNodeMiddleware(app);
const expressApp = express();
expressApp.use(serverMiddleware);
console.log(`Listening on port ${ProcessEnv.port}.`);
expressApp.listen(ProcessEnv.port);