206 lines
7.3 KiB
TypeScript
206 lines
7.3 KiB
TypeScript
import { Express, Request, Response } from "express";
|
|
import {
|
|
ButtonBuilder,
|
|
ButtonStyle,
|
|
ContainerBuilder,
|
|
MessageFlags,
|
|
SectionBuilder,
|
|
SeparatorBuilder,
|
|
SeparatorSpacingSize,
|
|
TextChannel,
|
|
TextDisplayBuilder,
|
|
ThumbnailBuilder,
|
|
} from "discord.js";
|
|
import { CHANNELS } from "../config";
|
|
import { client, db } from "../index";
|
|
|
|
const configured_channel = CHANNELS.UPDATES;
|
|
|
|
export default async function gitCommitPOST(app: Express) {
|
|
app.post("/git-commit", async (req: Request, res: Response) => {
|
|
try {
|
|
const event = req.headers["x-github-event"] as string;
|
|
|
|
// Acknowledge ping events
|
|
if (event === "ping") {
|
|
console.log("[WEB-gitCommit] Received GitHub ping event");
|
|
return res.status(200).json({ success: true, message: "pong" });
|
|
}
|
|
|
|
if (event !== "push") {
|
|
return res.status(200).json({
|
|
success: true,
|
|
message: `Event '${event}' ignored`,
|
|
});
|
|
}
|
|
|
|
const body = req.body;
|
|
const repo = body.repository;
|
|
const pusher = body.pusher;
|
|
const head_sha = body.after;
|
|
const commits: any[] = body.commits ?? [];
|
|
const headCommit = body.head_commit;
|
|
const ref: string = body.ref ?? "";
|
|
const branch = ref.replace("refs/heads/", "");
|
|
const compareUrl: string = body.compare ?? "";
|
|
const forced: boolean = body.forced ?? false;
|
|
|
|
if (!repo || !headCommit) {
|
|
return res.status(400).json({ error: "Invalid push payload" });
|
|
}
|
|
|
|
// ignore release by actions
|
|
if (ref.startsWith("refs/tags/")) {
|
|
return res.status(200).json({
|
|
success: true,
|
|
message: "Tag push ignored",
|
|
});
|
|
}
|
|
|
|
// Build commit list (max X)
|
|
const SHOW_MAX = 5;
|
|
const commitLines = commits.slice(0, SHOW_MAX).map((c: any) => {
|
|
const shortId = c.id.substring(0, 7);
|
|
const msg = c.message.split("\n")[0].substring(0, 64);
|
|
return `[\`${shortId}\`](${c.url}) ${msg}...`;
|
|
});
|
|
|
|
if (commits.length > SHOW_MAX) {
|
|
commitLines.push(`...and ${commits.length - SHOW_MAX} more`);
|
|
}
|
|
|
|
const container = new ContainerBuilder().setAccentColor(
|
|
forced ? 0xff4444 : 0x2ea44f,
|
|
);
|
|
|
|
// Author + title section
|
|
container.addSectionComponents(
|
|
new SectionBuilder()
|
|
.addTextDisplayComponents(
|
|
new TextDisplayBuilder().setContent(
|
|
`## ${forced ? "⚠️ Force Push" : "📦 New Push"} to \`${branch}\``,
|
|
),
|
|
)
|
|
.setThumbnailAccessory(
|
|
new ThumbnailBuilder({
|
|
media: {
|
|
url: `https://github.com/${pusher.name}.png`,
|
|
},
|
|
}),
|
|
),
|
|
);
|
|
container.addSeparatorComponents(
|
|
new SeparatorBuilder()
|
|
.setDivider(true)
|
|
.setSpacing(SeparatorSpacingSize.Small),
|
|
);
|
|
|
|
// Branch & commits
|
|
container.addTextDisplayComponents(
|
|
new TextDisplayBuilder().setContent(
|
|
`**🌿 Branch:** \`${branch}\``,
|
|
),
|
|
);
|
|
container.addSeparatorComponents(
|
|
new SeparatorBuilder()
|
|
.setDivider(false)
|
|
.setSpacing(SeparatorSpacingSize.Small),
|
|
);
|
|
container.addTextDisplayComponents(
|
|
new TextDisplayBuilder().setContent(
|
|
`**📝 Commits (${commits.length})**\n${
|
|
commitLines.join("\n") || "_No commits_"
|
|
}`,
|
|
),
|
|
);
|
|
|
|
// Compare link button (only if a URL is available)
|
|
if (compareUrl) {
|
|
container.addSeparatorComponents(
|
|
new SeparatorBuilder()
|
|
.setDivider(true)
|
|
.setSpacing(SeparatorSpacingSize.Small),
|
|
);
|
|
container.addSectionComponents(
|
|
new SectionBuilder()
|
|
.addTextDisplayComponents(
|
|
new TextDisplayBuilder().setContent(
|
|
"🔗 **View Changes**",
|
|
),
|
|
)
|
|
.setButtonAccessory(
|
|
new ButtonBuilder()
|
|
.setLabel("Compare")
|
|
.setURL(compareUrl)
|
|
.setStyle(ButtonStyle.Link),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Footer
|
|
container.addSeparatorComponents(
|
|
new SeparatorBuilder()
|
|
.setDivider(false)
|
|
.setSpacing(SeparatorSpacingSize.Small),
|
|
);
|
|
container.addTextDisplayComponents(
|
|
new TextDisplayBuilder().setContent(
|
|
`-# Delivery: ${
|
|
req.headers["x-github-delivery"] ?? "unknown"
|
|
}`,
|
|
),
|
|
);
|
|
|
|
const channel = (await client.channels.fetch(
|
|
configured_channel,
|
|
)) as TextChannel | null;
|
|
if (!channel || !channel.isTextBased()) {
|
|
console.error(
|
|
"[WEB-gitCommit] Configured channel not found or not text-based",
|
|
);
|
|
return res
|
|
.status(500)
|
|
.json({ error: "Discord channel unavailable" });
|
|
}
|
|
|
|
const message = await channel.send({
|
|
flags: MessageFlags.IsComponentsV2,
|
|
components: [container],
|
|
});
|
|
console.log(
|
|
`[WEB-gitCommit] Push event sent to configured channel (${commits.length} commits on ${branch})`,
|
|
);
|
|
|
|
// Reactions for engagement
|
|
await message.react("👍");
|
|
await message.react("🔥");
|
|
await message.react("🤯");
|
|
|
|
// Add to DB
|
|
await db.collection("git_commits").insertOne({
|
|
repository: repo.full_name,
|
|
pusher: pusher.name,
|
|
branch,
|
|
commitCount: commits.length,
|
|
commitLines,
|
|
compareUrl,
|
|
forced,
|
|
deliveryId: req.headers["x-github-delivery"] ?? "unknown",
|
|
timestamp: new Date(),
|
|
messageId: message.id,
|
|
head_sha: head_sha,
|
|
jobs: {},
|
|
lastEditedAt: new Date(),
|
|
pendingUpdate: false,
|
|
});
|
|
|
|
return res.status(200).json({ success: true });
|
|
} catch (error) {
|
|
console.error("[WEB-gitCommit] Error handling git commit:", error);
|
|
return res
|
|
.status(500)
|
|
.json({ success: false, error: "Internal Server Error" });
|
|
}
|
|
});
|
|
}
|