Compare commits

..

27 Commits

Author SHA1 Message Date
semantic-release-bot
ce76c5f08e chore(release): 1.0.0-dev.11 [skip ci]
# @revanced/bot-websocket-api [1.0.0-dev.11](https://github.com/revanced/revanced-bots/compare/@revanced/bot-websocket-api@1.0.0-dev.10...@revanced/bot-websocket-api@1.0.0-dev.11) (2025-04-04)

### Bug Fixes

* **apis/websocket:** attempt to fix missing remote address ([9b2888b](9b2888b944))
* run projects with `--bun` ([bb2182e](bb2182e707))
2025-04-04 16:56:18 +00:00
PalmDevs
bb2182e707 fix: run projects with --bun 2025-04-04 23:55:06 +07:00
PalmDevs
9b2888b944 fix(apis/websocket): attempt to fix missing remote address 2025-04-04 23:55:04 +07:00
PalmDevs
ba1a467e20 chore: update deps 2025-04-04 23:55:02 +07:00
semantic-release-bot
c97fffb32f chore(release): 1.0.0-dev.37 [skip ci]
# @revanced/discord-bot [1.0.0-dev.37](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.0.0-dev.36...@revanced/discord-bot@1.0.0-dev.37) (2025-03-08)

### Bug Fixes

* **bots/discord/utils/duration:** fix specified default unit not working ([d138af4](d138af46d1))
2025-03-08 23:34:30 +00:00
PalmDevs
d138af46d1 fix(bots/discord/utils/duration): fix specified default unit not working 2025-03-09 06:33:21 +07:00
semantic-release-bot
75a57b0e16 chore(release): 1.0.0-dev.36 [skip ci]
# @revanced/discord-bot [1.0.0-dev.36](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.0.0-dev.35...@revanced/discord-bot@1.0.0-dev.36) (2025-03-03)

### Bug Fixes

* **bots/discord/scripts/build:** check if dist dir exists before cleaning ([c06033e](c06033e573))
* **bots/discord/utils/duration:** make second the default unit ([5d1af3c](5d1af3c31c))
* **bots/discord:** add GuildMember partial ([8e3946a](8e3946a666))
* **bots/discord:** decrease length of an option in `ban` command ([22d3eea](22d3eea88d))
* **bots/discord:** delete expired appliedPresets entries after unapplying ([14c98e8](14c98e87df))
* fix typings and formatting ([479812e](479812e199))
* update repo url ([a21aa34](a21aa348d7))

### Features

* **bots/discord:** add more month aliases to duration parser ([c2009ca](c2009ca6d4))
2025-03-03 19:40:39 +00:00
PalmDevs
c06033e573 fix(bots/discord/scripts/build): check if dist dir exists before cleaning 2025-03-04 02:39:08 +07:00
semantic-release-bot
d290417ff3 chore(release): 1.0.0-dev.10 [skip ci]
# @revanced/bot-websocket-api [1.0.0-dev.10](https://github.com/revanced/revanced-bots/compare/@revanced/bot-websocket-api@1.0.0-dev.9...@revanced/bot-websocket-api@1.0.0-dev.10) (2025-03-03)

### Bug Fixes

* fix typings and formatting ([479812e](479812e199))
* update repo url ([a21aa34](a21aa348d7))
2025-03-03 19:36:29 +00:00
PalmDevs
a21aa348d7 fix: update repo url 2025-03-04 02:35:19 +07:00
PalmDevs
479812e199 fix: fix typings and formatting 2025-03-04 02:27:48 +07:00
PalmDevs
f6119946f8 chore: update deps 2025-03-04 02:19:06 +07:00
PalmDevs
5d1af3c31c fix(bots/discord/utils/duration): make second the default unit 2025-03-04 02:17:59 +07:00
PalmDevs
14c98e87df fix(bots/discord): delete expired appliedPresets entries after unapplying 2025-03-04 02:15:19 +07:00
PalmDevs
8e3946a666 fix(bots/discord): add GuildMember partial 2025-03-04 02:09:59 +07:00
PalmDevs
c2009ca6d4 feat(bots/discord): add more month aliases to duration parser 2024-10-30 18:56:54 +07:00
PalmDevs
22d3eea88d fix(bots/discord): decrease length of an option in ban command 2024-10-30 18:50:22 +07:00
semantic-release-bot
14d301eeb4 chore(release): 1.0.0-dev.35 [skip ci]
# @revanced/discord-bot [1.0.0-dev.35](https://github.com/revanced/revanced-helper/compare/@revanced/discord-bot@1.0.0-dev.34...@revanced/discord-bot@1.0.0-dev.35) (2024-10-17)

### Bug Fixes

* **bots/discord:** fix freeze on prod builds ([8efb549](8efb549453))
2024-10-17 18:34:04 +00:00
PalmDevs
8efb549453 fix(bots/discord): fix freeze on prod builds 2024-10-18 01:32:42 +07:00
PalmDevs
79fea8b286 fix: update patches for dependencies 2024-10-18 00:02:06 +07:00
semantic-release-bot
e798a9ef32 chore(release): 1.0.0-dev.34 [skip ci]
# @revanced/discord-bot [1.0.0-dev.34](https://github.com/revanced/revanced-helper/compare/@revanced/discord-bot@1.0.0-dev.33...@revanced/discord-bot@1.0.0-dev.34) (2024-10-17)

### Bug Fixes

* **bots/discord:** attempt to fix stuck sticky message timeouts ([3ed5bd1](3ed5bd11ac))
* **bots/discord:** fix reload not working ([11582d5](11582d5034))

### Features

* **bots/discord:** add default durations for moderation commands ([27d3b39](27d3b39209))
* **bots/discord:** cure on every event ([8ff6086](8ff6086028))
2024-10-17 16:56:34 +00:00
PalmDevs
7b5d4fa1a2 chore: update dependencies 2024-10-17 23:55:17 +07:00
PalmDevs
11582d5034 fix(bots/discord): fix reload not working 2024-10-17 23:20:02 +07:00
PalmDevs
488d37e65b fix(packages/shareed): add missing imports 2024-10-17 21:47:14 +07:00
PalmDevs
3ed5bd11ac fix(bots/discord): attempt to fix stuck sticky message timeouts 2024-10-17 21:40:41 +07:00
PalmDevs
8ff6086028 feat(bots/discord): cure on every event 2024-10-17 21:39:05 +07:00
PalmDevs
27d3b39209 feat(bots/discord): add default durations for moderation commands 2024-10-17 21:38:54 +07:00
37 changed files with 2139 additions and 174 deletions

View File

@@ -1,3 +1,19 @@
# @revanced/bot-websocket-api [1.0.0-dev.11](https://github.com/revanced/revanced-bots/compare/@revanced/bot-websocket-api@1.0.0-dev.10...@revanced/bot-websocket-api@1.0.0-dev.11) (2025-04-04)
### Bug Fixes
* **apis/websocket:** attempt to fix missing remote address ([9b2888b](https://github.com/revanced/revanced-bots/commit/9b2888b944ea1d61d31aa5df3536768e9a2dadf8))
* run projects with `--bun` ([bb2182e](https://github.com/revanced/revanced-bots/commit/bb2182e707fa40c555d56138972eeea28f1b3cf9))
# @revanced/bot-websocket-api [1.0.0-dev.10](https://github.com/revanced/revanced-bots/compare/@revanced/bot-websocket-api@1.0.0-dev.9...@revanced/bot-websocket-api@1.0.0-dev.10) (2025-03-03)
### Bug Fixes
* fix typings and formatting ([479812e](https://github.com/revanced/revanced-bots/commit/479812e199b52cdb295a5746e0767306afab3413))
* update repo url ([a21aa34](https://github.com/revanced/revanced-bots/commit/a21aa348d7f32cd0ee65b371e9594520c0a9d3f1))
# @revanced/bot-websocket-api [1.0.0-dev.9](https://github.com/revanced/revanced-helper/compare/@revanced/bot-websocket-api@1.0.0-dev.8...@revanced/bot-websocket-api@1.0.0-dev.9) (2024-08-03) # @revanced/bot-websocket-api [1.0.0-dev.9](https://github.com/revanced/revanced-helper/compare/@revanced/bot-websocket-api@1.0.0-dev.8...@revanced/bot-websocket-api@1.0.0-dev.9) (2024-08-03)

View File

@@ -14,4 +14,4 @@ WORKDIR /app
COPY --from=build /build/apis/websocket/dist /app COPY --from=build /build/apis/websocket/dist /app
USER 1000:1000 USER 1000:1000
ENTRYPOINT [ "bun", "run", "index.js" ] ENTRYPOINT [ "bun", "--bun", "run", "index.js" ]

View File

@@ -2,7 +2,7 @@
"name": "@revanced/bot-websocket-api", "name": "@revanced/bot-websocket-api",
"type": "module", "type": "module",
"private": true, "private": true,
"version": "1.0.0-dev.9", "version": "1.0.0-dev.11",
"description": "🧦 WebSocket API server for bots assisting ReVanced", "description": "🧦 WebSocket API server for bots assisting ReVanced",
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
@@ -13,7 +13,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/revanced/revanced-helper.git", "url": "git+https://github.com/revanced/revanced-bots.git",
"directory": "apis/websocket" "directory": "apis/websocket"
}, },
"author": "Palm <contact@palmdevs.me> (https://palmdevs.me)", "author": "Palm <contact@palmdevs.me> (https://palmdevs.me)",
@@ -23,18 +23,18 @@
], ],
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
"bugs": { "bugs": {
"url": "https://github.com/revanced/revanced-helper/issues" "url": "https://github.com/revanced/revanced-bots/issues"
}, },
"homepage": "https://github.com/revanced/revanced-helper#readme", "homepage": "https://github.com/revanced/revanced-bots#readme",
"dependencies": { "dependencies": {
"@revanced/bot-shared": "workspace:*", "@revanced/bot-shared": "workspace:*",
"@sapphire/async-queue": "^1.5.2", "@sapphire/async-queue": "^1.5.5",
"chalk": "^5.3.0", "chalk": "^5.4.1",
"tesseract.js": "^5.1.0", "tesseract.js": "^5.1.1",
"ws": "^8.17.1" "ws": "^8.18.1"
}, },
"devDependencies": { "devDependencies": {
"@types/ws": "^8.5.10", "@types/ws": "^8.18.1",
"typed-emitter": "^2.1.0" "typed-emitter": "^2.1.0"
} }
} }

View File

@@ -1,10 +1,10 @@
import { createLogger } from '@revanced/bot-shared' import { createLogger } from '@revanced/bot-shared'
import { cp, rm } from 'fs/promises' import { cp, exists, rm } from 'fs/promises'
const logger = createLogger() const logger = createLogger()
logger.info('Cleaning previous build...') logger.info('Cleaning previous build...')
await rm('./dist', { recursive: true }) if (await exists('./dist')) await rm('./dist', { recursive: true })
logger.info('Building WebSocket API...') logger.info('Building WebSocket API...')
await Bun.build({ await Bun.build({

View File

@@ -110,7 +110,7 @@ export default class Client {
protected _toBuffer(data: RawData) { protected _toBuffer(data: RawData) {
if (data instanceof Buffer) return data if (data instanceof Buffer) return data
if (data instanceof ArrayBuffer) return Buffer.from(data) if (data instanceof ArrayBuffer) return Buffer.from(data)
return Buffer.concat(data) return Buffer.concat(data as Uint8Array[])
} }
} }

View File

@@ -56,12 +56,13 @@ const wss = new WebSocketServer({
wss.on('connection', async (socket, request) => { wss.on('connection', async (socket, request) => {
try { try {
if (!request.socket.remoteAddress) { const addrInfo = request.socket.address()
if (!('address' in addrInfo)) {
socket.close() socket.close()
return logger.warn('Connection failed because client is missing remote address') return logger.warn('Connection failed because client is missing remote address. addrInfo =', addrInfo)
} }
const id = `${request.socket.remoteAddress}:${request.socket.remotePort}` const id = `${addrInfo.address}:${addrInfo.port}`
if (clientIds.has(id)) { if (clientIds.has(id)) {
logger.warn(`Client ${id} already connected, disconnecting old session`) logger.warn(`Client ${id} already connected, disconnecting old session`)

View File

@@ -1,3 +1,49 @@
# @revanced/discord-bot [1.0.0-dev.37](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.0.0-dev.36...@revanced/discord-bot@1.0.0-dev.37) (2025-03-08)
### Bug Fixes
* **bots/discord/utils/duration:** fix specified default unit not working ([d138af4](https://github.com/revanced/revanced-bots/commit/d138af46d1f25a11b6f8ab3790ecaa70b1d716a9))
# @revanced/discord-bot [1.0.0-dev.36](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.0.0-dev.35...@revanced/discord-bot@1.0.0-dev.36) (2025-03-03)
### Bug Fixes
* **bots/discord/scripts/build:** check if dist dir exists before cleaning ([c06033e](https://github.com/revanced/revanced-bots/commit/c06033e5730f82438e8052b9b519a8f8e2d25437))
* **bots/discord/utils/duration:** make second the default unit ([5d1af3c](https://github.com/revanced/revanced-bots/commit/5d1af3c31c3379b6a13684dfb07583737908c8aa))
* **bots/discord:** add GuildMember partial ([8e3946a](https://github.com/revanced/revanced-bots/commit/8e3946a66602838715787090008c7bfaf72b67e9))
* **bots/discord:** decrease length of an option in `ban` command ([22d3eea](https://github.com/revanced/revanced-bots/commit/22d3eea88d532792c1237d1a1ab18bc02e57816a))
* **bots/discord:** delete expired appliedPresets entries after unapplying ([14c98e8](https://github.com/revanced/revanced-bots/commit/14c98e87df1ec4fd762bbc48ca4c06470cb110a2))
* fix typings and formatting ([479812e](https://github.com/revanced/revanced-bots/commit/479812e199b52cdb295a5746e0767306afab3413))
* update repo url ([a21aa34](https://github.com/revanced/revanced-bots/commit/a21aa348d7f32cd0ee65b371e9594520c0a9d3f1))
### Features
* **bots/discord:** add more month aliases to duration parser ([c2009ca](https://github.com/revanced/revanced-bots/commit/c2009ca6d42e4387bc5f375d76ecf72991b7fe32))
# @revanced/discord-bot [1.0.0-dev.35](https://github.com/revanced/revanced-helper/compare/@revanced/discord-bot@1.0.0-dev.34...@revanced/discord-bot@1.0.0-dev.35) (2024-10-17)
### Bug Fixes
* **bots/discord:** fix freeze on prod builds ([8efb549](https://github.com/revanced/revanced-helper/commit/8efb549453a04fab1ac6414a7f7f8bf702df3c93))
# @revanced/discord-bot [1.0.0-dev.34](https://github.com/revanced/revanced-helper/compare/@revanced/discord-bot@1.0.0-dev.33...@revanced/discord-bot@1.0.0-dev.34) (2024-10-17)
### Bug Fixes
* **bots/discord:** attempt to fix stuck sticky message timeouts ([3ed5bd1](https://github.com/revanced/revanced-helper/commit/3ed5bd11acc3b4fbd57b0d632c68eb9f77365b8a))
* **bots/discord:** fix reload not working ([11582d5](https://github.com/revanced/revanced-helper/commit/11582d50345cae9fb645a65ca4e621596de6a408))
### Features
* **bots/discord:** add default durations for moderation commands ([27d3b39](https://github.com/revanced/revanced-helper/commit/27d3b392092141a1e3b4b0298131ff7817458dc1))
* **bots/discord:** cure on every event ([8ff6086](https://github.com/revanced/revanced-helper/commit/8ff6086028132cc4b49ee60846e8d6ef909f5a89))
# @revanced/discord-bot [1.0.0-dev.33](https://github.com/revanced/revanced-helper/compare/@revanced/discord-bot@1.0.0-dev.32...@revanced/discord-bot@1.0.0-dev.33) (2024-09-25) # @revanced/discord-bot [1.0.0-dev.33](https://github.com/revanced/revanced-helper/compare/@revanced/discord-bot@1.0.0-dev.32...@revanced/discord-bot@1.0.0-dev.33) (2024-09-25)

View File

@@ -15,4 +15,4 @@ COPY --from=build /build/bots/discord/dist /app
USER 1000:1000 USER 1000:1000
ENTRYPOINT [ "bun", "run", "src/index.js" ] ENTRYPOINT [ "bun", "--bun", "run", "src/index.js" ]

View File

@@ -19,8 +19,8 @@ export default {
}, },
timeout: 60000, timeout: 60000,
forceSendTimeout: 300000, forceSendTimeout: 300000,
} },
} },
}, },
moderation: { moderation: {
cure: { cure: {
@@ -77,7 +77,7 @@ export default {
attachments: { attachments: {
scanAttachments: true, scanAttachments: true,
allowedMimeTypes: ['image/jpeg', 'image/png', 'image/webp', 'text/plain'], allowedMimeTypes: ['image/jpeg', 'image/png', 'image/webp', 'text/plain'],
maxTextFileSize: 512000 maxTextFileSize: 512000,
}, },
responses: [ responses: [
{ {

View File

@@ -2,7 +2,7 @@
"name": "@revanced/discord-bot", "name": "@revanced/discord-bot",
"type": "module", "type": "module",
"private": true, "private": true,
"version": "1.0.0-dev.33", "version": "1.0.0-dev.37",
"description": "🤖 Discord bot assisting ReVanced", "description": "🤖 Discord bot assisting ReVanced",
"main": "src/index.ts", "main": "src/index.ts",
"scripts": { "scripts": {
@@ -14,7 +14,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/revanced/revanced-helper.git", "url": "git+https://github.com/revanced/revanced-bots.git",
"directory": "bots/discord" "directory": "bots/discord"
}, },
"author": "Palm <contact@palmdevs.me> (https://palmdevs.me)", "author": "Palm <contact@palmdevs.me> (https://palmdevs.me)",
@@ -24,23 +24,23 @@
], ],
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
"bugs": { "bugs": {
"url": "https://github.com/revanced/revanced-helper/issues" "url": "https://github.com/revanced/revanced-bots/issues"
}, },
"homepage": "https://github.com/revanced/revanced-helper#readme", "homepage": "https://github.com/revanced/revanced-bots#readme",
"dependencies": { "dependencies": {
"@discordjs/builders": "^1.8.2", "@discordjs/builders": "^1.10.1",
"@discordjs/rest": "^2.3.0", "@discordjs/rest": "^2.4.3",
"@revanced/bot-api": "workspace:*", "@revanced/bot-api": "workspace:*",
"@revanced/bot-shared": "workspace:*", "@revanced/bot-shared": "workspace:*",
"chalk": "^5.3.0", "chalk": "^5.4.1",
"decancer": "^3.2.4", "decancer": "^3.2.8",
"discord.js": "^14.15.3", "discord.js": "^14.18.0",
"drizzle-orm": "^0.31.4", "drizzle-orm": "^0.31.4",
"parse-duration": "^1.1.0" "parse-duration": "^1.1.2"
}, },
"devDependencies": { "devDependencies": {
"@libsql/client": "^0.7.0", "@libsql/client": "^0.7.0",
"discord-api-types": "^0.37.97", "discord-api-types": "^0.37.119",
"drizzle-kit": "^0.22.8" "drizzle-kit": "^0.22.8"
} }
} }

View File

@@ -1,10 +1,10 @@
import { createLogger } from '@revanced/bot-shared' import { createLogger } from '@revanced/bot-shared'
import { cp, rm } from 'fs/promises' import { cp, exists, rm } from 'fs/promises'
const logger = createLogger() const logger = createLogger()
logger.warn('Cleaning previous build...') logger.warn('Cleaning previous build...')
await rm('./dist', { recursive: true }) if (await exists('./dist')) await rm('./dist', { recursive: true })
logger.info('Building bot...') logger.info('Building bot...')
await Bun.build({ await Bun.build({

View File

@@ -1,8 +1,5 @@
import { dirname, join } from 'path'
import { AdminCommand } from '$/classes/Command' import { AdminCommand } from '$/classes/Command'
import type { Config } from 'config.schema'
export default new AdminCommand({ export default new AdminCommand({
name: 'reload', name: 'reload',
description: 'Reload configuration', description: 'Reload configuration',
@@ -10,10 +7,8 @@ export default new AdminCommand({
const { api, logger, discord } = context const { api, logger, discord } = context
logger.info(`Reload triggered by ${context.executor.tag} (${context.executor.id})`) logger.info(`Reload triggered by ${context.executor.tag} (${context.executor.id})`)
// Apparently the query strings only work with non-Windows "URLs", otherwise it'd just infinitely hang logger.debug('Invalidating previous config...')
const path = `${Bun.pathToFileURL(join(dirname(Bun.main), '..', 'config.js')).toString()}?cache=${Date.now()}` context.config.invalidate()
logger.debug(`Reloading configuration from: ${path}`)
context.config = ((await import(path)) as { default: Config }).default
if ('deferReply' in trigger) await trigger.deferReply({ ephemeral: true }) if ('deferReply' in trigger) await trigger.deferReply({ ephemeral: true })
@@ -28,7 +23,7 @@ export default new AdminCommand({
api.client.disconnect(true) api.client.disconnect(true)
api.disconnectCount = 0 api.disconnectCount = 0
api.intentionallyDisconnecting = false api.intentionallyDisconnecting = false
await api.client.connect() api.client.connect()
logger.info('Reinitializing Discord client to reload configuration...') logger.info('Reinitializing Discord client to reload configuration...')
await discord.client.destroy() await discord.client.destroy()

View File

@@ -18,13 +18,14 @@ export default new ModerationCommand({
required: false, required: false,
type: ModerationCommand.OptionType.String, type: ModerationCommand.OptionType.String,
}, },
dmd: { dmt: {
description: 'Duration to delete messages (must be from 0 to 7 days)', description:
'Time duration to delete messages (default time unit is days, must be from 0s to 7d, default is 0s)',
required: false, required: false,
type: ModerationCommand.OptionType.String, type: ModerationCommand.OptionType.String,
}, },
}, },
async execute({ logger, executor }, interaction, { user, reason, dmd }) { async execute({ logger, executor }, interaction, { user, reason, dmt }) {
const guild = await interaction.client.guilds.fetch(interaction.guildId) const guild = await interaction.client.guilds.fetch(interaction.guildId)
const member = await guild.members.fetch(user).catch(() => {}) const member = await guild.members.fetch(user).catch(() => {})
const moderator = await guild.members.fetch(executor.user) const moderator = await guild.members.fetch(executor.user)
@@ -40,7 +41,7 @@ export default new ModerationCommand({
) )
} }
const dms = Math.floor(dmd ? parseDuration(dmd) : 0 / 1000) const dms = Math.floor((dmt ? parseDuration(dmt, 'd') : 0) / 1000)
await interaction.guild!.members.ban(user, { await interaction.guild!.members.ban(user, {
reason: `Banned by moderator ${executor.user.tag} (${executor.id}): ${reason}`, reason: `Banned by moderator ${executor.user.tag} (${executor.id}): ${reason}`,
deleteMessageSeconds: dms, deleteMessageSeconds: dms,

View File

@@ -14,13 +14,13 @@ export default new ModerationCommand({
required: true, required: true,
type: ModerationCommand.OptionType.User, type: ModerationCommand.OptionType.User,
}, },
reason: { duration: {
description: 'The reason for muting the member', description: 'The duration of the mute (default time unit is minutes)',
required: false, required: false,
type: ModerationCommand.OptionType.String, type: ModerationCommand.OptionType.String,
}, },
duration: { reason: {
description: 'The duration of the mute', description: 'The reason for muting the member',
required: false, required: false,
type: ModerationCommand.OptionType.String, type: ModerationCommand.OptionType.String,
}, },
@@ -33,7 +33,7 @@ export default new ModerationCommand({
const guild = await interaction.client.guilds.fetch(interaction.guildId) const guild = await interaction.client.guilds.fetch(interaction.guildId)
const member = await guild.members.fetch(user.id) const member = await guild.members.fetch(user.id)
const moderator = await guild.members.fetch(executor.id) const moderator = await guild.members.fetch(executor.id)
const duration = durationInput ? parseDuration(durationInput) : Infinity const duration = durationInput ? parseDuration(durationInput, 'm') : Infinity
if (Number.isInteger(duration) && duration! < 1) if (Number.isInteger(duration) && duration! < 1)
throw new CommandError( throw new CommandError(

View File

@@ -11,12 +11,12 @@ const SubcommandOptions = {
type: ModerationCommand.OptionType.User, type: ModerationCommand.OptionType.User,
}, },
preset: { preset: {
description: 'The preset to apply or remove', description: 'The preset to manage',
required: true, required: true,
type: ModerationCommand.OptionType.String, type: ModerationCommand.OptionType.String,
}, },
duration: { duration: {
description: 'The duration to apply the preset for (only for apply action)', description: 'The duration to apply the preset for (only for apply action, default time unit is minutes)',
required: false, required: false,
type: ModerationCommand.OptionType.String, type: ModerationCommand.OptionType.String,
}, },
@@ -53,7 +53,7 @@ export default new ModerationCommand({
throw new CommandError(CommandErrorType.Generic, 'This user cannot be managed by the bot.') throw new CommandError(CommandErrorType.Generic, 'This user cannot be managed by the bot.')
if (apply) { if (apply) {
const duration = durationInput ? parseDuration(durationInput) : Infinity const duration = durationInput ? parseDuration(durationInput, 'm') : Infinity
if (Number.isInteger(duration) && duration! < 1) if (Number.isInteger(duration) && duration! < 1)
throw new CommandError( throw new CommandError(
CommandErrorType.InvalidArgument, CommandErrorType.InvalidArgument,
@@ -83,6 +83,13 @@ export default new ModerationCommand({
removeRolePreset(member, preset) removeRolePreset(member, preset)
}, expires) }, expires)
await sendPresetReplyAndLogs(apply ? 'apply' : 'remove', trigger, executor, user, preset, expires ? Math.ceil(expires / 1000) : undefined) await sendPresetReplyAndLogs(
apply ? 'apply' : 'remove',
trigger,
executor,
user,
preset,
expires ? Math.ceil(expires / 1000) : undefined,
)
}, },
}) })

View File

@@ -10,7 +10,7 @@ export default new ModerationCommand({
description: 'Set a slowmode for a channel', description: 'Set a slowmode for a channel',
options: { options: {
duration: { duration: {
description: 'The duration to set', description: 'The duration to set (default time unit is seconds)',
required: true, required: true,
type: ModerationCommand.OptionType.String, type: ModerationCommand.OptionType.String,
}, },
@@ -23,13 +23,10 @@ export default new ModerationCommand({
}, },
async execute({ logger, executor }, interaction, { duration: durationInput, channel: channelInput }) { async execute({ logger, executor }, interaction, { duration: durationInput, channel: channelInput }) {
const channel = channelInput ?? (await interaction.guild!.channels.fetch(interaction.channelId)) const channel = channelInput ?? (await interaction.guild!.channels.fetch(interaction.channelId))
const duration = parseDuration(durationInput) const duration = parseDuration(durationInput, 's')
if (!channel?.isTextBased() || channel.isDMBased()) if (!channel?.isTextBased() || channel.isDMBased())
throw new CommandError( throw new CommandError(CommandErrorType.InvalidArgument, 'The supplied channel is not a text channel.')
CommandErrorType.InvalidArgument,
'The supplied channel is not a text channel.',
)
if (Number.isNaN(duration)) throw new CommandError(CommandErrorType.InvalidArgument, 'Invalid duration.') if (Number.isNaN(duration)) throw new CommandError(CommandErrorType.InvalidArgument, 'Invalid duration.')
if (duration < 0 || duration > 36e4) if (duration < 0 || duration > 36e4)

View File

@@ -1,9 +1,9 @@
import Command from '$/classes/Command' import Command from '$/classes/Command'
import CommandError, { CommandErrorType } from '$/classes/CommandError' import CommandError, { CommandErrorType } from '$/classes/CommandError'
import { config } from '../../../context'
import type { FetchMessageOptions, MessageResolvable } from 'discord.js'
import type { ConfigMessageScanResponseLabelConfig } from 'config.schema'
import { createSuccessEmbed } from '$/utils/discord/embeds' import { createSuccessEmbed } from '$/utils/discord/embeds'
import type { ConfigMessageScanResponseLabelConfig } from 'config.schema'
import type { FetchMessageOptions, MessageResolvable } from 'discord.js'
import { config } from '../../../context'
const msRcConfig = config.messageScan?.humanCorrections?.allow const msRcConfig = config.messageScan?.humanCorrections?.allow

View File

@@ -1,8 +1,8 @@
import Command from '$/classes/Command' import Command from '$/classes/Command'
import CommandError, { CommandErrorType } from '$/classes/CommandError' import CommandError, { CommandErrorType } from '$/classes/CommandError'
import { config } from '../../../context'
import { type APIStringSelectComponent, ComponentType } from 'discord.js'
import type { ConfigMessageScanResponseLabelConfig } from 'config.schema' import type { ConfigMessageScanResponseLabelConfig } from 'config.schema'
import { type APIStringSelectComponent, ComponentType } from 'discord.js'
import { config } from '../../../context'
const msRcConfig = config.messageScan?.humanCorrections?.allow const msRcConfig = config.messageScan?.humanCorrections?.allow

View File

@@ -0,0 +1,28 @@
import { dirname, join } from 'path'
import _firstConfig from '../config.js'
let currentConfig = _firstConfig
// Other parts of the code will access properties of this proxy, they don't care what the target looks like
export const config = new Proxy(
{
INSPECTION_WARNING: 'Run `context.__getConfig()` to inspect the latest config.',
} as unknown as typeof currentConfig,
{
get(_, p, receiver) {
if (p === 'invalidate')
return async () => {
const path = join(dirname(Bun.main), '..', 'config.js')
Loader.registry.delete(path)
currentConfig = (await import(path)).default
}
return Reflect.get(currentConfig, p, receiver)
},
set(_, p, newValue, receiver) {
return Reflect.set(currentConfig, p, newValue, receiver)
},
},
) as typeof _firstConfig & { invalidate(): void }
export const __getConfig = () => currentConfig

View File

@@ -6,18 +6,19 @@ import { createLogger } from '@revanced/bot-shared'
import { Client as DiscordClient, type Message, Partials } from 'discord.js' import { Client as DiscordClient, type Message, Partials } from 'discord.js'
import { drizzle } from 'drizzle-orm/bun-sqlite' import { drizzle } from 'drizzle-orm/bun-sqlite'
// Export some things first, as commands require them import * as schemas from './database/schemas'
import config from '../config.js'
export { config } import type { default as Command, CommandOptionsOptions, CommandType } from './classes/Command'
import { __getConfig, config } from './config'
export { config, __getConfig }
export const logger = createLogger({ export const logger = createLogger({
level: config.logLevel === 'none' ? Number.MAX_SAFE_INTEGER : config.logLevel, level: config.logLevel === 'none' ? Number.MAX_SAFE_INTEGER : config.logLevel,
}) })
// Export a few things before we initialize commands
import * as commands from './commands' import * as commands from './commands'
import * as schemas from './database/schemas'
import type { default as Command, CommandOptionsOptions, CommandType } from './classes/Command'
export const api = { export const api = {
client: new APIClient({ client: new APIClient({
@@ -79,7 +80,7 @@ export const discord = {
parse: ['users'], parse: ['users'],
repliedUser: true, repliedUser: true,
}, },
partials: [Partials.Message, Partials.Reaction], partials: [Partials.Message, Partials.Reaction, Partials.GuildMember],
}), }),
commands: Object.fromEntries(Object.values(commands).map(cmd => [cmd.name, cmd])) as Record< commands: Object.fromEntries(Object.values(commands).map(cmd => [cmd.name, cmd])) as Record<
string, string,

View File

@@ -1,9 +1,9 @@
import { on } from '$/utils/discord/events' import { on } from '$/utils/discord/events'
import { cureNickname } from '$/utils/discord/moderation' import { cureNickname } from '$/utils/discord/moderation'
on('guildMemberUpdate', async (oldMember, newMember) => { on('guildMemberUpdate', (_, newMember) => {
if (newMember.user.bot) return if (newMember.user.bot) return
if (oldMember.displayName !== newMember.displayName) await cureNickname(newMember) cureNickname(newMember)
}) })
on('guildMemberAdd', member => { on('guildMemberAdd', member => {
@@ -11,7 +11,7 @@ on('guildMemberAdd', member => {
cureNickname(member) cureNickname(member)
}) })
on('messageCreate', async msg => { on('messageCreate', msg => {
if (msg.author.bot || !msg.member) return if (msg.author.bot || !msg.member) return
await cureNickname(msg.member) cureNickname(msg.member)
}) })

View File

@@ -9,8 +9,7 @@ withContext(on, 'interactionCreate', async (context, interaction) => {
const command = discord.commands[interaction.commandName] const command = discord.commands[interaction.commandName]
logger.debug(`Command ${interaction.commandName} being invoked by ${interaction.user.tag} via chat`) logger.debug(`Command ${interaction.commandName} being invoked by ${interaction.user.tag} via chat`)
if (!command) if (!command) return void logger.error(`Chat command ${interaction.commandName} not implemented but registered!!!`)
return void logger.error(`Chat command ${interaction.commandName} not implemented but registered!!!`)
try { try {
logger.debug(`Command ${interaction.commandName} being executed via chat`) logger.debug(`Command ${interaction.commandName} being executed via chat`)

View File

@@ -7,60 +7,36 @@ withContext(on, 'messageCreate', async ({ discord, logger }, msg) => {
const store = discord.stickyMessages[msg.guildId]?.[msg.channelId] const store = discord.stickyMessages[msg.guildId]?.[msg.channelId]
if (!store) return if (!store) return
// TODO: Fix this by fixing the logic below if (store.timerActive) {
if (store.timerActive && store.forceTimerActive) { // Timer is already active, so we try to start the force timer
logger.error( if (store.forceTimerMs) {
`Both timers are active in sticky message store: ${msg.guildId}.${msg.channelId}, this should not happen!`, // Force timer isn't active, so we start it
) if (!store.forceTimerActive) {
logger.info('Clearing the timer and the restarting the force timer...') logger.debug(
clearTimeout(store.timer) `Channel ${msg.channelId} in guild ${msg.guildId} is active, starting force send timer and clearing existing timer`,
store.timerActive = false )
// If the force timer is active, it implies the force timer exists
store.forceTimer!.refresh()
}
const timerPreviouslyActive = store.timerActive // Clear the timer
// If there isn't a timer, start it up clearTimeout(store.timer)
store.timerActive = true store.timerActive = false
if (!store.timer) store.timer = setTimeout(store.send, store.timerMs) as NodeJS.Timeout
else {
/*
If:
- (negate carried) There's a timer
- The timer is not active
- The force timer is not active
Then:
- Restart the timer
*/
if (!timerPreviouslyActive && !store.forceTimerActive) store.timer.refresh()
/*
If:
- Any of:
- (negate carried) The timer is active
- (negate carried) The force timer is active
- The force timer is not active
Then:
- Start the force timer and clear the existing timer
*/ else if (!store.forceTimerActive && store.forceTimerMs) {
logger.debug(
`Channel ${msg.channelId} in guild ${msg.guildId} is active, starting force send timer and clearing existing timer`,
)
// Clear the timer // (Re)start the force timer
clearTimeout(store.timer) store.forceTimerActive = true
store.timerActive = false if (!store.forceTimer)
store.forceTimer = setTimeout(
// (Re)start the force timer () =>
store.forceTimerActive = true store.send(true).then(() => {
if (!store.forceTimer) store.forceTimerActive = false
store.forceTimer = setTimeout( }),
() => store.forceTimerMs,
store.send(true).then(() => { ) as NodeJS.Timeout
store.forceTimerActive = false else store.forceTimer.refresh()
}), // Force timer is already active, so we force send
store.forceTimerMs, } else store.send()
) as NodeJS.Timeout
else store.forceTimer.refresh()
} }
} else if (!store.forceTimerActive) {
// Both timers aren't active, so we start the timer
store.timerActive = true
if (!store.timer) store.timer = setTimeout(store.send, store.timerMs) as NodeJS.Timeout
} }
}) })

View File

@@ -20,10 +20,10 @@ const PossibleReactions = Object.values(Reactions) as string[]
withContext(on, 'messageReactionAdd', async (context, rct, user) => { withContext(on, 'messageReactionAdd', async (context, rct, user) => {
if (user.bot) return if (user.bot) return
const { database: db, logger, config } = context const { database: db, logger, config } = context
const { messageScan: msConfig } = config const { messageScan: msConfig } = config
// If there's no config, we can't do anything // If there's no config, we can't do anything
if (!msConfig?.humanCorrections) return if (!msConfig?.humanCorrections) return

View File

@@ -3,7 +3,7 @@ import { appliedPresets } from '$/database/schemas'
import { applyCommonEmbedStyles } from '$/utils/discord/embeds' import { applyCommonEmbedStyles } from '$/utils/discord/embeds'
import { on, withContext } from '$/utils/discord/events' import { on, withContext } from '$/utils/discord/events'
import { removeRolePreset } from '$/utils/discord/rolePresets' import { removeRolePreset } from '$/utils/discord/rolePresets'
import { lt } from 'drizzle-orm' import { and, eq, lt } from 'drizzle-orm'
import type { Client } from 'discord.js' import type { Client } from 'discord.js'
@@ -60,7 +60,7 @@ export default withContext(on, 'ready', async ({ config, discord, logger }, clie
) )
} }
} }
// Set up the store // Set up the store
discord.stickyMessages[guildId]![channelId] = { discord.stickyMessages[guildId]![channelId] = {
forceTimerActive: false, forceTimerActive: false,
@@ -69,7 +69,7 @@ export default withContext(on, 'ready', async ({ config, discord, logger }, clie
timerMs: timeout, timerMs: timeout,
send, send,
// If the store exists before the configuration refresh, take its current message // If the store exists before the configuration refresh, take its current message
currentMessage: oldStore?.[channelId]?.currentMessage currentMessage: oldStore?.[channelId]?.currentMessage,
} }
// Send a new sticky message immediately, as well as deleting the old/outdated message, if it exists // Send a new sticky message immediately, as well as deleting the old/outdated message, if it exists
@@ -92,11 +92,15 @@ const removeExpiredPresets = async (client: Client) => {
for (const expired of expireds) for (const expired of expireds)
try { try {
logger.debug(`Removing role preset for ${expired.memberId} in ${expired.guildId}`)
const guild = await client.guilds.fetch(expired.guildId) const guild = await client.guilds.fetch(expired.guildId)
const member = await guild.members.fetch(expired.memberId) const member = await guild.members.fetch(expired.memberId)
logger.debug(`Removing role preset for ${expired.memberId} in ${expired.guildId}`)
await removeRolePreset(member, expired.preset) await removeRolePreset(member, expired.preset)
await database
.delete(appliedPresets)
.where(and(eq(appliedPresets.guildId, expired.guildId), eq(appliedPresets.memberId, expired.memberId)))
} catch (e) { } catch (e) {
logger.error(`Error while removing role preset for ${expired.memberId} in ${expired.guildId}: ${e}`) logger.error(`Error while removing role preset for ${expired.memberId} in ${expired.guildId}: ${e}`)
} }

View File

@@ -57,7 +57,7 @@ export const cureNickname = async (member: GuildMember) => {
cured = cured =
member.user.username.length >= 3 member.user.username.length >= 3
? member.user.username ? member.user.username
: config.moderation?.cure?.defaultName ?? 'Server member' : (config.moderation?.cure?.defaultName ?? 'Server member')
if (cured.toLowerCase() === name.toLowerCase()) return if (cured.toLowerCase() === name.toLowerCase()) return

View File

@@ -1,6 +1,15 @@
import parse from 'parse-duration' import parse from 'parse-duration'
export const parseDuration = (duration: string) => parse(duration, 'ms') ?? Number.NaN parse[''] = parse['s']!
parse['mo'] = parse['M'] = parse['month']!
export const parseDuration = (duration: string, defaultUnit?: parse.Units) => {
const defaultUnitValue = parse['']!
if (defaultUnit) parse[''] = parse[defaultUnit]!
const result = parse(duration, 'ms') ?? Number.NaN
parse[''] = defaultUnitValue
return result
}
export const durationToString = (duration: number) => { export const durationToString = (duration: number) => {
if (duration === 0) return '0s' if (duration === 0) return '0s'

1885
bun.lock Normal file

File diff suppressed because it is too large Load Diff

BIN
bun.lockb

Binary file not shown.

View File

@@ -1,7 +1,7 @@
# 🏗️ Setting up the development environment # 🏗️ Setting up the development environment
> [!IMPORTANT] > [!IMPORTANT]
> **This project uses [Bun](https://bun.sh) to run and bundle the code.** > **This project uses [Bun](https://bun.sh) to run and bundle the code.**
> Compatibility with other runtimes (Node.js, Deno, ...) are not guaranteed and most package scripts won't work. > Compatibility with other runtimes (Node.js, Deno, ...) are not guaranteed and most package scripts won't work.
To start developing, you'll need to set up the development environment first. To start developing, you'll need to set up the development environment first.
@@ -11,8 +11,8 @@ To start developing, you'll need to set up the development environment first.
2. Clone the mono-repository 2. Clone the mono-repository
```sh ```sh
git clone https://github.com/revanced/revanced-helper.git && git clone https://github.com/revanced/revanced-bots.git &&
cd revanced-helper cd revanced-bots
``` ```
3. Install dependencies 3. Install dependencies

View File

@@ -1,5 +1,5 @@
{ {
"name": "revanced-helper", "name": "revanced-bots",
"description": "🤖 Bots assisting ReVanced on multiple platforms", "description": "🤖 Bots assisting ReVanced on multiple platforms",
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.0",
@@ -15,13 +15,13 @@
"flint:check": "biome check .", "flint:check": "biome check .",
"clint": "commitlint --edit" "clint": "commitlint --edit"
}, },
"homepage": "https://github.com/revanced/revanced-helper#readme", "homepage": "https://github.com/revanced/revanced-bots#readme",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/revanced/revanced-helper.git" "url": "git+https://github.com/revanced/revanced-bots.git"
}, },
"bugs": { "bugs": {
"url": "https://github.com/revanced/revanced-helper/issues" "url": "https://github.com/revanced/revanced-bots/issues"
}, },
"contributors": [ "contributors": [
"Palm <contact@palmdevs.me> (https://palmdevs.me)", "Palm <contact@palmdevs.me> (https://palmdevs.me)",
@@ -29,23 +29,23 @@
], ],
"packageManager": "bun@1.1.20", "packageManager": "bun@1.1.20",
"devDependencies": { "devDependencies": {
"@anolilab/multi-semantic-release": "^1.1.3", "@anolilab/multi-semantic-release": "^1.1.10",
"@biomejs/biome": "^1.9.2", "@biomejs/biome": "^1.9.4",
"@codedependant/semantic-release-docker": "^5.0.3", "@codedependant/semantic-release-docker": "^5.1.0",
"@commitlint/cli": "^19.5.0", "@commitlint/cli": "^19.8.0",
"@commitlint/config-conventional": "^19.5.0", "@commitlint/config-conventional": "^19.8.0",
"@saithodev/semantic-release-backmerge": "^4.0.1", "@saithodev/semantic-release-backmerge": "^4.0.1",
"@semantic-release/changelog": "^6.0.3", "@semantic-release/changelog": "^6.0.3",
"@semantic-release/exec": "^6.0.3", "@semantic-release/exec": "^6.0.3",
"@semantic-release/git": "^10.0.1", "@semantic-release/git": "^10.0.1",
"@tsconfig/strictest": "^2.0.5", "@tsconfig/strictest": "^2.0.5",
"@types/bun": "^1.1.10", "@types/bun": "^1.2.8",
"conventional-changelog-conventionalcommits": "^7.0.2", "conventional-changelog-conventionalcommits": "^7.0.2",
"lefthook": "^1.7.15", "lefthook": "^1.11.6",
"portainer-service-webhook": "https://github.com/newarifrh/portainer-service-webhook#v1", "portainer-service-webhook": "https://github.com/newarifrh/portainer-service-webhook#v1",
"semantic-release": "^24.1.1", "semantic-release": "^24.2.3",
"turbo": "^2.1.2", "turbo": "^2.5.0",
"typescript": "^5.6.2" "typescript": "^5.8.2"
}, },
"trustedDependencies": [ "trustedDependencies": [
"@biomejs/biome", "@biomejs/biome",
@@ -56,6 +56,6 @@
"patchedDependencies": { "patchedDependencies": {
"@semantic-release/npm@12.0.1": "patches/@semantic-release%2Fnpm@12.0.1.patch", "@semantic-release/npm@12.0.1": "patches/@semantic-release%2Fnpm@12.0.1.patch",
"drizzle-kit@0.22.8": "patches/drizzle-kit@0.22.8.patch", "drizzle-kit@0.22.8": "patches/drizzle-kit@0.22.8.patch",
"decancer@3.2.3": "patches/decancer@3.2.3.patch" "decancer@3.2.4": "patches/decancer@3.2.4.patch"
} }
} }

View File

@@ -13,7 +13,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/revanced/revanced-helper.git", "url": "git+https://github.com/revanced/revanced-bots.git",
"directory": "packages/api" "directory": "packages/api"
}, },
"author": "Palm <contact@palmdevs.me> (https://palmdevs.me)", "author": "Palm <contact@palmdevs.me> (https://palmdevs.me)",
@@ -23,15 +23,15 @@
], ],
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
"bugs": { "bugs": {
"url": "https://github.com/revanced/revanced-helper/issues" "url": "https://github.com/revanced/revanced-bots/issues"
}, },
"homepage": "https://github.com/revanced/revanced-helper#readme", "homepage": "https://github.com/revanced/revanced-bots#readme",
"dependencies": { "dependencies": {
"@revanced/bot-shared": "workspace:*", "@revanced/bot-shared": "workspace:*",
"ws": "^8.17.1" "ws": "^8.18.1"
}, },
"devDependencies": { "devDependencies": {
"@types/ws": "^8.5.10", "@types/ws": "^8.18.1",
"typed-emitter": "^2.1.0" "typed-emitter": "^2.1.0"
} }
} }

View File

@@ -35,7 +35,7 @@ export class ClientWebSocketManager {
/** /**
* Sets the URL to connect to * Sets the URL to connect to
* *
* **Requires a reconnect to take effect** * **Requires a reconnect to take effect**
*/ */
async setOptions({ url, timeout }: Partial<ClientWebSocketManagerOptions>, autoReconnect = true) { async setOptions({ url, timeout }: Partial<ClientWebSocketManagerOptions>, autoReconnect = true) {
@@ -207,7 +207,7 @@ export class ClientWebSocketManager {
protected _toBuffer(data: RawData) { protected _toBuffer(data: RawData) {
if (data instanceof Buffer) return data if (data instanceof Buffer) return data
if (data instanceof ArrayBuffer) return Buffer.from(data) if (data instanceof ArrayBuffer) return Buffer.from(data)
return Buffer.concat(data) return Buffer.concat(data as Uint8Array[])
} }
} }

View File

@@ -16,7 +16,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/revanced/revanced-helper.git", "url": "git+https://github.com/revanced/revanced-bots.git",
"directory": "packages/shared" "directory": "packages/shared"
}, },
"author": "Palm <contact@palmdevs.me> (https://palmdevs.me)", "author": "Palm <contact@palmdevs.me> (https://palmdevs.me)",
@@ -26,12 +26,12 @@
], ],
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
"bugs": { "bugs": {
"url": "https://github.com/revanced/revanced-helper/issues" "url": "https://github.com/revanced/revanced-bots/issues"
}, },
"homepage": "https://github.com/revanced/revanced-helper#readme", "homepage": "https://github.com/revanced/revanced-bots#readme",
"dependencies": { "dependencies": {
"bson": "^6.7.0", "bson": "^6.10.3",
"chalk": "^5.3.0", "chalk": "^5.4.1",
"tracer": "^1.3.0", "tracer": "^1.3.0",
"valibot": "^0.30.0" "valibot": "^0.30.0"
} }

View File

@@ -1,18 +1,18 @@
import { import {
url,
type AnySchema, type AnySchema,
type BooleanSchema,
type NullSchema, type NullSchema,
type ObjectSchema, type ObjectSchema,
type Output, type Output,
type BooleanSchema,
array, array,
boolean,
enum_, enum_,
null_, null_,
object, object,
parse, parse,
special, special,
string, string,
boolean,
url,
// merge // merge
} from 'valibot' } from 'valibot'
import DisconnectReason from '../constants/DisconnectReason' import DisconnectReason from '../constants/DisconnectReason'

View File

@@ -18,6 +18,6 @@ export function serializePacket<TOp extends Operation>(packet: Packet<TOp>) {
* @returns A packet * @returns A packet
*/ */
export function deserializePacket(buffer: Buffer) { export function deserializePacket(buffer: Buffer) {
const data = BSON.deserialize(buffer) const data = BSON.deserialize(buffer as Uint8Array)
return parse(PacketSchema, data) as Packet return parse(PacketSchema, data) as Packet
} }