mirror of
https://github.com/ReVanced/revanced-bots.git
synced 2026-01-11 21:56:17 +00:00
Compare commits
10 Commits
@revanced/
...
@revanced/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc02c0a775 | ||
|
|
c83e219088 | ||
|
|
6164e6c1a5 | ||
|
|
47d2f8c015 | ||
|
|
c68cfd1c01 | ||
|
|
2b1928e116 | ||
|
|
670cc70057 | ||
|
|
439f301872 | ||
|
|
aeccf12906 | ||
|
|
b4ac8433f4 |
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@@ -20,11 +20,6 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
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
|
||||
uses: actions/cache@v4
|
||||
|
||||
@@ -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.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)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@revanced/bot-websocket-api",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"version": "1.0.2",
|
||||
"version": "1.1.0",
|
||||
"description": "🧦 WebSocket API server for bots assisting ReVanced",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
@@ -31,7 +31,7 @@
|
||||
"@sapphire/async-queue": "^1.5.5",
|
||||
"chalk": "^5.4.1",
|
||||
"tesseract.js": "^6.0.1",
|
||||
"ws": "^8.18.2"
|
||||
"ws": "^8.18.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ws": "^8.18.1",
|
||||
|
||||
@@ -23,12 +23,12 @@ export const wit = {
|
||||
|
||||
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) {
|
||||
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', {
|
||||
body: JSON.stringify([
|
||||
{
|
||||
@@ -41,7 +41,14 @@ export const wit = {
|
||||
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 {
|
||||
text: string
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { ClientOperation, Logger } from '@revanced/bot-shared'
|
||||
import type { Worker as TesseractWorker } from 'tesseract.js'
|
||||
import type { ClientPacketObject } from '../classes/Client'
|
||||
import type { WitMessageResponse } from '../context'
|
||||
import type { Wit } from '../context'
|
||||
import type { Config } from '../utils/config'
|
||||
|
||||
export { default as parseImageEventHandler } from './parseImage'
|
||||
@@ -14,10 +14,7 @@ export type EventHandler<POp extends ClientOperation> = (
|
||||
) => void | Promise<void>
|
||||
|
||||
export type EventContext = {
|
||||
wit: {
|
||||
train(text: string, label: string): Promise<void>
|
||||
message(text: string): Promise<WitMessageResponse>
|
||||
}
|
||||
wit: Wit
|
||||
tesseract: TesseractWorker
|
||||
logger: Logger
|
||||
config: Config
|
||||
|
||||
@@ -10,7 +10,7 @@ const trainMessageEventHandler: EventHandler<ClientOperation.TrainMessage> = asy
|
||||
const nextSeq = client.currentSequence++
|
||||
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 {
|
||||
await wit.train(actualText, label)
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
# @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)
|
||||
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ export default {
|
||||
},
|
||||
},
|
||||
humanCorrections: {
|
||||
falsePositiveLabel: 'false_positive',
|
||||
allow: {
|
||||
members: {
|
||||
permissions: 8n,
|
||||
|
||||
@@ -36,7 +36,6 @@ export type Config = {
|
||||
blacklist?: Filter
|
||||
}
|
||||
humanCorrections: {
|
||||
falsePositiveLabel: string
|
||||
allow?: {
|
||||
users?: string[]
|
||||
members?: {
|
||||
@@ -72,7 +71,7 @@ export type ConfigMessageScanResponse = {
|
||||
image?: Array<RegExp>
|
||||
}
|
||||
filterOverride?: NonNullable<Config['messageScan']>['filter']
|
||||
response: ConfigMessageScanResponseMessage | null
|
||||
response: ConfigMessageScanResponseMessage
|
||||
respondToReply?: boolean
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@revanced/discord-bot",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"version": "1.2.2",
|
||||
"version": "1.3.0",
|
||||
"description": "🤖 Discord bot assisting ReVanced",
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
@@ -35,12 +35,12 @@
|
||||
"@sapphire/duration": "^1.2.0",
|
||||
"chalk": "^5.4.1",
|
||||
"decancer": "^3.3.2",
|
||||
"discord.js": "^14.20.0",
|
||||
"discord.js": "^14.21.0",
|
||||
"drizzle-orm": "^0.44.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@libsql/client": "^0.15.9",
|
||||
"discord-api-types": "^0.38.13",
|
||||
"drizzle-kit": "^0.31.2"
|
||||
"discord-api-types": "^0.38.15",
|
||||
"drizzle-kit": "^0.31.4"
|
||||
}
|
||||
}
|
||||
@@ -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 { unlinkSync, writeFileSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
import { inspect } from 'util'
|
||||
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({
|
||||
name: 'eval',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ApplicationCommandOptionType } from 'discord.js'
|
||||
import { AdminCommand } from '$/classes/Command'
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { ApplicationCommandOptionType } from 'discord.js'
|
||||
|
||||
export default new AdminCommand({
|
||||
name: 'exception-test',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AdminCommand } from '$/classes/Command'
|
||||
import { type CommandInteraction, MessageFlags } from 'discord.js'
|
||||
import { AdminCommand } from '$/classes/Command'
|
||||
|
||||
export default new AdminCommand({
|
||||
name: 'reload',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ApplicationCommandOptionType, Routes } from 'discord.js'
|
||||
import { AdminCommand } from '$/classes/Command'
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { createSuccessEmbed } from '$/utils/discord/embeds'
|
||||
import { ApplicationCommandOptionType, Routes } from 'discord.js'
|
||||
|
||||
const SubcommandOptions = {
|
||||
where: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AdminCommand } from '$/classes/Command'
|
||||
import { MessageFlags } from 'discord.js'
|
||||
import { AdminCommand } from '$/classes/Command'
|
||||
|
||||
export default new AdminCommand({
|
||||
name: 'stop',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EmbedBuilder, MessageFlags } from 'discord.js'
|
||||
import Command from '$/classes/Command'
|
||||
import { applyCommonEmbedStyles } from '$/utils/discord/embeds'
|
||||
import { EmbedBuilder, MessageFlags } from 'discord.js'
|
||||
|
||||
export default new Command({
|
||||
name: 'coinflip',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { ApplicationCommandOptionType, Message, MessageFlags } from 'discord.js'
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { ModerationCommand } from '../../classes/Command'
|
||||
|
||||
export default new ModerationCommand({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { MessageFlags } from 'discord.js'
|
||||
import { ModerationCommand } from '$/classes/Command'
|
||||
import { createSuccessEmbed } from '$/utils/discord/embeds'
|
||||
import { cureNickname } from '$/utils/discord/moderation'
|
||||
import { MessageFlags } from 'discord.js'
|
||||
|
||||
export default new ModerationCommand({
|
||||
name: 'cure',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { EmbedBuilder } from 'discord.js'
|
||||
import { ModerationCommand } from '$/classes/Command'
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { applyCommonEmbedStyles } from '$/utils/discord/embeds'
|
||||
import { EmbedBuilder } from 'discord.js'
|
||||
|
||||
export default new ModerationCommand({
|
||||
name: 'purge',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ChannelType } from 'discord.js'
|
||||
import { ModerationCommand } from '$/classes/Command'
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { createSuccessEmbed } from '$/utils/discord/embeds'
|
||||
import { durationToString, parseDuration } from '$/utils/duration'
|
||||
import { ChannelType } from 'discord.js'
|
||||
|
||||
export default new ModerationCommand({
|
||||
name: 'slowmode',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { ModerationCommand } from '$/classes/Command'
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { appliedPresets } from '$/database/schemas'
|
||||
import { createModerationActionEmbed } from '$/utils/discord/embeds'
|
||||
import { sendModerationReplyAndLogs } from '$/utils/discord/moderation'
|
||||
import { removeRolePreset } from '$/utils/discord/rolePresets'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
|
||||
export default new ModerationCommand({
|
||||
name: 'unmute',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type FetchMessageOptions, MessageFlags, type MessageResolvable } from 'discord.js'
|
||||
import Command from '$/classes/Command'
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { createSuccessEmbed } from '$/utils/discord/embeds'
|
||||
import { type FetchMessageOptions, MessageFlags, type MessageResolvable } from 'discord.js'
|
||||
import { config } from '../../../context'
|
||||
import type { ConfigMessageScanResponseLabelConfig } from 'config.schema'
|
||||
|
||||
@@ -9,7 +9,7 @@ const msRcConfig = config.messageScan?.humanCorrections?.allow
|
||||
|
||||
export default new Command({
|
||||
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,
|
||||
requirements: {
|
||||
users: msRcConfig?.users,
|
||||
@@ -26,9 +26,9 @@ export default new Command({
|
||||
required: true,
|
||||
},
|
||||
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,
|
||||
required: true,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
allowMessageCommand: true,
|
||||
@@ -49,7 +49,7 @@ export default new Command({
|
||||
'This command can only be used in or on text channels',
|
||||
)
|
||||
|
||||
if (!labels.includes(label))
|
||||
if (label && !labels.includes(label))
|
||||
throw new CommandError(
|
||||
CommandErrorType.InvalidArgument,
|
||||
`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.')
|
||||
|
||||
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 trigger.reply({
|
||||
embeds: [
|
||||
createSuccessEmbed(
|
||||
'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,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type APIStringSelectComponent, ComponentType, MessageFlags } from 'discord.js'
|
||||
import Command from '$/classes/Command'
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { type APIStringSelectComponent, ComponentType, MessageFlags } from 'discord.js'
|
||||
import { config } from '../../../context'
|
||||
import type { ConfigMessageScanResponseLabelConfig } from 'config.schema'
|
||||
|
||||
@@ -37,7 +37,10 @@ export default new Command({
|
||||
components: [
|
||||
{
|
||||
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: '', emoji: { name: '❌' } },
|
||||
],
|
||||
type: ComponentType.StringSelect,
|
||||
} satisfies APIStringSelectComponent,
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { on, withContext } from '$utils/api/events'
|
||||
import { DisconnectReason, HumanizedDisconnectReason } from '@revanced/bot-shared'
|
||||
import { on, withContext } from '$utils/api/events'
|
||||
|
||||
withContext(on, 'disconnect', ({ api, config, logger }, reason, msg) => {
|
||||
if (reason === DisconnectReason.PlannedDisconnect && api.intentionallyDisconnecting) return
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { and, eq, gt } from 'drizzle-orm'
|
||||
import { appliedPresets } from '$/database/schemas'
|
||||
import { on, withContext } from '$/utils/discord/events'
|
||||
import { applyRolesUsingPreset } from '$/utils/discord/rolePresets'
|
||||
import { and, eq, gt } from 'drizzle-orm'
|
||||
|
||||
withContext(on, 'guildMemberAdd', async ({ database }, member) => {
|
||||
const applieds = await database.query.appliedPresets.findMany({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { MessageFlags } from 'discord.js'
|
||||
import CommandError from '$/classes/CommandError'
|
||||
import { createStackTraceEmbed } from '$utils/discord/embeds'
|
||||
import { on, withContext } from '$utils/discord/events'
|
||||
import { MessageFlags } from 'discord.js'
|
||||
|
||||
withContext(on, 'interactionCreate', async (context, interaction) => {
|
||||
if (!interaction.isChatInputCommand()) return
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { MessageFlags } from 'discord.js'
|
||||
import CommandError from '$/classes/CommandError'
|
||||
import { createStackTraceEmbed } from '$utils/discord/embeds'
|
||||
import { on, withContext } from '$utils/discord/events'
|
||||
import { MessageFlags } from 'discord.js'
|
||||
|
||||
withContext(on, 'interactionCreate', async (context, interaction) => {
|
||||
if (!interaction.isContextMenuCommand()) return
|
||||
|
||||
@@ -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 {
|
||||
type ButtonInteraction,
|
||||
MessageFlags,
|
||||
@@ -9,6 +5,10 @@ import {
|
||||
type TextBasedChannel,
|
||||
} from 'discord.js'
|
||||
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
|
||||
withContext(on, 'interactionCreate', async (context, interaction) => {
|
||||
@@ -58,8 +58,8 @@ withContext(on, 'interactionCreate', async (context, interaction) => {
|
||||
|
||||
const editMessage = (content: string, description?: string) =>
|
||||
editInteractionMessage(interaction, msg.url, content, description)
|
||||
const handleCorrection = (label: string) =>
|
||||
handleUserResponseCorrection(context, response, msg, label, interaction.user)
|
||||
const handleCorrection = (label?: string) =>
|
||||
handleUserResponseCorrection(context, response, msg, interaction.user, label)
|
||||
|
||||
if (response.correctedById)
|
||||
return await editMessage(
|
||||
@@ -82,7 +82,7 @@ withContext(on, 'interactionCreate', async (context, interaction) => {
|
||||
await editMessage('Canceled', 'You canceled this interaction. 😞')
|
||||
break
|
||||
case 'delete':
|
||||
await handleCorrection(msConfig.humanCorrections.falsePositiveLabel)
|
||||
await handleCorrection()
|
||||
await editMessage(
|
||||
'Marked as false positive',
|
||||
'The response has been deleted and marked as a false positive. Thank you for your feedback. 🎉',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { MessageFlags, type TextBasedChannel } from 'discord.js'
|
||||
import { createErrorEmbed, createStackTraceEmbed, createSuccessEmbed } from '$utils/discord/embeds'
|
||||
import { on, withContext } from '$utils/discord/events'
|
||||
import { MessageFlags, type TextBasedChannel } from 'discord.js'
|
||||
|
||||
withContext(on, 'interactionCreate', async (context, interaction) => {
|
||||
const {
|
||||
@@ -30,7 +30,8 @@ withContext(on, 'interactionCreate', async (context, interaction) => {
|
||||
flags: MessageFlags.Ephemeral,
|
||||
}))
|
||||
|
||||
const selectedLabel = interaction.values[0]!
|
||||
// If selectedLabel is empty, it means "out of scope", so we pass undefined
|
||||
const selectedLabel = interaction.values[0] || undefined
|
||||
await context.api.client.trainMessage(msg.content, selectedLabel)
|
||||
await interaction.reply({
|
||||
embeds: [
|
||||
|
||||
@@ -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 {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
@@ -12,6 +6,12 @@ import {
|
||||
StringSelectMenuOptionBuilder,
|
||||
} from 'discord.js'
|
||||
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'
|
||||
|
||||
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}`)
|
||||
|
||||
const handleCorrection = (label: string) =>
|
||||
handleUserResponseCorrection(context, response, reactionMessage, label, user)
|
||||
const handleCorrection = (label?: string) =>
|
||||
handleUserResponseCorrection(context, response, reactionMessage, user, label)
|
||||
|
||||
try {
|
||||
if (reaction.emoji.name === Reactions.train) {
|
||||
@@ -106,7 +106,7 @@ withContext(on, 'messageReactionAdd', async (context, rct, user) => {
|
||||
.setCustomId(`${componentPrefix}_cancel`),
|
||||
new ButtonBuilder()
|
||||
.setEmoji(Reactions.delete)
|
||||
.setLabel('Delete (mark as false positive)')
|
||||
.setLabel('Delete (mark as out of scope)')
|
||||
.setStyle(ButtonStyle.Danger)
|
||||
.setCustomId(`${componentPrefix}_delete`),
|
||||
),
|
||||
@@ -117,8 +117,8 @@ withContext(on, 'messageReactionAdd', async (context, rct, user) => {
|
||||
components: rows,
|
||||
})
|
||||
} else if (reaction.emoji.name === Reactions.delete) {
|
||||
await handleCorrection(msConfig.humanCorrections.falsePositiveLabel)
|
||||
await user.send({ content: 'The response has been deleted and marked as a false positive.' })
|
||||
await handleCorrection()
|
||||
await user.send({ content: 'The response has been deleted and marked as out of scope.' })
|
||||
}
|
||||
} catch (e) {
|
||||
logger.error('Failed to correct response:', e)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { type Client, DiscordAPIError } from 'discord.js'
|
||||
import { and, eq, lt } from 'drizzle-orm'
|
||||
import { database, logger } from '$/context'
|
||||
import { appliedPresets } from '$/database/schemas'
|
||||
import { on, withContext } from '$/utils/discord/events'
|
||||
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) => {
|
||||
if (config.rolePresets) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { api, discord, logger } from '$/context'
|
||||
import { getMissingEnvironmentVariables } from '@revanced/bot-shared'
|
||||
import { api, discord, logger } from '$/context'
|
||||
|
||||
import './events/register'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { DefaultEmbedColor, ReVancedLogoURL } from '$/constants'
|
||||
import { type APIEmbed, EmbedBuilder, type EmbedField, type JSONEncodable, type User } from 'discord.js'
|
||||
import { DefaultEmbedColor, ReVancedLogoURL } from '$/constants'
|
||||
import type { ConfigMessageScanResponseMessage } from '../../../config.schema'
|
||||
|
||||
export const createErrorEmbed = (title: string | null, description?: string) =>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type Response, responses } from '$/database/schemas'
|
||||
import { ButtonStyle, ComponentType } from 'discord.js'
|
||||
import { eq } from 'drizzle-orm'
|
||||
import { type Response, responses } from '$/database/schemas'
|
||||
import { createMessageScanResponseEmbed } from './embeds'
|
||||
import type { Config, ConfigMessageScanResponse, ConfigMessageScanResponseLabelConfig } from 'config.schema'
|
||||
import type { APIActionRowComponent, APIButtonComponent, Message, PartialUser, User } from 'discord.js'
|
||||
@@ -17,7 +17,7 @@ export const getResponseFromText = async (
|
||||
type ResponseConfig = Awaited<ReturnType<typeof getResponseFromText>>
|
||||
let responseConfig: Omit<ResponseConfig, 'triggers'> & { triggers?: ResponseConfig['triggers'] } = {
|
||||
triggers: undefined,
|
||||
response: null,
|
||||
response: null!,
|
||||
}
|
||||
|
||||
const firstLabelIndexes: number[] = []
|
||||
@@ -143,15 +143,22 @@ export const handleUserResponseCorrection = async (
|
||||
{ api, database: db, config: { messageScan: msConfig }, logger }: typeof import('$/context'),
|
||||
response: Response,
|
||||
reply: Message,
|
||||
label: string,
|
||||
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 =>
|
||||
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.response) return void (await reply.delete())
|
||||
|
||||
if (response.label !== label) {
|
||||
db.update(responses)
|
||||
@@ -168,12 +175,12 @@ export const handleUserResponseCorrection = async (
|
||||
}))
|
||||
}
|
||||
|
||||
await api.client.trainMessage(response.content, label)
|
||||
logger.debug(`User ${user.id} trained message ${response.replyId} as ${label} (positive)`)
|
||||
|
||||
await reply.edit({
|
||||
components: [],
|
||||
})
|
||||
await Promise.all([
|
||||
api.client.trainMessage(response.content, label),
|
||||
reply.edit({
|
||||
components: [],
|
||||
}),
|
||||
]).finally(() => logger.debug(`User ${user.id} trained message ${response.replyId} as ${label}`))
|
||||
}
|
||||
|
||||
export const createMessageScanResponseComponents = (reply: Message<true>) => [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { config, logger } from '$/context'
|
||||
import decancer from 'decancer'
|
||||
import { config, logger } from '$/context'
|
||||
import { applyReferenceToModerationActionEmbed, createModerationActionEmbed } from './embeds'
|
||||
import type { CommandInteraction, EmbedBuilder, Guild, GuildMember, Message, User } from 'discord.js'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { config, database } from '$/context'
|
||||
import { appliedPresets } from '$/database/schemas'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import type { GuildMember } from 'discord.js'
|
||||
|
||||
// TODO: Fix this type
|
||||
|
||||
17
package.json
17
package.json
@@ -33,8 +33,8 @@
|
||||
],
|
||||
"packageManager": "bun@1.2.17",
|
||||
"devDependencies": {
|
||||
"@anolilab/multi-semantic-release": "^2.0.0",
|
||||
"@biomejs/biome": "^2.0.5",
|
||||
"@anolilab/multi-semantic-release": "^2.0.2",
|
||||
"@biomejs/biome": "^2.1.1",
|
||||
"@codedependant/semantic-release-docker": "^5.1.1",
|
||||
"@commitlint/cli": "^19.8.1",
|
||||
"@commitlint/config-conventional": "^19.8.1",
|
||||
@@ -43,11 +43,11 @@
|
||||
"@semantic-release/exec": "^7.1.0",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"@tsconfig/strictest": "^2.0.5",
|
||||
"@types/bun": "^1.2.17",
|
||||
"conventional-changelog-conventionalcommits": "^9.0.0",
|
||||
"lefthook": "^1.11.14",
|
||||
"@types/bun": "^1.2.18",
|
||||
"conventional-changelog-conventionalcommits": "^9.1.0",
|
||||
"lefthook": "^1.12.2",
|
||||
"portainer-service-webhook": "https://github.com/newarifrh/portainer-service-webhook#v1",
|
||||
"semantic-release": "^24.2.5",
|
||||
"semantic-release": "^24.2.6",
|
||||
"turbo": "^2.5.4",
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
@@ -58,9 +58,6 @@
|
||||
"lefthook"
|
||||
],
|
||||
"patchedDependencies": {
|
||||
"@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",
|
||||
"decancer@3.2.4": "patches/decancer@3.2.4.patch",
|
||||
"discord.js@14.18.0": "patches/discord.js@14.18.0.patch"
|
||||
"@semantic-release/npm@12.0.2": "patches/@semantic-release%2Fnpm@12.0.2.patch"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"homepage": "https://github.com/revanced/revanced-bots#readme",
|
||||
"dependencies": {
|
||||
"@revanced/bot-shared": "workspace:*",
|
||||
"ws": "^8.18.2"
|
||||
"ws": "^8.18.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ws": "^8.18.1",
|
||||
|
||||
@@ -101,7 +101,7 @@ export default class Client {
|
||||
return packet
|
||||
}
|
||||
|
||||
async trainMessage(text: string, label: string) {
|
||||
async trainMessage(text: string, label?: string) {
|
||||
this.#throwIfNotReady()
|
||||
|
||||
this.ws.send({
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import {
|
||||
type AnySchema,
|
||||
array,
|
||||
type BooleanSchema,
|
||||
boolean,
|
||||
custom,
|
||||
enum_,
|
||||
type InferOutput,
|
||||
type NullSchema,
|
||||
null_,
|
||||
type ObjectSchema,
|
||||
object,
|
||||
optional,
|
||||
parse,
|
||||
pipe,
|
||||
string,
|
||||
@@ -75,13 +72,9 @@ export const PacketDataSchemas = {
|
||||
}),
|
||||
[ClientOperation.TrainMessage]: object({
|
||||
text: string(),
|
||||
label: string(),
|
||||
label: optional(string()),
|
||||
}),
|
||||
} as const satisfies Record<
|
||||
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>
|
||||
>
|
||||
} as const
|
||||
|
||||
export type Packet<TOp extends Operation = Operation> = TOp extends ServerOperation
|
||||
? PacketWithSequenceNumber<TOp>
|
||||
|
||||
@@ -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
|
||||
index 3e76bec44cf595a1b4141728336bed904d4d518d..4b25ca64879bbee2a600f2b23b738c86136ad9c6 100644
|
||||
--- a/lib/prepare.js
|
||||
@@ -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}`)
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>",
|
||||
Reference in New Issue
Block a user