Compare commits

..

19 Commits

Author SHA1 Message Date
semantic-release-bot
0a5a9c3e27 chore(release): 1.4.1 [skip ci]
## @revanced/discord-bot [1.4.1](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.4.0...@revanced/discord-bot@1.4.1) (2025-09-13)

### Bug Fixes

* **bots/discord/database:** use non-deprecated way to create indexes ([8cc2377](8cc2377cbf))
* **bots/discord:** allow partial users ([dd3e7d2](dd3e7d2ee0))
* **bots/discord:** error in cache `keepOverLimit` comparison ([567c5d2](567c5d2c7f))
2025-09-13 12:28:35 +00:00
PalmDevs
50a205c430 chore: update dependencies 2025-09-13 19:27:45 +07:00
PalmDevs
dd3e7d2ee0 fix(bots/discord): allow partial users 2025-09-13 19:27:43 +07:00
PalmDevs
567c5d2c7f fix(bots/discord): error in cache keepOverLimit comparison 2025-09-13 19:27:42 +07:00
PalmDevs
8cc2377cbf fix(bots/discord/database): use non-deprecated way to create indexes 2025-09-13 19:27:41 +07:00
semantic-release-bot
f3c199d573 chore(release): 1.4.0 [skip ci]
# @revanced/discord-bot [1.4.0](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.3.0...@revanced/discord-bot@1.4.0) (2025-07-11)

### Bug Fixes

* **bots/discord:** pass non-empty out of scope label to discord ([fbd9480](fbd9480036))

### Features

* **bots/discord:** react to label classified response ([96a9b83](96a9b83c48))
2025-07-11 18:23:24 +00:00
PalmDevs
42c0facef1 chore: format 2025-07-12 01:22:30 +07:00
PalmDevs
96a9b83c48 feat(bots/discord): react to label classified response 2025-07-12 01:22:28 +07:00
PalmDevs
fbd9480036 fix(bots/discord): pass non-empty out of scope label to discord 2025-07-12 01:22:27 +07:00
semantic-release-bot
cc02c0a775 chore(release): 1.3.0 [skip ci]
# @revanced/discord-bot [1.3.0](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.2.3...@revanced/discord-bot@1.3.0) (2025-07-11)

### Features

* **bots/discord:** support training without label ([c68cfd1](c68cfd1c01))
2025-07-11 18:08:35 +00:00
semantic-release-bot
c83e219088 chore(release): 1.1.0 [skip ci]
# @revanced/bot-websocket-api [1.1.0](https://github.com/revanced/revanced-bots/compare/@revanced/bot-websocket-api@1.0.2...@revanced/bot-websocket-api@1.1.0) (2025-07-11)

### Features

* **apis/websocket:** support training without label ([670cc70](670cc70057))
2025-07-11 18:07:46 +00:00
PalmDevs
6164e6c1a5 chore: format 2025-07-12 01:06:45 +07:00
PalmDevs
47d2f8c015 chore: update dependencies and remove outdated patches 2025-07-12 01:06:43 +07:00
PalmDevs
c68cfd1c01 feat(bots/discord): support training without label 2025-07-12 01:06:41 +07:00
PalmDevs
2b1928e116 feat(packages/api): support training without label 2025-07-12 01:06:39 +07:00
PalmDevs
670cc70057 feat(apis/websocket): support training without label 2025-07-12 01:06:37 +07:00
Palm
439f301872 chore: merge dev to main 2025-07-11 21:05:10 +07:00
Pun Butrach
aeccf12906 ci: Use default fetch-depth of 1 for checkout step (#47) 2025-07-08 18:14:54 +02:00
semantic-release-bot
b4ac8433f4 chore(release): 1.2.3 [skip ci]
## @revanced/discord-bot [1.2.3](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.2.2...@revanced/discord-bot@1.2.3) (2025-06-23)

### Bug Fixes

* **bots/discord:** disable unneeded cache, enable message cache sweeping ([3a0f0fe](3a0f0fe786))
2025-06-23 13:33:41 +00:00
49 changed files with 872 additions and 324 deletions

View File

@@ -20,11 +20,6 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
# Make sure the release step uses its own credentials:
# https://github.com/cycjimmy/semantic-release-action#private-packages
persist-credentials: false
fetch-depth: 0
- name: Cache dependencies - name: Cache dependencies
uses: actions/cache@v4 uses: actions/cache@v4

View File

@@ -1,3 +1,10 @@
# @revanced/bot-websocket-api [1.1.0](https://github.com/revanced/revanced-bots/compare/@revanced/bot-websocket-api@1.0.2...@revanced/bot-websocket-api@1.1.0) (2025-07-11)
### Features
* **apis/websocket:** support training without label ([670cc70](https://github.com/revanced/revanced-bots/commit/670cc700570b32924738c3f24acb9f5312d2dcdb))
## @revanced/bot-websocket-api [1.0.2](https://github.com/revanced/revanced-bots/compare/@revanced/bot-websocket-api@1.0.1...@revanced/bot-websocket-api@1.0.2) (2025-06-23) ## @revanced/bot-websocket-api [1.0.2](https://github.com/revanced/revanced-bots/compare/@revanced/bot-websocket-api@1.0.1...@revanced/bot-websocket-api@1.0.2) (2025-06-23)
## @revanced/bot-websocket-api [1.0.1](https://github.com/revanced/revanced-bots/compare/@revanced/bot-websocket-api@1.0.0...@revanced/bot-websocket-api@1.0.1) (2025-04-09) ## @revanced/bot-websocket-api [1.0.1](https://github.com/revanced/revanced-bots/compare/@revanced/bot-websocket-api@1.0.0...@revanced/bot-websocket-api@1.0.1) (2025-04-09)

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.2", "version": "1.1.0",
"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": {
@@ -29,9 +29,9 @@
"dependencies": { "dependencies": {
"@revanced/bot-shared": "workspace:*", "@revanced/bot-shared": "workspace:*",
"@sapphire/async-queue": "^1.5.5", "@sapphire/async-queue": "^1.5.5",
"chalk": "^5.4.1", "chalk": "^5.6.2",
"tesseract.js": "^6.0.1", "tesseract.js": "^6.0.1",
"ws": "^8.18.2" "ws": "^8.18.3"
}, },
"devDependencies": { "devDependencies": {
"@types/ws": "^8.18.1", "@types/ws": "^8.18.1",

View File

@@ -23,12 +23,12 @@ export const wit = {
if (!res.ok) throw new Error(`Failed to fetch from Wit.ai: ${res.statusText} (${res.status})`) if (!res.ok) throw new Error(`Failed to fetch from Wit.ai: ${res.statusText} (${res.status})`)
return await res.json() return (await res.json()) as WitMessageResponse
}, },
message(text: string) { message(text: string) {
return this.fetch(`/message?q=${encodeURIComponent(text)}&n=8`) as Promise<WitMessageResponse> return this.fetch(`/message?q=${encodeURIComponent(text)}&n=8`) as Promise<WitMessageResponse>
}, },
async train(text: string, label: string) { async train(text: string, label?: string) {
await this.fetch('/utterances', { await this.fetch('/utterances', {
body: JSON.stringify([ body: JSON.stringify([
{ {
@@ -41,7 +41,14 @@ export const wit = {
method: 'POST', method: 'POST',
}) })
}, },
} as const } satisfies Wit
export interface Wit {
token: string
fetch(route: string, options?: RequestInit): Promise<WitMessageResponse>
message(text: string): Promise<WitMessageResponse>
train(text: string, label?: string): Promise<void>
}
export interface WitMessageResponse { export interface WitMessageResponse {
text: string text: string

View File

@@ -1,7 +1,7 @@
import type { ClientOperation, Logger } from '@revanced/bot-shared' import type { ClientOperation, Logger } from '@revanced/bot-shared'
import type { Worker as TesseractWorker } from 'tesseract.js' import type { Worker as TesseractWorker } from 'tesseract.js'
import type { ClientPacketObject } from '../classes/Client' import type { ClientPacketObject } from '../classes/Client'
import type { WitMessageResponse } from '../context' import type { Wit } from '../context'
import type { Config } from '../utils/config' import type { Config } from '../utils/config'
export { default as parseImageEventHandler } from './parseImage' export { default as parseImageEventHandler } from './parseImage'
@@ -14,10 +14,7 @@ export type EventHandler<POp extends ClientOperation> = (
) => void | Promise<void> ) => void | Promise<void>
export type EventContext = { export type EventContext = {
wit: { wit: Wit
train(text: string, label: string): Promise<void>
message(text: string): Promise<WitMessageResponse>
}
tesseract: TesseractWorker tesseract: TesseractWorker
logger: Logger logger: Logger
config: Config config: Config

View File

@@ -10,7 +10,7 @@ const trainMessageEventHandler: EventHandler<ClientOperation.TrainMessage> = asy
const nextSeq = client.currentSequence++ const nextSeq = client.currentSequence++
const actualText = text.slice(0, 279) const actualText = text.slice(0, 279)
logger.debug(`${client.id} requested to train label ${label} (${nextSeq}) with:`, actualText) logger.debug(`${client.id} requested to train label ${label ?? '<out of scope>'} (${nextSeq}) with:`, actualText)
try { try {
await wit.train(actualText, label) await wit.train(actualText, label)

View File

@@ -1,3 +1,38 @@
## @revanced/discord-bot [1.4.1](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.4.0...@revanced/discord-bot@1.4.1) (2025-09-13)
### Bug Fixes
* **bots/discord/database:** use non-deprecated way to create indexes ([8cc2377](https://github.com/revanced/revanced-bots/commit/8cc2377cbfcc74c2c3228ed18da2495b4efd45aa))
* **bots/discord:** allow partial users ([dd3e7d2](https://github.com/revanced/revanced-bots/commit/dd3e7d2ee0cdf40e083af7f6db35ac3508ddf763))
* **bots/discord:** error in cache `keepOverLimit` comparison ([567c5d2](https://github.com/revanced/revanced-bots/commit/567c5d2c7f41dae7d7fec9946a7dd2ac1b10cc2a))
# @revanced/discord-bot [1.4.0](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.3.0...@revanced/discord-bot@1.4.0) (2025-07-11)
### Bug Fixes
* **bots/discord:** pass non-empty out of scope label to discord ([fbd9480](https://github.com/revanced/revanced-bots/commit/fbd948003631b48a1914eb7b2551ead4b05089b7))
### Features
* **bots/discord:** react to label classified response ([96a9b83](https://github.com/revanced/revanced-bots/commit/96a9b83c486fdc6e78f4c59e197fa6c1dab09161))
# @revanced/discord-bot [1.3.0](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.2.3...@revanced/discord-bot@1.3.0) (2025-07-11)
### Features
* **bots/discord:** support training without label ([c68cfd1](https://github.com/revanced/revanced-bots/commit/c68cfd1c01703fad17f233ad4e13cf81913afbb6))
## @revanced/discord-bot [1.2.3](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.2.2...@revanced/discord-bot@1.2.3) (2025-06-23)
### Bug Fixes
* **bots/discord:** disable unneeded cache, enable message cache sweeping ([3a0f0fe](https://github.com/revanced/revanced-bots/commit/3a0f0fe7861d73a4d81ecaba0e12bd60c06f8eb8))
## @revanced/discord-bot [1.2.2](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.2.1...@revanced/discord-bot@1.2.2) (2025-06-10) ## @revanced/discord-bot [1.2.2](https://github.com/revanced/revanced-bots/compare/@revanced/discord-bot@1.2.1...@revanced/discord-bot@1.2.2) (2025-06-10)

View File

@@ -66,7 +66,6 @@ export default {
}, },
}, },
humanCorrections: { humanCorrections: {
falsePositiveLabel: 'false_positive',
allow: { allow: {
members: { members: {
permissions: 8n, permissions: 8n,

View File

@@ -36,7 +36,6 @@ export type Config = {
blacklist?: Filter blacklist?: Filter
} }
humanCorrections: { humanCorrections: {
falsePositiveLabel: string
allow?: { allow?: {
users?: string[] users?: string[]
members?: { members?: {
@@ -72,7 +71,7 @@ export type ConfigMessageScanResponse = {
image?: Array<RegExp> image?: Array<RegExp>
} }
filterOverride?: NonNullable<Config['messageScan']>['filter'] filterOverride?: NonNullable<Config['messageScan']>['filter']
response: ConfigMessageScanResponseMessage | null response: ConfigMessageScanResponseMessage
respondToReply?: boolean respondToReply?: boolean
} }

View File

@@ -2,7 +2,7 @@
"name": "@revanced/discord-bot", "name": "@revanced/discord-bot",
"type": "module", "type": "module",
"private": true, "private": true,
"version": "1.2.2", "version": "1.4.1",
"description": "🤖 Discord bot assisting ReVanced", "description": "🤖 Discord bot assisting ReVanced",
"main": "src/index.ts", "main": "src/index.ts",
"scripts": { "scripts": {
@@ -28,19 +28,19 @@
}, },
"homepage": "https://github.com/revanced/revanced-bots#readme", "homepage": "https://github.com/revanced/revanced-bots#readme",
"dependencies": { "dependencies": {
"@discordjs/builders": "^1.11.2", "@discordjs/builders": "^1.11.3",
"@discordjs/rest": "^2.5.1", "@discordjs/rest": "^2.6.0",
"@revanced/bot-api": "workspace:*", "@revanced/bot-api": "workspace:*",
"@revanced/bot-shared": "workspace:*", "@revanced/bot-shared": "workspace:*",
"@sapphire/duration": "^1.2.0", "@sapphire/duration": "^1.2.0",
"chalk": "^5.4.1", "chalk": "^5.6.2",
"decancer": "^3.3.2", "decancer": "^3.3.3",
"discord.js": "^14.20.0", "discord.js": "^14.22.1",
"drizzle-orm": "^0.44.2" "drizzle-orm": "^0.44.5"
}, },
"devDependencies": { "devDependencies": {
"@libsql/client": "^0.15.9", "@libsql/client": "^0.15.15",
"discord-api-types": "^0.38.13", "discord-api-types": "^0.38.24",
"drizzle-kit": "^0.31.2" "drizzle-kit": "^0.31.4"
} }
} }

View File

@@ -1,11 +1,11 @@
import { AdminCommand } from '$/classes/Command'
import { createSuccessEmbed } from '$/utils/discord/embeds'
import { parseDuration } from '$/utils/duration'
import { ApplicationCommandOptionType, MessageFlags } from 'discord.js' import { ApplicationCommandOptionType, MessageFlags } from 'discord.js'
import { unlinkSync, writeFileSync } from 'fs' import { unlinkSync, writeFileSync } from 'fs'
import { join } from 'path' import { join } from 'path'
import { inspect } from 'util' import { inspect } from 'util'
import { createContext, runInContext } from 'vm' import { createContext, runInContext } from 'vm'
import { AdminCommand } from '$/classes/Command'
import { createSuccessEmbed } from '$/utils/discord/embeds'
import { parseDuration } from '$/utils/duration'
export default new AdminCommand({ export default new AdminCommand({
name: 'eval', name: 'eval',

View File

@@ -1,6 +1,6 @@
import { ApplicationCommandOptionType } from 'discord.js'
import { AdminCommand } from '$/classes/Command' import { AdminCommand } from '$/classes/Command'
import CommandError, { CommandErrorType } from '$/classes/CommandError' import CommandError, { CommandErrorType } from '$/classes/CommandError'
import { ApplicationCommandOptionType } from 'discord.js'
export default new AdminCommand({ export default new AdminCommand({
name: 'exception-test', name: 'exception-test',

View File

@@ -1,5 +1,5 @@
import { AdminCommand } from '$/classes/Command'
import { type CommandInteraction, MessageFlags } from 'discord.js' import { type CommandInteraction, MessageFlags } from 'discord.js'
import { AdminCommand } from '$/classes/Command'
export default new AdminCommand({ export default new AdminCommand({
name: 'reload', name: 'reload',

View File

@@ -1,7 +1,7 @@
import { ApplicationCommandOptionType, Routes } from 'discord.js'
import { AdminCommand } from '$/classes/Command' import { AdminCommand } from '$/classes/Command'
import CommandError, { CommandErrorType } from '$/classes/CommandError' import CommandError, { CommandErrorType } from '$/classes/CommandError'
import { createSuccessEmbed } from '$/utils/discord/embeds' import { createSuccessEmbed } from '$/utils/discord/embeds'
import { ApplicationCommandOptionType, Routes } from 'discord.js'
const SubcommandOptions = { const SubcommandOptions = {
where: { where: {

View File

@@ -1,5 +1,5 @@
import { AdminCommand } from '$/classes/Command'
import { MessageFlags } from 'discord.js' import { MessageFlags } from 'discord.js'
import { AdminCommand } from '$/classes/Command'
export default new AdminCommand({ export default new AdminCommand({
name: 'stop', name: 'stop',

View File

@@ -1,6 +1,6 @@
import { EmbedBuilder, MessageFlags } from 'discord.js'
import Command from '$/classes/Command' import Command from '$/classes/Command'
import { applyCommonEmbedStyles } from '$/utils/discord/embeds' import { applyCommonEmbedStyles } from '$/utils/discord/embeds'
import { EmbedBuilder, MessageFlags } from 'discord.js'
export default new Command({ export default new Command({
name: 'coinflip', name: 'coinflip',

View File

@@ -1,5 +1,5 @@
import CommandError, { CommandErrorType } from '$/classes/CommandError'
import { ApplicationCommandOptionType, Message, MessageFlags } from 'discord.js' import { ApplicationCommandOptionType, Message, MessageFlags } from 'discord.js'
import CommandError, { CommandErrorType } from '$/classes/CommandError'
import { ModerationCommand } from '../../classes/Command' import { ModerationCommand } from '../../classes/Command'
export default new ModerationCommand({ export default new ModerationCommand({

View File

@@ -1,7 +1,7 @@
import { MessageFlags } from 'discord.js'
import { ModerationCommand } from '$/classes/Command' import { ModerationCommand } from '$/classes/Command'
import { createSuccessEmbed } from '$/utils/discord/embeds' import { createSuccessEmbed } from '$/utils/discord/embeds'
import { cureNickname } from '$/utils/discord/moderation' import { cureNickname } from '$/utils/discord/moderation'
import { MessageFlags } from 'discord.js'
export default new ModerationCommand({ export default new ModerationCommand({
name: 'cure', name: 'cure',

View File

@@ -1,7 +1,7 @@
import { EmbedBuilder } from 'discord.js'
import { ModerationCommand } from '$/classes/Command' import { ModerationCommand } from '$/classes/Command'
import CommandError, { CommandErrorType } from '$/classes/CommandError' import CommandError, { CommandErrorType } from '$/classes/CommandError'
import { applyCommonEmbedStyles } from '$/utils/discord/embeds' import { applyCommonEmbedStyles } from '$/utils/discord/embeds'
import { EmbedBuilder } from 'discord.js'
export default new ModerationCommand({ export default new ModerationCommand({
name: 'purge', name: 'purge',

View File

@@ -1,8 +1,8 @@
import { ChannelType } from 'discord.js'
import { ModerationCommand } from '$/classes/Command' import { ModerationCommand } from '$/classes/Command'
import CommandError, { CommandErrorType } from '$/classes/CommandError' import CommandError, { CommandErrorType } from '$/classes/CommandError'
import { createSuccessEmbed } from '$/utils/discord/embeds' import { createSuccessEmbed } from '$/utils/discord/embeds'
import { durationToString, parseDuration } from '$/utils/duration' import { durationToString, parseDuration } from '$/utils/duration'
import { ChannelType } from 'discord.js'
export default new ModerationCommand({ export default new ModerationCommand({
name: 'slowmode', name: 'slowmode',

View File

@@ -1,10 +1,10 @@
import { and, eq } from 'drizzle-orm'
import { ModerationCommand } from '$/classes/Command' import { ModerationCommand } from '$/classes/Command'
import CommandError, { CommandErrorType } from '$/classes/CommandError' import CommandError, { CommandErrorType } from '$/classes/CommandError'
import { appliedPresets } from '$/database/schemas' import { appliedPresets } from '$/database/schemas'
import { createModerationActionEmbed } from '$/utils/discord/embeds' import { createModerationActionEmbed } from '$/utils/discord/embeds'
import { sendModerationReplyAndLogs } from '$/utils/discord/moderation' import { sendModerationReplyAndLogs } from '$/utils/discord/moderation'
import { removeRolePreset } from '$/utils/discord/rolePresets' import { removeRolePreset } from '$/utils/discord/rolePresets'
import { and, eq } from 'drizzle-orm'
export default new ModerationCommand({ export default new ModerationCommand({
name: 'unmute', name: 'unmute',

View File

@@ -1,7 +1,7 @@
import { type FetchMessageOptions, MessageFlags, type MessageResolvable } from 'discord.js'
import Command from '$/classes/Command' import Command from '$/classes/Command'
import CommandError, { CommandErrorType } from '$/classes/CommandError' import CommandError, { CommandErrorType } from '$/classes/CommandError'
import { createSuccessEmbed } from '$/utils/discord/embeds' import { createSuccessEmbed } from '$/utils/discord/embeds'
import { type FetchMessageOptions, MessageFlags, type MessageResolvable } from 'discord.js'
import { config } from '../../../context' import { config } from '../../../context'
import type { ConfigMessageScanResponseLabelConfig } from 'config.schema' import type { ConfigMessageScanResponseLabelConfig } from 'config.schema'
@@ -9,7 +9,7 @@ const msRcConfig = config.messageScan?.humanCorrections?.allow
export default new Command({ export default new Command({
name: 'train', name: 'train',
description: 'Train a specific message or text to a specific label', description: 'Train a specific message to a specific label',
type: Command.Type.ChatGuild, type: Command.Type.ChatGuild,
requirements: { requirements: {
users: msRcConfig?.users, users: msRcConfig?.users,
@@ -26,9 +26,9 @@ export default new Command({
required: true, required: true,
}, },
label: { label: {
description: 'The label to train the message as', description: 'The label to train the message as (leave empty for out of scope)',
type: Command.OptionType.String, type: Command.OptionType.String,
required: true, required: false,
}, },
}, },
allowMessageCommand: true, allowMessageCommand: true,
@@ -49,7 +49,7 @@ export default new Command({
'This command can only be used in or on text channels', 'This command can only be used in or on text channels',
) )
if (!labels.includes(label)) if (label && !labels.includes(label))
throw new CommandError( throw new CommandError(
CommandErrorType.InvalidArgument, CommandErrorType.InvalidArgument,
`The provided label is invalid.\nValid labels are:${labels.map(l => `\n- \`${l}\``).join('')}`, `The provided label is invalid.\nValid labels are:${labels.map(l => `\n- \`${l}\``).join('')}`,
@@ -60,14 +60,14 @@ export default new Command({
) )
if (!refMsg) throw new CommandError(CommandErrorType.InvalidArgument, 'The provided message does not exist.') if (!refMsg) throw new CommandError(CommandErrorType.InvalidArgument, 'The provided message does not exist.')
logger.debug(`User ${context.executor.id} is training message ${refMsg?.id} as ${label}`) logger.debug(`User ${context.executor.id} is training message ${refMsg?.id} as ${label ?? 'out of scope'}`)
await context.api.client.trainMessage(refMsg.content, label) await context.api.client.trainMessage(refMsg.content, label)
await trigger.reply({ await trigger.reply({
embeds: [ embeds: [
createSuccessEmbed( createSuccessEmbed(
'Message trained', 'Message trained',
`The provided message has been trained as \`${label}\`. Thank you for your contribution!`, `The provided message has been trained as ${label ? `\`${label}\`` : 'out of scope'}. Thank you for your contribution!`,
), ),
], ],
flags: MessageFlags.Ephemeral, flags: MessageFlags.Ephemeral,

View File

@@ -1,6 +1,6 @@
import { type APIStringSelectComponent, ComponentType, MessageFlags } from 'discord.js'
import Command from '$/classes/Command' import Command from '$/classes/Command'
import CommandError, { CommandErrorType } from '$/classes/CommandError' import CommandError, { CommandErrorType } from '$/classes/CommandError'
import { type APIStringSelectComponent, ComponentType, MessageFlags } from 'discord.js'
import { config } from '../../../context' import { config } from '../../../context'
import type { ConfigMessageScanResponseLabelConfig } from 'config.schema' import type { ConfigMessageScanResponseLabelConfig } from 'config.schema'
@@ -37,7 +37,10 @@ export default new Command({
components: [ components: [
{ {
custom_id: `tr_${trigger.targetMessage.channelId}_${trigger.targetId}`, custom_id: `tr_${trigger.targetMessage.channelId}_${trigger.targetId}`,
options: labels.map(label => ({ label, value: label })), options: [
...labels.map(label => ({ label, value: label })),
{ label: 'Out of scope', value: OutOfScopeLabel, emoji: { name: '❌' } },
],
type: ComponentType.StringSelect, type: ComponentType.StringSelect,
} satisfies APIStringSelectComponent, } satisfies APIStringSelectComponent,
], ],
@@ -48,3 +51,5 @@ export default new Command({
}) })
}, },
}) })
export const OutOfScopeLabel = '<out of scope>'

View File

@@ -100,7 +100,7 @@ export const discord = {
GuildMessageManager: { GuildMessageManager: {
maxSize: 0, maxSize: 0,
// Always keep messages posted by the client in cache // Always keep messages posted by the client in cache
keepOverLimit: message => message.author.id === message.client.user.id, keepOverLimit: message => message.author?.id === message.client.user.id,
}, },
// Unneeded cache // Unneeded cache
MessageManager: 0, MessageManager: 0,
@@ -122,7 +122,7 @@ export const discord = {
BaseGuildEmojiManager: 0, BaseGuildEmojiManager: 0,
GuildInviteManager: 0, GuildInviteManager: 0,
}), }),
partials: [Partials.Message, Partials.Reaction, Partials.GuildMember], partials: [Partials.Message, Partials.Reaction, Partials.GuildMember, Partials.User],
}), }),
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

@@ -20,9 +20,7 @@ export const appliedPresets = sqliteTable(
preset: text('preset').notNull(), preset: text('preset').notNull(),
until: integer('until'), until: integer('until'),
}, },
table => ({ table => [uniqueIndex('unique_composite').on(table.memberId, table.preset, table.guildId)],
uniqueComposite: uniqueIndex('unique_composite').on(table.memberId, table.preset, table.guildId),
}),
) )
export type Response = InferSelectModel<typeof responses> export type Response = InferSelectModel<typeof responses>

View File

@@ -1,5 +1,5 @@
import { on, withContext } from '$utils/api/events'
import { DisconnectReason, HumanizedDisconnectReason } from '@revanced/bot-shared' import { DisconnectReason, HumanizedDisconnectReason } from '@revanced/bot-shared'
import { on, withContext } from '$utils/api/events'
withContext(on, 'disconnect', ({ api, config, logger }, reason, msg) => { withContext(on, 'disconnect', ({ api, config, logger }, reason, msg) => {
if (reason === DisconnectReason.PlannedDisconnect && api.intentionallyDisconnecting) return if (reason === DisconnectReason.PlannedDisconnect && api.intentionallyDisconnecting) return

View File

@@ -1,7 +1,7 @@
import { and, eq, gt } from 'drizzle-orm'
import { appliedPresets } from '$/database/schemas' import { appliedPresets } from '$/database/schemas'
import { on, withContext } from '$/utils/discord/events' import { on, withContext } from '$/utils/discord/events'
import { applyRolesUsingPreset } from '$/utils/discord/rolePresets' import { applyRolesUsingPreset } from '$/utils/discord/rolePresets'
import { and, eq, gt } from 'drizzle-orm'
withContext(on, 'guildMemberAdd', async ({ database }, member) => { withContext(on, 'guildMemberAdd', async ({ database }, member) => {
const applieds = await database.query.appliedPresets.findMany({ const applieds = await database.query.appliedPresets.findMany({

View File

@@ -1,7 +1,7 @@
import { MessageFlags } from 'discord.js'
import CommandError from '$/classes/CommandError' import CommandError from '$/classes/CommandError'
import { createStackTraceEmbed } from '$utils/discord/embeds' import { createStackTraceEmbed } from '$utils/discord/embeds'
import { on, withContext } from '$utils/discord/events' import { on, withContext } from '$utils/discord/events'
import { MessageFlags } from 'discord.js'
withContext(on, 'interactionCreate', async (context, interaction) => { withContext(on, 'interactionCreate', async (context, interaction) => {
if (!interaction.isChatInputCommand()) return if (!interaction.isChatInputCommand()) return

View File

@@ -1,7 +1,7 @@
import { MessageFlags } from 'discord.js'
import CommandError from '$/classes/CommandError' import CommandError from '$/classes/CommandError'
import { createStackTraceEmbed } from '$utils/discord/embeds' import { createStackTraceEmbed } from '$utils/discord/embeds'
import { on, withContext } from '$utils/discord/events' import { on, withContext } from '$utils/discord/events'
import { MessageFlags } from 'discord.js'
withContext(on, 'interactionCreate', async (context, interaction) => { withContext(on, 'interactionCreate', async (context, interaction) => {
if (!interaction.isContextMenuCommand()) return if (!interaction.isContextMenuCommand()) return

View File

@@ -1,7 +1,3 @@
import { responses } from '$/database/schemas'
import { handleUserResponseCorrection } from '$/utils/discord/messageScan'
import { createErrorEmbed, createStackTraceEmbed, createSuccessEmbed } from '$utils/discord/embeds'
import { on, withContext } from '$utils/discord/events'
import { import {
type ButtonInteraction, type ButtonInteraction,
MessageFlags, MessageFlags,
@@ -9,6 +5,10 @@ import {
type TextBasedChannel, type TextBasedChannel,
} from 'discord.js' } from 'discord.js'
import { eq } from 'drizzle-orm' import { eq } from 'drizzle-orm'
import { responses } from '$/database/schemas'
import { handleUserResponseCorrection } from '$/utils/discord/messageScan'
import { createErrorEmbed, createStackTraceEmbed, createSuccessEmbed } from '$utils/discord/embeds'
import { on, withContext } from '$utils/discord/events'
// No permission check required as it is already done when the user reacts to a bot response // No permission check required as it is already done when the user reacts to a bot response
withContext(on, 'interactionCreate', async (context, interaction) => { withContext(on, 'interactionCreate', async (context, interaction) => {
@@ -58,8 +58,8 @@ withContext(on, 'interactionCreate', async (context, interaction) => {
const editMessage = (content: string, description?: string) => const editMessage = (content: string, description?: string) =>
editInteractionMessage(interaction, msg.url, content, description) editInteractionMessage(interaction, msg.url, content, description)
const handleCorrection = (label: string) => const handleCorrection = (label?: string) =>
handleUserResponseCorrection(context, response, msg, label, interaction.user) handleUserResponseCorrection(context, response, msg, interaction.user, label)
if (response.correctedById) if (response.correctedById)
return await editMessage( return await editMessage(
@@ -82,7 +82,7 @@ withContext(on, 'interactionCreate', async (context, interaction) => {
await editMessage('Canceled', 'You canceled this interaction. 😞') await editMessage('Canceled', 'You canceled this interaction. 😞')
break break
case 'delete': case 'delete':
await handleCorrection(msConfig.humanCorrections.falsePositiveLabel) await handleCorrection()
await editMessage( await editMessage(
'Marked as false positive', 'Marked as false positive',
'The response has been deleted and marked as a false positive. Thank you for your feedback. 🎉', 'The response has been deleted and marked as a false positive. Thank you for your feedback. 🎉',

View File

@@ -1,6 +1,7 @@
import { MessageFlags, type TextBasedChannel } from 'discord.js'
import { OutOfScopeLabel } from '$/commands/support/train/context-menu'
import { createErrorEmbed, createStackTraceEmbed, createSuccessEmbed } from '$utils/discord/embeds' import { createErrorEmbed, createStackTraceEmbed, createSuccessEmbed } from '$utils/discord/embeds'
import { on, withContext } from '$utils/discord/events' import { on, withContext } from '$utils/discord/events'
import { MessageFlags, type TextBasedChannel } from 'discord.js'
withContext(on, 'interactionCreate', async (context, interaction) => { withContext(on, 'interactionCreate', async (context, interaction) => {
const { const {
@@ -30,8 +31,11 @@ withContext(on, 'interactionCreate', async (context, interaction) => {
flags: MessageFlags.Ephemeral, flags: MessageFlags.Ephemeral,
})) }))
const selectedLabel = interaction.values[0]! const selectedLabel = interaction.values[0]
await context.api.client.trainMessage(msg.content, selectedLabel) await context.api.client.trainMessage(
msg.content,
selectedLabel === OutOfScopeLabel ? undefined : selectedLabel,
)
await interaction.reply({ await interaction.reply({
embeds: [ embeds: [
createSuccessEmbed( createSuccessEmbed(

View File

@@ -1,3 +1,4 @@
import { MessageScanLabeledResponseReactions } from '$/constants'
import { responses } from '$/database/schemas' import { responses } from '$/database/schemas'
import { getResponseFromText, messageMatchesFilter } from '$/utils/discord/messageScan' import { getResponseFromText, messageMatchesFilter } from '$/utils/discord/messageScan'
import { createMessageScanResponseEmbed } from '$utils/discord/embeds' import { createMessageScanResponseEmbed } from '$utils/discord/embeds'
@@ -47,6 +48,8 @@ withContext(on, 'messageCreate', async (context, msg) => {
label, label,
content: msg.content, content: msg.content,
}) })
await Promise.all(Object.values(MessageScanLabeledResponseReactions).map(name => reply.react(name)))
} }
} }
} catch (e) { } catch (e) {

View File

@@ -1,9 +1,3 @@
import { MessageScanLabeledResponseReactions as Reactions } from '$/constants'
import { responses } from '$/database/schemas'
import { createErrorEmbed, createStackTraceEmbed, createSuccessEmbed } from '$/utils/discord/embeds'
import { on, withContext } from '$/utils/discord/events'
import { handleUserResponseCorrection } from '$/utils/discord/messageScan'
import { isAdmin } from '$/utils/discord/permissions'
import { import {
ActionRowBuilder, ActionRowBuilder,
ButtonBuilder, ButtonBuilder,
@@ -12,6 +6,12 @@ import {
StringSelectMenuOptionBuilder, StringSelectMenuOptionBuilder,
} from 'discord.js' } from 'discord.js'
import { eq } from 'drizzle-orm' import { eq } from 'drizzle-orm'
import { MessageScanLabeledResponseReactions as Reactions } from '$/constants'
import { responses } from '$/database/schemas'
import { createErrorEmbed, createStackTraceEmbed, createSuccessEmbed } from '$/utils/discord/embeds'
import { on, withContext } from '$/utils/discord/events'
import { handleUserResponseCorrection } from '$/utils/discord/messageScan'
import { isAdmin } from '$/utils/discord/permissions'
import type { ConfigMessageScanResponseLabelConfig } from '$/../config.schema' import type { ConfigMessageScanResponseLabelConfig } from '$/../config.schema'
const PossibleReactions = Object.values(Reactions) as string[] const PossibleReactions = Object.values(Reactions) as string[]
@@ -63,8 +63,8 @@ withContext(on, 'messageReactionAdd', async (context, rct, user) => {
logger.debug(`User ${user.id} is trying to correct the response ${rct.message.id}`) logger.debug(`User ${user.id} is trying to correct the response ${rct.message.id}`)
const handleCorrection = (label: string) => const handleCorrection = (label?: string) =>
handleUserResponseCorrection(context, response, reactionMessage, label, user) handleUserResponseCorrection(context, response, reactionMessage, user, label)
try { try {
if (reaction.emoji.name === Reactions.train) { if (reaction.emoji.name === Reactions.train) {
@@ -106,7 +106,7 @@ withContext(on, 'messageReactionAdd', async (context, rct, user) => {
.setCustomId(`${componentPrefix}_cancel`), .setCustomId(`${componentPrefix}_cancel`),
new ButtonBuilder() new ButtonBuilder()
.setEmoji(Reactions.delete) .setEmoji(Reactions.delete)
.setLabel('Delete (mark as false positive)') .setLabel('Delete (mark as out of scope)')
.setStyle(ButtonStyle.Danger) .setStyle(ButtonStyle.Danger)
.setCustomId(`${componentPrefix}_delete`), .setCustomId(`${componentPrefix}_delete`),
), ),
@@ -117,8 +117,8 @@ withContext(on, 'messageReactionAdd', async (context, rct, user) => {
components: rows, components: rows,
}) })
} else if (reaction.emoji.name === Reactions.delete) { } else if (reaction.emoji.name === Reactions.delete) {
await handleCorrection(msConfig.humanCorrections.falsePositiveLabel) await handleCorrection()
await user.send({ content: 'The response has been deleted and marked as a false positive.' }) await user.send({ content: 'The response has been deleted and marked as out of scope.' })
} }
} catch (e) { } catch (e) {
logger.error('Failed to correct response:', e) logger.error('Failed to correct response:', e)

View File

@@ -1,9 +1,9 @@
import { type Client, DiscordAPIError } from 'discord.js'
import { and, eq, lt } from 'drizzle-orm'
import { database, logger } from '$/context' import { database, logger } from '$/context'
import { appliedPresets } from '$/database/schemas' import { appliedPresets } from '$/database/schemas'
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 { type Client, DiscordAPIError } from 'discord.js'
import { and, eq, lt } from 'drizzle-orm'
export default withContext(on, 'ready', async ({ config }, client) => { export default withContext(on, 'ready', async ({ config }, client) => {
if (config.rolePresets) { if (config.rolePresets) {

View File

@@ -1,5 +1,5 @@
import { api, discord, logger } from '$/context'
import { getMissingEnvironmentVariables } from '@revanced/bot-shared' import { getMissingEnvironmentVariables } from '@revanced/bot-shared'
import { api, discord, logger } from '$/context'
import './events/register' import './events/register'

View File

@@ -1,5 +1,5 @@
import { DefaultEmbedColor, ReVancedLogoURL } from '$/constants'
import { type APIEmbed, EmbedBuilder, type EmbedField, type JSONEncodable, type User } from 'discord.js' import { type APIEmbed, EmbedBuilder, type EmbedField, type JSONEncodable, type User } from 'discord.js'
import { DefaultEmbedColor, ReVancedLogoURL } from '$/constants'
import type { ConfigMessageScanResponseMessage } from '../../../config.schema' import type { ConfigMessageScanResponseMessage } from '../../../config.schema'
export const createErrorEmbed = (title: string | null, description?: string) => export const createErrorEmbed = (title: string | null, description?: string) =>

View File

@@ -1,6 +1,6 @@
import { type Response, responses } from '$/database/schemas'
import { ButtonStyle, ComponentType } from 'discord.js' import { ButtonStyle, ComponentType } from 'discord.js'
import { eq } from 'drizzle-orm' import { eq } from 'drizzle-orm'
import { type Response, responses } from '$/database/schemas'
import { createMessageScanResponseEmbed } from './embeds' import { createMessageScanResponseEmbed } from './embeds'
import type { Config, ConfigMessageScanResponse, ConfigMessageScanResponseLabelConfig } from 'config.schema' import type { Config, ConfigMessageScanResponse, ConfigMessageScanResponseLabelConfig } from 'config.schema'
import type { APIActionRowComponent, APIButtonComponent, Message, PartialUser, User } from 'discord.js' import type { APIActionRowComponent, APIButtonComponent, Message, PartialUser, User } from 'discord.js'
@@ -17,7 +17,7 @@ export const getResponseFromText = async (
type ResponseConfig = Awaited<ReturnType<typeof getResponseFromText>> type ResponseConfig = Awaited<ReturnType<typeof getResponseFromText>>
let responseConfig: Omit<ResponseConfig, 'triggers'> & { triggers?: ResponseConfig['triggers'] } = { let responseConfig: Omit<ResponseConfig, 'triggers'> & { triggers?: ResponseConfig['triggers'] } = {
triggers: undefined, triggers: undefined,
response: null, response: null!,
} }
const firstLabelIndexes: number[] = [] const firstLabelIndexes: number[] = []
@@ -143,15 +143,22 @@ export const handleUserResponseCorrection = async (
{ api, database: db, config: { messageScan: msConfig }, logger }: typeof import('$/context'), { api, database: db, config: { messageScan: msConfig }, logger }: typeof import('$/context'),
response: Response, response: Response,
reply: Message, reply: Message,
label: string,
user: User | PartialUser, user: User | PartialUser,
label?: string,
) => { ) => {
if (!label) {
await Promise.all([reply.delete(), api.client.trainMessage(response.content, label)]).finally(() =>
logger.debug(`User ${user.id} trained message ${response.replyId} as out of scope`),
)
return
}
const correctLabelResponse = msConfig!.responses!.find(r => const correctLabelResponse = msConfig!.responses!.find(r =>
r.triggers.text!.some(t => 'label' in t && t.label === label), r.triggers.text!.some(t => 'label' in t && t.label === label),
) )
if (!correctLabelResponse) throw new Error('Cannot find label config for the selected label') if (!correctLabelResponse) throw new Error('Cannot find label config for the selected label')
if (!correctLabelResponse.response) return void (await reply.delete())
if (response.label !== label) { if (response.label !== label) {
db.update(responses) db.update(responses)
@@ -168,12 +175,12 @@ export const handleUserResponseCorrection = async (
})) }))
} }
await api.client.trainMessage(response.content, label) await Promise.all([
logger.debug(`User ${user.id} trained message ${response.replyId} as ${label} (positive)`) api.client.trainMessage(response.content, label),
reply.edit({
await reply.edit({
components: [], components: [],
}) }),
]).finally(() => logger.debug(`User ${user.id} trained message ${response.replyId} as ${label}`))
} }
export const createMessageScanResponseComponents = (reply: Message<true>) => [ export const createMessageScanResponseComponents = (reply: Message<true>) => [

View File

@@ -1,5 +1,5 @@
import { config, logger } from '$/context'
import decancer from 'decancer' import decancer from 'decancer'
import { config, logger } from '$/context'
import { applyReferenceToModerationActionEmbed, createModerationActionEmbed } from './embeds' import { applyReferenceToModerationActionEmbed, createModerationActionEmbed } from './embeds'
import type { CommandInteraction, EmbedBuilder, Guild, GuildMember, Message, User } from 'discord.js' import type { CommandInteraction, EmbedBuilder, Guild, GuildMember, Message, User } from 'discord.js'

View File

@@ -1,6 +1,6 @@
import { and, eq } from 'drizzle-orm'
import { config, database } from '$/context' import { config, database } from '$/context'
import { appliedPresets } from '$/database/schemas' import { appliedPresets } from '$/database/schemas'
import { and, eq } from 'drizzle-orm'
import type { GuildMember } from 'discord.js' import type { GuildMember } from 'discord.js'
// TODO: Fix this type // TODO: Fix this type

840
bun.lock

File diff suppressed because it is too large Load Diff

View File

@@ -33,8 +33,8 @@
], ],
"packageManager": "bun@1.2.17", "packageManager": "bun@1.2.17",
"devDependencies": { "devDependencies": {
"@anolilab/multi-semantic-release": "^2.0.0", "@anolilab/multi-semantic-release": "^2.0.3",
"@biomejs/biome": "^2.0.5", "@biomejs/biome": "^2.2.4",
"@codedependant/semantic-release-docker": "^5.1.1", "@codedependant/semantic-release-docker": "^5.1.1",
"@commitlint/cli": "^19.8.1", "@commitlint/cli": "^19.8.1",
"@commitlint/config-conventional": "^19.8.1", "@commitlint/config-conventional": "^19.8.1",
@@ -43,13 +43,13 @@
"@semantic-release/exec": "^7.1.0", "@semantic-release/exec": "^7.1.0",
"@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.2.17", "@types/bun": "^1.2.21",
"conventional-changelog-conventionalcommits": "^9.0.0", "conventional-changelog-conventionalcommits": "^9.1.0",
"lefthook": "^1.11.14", "lefthook": "^1.13.0",
"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.2.5", "semantic-release": "^24.2.8",
"turbo": "^2.5.4", "turbo": "^2.5.6",
"typescript": "^5.8.3" "typescript": "^5.9.2"
}, },
"trustedDependencies": [ "trustedDependencies": [
"@biomejs/biome", "@biomejs/biome",
@@ -58,9 +58,6 @@
"lefthook" "lefthook"
], ],
"patchedDependencies": { "patchedDependencies": {
"@semantic-release/npm@12.0.1": "patches/@semantic-release%2Fnpm@12.0.1.patch", "@semantic-release/npm@12.0.2": "patches/@semantic-release%2Fnpm@12.0.2.patch"
"drizzle-kit@0.22.8": "patches/drizzle-kit@0.22.8.patch",
"decancer@3.2.4": "patches/decancer@3.2.4.patch",
"discord.js@14.18.0": "patches/discord.js@14.18.0.patch"
} }
} }

View File

@@ -28,7 +28,7 @@
"homepage": "https://github.com/revanced/revanced-bots#readme", "homepage": "https://github.com/revanced/revanced-bots#readme",
"dependencies": { "dependencies": {
"@revanced/bot-shared": "workspace:*", "@revanced/bot-shared": "workspace:*",
"ws": "^8.18.2" "ws": "^8.18.3"
}, },
"devDependencies": { "devDependencies": {
"@types/ws": "^8.18.1", "@types/ws": "^8.18.1",

View File

@@ -101,7 +101,7 @@ export default class Client {
return packet return packet
} }
async trainMessage(text: string, label: string) { async trainMessage(text: string, label?: string) {
this.#throwIfNotReady() this.#throwIfNotReady()
this.ws.send({ this.ws.send({

View File

@@ -31,7 +31,7 @@
"homepage": "https://github.com/revanced/revanced-bots#readme", "homepage": "https://github.com/revanced/revanced-bots#readme",
"dependencies": { "dependencies": {
"bson": "^6.10.4", "bson": "^6.10.4",
"chalk": "^5.4.1", "chalk": "^5.6.2",
"tracer": "^1.3.0", "tracer": "^1.3.0",
"valibot": "^1.1.0" "valibot": "^1.1.0"
} }

View File

@@ -1,15 +1,12 @@
import { import {
type AnySchema,
array, array,
type BooleanSchema,
boolean, boolean,
custom, custom,
enum_, enum_,
type InferOutput, type InferOutput,
type NullSchema,
null_, null_,
type ObjectSchema,
object, object,
optional,
parse, parse,
pipe, pipe,
string, string,
@@ -75,13 +72,9 @@ export const PacketDataSchemas = {
}), }),
[ClientOperation.TrainMessage]: object({ [ClientOperation.TrainMessage]: object({
text: string(), text: string(),
label: string(), label: optional(string()),
}), }),
} as const satisfies Record< } as const
Operation,
// biome-ignore lint/suspicious/noExplicitAny: This is a schema, it's not possible to type it
ObjectSchema<any, any> | AnySchema | NullSchema<any> | BooleanSchema<any>
>
export type Packet<TOp extends Operation = Operation> = TOp extends ServerOperation export type Packet<TOp extends Operation = Operation> = TOp extends ServerOperation
? PacketWithSequenceNumber<TOp> ? PacketWithSequenceNumber<TOp>

View File

@@ -1,12 +1,3 @@
diff --git a/node_modules/@semantic-release/npm/.bun-tag-3853154e196b7721 b/.bun-tag-3853154e196b7721
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/node_modules/@semantic-release/npm/.bun-tag-550461f23a8ec245 b/.bun-tag-550461f23a8ec245
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/node_modules/@semantic-release/npm/.bun-tag-c9c8130945517add b/.bun-tag-c9c8130945517add
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/lib/prepare.js b/lib/prepare.js diff --git a/lib/prepare.js b/lib/prepare.js
index 3e76bec44cf595a1b4141728336bed904d4d518d..4b25ca64879bbee2a600f2b23b738c86136ad9c6 100644 index 3e76bec44cf595a1b4141728336bed904d4d518d..4b25ca64879bbee2a600f2b23b738c86136ad9c6 100644
--- a/lib/prepare.js --- a/lib/prepare.js

View File

@@ -1,13 +0,0 @@
diff --git a/src/lib.js b/src/lib.js
index de45d7dbe82975b09eff3742d0718accae2107fc..0575daa03dfabdd5c96928458ff4270cb8f7188a 100644
--- a/src/lib.js
+++ b/src/lib.js
@@ -42,7 +42,7 @@ function isMusl() {
}
function getBinding(name) {
- const path = join(__dirname, '..', `decancer.${name}.node`)
+ const path = join(import.meta.dir, '..', `decancer.${name}.node`)
return require(existsSync(path) ? path : `@vierofernando/decancer-${name}`)
}

View File

@@ -1,17 +0,0 @@
# Make Message#reply work with { flags: MessageFlags.Ephemeral } in typings
# So our Command system doesn't break
diff --git a/typings/index.d.mts b/typings/index.d.mts
index 645b870..fa93158 100644
--- a/typings/index.d.mts
+++ b/typings/index.d.mts
@@ -6764,8 +6764,8 @@ export interface MessageCreateOptions extends BaseMessageOptionsWithPoll {
stickers?: readonly StickerResolvable[];
flags?:
| BitFieldResolvable<
- Extract<MessageFlagsString, 'SuppressEmbeds' | 'SuppressNotifications'>,
- MessageFlags.SuppressEmbeds | MessageFlags.SuppressNotifications
+ Extract<MessageFlagsString, 'SuppressEmbeds' | 'SuppressNotifications' | 'Ephemeral'>,
+ MessageFlags.SuppressEmbeds | MessageFlags.SuppressNotifications | MessageFlags.Ephemeral
>
| undefined;
}

View File

@@ -1,21 +0,0 @@
diff --git a/bin.cjs b/bin.cjs
index 142ed9c20f28dc1080bebfb52325fa308c6cb771..9d3bea0787f6c05df11567c6821bc85743286340 100644
--- a/bin.cjs
+++ b/bin.cjs
@@ -22053,7 +22053,7 @@ var init_sqliteImports = __esm({
const { unregister } = await safeRegister();
for (let i2 = 0; i2 < imports.length; i2++) {
const it = imports[i2];
- const i0 = require(`${it}`);
+ const i0 = await import(`${it}`);
const prepared = prepareFromExports3(i0);
tables.push(...prepared.tables);
}
@@ -129572,6 +129572,7 @@ var generateCommand = new Command("generate").option("--dialect <dialect>", "Dat
} else {
assertUnreachable(dialect7);
}
+ process.exit(0);
});
var migrateCommand = new Command("migrate").option(
"--config <config>",