From 2b83d691b351b6666f1b3d86ceb3d5db5392acc1 Mon Sep 17 00:00:00 2001 From: Endy Date: Sat, 6 May 2023 21:57:43 +0700 Subject: [PATCH 01/12] Toggle `Interaction.acknowledged` in `defer` (#3022) --- packages/bot/src/transformers/interaction.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/bot/src/transformers/interaction.ts b/packages/bot/src/transformers/interaction.ts index 7f8430b6a..f18fd90b9 100644 --- a/packages/bot/src/transformers/interaction.ts +++ b/packages/bot/src/transformers/interaction.ts @@ -128,14 +128,16 @@ const baseInteraction: Partial & BaseInteraction = { if (this.acknowledged) throw new Error('Cannot defer an already responded interaction') // Determine the type of defer response - let type: InteractionResponseTypes - if (this.type === InteractionTypes.MessageComponent) type = InteractionResponseTypes.DeferredUpdateMessage - else type = InteractionResponseTypes.DeferredChannelMessageWithSource + const type = + this.type === InteractionTypes.MessageComponent + ? InteractionResponseTypes.DeferredUpdateMessage + : InteractionResponseTypes.DeferredChannelMessageWithSource // If user wants to send a private message const data: InteractionCallbackData = {} if (isPrivate) data.flags = 64 + this.acknowledged = true return await this.bot?.rest.sendInteractionResponse(this.id!, this.token!, { type, data }) }, From dfbee47667815b82d60d7645d1043a1622049a9a Mon Sep 17 00:00:00 2001 From: Endy Date: Mon, 8 May 2023 22:58:33 +0700 Subject: [PATCH 02/12] Fix `BaseInteraction.respond` & response validation (#3023) --- packages/bot/src/transformers/interaction.ts | 39 ++++++++------------ 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/packages/bot/src/transformers/interaction.ts b/packages/bot/src/transformers/interaction.ts index f18fd90b9..34616f433 100644 --- a/packages/bot/src/transformers/interaction.ts +++ b/packages/bot/src/transformers/interaction.ts @@ -23,10 +23,8 @@ import type { User } from './user.js' export interface Interaction extends BaseInteraction { /** The bot object */ bot: Bot - /** Whether or not this interaction has been replied to. */ + /** Whether or not this interaction has been responded to. */ acknowledged: boolean - /** Whether or not a modal has been shown for this interaction. */ - shownModal: boolean /** Id of the interaction */ id: bigint /** Id of the application this interaction is for */ @@ -84,41 +82,36 @@ const baseInteraction: Partial & BaseInteraction = { async respond(response, options) { let type = InteractionResponseTypes.ChannelMessageWithSource - // If user provides a string, change it to response object - if (typeof response === 'string') { - response = { - content: response, - } - } + // If user provides a string, change it to a response object + if (typeof response === 'string') response = { content: response } // If user provides an object, determine if it should be an autocomplete or a modal response - else { - if (response.title) type = InteractionResponseTypes.Modal - else if (this.type === InteractionTypes.ApplicationCommandAutocomplete) type = InteractionResponseTypes.ApplicationCommandAutocompleteResult - } + else if (response.title) type = InteractionResponseTypes.Modal + else if (this.type === InteractionTypes.ApplicationCommandAutocomplete) type = InteractionResponseTypes.ApplicationCommandAutocompleteResult // If user wants to send a private message if (type === InteractionResponseTypes.ChannelMessageWithSource && options?.isPrivate) response.flags = 64 // Since this has already been given a response, any further responses must be followups. if (this.acknowledged) return await this.bot?.rest.sendFollowupMessage(this.token!, response) - if (this.shownModal && type === InteractionResponseTypes.Modal) throw new Error('Cannot respond to a modal interaction with another modal.') + + // Modals cannot be chained + if (this.type === InteractionTypes.ModalSubmit && type === InteractionResponseTypes.Modal) + throw new Error('Cannot respond to a modal interaction with another modal.') + + // Autocomplete response can only be used for autocomplete interactions + if (this.type === InteractionTypes.ApplicationCommandAutocomplete && type !== InteractionResponseTypes.ApplicationCommandAutocompleteResult) + throw new Error('Cannot respond to an autocomplete interaction with a modal or message.') // If user has not already responded to this interaction we need to send an original response - if (type === InteractionResponseTypes.Modal) this.shownModal = true - if (type === InteractionResponseTypes.ChannelMessageWithSource) this.acknowledged = true - + this.acknowledged = true return await this.bot?.rest.sendInteractionResponse(this.id!, this.token!, { type, data: response }) }, async edit(response) { if (this.type === InteractionTypes.ApplicationCommandAutocomplete) throw new Error('Cannot edit an autocomplete interaction') - // If user provides a string, change it to response object - if (typeof response === 'string') { - response = { - content: response, - } - } + // If user provides a string, change it to a response object + if (typeof response === 'string') response = { content: response } return await this.bot!.rest.editOriginalInteractionResponse(this.token!, response) }, From a3e6551f221611bc52f7bc835082a4021cb052ac Mon Sep 17 00:00:00 2001 From: Awesome Stickz Date: Mon, 8 May 2023 21:29:23 +0530 Subject: [PATCH 03/12] fix(gateway): lastShardId (#3026) --- packages/gateway/src/manager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/gateway/src/manager.ts b/packages/gateway/src/manager.ts index 5cf467dfb..edaf9d132 100644 --- a/packages/gateway/src/manager.ts +++ b/packages/gateway/src/manager.ts @@ -32,7 +32,7 @@ export function createGatewayManager(options: CreateGatewayManagerOptions): Gate version: options.version ?? 10, connection: options.connection, totalShards: options.totalShards ?? options.connection.shards ?? 1, - lastShardId: options.lastShardId ?? 0, + lastShardId: options.lastShardId ?? (options.totalShards ? options.totalShards - 1 : (options.connection ? options.connection.shards - 1 : 0)), firstShardId: options.firstShardId ?? 0, totalWorkers: options.totalWorkers ?? 4, shardsPerWorker: options.shardsPerWorker ?? 25, From c76a17365573dad07f947d09d8cd0ab75b6f9950 Mon Sep 17 00:00:00 2001 From: Endy Date: Mon, 8 May 2023 23:33:57 +0700 Subject: [PATCH 04/12] Add `channel_types` prop to channel select menu (#3027) https://discord.com/developers/docs/interactions/message-components#select-menu-object-select-menu-structure --- packages/bot/src/transformers/component.ts | 5 ++++- packages/bot/src/transformers/reverse/component.ts | 1 + packages/bot/src/typings.ts | 9 ++++++--- packages/types/src/discord.ts | 2 ++ packages/types/src/discordeno.ts | 2 ++ 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/bot/src/transformers/component.ts b/packages/bot/src/transformers/component.ts index fefc0a6b9..08f71d8b4 100644 --- a/packages/bot/src/transformers/component.ts +++ b/packages/bot/src/transformers/component.ts @@ -1,4 +1,4 @@ -import type { ButtonStyles, MessageComponentTypes, SelectOption, TextStyles } from '@discordeno/types' +import type { ButtonStyles, ChannelTypes, MessageComponentTypes, SelectOption, TextStyles } from '@discordeno/types' import type { Bot } from '../index.js' import type { DiscordComponent } from '../typings.js' @@ -17,6 +17,7 @@ export function transformComponent(bot: Bot, payload: DiscordComponent): Compone } : undefined, url: payload.url, + channelTypes: payload.channel_types, options: payload.options?.map((option) => ({ label: option.label, value: option.value, @@ -68,6 +69,8 @@ export interface Component { } /** optional url for link-style buttons that can navigate a user to the web. Only type 5 Link buttons can have a url */ url?: string + /** List of channel types to include in a channel select menu options list */ + channelTypes?: ChannelTypes[] /** The choices! Maximum of 25 items. */ options?: SelectOption[] /** A custom placeholder text if nothing is selected. Maximum 150 characters. */ diff --git a/packages/bot/src/transformers/reverse/component.ts b/packages/bot/src/transformers/reverse/component.ts index d28622dc8..7180eaf5b 100644 --- a/packages/bot/src/transformers/reverse/component.ts +++ b/packages/bot/src/transformers/reverse/component.ts @@ -18,6 +18,7 @@ export function transformComponentToDiscordComponent(bot: Bot, payload: Componen } : undefined, url: payload.url, + channel_types: payload.channelTypes, options: payload.options?.map((option) => ({ label: option.label, value: option.value, diff --git a/packages/bot/src/typings.ts b/packages/bot/src/typings.ts index 5582e9af4..46b81621d 100644 --- a/packages/bot/src/typings.ts +++ b/packages/bot/src/typings.ts @@ -2,6 +2,7 @@ import { ApplicationCommandTypes, type AllowedMentions, type ButtonStyles, + type ChannelTypes, type CreateApplicationCommand, type CreateContextApplicationCommand, type DiscordAllowedMentions, @@ -16,13 +17,13 @@ import { type DiscordUser, type FileContent, type InteractionResponseTypes, - type MessageComponents, type MessageComponentTypes, + type MessageComponents, type TextStyles, } from '@discordeno/types' import type * as handlers from './handlers/index.js' -import type { Embed } from './transformers/embed.js' import type { ApplicationCommandOptionChoice } from './transformers/applicationCommandOptionChoice.js' +import type { Embed } from './transformers/embed.js' export function isContextApplicationCommand(command: CreateApplicationCommand): command is CreateContextApplicationCommand { return command.type === ApplicationCommandTypes.Message || command.type === ApplicationCommandTypes.User @@ -69,6 +70,8 @@ export interface DiscordComponent { } /** optional url for link-style buttons that can navigate a user to the web. Only type 5 Link buttons can have a url */ url?: string + /** List of channel types to include in a channel select menu options list */ + channel_types?: ChannelTypes[] /** The choices! Maximum of 25 items. */ options?: DiscordSelectOption[] /** A custom placeholder text if nothing is selected. Maximum 150 characters. */ @@ -205,7 +208,7 @@ export interface BotGatewayHandlerOptions { export enum MessageFlags { /** Whether this message has been published to subscribed channels (via Channel Following) */ - Crossposted = 1 << 0, + Crossposted = 1 << 0, /** Whether this message originated from a message in another channel (via Channel Following) */ IsCrosspost = 1 << 1, /** Whether do not include any embeds when serializing this message */ diff --git a/packages/types/src/discord.ts b/packages/types/src/discord.ts index 3416cb5f7..ca613ea98 100644 --- a/packages/types/src/discord.ts +++ b/packages/types/src/discord.ts @@ -1134,6 +1134,8 @@ export interface DiscordSelectMenuComponent { min_values?: number /** The maximum number of items that can be selected. Default 1. Between 1-25. */ max_values?: number + /** List of channel types to include in a channel select menu options list */ + channelTypes?: ChannelTypes[] /** The choices! Maximum of 25 items. */ options: DiscordSelectOption[] } diff --git a/packages/types/src/discordeno.ts b/packages/types/src/discordeno.ts index 38c184ea2..8c88d9e2b 100644 --- a/packages/types/src/discordeno.ts +++ b/packages/types/src/discordeno.ts @@ -195,6 +195,8 @@ export interface SelectMenuChannelsComponent { minValues?: number /** The maximum number of items that can be selected. Default 1. Between 1-25. */ maxValues?: number + /** List of channel types to include in the options list */ + channelTypes?: ChannelTypes[] /** Whether or not this select is disabled */ disabled?: boolean } From 5edfbb7efb74ddff24c830d8a92007bd21507d1b Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 8 May 2023 13:21:51 -0500 Subject: [PATCH 05/12] fix: localization snake case bug --- packages/rest/src/manager.ts | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/packages/rest/src/manager.ts b/packages/rest/src/manager.ts index f820f566c..b519a449d 100644 --- a/packages/rest/src/manager.ts +++ b/packages/rest/src/manager.ts @@ -118,18 +118,29 @@ export function createRestManager(options: CreateRestManagerOptions): RestManage const newObj: any = {} for (const key of Object.keys(obj)) { - // Keys that dont require snake casing - if (['permissions', 'allow', 'deny'].includes(key) && obj[key] !== undefined) { - newObj[key] = calculateBits(obj[key]) - continue + const value = obj[key] + + // Some falsy values should be allowed like null or 0 + if (value !== undefined) { + switch (key) { + case 'permissions': + case 'allow': + case 'deny': + newObj[key] = calculateBits(value) + continue + case 'defaultMemberPermissions': + newObj.default_member_permissions = calculateBits(value) + continue + case 'nameLocalizations': + newObj.name_localizations = value + continue + case 'descriptionLocalizations': + newObj.description_localizations = value + continue + } } - if (key === 'defaultMemberPermissions' && obj[key] !== undefined) { - newObj.default_member_permissions = calculateBits(obj[key]) - continue - } - - newObj[camelToSnakeCase(key)] = rest.changeToDiscordFormat(obj[key]) + newObj[camelToSnakeCase(key)] = rest.changeToDiscordFormat(value) } return newObj From a1b2b3fb2c957808b213902292120cc03d1bba1c Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 8 May 2023 13:36:33 -0500 Subject: [PATCH 06/12] fix: Closes #3011 guide fixes --- website/docs/bigbot/step-2-rest.md | 4 ++-- website/docs/bigbot/step-3-gateway.md | 5 +++-- website/docs/bigbot/step-4-bot.md | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/website/docs/bigbot/step-2-rest.md b/website/docs/bigbot/step-2-rest.md index 61187dcea..44d1fb1dd 100644 --- a/website/docs/bigbot/step-2-rest.md +++ b/website/docs/bigbot/step-2-rest.md @@ -64,8 +64,8 @@ app.all('/*', async (req, res) => { try { const result = await REST.makeRequest( req.method, - `${REST.baseUrl}${req.url}`, - req.body + req.url.substring(4), + { body: req.method !== 'DELETE' && req.method !== 'GET' ? {} : req.body } ) if (result) { diff --git a/website/docs/bigbot/step-3-gateway.md b/website/docs/bigbot/step-3-gateway.md index 24eb53704..687a3af44 100644 --- a/website/docs/bigbot/step-3-gateway.md +++ b/website/docs/bigbot/step-3-gateway.md @@ -58,7 +58,7 @@ export const GATEWAY = createGatewayManager({ connection: await REST.getSessionInfo(), }) -// More code to be added here but first you need to understand this part. +GATEWAY.spawnShards() ``` Now let's break it down. @@ -149,6 +149,7 @@ GATEWAY.tellWorkerToIdentify = async function (workerId, shardId, bucketId) { method: 'POST', headers: { authorization: process.env.AUTHORIZATION, + "Content-type": "application/json", }, body: JSON.stringify({ type: 'IDENTIFY_SHARD', shardId }), }) @@ -156,7 +157,7 @@ GATEWAY.tellWorkerToIdentify = async function (workerId, shardId, bucketId) { .catch(logger.error) } -// More code to be added here but first you need to understand this part. +GATEWAY.spawnShards() ``` Here, we are overriding the built in method on the gateway manager called `tellWorkerToIdentify`. Internally, this function just simply starts a new shard as by default the lib supports small bots. For our case, we are going to make it get the server url from a `.env` file diff --git a/website/docs/bigbot/step-4-bot.md b/website/docs/bigbot/step-4-bot.md index 6ba2c4e4b..9fa7ea36e 100644 --- a/website/docs/bigbot/step-4-bot.md +++ b/website/docs/bigbot/step-4-bot.md @@ -114,7 +114,7 @@ try { // OPTIONAL: Runs the raw event handler if you need it bot.events.raw(bot, req.body.payload, req.body.shardId); // Runs the event handler if available - if (message.t) bot.events.[snakeToCamelCase(message.t)]?.(req.body.payload, req.body.shardId); + if (message.t) bot.events.[snakeToCamelCase(message.t.toLowerCase())]?.(req.body.payload, req.body.shardId); res.status(200).json({ success: true }) } From 9de1f66bcad00bdefbf146a42e90b357d77502aa Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 8 May 2023 13:43:42 -0500 Subject: [PATCH 07/12] fix: guild object should accept thread channels Closes #3024 --- packages/bot/src/transformers/guild.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/bot/src/transformers/guild.ts b/packages/bot/src/transformers/guild.ts index 2e78c05c4..6c8329aa5 100644 --- a/packages/bot/src/transformers/guild.ts +++ b/packages/bot/src/transformers/guild.ts @@ -60,7 +60,7 @@ export function transformGuild(bot: Bot, payload: { guild: DiscordGuild } & { sh banner: payload.guild.banner ? iconHashToBigInt(payload.guild.banner) : undefined, splash: payload.guild.splash ? iconHashToBigInt(payload.guild.splash) : undefined, channels: new Collection( - payload.guild.channels?.map((channel) => { + [...(payload.guild.channels ?? []), ...(payload.guild.threads ?? [])].map((channel) => { const result = bot.transformers.channel(bot, { channel, guildId }) return [result.id, result] }), @@ -86,7 +86,6 @@ export function transformGuild(bot: Bot, payload: { guild: DiscordGuild } & { sh voiceStates: new Collection( (payload.guild.voice_states ?? []).map((vs) => bot.transformers.voiceState(bot, { voiceState: vs, guildId })).map((vs) => [vs.userId, vs]), ), - id: guildId, // WEIRD EDGE CASE WITH BOT CREATED SERVERS ownerId: payload.guild.owner_id ? bot.transformers.snowflake(payload.guild.owner_id) : 0n, From c675b450c134bb7a36328a27d4175381894a9603 Mon Sep 17 00:00:00 2001 From: Skillz Date: Mon, 8 May 2023 14:02:18 -0500 Subject: [PATCH 08/12] fix: deno ws fix --- packages/bot/src/bot.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/bot/src/bot.ts b/packages/bot/src/bot.ts index 9b267e27d..02a3016fb 100644 --- a/packages/bot/src/bot.ts +++ b/packages/bot/src/bot.ts @@ -67,6 +67,14 @@ export function createBot(options: CreateBotOptions): Bot { // Set up helpers below. helpers: {} as BotHelpers, async start() { + // @ts-expect-error should this work + if (typeof Deno !== 'undefined') { + // @ts-expect-error should this work + const katsura = await import('https://x.nest.land/katsura@1.3.9/src/discordenoFixes/gatewaySocket.ts') + + await katsura(bot.gateway) + } + if (!options.gateway?.connection) { bot.gateway.connection = await bot.rest.getSessionInfo() } From 169e11771d3dbb5f2fbba25a66d4b1418a9ea862 Mon Sep 17 00:00:00 2001 From: Jonathan Ho Date: Thu, 11 May 2023 08:12:20 -0700 Subject: [PATCH 09/12] ci: add snyk for image scan (#3031) --- .github/workflows/rest-proxy.yml | 56 ++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/.github/workflows/rest-proxy.yml b/.github/workflows/rest-proxy.yml index b7fdea47e..1fc212be3 100644 --- a/.github/workflows/rest-proxy.yml +++ b/.github/workflows/rest-proxy.yml @@ -3,16 +3,16 @@ name: Rest proxy on: push: branches: - - "main" + - 'main' paths: - - ".github/workflows/rest-proxy.yml" - - "proxies/rest/**" + - '.github/workflows/rest-proxy.yml' + - 'proxies/rest/**' pull_request: paths: - - ".github/workflows/rest-proxy.yml" - - "proxies/rest/**" + - '.github/workflows/rest-proxy.yml' + - 'proxies/rest/**' schedule: - - cron: "0 0 * * *" + - cron: '0 0 * * *' jobs: build: @@ -59,6 +59,7 @@ jobs: runs-on: ubuntu-latest needs: build steps: + - uses: actions/checkout@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Download artifact @@ -71,27 +72,42 @@ jobs: - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: - image-ref: "discordeno/rest-proxy:latest" - format: "table" - exit-code: "0" + image-ref: 'discordeno/rest-proxy:latest' + format: 'table' + exit-code: '0' ignore-unfixed: true - vuln-type: "os,library" - severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL" + vuln-type: 'os,library' + severity: 'UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL' - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master if: ${{ github.event_name == 'schedule' }} with: - image-ref: "discordeno/rest-proxy:latest" - exit-code: "0" - vuln-type: "os,library" - severity: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL" - format: "sarif" - output: "trivy-results.sarif" + image-ref: 'discordeno/rest-proxy:latest' + exit-code: '0' + vuln-type: 'os,library' + severity: 'UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL' + format: 'sarif' + output: 'trivy-results.sarif' - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v2 if: ${{ github.event_name == 'schedule' }} with: - sarif_file: "trivy-results.sarif" + sarif_file: 'trivy-results.sarif' + + - name: Run Snyk to check Docker image for vulnerabilities + if: ${{ github.event_name == 'schedule' }} + continue-on-error: true + uses: snyk/actions/docker@master + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + image: 'discordeno/rest-proxy:latest' + args: --file=proxies/rest/Dockerfile + - name: Upload result to GitHub Code Scanning + if: ${{ github.event_name == 'schedule' }} + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: snyk.sarif build-all-arch: name: Build image for all architectures @@ -117,7 +133,7 @@ jobs: with: context: proxies/rest push: false - tags: "discordeno/rest-proxy:latest" + tags: 'discordeno/rest-proxy:latest' # linux/s390x stuck at yarn install, remove it for now platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le target: runner @@ -157,7 +173,7 @@ jobs: with: context: proxies/rest push: true - tags: "ghcr.io/discordeno/rest-proxy:latest" + tags: 'ghcr.io/discordeno/rest-proxy:latest' # linux/s390x stuck at yarn install, remove it for now platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le target: runner From dcc121af4699269a45d070600d31b96541990416 Mon Sep 17 00:00:00 2001 From: Endy Date: Mon, 5 Jun 2023 09:27:38 +0700 Subject: [PATCH 10/12] fix(gateway): Use Deno's WebSocket (#3030) * fix(gateway): Use Deno's WebSocket * invert runtime check --- packages/bot/src/bot.ts | 8 -------- packages/gateway/src/Shard.ts | 22 ++++++++++++---------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/packages/bot/src/bot.ts b/packages/bot/src/bot.ts index 02a3016fb..9b267e27d 100644 --- a/packages/bot/src/bot.ts +++ b/packages/bot/src/bot.ts @@ -67,14 +67,6 @@ export function createBot(options: CreateBotOptions): Bot { // Set up helpers below. helpers: {} as BotHelpers, async start() { - // @ts-expect-error should this work - if (typeof Deno !== 'undefined') { - // @ts-expect-error should this work - const katsura = await import('https://x.nest.land/katsura@1.3.9/src/discordenoFixes/gatewaySocket.ts') - - await katsura(bot.gateway) - } - if (!options.gateway?.connection) { bot.gateway.connection = await bot.rest.getSessionInfo() } diff --git a/packages/gateway/src/Shard.ts b/packages/gateway/src/Shard.ts index 3fb47e0bd..06361135c 100644 --- a/packages/gateway/src/Shard.ts +++ b/packages/gateway/src/Shard.ts @@ -12,11 +12,13 @@ import type { import { GatewayCloseEventCodes, GatewayIntents, GatewayOpcodes } from '@discordeno/types' import { Collection, LeakyBucket, camelize, delay, logger } from '@discordeno/utils' import { inflateSync } from 'node:zlib' -import WebSocket from 'ws' +import NodeWebSocket from 'ws' import type { RequestMemberRequest } from './manager.js' import type { BotStatusUpdate, ShardEvents, ShardGatewayConfig, ShardHeart, ShardSocketRequest, StatusUpdate, UpdateVoiceState } from './types.js' import { ShardSocketCloseCodes, ShardState } from './types.js' +declare let WebSocket: any + export class DiscordenoShard { /** The id of the shard */ id: number @@ -33,7 +35,7 @@ export class DiscordenoShard { /** Current session id of the shard if present. */ sessionId?: string /** This contains the WebSocket connection to Discord, if currently connected. */ - socket?: WebSocket + socket?: NodeWebSocket /** Current internal state of the this. */ state = ShardState.Offline /** The url provided by discord to use when resuming a connection for this this. */ @@ -111,7 +113,7 @@ export class DiscordenoShard { /** Close the socket connection to discord if present. */ close(code: number, reason: string): void { - if (this.socket?.readyState !== WebSocket.OPEN) return + if (this.socket?.readyState !== NodeWebSocket.OPEN) return this.socket?.close(code, reason) } @@ -129,13 +131,13 @@ export class DiscordenoShard { url.searchParams.set('v', this.gatewayConfig.version.toString()) url.searchParams.set('encoding', 'json') - const socket = new WebSocket(url.toString()) + const socket: NodeWebSocket = process?.versions !== undefined ? new NodeWebSocket(url.toString()) : new WebSocket(url.toString()) this.socket = socket // TODO: proper event handling - socket.onerror = (event) => console.log({ error: event, shardId: this.id }) - socket.onclose = async (event) => await this.handleClose(event) - socket.onmessage = async (message) => await this.handleMessage(message) + socket.onerror = (event: NodeWebSocket.ErrorEvent) => console.log({ error: event, shardId: this.id }) + socket.onclose = async (event: NodeWebSocket.CloseEvent) => await this.handleClose(event) + socket.onmessage = async (message: NodeWebSocket.MessageEvent) => await this.handleMessage(message) return await new Promise((resolve) => { socket.onopen = () => { @@ -204,7 +206,7 @@ export class DiscordenoShard { /** Check whether the connection to Discord is currently open. */ isOpen(): boolean { - return this.socket?.readyState === WebSocket.OPEN + return this.socket?.readyState === NodeWebSocket.OPEN } /** Attempt to resume the previous shards session with the gateway. */ @@ -282,7 +284,7 @@ export class DiscordenoShard { } /** Handle a gateway connection close. */ - async handleClose(close: WebSocket.CloseEvent): Promise { + async handleClose(close: NodeWebSocket.CloseEvent): Promise { // gateway.debug("GW CLOSED", { shardId, payload: event }); this.stopHeartbeating() @@ -485,7 +487,7 @@ export class DiscordenoShard { } /** Handle an incoming gateway message. */ - async handleMessage(message: WebSocket.MessageEvent): Promise { + async handleMessage(message: NodeWebSocket.MessageEvent): Promise { let preProcessMessage = message.data // If message compression is enabled, From 6ea65c70e3876c1eec860f191337561b5b4ffb45 Mon Sep 17 00:00:00 2001 From: Jonathan Ho Date: Sun, 4 Jun 2023 19:37:46 -0700 Subject: [PATCH 11/12] chore(rest-proxy): update base image (#3045) --- proxies/rest/Dockerfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proxies/rest/Dockerfile b/proxies/rest/Dockerfile index a24811149..1d1b44ee2 100644 --- a/proxies/rest/Dockerfile +++ b/proxies/rest/Dockerfile @@ -1,4 +1,4 @@ -# we node 18 alpine 3.17 as base image +# we node 18 alpine 3.18 as base image # we use multi stage build in this file # deps: contain all dependencies including dev dependencies # builder: contains all compiled files @@ -6,7 +6,7 @@ # runner: the final image, with only the dependencies and compiled files # build only with the platform of the host machine, since it only uses for dev purposes -FROM --platform=$BUILDPLATFORM node:18.15.0-alpine3.17 AS deps +FROM --platform=$BUILDPLATFORM node:18.16.0-alpine3.18 AS deps WORKDIR /app # copy necessary for install dependencies COPY package.json yarn.lock ./ @@ -14,7 +14,7 @@ COPY package.json yarn.lock ./ RUN yarn install # build only with the platform of the host machine, since we just need its files -FROM --platform=$BUILDPLATFORM node:18.15.0-alpine3.17 AS builder +FROM --platform=$BUILDPLATFORM node:18.16.0-alpine3.18 AS builder # copy the dependencies (node_modules) from the deps image COPY --from=deps /app /app WORKDIR /app @@ -25,7 +25,7 @@ COPY .swcrc ./ # compile the files RUN yarn build -FROM node:18.15.0-alpine3.17 AS prod-deps +FROM node:18.16.0-alpine3.18 AS prod-deps WORKDIR /app # copy necessary files for install dependencies COPY package.json yarn.lock .yarnrc.yml ./ @@ -35,7 +35,7 @@ RUN yarn plugin import workspace-tools # install prod dependencies RUN yarn workspaces focus --all --production -FROM node:18.15.0-alpine3.17 AS runner +FROM node:18.16.0-alpine3.18 AS runner # copy the compiled files from the builder image COPY --from=builder /app/dist /app/dist # copy the prod dependencies (node_modules) from the prod-deps image From abfa0bb8fbb3845e9411f2fd6e75ff70d7417e85 Mon Sep 17 00:00:00 2001 From: Jonathan Ho Date: Mon, 5 Jun 2023 18:46:39 -0700 Subject: [PATCH 12/12] test(rest-proxy): add image scan on push to main (#3046) --- .github/workflows/rest-proxy.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rest-proxy.yml b/.github/workflows/rest-proxy.yml index 1fc212be3..22681baaa 100644 --- a/.github/workflows/rest-proxy.yml +++ b/.github/workflows/rest-proxy.yml @@ -80,7 +80,7 @@ jobs: severity: 'UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL' - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master - if: ${{ github.event_name == 'schedule' }} + if: ${{ github.event_name == 'schedule' || github.event_name == 'push' }} with: image-ref: 'discordeno/rest-proxy:latest' exit-code: '0' @@ -90,12 +90,12 @@ jobs: output: 'trivy-results.sarif' - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v2 - if: ${{ github.event_name == 'schedule' }} + if: ${{ github.event_name == 'schedule' || github.event_name == 'push' }} with: sarif_file: 'trivy-results.sarif' - name: Run Snyk to check Docker image for vulnerabilities - if: ${{ github.event_name == 'schedule' }} + if: ${{ github.event_name == 'schedule' || github.event_name == 'push' }} continue-on-error: true uses: snyk/actions/docker@master env: @@ -104,7 +104,7 @@ jobs: image: 'discordeno/rest-proxy:latest' args: --file=proxies/rest/Dockerfile - name: Upload result to GitHub Code Scanning - if: ${{ github.event_name == 'schedule' }} + if: ${{ github.event_name == 'schedule' || github.event_name == 'push' }} uses: github/codeql-action/upload-sarif@v2 with: sarif_file: snyk.sarif