mirror of
https://github.com/ReVanced/revanced-bots.git
synced 2026-01-12 06:06:21 +00:00
Compare commits
6 Commits
@revanced/
...
@revanced/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5db076aee5 | ||
|
|
12f5aaf70f | ||
|
|
94d0dcc32b | ||
|
|
4834685186 | ||
|
|
ffe0a3ddf5 | ||
|
|
89d8ab1ee5 |
@@ -1,3 +1,10 @@
|
|||||||
|
# @revanced/bot-websocket-api [1.0.0-dev.3](https://github.com/revanced/revanced-helper/compare/@revanced/bot-websocket-api@1.0.0-dev.2...@revanced/bot-websocket-api@1.0.0-dev.3) (2024-07-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **apis/websocket:** build and runtime issues ([89d8ab1](https://github.com/revanced/revanced-helper/commit/89d8ab1ee58278a9a96cdc31c679d0a0a0d865af))
|
||||||
|
|
||||||
# @revanced/bot-websocket-api [1.0.0-dev.2](https://github.com/revanced/revanced-helper/compare/@revanced/bot-websocket-api@1.0.0-dev.1...@revanced/bot-websocket-api@1.0.0-dev.2) (2024-07-22)
|
# @revanced/bot-websocket-api [1.0.0-dev.2](https://github.com/revanced/revanced-helper/compare/@revanced/bot-websocket-api@1.0.0-dev.1...@revanced/bot-websocket-api@1.0.0-dev.2) (2024-07-22)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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.2",
|
"version": "1.0.0-dev.3",
|
||||||
"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": {
|
||||||
|
|||||||
@@ -1,29 +1,33 @@
|
|||||||
import { createLogger } from '@revanced/bot-shared'
|
import { createLogger } from '@revanced/bot-shared'
|
||||||
import { cp, rm } from 'fs/promises'
|
import { cp, rm } from 'fs/promises'
|
||||||
|
|
||||||
async function build(): Promise<void> {
|
const logger = createLogger()
|
||||||
const logger = createLogger()
|
|
||||||
|
|
||||||
logger.info('Cleaning previous build...')
|
logger.info('Cleaning previous build...')
|
||||||
await rm('./dist', { recursive: true })
|
await rm('./dist', { recursive: true })
|
||||||
|
|
||||||
logger.info('Building Tesseract.js worker...')
|
logger.info('Building WebSocket API...')
|
||||||
await Bun.build({
|
await Bun.build({
|
||||||
entrypoints: ['../../node_modules/tesseract.js/src/worker-script/node/index.js'],
|
entrypoints: ['./src/index.ts'],
|
||||||
target: 'bun',
|
outdir: './dist',
|
||||||
outdir: './dist/worker',
|
target: 'bun',
|
||||||
})
|
minify: true,
|
||||||
|
sourcemap: 'external',
|
||||||
|
})
|
||||||
|
|
||||||
logger.info('Copying Tesseract.js WASM...')
|
logger.info('Building Tesseract.js worker...')
|
||||||
await cp('../../node_modules/tesseract.js-core', './dist/worker/core', { recursive: true })
|
await Bun.build({
|
||||||
|
entrypoints: ['../../node_modules/tesseract.js/src/worker-script/node/index.js'],
|
||||||
|
target: 'bun',
|
||||||
|
outdir: './dist/worker',
|
||||||
|
minify: true,
|
||||||
|
sourcemap: 'external',
|
||||||
|
})
|
||||||
|
|
||||||
logger.info('Building WebSocket API...')
|
// Tesseract.js is really bad for minification
|
||||||
await Bun.build({
|
// It forcefully requires this core module to be present which contains the WASM files
|
||||||
entrypoints: ['./src/index.ts'],
|
logger.info('Copying Tesseract.js Core...')
|
||||||
outdir: './dist',
|
await cp('../../node_modules/tesseract.js-core', './dist/node_modules/tesseract.js-core', { recursive: true })
|
||||||
target: 'bun',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
await build()
|
logger.info('Copying config...')
|
||||||
await cp('config.json', 'dist/config.json')
|
await cp('config.json', 'dist/config.json')
|
||||||
|
|||||||
@@ -55,12 +55,9 @@ export interface WitMessageResponse {
|
|||||||
|
|
||||||
const TesseractWorkerDirPath = joinPath(import.meta.dir, 'worker')
|
const TesseractWorkerDirPath = joinPath(import.meta.dir, 'worker')
|
||||||
const TesseractWorkerPath = joinPath(TesseractWorkerDirPath, 'index.js')
|
const TesseractWorkerPath = joinPath(TesseractWorkerDirPath, 'index.js')
|
||||||
const TesseractCorePath = joinPath(TesseractWorkerDirPath, 'core')
|
|
||||||
|
|
||||||
export const tesseract = await createTesseractWorker(
|
export const tesseract = await createTesseractWorker(
|
||||||
'eng',
|
'eng',
|
||||||
OEM.DEFAULT,
|
OEM.DEFAULT,
|
||||||
(await pathExists(TesseractWorkerDirPath))
|
(await pathExists(TesseractWorkerDirPath)) ? { workerPath: TesseractWorkerPath } : undefined,
|
||||||
? { workerPath: TesseractWorkerPath, corePath: TesseractCorePath }
|
|
||||||
: undefined,
|
|
||||||
)
|
)
|
||||||
|
|||||||
1
bots/discord/.gitignore
vendored
1
bots/discord/.gitignore
vendored
@@ -181,6 +181,7 @@ config.ts
|
|||||||
*.db
|
*.db
|
||||||
*.sqlite
|
*.sqlite
|
||||||
*.sqlite3
|
*.sqlite3
|
||||||
|
.drizzle
|
||||||
|
|
||||||
# Auto-generated files
|
# Auto-generated files
|
||||||
src/commands/index.ts
|
src/commands/index.ts
|
||||||
|
|||||||
@@ -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", "run", "index.js" ]
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import type { Config } from './config.schema'
|
// @ts-check
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {import('./config.schema').Config}
|
||||||
|
*/
|
||||||
export default {
|
export default {
|
||||||
owners: ['USER_ID_HERE'],
|
owners: ['USER_ID_HERE'],
|
||||||
guilds: ['GUILD_ID_HERE'],
|
guilds: ['GUILD_ID_HERE'],
|
||||||
@@ -70,4 +73,4 @@ export default {
|
|||||||
disconnectLimit: 3,
|
disconnectLimit: 3,
|
||||||
disconnectRetryInterval: 10000,
|
disconnectRetryInterval: 10000,
|
||||||
},
|
},
|
||||||
} satisfies Config as Config
|
}
|
||||||
@@ -29,9 +29,8 @@ The distribution files will be placed inside the `dist` directory. Inside will i
|
|||||||
|
|
||||||
To deploy the bot, you'll need to:
|
To deploy the bot, you'll need to:
|
||||||
|
|
||||||
1. Replace the `config.ts` file with your own configuration _(optional)_
|
1. [Build the bot as seen in the previous step](#-building)
|
||||||
2. [Build the bot as seen in the previous step](#-building)
|
2. Run the `reload-slash-commands` script
|
||||||
3. Run the `reload-slash-commands` script
|
|
||||||
This is to ensure all commands are registered, so they can be used.
|
This is to ensure all commands are registered, so they can be used.
|
||||||
**It may take up to 2 hours until **global** commands are updated. This is a Discord limitation.**
|
**It may take up to 2 hours until **global** commands are updated. This is a Discord limitation.**
|
||||||
|
|
||||||
@@ -40,7 +39,7 @@ To deploy the bot, you'll need to:
|
|||||||
bun run scripts/reload-slash-commands.ts
|
bun run scripts/reload-slash-commands.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Copy contents of the `dist` directory
|
3. Copy contents of the `dist` directory
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# For instance, we'll copy them both to /usr/src/discord-bot
|
# For instance, we'll copy them both to /usr/src/discord-bot
|
||||||
@@ -48,22 +47,14 @@ To deploy the bot, you'll need to:
|
|||||||
cp -R ./dist/* /usr/src/discord-bot
|
cp -R ./dist/* /usr/src/discord-bot
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Copy the empty database (or use your own existing database)
|
4. Configure environment variables
|
||||||
|
|
||||||
```sh
|
|
||||||
# By default, the build script creates the database called "db.sqlite3"
|
|
||||||
# Unless you specify otherwise via the "DATABASE_PATH" environment variable
|
|
||||||
cp ./db.sqlite3 /usr/src/discord-bot
|
|
||||||
```
|
|
||||||
|
|
||||||
6. Configure environment variables
|
|
||||||
As seen in [`.env.example`](../.env.example). You can also optionally use a `.env` file which **Bun will automatically load**.
|
As seen in [`.env.example`](../.env.example). You can also optionally use a `.env` file which **Bun will automatically load**.
|
||||||
|
|
||||||
7. Finally, run the bot
|
5. Finally, run the bot
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd /usr/src/discord-bot
|
cd /usr/src/discord-bot
|
||||||
bun run src/index.js
|
bun run index.js
|
||||||
```
|
```
|
||||||
|
|
||||||
## ⏭️ What's next
|
## ⏭️ What's next
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { defineConfig } from 'drizzle-kit'
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
dialect: 'sqlite',
|
dialect: 'sqlite',
|
||||||
schema: './src/database/schemas.ts',
|
schema: './src/database/schemas.ts',
|
||||||
|
out: './.drizzle',
|
||||||
dbCredentials: {
|
dbCredentials: {
|
||||||
url: process.env['DATABASE_PATH'] ? `file:./${process.env['DATABASE_PATH']}` : 'file:./db.sqlite3',
|
url: process.env['DATABASE_PATH'] ? `file:./${process.env['DATABASE_PATH']}` : 'file:./db.sqlite3',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,10 +9,9 @@
|
|||||||
"register": "bun run scripts/reload-slash-commands.ts",
|
"register": "bun run scripts/reload-slash-commands.ts",
|
||||||
"start": "bun prepare && bun run src/index.ts",
|
"start": "bun prepare && bun run src/index.ts",
|
||||||
"dev": "bun prepare && bun --watch src/index.ts",
|
"dev": "bun prepare && bun --watch src/index.ts",
|
||||||
"build:config": "bun build config.ts --outdir=dist",
|
"build": "bun prepare && bun run scripts/build.ts",
|
||||||
"build": "bun prepare && bun build:config && bun build src/index.ts -e ./config.js --target=bun --outdir=dist/src",
|
|
||||||
"watch": "bun dev",
|
"watch": "bun dev",
|
||||||
"prepare": "bun run scripts/generate-indexes.ts && drizzle-kit push"
|
"prepare": "bun run scripts/generate-indexes.ts && drizzle-kit generate --name=schema"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
24
bots/discord/scripts/build.ts
Normal file
24
bots/discord/scripts/build.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { createLogger } from '@revanced/bot-shared'
|
||||||
|
import { cp, rm } from 'fs/promises'
|
||||||
|
|
||||||
|
const logger = createLogger()
|
||||||
|
|
||||||
|
logger.warn('Cleaning previous build...')
|
||||||
|
await rm('./dist', { recursive: true })
|
||||||
|
await rm('./.drizzle', { recursive: true })
|
||||||
|
|
||||||
|
logger.info('Building bot...')
|
||||||
|
await Bun.build({
|
||||||
|
entrypoints: ['./src/index.ts'],
|
||||||
|
outdir: './dist',
|
||||||
|
target: 'bun',
|
||||||
|
external: ['./config.js'],
|
||||||
|
minify: true,
|
||||||
|
sourcemap: 'external',
|
||||||
|
})
|
||||||
|
|
||||||
|
logger.info('Copying config...')
|
||||||
|
await cp('config.js', 'dist/config.js')
|
||||||
|
|
||||||
|
logger.info('Copying database schema...')
|
||||||
|
await cp('.drizzle', 'dist/.drizzle', { recursive: true })
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
import { Database } from 'bun:sqlite'
|
import { Database } from 'bun:sqlite'
|
||||||
|
import { existsSync, readFileSync, readdirSync } from 'fs'
|
||||||
|
import { join } from 'path'
|
||||||
import { Client as APIClient } from '@revanced/bot-api'
|
import { Client as APIClient } from '@revanced/bot-api'
|
||||||
import { createLogger } from '@revanced/bot-shared'
|
import { createLogger } from '@revanced/bot-shared'
|
||||||
import { ActivityType, Client as DiscordClient, Partials } from 'discord.js'
|
import { ActivityType, Client as DiscordClient, Partials } from 'discord.js'
|
||||||
@@ -29,7 +31,33 @@ export const api = {
|
|||||||
disconnectCount: 0,
|
disconnectCount: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
const db = new Database(process.env['DATABASE_PATH'])
|
const DatabasePath = process.env['DATABASE_PATH']
|
||||||
|
const DatabaseSchemaDir = join(import.meta.dir, '.drizzle')
|
||||||
|
|
||||||
|
let dbSchemaFileName: string | undefined
|
||||||
|
|
||||||
|
if (DatabasePath && !existsSync(DatabasePath)) {
|
||||||
|
logger.warn('Database file not found, trying to create from schema...')
|
||||||
|
|
||||||
|
try {
|
||||||
|
const file = readdirSync(DatabaseSchemaDir, { withFileTypes: true })
|
||||||
|
.filter(file => file.isFile() && file.name.endsWith('.sql'))
|
||||||
|
.sort()
|
||||||
|
.at(-1)
|
||||||
|
|
||||||
|
if (!file) throw new Error('No schema file found')
|
||||||
|
|
||||||
|
dbSchemaFileName = file.name
|
||||||
|
logger.debug(`Using schema file: ${dbSchemaFileName}`)
|
||||||
|
} catch (e) {
|
||||||
|
logger.fatal('Could not create database from schema, check if the schema file exists and is accessible')
|
||||||
|
logger.fatal(e)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = new Database(DatabasePath)
|
||||||
|
if (dbSchemaFileName) db.run(readFileSync(join(DatabaseSchemaDir, dbSchemaFileName)).toString())
|
||||||
|
|
||||||
export const database = drizzle(db, {
|
export const database = drizzle(db, {
|
||||||
schema: schemas,
|
schema: schemas,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"composite": false,
|
"composite": false,
|
||||||
"exactOptionalPropertyTypes": false,
|
"exactOptionalPropertyTypes": false,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
"allowJs": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"$/*": ["./src/*"],
|
"$/*": ["./src/*"],
|
||||||
"$constants": ["./src/constants"],
|
"$constants": ["./src/constants"],
|
||||||
|
|||||||
@@ -41,11 +41,11 @@
|
|||||||
"@tsconfig/strictest": "^2.0.5",
|
"@tsconfig/strictest": "^2.0.5",
|
||||||
"@types/bun": "^1.1.6",
|
"@types/bun": "^1.1.6",
|
||||||
"conventional-changelog-conventionalcommits": "^7.0.2",
|
"conventional-changelog-conventionalcommits": "^7.0.2",
|
||||||
"lefthook": "^1.7.4",
|
"lefthook": "^1.7.5",
|
||||||
"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.0.0",
|
"semantic-release": "^24.0.0",
|
||||||
"turbo": "^2.0.9",
|
"turbo": "^2.0.9",
|
||||||
"typescript": "^5.5.3"
|
"typescript": "^5.5.4"
|
||||||
},
|
},
|
||||||
"trustedDependencies": [
|
"trustedDependencies": [
|
||||||
"@biomejs/biome",
|
"@biomejs/biome",
|
||||||
|
|||||||
@@ -53,23 +53,34 @@ export class ClientWebSocketManager {
|
|||||||
}
|
}
|
||||||
}, this.timeout)
|
}, this.timeout)
|
||||||
|
|
||||||
this.#socket.on('open', () => {
|
const errorBeforeReadyHandler = (err: Error) => {
|
||||||
this.disconnected = false
|
cleanup()
|
||||||
clearTimeout(timeout)
|
|
||||||
this.#listen()
|
|
||||||
rs()
|
|
||||||
})
|
|
||||||
|
|
||||||
this.#socket.on('error', err => {
|
|
||||||
clearTimeout(timeout)
|
|
||||||
throw err
|
throw err
|
||||||
})
|
}
|
||||||
|
|
||||||
this.#socket.on('close', (code, reason) => {
|
const closeBeforeReadyHandler = (code: number, reason: Buffer) => {
|
||||||
clearTimeout(timeout)
|
clearTimeout(timeout)
|
||||||
this._handleDisconnect(code, reason.toString())
|
this._handleDisconnect(code, reason.toString())
|
||||||
throw new Error('WebSocket connection closed before ready')
|
throw new Error('WebSocket connection closed before ready')
|
||||||
})
|
}
|
||||||
|
|
||||||
|
const readyHandler = () => {
|
||||||
|
this.disconnected = false
|
||||||
|
cleanup()
|
||||||
|
this.#listen()
|
||||||
|
rs()
|
||||||
|
}
|
||||||
|
|
||||||
|
const cleanup = () => {
|
||||||
|
this.#socket.off('open', readyHandler)
|
||||||
|
this.#socket.off('close', closeBeforeReadyHandler)
|
||||||
|
this.#socket.off('error', errorBeforeReadyHandler)
|
||||||
|
clearTimeout(timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#socket.on('open', readyHandler)
|
||||||
|
this.#socket.on('error', errorBeforeReadyHandler)
|
||||||
|
this.#socket.on('close', closeBeforeReadyHandler)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
rj(e)
|
rj(e)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user