generated from nhcarrigan/template
feat: remove webhooks and add invite button
This commit is contained in:
@ -20,10 +20,6 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/nhcarrigan/mod-bot/issues"
|
"url": "https://github.com/nhcarrigan/mod-bot/issues"
|
||||||
},
|
},
|
||||||
"engines": {
|
|
||||||
"node": "22",
|
|
||||||
"pnpm": "10"
|
|
||||||
},
|
|
||||||
"homepage": "https://github.com/nhcarrigan/mod-bot#readme",
|
"homepage": "https://github.com/nhcarrigan/mod-bot#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nhcarrigan/eslint-config": "3.2.0",
|
"@nhcarrigan/eslint-config": "3.2.0",
|
||||||
|
@ -1,190 +0,0 @@
|
|||||||
/**
|
|
||||||
* The structure of the NESTED issue data from the GitHub Webhook.
|
|
||||||
*/
|
|
||||||
interface GithubIssuePayload {
|
|
||||||
id: number;
|
|
||||||
node_id: string;
|
|
||||||
url: string;
|
|
||||||
repository_url: string;
|
|
||||||
html_url: string;
|
|
||||||
number: number;
|
|
||||||
state: string;
|
|
||||||
state_reason: string | null;
|
|
||||||
title: string;
|
|
||||||
body: string;
|
|
||||||
user: GithubUserPayload;
|
|
||||||
created_at: string;
|
|
||||||
updated_at: string;
|
|
||||||
closed_by: GithubUserPayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GithubPullRequestPayload {
|
|
||||||
html_url: string;
|
|
||||||
body: string;
|
|
||||||
number: number;
|
|
||||||
merged: boolean;
|
|
||||||
title: string;
|
|
||||||
user: GithubUserPayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Structure of the repo data, sent on pretty much
|
|
||||||
* every GitHub Webhook payload.
|
|
||||||
*/
|
|
||||||
interface GithubRepoPayload {
|
|
||||||
id: number;
|
|
||||||
node_id: string;
|
|
||||||
name: string;
|
|
||||||
full_name: string;
|
|
||||||
owner: GithubUserPayload;
|
|
||||||
private: boolean;
|
|
||||||
html_url: string;
|
|
||||||
description: string;
|
|
||||||
fork: boolean;
|
|
||||||
url: string;
|
|
||||||
archive_url: string;
|
|
||||||
assignees_url: string;
|
|
||||||
blobs_url: string;
|
|
||||||
branches_url: string;
|
|
||||||
collaborators_url: string;
|
|
||||||
comments_url: string;
|
|
||||||
commits_url: string;
|
|
||||||
compare_url: string;
|
|
||||||
contents_url: string;
|
|
||||||
contributors_url: string;
|
|
||||||
deployments_url: string;
|
|
||||||
downloads_url: string;
|
|
||||||
events_url: string;
|
|
||||||
forks_url: string;
|
|
||||||
git_commits_url: string;
|
|
||||||
git_refs_url: string;
|
|
||||||
git_tags_url: string;
|
|
||||||
git_url: string;
|
|
||||||
issue_comment_url: string;
|
|
||||||
issue_events_url: string;
|
|
||||||
issues_url: string;
|
|
||||||
keys_url: string;
|
|
||||||
labels_url: string;
|
|
||||||
languages_url: string;
|
|
||||||
merges_url: string;
|
|
||||||
milestones_url: string;
|
|
||||||
notifications_url: string;
|
|
||||||
pulls_url: string;
|
|
||||||
releases_url: string;
|
|
||||||
ssh_url: string;
|
|
||||||
stargazers_url: string;
|
|
||||||
statuses_url: string;
|
|
||||||
subscribers_url: string;
|
|
||||||
subscription_url: string;
|
|
||||||
tags_url: string;
|
|
||||||
teams_url: string;
|
|
||||||
trees_url: string;
|
|
||||||
clone_url: string;
|
|
||||||
mirror_url: string;
|
|
||||||
hooks_url: string;
|
|
||||||
svn_url: string;
|
|
||||||
homepage: string;
|
|
||||||
language: string | null;
|
|
||||||
forks: number;
|
|
||||||
forks_count: number;
|
|
||||||
stargazers_count: number;
|
|
||||||
watchers_count: number;
|
|
||||||
watchers: number;
|
|
||||||
size: number;
|
|
||||||
default_branch: string;
|
|
||||||
open_issues_count: number;
|
|
||||||
open_issues: number;
|
|
||||||
created_at: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GithubUserPayload {
|
|
||||||
login: string;
|
|
||||||
id: number;
|
|
||||||
node_id: string;
|
|
||||||
avatar_url: string;
|
|
||||||
gravatar_id: string;
|
|
||||||
url: string;
|
|
||||||
html_url: string;
|
|
||||||
followers_url: string;
|
|
||||||
following_url: string;
|
|
||||||
gists_url: string;
|
|
||||||
starred_url: string;
|
|
||||||
subscriptions_url: string;
|
|
||||||
organizations_url: string;
|
|
||||||
repos_url: string;
|
|
||||||
events_url: string;
|
|
||||||
received_events_url: string;
|
|
||||||
type: string;
|
|
||||||
site_admin: boolean;
|
|
||||||
name: string;
|
|
||||||
company: string;
|
|
||||||
blog: string;
|
|
||||||
location: string;
|
|
||||||
email: string;
|
|
||||||
hireable: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The structure of the comment data from the Github Webhook.
|
|
||||||
*/
|
|
||||||
export interface GithubCommentPayload {
|
|
||||||
action: string;
|
|
||||||
issue: GithubIssuePayload;
|
|
||||||
comment: {
|
|
||||||
html_url: string;
|
|
||||||
body: string;
|
|
||||||
user: GithubUserPayload;
|
|
||||||
};
|
|
||||||
repository: GithubRepoPayload;
|
|
||||||
sender: GithubUserPayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GithubForkPayload {
|
|
||||||
forkee: GithubRepoPayload;
|
|
||||||
repository: GithubRepoPayload;
|
|
||||||
sender: GithubUserPayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The structure of the top level issue data from the GitHub webhook.
|
|
||||||
*/
|
|
||||||
export interface GithubIssuesPayload {
|
|
||||||
action: string;
|
|
||||||
issue: GithubIssuePayload;
|
|
||||||
repository: GithubRepoPayload;
|
|
||||||
sender: GithubUserPayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The structure of the ping payload when a new GitHub webhook
|
|
||||||
* is initialised.
|
|
||||||
*/
|
|
||||||
export interface GithubPingPayload {
|
|
||||||
zen: string;
|
|
||||||
hook_id: string;
|
|
||||||
hook: Record<string, unknown>;
|
|
||||||
repository: GithubRepoPayload;
|
|
||||||
organization: Record<string, unknown>;
|
|
||||||
sender: GithubUserPayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Structure of the pull request data from the GitHub Webhook.
|
|
||||||
*/
|
|
||||||
export interface GithubPullPayload {
|
|
||||||
action: string;
|
|
||||||
number: number;
|
|
||||||
pull_request: GithubPullRequestPayload;
|
|
||||||
repository: GithubRepoPayload;
|
|
||||||
sender: GithubUserPayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Structure of the star data sent from the GitHub Webhook.
|
|
||||||
*/
|
|
||||||
export interface GithubStarPayload {
|
|
||||||
action: "created" | "deleted";
|
|
||||||
starred_at: string;
|
|
||||||
repository: GithubRepoPayload;
|
|
||||||
sender: GithubUserPayload;
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
import { GithubCommentPayload } from "../../interfaces/GitHubPayloads";
|
|
||||||
|
|
||||||
export const generateCommentEmbed = (data: GithubCommentPayload): string => {
|
|
||||||
return `[New comment detected on ${data.repository.name}#${data.issue.number}.](<${data.comment.html_url}>)`;
|
|
||||||
};
|
|
@ -1,5 +0,0 @@
|
|||||||
import { GithubForkPayload } from "../../interfaces/GitHubPayloads";
|
|
||||||
|
|
||||||
export const generateForkEmbed = (data: GithubForkPayload): string => {
|
|
||||||
return `[New fork detected - ${data.repository.name}](<${data.forkee.html_url}>)`;
|
|
||||||
};
|
|
@ -1,25 +0,0 @@
|
|||||||
import { GithubIssuesPayload } from "../../interfaces/GitHubPayloads";
|
|
||||||
|
|
||||||
export const generateIssuesEmbed = (
|
|
||||||
data: GithubIssuesPayload
|
|
||||||
): string | null => {
|
|
||||||
if (!["opened", "edited", "closed"].includes(data.action)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (data.action === "closed") {
|
|
||||||
if (data.issue.state_reason === "completed") {
|
|
||||||
return `[Issue closed as complete - ${data.repository.name}#${data.issue.number}](<${data.issue.html_url}>)`;
|
|
||||||
}
|
|
||||||
if (data.issue.state_reason === "not_planned") {
|
|
||||||
return `[Issue closed as not planned - ${data.repository.name}#${data.issue.number}](<${data.issue.html_url}>)`;
|
|
||||||
}
|
|
||||||
return `[Issue closed - ${data.repository.name}#${data.issue.number}](<${data.issue.html_url}>)`;
|
|
||||||
}
|
|
||||||
if (data.issue.state_reason === "reopened") {
|
|
||||||
return `[Issue reopened - ${data.repository.name}#${data.issue.number}](<${data.issue.html_url}>)`;
|
|
||||||
}
|
|
||||||
if (data.action === "edited") {
|
|
||||||
return `[Issue updated - ${data.repository.name}#${data.issue.number}](<${data.issue.html_url}>)`;
|
|
||||||
}
|
|
||||||
return `[New issue created - ${data.repository.name}#${data.issue.number}](<${data.issue.html_url}>)`;
|
|
||||||
};
|
|
@ -1,5 +0,0 @@
|
|||||||
import { GithubPingPayload } from "../../interfaces/GitHubPayloads";
|
|
||||||
|
|
||||||
export const generatePingEmbed = (data: GithubPingPayload): string => {
|
|
||||||
return `[Now watching ${data.repository.name}](<${data.repository.url}>)`;
|
|
||||||
};
|
|
@ -1,17 +0,0 @@
|
|||||||
import { GithubPullPayload } from "../../interfaces/GitHubPayloads";
|
|
||||||
|
|
||||||
export const generatePullEmbed = (data: GithubPullPayload): string | null => {
|
|
||||||
if (!["opened", "edited", "closed"].includes(data.action)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (data.pull_request.merged) {
|
|
||||||
return `[Pull request merged - ${data.repository.name}#${data.pull_request.number}](<${data.pull_request.html_url}>)`;
|
|
||||||
}
|
|
||||||
if (data.action === "edited") {
|
|
||||||
return `[Pull request updated - ${data.repository.name}#${data.pull_request.number}](<${data.pull_request.html_url}>)`;
|
|
||||||
}
|
|
||||||
if (data.action === "closed") {
|
|
||||||
return `[Pull request closed - ${data.repository.name}#${data.pull_request.number}](<${data.pull_request.html_url}>)`;
|
|
||||||
}
|
|
||||||
return `[New pull request - ${data.repository.name}#${data.pull_request.number}](<${data.pull_request.html_url}>)`;
|
|
||||||
};
|
|
@ -1,8 +0,0 @@
|
|||||||
import { GithubStarPayload } from "../../interfaces/GitHubPayloads";
|
|
||||||
|
|
||||||
export const generateStarEmbed = (data: GithubStarPayload): string | null => {
|
|
||||||
if (data.action !== "created") {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return `[New stargazer! ${data.repository.name}](<${data.repository.html_url}>)`;
|
|
||||||
};
|
|
@ -1,23 +1,11 @@
|
|||||||
import { createHmac, timingSafeEqual } from "crypto";
|
|
||||||
import { readFile } from "fs/promises";
|
import { readFile } from "fs/promises";
|
||||||
import http from "http";
|
import http from "http";
|
||||||
import https from "https";
|
import https from "https";
|
||||||
|
|
||||||
import { Octokit } from "@octokit/rest";
|
|
||||||
import { GuildTextBasedChannel } from "discord.js";
|
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import { register } from "prom-client";
|
import { register } from "prom-client";
|
||||||
|
|
||||||
import { IgnoredActors, ThankYou } from "../config/Github";
|
|
||||||
import { ExtendedClient } from "../interfaces/ExtendedClient";
|
import { ExtendedClient } from "../interfaces/ExtendedClient";
|
||||||
import { errorHandler } from "../utils/errorHandler";
|
|
||||||
|
|
||||||
import { generateCommentEmbed } from "./github/generateCommentEmbed";
|
|
||||||
import { generateForkEmbed } from "./github/generateForkEmbed";
|
|
||||||
import { generateIssuesEmbed } from "./github/generateIssueEmbed";
|
|
||||||
import { generatePingEmbed } from "./github/generatePingEmbed";
|
|
||||||
import { generatePullEmbed } from "./github/generatePullEmbed";
|
|
||||||
import { generateStarEmbed } from "./github/generateStarEmbed";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates the web server for GitHub webhooks.
|
* Instantiates the web server for GitHub webhooks.
|
||||||
@ -25,24 +13,7 @@ import { generateStarEmbed } from "./github/generateStarEmbed";
|
|||||||
* @param {ExtendedClient} bot The bot's Discord instance.
|
* @param {ExtendedClient} bot The bot's Discord instance.
|
||||||
*/
|
*/
|
||||||
export const serve = async (bot: ExtendedClient) => {
|
export const serve = async (bot: ExtendedClient) => {
|
||||||
const githubSecret = process.env.GITHUB_WEBHOOK_SECRET;
|
|
||||||
const patreonSecret = process.env.PATREON_WEBHOOK_SECRET;
|
|
||||||
const kofiSecret = process.env.KOFI_WEBHOOK_SECRET;
|
|
||||||
const token = process.env.GITHUB_TOKEN;
|
|
||||||
if (!githubSecret || !token || !kofiSecret || !patreonSecret) {
|
|
||||||
await bot.env.debugHook.send({
|
|
||||||
content: "Missing necessary secrets. Web server will not be started.",
|
|
||||||
username: bot.user?.username ?? "bot",
|
|
||||||
avatarURL:
|
|
||||||
bot.user?.displayAvatarURL() ??
|
|
||||||
"https://cdn.nhcarrigan.com/avatars/nhcarrigan.png"
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.post("/patreon", express.text({ type: "*/*" }));
|
|
||||||
app.use(express.urlencoded({ extended: true }));
|
|
||||||
app.use(express.json());
|
|
||||||
|
|
||||||
app.get("/", (_req, res) => {
|
app.get("/", (_req, res) => {
|
||||||
res.send(`
|
res.send(`
|
||||||
@ -61,6 +32,9 @@ export const serve = async (bot: ExtendedClient) => {
|
|||||||
<img src="https://cdn.nhcarrigan.com/new-avatars/celestine-full.png" width="250" alt="Celestine" />
|
<img src="https://cdn.nhcarrigan.com/new-avatars/celestine-full.png" width="250" alt="Celestine" />
|
||||||
<section>
|
<section>
|
||||||
<p>A paid moderation bot for Discord.</p>
|
<p>A paid moderation bot for Discord.</p>
|
||||||
|
<a href="https://discord.com/oauth2/authorize?client_id=1235128719836712970&permissions=8&integration_type=0&scope=bot+applications.commands" class="social-button discord-button" style="display: inline-block; background-color: #5865F2; color: white; padding: 10px 20px; text-decoration: none; border-radius: 4px; margin: 5px;">
|
||||||
|
<i class="fab fa-discord"></i> Add to Discord
|
||||||
|
</a>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<h2>Links</h2>
|
<h2>Links</h2>
|
||||||
@ -95,218 +69,6 @@ export const serve = async (bot: ExtendedClient) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/kofi", async (req, res) => {
|
|
||||||
const payload = JSON.parse(req.body.data);
|
|
||||||
const {
|
|
||||||
verification_token: verifyToken,
|
|
||||||
from_name: fromName,
|
|
||||||
is_subscription_payment: isSub,
|
|
||||||
is_first_subscription_payment: isFirstSub
|
|
||||||
} = payload;
|
|
||||||
if (!verifyToken) {
|
|
||||||
await bot.env.debugHook.send({
|
|
||||||
content:
|
|
||||||
"Received request with no signature.\n\n" +
|
|
||||||
JSON.stringify(req.body).slice(0, 1500),
|
|
||||||
username: bot.user?.username ?? "bot",
|
|
||||||
avatarURL:
|
|
||||||
bot.user?.displayAvatarURL() ??
|
|
||||||
"https://cdn.nhcarrigan.com/avatars/nhcarrigan.png"
|
|
||||||
});
|
|
||||||
res.status(400).send("Invalid payload.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (verifyToken !== kofiSecret) {
|
|
||||||
await bot.env.debugHook.send({
|
|
||||||
content:
|
|
||||||
"Received request with bad signature.\n\n" +
|
|
||||||
JSON.stringify(req.body).slice(0, 1500),
|
|
||||||
username: bot.user?.username ?? "bot",
|
|
||||||
avatarURL:
|
|
||||||
bot.user?.displayAvatarURL() ??
|
|
||||||
"https://cdn.nhcarrigan.com/avatars/nhcarrigan.png"
|
|
||||||
});
|
|
||||||
res.status(403).send("Invalid signature.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
res.status(200).send("Valid signature found!");
|
|
||||||
|
|
||||||
// ignore recurring subscriptions
|
|
||||||
if (isSub && !isFirstSub) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const channel = (await bot.channels.fetch(
|
|
||||||
"1235114666322034790"
|
|
||||||
)) as GuildTextBasedChannel;
|
|
||||||
|
|
||||||
await channel.send({
|
|
||||||
content: `## Big thanks to ${fromName} for sponsoring us on KoFi!\n\nTo claim your sponsor role, please DM Naomi with your KoFi receipt.`
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app.post("/patreon", async (req, res) => {
|
|
||||||
// validate headers
|
|
||||||
const header = req.headers["x-patreon-signature"];
|
|
||||||
if (!header) {
|
|
||||||
await bot.env.debugHook.send({
|
|
||||||
content:
|
|
||||||
"Received request with no signature.\n\n" +
|
|
||||||
String(req.body).slice(0, 1500),
|
|
||||||
username: bot.user?.username ?? "bot",
|
|
||||||
avatarURL:
|
|
||||||
bot.user?.displayAvatarURL() ??
|
|
||||||
"https://cdn.nhcarrigan.com/avatars/nhcarrigan.png"
|
|
||||||
});
|
|
||||||
res.status(403).send("No valid signature present.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const hash = createHmac("MD5", patreonSecret)
|
|
||||||
.update(req.body)
|
|
||||||
.digest("hex");
|
|
||||||
if (hash !== header) {
|
|
||||||
await bot.env.debugHook.send({
|
|
||||||
content:
|
|
||||||
"Received request with bad signature.\n\n" +
|
|
||||||
String(req.body).slice(0, 1500),
|
|
||||||
username: bot.user?.username ?? "bot",
|
|
||||||
avatarURL:
|
|
||||||
bot.user?.displayAvatarURL() ??
|
|
||||||
"https://cdn.nhcarrigan.com/avatars/nhcarrigan.png"
|
|
||||||
});
|
|
||||||
res.status(403).send("Signature is not correct.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
res.status(200).send("Signature is correct.");
|
|
||||||
|
|
||||||
const event = req.headers["x-patreon-event"];
|
|
||||||
|
|
||||||
if (event !== "pledges:create") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const obj = JSON.parse(req.body);
|
|
||||||
|
|
||||||
const user = obj.included.find(
|
|
||||||
(obj: Record<string, string>) => obj.type === "user"
|
|
||||||
);
|
|
||||||
|
|
||||||
const channel = (await bot.channels.fetch(
|
|
||||||
"1235114666322034790"
|
|
||||||
)) as GuildTextBasedChannel;
|
|
||||||
|
|
||||||
await channel?.send({
|
|
||||||
content: `## Big thanks to ${user.attributes.full_name} for sponsoring us on Patreon!\n\nTo claim your sponsor role, please DM Naomi with your patreon receipt.`
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
app.post("/github", async (req, res) => {
|
|
||||||
try {
|
|
||||||
const header = req.headers["x-hub-signature-256"];
|
|
||||||
if (!header || Array.isArray(header)) {
|
|
||||||
await bot.env.debugHook.send({
|
|
||||||
content:
|
|
||||||
"Received request with no signature.\n\n" +
|
|
||||||
JSON.stringify(req.body).slice(0, 1500),
|
|
||||||
username: bot.user?.username ?? "bot",
|
|
||||||
avatarURL:
|
|
||||||
bot.user?.displayAvatarURL() ??
|
|
||||||
"https://cdn.nhcarrigan.com/avatars/nhcarrigan.png"
|
|
||||||
});
|
|
||||||
res.status(403).send("No valid signature present.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const signature = createHmac("sha256", githubSecret)
|
|
||||||
.update(JSON.stringify(req.body))
|
|
||||||
.digest("hex");
|
|
||||||
const trusted = Buffer.from(`sha256=${signature}`, "ascii");
|
|
||||||
const sent = Buffer.from(header, "ascii");
|
|
||||||
const safe = timingSafeEqual(trusted, sent);
|
|
||||||
if (!safe) {
|
|
||||||
await bot.env.debugHook.send({
|
|
||||||
content:
|
|
||||||
"Received request with bad signature.\n\n" +
|
|
||||||
JSON.stringify(req.body).slice(0, 1500),
|
|
||||||
username: bot.user?.username ?? "bot",
|
|
||||||
avatarURL:
|
|
||||||
bot.user?.displayAvatarURL() ??
|
|
||||||
"https://cdn.nhcarrigan.com/avatars/nhcarrigan.png"
|
|
||||||
});
|
|
||||||
res.status(403).send("Signature is not correct.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
res.status(200).send("Signature is correct.");
|
|
||||||
|
|
||||||
const event = req.headers["x-github-event"] as string;
|
|
||||||
if (event === "sponsorship" && req.body.action === "created") {
|
|
||||||
const channel = (await bot.channels.fetch(
|
|
||||||
"1235114666322034790"
|
|
||||||
)) as GuildTextBasedChannel;
|
|
||||||
await channel?.send({
|
|
||||||
content: `## Big thanks to ${req.body.sponsorship.sponsor.login} for sponsoring us on GitHub!\n\nTo claim your sponsor role, please make sure your GitHub account is connected to your Discord account, then ping Mama Naomi for your role!`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
IgnoredActors.includes(
|
|
||||||
req.body.pull_request?.user.login || req.body.sender?.login
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const embedGenerator = {
|
|
||||||
ping: generatePingEmbed,
|
|
||||||
star: generateStarEmbed,
|
|
||||||
issues: generateIssuesEmbed,
|
|
||||||
pull_request: generatePullEmbed,
|
|
||||||
issue_comment: generateCommentEmbed,
|
|
||||||
fork: generateForkEmbed
|
|
||||||
};
|
|
||||||
|
|
||||||
const isValidKey = (
|
|
||||||
event: string
|
|
||||||
): event is keyof typeof embedGenerator => {
|
|
||||||
return event in embedGenerator;
|
|
||||||
};
|
|
||||||
|
|
||||||
const content = isValidKey(event)
|
|
||||||
? embedGenerator[event](req.body)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
if (content) {
|
|
||||||
const channel = (await bot.channels.fetch(
|
|
||||||
"1231028190403891212"
|
|
||||||
)) as GuildTextBasedChannel;
|
|
||||||
|
|
||||||
await channel?.send({
|
|
||||||
content
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event === "pull_request") {
|
|
||||||
const owner = req.body.repository.owner.login;
|
|
||||||
const repo = req.body.repository.name;
|
|
||||||
const number = req.body.number;
|
|
||||||
const isMerged =
|
|
||||||
req.body.action === "closed" && req.body.pull_request.merged;
|
|
||||||
const github = new Octokit({
|
|
||||||
auth: process.env.GITHUB_TOKEN
|
|
||||||
});
|
|
||||||
if (isMerged && req.body.pull_request?.user.login !== "naomi-lgbt") {
|
|
||||||
await github.issues.createComment({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
issue_number: number,
|
|
||||||
body: ThankYou
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
await errorHandler(bot, "github webhook", err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const httpServer = http.createServer(app);
|
const httpServer = http.createServer(app);
|
||||||
|
|
||||||
httpServer.listen(9080, async () => {
|
httpServer.listen(9080, async () => {
|
||||||
|
Reference in New Issue
Block a user