Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a820f74
fix: minor bug fixes
ijsKoud Apr 24, 2023
bb24eb1
fix: incorrect content-type header
ijsKoud Apr 24, 2023
212813e
feat: add create ref embed
ijsKoud Apr 24, 2023
b88a8bd
feat: add delete ref embed
ijsKoud Apr 24, 2023
c7b808b
fix: critical loading loop fix
ijsKoud Apr 24, 2023
a82a1c0
fix: minor bug fixes
ijsKoud Apr 24, 2023
9d04a5b
feat(WebhookManager): add base for forum channels
ijsKoud Apr 24, 2023
9ff5cc7
feat: add pull request opened embed
ijsKoud Apr 24, 2023
41c93b6
fix: incorrect embed color for push event
ijsKoud Apr 24, 2023
e47c06b
feat: add more pull request embed options
ijsKoud Apr 24, 2023
2e854a7
feat: add thread creation
ijsKoud Apr 24, 2023
8b04509
feat: add thread creation
ijsKoud Apr 24, 2023
808545f
feat(PullRequestEmbed): add missing types
ijsKoud Apr 24, 2023
729b336
feat(GitHubWebhookManager): add request handling
ijsKoud Apr 25, 2023
53a6122
feat: add collaborator embed
ijsKoud Apr 25, 2023
c3bcb37
feat: add commit comment embed
ijsKoud Apr 25, 2023
db3e00d
feat(PrEmbed): update title
ijsKoud Apr 25, 2023
213e421
fix: minor bug fix
ijsKoud Apr 25, 2023
d9b045d
fix(CommitComment): incorrect urls
ijsKoud Apr 25, 2023
965e4c2
feat: add issue comment embed
ijsKoud Apr 25, 2023
7229a64
fix(PullRequestEmbed): incorrect pr number provided
ijsKoud Apr 25, 2023
2e21c74
feat: add issue embed creator
ijsKoud Apr 25, 2023
eea450c
feat: add milestone embed
ijsKoud Apr 25, 2023
348e110
feat: add package embed
ijsKoud Apr 25, 2023
97571f7
feat(PrEmbed): update title
ijsKoud Apr 25, 2023
431a434
feat: add release embed
ijsKoud Apr 25, 2023
d13f13e
feat(PrEmbed): update stage change design
ijsKoud Apr 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"@sapphire/ts-config": "^4.0.0",
"@types/eventsource": "^1.1.11",
"@types/express": "^4.17.17",
"@types/lodash": "^4.14.194",
"@types/node": "^18.16.0",
"@typescript-eslint/eslint-plugin": "^5.59.0",
"@typescript-eslint/parser": "^5.59.0",
Expand Down Expand Up @@ -60,6 +61,7 @@
"dotenv": "^16.0.3",
"eventsource": "^2.0.2",
"express": "^4.18.2",
"lodash": "^4.17.21",
"zod": "^3.21.4"
}
}
3 changes: 2 additions & 1 deletion src/database/structures/Guild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type GitCordClient from "#discord/lib/GitCordClient.js";
import { ChannelType, Collection, ForumChannel, Guild, TextChannel } from "discord.js";
import GitCordGuildWebhook from "./GuildWebhook.js";
import { randomBytes } from "node:crypto";
import { GITHUB_AVATAR_URL } from "#shared/constants.js";

export default class GitCordGuild {
public guild!: Guild;
Expand Down Expand Up @@ -37,7 +38,7 @@ export default class GitCordGuild {
*/
public async create(channel: ForumChannel | TextChannel) {
const type = channel.type === ChannelType.GuildForum ? "FORUM" : "CHANNEL";
const webhook = await channel.createWebhook({ name: "GitCord", avatar: "https://cdn.ijskoud.dev/files/2zVGPBN3ZmId.webp" }).catch(() => {
const webhook = await channel.createWebhook({ name: "GitCord", avatar: GITHUB_AVATAR_URL }).catch(() => {
throw new Error("Unable to create a webhook, probably missing permissions.");
});

Expand Down
16 changes: 16 additions & 0 deletions src/github/embeds/Ref/CreateRefEmbed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { GitHubEmbed, type GitHubEmbedOptions } from "#github/lib/embed/structures/GitHubEmbed.js";
import type { CreateEvent } from "@octokit/webhooks-types";
import type { EmbedBuilder } from "discord.js";
import { ApplyOptions } from "#github/lib/embed/decorators.js";
import _ from "lodash";

@ApplyOptions<GitHubEmbedOptions>({ name: "create" })
export default class extends GitHubEmbed {
public override run(event: CreateEvent, embed: EmbedBuilder) {
const type = _.capitalize(event.ref_type);
const updatedTitle = embed.data.title!.replace("{type}", type);
embed.setTitle(updatedTitle).setDescription(`${type}: **${event.ref}**`);

return embed;
}
}
16 changes: 16 additions & 0 deletions src/github/embeds/Ref/DeleteRefEmbed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { GitHubEmbed, type GitHubEmbedOptions } from "#github/lib/embed/structures/GitHubEmbed.js";
import type { CreateEvent } from "@octokit/webhooks-types";
import type { EmbedBuilder } from "discord.js";
import { ApplyOptions } from "#github/lib/embed/decorators.js";
import _ from "lodash";

@ApplyOptions<GitHubEmbedOptions>({ name: "delete" })
export default class extends GitHubEmbed {
public override run(event: CreateEvent, embed: EmbedBuilder) {
const type = _.capitalize(event.ref_type);
const updatedTitle = embed.data.title!.replace("{type}", type);
embed.setTitle(updatedTitle).setDescription(`${type}: **${event.ref}**`);

return embed;
}
}
20 changes: 20 additions & 0 deletions src/github/embeds/commits/CommitComment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { GitHubEmbed, type GitHubEmbedOptions } from "#github/lib/embed/structures/GitHubEmbed.js";
import type { CommitCommentEvent } from "@octokit/webhooks-types";
import type { EmbedBuilder } from "discord.js";
import { ApplyOptions } from "#github/lib/embed/decorators.js";
import { EmbedLimits } from "@sapphire/discord-utilities";

@ApplyOptions<GitHubEmbedOptions>({ name: "commit_comment" })
export default class extends GitHubEmbed {
public override run(event: CommitCommentEvent, embed: EmbedBuilder) {
const commit = event.comment.commit_id.slice(0, 7);
const commitUrl = `https://github.com/${event.repository.full_name}/commit/${event.comment.commit_id}`;

embed
.setURL(event.comment.html_url)
.setDescription(event.comment.body.slice(0, EmbedLimits.MaximumDescriptionLength))
.addFields([{ name: "On commit", value: `[\`${commit}\`](${commitUrl})` }]);

return embed;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { GitHubEmbed, type GitHubEmbedOptions } from "../lib/embed/structures/GitHubEmbed.js";
import { GitHubEmbed, type GitHubEmbedOptions } from "#github/lib/embed/structures/GitHubEmbed.js";
import type { PushEvent } from "@octokit/webhooks-types";
import type { EmbedBuilder } from "discord.js";
import { ApplyOptions } from "../lib/embed/decorators.js";
import { ApplyOptions } from "#github/lib/embed/decorators.js";
import { EMBED_COLORS } from "#github/lib/types.js";

@ApplyOptions<GitHubEmbedOptions>({ name: "push" })
export default class extends GitHubEmbed {
Expand All @@ -12,14 +13,17 @@ export default class extends GitHubEmbed {

const refUrl = `${event.repository.svn_url}/tree/${id}`;
const commits = event.commits.map(
(commit) => `[\`${commit.id.slice(0, 7)}\`](${commit.url}) ${commit.message} - ${commit.author.username || commit.author.name}`
(commit) =>
`[\`${commit.id.slice(0, 7)}\`](${commit.url}) ${commit.message.split("\n")[0]} - ${commit.author.username || commit.author.name}`
);

embed.setDescription(commits.join("\n").slice(0, 4096));
embed.addFields({ name: `On ${type}`, value: `[${id}](${refUrl})`.slice(0, 1024) });

const updatedTitle = embed.data.title!.replace(`{commit_count}`, commits.length.toString());
embed.setTitle(`${updatedTitle}${commits.length === 1 ? "" : "s"}`);
embed.setTitle(`${updatedTitle}${commits.length === 1 ? "" : "s"} ${event.forced ? `(forced)` : ""}`.trim());

if (event.forced) embed.setColor(EMBED_COLORS.FAILED);

return embed;
}
Expand Down
23 changes: 23 additions & 0 deletions src/github/embeds/issues/IssueComment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { GitHubEmbed, type GitHubEmbedOptions } from "#github/lib/embed/structures/GitHubEmbed.js";
import type { IssueCommentEvent } from "@octokit/webhooks-types";
import type { EmbedBuilder } from "discord.js";
import { ApplyOptions } from "#github/lib/embed/decorators.js";
import { EmbedLimits } from "@sapphire/discord-utilities";

@ApplyOptions<GitHubEmbedOptions>({ name: "issue_comment" })
export default class extends GitHubEmbed {
public override run(event: IssueCommentEvent, embed: EmbedBuilder) {
if (event.action !== "created") return null;

const isPr = Boolean(event.issue.pull_request);
const issue = `${event.issue.title} (#${event.issue.number})`;

embed
.setTitle(`${event.repository.full_name} — ${isPr ? "Pull Request" : "Issue"} Comment Created`)
.setURL(event.comment.html_url)
.setDescription(event.comment.body.slice(0, EmbedLimits.MaximumDescriptionLength))
.addFields([{ name: `On ${isPr ? "Pull Request" : "Issue"}`, value: `[${issue}](${event.issue.html_url})` }]);

return embed;
}
}
108 changes: 108 additions & 0 deletions src/github/embeds/issues/IssueEmbed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { GitHubEmbed, type GitHubEmbedOptions } from "#github/lib/embed/structures/GitHubEmbed.js";
import type {
IssuesAssignedEvent,
IssuesClosedEvent,
IssuesDemilestonedEvent,
IssuesEvent,
IssuesMilestonedEvent,
IssuesOpenedEvent,
IssuesReopenedEvent,
IssuesUnassignedEvent
} from "@octokit/webhooks-types";
import type { EmbedBuilder } from "discord.js";
import { ApplyOptions } from "#github/lib/embed/decorators.js";
import { EMBED_COLORS } from "#github/lib/types.js";
import _ from "lodash";
import { EmbedLimits } from "@sapphire/discord-utilities";

@ApplyOptions<GitHubEmbedOptions>({ name: "issues" })
export default class extends GitHubEmbed {
public override run(event: IssuesEvent, embed: EmbedBuilder) {
embed.setURL(event.issue.html_url);

switch (event.action) {
case "opened":
case "reopened":
this.opened(event, embed);
break;
case "closed":
this.closed(event, embed);
break;
case "locked":
case "unlocked":
this.stageChange(event, embed);
break;
case "assigned":
case "unassigned":
this.assignUpdate(event, embed);
break;
case "demilestoned":
case "milestoned":
this.milestoneUpdate(event, embed);
break;
case "labeled":
case "unlabeled":
case "pinned":
case "unpinned":
case "deleted":
case "edited":
case "transferred":
return null;
default:
break;
}

return embed;
}

private opened(event: IssuesOpenedEvent | IssuesReopenedEvent, embed: EmbedBuilder) {
embed
.setTitle(`${embed.data.title} #${event.issue.number}`)
.setDescription([`Title: **${event.issue.title}**\n`, `${event.issue.body}`].join("\n").slice(0, EmbedLimits.MaximumDescriptionLength));
}

private closed(event: IssuesClosedEvent, embed: EmbedBuilder) {
embed
.setTitle(`${embed.data.title} #${event.issue.number}`)
.setDescription([`Title: **${event.issue.title}**`, `State: ${event.issue.active_lock_reason ?? "closed"}`].join("\n"));
}

private stageChange(event: IssuesEvent, embed: EmbedBuilder) {
const state = event.action
.replace(/\_/g, " ")
.trim()
.toLowerCase()
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");

embed
.setColor(EMBED_COLORS.UPDATE)
.setTitle(`${event.repository.full_name} — Issue #${event.issue.number}: Stage Update`)
.setDescription(`**${event.issue.title}**\nState: **${state}**`);
}

private assignUpdate(event: IssuesAssignedEvent | IssuesUnassignedEvent, embed: EmbedBuilder) {
embed
.setTitle(`${event.repository.full_name} — Issue #${event.issue.number}: User ${_.capitalize(event.action)}`)
.setDescription(
[
`**${event.issue.title}**`,
`Action: \`${_.capitalize(event.action)}\``,
`Assignee: [${event.assignee?.login}](${event.assignee?.html_url})`
].join("\n")
);
}

private milestoneUpdate(event: IssuesMilestonedEvent | IssuesDemilestonedEvent, embed: EmbedBuilder) {
embed
.setTitle(`${event.repository.full_name} — Issue #${event.issue.number}`)
.setDescription(
[
`**${event.issue.title}**`,
`Action: \`${_.capitalize(event.action)}\``,
`Milestone: [${event.milestone.title}](${event.milestone.html_url})`
].join("\n")
);
}
}
127 changes: 127 additions & 0 deletions src/github/embeds/pr/PullRequestEmbed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { GitHubEmbed, type GitHubEmbedOptions } from "#github/lib/embed/structures/GitHubEmbed.js";
import type {
PullRequestAssignedEvent,
PullRequestClosedEvent,
PullRequestDemilestonedEvent,
PullRequestEvent,
PullRequestMilestonedEvent,
PullRequestOpenedEvent,
PullRequestReopenedEvent,
PullRequestReviewRequestRemovedEvent,
PullRequestReviewRequestedEvent,
PullRequestUnassignedEvent
} from "@octokit/webhooks-types";
import type { EmbedBuilder } from "discord.js";
import { ApplyOptions } from "#github/lib/embed/decorators.js";
import { EMBED_COLORS } from "#github/lib/types.js";
import _ from "lodash";
import { EmbedLimits } from "@sapphire/discord-utilities";

@ApplyOptions<GitHubEmbedOptions>({ name: "pull_request" })
export default class extends GitHubEmbed {
public override run(event: PullRequestEvent, embed: EmbedBuilder) {
embed.setURL(event.pull_request.html_url);

switch (event.action) {
case "opened":
case "reopened":
this.opened(event, embed);
break;
case "closed":
this.closed(event, embed);
break;
case "converted_to_draft":
case "ready_for_review":
case "locked":
case "unlocked":
this.stageChange(event, embed);
break;
case "assigned":
case "unassigned":
this.assignUpdate(event, embed);
break;
case "demilestoned":
case "milestoned":
this.milestoneUpdate(event, embed);
break;
case "review_requested":
case "review_request_removed":
this.reviewUpdate(event, embed);
break;
case "auto_merge_disabled":
case "auto_merge_enabled":
case "queued":
case "synchronize":
case "edited":
case "dequeued":
case "labeled":
case "unlabeled":
return null;
default:
break;
}

return embed;
}

private opened(event: PullRequestOpenedEvent | PullRequestReopenedEvent, embed: EmbedBuilder) {
embed
.setTitle(`${embed.data.title} #${event.pull_request.number}`)
.setDescription(
[`Title: **${event.pull_request.title}**\n`, `${event.pull_request.body}`].join("\n").slice(0, EmbedLimits.MaximumDescriptionLength)
);
}

private closed(event: PullRequestClosedEvent, embed: EmbedBuilder) {
embed
.setTitle(`${embed.data.title} #${event.pull_request.number}`)
.setDescription([`Title: **${event.pull_request.title}**`, `State: ${event.pull_request.merged ? "merged" : "closed"}`].join("\n"));
}

private stageChange(event: PullRequestEvent, embed: EmbedBuilder) {
const state = event.action
.replace(/\_/g, " ")
.trim()
.toLowerCase()
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");

embed
.setColor(EMBED_COLORS.UPDATE)
.setTitle(`${event.repository.full_name} — Pull Request #${event.pull_request.number}: Stage Update`)
.setDescription(`**${event.pull_request.title}**\nState: \`${state}\``);
}

private assignUpdate(event: PullRequestAssignedEvent | PullRequestUnassignedEvent, embed: EmbedBuilder) {
embed
.setTitle(`${event.repository.full_name} — Pull Request #${event.pull_request.number}: User ${_.capitalize(event.action)}`)
.setDescription([`**${event.pull_request.title}**`, `Assignee: [${event.assignee.login}](${event.assignee.html_url})`].join("\n"));
}

private milestoneUpdate(event: PullRequestMilestonedEvent | PullRequestDemilestonedEvent, embed: EmbedBuilder) {
embed
.setTitle(`${event.repository.full_name} — Pull Request #${event.pull_request.number}: ${_.capitalize(event.action)}`)
.setDescription([`**${event.pull_request.title}**`, `Milestone: [${event.milestone.title}](${event.milestone.html_url})`].join("\n"));
}

private reviewUpdate(event: PullRequestReviewRequestedEvent | PullRequestReviewRequestRemovedEvent, embed: EmbedBuilder) {
if ("requested_reviewer" in event) {
const action = event.action
.replace(/\_/g, " ")
.trim()
.toLowerCase()
.split(" ")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");

embed
.setTitle(`${event.repository.full_name} — Pull Request #${event.pull_request.number}: ${action}`)
.setDescription(
[`**${event.pull_request.title}**`, `Reviewer: [${event.requested_reviewer.login}](${event.requested_reviewer.html_url})`].join(
"\n"
)
);
}
}
}
14 changes: 14 additions & 0 deletions src/github/embeds/repository/CollaboratorEmbed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { GitHubEmbed, type GitHubEmbedOptions } from "#github/lib/embed/structures/GitHubEmbed.js";
import type { MemberEvent } from "@octokit/webhooks-types";
import type { EmbedBuilder } from "discord.js";
import { ApplyOptions } from "#github/lib/embed/decorators.js";

@ApplyOptions<GitHubEmbedOptions>({ name: "member" })
export default class extends GitHubEmbed {
public override run(event: MemberEvent, embed: EmbedBuilder) {
const updatedTitle = embed.data.title!.replace("Member", "Collaborator");
embed.setTitle(updatedTitle).setDescription(`Collaborator: [${event.member.login}](${event.member.html_url})`);

return embed;
}
}
Loading