diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..a8d8fcb --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "tabWidth": 4, + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/files/tags.toml b/files/tags.toml index 007aa0c..7bf0158 100644 --- a/files/tags.toml +++ b/files/tags.toml @@ -1,10 +1,7 @@ [bun] keywords = ["bun", "bun.sh"] content = """ -Bun is a modern JavaScript runtime like Node or Deno. It was built from scratch to focus on three main things: -• Start fast (it has the edge in mind). -• New levels of performance (extending JavaScriptCore, the engine). -• Being a great and complete tool (bundler, transpiler, package manager). +Bun is an all-in-one JavaScript runtime & toolkit designed for speed, complete with a bundler, test runner, and Node.js-compatible package manager. Read more [here]() """ @@ -13,42 +10,24 @@ Read more [here]() keywords = ["bug", "report", "bugs"] content = """ Found a bug in bun? -• If you are unsure, first discuss your bug in <#887787428973281300> or <#995247410794217553> -• [Open an issue on GitHub]() and fill out the given template +- If you are unsure, first discuss your bug in <#887787428973281300> or <#995247410794217553> +- [Open an issue on GitHub]() and fill out the given template """ [feature-request] keywords = ["feature-request", "feature", "request"] content = """ Any idea what to add to bun? -• Please consider if this is a request for bun, not for other 3rd party packages -• [Open an issue on GitHub]() and fill out the given template +- Please consider if this is a request for bun, not for other 3rd party packages +- [Open an issue on GitHub]() and fill out the given template """ -[contributing-tags] +[tags] keywords = ["contributing-tags", "contributing", "tags"] content = """ To create or update tag, check [xHyroM/bun-discord-bot#contributing-tags]() """ -[hono] -keywords = ["hono", "express", "server", "routes"] -content = """ -**Hono - [炎] means flame🔥 in Japanese** -• Is a small, simple, and ultrafast web framework for Cloudflare Workers, Deno, Bun, and others - -[Bun supports partially express, but you can also use hono.]() -""" - -[not-same-file-system] -keywords = ["not-same-file-system", "backend copyfile", "copyfile"] -content = """ -**error: NotSameFileSystem installing [package]** - -You have old bun. Use `bun upgrade` to upgrade. -If you have problems with upgrade, reinstall bun using `curl https://bun.sh/install | bash` -""" - [windows] keywords = ["windows", "windows support"] content = """ @@ -65,11 +44,11 @@ To fix this error, you need to update Linux kernel. If you are using the Windows Subsystem for Linux, do: **1.** Open powershell as administrator **2.** Run: - • wsl --set-version 2 - • If it throws `Please enable the Virtual Machine Platform Windows feature and ensure virtualization is enabled in the BIOS.`, turn on Virtual Machine Platform in Windows Features and then rerun this command. - • PS: You can get distro name from `wsl --list -v` - • wsl --update - • wsl --shutdown + - wsl --set-version 2 + - If it throws `Please enable the Virtual Machine Platform Windows feature and ensure virtualization is enabled in the BIOS.`, turn on Virtual Machine Platform in Windows Features and then rerun this command. + - PS: You can get distro name from `wsl --list -v` + - wsl --update + - wsl --shutdown If that doesn't work (and you're on a Windows machine), try this: **1.** Open Windows Update @@ -89,10 +68,23 @@ curl https://bun.sh/install | bash or install latest *-baseline build from [GitHub Releases]() """ -[why-zig] -keywords = ["why-zig", "zig", "zig-lang", "zig lang bun"] -content = """ -[**Zig**]() is a general-purpose programming language and toolchain for maintaining **robust**, **optimal** and **reusable** software. +# common questions -Its **low-level control over memory** and **lack of hidden control flow**, whilst retaining **simplicity** and **flexibility**, makes building _fast_ software (in development time as well) relatively easier. +[ts] # 'how do i use typescript or jsx?' +keywords = ["typescript", "tsc"] +content = """ +Bun supports TypeScript and JSX out of the box. They can be run directly with [`bun run`](https://bun.sh/docs/cli/run). +For setting up IDE support, [documentation page on TypeScript](https://bun.sh/docs/runtime/typescript) +""" + +[nix] # 'it doesnt work on nixos' +keywords = ["nix", "nixos"] +content = """ +To use Bun on NixOS, you must install it through the nix package manager using [the `bun` package in nixpkgs](https://search.nixos.org/packages?channel=unstable&show=bun&from=0&size=1&sort=relevance&type=packages&query=bun): + ++++ +nix-env -iA nixos.bun ++++ + +Using `bun upgrade` or the curl installer will not work because NixOS does not provide `ld.so` which means any non-nixos linux executables will not work (you'll see "File not found" when trying to run them, even though the binary is there). """ diff --git a/files/utilities.toml b/files/utilities.toml index 4e8db31..679cb2a 100644 --- a/files/utilities.toml +++ b/files/utilities.toml @@ -1,8 +1,5 @@ [github] repositories = [ "oven-sh/bun", - "oven-sh/docs", - "oven-sh/bun-dependencies", - "oven-sh/bun-types", "xHyroM/bun-discord-bot" ] diff --git a/src/commands/tags.ts b/src/commands/tag.ts similarity index 57% rename from src/commands/tags.ts rename to src/commands/tag.ts index 186bdb8..32e9a6d 100644 --- a/src/commands/tags.ts +++ b/src/commands/tag.ts @@ -1,9 +1,14 @@ -import { APIApplicationCommandInteractionDataStringOption, ApplicationCommandOptionType, InteractionResponseType, MessageFlags } from 'discord-api-types/v10'; +import { + APIApplicationCommandInteractionDataStringOption, + ApplicationCommandOptionType, + InteractionResponseType, + MessageFlags, +} from 'discord-api-types/v10'; import { Command } from '../structures/Command'; import { findTags, getTag } from '../utils/tagsUtils'; new Command({ - name: 'tags', + name: 'tag', description: 'Send a tag by name or alias', options: [ { @@ -13,18 +18,21 @@ new Command({ required: true, run: (ctx) => { return ctx.respond(findTags(ctx.value)); - } + }, }, { name: 'target', description: 'User to mention', type: ApplicationCommandOptionType.User, - required: false - } + 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 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) @@ -32,13 +40,15 @@ new Command({ type: InteractionResponseType.ChannelMessageWithSource, data: { content: `\`❌\` Could not find a tag \`${query.value}\``, - flags: MessageFlags.Ephemeral - } + flags: MessageFlags.Ephemeral, + }, }); - return ctx.respond([ - target ? `*Tag suggestion for <@${target.id}>:*` : '', - tag.content - ].join('\n')); - } -}) \ No newline at end of file + return ctx.respond( + [ + target ? `*Tag suggestion for <@${target.id}>:*` : '', + tag.content, + ].join('\n') + ); + }, +}); diff --git a/src/index.ts b/src/index.ts index 39832dc..778423a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,156 +6,217 @@ import { Logger } from './utils/Logger'; 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 { + 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 { + 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!'); +(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); + 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 +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; + 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?' + 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?', + }, + }); +}); 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 - - if ( - !verifyGithubKey( - JSON.stringify(c.req.parsedBody), - c.req.headers.get('X-Hub-Signature-256'), - config.api.github_webhooks_secret + 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 + 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)', - }) + 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}`, '') + ); } - 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/', '') + + return c.json( + { + message: 'OK', + }, + 200 ); - 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, + port: config.server.port, + fetch: app.fetch, }); Logger.info('🚀 Server started at', config.server.port.toString()); -Logger.debug(`🌍 http://localhost:${config.server.port}`); \ No newline at end of file +Logger.debug(`🌍 http://localhost:${config.server.port}`);