chore: cleanup

This commit is contained in:
xHyroM 2022-07-14 07:57:44 +02:00
parent 66ed183c13
commit 21b74eb472
6 changed files with 34 additions and 27 deletions

View file

@ -6,7 +6,6 @@ import Collection from '@discordjs/collection';
import { CommandContext } from '../structures/contexts/CommandContext'; import { CommandContext } from '../structures/contexts/CommandContext';
import { getIssueOrPR, search, formatStatus } from '../utils/githubUtils'; import { getIssueOrPR, search, formatStatus } from '../utils/githubUtils';
const cooldowns: Collection<string, number> = new Collection();
const invalidIssue = (ctx: CommandContext, query: string) => { const invalidIssue = (ctx: CommandContext, query: string) => {
return ctx.editResponse( return ctx.editResponse(
`\`\` Invalid issue or pull request \`${query}\`. You can check [github search syntax](https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests)` `\`\` Invalid issue or pull request \`${query}\`. You can check [github search syntax](https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests)`
@ -40,22 +39,12 @@ new Command({
} }
], ],
run: async(ctx) => { run: async(ctx) => {
if (cooldowns?.has(ctx.user.id) && cooldowns.get(ctx.user.id) > Date.now()) { ctx.command.runEditResponse(ctx)
return ctx.respond({ return ctx.respond({
type: InteractionResponseType.ChannelMessageWithSource, type: InteractionResponseType.DeferredChannelMessageWithSource
data: { })
content: `⚠️ You are in cooldown, you will be able to use this command <t:${Math.floor(cooldowns.get(ctx.user.id) / 1000)}:R>.`,
flags: MessageFlags.Ephemeral,
}
});
} else {
ctx.command.runWithoutReturn(ctx)
return ctx.respond({
type: InteractionResponseType.DeferredChannelMessageWithSource
})
}
}, },
runWithoutReturn: async(ctx) => { runEditResponse: async(ctx) => {
let query: string = (ctx.options[0] as APIApplicationCommandInteractionDataStringOption).value; let query: string = (ctx.options[0] as APIApplicationCommandInteractionDataStringOption).value;
const repository: string = (ctx.options?.[1] as APIApplicationCommandInteractionDataStringOption)?.value || 'oven-sh/bun'; const repository: string = (ctx.options?.[1] as APIApplicationCommandInteractionDataStringOption)?.value || 'oven-sh/bun';

View file

@ -5,7 +5,7 @@ import { Logger } from './utils/Logger';
// @ts-expect-error Types :( // @ts-expect-error Types :(
import config from '../files/config.toml'; import config from '../files/config.toml';
import loadCommands from './utils/loadCommands'; import loadCommands from './utils/loadCommands';
import { verifyKey } from './utils/verify'; import { verifyGithubKey, verifyKey } from './utils/verify';
import { APIPingInteraction, APIApplicationCommandInteraction, APIMessageComponentInteraction, InteractionType, InteractionResponseType, ApplicationCommandType, APIApplicationCommandAutocompleteInteraction, ApplicationCommandOptionType } from 'discord-api-types/v10'; import { APIPingInteraction, APIApplicationCommandInteraction, APIMessageComponentInteraction, InteractionType, InteractionResponseType, ApplicationCommandType, APIApplicationCommandAutocompleteInteraction, ApplicationCommandOptionType } from 'discord-api-types/v10';
import { CommandContext } from './structures/contexts/CommandContext'; import { CommandContext } from './structures/contexts/CommandContext';
import { Commands } from './managers/CommandManager'; import { Commands } from './managers/CommandManager';
@ -13,7 +13,6 @@ import registerCommands from './utils/registerCommands';
import { Option, OptionOptions } from './structures/Option'; import { Option, OptionOptions } from './structures/Option';
import { AutocompleteContext } from './structures/contexts/AutocompleteContext'; import { AutocompleteContext } from './structures/contexts/AutocompleteContext';
import { deleteIssueOrPR, fetchIssues, fetchPullRequests, setIssue, setPullRequest } from './utils/githubUtils'; import { deleteIssueOrPR, fetchIssues, fetchPullRequests, setIssue, setPullRequest } from './utils/githubUtils';
import createHmac from 'create-hmac';
await fetchIssues(); await fetchIssues();
await fetchPullRequests(); await fetchPullRequests();
@ -88,9 +87,13 @@ app.post('/github_webhook', bodyParse(), (c) => {
typeof c.req?.parsedBody !== 'object' typeof c.req?.parsedBody !== 'object'
) return c.redirect('https://www.youtube.com/watch?v=FMhScnY0dME'); // fireship :D ) return c.redirect('https://www.youtube.com/watch?v=FMhScnY0dME'); // fireship :D
const githubWebhooksSecret = new TextEncoder().encode(config.api.github_webhooks_secret); if (
const sha256 = `sha256=${createHmac('sha256', githubWebhooksSecret).update(JSON.stringify(c.req.parsedBody)).digest('hex')}`; !verifyGithubKey(
if (sha256 !== c.req.headers.get('X-Hub-Signature-256')) return c.redirect('https://www.youtube.com/watch?v=FMhScnY0dME'); // fireship :D JSON.stringify(c.req.parsedBody),
c.req.headers.get('X-Hub-Signature-256'),
config.api.github_webhooks_secret
)
) return c.redirect('https://www.youtube.com/watch?v=FMhScnY0dME'); // fireship :D
const issueOrPr = c.req.parsedBody; const issueOrPr = c.req.parsedBody;
if (issueOrPr.action !== 'deleted') { if (issueOrPr.action !== 'deleted') {

View file

@ -16,7 +16,7 @@ export interface CommandOptions {
defaultMemberPermissions?: string; defaultMemberPermissions?: string;
options?: Option[] | OptionOptions[]; options?: Option[] | OptionOptions[];
run: (ctx: CommandContext) => Response | Promise<Response>; run: (ctx: CommandContext) => Response | Promise<Response>;
runWithoutReturn?: (ctx: CommandContext) => any; runEditResponse?: (ctx: CommandContext) => any;
} }
export class Command { export class Command {
@ -28,7 +28,7 @@ export class Command {
public defaultMemberPermissions?: string; public defaultMemberPermissions?: string;
public options: Option[] | OptionOptions[]; public options: Option[] | OptionOptions[];
public run: (ctx: CommandContext) => Response | Promise<Response>; public run: (ctx: CommandContext) => Response | Promise<Response>;
public runWithoutReturn: (ctx: CommandContext) => any; public runEditResponse: (ctx: CommandContext) => any;
public constructor(options: CommandOptions) { public constructor(options: CommandOptions) {
this.name = options.name; this.name = options.name;
@ -45,7 +45,7 @@ export class Command {
else return new Option(option); else return new Option(option);
}); });
this.run = options.run; this.run = options.run;
this.runWithoutReturn = options.runWithoutReturn; this.runEditResponse = options.runEditResponse;
Commands.register(this); Commands.register(this);
} }

View file

@ -1 +0,0 @@
export default (value: string) => /^-?\d+$/.test(value);

View file

@ -1,2 +0,0 @@
export const githubIssuesAndPullRequests = (owner: string, repository: string) =>
new RegExp(`https?:\\\/\\\/github\\\.com\\\/${owner}\\\/${repository}\\\/(?:issues\\\/\\\d+|pull\\\/\d+)`, 'gm');

View file

@ -1,6 +1,7 @@
// from https://github.com/discord/discord-interactions-js/blob/main/src/index.ts // from https://github.com/discord/discord-interactions-js/blob/main/src/index.ts
import { sign } from 'tweetnacl'; import { sign } from 'tweetnacl';
import createHmac from 'create-hmac';
/** /**
* Converts different types to Uint8Array. * Converts different types to Uint8Array.
@ -83,4 +84,21 @@ export const verifyKey = (
console.error('[discord-interactions]: Invalid verifyKey parameters', ex); console.error('[discord-interactions]: Invalid verifyKey parameters', ex);
return false; return false;
} }
}
/**
* Validates a payload from GitHub against its signature and secret
*/
export const verifyGithubKey = (
body: string,
signature: string,
secret: string
): boolean => {
if (!body || !signature || !secret) return false;
const githubWebhooksSecret = new TextEncoder().encode(secret);
const sha256 = `sha256=${createHmac('sha256', githubWebhooksSecret).update(body).digest('hex')}`;
if (sha256 !== signature) return false;
return true;
} }