From a5f1742918dadf2bb38744a93783e48829872dbb Mon Sep 17 00:00:00 2001 From: xHyroM Date: Fri, 21 Jul 2023 22:58:45 +0200 Subject: [PATCH 01/27] refactor: rewrite start working on full rewrite [part 1] --- .github/workflows/validate.yml | 47 ++- .gitignore | 2 - .prettierrc | 5 - bun.lockb | Bin 7878 -> 17869 bytes files/config.example.toml | 16 -- files/{utilities.toml => github.toml} | 1 - package.json | 16 +- scripts/validateTags/files.json | 3 - scripts/validateTags/package.json | 6 - scripts/validateTags/src/index.ts | 115 -------- scripts/validate_tags/files.json | 1 + scripts/validate_tags/package.json | 6 + scripts/validate_tags/src/index.ts | 108 +++++++ scripts/validate_tags/src/types.d.ts | 4 + .../tsconfig.json | 0 src/Bient.ts | 39 +++ src/commands/Ping.ts | 9 + src/commands/github.ts | 135 --------- src/commands/ping.ts | 16 -- src/commands/tag.ts | 54 ---- src/commands/version.ts | 22 -- src/decorators/Command.ts | 6 + src/decorators/Listener.ts | 12 + src/index.ts | 224 +-------------- src/listeners/Ready.ts | 10 + src/managers/CommandManager.ts | 20 -- src/structures/Command.ts | 64 ----- src/structures/Option.ts | 96 ------- .../contexts/AutocompleteContext.ts | 26 -- src/structures/contexts/CommandContext.ts | 58 ---- src/utils.ts | 13 + src/utils/Logger.ts | 47 --- src/utils/discord.ts | 46 --- src/utils/githubUtils.ts | 270 ------------------ src/utils/loadCommands.ts | 17 -- src/utils/regexes.ts | 1 - src/utils/registerCommands.ts | 56 ---- src/utils/tagsUtils.ts | 69 ----- src/utils/verify.ts | 104 ------- tsconfig.json | 19 +- 40 files changed, 252 insertions(+), 1511 deletions(-) delete mode 100644 .prettierrc delete mode 100644 files/config.example.toml rename files/{utilities.toml => github.toml} (88%) delete mode 100644 scripts/validateTags/files.json delete mode 100644 scripts/validateTags/package.json delete mode 100644 scripts/validateTags/src/index.ts create mode 100644 scripts/validate_tags/files.json create mode 100644 scripts/validate_tags/package.json create mode 100644 scripts/validate_tags/src/index.ts create mode 100644 scripts/validate_tags/src/types.d.ts rename scripts/{validateTags => validate_tags}/tsconfig.json (100%) create mode 100644 src/Bient.ts create mode 100644 src/commands/Ping.ts delete mode 100644 src/commands/github.ts delete mode 100644 src/commands/ping.ts delete mode 100644 src/commands/tag.ts delete mode 100644 src/commands/version.ts create mode 100644 src/decorators/Command.ts create mode 100644 src/decorators/Listener.ts create mode 100644 src/listeners/Ready.ts delete mode 100644 src/managers/CommandManager.ts delete mode 100644 src/structures/Command.ts delete mode 100644 src/structures/Option.ts delete mode 100644 src/structures/contexts/AutocompleteContext.ts delete mode 100644 src/structures/contexts/CommandContext.ts create mode 100644 src/utils.ts delete mode 100644 src/utils/Logger.ts delete mode 100644 src/utils/discord.ts delete mode 100644 src/utils/githubUtils.ts delete mode 100644 src/utils/loadCommands.ts delete mode 100644 src/utils/regexes.ts delete mode 100644 src/utils/registerCommands.ts delete mode 100644 src/utils/tagsUtils.ts delete mode 100644 src/utils/verify.ts diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 5c808bb..0b76e69 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -1,34 +1,33 @@ name: Validate on: - pull_request_target: + pull_request_target: jobs: - test: - runs-on: ubuntu-latest + test: + runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - ref: refs/pull/${{ github.event.number }}/merge + steps: + - uses: actions/checkout@v2 + with: + ref: refs/pull/${{ github.event.number }}/merge - - name: Setup Bun - uses: xhyrom/setup-bun@v0.1.3 - with: - bun-version: latest - github-token: ${{ secrets.GITHUB_TOKEN }} + - name: Setup Bun + uses: oven-sh/setup-bun@v1 + with: + bun-version: latest - - name: Get changed files - uses: Mineflash07/gh-action-get-changed-files@feature/support-pr-target-event - with: - token: ${{ secrets.GITHUB_TOKEN }} + - name: Get changed files + uses: Mineflash07/gh-action-get-changed-files@feature/support-pr-target-event + with: + token: ${{ secrets.GITHUB_TOKEN }} - - name: Add json - run: cp $HOME/files.json ./scripts/validateTags/ + - name: Update files.json file + run: cp $HOME/files.json ./scripts/validate_tags/ - - name: Validate tag - run: bun run validate - env: - github-token: ${{ secrets.GITHUB_TOKEN }} - commit-sha: ${{ github.event.pull_request.head.sha }} - pr-number: ${{ github.event.pull_request.number }} \ No newline at end of file + - name: Validate tags + run: bun run validate:tags + env: + github-token: ${{ secrets.GITHUB_TOKEN }} + commit-sha: ${{ github.event.pull_request.head.sha }} + pr-number: ${{ github.event.pull_request.number }} diff --git a/.gitignore b/.gitignore index d2c0e42..54d3912 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,6 @@ # Edit at https://www.toptal.com/developers/gitignore?templates=node files/database.sqlite -files/config.toml -requests.rest ### Node ### # Logs diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index a8d8fcb..0000000 --- a/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "tabWidth": 4, - "singleQuote": true, - "trailingComma": "es5" -} diff --git a/bun.lockb b/bun.lockb index 5e84d2896f59134ebe98cbeafc25017eb06280a9..4d5507a3a491730acfabbceb6457503551456ebb 100755 GIT binary patch literal 17869 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 H|NZ|TN^J@@ literal 7878 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' - ) errors.push(`**[${key}]:** Link must be wrapped in <>`); - } - } - - if (tag.keywords) { - const keywords = [...new Set(tag.keywords)]; - if (keywords.length !== tag.keywords.length) errors.push(`**[${key}]:** Keywords must be unique`); - } -} - -if (errors.length === 0) { - requestGithub( - `pulls/${pullRequestNumber}/reviews`, - { - commit_id: commitSha, - event: 'APPROVE', - } - ); - - requestGithub( - `pulls/${pullRequestNumber}/requested_reviewers`, - { - reviewers: ['xHyroM'] - } - ); - - requestGithub( - `issues/${pullRequestNumber}/labels/waiting`, - {}, - 'DELETE' - ); - - requestGithub( - `issues/${pullRequestNumber}/labels`, - { - labels: ['ready'] - } - ); -} else { - requestGithub( - `pulls/${pullRequestNumber}/reviews`, - { - commit_id: commitSha, - body: '### Please fix the following problems:\n' + errors.join('\n'), - event: 'REQUEST_CHANGES', - } - ); - - requestGithub( - `issues/${pullRequestNumber}/labels`, - { - labels: ['waiting'] - } - ); -} - -function requestGithub(url: string, body: any, method?: 'POST' | 'DELETE') { - fetch(`https://api.github.com/repos/xHyroM/bun-discord-bot/${url}`, { - method: method || 'POST', - headers: { - 'Accept': 'application/vnd.github+json', - 'Authorization': `token ${githubToken}` - }, - body: JSON.stringify(body) - }) -} - -export { }; diff --git a/scripts/validate_tags/files.json b/scripts/validate_tags/files.json new file mode 100644 index 0000000..fe993dd --- /dev/null +++ b/scripts/validate_tags/files.json @@ -0,0 +1 @@ +["files/tags.toml"] diff --git a/scripts/validate_tags/package.json b/scripts/validate_tags/package.json new file mode 100644 index 0000000..809891a --- /dev/null +++ b/scripts/validate_tags/package.json @@ -0,0 +1,6 @@ +{ + "name": "validate_tags", + "scripts": { + "start": "bun src/index.ts" + } +} diff --git a/scripts/validate_tags/src/index.ts b/scripts/validate_tags/src/index.ts new file mode 100644 index 0000000..eefc19d --- /dev/null +++ b/scripts/validate_tags/src/index.ts @@ -0,0 +1,108 @@ +interface Tag { + keywords: string[]; + content: string; +} + +const githubToken = process.env['github-token']; +const commitSha = process.env['commit-sha']; +const pullRequestNumber = process.env['pr-number']; + +const codeBlockRegex = /(`{1,3}).+?\1/gs; +const urlRegex = + /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&\/\/=]*)/gi; + +// Check if files/tags.toml was changed +const files = await Bun.file('./files.json').text(); +if (!files.includes('files/tags.toml')) process.exit(0); + +const errors = []; + +let tags; +try { + tags = (await import('../../../files/tags.toml')).default; + + await requestGithub(`issues/${pullRequestNumber}/labels`, { + labels: ['tags'], + }); +} catch (e) { + tags = []; + errors.push(e.message); +} + +for (const [key, value] of Object.entries(tags)) { + const tag = value as Tag; + + if (!tag?.keywords || tag.keywords.length === 0) + errors.push(`**[${key}]:** Tag must have keywords`); + if (tag?.keywords?.[0] !== key) + errors.push( + `**[${key}]:** First keyword of tag is not the same as the tag name` + ); + if (!tag.content) errors.push(`**[${key}]:** Tag must have content`); + + if (tag.content) { + const cleanedContent = tag.content + .replaceAll('+++', '```') + .replace(codeBlockRegex, ''); + for (const url of cleanedContent.match(urlRegex) || []) { + const firstChar = tag.content.split(url)[0].slice(-1); + const lastChar = tag.content.split(url)[1].slice(0, 1); + if (firstChar !== '<' || lastChar !== '>') + errors.push(`**[${key}]:** Link must be wrapped in <>`); + } + } + + if (tag.keywords) { + const keywords = [...new Set(tag.keywords)]; + if (keywords.length !== tag.keywords.length) + errors.push(`**[${key}]:** Keywords must be unique`); + } +} + +if (errors.length === 0) { + await requestGithub(`pulls/${pullRequestNumber}/reviews`, { + commit_id: commitSha, + event: 'APPROVE', + }); + + await requestGithub(`pulls/${pullRequestNumber}/requested_reviewers`, { + reviewers: ['xHyroM'], + }); + + await requestGithub( + `issues/${pullRequestNumber}/labels/waiting`, + {}, + 'DELETE' + ); + + await requestGithub(`issues/${pullRequestNumber}/labels`, { + labels: ['ready'], + }); +} else { + await requestGithub(`pulls/${pullRequestNumber}/reviews`, { + commit_id: commitSha, + body: '### Please fix the following problems:\n' + errors.join('\n'), + event: 'REQUEST_CHANGES', + }); + + await requestGithub(`issues/${pullRequestNumber}/labels`, { + labels: ['waiting'], + }); +} + +async function requestGithub( + url: string, + body: any, + method?: 'POST' | 'DELETE' +) { + await fetch(`https://api.github.com/repos/xHyroM/bun-discord-bot/${url}`, { + method: method || 'POST', + headers: { + Accept: 'application/vnd.github+json', + Authorization: `token ${githubToken}`, + }, + body: JSON.stringify(body), + }); +} + +export {}; diff --git a/scripts/validate_tags/src/types.d.ts b/scripts/validate_tags/src/types.d.ts new file mode 100644 index 0000000..87dc72a --- /dev/null +++ b/scripts/validate_tags/src/types.d.ts @@ -0,0 +1,4 @@ +declare module '*.toml' { + const value: any; + export default value; +} diff --git a/scripts/validateTags/tsconfig.json b/scripts/validate_tags/tsconfig.json similarity index 100% rename from scripts/validateTags/tsconfig.json rename to scripts/validate_tags/tsconfig.json diff --git a/src/Bient.ts b/src/Bient.ts new file mode 100644 index 0000000..67a647b --- /dev/null +++ b/src/Bient.ts @@ -0,0 +1,39 @@ +import { info } from "@paperdave/logger"; +import { Client, ClientOptions } from "discord.js"; +import { redactToken } from "./utils"; + +export class Bient extends Client { + public static instance: Bient; + + constructor(options: ClientOptions) { + super(options); + + Bient.instance = this; + } + + public async load(): Promise { + info("Loading listeners and commands..."); + + const start = performance.now(); + + await this.loadListeners(); + await this.loadCommands(); + + const end = performance.now(); + + info(`Loaded listeners and commands in ${end - start}ms`); + } + + public async loadCommands(): Promise { + await import("./commands/Ping.ts"); + } + + public async loadListeners(): Promise { + await import("./listeners/Ready.ts"); + } + + public login(): Promise { + info(`Logging in using ${redactToken(process.env.BOT_TOKEN)}`); + return super.login(process.env.BOT_TOKEN); + } +} diff --git a/src/commands/Ping.ts b/src/commands/Ping.ts new file mode 100644 index 0000000..f0523d2 --- /dev/null +++ b/src/commands/Ping.ts @@ -0,0 +1,9 @@ +import { CommandInteraction } from "discord.js"; +import { Command } from "../decorators/Command"; + +@Command("ping") +export class Ping { + async run(context: CommandInteraction) { + context.reply("Pong!"); + } +} diff --git a/src/commands/github.ts b/src/commands/github.ts deleted file mode 100644 index c833bac..0000000 --- a/src/commands/github.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { APIApplicationCommandInteractionDataStringOption, ApplicationCommandOptionType, InteractionResponseType, MessageFlags } from 'discord-api-types/v10'; -import { Command } from '../structures/Command'; -// @ts-expect-error Types :( -import utilities from '../../files/utilities.toml'; -import { CommandContext } from '../structures/contexts/CommandContext'; -import { getIssueOrPR, search, formatStatus, formatEmojiStatus, IssueState, IssueType } from '../utils/githubUtils'; - -const invalidIssue = (ctx: CommandContext, query: string) => { - 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)` - ); -} - -new Command({ - name: 'github', - description: 'Query an issue, pull request or direct link to Github Issue or PR', - options: [ - { - name: 'query', - description: 'Issue numer/name, PR number/name or direct link to Github Issue or PR', - type: ApplicationCommandOptionType.String, - required: true, - run: async(ctx) => { - return ctx.respond( - await search( - ctx.value, - (ctx.options.find(o => o.name === 'repository'))?.value as string || 'oven-sh/bun', - (ctx.options.find(o => o.name === 'state')?.value as string || 'all') as IssueState, - (ctx.options.find(o => o.name === 'type')?.value as string || '(IS|PR)') as IssueType, - ) - ); - } - }, - { - name: 'state', - description: 'Issue or PR state', - type: ApplicationCommandOptionType.String, - required: false, - choices: [ - { - name: 'open', - value: 'open', - }, - { - name: 'closed', - value: 'closed', - }, - { - name: 'merged', - value: 'merged', - }, - { - name: 'all (default)', - value: 'all', - } - ] - }, - { - name: 'type', - description: 'Issues or PRs', - type: ApplicationCommandOptionType.String, - required: false, - choices: [ - { - name: 'Issues', - value: '(IS)', - }, - { - name: 'Pull Requests', - value: '(PR)', - }, - { - name: 'Both', - value: '(IS|PR)', - } - ] - }, - { - name: 'repository', - description: 'Project repository (default oven-sh/bun)', - type: ApplicationCommandOptionType.String, - required: false, - choices: [ - ...utilities.github.repositories.map(repository => new Object({ - name: repository.split('/')[1], - value: repository - })) - ] - }, - ], - run: async(ctx) => { - ctx.command.runEditResponse(ctx) - return ctx.respond({ - type: InteractionResponseType.DeferredChannelMessageWithSource - }) - }, - runEditResponse: async(ctx) => { - let query: string = (ctx.options[0] as APIApplicationCommandInteractionDataStringOption).value; - const repository: string = (ctx.options.find(o => o.name === 'repository') as APIApplicationCommandInteractionDataStringOption)?.value || 'oven-sh/bun'; - const state: IssueState = ((ctx.options.find(o => o.name === 'state') as APIApplicationCommandInteractionDataStringOption)?.value || 'all') as IssueState; - const type: IssueType = ((ctx.options.find(o => o.name === 'type') as APIApplicationCommandInteractionDataStringOption)?.value || '(IS|PR)') as IssueType; - - const repositorySplit = repository.split('/'); - const repositoryOwner = repositorySplit[0]; - const repositoryName = repositorySplit[1]; - - let issueOrPR = await getIssueOrPR(parseInt(query), repository, state, type); - if (!issueOrPR) { - const res = await fetch(`https://api.github.com/search/issues?q=${encodeURIComponent(query)}${encodeURIComponent(' repo:oven-sh/bun')}`); - - const data: any = await res.json(); - if (data.message || data?.items?.length === 0) return invalidIssue(ctx, query); - - const item = data.items[0]; - issueOrPR = { - id: item.number, - repository: item.repository_url.replace('https://api.github.com/repos/', ''), - title: item.title, - number: item.number, - state: item.state, - created_at: item.created_at, - closed_at: item.closed_at, - html_url: item.html_url, - user_login: item.user.login, - user_html_url: item.user.html_url, - type: item.pull_request ? '(PR)' : '(IS)', - }; - } - - return ctx.editResponse([ - `${formatEmojiStatus(issueOrPR)} [#${issueOrPR.number} ${issueOrPR.title.replace(/\[\]/g, '').slice(0, 1500)} (${repositoryOwner}/${repositoryName})](<${issueOrPR.html_url}>) by [${issueOrPR.user_login}](<${issueOrPR.user_html_url}>) ${formatStatus(issueOrPR)}`, - issueOrPR.title - ].join('\n')); - } -}) \ No newline at end of file diff --git a/src/commands/ping.ts b/src/commands/ping.ts deleted file mode 100644 index 5bc9178..0000000 --- a/src/commands/ping.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { InteractionResponseType, MessageFlags } from 'discord-api-types/v10'; -import { Command } from '../structures/Command'; - -new Command({ - name: 'ping', - description: 'pong', - run: (ctx) => { - return ctx.respond({ - type: InteractionResponseType.ChannelMessageWithSource, - data: { - content: 'Pong 🏓', - flags: MessageFlags.Ephemeral, - } - }) - } -}) \ No newline at end of file diff --git a/src/commands/tag.ts b/src/commands/tag.ts deleted file mode 100644 index 32e9a6d..0000000 --- a/src/commands/tag.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { - APIApplicationCommandInteractionDataStringOption, - ApplicationCommandOptionType, - InteractionResponseType, - MessageFlags, -} from 'discord-api-types/v10'; -import { Command } from '../structures/Command'; -import { findTags, getTag } from '../utils/tagsUtils'; - -new Command({ - name: 'tag', - description: 'Send a tag by name or alias', - options: [ - { - name: 'query', - description: 'Tag name or alias', - type: ApplicationCommandOptionType.String, - required: true, - run: (ctx) => { - return ctx.respond(findTags(ctx.value)); - }, - }, - { - name: 'target', - description: 'User to mention', - type: ApplicationCommandOptionType.User, - required: false, - }, - ], - run: (ctx) => { - const query: APIApplicationCommandInteractionDataStringOption = ctx - .options[0] as APIApplicationCommandInteractionDataStringOption; - const target = ctx?.resolved?.users - ? Object.values(ctx?.resolved?.users)[0] - : null; - - const tag = getTag(query.value, false); - if (!tag) - return ctx.respond({ - type: InteractionResponseType.ChannelMessageWithSource, - data: { - content: `\`❌\` Could not find a tag \`${query.value}\``, - flags: MessageFlags.Ephemeral, - }, - }); - - return ctx.respond( - [ - target ? `*Tag suggestion for <@${target.id}>:*` : '', - tag.content, - ].join('\n') - ); - }, -}); diff --git a/src/commands/version.ts b/src/commands/version.ts deleted file mode 100644 index 5cc58ba..0000000 --- a/src/commands/version.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { InteractionResponseType, MessageFlags } from 'discord-api-types/v10'; -import { Command } from '../structures/Command'; -import { exec } from 'bun-utilities/spawn'; - -const commitHash = exec(['git', 'log', '--pretty=format:\'%h\'', '-n', '1']).stdout.replaceAll('\'', ''); - -new Command({ - name: 'version', - description: 'Check bot and bun version', - run: (ctx) => { - return ctx.respond({ - type: InteractionResponseType.ChannelMessageWithSource, - data: { - content: [ - `Bot version: [git-bun-discord-bot-"${commitHash}"]()`, - `Bun version: [${process.version}]()`, - ].join('\n'), - flags: MessageFlags.Ephemeral, - } - }) - } -}) \ No newline at end of file diff --git a/src/decorators/Command.ts b/src/decorators/Command.ts new file mode 100644 index 0000000..a801c65 --- /dev/null +++ b/src/decorators/Command.ts @@ -0,0 +1,6 @@ +import { ClientEvents } from "discord.js"; +import { Bient } from "../Bient"; + +export function Command(name: string) { + return (constructor: Function, context: ClassDecoratorContext) => {}; +} diff --git a/src/decorators/Listener.ts b/src/decorators/Listener.ts new file mode 100644 index 0000000..f156cd7 --- /dev/null +++ b/src/decorators/Listener.ts @@ -0,0 +1,12 @@ +import { ClientEvents } from "discord.js"; +import { Bient } from "../Bient"; + +export function Listener(event: keyof ClientEvents) { + return (constructor: Function, context: ClassMethodDecoratorContext) => { + const name = context as unknown as string; + + Bient.instance.on.bind(Bient.instance)(event, (...args) => + constructor[name]([...args]) + ); + }; +} diff --git a/src/index.ts b/src/index.ts index 778423a..97913f9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,222 +1,10 @@ -import { Hono } from 'hono'; -import { bodyParse } from 'hono/body-parse'; -import { Logger } from './utils/Logger'; +import { GatewayIntentBits } from "discord.js"; +import { Bient } from "./Bient.ts"; -// @ts-expect-error Types :( -import config from '../files/config.toml'; -import loadCommands from './utils/loadCommands'; -import { verifyGithubKey, verifyKey } from './utils/verify'; -import { - APIPingInteraction, - APIApplicationCommandInteraction, - APIMessageComponentInteraction, - InteractionType, - InteractionResponseType, - ApplicationCommandType, - APIApplicationCommandAutocompleteInteraction, - ApplicationCommandOptionType, -} from 'discord-api-types/v10'; -import { CommandContext } from './structures/contexts/CommandContext'; -import { Commands } from './managers/CommandManager'; -import registerCommands from './utils/registerCommands'; -import { Option, OptionOptions } from './structures/Option'; -import { AutocompleteContext } from './structures/contexts/AutocompleteContext'; -import { - deleteIssueOrPR, - fetchIssues, - fetchPullRequests, - setIssue, - setPullRequest, -} from './utils/githubUtils'; -import { removeExclamationFromNicknames } from './utils/discord'; - -await fetchIssues(); -await fetchPullRequests(); -(async () => { - Logger.info('Removing exclamation marks from nicknames...'); - await removeExclamationFromNicknames(config.client.token); - Logger.info('Removing is done!'); -})(); -await loadCommands(); -try { - await registerCommands(config.client.token, config.client.id); -} catch (e) { - console.log(e); -} - -const app = new Hono(); -app.get('*', (c) => c.redirect('https://www.youtube.com/watch?v=FMhScnY0dME')); // fireship :D - -app.post('/interaction', bodyParse(), async (c) => { - const signature = c.req.headers.get('X-Signature-Ed25519'); - const timestamp = c.req.headers.get('X-Signature-Timestamp'); - if (!signature || !timestamp) - return c.redirect('https://www.youtube.com/watch?v=FMhScnY0dME'); // fireship :D - if ( - !(await verifyKey( - JSON.stringify(c.req.parsedBody), - signature, - timestamp, - config.client.public_key - )) - ) - return c.redirect('https://www.youtube.com/watch?v=FMhScnY0dME'); // fireship :D - - const interaction = c.req.parsedBody as unknown as - | APIPingInteraction - | APIApplicationCommandInteraction - | APIMessageComponentInteraction - | APIApplicationCommandAutocompleteInteraction; - - if (interaction.type === InteractionType.Ping) { - return new CommandContext(c).respond({ - type: InteractionResponseType.Pong, - }); - } - - if ( - interaction.type === InteractionType.ApplicationCommandAutocomplete && - interaction.data.type === ApplicationCommandType.ChatInput - ) { - const command = Commands.get(interaction.data.name); - let options = command.options; - const subCommandGroup = interaction.data.options.find( - (option) => - option.type === ApplicationCommandOptionType.SubcommandGroup - ); - const subCommand = interaction.data.options.find( - (option) => option.type === ApplicationCommandOptionType.Subcommand - ); - - // @ts-expect-error ?? find - if (subCommandGroup) - options = options.find( - (option) => option.name === subCommandGroup.name - )?.options; - // @ts-expect-error ?? find - if (subCommand) - options = options.find( - (option) => option.name === subCommand.name - )?.options; - - // @ts-expect-error i dont want waste time - const focused: APIApplicationCommandBasicOption = - interaction.data.options.find((option) => option.focused === true); - // @ts-expect-error ?? find - const option: Option | OptionOptions = options.find( - (option) => option.name === focused.name - ); - - return option.run( - new AutocompleteContext( - c, - option, - focused.value, - interaction.data.options as any - ) - ); - } - - if ( - interaction.type === InteractionType.ApplicationCommand && - interaction.data.type === ApplicationCommandType.ChatInput - ) { - const commands = Commands.get(interaction.data.name); - return await commands.run(new CommandContext(c, commands, interaction)); - } - - return new CommandContext(c).respond({ - type: InteractionResponseType.ChannelMessageWithSource, - data: { - content: 'Beep boop. Boop beep?', - }, - }); +const client = new Bient({ + intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages], }); -app.post('/github_webhook', bodyParse(), (c) => { - if ( - !c.req.headers.get('User-Agent').startsWith('GitHub-Hookshot/') || - typeof c.req?.parsedBody !== 'object' - ) - return c.redirect('https://www.youtube.com/watch?v=FMhScnY0dME'); // fireship :D +await client.load(); - if ( - !verifyGithubKey( - 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; - if (issueOrPr.action !== 'deleted') { - if ('issue' in issueOrPr) { - setIssue({ - id: issueOrPr.issue.number, - repository: issueOrPr.issue.repository_url.replace( - 'https://api.github.com/repos/', - '' - ), - title: issueOrPr.issue.title, - number: issueOrPr.issue.number, - state: issueOrPr.issue.state, - created_at: issueOrPr.issue.created_at, - closed_at: issueOrPr.issue.closed_at, - html_url: issueOrPr.issue.html_url, - user_login: issueOrPr.issue.user.login, - user_html_url: issueOrPr.issue.user.html_url, - type: '(IS)', - }); - } else if ('pull_request' in issueOrPr) { - setPullRequest({ - id: issueOrPr.pull_request.number, - repository: issueOrPr.pull_request.html_url - .replace('https://github.com/', '') - .replace(`/pull/${issueOrPr.pull_request.number}`, ''), - title: issueOrPr.pull_request.title, - number: issueOrPr.pull_request.number, - state: issueOrPr.pull_request.state, - created_at: issueOrPr.pull_request.created_at, - closed_at: issueOrPr.pull_request.closed_at, - merged_at: issueOrPr.pull_request.merged_at, - html_url: issueOrPr.pull_request.html_url, - user_login: issueOrPr.pull_request.user.login, - user_html_url: issueOrPr.pull_request.user.html_url, - type: '(PR)', - draft: issueOrPr.pull_request.draft, - }); - } - } else { - if ('issue' in issueOrPr) - deleteIssueOrPR( - issueOrPr.issue.number, - issueOrPr.issue.repository_url.replace( - 'https://api.github.com/repos/', - '' - ) - ); - else if ('pull_request' in issueOrPr) - deleteIssueOrPR( - issueOrPr.pull_request.number, - issueOrPr.pull_request.html_url - .replace('https://github.com/', '') - .replace(`/pull/${issueOrPr.pull_request.number}`, '') - ); - } - - return c.json( - { - message: 'OK', - }, - 200 - ); -}); - -await Bun.serve({ - port: config.server.port, - fetch: app.fetch, -}); - -Logger.info('🚀 Server started at', config.server.port.toString()); -Logger.debug(`🌍 http://localhost:${config.server.port}`); +client.login(); diff --git a/src/listeners/Ready.ts b/src/listeners/Ready.ts new file mode 100644 index 0000000..798c962 --- /dev/null +++ b/src/listeners/Ready.ts @@ -0,0 +1,10 @@ +import { success } from "@paperdave/logger"; +import { Listener } from "../decorators/Listener"; +import { ArgsOf } from "../utils"; + +export class Ready { + @Listener("ready") + onReady([client]: ArgsOf<"ready">) { + success(`Logged in as ${client.user?.tag}`); + } +} diff --git a/src/managers/CommandManager.ts b/src/managers/CommandManager.ts deleted file mode 100644 index 8b29447..0000000 --- a/src/managers/CommandManager.ts +++ /dev/null @@ -1,20 +0,0 @@ -import Collection from '@discordjs/collection'; -import { Command } from '../structures/Command'; - -class CommandManager extends Collection { - constructor() { - super(); - } - - public register(command: Command): CommandManager { - this.set(command.name, command); - return this; - } - - public unregister(command: Command): CommandManager { - this.delete(command.name); - return this; - } -} - -export const Commands = new CommandManager(); \ No newline at end of file diff --git a/src/structures/Command.ts b/src/structures/Command.ts deleted file mode 100644 index 6dd2a2f..0000000 --- a/src/structures/Command.ts +++ /dev/null @@ -1,64 +0,0 @@ -// Taken from https://github.com/Garlic-Team/gcommands/blob/next/src/lib/structures/Command.ts - -// @ts-expect-error Types :( -import config from '../../files/config.toml'; -import { LocaleString } from 'discord-api-types/v10'; -import { Commands } from '../managers/CommandManager'; -import { CommandContext } from './contexts/CommandContext'; -import { Option, OptionOptions } from './Option'; - -export interface CommandOptions { - name: string; - nameLocalizations?: Record; - description?: string; - descriptionLocalizations?: Record; - guildId?: string; - defaultMemberPermissions?: string; - options?: Option[] | OptionOptions[]; - run: (ctx: CommandContext) => Response | Promise; - runEditResponse?: (ctx: CommandContext) => any; -} - -export class Command { - public name: string; - public nameLocalizations?: Record; - public description?: string; - public descriptionLocalizations?: Record; - public guildId?: string = config.client.guild_id; - public defaultMemberPermissions?: string; - public options: Option[] | OptionOptions[]; - public run: (ctx: CommandContext) => Response | Promise; - public runEditResponse: (ctx: CommandContext) => any; - - public constructor(options: CommandOptions) { - this.name = options.name; - this.nameLocalizations = options.nameLocalizations; - - this.description = options.description; - this.descriptionLocalizations = options.descriptionLocalizations; - - this.guildId = options.guildId; - this.defaultMemberPermissions = options.defaultMemberPermissions; - - this.options = options.options?.map(option => { - if (option instanceof Option) return option; - else return new Option(option); - }); - this.run = options.run; - this.runEditResponse = options.runEditResponse; - - Commands.register(this); - } - - public toJSON(): Record { - return { - name: this.name, - name_localizations: this.nameLocalizations, - description: this.description, - description_localizations: this.descriptionLocalizations, - guild_id: this.guildId, - default_member_permissions: this.defaultMemberPermissions, - options: this.options?.map(option => option.toJSON()), - } - } -} \ No newline at end of file diff --git a/src/structures/Option.ts b/src/structures/Option.ts deleted file mode 100644 index e4683a9..0000000 --- a/src/structures/Option.ts +++ /dev/null @@ -1,96 +0,0 @@ -// Taken from https://github.com/Garlic-Team/gcommands/blob/next/src/lib/structures/Argument.ts - -import { ApplicationCommandOptionType, ChannelType, LocaleString } from 'discord-api-types/v10'; -import { AutocompleteContext } from './contexts/AutocompleteContext'; - -export interface OptionChoice { - name: string; - nameLocalizations?: Record; - value: string | number; -} - -export interface OptionOptions { - name: string; - nameLocalizations?: Record; - description: string; - descriptionLocalizations?: Record; - type: ApplicationCommandOptionType - required?: boolean; - choices?: OptionChoice[]; - options?: Array