diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 4fbe2e74..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "env": { - "es6": true, - "node": true - }, - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "tsconfig.json", - "sourceType": "module" - }, - "plugins": [ - "simple-import-sort", - "unused-imports" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:@stylistic/disable-legacy" - ], - "root": true, - "rules": { - // TypeScript Specific Rules - "@typescript-eslint/ban-ts-comment": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-namespace": "off", - "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], - - // General JavaScript Rules - "comma-dangle": ["error", "always-multiline"], - "no-unused-expressions": "error", - "no-undef": "off", - "no-unused-vars": "off", - "unused-imports/no-unused-imports": "error", - "simple-import-sort/imports": "error", - - // Formatting and Stylistic Rules - "brace-style": ["error", "stroustrup", { "allowSingleLine": true }], - "comma-spacing": ["error", { "before": false, "after": true }], - "comma-style": ["error", "last"], - "curly": ["error", "multi-line", "consistent"], - "dot-location": ["error", "property"], - "indent": ["error", "tab", { "SwitchCase": 1 }], - "max-nested-callbacks": ["error", { "max": 4 }], - "max-statements-per-line": ["error", { "max": 2 }], - "no-case-declarations": "off", - "no-empty-function": ["error", { "allow": ["constructors"] }], - "no-floating-decimal": "error", - "no-inner-declarations": "off", - "no-lonely-if": "error", - "no-multi-spaces": "error", - "no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 0, "maxBOF": 0 }], - "no-trailing-spaces": "error", - "no-var": "error", - "object-curly-spacing": ["error", "always"], - "prefer-const": "error", - "quotes": ["error", "double", { "avoidEscape": true, "allowTemplateLiterals": true }], - "semi": ["error", "always"], - "space-before-blocks": "error", - "space-before-function-paren": ["error", { - "anonymous": "never", - "named": "never", - "asyncArrow": "always" - }], - "space-infix-ops": "error", - "space-unary-ops": "error", - "spaced-comment": ["error", "always", { - "line": { - "markers": ["/"], - "exceptions": ["-", "+"] - }, - "block": { - "balanced": true - } - }], - "yoda": ["error", "never"] - }, - "overrides": [ - { - "files": ["src/**/*.ts"] - } - ] -} diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d70d9e2c..aa64d4d8 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -17,3 +17,12 @@ updates: update-types: - minor - patch + + - package-ecosystem: npm + directory: / + schedule: + interval: daily + open-pull-requests-limit: 0 + labels: + - dependencies + - npm diff --git a/.github/workflows/provision-and-deploy.yml b/.github/workflows/provision-and-deploy.yml index 74c3a2d2..37e61302 100644 --- a/.github/workflows/provision-and-deploy.yml +++ b/.github/workflows/provision-and-deploy.yml @@ -23,6 +23,7 @@ jobs: - run: npm run lint:check - run: npm run typecheck - run: npm run test + - run: npm audit --audit-level=critical gate: needs: ci diff --git a/Dockerfile b/Dockerfile index 04f8226e..cf30ee87 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,16 @@ -# ---- Base ---- -FROM node:24-alpine AS base +# syntax=docker/dockerfile:1.7 +# ---- deps (install + prebuild verification) ---- +FROM node:24-alpine AS deps WORKDIR /app +COPY package.json package-lock.json ./ +RUN --mount=type=cache,target=/root/.npm \ + npm ci --omit=dev --prefer-offline --no-audit --no-fund \ + && node -e "require('better-sqlite3'); require.resolve('@swc-node/register'); require.resolve('@swc/core'); console.log('native + loader prebuild OK')" -# Copy package.json and package-lock.json -COPY package*.json ./ - -# ---- Dependencies ---- -FROM base AS dependencies - -# Install npm dependencies -RUN npm ci - -# ---- Production ---- -FROM dependencies AS production - -# Copy all source files +# ---- runtime ---- +FROM node:24-alpine AS runtime +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules COPY . . - -# Default command to start the application -ENTRYPOINT ["npm", "start"] \ No newline at end of file +ENTRYPOINT ["npm", "start"] diff --git a/README.md b/README.md index f246b6eb..b1c46b2d 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Restricted to users with the **Administrator** permission and users added via `/ `/whitelist` - manage whitelisted users and roles (`scope`: `queue` / `event` / `global`) `/clear` - remove all members from queue(s) `/displays` - manage display channels -`/events` - manage recurring events with auto-managed queues (and optional auto-created per-room channels) +`/events` - manage recurring events with auto-managed queues (optional per-room channels, optional sub auto-pull at room start, optional auto-revoked winner roles) `/logging` - manage logging channels `/members` - manage queue members `/move` - change the position of a queue member diff --git a/data/migrations/0012_powerful_songbird.sql b/data/migrations/0012_powerful_songbird.sql new file mode 100644 index 00000000..32f15b6f --- /dev/null +++ b/data/migrations/0012_powerful_songbird.sql @@ -0,0 +1,13 @@ +CREATE TABLE `event_occurrence_room_pull` ( + `occurrence_id` integer NOT NULL, + `event_queue_id` integer NOT NULL, + `handled_at` integer NOT NULL, + PRIMARY KEY(`occurrence_id`, `event_queue_id`), + FOREIGN KEY (`occurrence_id`) REFERENCES `event_occurrence`(`id`) ON UPDATE no action ON DELETE cascade, + FOREIGN KEY (`event_queue_id`) REFERENCES `event_queue`(`id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE INDEX `event_occurrence_room_pull_occurrence_id_index` ON `event_occurrence_room_pull` (`occurrence_id`);--> statement-breakpoint +ALTER TABLE `event` ADD `auto_pull_subs_at_room_start_toggle` integer DEFAULT false NOT NULL;--> statement-breakpoint +ALTER TABLE `event` ADD `shuffle_subs_before_auto_pull_toggle` integer DEFAULT false NOT NULL;--> statement-breakpoint +ALTER TABLE `event` ADD `sub_auto_pull_mode` text DEFAULT 'drain' NOT NULL; \ No newline at end of file diff --git a/data/migrations/0013_mature_steve_rogers.sql b/data/migrations/0013_mature_steve_rogers.sql new file mode 100644 index 00000000..501416b9 --- /dev/null +++ b/data/migrations/0013_mature_steve_rogers.sql @@ -0,0 +1,16 @@ +CREATE TABLE `event_winner` ( + `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, + `guild_id` text NOT NULL, + `event_id` integer NOT NULL, + `room_index` integer NOT NULL, + `user_id` text NOT NULL, + `role_id` text NOT NULL, + `declared_at` integer NOT NULL, + FOREIGN KEY (`guild_id`) REFERENCES `guild`(`guild_id`) ON UPDATE no action ON DELETE cascade, + FOREIGN KEY (`event_id`) REFERENCES `event`(`id`) ON UPDATE no action ON DELETE cascade +); +--> statement-breakpoint +CREATE INDEX `event_winner_guild_id_index` ON `event_winner` (`guild_id`);--> statement-breakpoint +CREATE INDEX `event_winner_event_id_index` ON `event_winner` (`event_id`);--> statement-breakpoint +CREATE UNIQUE INDEX `event_winner_event_id_room_index_user_id_unique` ON `event_winner` (`event_id`,`room_index`,`user_id`);--> statement-breakpoint +ALTER TABLE `event` ADD `winner_role_id` text; \ No newline at end of file diff --git a/data/migrations/meta/0012_snapshot.json b/data/migrations/meta/0012_snapshot.json new file mode 100644 index 00000000..8dca5bed --- /dev/null +++ b/data/migrations/meta/0012_snapshot.json @@ -0,0 +1,2932 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "f4e7efbc-16ea-411f-a9ec-7026c388ba38", + "prevId": "2c55b919-92ec-42c5-b7f7-aa0547dc7da9", + "tables": { + "admin": { + "name": "admin", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "admin_guild_id_index": { + "name": "admin_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "admin_guild_id_subject_id_unique": { + "name": "admin_guild_id_subject_id_unique", + "columns": [ + "guild_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "admin_guild_id_guild_guild_id_fk": { + "name": "admin_guild_id_guild_guild_id_fk", + "tableFrom": "admin", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "archived_member": { + "name": "archived_member", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "position_time": { + "name": "position_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "join_time": { + "name": "join_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "archived_time": { + "name": "archived_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "archived_member_queue_id_user_id_unique": { + "name": "archived_member_queue_id_user_id_unique", + "columns": [ + "queue_id", + "user_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "blacklisted": { + "name": "blacklisted", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "blacklisted_guild_id_index": { + "name": "blacklisted_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "blacklisted_queue_id_subject_id_unique": { + "name": "blacklisted_queue_id_subject_id_unique", + "columns": [ + "queue_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "blacklisted_guild_id_guild_guild_id_fk": { + "name": "blacklisted_guild_id_guild_guild_id_fk", + "tableFrom": "blacklisted", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "blacklisted_queue_id_queue_id_fk": { + "name": "blacklisted_queue_id_queue_id_fk", + "tableFrom": "blacklisted", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "display": { + "name": "display", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "display_channel_id": { + "name": "display_channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_message_id": { + "name": "last_message_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "display_guild_id_index": { + "name": "display_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "display_queue_id_display_channel_id_unique": { + "name": "display_queue_id_display_channel_id_unique", + "columns": [ + "queue_id", + "display_channel_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "display_guild_id_guild_guild_id_fk": { + "name": "display_guild_id_guild_guild_id_fk", + "tableFrom": "display", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "display_queue_id_queue_id_fk": { + "name": "display_queue_id_queue_id_fk", + "tableFrom": "display", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_blacklisted": { + "name": "event_blacklisted", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_blacklisted_guild_id_index": { + "name": "event_blacklisted_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_blacklisted_event_id_index": { + "name": "event_blacklisted_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_blacklisted_event_id_subject_id_unique": { + "name": "event_blacklisted_event_id_subject_id_unique", + "columns": [ + "event_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_blacklisted_guild_id_guild_guild_id_fk": { + "name": "event_blacklisted_guild_id_guild_guild_id_fk", + "tableFrom": "event_blacklisted", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_blacklisted_event_id_event_id_fk": { + "name": "event_blacklisted_event_id_event_id_fk", + "tableFrom": "event_blacklisted", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_default": { + "name": "event_default", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_role": { + "name": "queue_role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "autopull_toggle": { + "name": "autopull_toggle", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "badge_toggle": { + "name": "badge_toggle", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "display_update_type": { + "name": "display_update_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "dm_on_pull_toggle": { + "name": "dm_on_pull_toggle", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "buttons_toggles": { + "name": "buttons_toggles", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "header": { + "name": "header", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "inline_toggle": { + "name": "inline_toggle", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "lock_toggle": { + "name": "lock_toggle", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "member_display_type": { + "name": "member_display_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pull_batch_size": { + "name": "pull_batch_size", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pull_message": { + "name": "pull_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pull_message_display_type": { + "name": "pull_message_display_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pull_message_channel_id": { + "name": "pull_message_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "rejoin_cooldown_period": { + "name": "rejoin_cooldown_period", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "rejoin_grace_period": { + "name": "rejoin_grace_period", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "require_message_to_join": { + "name": "require_message_to_join", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_in_queue_id": { + "name": "role_in_queue_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_on_pull_id": { + "name": "role_on_pull_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "time_display_type": { + "name": "time_display_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "voice_destination_channel_id": { + "name": "voice_destination_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "voice_only_toggle": { + "name": "voice_only_toggle", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_default_guild_id_index": { + "name": "event_default_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_default_event_id_queue_role_unique": { + "name": "event_default_event_id_queue_role_unique", + "columns": [ + "event_id", + "queue_role" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_default_guild_id_guild_guild_id_fk": { + "name": "event_default_guild_id_guild_guild_id_fk", + "tableFrom": "event_default", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_default_event_id_event_id_fk": { + "name": "event_default_event_id_event_id_fk", + "tableFrom": "event_default", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_occurrence_room_ping": { + "name": "event_occurrence_room_ping", + "columns": { + "occurrence_id": { + "name": "occurrence_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_queue_id": { + "name": "event_queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "handled_at": { + "name": "handled_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "event_occurrence_room_ping_occurrence_id_index": { + "name": "event_occurrence_room_ping_occurrence_id_index", + "columns": [ + "occurrence_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "event_occurrence_room_ping_occurrence_id_event_occurrence_id_fk": { + "name": "event_occurrence_room_ping_occurrence_id_event_occurrence_id_fk", + "tableFrom": "event_occurrence_room_ping", + "tableTo": "event_occurrence", + "columnsFrom": [ + "occurrence_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_occurrence_room_ping_event_queue_id_event_queue_id_fk": { + "name": "event_occurrence_room_ping_event_queue_id_event_queue_id_fk", + "tableFrom": "event_occurrence_room_ping", + "tableTo": "event_queue", + "columnsFrom": [ + "event_queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "event_occurrence_room_ping_occurrence_id_event_queue_id_pk": { + "columns": [ + "occurrence_id", + "event_queue_id" + ], + "name": "event_occurrence_room_ping_occurrence_id_event_queue_id_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_occurrence_room_pull": { + "name": "event_occurrence_room_pull", + "columns": { + "occurrence_id": { + "name": "occurrence_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_queue_id": { + "name": "event_queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "handled_at": { + "name": "handled_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "event_occurrence_room_pull_occurrence_id_index": { + "name": "event_occurrence_room_pull_occurrence_id_index", + "columns": [ + "occurrence_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "event_occurrence_room_pull_occurrence_id_event_occurrence_id_fk": { + "name": "event_occurrence_room_pull_occurrence_id_event_occurrence_id_fk", + "tableFrom": "event_occurrence_room_pull", + "tableTo": "event_occurrence", + "columnsFrom": [ + "occurrence_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_occurrence_room_pull_event_queue_id_event_queue_id_fk": { + "name": "event_occurrence_room_pull_event_queue_id_event_queue_id_fk", + "tableFrom": "event_occurrence_room_pull", + "tableTo": "event_queue", + "columnsFrom": [ + "event_queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "event_occurrence_room_pull_occurrence_id_event_queue_id_pk": { + "columns": [ + "occurrence_id", + "event_queue_id" + ], + "name": "event_occurrence_room_pull_occurrence_id_event_queue_id_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_occurrence": { + "name": "event_occurrence", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "start_time": { + "name": "start_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "open_handled_at": { + "name": "open_handled_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "lock_handled_at": { + "name": "lock_handled_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "discord_event_id": { + "name": "discord_event_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_occurrence_guild_id_index": { + "name": "event_occurrence_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_occurrence_event_id_index": { + "name": "event_occurrence_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_occurrence_event_id_start_time_unique": { + "name": "event_occurrence_event_id_start_time_unique", + "columns": [ + "event_id", + "start_time" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_occurrence_guild_id_guild_guild_id_fk": { + "name": "event_occurrence_guild_id_guild_guild_id_fk", + "tableFrom": "event_occurrence", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_occurrence_event_id_event_id_fk": { + "name": "event_occurrence_event_id_event_id_fk", + "tableFrom": "event_occurrence", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_prioritized": { + "name": "event_prioritized", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "priority_order": { + "name": "priority_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 5 + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_prioritized_guild_id_index": { + "name": "event_prioritized_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_prioritized_event_id_index": { + "name": "event_prioritized_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_prioritized_event_id_subject_id_unique": { + "name": "event_prioritized_event_id_subject_id_unique", + "columns": [ + "event_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_prioritized_guild_id_guild_guild_id_fk": { + "name": "event_prioritized_guild_id_guild_guild_id_fk", + "tableFrom": "event_prioritized", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_prioritized_event_id_event_id_fk": { + "name": "event_prioritized_event_id_event_id_fk", + "tableFrom": "event_prioritized", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_queue": { + "name": "event_queue", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_role": { + "name": "queue_role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_index": { + "name": "queue_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "ping_channel_id": { + "name": "ping_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "auto_created_role_id": { + "name": "auto_created_role_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_queue_guild_id_index": { + "name": "event_queue_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_queue_event_id_index": { + "name": "event_queue_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_queue_event_id_queue_role_queue_index_unique": { + "name": "event_queue_event_id_queue_role_queue_index_unique", + "columns": [ + "event_id", + "queue_role", + "queue_index" + ], + "isUnique": true + }, + "event_queue_queue_id_unique": { + "name": "event_queue_queue_id_unique", + "columns": [ + "queue_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_queue_guild_id_guild_guild_id_fk": { + "name": "event_queue_guild_id_guild_guild_id_fk", + "tableFrom": "event_queue", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_queue_event_id_event_id_fk": { + "name": "event_queue_event_id_event_id_fk", + "tableFrom": "event_queue", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_queue_queue_id_queue_id_fk": { + "name": "event_queue_queue_id_queue_id_fk", + "tableFrom": "event_queue", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_room_channel": { + "name": "event_room_channel", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "room_index": { + "name": "room_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "suffix": { + "name": "suffix", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "event_room_channel_guild_id_index": { + "name": "event_room_channel_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_room_channel_event_id_index": { + "name": "event_room_channel_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_room_channel_event_id_room_index_suffix_unique": { + "name": "event_room_channel_event_id_room_index_suffix_unique", + "columns": [ + "event_id", + "room_index", + "suffix" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_room_channel_guild_id_guild_guild_id_fk": { + "name": "event_room_channel_guild_id_guild_guild_id_fk", + "tableFrom": "event_room_channel", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_room_channel_event_id_event_id_fk": { + "name": "event_room_channel_event_id_event_id_fk", + "tableFrom": "event_room_channel", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_room_channel_template": { + "name": "event_room_channel_template", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "suffix": { + "name": "suffix", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slowmode_seconds": { + "name": "slowmode_seconds", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_room_channel_template_guild_id_index": { + "name": "event_room_channel_template_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_room_channel_template_event_id_index": { + "name": "event_room_channel_template_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_room_channel_template_event_id_suffix_unique": { + "name": "event_room_channel_template_event_id_suffix_unique", + "columns": [ + "event_id", + "suffix" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_room_channel_template_guild_id_guild_guild_id_fk": { + "name": "event_room_channel_template_guild_id_guild_guild_id_fk", + "tableFrom": "event_room_channel_template", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_room_channel_template_event_id_event_id_fk": { + "name": "event_room_channel_template_event_id_event_id_fk", + "tableFrom": "event_room_channel_template", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event": { + "name": "event", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "room_count": { + "name": "room_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "room_queues_channel_id": { + "name": "room_queues_channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sub_queues_channel_id": { + "name": "sub_queues_channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "room_length_ms": { + "name": "room_length_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "room_scheduling": { + "name": "room_scheduling", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'parallel'" + }, + "create_offset_ms": { + "name": "create_offset_ms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 86400000 + }, + "lock_offset_ms": { + "name": "lock_offset_ms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "cleanup_offset_ms": { + "name": "cleanup_offset_ms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 3600000 + }, + "announcement_channel_id": { + "name": "announcement_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "announcement_message": { + "name": "announcement_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "room_ping_message": { + "name": "room_ping_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "max_rooms_per_user": { + "name": "max_rooms_per_user", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "max_subs_per_user": { + "name": "max_subs_per_user", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "parent_sub_mutually_exclusive": { + "name": "parent_sub_mutually_exclusive", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "room_category_id": { + "name": "room_category_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_in_room_queue": { + "name": "role_in_room_queue", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "role_on_room_pull": { + "name": "role_on_room_pull", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "role_in_sub_queue": { + "name": "role_in_sub_queue", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "role_on_sub_pull": { + "name": "role_on_sub_pull", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "auto_pull_subs_at_room_start_toggle": { + "name": "auto_pull_subs_at_room_start_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "shuffle_subs_before_auto_pull_toggle": { + "name": "shuffle_subs_before_auto_pull_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "sub_auto_pull_mode": { + "name": "sub_auto_pull_mode", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'drain'" + }, + "create_discord_event": { + "name": "create_discord_event", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "discord_event_description": { + "name": "discord_event_description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_guild_id_index": { + "name": "event_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_name_guild_id_unique": { + "name": "event_name_guild_id_unique", + "columns": [ + "name", + "guild_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_guild_id_guild_guild_id_fk": { + "name": "event_guild_id_guild_guild_id_fk", + "tableFrom": "event", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_whitelisted": { + "name": "event_whitelisted", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_whitelisted_guild_id_index": { + "name": "event_whitelisted_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_whitelisted_event_id_index": { + "name": "event_whitelisted_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_whitelisted_event_id_subject_id_unique": { + "name": "event_whitelisted_event_id_subject_id_unique", + "columns": [ + "event_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_whitelisted_guild_id_guild_guild_id_fk": { + "name": "event_whitelisted_guild_id_guild_guild_id_fk", + "tableFrom": "event_whitelisted", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_whitelisted_event_id_event_id_fk": { + "name": "event_whitelisted_event_id_event_id_fk", + "tableFrom": "event_whitelisted", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "guild_blacklisted": { + "name": "guild_blacklisted", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "guild_blacklisted_guild_id_index": { + "name": "guild_blacklisted_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "guild_blacklisted_guild_id_subject_id_unique": { + "name": "guild_blacklisted_guild_id_subject_id_unique", + "columns": [ + "guild_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "guild_blacklisted_guild_id_guild_guild_id_fk": { + "name": "guild_blacklisted_guild_id_guild_guild_id_fk", + "tableFrom": "guild_blacklisted", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "guild_prioritized": { + "name": "guild_prioritized", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "priority_order": { + "name": "priority_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 5 + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "guild_prioritized_guild_id_index": { + "name": "guild_prioritized_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "guild_prioritized_guild_id_subject_id_unique": { + "name": "guild_prioritized_guild_id_subject_id_unique", + "columns": [ + "guild_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "guild_prioritized_guild_id_guild_guild_id_fk": { + "name": "guild_prioritized_guild_id_guild_guild_id_fk", + "tableFrom": "guild_prioritized", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "guild": { + "name": "guild", + "columns": { + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "log_channel_id": { + "name": "log_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "log_scope": { + "name": "log_scope", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "joinTime": { + "name": "joinTime", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_updated_time": { + "name": "last_updated_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "messages_received": { + "name": "messages_received", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "commands_received": { + "name": "commands_received", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "buttons_received": { + "name": "buttons_received", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "queues_added": { + "name": "queues_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "voices_added": { + "name": "voices_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "displays_added": { + "name": "displays_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "members_added": { + "name": "members_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "schedules_added": { + "name": "schedules_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "whitelisted_added": { + "name": "whitelisted_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "blacklisted_added": { + "name": "blacklisted_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "prioritized_added": { + "name": "prioritized_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "admins_added": { + "name": "admins_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "archived_members_added": { + "name": "archived_members_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "events_added": { + "name": "events_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "guild_whitelisted": { + "name": "guild_whitelisted", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "guild_whitelisted_guild_id_index": { + "name": "guild_whitelisted_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "guild_whitelisted_guild_id_subject_id_unique": { + "name": "guild_whitelisted_guild_id_subject_id_unique", + "columns": [ + "guild_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "guild_whitelisted_guild_id_guild_guild_id_fk": { + "name": "guild_whitelisted_guild_id_guild_guild_id_fk", + "tableFrom": "guild_whitelisted", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "member": { + "name": "member", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "position_time": { + "name": "position_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "join_time": { + "name": "join_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "priority_order": { + "name": "priority_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "member_guild_id_index": { + "name": "member_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "member_priority_order_index": { + "name": "member_priority_order_index", + "columns": [ + "priority_order" + ], + "isUnique": false + }, + "member_position_time_index": { + "name": "member_position_time_index", + "columns": [ + "position_time" + ], + "isUnique": false + }, + "member_queue_id_user_id_unique": { + "name": "member_queue_id_user_id_unique", + "columns": [ + "queue_id", + "user_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "member_guild_id_guild_guild_id_fk": { + "name": "member_guild_id_guild_guild_id_fk", + "tableFrom": "member", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_queue_id_queue_id_fk": { + "name": "member_queue_id_queue_id_fk", + "tableFrom": "member", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "patch_note": { + "name": "patch_note", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "file_name": { + "name": "file_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "prioritized": { + "name": "prioritized", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "priority_order": { + "name": "priority_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 5 + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "prioritized_guild_id_index": { + "name": "prioritized_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "prioritized_queue_id_subject_id_unique": { + "name": "prioritized_queue_id_subject_id_unique", + "columns": [ + "queue_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "prioritized_guild_id_guild_guild_id_fk": { + "name": "prioritized_guild_id_guild_guild_id_fk", + "tableFrom": "prioritized", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "prioritized_queue_id_queue_id_fk": { + "name": "prioritized_queue_id_queue_id_fk", + "tableFrom": "prioritized", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "queue": { + "name": "queue", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "autopull_toggle": { + "name": "autopull_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "badge_toggle": { + "name": "badge_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'Random'" + }, + "display_update_type": { + "name": "display_update_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'edit'" + }, + "dm_on_pull_toggle": { + "name": "dm_on_pull_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "buttons_toggles": { + "name": "buttons_toggles", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'all'" + }, + "header": { + "name": "header", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "inline_toggle": { + "name": "inline_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "lock_toggle": { + "name": "lock_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "member_display_type": { + "name": "member_display_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'mention'" + }, + "pull_batch_size": { + "name": "pull_batch_size", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "pull_message": { + "name": "pull_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pull_message_display_type": { + "name": "pull_message_display_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'private'" + }, + "pull_message_channel_id": { + "name": "pull_message_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "rejoin_cooldown_period": { + "name": "rejoin_cooldown_period", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "rejoin_grace_period": { + "name": "rejoin_grace_period", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "require_message_to_join": { + "name": "require_message_to_join", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "role_in_queue_id": { + "name": "role_in_queue_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_on_pull_id": { + "name": "role_on_pull_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "time_display_type": { + "name": "time_display_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'off'" + }, + "voice_destination_channel_id": { + "name": "voice_destination_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "voice_only_toggle": { + "name": "voice_only_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + } + }, + "indexes": { + "queue_guild_id_index": { + "name": "queue_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "queue_name_guild_id_unique": { + "name": "queue_name_guild_id_unique", + "columns": [ + "name", + "guild_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "queue_guild_id_guild_guild_id_fk": { + "name": "queue_guild_id_guild_guild_id_fk", + "tableFrom": "queue", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "schedule": { + "name": "schedule", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "cron": { + "name": "cron", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'america/chicago'" + }, + "message_channel_id": { + "name": "message_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "schedule_guild_id_index": { + "name": "schedule_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "schedule_queue_id_command_cron_timezone_unique": { + "name": "schedule_queue_id_command_cron_timezone_unique", + "columns": [ + "queue_id", + "command", + "cron", + "timezone" + ], + "isUnique": true + } + }, + "foreignKeys": { + "schedule_guild_id_guild_guild_id_fk": { + "name": "schedule_guild_id_guild_guild_id_fk", + "tableFrom": "schedule", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "schedule_queue_id_queue_id_fk": { + "name": "schedule_queue_id_queue_id_fk", + "tableFrom": "schedule", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "voice": { + "name": "voice", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_channel_id": { + "name": "source_channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "join_sync_toggle": { + "name": "join_sync_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "leave_sync_toggle": { + "name": "leave_sync_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + } + }, + "indexes": { + "voice_guild_id_index": { + "name": "voice_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "voice_queue_id_source_channel_id_unique": { + "name": "voice_queue_id_source_channel_id_unique", + "columns": [ + "queue_id", + "source_channel_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "voice_guild_id_guild_guild_id_fk": { + "name": "voice_guild_id_guild_guild_id_fk", + "tableFrom": "voice", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "voice_queue_id_queue_id_fk": { + "name": "voice_queue_id_queue_id_fk", + "tableFrom": "voice", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "whitelisted": { + "name": "whitelisted", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "whitelisted_guild_id_index": { + "name": "whitelisted_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "whitelisted_queue_id_subject_id_unique": { + "name": "whitelisted_queue_id_subject_id_unique", + "columns": [ + "queue_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "whitelisted_guild_id_guild_guild_id_fk": { + "name": "whitelisted_guild_id_guild_guild_id_fk", + "tableFrom": "whitelisted", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "whitelisted_queue_id_queue_id_fk": { + "name": "whitelisted_queue_id_queue_id_fk", + "tableFrom": "whitelisted", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/data/migrations/meta/0013_snapshot.json b/data/migrations/meta/0013_snapshot.json new file mode 100644 index 00000000..172483a3 --- /dev/null +++ b/data/migrations/meta/0013_snapshot.json @@ -0,0 +1,3049 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "afe1d2ce-4d72-45aa-b4f3-0a5aceeead86", + "prevId": "f4e7efbc-16ea-411f-a9ec-7026c388ba38", + "tables": { + "admin": { + "name": "admin", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "admin_guild_id_index": { + "name": "admin_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "admin_guild_id_subject_id_unique": { + "name": "admin_guild_id_subject_id_unique", + "columns": [ + "guild_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "admin_guild_id_guild_guild_id_fk": { + "name": "admin_guild_id_guild_guild_id_fk", + "tableFrom": "admin", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "archived_member": { + "name": "archived_member", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "position_time": { + "name": "position_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "join_time": { + "name": "join_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "archived_time": { + "name": "archived_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "archived_member_queue_id_user_id_unique": { + "name": "archived_member_queue_id_user_id_unique", + "columns": [ + "queue_id", + "user_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "blacklisted": { + "name": "blacklisted", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "blacklisted_guild_id_index": { + "name": "blacklisted_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "blacklisted_queue_id_subject_id_unique": { + "name": "blacklisted_queue_id_subject_id_unique", + "columns": [ + "queue_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "blacklisted_guild_id_guild_guild_id_fk": { + "name": "blacklisted_guild_id_guild_guild_id_fk", + "tableFrom": "blacklisted", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "blacklisted_queue_id_queue_id_fk": { + "name": "blacklisted_queue_id_queue_id_fk", + "tableFrom": "blacklisted", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "display": { + "name": "display", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "display_channel_id": { + "name": "display_channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_message_id": { + "name": "last_message_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "display_guild_id_index": { + "name": "display_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "display_queue_id_display_channel_id_unique": { + "name": "display_queue_id_display_channel_id_unique", + "columns": [ + "queue_id", + "display_channel_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "display_guild_id_guild_guild_id_fk": { + "name": "display_guild_id_guild_guild_id_fk", + "tableFrom": "display", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "display_queue_id_queue_id_fk": { + "name": "display_queue_id_queue_id_fk", + "tableFrom": "display", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_blacklisted": { + "name": "event_blacklisted", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_blacklisted_guild_id_index": { + "name": "event_blacklisted_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_blacklisted_event_id_index": { + "name": "event_blacklisted_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_blacklisted_event_id_subject_id_unique": { + "name": "event_blacklisted_event_id_subject_id_unique", + "columns": [ + "event_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_blacklisted_guild_id_guild_guild_id_fk": { + "name": "event_blacklisted_guild_id_guild_guild_id_fk", + "tableFrom": "event_blacklisted", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_blacklisted_event_id_event_id_fk": { + "name": "event_blacklisted_event_id_event_id_fk", + "tableFrom": "event_blacklisted", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_default": { + "name": "event_default", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_role": { + "name": "queue_role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "autopull_toggle": { + "name": "autopull_toggle", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "badge_toggle": { + "name": "badge_toggle", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "display_update_type": { + "name": "display_update_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "dm_on_pull_toggle": { + "name": "dm_on_pull_toggle", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "buttons_toggles": { + "name": "buttons_toggles", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "header": { + "name": "header", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "inline_toggle": { + "name": "inline_toggle", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "lock_toggle": { + "name": "lock_toggle", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "member_display_type": { + "name": "member_display_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pull_batch_size": { + "name": "pull_batch_size", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pull_message": { + "name": "pull_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pull_message_display_type": { + "name": "pull_message_display_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pull_message_channel_id": { + "name": "pull_message_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "rejoin_cooldown_period": { + "name": "rejoin_cooldown_period", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "rejoin_grace_period": { + "name": "rejoin_grace_period", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "require_message_to_join": { + "name": "require_message_to_join", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_in_queue_id": { + "name": "role_in_queue_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_on_pull_id": { + "name": "role_on_pull_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "time_display_type": { + "name": "time_display_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "voice_destination_channel_id": { + "name": "voice_destination_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "voice_only_toggle": { + "name": "voice_only_toggle", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_default_guild_id_index": { + "name": "event_default_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_default_event_id_queue_role_unique": { + "name": "event_default_event_id_queue_role_unique", + "columns": [ + "event_id", + "queue_role" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_default_guild_id_guild_guild_id_fk": { + "name": "event_default_guild_id_guild_guild_id_fk", + "tableFrom": "event_default", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_default_event_id_event_id_fk": { + "name": "event_default_event_id_event_id_fk", + "tableFrom": "event_default", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_occurrence_room_ping": { + "name": "event_occurrence_room_ping", + "columns": { + "occurrence_id": { + "name": "occurrence_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_queue_id": { + "name": "event_queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "handled_at": { + "name": "handled_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "event_occurrence_room_ping_occurrence_id_index": { + "name": "event_occurrence_room_ping_occurrence_id_index", + "columns": [ + "occurrence_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "event_occurrence_room_ping_occurrence_id_event_occurrence_id_fk": { + "name": "event_occurrence_room_ping_occurrence_id_event_occurrence_id_fk", + "tableFrom": "event_occurrence_room_ping", + "tableTo": "event_occurrence", + "columnsFrom": [ + "occurrence_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_occurrence_room_ping_event_queue_id_event_queue_id_fk": { + "name": "event_occurrence_room_ping_event_queue_id_event_queue_id_fk", + "tableFrom": "event_occurrence_room_ping", + "tableTo": "event_queue", + "columnsFrom": [ + "event_queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "event_occurrence_room_ping_occurrence_id_event_queue_id_pk": { + "columns": [ + "occurrence_id", + "event_queue_id" + ], + "name": "event_occurrence_room_ping_occurrence_id_event_queue_id_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_occurrence_room_pull": { + "name": "event_occurrence_room_pull", + "columns": { + "occurrence_id": { + "name": "occurrence_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_queue_id": { + "name": "event_queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "handled_at": { + "name": "handled_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "event_occurrence_room_pull_occurrence_id_index": { + "name": "event_occurrence_room_pull_occurrence_id_index", + "columns": [ + "occurrence_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "event_occurrence_room_pull_occurrence_id_event_occurrence_id_fk": { + "name": "event_occurrence_room_pull_occurrence_id_event_occurrence_id_fk", + "tableFrom": "event_occurrence_room_pull", + "tableTo": "event_occurrence", + "columnsFrom": [ + "occurrence_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_occurrence_room_pull_event_queue_id_event_queue_id_fk": { + "name": "event_occurrence_room_pull_event_queue_id_event_queue_id_fk", + "tableFrom": "event_occurrence_room_pull", + "tableTo": "event_queue", + "columnsFrom": [ + "event_queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "event_occurrence_room_pull_occurrence_id_event_queue_id_pk": { + "columns": [ + "occurrence_id", + "event_queue_id" + ], + "name": "event_occurrence_room_pull_occurrence_id_event_queue_id_pk" + } + }, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_occurrence": { + "name": "event_occurrence", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "start_time": { + "name": "start_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "open_handled_at": { + "name": "open_handled_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "lock_handled_at": { + "name": "lock_handled_at", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "discord_event_id": { + "name": "discord_event_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_occurrence_guild_id_index": { + "name": "event_occurrence_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_occurrence_event_id_index": { + "name": "event_occurrence_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_occurrence_event_id_start_time_unique": { + "name": "event_occurrence_event_id_start_time_unique", + "columns": [ + "event_id", + "start_time" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_occurrence_guild_id_guild_guild_id_fk": { + "name": "event_occurrence_guild_id_guild_guild_id_fk", + "tableFrom": "event_occurrence", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_occurrence_event_id_event_id_fk": { + "name": "event_occurrence_event_id_event_id_fk", + "tableFrom": "event_occurrence", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_prioritized": { + "name": "event_prioritized", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "priority_order": { + "name": "priority_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 5 + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_prioritized_guild_id_index": { + "name": "event_prioritized_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_prioritized_event_id_index": { + "name": "event_prioritized_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_prioritized_event_id_subject_id_unique": { + "name": "event_prioritized_event_id_subject_id_unique", + "columns": [ + "event_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_prioritized_guild_id_guild_guild_id_fk": { + "name": "event_prioritized_guild_id_guild_guild_id_fk", + "tableFrom": "event_prioritized", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_prioritized_event_id_event_id_fk": { + "name": "event_prioritized_event_id_event_id_fk", + "tableFrom": "event_prioritized", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_queue": { + "name": "event_queue", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_role": { + "name": "queue_role", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_index": { + "name": "queue_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "ping_channel_id": { + "name": "ping_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "auto_created_role_id": { + "name": "auto_created_role_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_queue_guild_id_index": { + "name": "event_queue_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_queue_event_id_index": { + "name": "event_queue_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_queue_event_id_queue_role_queue_index_unique": { + "name": "event_queue_event_id_queue_role_queue_index_unique", + "columns": [ + "event_id", + "queue_role", + "queue_index" + ], + "isUnique": true + }, + "event_queue_queue_id_unique": { + "name": "event_queue_queue_id_unique", + "columns": [ + "queue_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_queue_guild_id_guild_guild_id_fk": { + "name": "event_queue_guild_id_guild_guild_id_fk", + "tableFrom": "event_queue", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_queue_event_id_event_id_fk": { + "name": "event_queue_event_id_event_id_fk", + "tableFrom": "event_queue", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_queue_queue_id_queue_id_fk": { + "name": "event_queue_queue_id_queue_id_fk", + "tableFrom": "event_queue", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_room_channel": { + "name": "event_room_channel", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "room_index": { + "name": "room_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "suffix": { + "name": "suffix", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "channel_id": { + "name": "channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "event_room_channel_guild_id_index": { + "name": "event_room_channel_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_room_channel_event_id_index": { + "name": "event_room_channel_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_room_channel_event_id_room_index_suffix_unique": { + "name": "event_room_channel_event_id_room_index_suffix_unique", + "columns": [ + "event_id", + "room_index", + "suffix" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_room_channel_guild_id_guild_guild_id_fk": { + "name": "event_room_channel_guild_id_guild_guild_id_fk", + "tableFrom": "event_room_channel", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_room_channel_event_id_event_id_fk": { + "name": "event_room_channel_event_id_event_id_fk", + "tableFrom": "event_room_channel", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_room_channel_template": { + "name": "event_room_channel_template", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "suffix": { + "name": "suffix", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "slowmode_seconds": { + "name": "slowmode_seconds", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_room_channel_template_guild_id_index": { + "name": "event_room_channel_template_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_room_channel_template_event_id_index": { + "name": "event_room_channel_template_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_room_channel_template_event_id_suffix_unique": { + "name": "event_room_channel_template_event_id_suffix_unique", + "columns": [ + "event_id", + "suffix" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_room_channel_template_guild_id_guild_guild_id_fk": { + "name": "event_room_channel_template_guild_id_guild_guild_id_fk", + "tableFrom": "event_room_channel_template", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_room_channel_template_event_id_event_id_fk": { + "name": "event_room_channel_template_event_id_event_id_fk", + "tableFrom": "event_room_channel_template", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event": { + "name": "event", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "room_count": { + "name": "room_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "room_queues_channel_id": { + "name": "room_queues_channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sub_queues_channel_id": { + "name": "sub_queues_channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "room_length_ms": { + "name": "room_length_ms", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "room_scheduling": { + "name": "room_scheduling", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'parallel'" + }, + "create_offset_ms": { + "name": "create_offset_ms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 86400000 + }, + "lock_offset_ms": { + "name": "lock_offset_ms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "cleanup_offset_ms": { + "name": "cleanup_offset_ms", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 3600000 + }, + "announcement_channel_id": { + "name": "announcement_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "announcement_message": { + "name": "announcement_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "room_ping_message": { + "name": "room_ping_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "max_rooms_per_user": { + "name": "max_rooms_per_user", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "max_subs_per_user": { + "name": "max_subs_per_user", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "parent_sub_mutually_exclusive": { + "name": "parent_sub_mutually_exclusive", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "room_category_id": { + "name": "room_category_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_in_room_queue": { + "name": "role_in_room_queue", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "role_on_room_pull": { + "name": "role_on_room_pull", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "role_in_sub_queue": { + "name": "role_in_sub_queue", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "role_on_sub_pull": { + "name": "role_on_sub_pull", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "auto_pull_subs_at_room_start_toggle": { + "name": "auto_pull_subs_at_room_start_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "shuffle_subs_before_auto_pull_toggle": { + "name": "shuffle_subs_before_auto_pull_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "sub_auto_pull_mode": { + "name": "sub_auto_pull_mode", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'drain'" + }, + "create_discord_event": { + "name": "create_discord_event", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "discord_event_description": { + "name": "discord_event_description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "winner_role_id": { + "name": "winner_role_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_guild_id_index": { + "name": "event_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_name_guild_id_unique": { + "name": "event_name_guild_id_unique", + "columns": [ + "name", + "guild_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_guild_id_guild_guild_id_fk": { + "name": "event_guild_id_guild_guild_id_fk", + "tableFrom": "event", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_whitelisted": { + "name": "event_whitelisted", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "event_whitelisted_guild_id_index": { + "name": "event_whitelisted_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_whitelisted_event_id_index": { + "name": "event_whitelisted_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_whitelisted_event_id_subject_id_unique": { + "name": "event_whitelisted_event_id_subject_id_unique", + "columns": [ + "event_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_whitelisted_guild_id_guild_guild_id_fk": { + "name": "event_whitelisted_guild_id_guild_guild_id_fk", + "tableFrom": "event_whitelisted", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_whitelisted_event_id_event_id_fk": { + "name": "event_whitelisted_event_id_event_id_fk", + "tableFrom": "event_whitelisted", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "event_winner": { + "name": "event_winner", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "event_id": { + "name": "event_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "room_index": { + "name": "room_index", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role_id": { + "name": "role_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "declared_at": { + "name": "declared_at", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "event_winner_guild_id_index": { + "name": "event_winner_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "event_winner_event_id_index": { + "name": "event_winner_event_id_index", + "columns": [ + "event_id" + ], + "isUnique": false + }, + "event_winner_event_id_room_index_user_id_unique": { + "name": "event_winner_event_id_room_index_user_id_unique", + "columns": [ + "event_id", + "room_index", + "user_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "event_winner_guild_id_guild_guild_id_fk": { + "name": "event_winner_guild_id_guild_guild_id_fk", + "tableFrom": "event_winner", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "event_winner_event_id_event_id_fk": { + "name": "event_winner_event_id_event_id_fk", + "tableFrom": "event_winner", + "tableTo": "event", + "columnsFrom": [ + "event_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "guild_blacklisted": { + "name": "guild_blacklisted", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "guild_blacklisted_guild_id_index": { + "name": "guild_blacklisted_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "guild_blacklisted_guild_id_subject_id_unique": { + "name": "guild_blacklisted_guild_id_subject_id_unique", + "columns": [ + "guild_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "guild_blacklisted_guild_id_guild_guild_id_fk": { + "name": "guild_blacklisted_guild_id_guild_guild_id_fk", + "tableFrom": "guild_blacklisted", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "guild_prioritized": { + "name": "guild_prioritized", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "priority_order": { + "name": "priority_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 5 + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "guild_prioritized_guild_id_index": { + "name": "guild_prioritized_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "guild_prioritized_guild_id_subject_id_unique": { + "name": "guild_prioritized_guild_id_subject_id_unique", + "columns": [ + "guild_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "guild_prioritized_guild_id_guild_guild_id_fk": { + "name": "guild_prioritized_guild_id_guild_guild_id_fk", + "tableFrom": "guild_prioritized", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "guild": { + "name": "guild", + "columns": { + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "log_channel_id": { + "name": "log_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "log_scope": { + "name": "log_scope", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "joinTime": { + "name": "joinTime", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_updated_time": { + "name": "last_updated_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "messages_received": { + "name": "messages_received", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "commands_received": { + "name": "commands_received", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "buttons_received": { + "name": "buttons_received", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "queues_added": { + "name": "queues_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "voices_added": { + "name": "voices_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "displays_added": { + "name": "displays_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "members_added": { + "name": "members_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "schedules_added": { + "name": "schedules_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "whitelisted_added": { + "name": "whitelisted_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "blacklisted_added": { + "name": "blacklisted_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "prioritized_added": { + "name": "prioritized_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "admins_added": { + "name": "admins_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "archived_members_added": { + "name": "archived_members_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "events_added": { + "name": "events_added", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "guild_whitelisted": { + "name": "guild_whitelisted", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "guild_whitelisted_guild_id_index": { + "name": "guild_whitelisted_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "guild_whitelisted_guild_id_subject_id_unique": { + "name": "guild_whitelisted_guild_id_subject_id_unique", + "columns": [ + "guild_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "guild_whitelisted_guild_id_guild_guild_id_fk": { + "name": "guild_whitelisted_guild_id_guild_guild_id_fk", + "tableFrom": "guild_whitelisted", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "member": { + "name": "member", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "position_time": { + "name": "position_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "join_time": { + "name": "join_time", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "priority_order": { + "name": "priority_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "member_guild_id_index": { + "name": "member_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "member_priority_order_index": { + "name": "member_priority_order_index", + "columns": [ + "priority_order" + ], + "isUnique": false + }, + "member_position_time_index": { + "name": "member_position_time_index", + "columns": [ + "position_time" + ], + "isUnique": false + }, + "member_queue_id_user_id_unique": { + "name": "member_queue_id_user_id_unique", + "columns": [ + "queue_id", + "user_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "member_guild_id_guild_guild_id_fk": { + "name": "member_guild_id_guild_guild_id_fk", + "tableFrom": "member", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "member_queue_id_queue_id_fk": { + "name": "member_queue_id_queue_id_fk", + "tableFrom": "member", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "patch_note": { + "name": "patch_note", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "file_name": { + "name": "file_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "prioritized": { + "name": "prioritized", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "priority_order": { + "name": "priority_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 5 + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "prioritized_guild_id_index": { + "name": "prioritized_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "prioritized_queue_id_subject_id_unique": { + "name": "prioritized_queue_id_subject_id_unique", + "columns": [ + "queue_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "prioritized_guild_id_guild_guild_id_fk": { + "name": "prioritized_guild_id_guild_guild_id_fk", + "tableFrom": "prioritized", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "prioritized_queue_id_queue_id_fk": { + "name": "prioritized_queue_id_queue_id_fk", + "tableFrom": "prioritized", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "queue": { + "name": "queue", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "autopull_toggle": { + "name": "autopull_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "badge_toggle": { + "name": "badge_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'Random'" + }, + "display_update_type": { + "name": "display_update_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'edit'" + }, + "dm_on_pull_toggle": { + "name": "dm_on_pull_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "buttons_toggles": { + "name": "buttons_toggles", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'all'" + }, + "header": { + "name": "header", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "inline_toggle": { + "name": "inline_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "lock_toggle": { + "name": "lock_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "member_display_type": { + "name": "member_display_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'mention'" + }, + "pull_batch_size": { + "name": "pull_batch_size", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 1 + }, + "pull_message": { + "name": "pull_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pull_message_display_type": { + "name": "pull_message_display_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'private'" + }, + "pull_message_channel_id": { + "name": "pull_message_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "rejoin_cooldown_period": { + "name": "rejoin_cooldown_period", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "rejoin_grace_period": { + "name": "rejoin_grace_period", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "require_message_to_join": { + "name": "require_message_to_join", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": false + }, + "role_in_queue_id": { + "name": "role_in_queue_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_on_pull_id": { + "name": "role_on_pull_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "time_display_type": { + "name": "time_display_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'off'" + }, + "voice_destination_channel_id": { + "name": "voice_destination_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "voice_only_toggle": { + "name": "voice_only_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + } + }, + "indexes": { + "queue_guild_id_index": { + "name": "queue_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "queue_name_guild_id_unique": { + "name": "queue_name_guild_id_unique", + "columns": [ + "name", + "guild_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "queue_guild_id_guild_guild_id_fk": { + "name": "queue_guild_id_guild_guild_id_fk", + "tableFrom": "queue", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "schedule": { + "name": "schedule", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "command": { + "name": "command", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "cron": { + "name": "cron", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "timezone": { + "name": "timezone", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'america/chicago'" + }, + "message_channel_id": { + "name": "message_channel_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "schedule_guild_id_index": { + "name": "schedule_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "schedule_queue_id_command_cron_timezone_unique": { + "name": "schedule_queue_id_command_cron_timezone_unique", + "columns": [ + "queue_id", + "command", + "cron", + "timezone" + ], + "isUnique": true + } + }, + "foreignKeys": { + "schedule_guild_id_guild_guild_id_fk": { + "name": "schedule_guild_id_guild_guild_id_fk", + "tableFrom": "schedule", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "schedule_queue_id_queue_id_fk": { + "name": "schedule_queue_id_queue_id_fk", + "tableFrom": "schedule", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "voice": { + "name": "voice", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "source_channel_id": { + "name": "source_channel_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "join_sync_toggle": { + "name": "join_sync_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "leave_sync_toggle": { + "name": "leave_sync_toggle", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + } + }, + "indexes": { + "voice_guild_id_index": { + "name": "voice_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "voice_queue_id_source_channel_id_unique": { + "name": "voice_queue_id_source_channel_id_unique", + "columns": [ + "queue_id", + "source_channel_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "voice_guild_id_guild_guild_id_fk": { + "name": "voice_guild_id_guild_guild_id_fk", + "tableFrom": "voice", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "voice_queue_id_queue_id_fk": { + "name": "voice_queue_id_queue_id_fk", + "tableFrom": "voice", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "whitelisted": { + "name": "whitelisted", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "guild_id": { + "name": "guild_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "queue_id": { + "name": "queue_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject_id": { + "name": "subject_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_role": { + "name": "is_role", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reason": { + "name": "reason", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": { + "whitelisted_guild_id_index": { + "name": "whitelisted_guild_id_index", + "columns": [ + "guild_id" + ], + "isUnique": false + }, + "whitelisted_queue_id_subject_id_unique": { + "name": "whitelisted_queue_id_subject_id_unique", + "columns": [ + "queue_id", + "subject_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "whitelisted_guild_id_guild_guild_id_fk": { + "name": "whitelisted_guild_id_guild_guild_id_fk", + "tableFrom": "whitelisted", + "tableTo": "guild", + "columnsFrom": [ + "guild_id" + ], + "columnsTo": [ + "guild_id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "whitelisted_queue_id_queue_id_fk": { + "name": "whitelisted_queue_id_queue_id_fk", + "tableFrom": "whitelisted", + "tableTo": "queue", + "columnsFrom": [ + "queue_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/data/migrations/meta/_journal.json b/data/migrations/meta/_journal.json index 2c9ed45c..a8405f29 100644 --- a/data/migrations/meta/_journal.json +++ b/data/migrations/meta/_journal.json @@ -85,6 +85,20 @@ "when": 1779518043928, "tag": "0011_complete_ted_forrester", "breakpoints": true + }, + { + "idx": 12, + "version": "6", + "when": 1779693989600, + "tag": "0012_powerful_songbird", + "breakpoints": true + }, + { + "idx": 13, + "version": "6", + "when": 1780196657727, + "tag": "0013_mature_steve_rogers", + "breakpoints": true } ] } \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..dca1043a --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,92 @@ +import js from "@eslint/js"; +import stylistic from "@stylistic/eslint-plugin"; +import simpleImportSort from "eslint-plugin-simple-import-sort"; +import unusedImports from "eslint-plugin-unused-imports"; +import globals from "globals"; +import tseslint from "typescript-eslint"; + +export default tseslint.config( + { + ignores: ["node_modules/**", "data/**", "logs/**"], + }, + { + files: ["src/**/*.ts", "patch-notes/**/*.ts", "*.config.ts"], + extends: [ + js.configs.recommended, + ...tseslint.configs.recommended, + ], + plugins: { + "@stylistic": stylistic, + "simple-import-sort": simpleImportSort, + "unused-imports": unusedImports, + }, + languageOptions: { + parserOptions: { + project: "tsconfig.json", + sourceType: "module", + }, + globals: { + ...globals.node, + }, + }, + rules: { + // TypeScript Specific Rules + // `no-namespace` and `no-explicit-any` are intentionally off: util files + // (MemberUtils, Queries, DisplayUtils, …) are namespace-based by design and + // `any` is used at interaction-typing seams (tsconfig has `noImplicitAny: + // false`). The rest of `tseslint.configs.recommended` is left enabled. + "@typescript-eslint/no-namespace": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }], + + // `no-undef` and `no-unused-vars` are turned off per typescript-eslint convention + // (TS itself catches undefined refs; the @typescript-eslint/no-unused-vars rule + // supersedes the core one). All other `eslint:recommended` rules stay on. + "no-undef": "off", + "no-unused-vars": "off", + + // Plugin rules + "unused-imports/no-unused-imports": "error", + "simple-import-sort/imports": "error", + + // Additional core rules (not in recommended) carried over from the legacy config + "no-empty-function": ["error", { allow: ["constructors"] }], + "no-lonely-if": "error", + "no-var": "error", + "prefer-const": "error", + "max-nested-callbacks": ["error", { max: 4 }], + "curly": ["error", "multi-line", "consistent"], + "yoda": ["error", "never"], + + // Formatting and Stylistic Rules (moved from core to @stylistic) + "@stylistic/brace-style": ["error", "stroustrup", { allowSingleLine: true }], + // Trailing commas are optional: allowed in multiline lists, forbidden on + // single-line ones (so `[1, 2,]` is still caught). + "@stylistic/comma-dangle": ["error", "only-multiline"], + "@stylistic/comma-spacing": ["error", { before: false, after: true }], + "@stylistic/comma-style": ["error", "last"], + "@stylistic/dot-location": ["error", "property"], + "@stylistic/indent": ["error", "tab", { SwitchCase: 1 }], + "@stylistic/max-statements-per-line": ["error", { max: 2 }], + "@stylistic/no-floating-decimal": "error", + "@stylistic/no-multi-spaces": "error", + "@stylistic/no-multiple-empty-lines": ["error", { max: 2, maxEOF: 0, maxBOF: 0 }], + "@stylistic/no-trailing-spaces": "error", + "@stylistic/object-curly-spacing": ["error", "always"], + "@stylistic/quotes": ["error", "double", { avoidEscape: true, allowTemplateLiterals: "always" }], + "@stylistic/semi": ["error", "always"], + "@stylistic/space-before-blocks": "error", + "@stylistic/space-before-function-paren": ["error", { + anonymous: "never", + named: "never", + asyncArrow: "always", + }], + "@stylistic/space-infix-ops": "error", + "@stylistic/space-unary-ops": "error", + "@stylistic/spaced-comment": ["error", "always", { + line: { markers: ["/"], exceptions: ["-", "+"] }, + block: { balanced: true }, + }], + }, + }, +); diff --git a/infra/digitalocean/cloud-init.yml b/infra/digitalocean/cloud-init.yml index a7109ea9..aba7772e 100644 --- a/infra/digitalocean/cloud-init.yml +++ b/infra/digitalocean/cloud-init.yml @@ -50,7 +50,7 @@ write_files: fi docker compose up -d --build - docker image prune -f + docker image prune -f --filter "until=72h" docker logs --tail 100 queue-bot - path: /etc/sudoers.d/event-queue-bot-deploy diff --git a/package-lock.json b/package-lock.json index 8cc6a6dd..3646b2b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,31 +6,33 @@ "": { "name": "queue-bot", "dependencies": { + "@swc-node/register": "^1.9.2", "better-sqlite3": "^12.10.0", - "cronstrue": "^2.48.0", + "cronstrue": "^3.14.0", "csv-parser": "^3.0.0", "date-fns": "^4.1.0", "discord.js": "^14.14.1", - "drizzle-kit": "^0.31.1", - "drizzle-orm": "^0.43.1", + "drizzle-kit": "^0.31.10", + "drizzle-orm": "^0.45.2", "lodash-es": "^4.17.21", - "moment-timezone": "^0.5.45", - "node-cron": "^3.0.3", + "moment-timezone": "^0.6.2", + "node-cron": "^4.2.1", "node-schedule": "^2.1.1", "topgg-autoposter": "^2.0.2" }, "devDependencies": { - "@stylistic/eslint-plugin": "^2.12.1", - "@swc-node/register": "^1.9.2", + "@eslint/js": "^10.0.1", + "@stylistic/eslint-plugin": "^5.10.0", "@types/better-sqlite3": "^7.6.9", "@types/lodash-es": "^4.17.12", - "@types/node": "^22.10.2", - "@types/node-cron": "^3.0.11", + "@types/node": "^24.12.4", "@types/node-schedule": "^2.1.8", - "@typescript-eslint/eslint-plugin": "^7.1.0", - "eslint-plugin-simple-import-sort": "^12.0.0", + "eslint": "^10.4.0", + "eslint-plugin-simple-import-sort": "^13.0.0", "eslint-plugin-unused-imports": "^4.1.4", - "typescript": "^5.0.0", + "globals": "^16.5.0", + "typescript": "^6.0.3", + "typescript-eslint": "^8.59.4", "vitest": "^4.1.7" } }, @@ -184,7 +186,6 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -196,7 +197,6 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -207,7 +207,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1083,99 +1082,90 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", "dev": true, - "license": "MIT", - "peer": true, + "license": "Apache-2.0", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "node_modules/@eslint/config-helpers": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.6.0.tgz", + "integrity": "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==", "dev": true, - "license": "MIT", - "peer": true, + "license": "Apache-2.0", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@eslint/eslintrc/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", "dev": true, "license": "Apache-2.0", - "peer": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "dependencies": { + "@types/json-schema": "^7.0.15" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@eslint/eslintrc/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", "dev": true, - "license": "BSD-2-Clause", - "peer": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "Apache-2.0", "engines": { - "node": "*" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "node_modules/@eslint/plugin-kit": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz", + "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==", "dev": true, - "license": "MIT", - "peer": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@fastify/busboy": { @@ -1187,47 +1177,42 @@ "node": ">=14" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@humanfs/types": "^0.15.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "dev": true, - "license": "MIT", - "peer": true, + "license": "Apache-2.0", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "Apache-2.0", "engines": { - "node": "*" + "node": ">=18.18.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -1236,7 +1221,6 @@ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=12.22" }, @@ -1245,14 +1229,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, - "license": "BSD-3-Clause", - "peer": true + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@jpbberry/typed-emitter": { "version": "1.2.1", @@ -1271,7 +1260,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1286,44 +1274,6 @@ "@emnapi/runtime": "^1.7.1" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/@oxc-project/types": { "version": "0.132.0", "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.132.0.tgz", @@ -1341,7 +1291,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1355,7 +1304,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1369,7 +1317,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1383,7 +1330,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1397,7 +1343,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1411,7 +1356,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1425,7 +1369,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1439,7 +1382,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1453,7 +1395,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1467,7 +1408,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1481,7 +1421,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1495,7 +1434,6 @@ "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1509,7 +1447,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1523,7 +1460,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1537,7 +1473,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1551,7 +1486,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1565,7 +1499,6 @@ "cpu": [ "wasm32" ], - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1582,7 +1515,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1596,7 +1528,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1610,7 +1541,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1922,30 +1852,30 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.13.0.tgz", - "integrity": "sha512-RnO1SaiCFHn666wNz2QfZEFxvmiNRqhzaMXHXxXXKt+MEP7aajlPxUSMIQpKAaJfverpovEYqjBOXDq6dDcaOQ==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.10.0.tgz", + "integrity": "sha512-nPK52ZHvot8Ju/0A4ucSX1dcPV2/1clx0kLcH5wDmrE4naKso7TUC/voUyU1O9OTKTrR6MYip6LP0ogEMQ9jPQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.13.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/types": "^8.56.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "estraverse": "^5.3.0", - "picomatch": "^4.0.2" + "picomatch": "^4.0.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "peerDependencies": { - "eslint": ">=8.40.0" + "eslint": "^9.0.0 || ^10.0.0" } }, "node_modules/@swc-node/core": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@swc-node/core/-/core-1.14.1.tgz", "integrity": "sha512-jrt5GUaZUU6cmMS+WTJEvGvaB6j1YNKPHPzC2PUi2BjaFbtxURHj6641Az6xN7b665hNniAIdvjxWcRml5yCnw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 10" @@ -1963,7 +1893,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@swc-node/register/-/register-1.11.1.tgz", "integrity": "sha512-VQ0hJ5jX31TVv/fhZx4xJRzd8pwn6VvzYd2tGOHHr2TfXGCBixZoqdPDXTiEoJLCTS2MmvBf6zyQZZ0M8aGQCQ==", - "dev": true, "license": "MIT", "dependencies": { "@swc-node/core": "^1.14.1", @@ -1987,7 +1916,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/@swc-node/sourcemap-support/-/sourcemap-support-0.6.1.tgz", "integrity": "sha512-ovltDVH5QpdHXZkW138vG4+dgcNsxfwxHVoV6BtmTbz2KKl1A8ZSlbdtxzzfNjCjbpayda8Us9eMtcHobm38dA==", - "dev": true, "license": "MIT", "dependencies": { "source-map-support": "^0.5.21", @@ -1998,7 +1926,6 @@ "version": "1.15.40", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.40.tgz", "integrity": "sha512-2kwzJikRvgtNAG7MwVZY2vEzZjTxKIq5jXOihuSV/8U+Hej8Va22t65aKnJZs3P+NwojZvR8Mf8kyM7O+V8sQg==", - "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "peer": true, @@ -2043,7 +1970,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -2061,7 +1987,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -2079,7 +2004,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -2097,7 +2021,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -2115,7 +2038,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -2133,7 +2055,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -2151,7 +2072,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -2169,7 +2089,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -2187,7 +2106,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -2205,7 +2123,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -2223,7 +2140,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -2241,7 +2157,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -2256,7 +2171,6 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "dev": true, "license": "Apache-2.0", "peer": true }, @@ -2264,7 +2178,6 @@ "version": "0.1.26", "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.26.tgz", "integrity": "sha512-lyMwd7WGgG79RS7EERZV3T8wMdmPq3xwyg+1nmAM64kIhx5yl+juO2PYIHb7vTiPgPCj8LYjsNV2T5wiQHUEaw==", - "dev": true, "license": "Apache-2.0", "peer": true, "dependencies": { @@ -2297,7 +2210,6 @@ "version": "0.10.2", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -2332,6 +2244,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", @@ -2339,6 +2258,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/lodash": { "version": "4.17.24", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", @@ -2357,21 +2283,14 @@ } }, "node_modules/@types/node": { - "version": "22.19.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz", - "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==", + "version": "24.12.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.4.tgz", + "integrity": "sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==", "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.16.0" } }, - "node_modules/@types/node-cron": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-3.0.11.tgz", - "integrity": "sha512-0ikrnug3/IyneSHqCBeslAhlK2aBfYek1fGo4bP4QnZPmiqSGRK+Oy7ZMisLWkesffJvQ1cqAcBnJC+8+nxIAg==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node-schedule": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/@types/node-schedule/-/node-schedule-2.1.8.tgz", @@ -2392,90 +2311,67 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", - "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "version": "8.59.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.4.tgz", + "integrity": "sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/type-utils": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.59.4", + "@typescript-eslint/type-utils": "8.59.4", + "@typescript-eslint/utils": "8.59.4", + "@typescript-eslint/visitor-keys": "8.59.4", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@typescript-eslint/parser": "^8.59.4", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" - }, "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", - "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "version": "8.59.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.4.tgz", + "integrity": "sha512-zORHqO/tuhxY1zWuTvMUqddRxpiFJ72xVfcNoWpqdLjs6lfPbuQBJuW4pk+49/uBMy7Ssr4bzgjiKmmDB1UbZQ==", "dev": true, - "license": "BSD-2-Clause", - "peer": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.59.4", + "@typescript-eslint/types": "8.59.4", + "@typescript-eslint/typescript-estree": "8.59.4", + "@typescript-eslint/visitor-keys": "8.59.4", + "debug": "^4.4.3" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/project-service": { @@ -2500,32 +2396,18 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/project-service/node_modules/@typescript-eslint/types": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.4.tgz", - "integrity": "sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "version": "8.59.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.4.tgz", + "integrity": "sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" + "@typescript-eslint/types": "8.59.4", + "@typescript-eslint/visitor-keys": "8.59.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2550,97 +2432,70 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", - "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "version": "8.59.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.4.tgz", + "integrity": "sha512-uonTuPAAKr9XaBGqJ3LjYTh72zy5DyGesljO9gtmk/eFW0W1fRHjnwVYKB35Lm8d5Q5CluEW3gPHjTvZTmgrfA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "@typescript-eslint/types": "8.59.4", + "@typescript-eslint/typescript-estree": "8.59.4", + "@typescript-eslint/utils": "8.59.4", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "node_modules/@typescript-eslint/types": { + "version": "8.59.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.4.tgz", + "integrity": "sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==", "dev": true, "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" - }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" } }, - "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.59.4", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.4.tgz", + "integrity": "sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag==", "dev": true, "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.59.4", + "@typescript-eslint/tsconfig-utils": "8.59.4", + "@typescript-eslint/types": "8.59.4", + "@typescript-eslint/visitor-keys": "8.59.4", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/utils": { @@ -2667,67 +2522,7 @@ "typescript": ">=4.8.4 <6.1.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.4.tgz", - "integrity": "sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.4.tgz", - "integrity": "sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.59.4", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.4.tgz", - "integrity": "sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.59.4", - "@typescript-eslint/tsconfig-utils": "8.59.4", - "@typescript-eslint/types": "8.59.4", - "@typescript-eslint/visitor-keys": "8.59.4", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "node_modules/@typescript-eslint/visitor-keys": { "version": "8.59.4", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.4.tgz", "integrity": "sha512-U3gxVaDVnuZKhSspW/MzMxE1kq7zOdc072FcSNoqA1I9p8HyKbBFfEHoWckBAMgNMph4MamwS5iTVzFmrnt8TQ==", @@ -2745,30 +2540,7 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/utils/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-visitor-keys": { + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", @@ -2781,74 +2553,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@typescript-eslint/utils/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/ts-api-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", - "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", - "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", - "dev": true, - "license": "ISC", - "peer": true - }, "node_modules/@vitest/expect": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.7.tgz", @@ -2974,7 +2678,6 @@ "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -2986,52 +2689,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0", - "peer": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -3043,11 +2700,14 @@ } }, "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } }, "node_modules/base64-js": { "version": "1.5.1", @@ -3104,26 +2764,16 @@ } }, "node_modules/brace-expansion": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", - "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { - "fill-range": "^7.1.1" + "balanced-match": "^4.0.2" }, "engines": { - "node": ">=8" + "node": "18 || 20 || >=22" } }, "node_modules/buffer": { @@ -3165,17 +2815,6 @@ "node": ">= 0.8" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", @@ -3186,67 +2825,18 @@ "node": ">=18" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/chownr": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "license": "ISC" }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, "license": "MIT" }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -3267,9 +2857,9 @@ } }, "node_modules/cronstrue": { - "version": "2.59.0", - "resolved": "https://registry.npmjs.org/cronstrue/-/cronstrue-2.59.0.tgz", - "integrity": "sha512-YKGmAy84hKH+hHIIER07VCAHf9u0Ldelx1uU6EBxsRPDXIA1m5fsKmJfyC3xBhw6cVC/1i83VdbL4PvepTrt8A==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/cronstrue/-/cronstrue-3.14.0.tgz", + "integrity": "sha512-XnW4vuK/jPJjmTyDWiej1Zq36Od7ITwxaV2O1pzHZuyMVvdy7NAvyvIBzybt+idqSpfqYuoDG7uf/ocGtJVWxA==", "license": "MIT", "bin": { "cronstrue": "bin/cli.js" @@ -3281,7 +2871,6 @@ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -3317,7 +2906,6 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -3360,8 +2948,7 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/depd": { "version": "2.0.0", @@ -3381,19 +2968,6 @@ "node": ">=8" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/discord-api-types": { "version": "0.38.47", "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.38.47.tgz", @@ -3430,20 +3004,6 @@ "url": "https://github.com/discordjs/discord.js?sponsor" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/drizzle-kit": { "version": "0.31.10", "resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.31.10.tgz", @@ -3460,9 +3020,9 @@ } }, "node_modules/drizzle-orm": { - "version": "0.43.1", - "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.43.1.tgz", - "integrity": "sha512-dUcDaZtE/zN4RV/xqGrVSMpnEczxd5cIaoDeor7Zst9wOe/HzC/7eAaulywWGYXdDEc9oBPMjayVEDg0ziTLJA==", + "version": "0.45.2", + "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.45.2.tgz", + "integrity": "sha512-kY0BSaTNYWnoDMVoyY8uxmyHjpJW1geOmBMdSSicKo9CIIWkSxMIj2rkeSR51b8KAPB7m+qysjuHme5nKP+E5Q==", "license": "Apache-2.0", "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", @@ -3479,6 +3039,7 @@ "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", + "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", @@ -3536,6 +3097,9 @@ "@types/sql.js": { "optional": true }, + "@upstash/redis": { + "optional": true + }, "@vercel/postgres": { "optional": true }, @@ -3643,7 +3207,6 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -3652,67 +3215,65 @@ } }, "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.4.0.tgz", + "integrity": "sha512-loXy6bWOoP3EP6JA7jo6p5jMpBJmHmsNZM5SFRHLdh1MGOPurMnNBj4ZlAbaqUAaQWbCr7jHV4P7gzAyryZWkQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.6.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.1", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^10.2.4", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-plugin-simple-import-sort": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz", - "integrity": "sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-13.0.0.tgz", + "integrity": "sha512-McAc+/Nlvcg4byY/CABGH8kqnefWBj8s3JA2okEtz8ixbECQgU46p0HkTUKa4YS7wvgGceimlc34p1nXqbWqtA==", "dev": true, "license": "MIT", "peerDependencies": { @@ -3736,18 +3297,19 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -3766,65 +3328,37 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^5.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/espree": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", @@ -3849,7 +3383,6 @@ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -3863,7 +3396,6 @@ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -3897,7 +3429,6 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -3927,61 +3458,19 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } + "license": "MIT" }, "node_modules/fdir": { "version": "6.5.0", @@ -4002,17 +3491,16 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-uri-to-path": { @@ -4021,26 +3509,12 @@ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "license": "MIT" }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -4053,19 +3527,17 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -4073,8 +3545,7 @@ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/fs-constants": { "version": "1.0.0", @@ -4082,14 +3553,6 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "license": "MIT" }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC", - "peer": true - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -4122,36 +3585,12 @@ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "license": "MIT" }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -4159,88 +3598,19 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true, "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", @@ -4303,48 +3673,16 @@ "node": ">= 4" } }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.8.19" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -4373,32 +3711,11 @@ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "peer": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, "node_modules/isexe": { @@ -4406,46 +3723,28 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, - "license": "ISC", - "peer": true - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } + "license": "ISC" }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/keyv": { "version": "4.5.4", @@ -4453,7 +3752,6 @@ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "json-buffer": "3.0.1" } @@ -4464,7 +3762,6 @@ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -4740,7 +4037,6 @@ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -4763,14 +4059,6 @@ "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", "license": "MIT" }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/lodash.snakecase": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", @@ -4808,43 +4096,6 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", @@ -4858,16 +4109,16 @@ } }, "node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.2" + "brace-expansion": "^5.0.5" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4898,9 +4149,9 @@ } }, "node_modules/moment-timezone": { - "version": "0.5.48", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz", - "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.2.tgz", + "integrity": "sha512-lDsQv8FoGdBUdf0+TjGsq2orxKuXdwFlQ6Zw6TX3xIcTwTfEpCLyKqvEauvCHJ8iu3KBV8+uPhlv70YsNGdUBQ==", "license": "MIT", "dependencies": { "moment": "^2.29.4" @@ -4913,7 +4164,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/nanoid": { @@ -4961,13 +4211,10 @@ } }, "node_modules/node-cron": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz", - "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-4.2.1.tgz", + "integrity": "sha512-lgimEHPE/QDgFlywTd8yTR61ptugX3Qer29efeyWw2rv259HtGBNn1vZVmp8lB9uo9wC0t/AT4iGqXxia+CJFg==", "license": "ISC", - "dependencies": { - "uuid": "8.3.2" - }, "engines": { "node": ">=6.0.0" } @@ -5012,7 +4259,6 @@ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -5029,7 +4275,6 @@ "version": "11.19.1", "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-11.19.1.tgz", "integrity": "sha512-qE/CIg/spwrTBFt5aKmwe3ifeDdLfA2NESN30E42X/lII5ClF8V7Wt6WIJhcGZjp0/Q+nQ+9vgxGk//xZNX2hg==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" @@ -5063,7 +4308,6 @@ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -5080,7 +4324,6 @@ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -5091,59 +4334,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -5179,7 +4385,6 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -5247,7 +4452,6 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8.0" } @@ -5268,32 +4472,10 @@ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=6" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/raw-body": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", @@ -5347,17 +4529,6 @@ "node": ">= 6" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=4" - } - }, "node_modules/resolve-pkg-maps": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", @@ -5367,35 +4538,6 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rolldown": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.2.tgz", @@ -5430,30 +4572,6 @@ "@rolldown/binding-win32-x64-msvc": "1.0.2" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -5504,7 +4622,6 @@ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -5518,7 +4635,6 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -5575,16 +4691,6 @@ "simple-concat": "^1.0.0" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/sorted-array-functions": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", @@ -5652,48 +4758,6 @@ "safe-buffer": "~5.2.0" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/tar-fs": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", @@ -5722,14 +4786,6 @@ "node": ">=6" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -5774,19 +4830,6 @@ "node": ">=14.0.0" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -5807,16 +4850,16 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/ts-mixer": { @@ -6324,7 +5367,6 @@ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -6332,25 +5374,10 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -6360,6 +5387,30 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.59.4", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.4.tgz", + "integrity": "sha512-Rw6+44QNFaXtgHSjPy+Kw8hrJniMYzR85E9yLmOLcfZ91/rz+JXQbDTCmc6ccxMPY6K6PgAq26f0JCBfR7LIPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.59.4", + "@typescript-eslint/parser": "8.59.4", + "@typescript-eslint/typescript-estree": "8.59.4", + "@typescript-eslint/utils": "8.59.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/undici": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/undici/-/undici-6.24.1.tgz", @@ -6370,9 +5421,9 @@ } }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "license": "MIT" }, "node_modules/unpipe": { @@ -6390,7 +5441,6 @@ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "punycode": "^2.1.0" } @@ -6401,16 +5451,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/vitest": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.7.tgz", @@ -6612,7 +5652,6 @@ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "isexe": "^2.0.0" }, @@ -6646,7 +5685,6 @@ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -6684,7 +5722,6 @@ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index 2a64d5da..3ca87d68 100644 --- a/package.json +++ b/package.json @@ -5,37 +5,39 @@ "scripts": { "setup": "npm ci", "start": "node --loader @swc-node/register/esm --no-warnings --enable-source-maps --env-file .env src/index.ts", - "lint": "eslint src --fix", - "lint:check": "eslint src", + "lint": "eslint src patch-notes drizzle.config.ts vitest.config.ts --fix", + "lint:check": "eslint src patch-notes drizzle.config.ts vitest.config.ts", "typecheck": "tsc --noEmit", "test": "vitest run --passWithNoTests" }, "type": "module", "devDependencies": { - "@stylistic/eslint-plugin": "^2.12.1", - "@swc-node/register": "^1.9.2", + "@eslint/js": "^10.0.1", + "@stylistic/eslint-plugin": "^5.10.0", "@types/better-sqlite3": "^7.6.9", "@types/lodash-es": "^4.17.12", - "@types/node": "^22.10.2", - "@types/node-cron": "^3.0.11", + "@types/node": "^24.12.4", "@types/node-schedule": "^2.1.8", - "@typescript-eslint/eslint-plugin": "^7.1.0", - "eslint-plugin-simple-import-sort": "^12.0.0", + "eslint": "^10.4.0", + "eslint-plugin-simple-import-sort": "^13.0.0", "eslint-plugin-unused-imports": "^4.1.4", - "typescript": "^5.0.0", + "globals": "^16.5.0", + "typescript": "^6.0.3", + "typescript-eslint": "^8.59.4", "vitest": "^4.1.7" }, "dependencies": { + "@swc-node/register": "^1.9.2", "better-sqlite3": "^12.10.0", - "cronstrue": "^2.48.0", + "cronstrue": "^3.14.0", "csv-parser": "^3.0.0", "date-fns": "^4.1.0", "discord.js": "^14.14.1", - "drizzle-kit": "^0.31.1", - "drizzle-orm": "^0.43.1", + "drizzle-kit": "^0.31.10", + "drizzle-orm": "^0.45.2", "lodash-es": "^4.17.21", - "moment-timezone": "^0.5.45", - "node-cron": "^3.0.3", + "moment-timezone": "^0.6.2", + "node-cron": "^4.2.1", "node-schedule": "^2.1.1", "topgg-autoposter": "^2.0.2" } diff --git a/src/commands/commands/events.command.ts b/src/commands/commands/events.command.ts index bc2a7a95..5a6fdde0 100644 --- a/src/commands/commands/events.command.ts +++ b/src/commands/commands/events.command.ts @@ -1,11 +1,13 @@ -import { channelMention, type Collection, EmbedBuilder, inlineCode, PermissionsBitField, SlashCommandBuilder, time, TimestampStyles } from "discord.js"; +import { channelMention, type Collection, EmbedBuilder, inlineCode, PermissionsBitField, roleMention, SlashCommandBuilder, time, TimestampStyles, userMention } from "discord.js"; import { SQLiteColumn } from "drizzle-orm/sqlite-core"; -import { findKey, isNil, omitBy } from "lodash-es"; +import { compact, findKey, isNil, omitBy } from "lodash-es"; import { Queries } from "../../db/queries.ts"; import { type DbEvent, EVENT_TABLE, QUEUE_TABLE } from "../../db/schema.ts"; +import { UserOption } from "../../options/base-option.ts"; import { AnnouncementChannelOption } from "../../options/options/announcement-channel.option.ts"; import { AnnouncementMessageOption } from "../../options/options/announcement-message.option.ts"; +import { AutoPullSubsAtRoomStartToggleOption } from "../../options/options/auto-pull-subs-at-room-start-toggle.option.ts"; import { AutopullToggleOption } from "../../options/options/autopull-toggle.option.ts"; import { BadgeToggleOption } from "../../options/options/badge-toggle.option.ts"; import { ChannelSuffixOption } from "../../options/options/channel-suffix.option.ts"; @@ -45,31 +47,37 @@ import { RoleOnRoomPullOption } from "../../options/options/role-on-room-pull.op import { RoleOnSubPullOption } from "../../options/options/role-on-sub-pull.option.ts"; import { RoomCategoryOption } from "../../options/options/room-category.option.ts"; import { RoomCountOption } from "../../options/options/room-count.option.ts"; +import { RoomIndexOption } from "../../options/options/room-index.option.ts"; import { RoomLengthMinutesOption } from "../../options/options/room-length-minutes.option.ts"; import { RoomPingMessageOption } from "../../options/options/room-ping-message.option.ts"; import { RoomQueuesChannelOption } from "../../options/options/room-queues-channel.option.ts"; import { RoomSchedulingOption } from "../../options/options/room-scheduling.option.ts"; +import { ShuffleSubsBeforeAutoPullToggleOption } from "../../options/options/shuffle-subs-before-auto-pull-toggle.option.ts"; import { SizeOption } from "../../options/options/size.option.ts"; import { SlowmodeOption } from "../../options/options/slowmode.option.ts"; import { SlowmodeTimeOption } from "../../options/options/slowmode-time.option.ts"; import { StartTimeOption } from "../../options/options/start-time.option.ts"; +import { SubAutoPullModeOption } from "../../options/options/sub-auto-pull-mode.option.ts"; import { SubQueuesChannelOption } from "../../options/options/sub-queues-channel.option.ts"; import { TimestampTypeOption } from "../../options/options/timestamp-type.option.ts"; import { TimezoneOption } from "../../options/options/timezone.option.ts"; import { VoiceDestinationChannelOption } from "../../options/options/voice-destination-channel.option.ts"; import { VoiceOnlyToggleOption } from "../../options/options/voice-only-toggle.option.ts"; +import { WinnerRoleOption } from "../../options/options/winner-role.option.ts"; import { YearOption } from "../../options/options/year.option.ts"; import { AdminCommand } from "../../types/command.types.ts"; -import { Color, EventQueueRole, type RoomScheduling } from "../../types/db.types.ts"; +import { Color, EventQueueRole, type RoomScheduling, type SubAutoPullMode } from "../../types/db.types.ts"; import type { SlashInteraction } from "../../types/interaction.types.ts"; import { DateUtils } from "../../utils/date.utils.ts"; -import { CustomError, EventNotFoundWarning } from "../../utils/error.utils.ts"; +import { CustomError, EventNotFoundWarning, RoomIndexNotFoundWarning, WinnerRoleNotSetWarning } from "../../utils/error.utils.ts"; import { EventUtils } from "../../utils/event.utils.ts"; import { EventChannelUtils } from "../../utils/event-channel.utils.ts"; import { EventSyncLock } from "../../utils/event-sync-lock.utils.ts"; import { SelectMenuTransactor } from "../../utils/message-utils/select-menu-transactor.ts"; import { toCollection } from "../../utils/misc.utils.ts"; import { commandMention, describeTable, eventMention, queuesMention } from "../../utils/string.utils.ts"; +import { groupWinnersByRoom } from "../../utils/winner.logic.ts"; +import { WinnerUtils } from "../../utils/winner.utils.ts"; const HOURS_TO_MS = 3_600_000n; const MINUTES_TO_MS = 60_000n; @@ -134,6 +142,9 @@ export class EventsCommand extends AdminCommand { events_schedule = EventsCommand.events_schedule; events_cancel = EventsCommand.events_cancel; events_delete = EventsCommand.events_delete; + events_declare_winners = EventsCommand.events_declare_winners; + events_winners = EventsCommand.events_winners; + events_clear_winners = EventsCommand.events_clear_winners; events_help = EventsCommand.events_help; data = new SlashCommandBuilder() @@ -244,6 +255,27 @@ export class EventsCommand extends AdminCommand { Object.values(EventsCommand.DELETE_OPTIONS).forEach(option => option.addToCommand(subcommand)); return subcommand; }) + .addSubcommand(subcommand => { + subcommand + .setName("declare-winners") + .setDescription("Grant the winner role to a room's winner(s)"); + Object.values(EventsCommand.DECLARE_WINNERS_OPTIONS).forEach(option => option.addToCommand(subcommand)); + return subcommand; + }) + .addSubcommand(subcommand => { + subcommand + .setName("winners") + .setDescription("List declared winners per room"); + Object.values(EventsCommand.WINNERS_OPTIONS).forEach(option => option.addToCommand(subcommand)); + return subcommand; + }) + .addSubcommand(subcommand => { + subcommand + .setName("clear-winners") + .setDescription("Revoke winner role(s) for a room or the whole event"); + Object.values(EventsCommand.CLEAR_WINNERS_OPTIONS).forEach(option => option.addToCommand(subcommand)); + return subcommand; + }) .addSubcommand(subcommand => { subcommand .setName("help") @@ -292,6 +324,7 @@ export class EventsCommand extends AdminCommand { announcementChannelId: event.announcementChannelId ? channelMention(event.announcementChannelId) : null, roomCategoryId: event.roomCategoryId ? channelMention(event.roomCategoryId) : null, roomChannelTemplates: templateSummary, + winnerRoleId: event.winnerRoleId ? roleMention(event.winnerRoleId) : null, }; }); @@ -333,6 +366,9 @@ export class EventsCommand extends AdminCommand { roleOnRoomPull: new RoleOnRoomPullOption({ description: "Assign room role on room queue pull" }), roleInSubQueue: new RoleInSubQueueOption({ description: "Assign room role while in sub queue" }), roleOnSubPull: new RoleOnSubPullOption({ description: "Assign room role on sub queue pull" }), + autoPullSubsAtRoomStartToggle: new AutoPullSubsAtRoomStartToggleOption({ description: "Auto-pull subs at room start" }), + shuffleSubsBeforeAutoPullToggle: new ShuffleSubsBeforeAutoPullToggleOption({ description: "Shuffle subs before auto-pull" }), + subAutoPullMode: new SubAutoPullModeOption({ description: "Auto-pull mode" }), createDiscordEvent: new CreateDiscordEventToggleOption({ description: "Create Discord scheduled event per occurrence" }), discordEventDescription: new DiscordEventDescriptionOption({ description: "Use {event_name}, {start_time}, {start_time_relative}, {room_queues_channel}, {sub_queues_channel}" }), }; @@ -368,6 +404,9 @@ export class EventsCommand extends AdminCommand { roleOnRoomPull: EventsCommand.ADD_OPTIONS.roleOnRoomPull.get(inter), roleInSubQueue: EventsCommand.ADD_OPTIONS.roleInSubQueue.get(inter), roleOnSubPull: EventsCommand.ADD_OPTIONS.roleOnSubPull.get(inter), + autoPullSubsAtRoomStartToggle: EventsCommand.ADD_OPTIONS.autoPullSubsAtRoomStartToggle.get(inter), + shuffleSubsBeforeAutoPullToggle: EventsCommand.ADD_OPTIONS.shuffleSubsBeforeAutoPullToggle.get(inter), + subAutoPullMode: EventsCommand.ADD_OPTIONS.subAutoPullMode.get(inter) as SubAutoPullMode, createDiscordEvent: EventsCommand.ADD_OPTIONS.createDiscordEvent.get(inter), discordEventDescription: EventsCommand.ADD_OPTIONS.discordEventDescription.get(inter), }, isNil), @@ -413,8 +452,12 @@ export class EventsCommand extends AdminCommand { roleOnRoomPull: new RoleOnRoomPullOption({ description: "Assign room role on room queue pull" }), roleInSubQueue: new RoleInSubQueueOption({ description: "Assign room role while in sub queue" }), roleOnSubPull: new RoleOnSubPullOption({ description: "Assign room role on sub queue pull" }), + autoPullSubsAtRoomStartToggle: new AutoPullSubsAtRoomStartToggleOption({ description: "Auto-pull subs at room start" }), + shuffleSubsBeforeAutoPullToggle: new ShuffleSubsBeforeAutoPullToggleOption({ description: "Shuffle subs before auto-pull" }), + subAutoPullMode: new SubAutoPullModeOption({ description: "Auto-pull mode" }), createDiscordEvent: new CreateDiscordEventToggleOption({ description: "Create Discord scheduled event per occurrence" }), discordEventDescription: new DiscordEventDescriptionOption({ description: "Use {event_name}, {start_time}, {start_time_relative}, {room_queues_channel}, {sub_queues_channel}" }), + winnerRole: new WinnerRoleOption({ description: "Role granted to declared room winners" }), }; static async events_set(inter: SlashInteraction) { @@ -449,8 +492,12 @@ export class EventsCommand extends AdminCommand { roleOnRoomPull: EventsCommand.SET_OPTIONS.roleOnRoomPull.get(inter), roleInSubQueue: EventsCommand.SET_OPTIONS.roleInSubQueue.get(inter), roleOnSubPull: EventsCommand.SET_OPTIONS.roleOnSubPull.get(inter), + autoPullSubsAtRoomStartToggle: EventsCommand.SET_OPTIONS.autoPullSubsAtRoomStartToggle.get(inter), + shuffleSubsBeforeAutoPullToggle: EventsCommand.SET_OPTIONS.shuffleSubsBeforeAutoPullToggle.get(inter), + subAutoPullMode: EventsCommand.SET_OPTIONS.subAutoPullMode.get(inter) as SubAutoPullMode, createDiscordEvent: EventsCommand.SET_OPTIONS.createDiscordEvent.get(inter), discordEventDescription: EventsCommand.SET_OPTIONS.discordEventDescription.get(inter), + winnerRoleId: EventsCommand.SET_OPTIONS.winnerRole.get(inter)?.id, }, isNil); const effectiveMessage = announcementMessage ?? event.announcementMessage; @@ -794,8 +841,12 @@ export class EventsCommand extends AdminCommand { { name: RoleOnRoomPullOption.ID, value: EVENT_TABLE.roleOnRoomPull.name }, { name: RoleInSubQueueOption.ID, value: EVENT_TABLE.roleInSubQueue.name }, { name: RoleOnSubPullOption.ID, value: EVENT_TABLE.roleOnSubPull.name }, + { name: AutoPullSubsAtRoomStartToggleOption.ID, value: EVENT_TABLE.autoPullSubsAtRoomStartToggle.name }, + { name: ShuffleSubsBeforeAutoPullToggleOption.ID, value: EVENT_TABLE.shuffleSubsBeforeAutoPullToggle.name }, + { name: SubAutoPullModeOption.ID, value: EVENT_TABLE.subAutoPullMode.name }, { name: CreateDiscordEventToggleOption.ID, value: EVENT_TABLE.createDiscordEvent.name }, { name: DiscordEventDescriptionOption.ID, value: EVENT_TABLE.discordEventDescription.name }, + { name: `${WinnerRoleOption.ID} (does not revoke already-granted roles)`, value: EVENT_TABLE.winnerRoleId.name }, ]; const selectMenuTransactor = new SelectMenuTransactor(inter); const propertiesToReset = await selectMenuTransactor.sendAndReceive("Event properties to reset", selectMenuOptions) ?? []; @@ -1030,6 +1081,115 @@ export class EventsCommand extends AdminCommand { await inter.respond(`Deleted the ${eventMention(event)} event and all its queues.`, true); } + // ==================================================================== + // /events declare-winners + // ==================================================================== + + static readonly DECLARE_WINNERS_OPTIONS = { + event: new EventOption({ required: true, description: "Target event" }), + roomIndex: new RoomIndexOption({ required: true, description: "Room number (1..room count)" }), + winner1: new UserOption({ required: true, id: "winner_1", description: "A room winner" }), + winner2: new UserOption({ id: "winner_2", description: "A room winner" }), + winner3: new UserOption({ id: "winner_3", description: "A room winner" }), + winner4: new UserOption({ id: "winner_4", description: "A room winner" }), + winner5: new UserOption({ id: "winner_5", description: "A room winner" }), + }; + + static async events_declare_winners(inter: SlashInteraction) { + await inter.deferReply(); + const event = await EventsCommand.DECLARE_WINNERS_OPTIONS.event.get(inter); + if (!event.winnerRoleId) { + throw new WinnerRoleNotSetWarning(); + } + const roomIndex = EventsCommand.DECLARE_WINNERS_OPTIONS.roomIndex.get(inter); + if (roomIndex < 1 || BigInt(roomIndex) > event.roomCount) { + throw new RoomIndexNotFoundWarning(Number(event.roomCount)); + } + + const userIds = new Set(compact([ + EventsCommand.DECLARE_WINNERS_OPTIONS.winner1.get(inter), + EventsCommand.DECLARE_WINNERS_OPTIONS.winner2.get(inter), + EventsCommand.DECLARE_WINNERS_OPTIONS.winner3.get(inter), + EventsCommand.DECLARE_WINNERS_OPTIONS.winner4.get(inter), + EventsCommand.DECLARE_WINNERS_OPTIONS.winner5.get(inter), + ]).map(user => user.id)); + + const added = await WinnerUtils.declareRoomWinners(inter.store, event, BigInt(roomIndex), userIds); + + if (added.length === 0) { + await inter.respond(`No new winners added to room ${roomIndex} of ${eventMention(event)} — all selected users already win that room.`, true); + return; + } + + const mentions = added.map(userMention).join(", "); + await inter.respond( + `Granted ${roleMention(event.winnerRoleId)} to ${mentions} as winner(s) of room ${roomIndex} in ${eventMention(event)}.`, + true, + ); + } + + // ==================================================================== + // /events winners + // ==================================================================== + + static readonly WINNERS_OPTIONS = { + event: new EventOption({ required: true, description: "Target event" }), + }; + + static async events_winners(inter: SlashInteraction) { + await inter.deferReply({ ephemeral: true }); + const event = await EventsCommand.WINNERS_OPTIONS.event.get(inter); + + const grouped = groupWinnersByRoom(Queries.selectManyEventWinners({ guildId: inter.guildId, eventId: event.id })); + const roleLine = `Winner role: ${event.winnerRoleId ? roleMention(event.winnerRoleId) : "not set"}`; + + if (grouped.size === 0) { + await inter.respond(`No winners declared yet for ${eventMention(event)}.\n${roleLine}`); + return; + } + + const roomLines = [...grouped.entries()].map(([roomIndex, userIds]) => + `Room ${roomIndex}: ${userIds.map(userMention).join(", ")}` + ); + + const embed = new EmbedBuilder() + .setTitle(`Winners — ${event.name}`) + .setColor(Color.Gold) + .setDescription(`${roomLines.join("\n")}\n\n${roleLine}`); + + await inter.respond({ embeds: [embed] }); + } + + // ==================================================================== + // /events clear-winners + // ==================================================================== + + static readonly CLEAR_WINNERS_OPTIONS = { + event: new EventOption({ required: true, description: "Target event" }), + roomIndex: new RoomIndexOption({ description: "Room number to clear (omit = all rooms)" }), + }; + + static async events_clear_winners(inter: SlashInteraction) { + await inter.deferReply(); + const event = await EventsCommand.CLEAR_WINNERS_OPTIONS.event.get(inter); + const roomIndex = EventsCommand.CLEAR_WINNERS_OPTIONS.roomIndex.get(inter); + if (roomIndex != null && (roomIndex < 1 || BigInt(roomIndex) > event.roomCount)) { + throw new RoomIndexNotFoundWarning(Number(event.roomCount)); + } + + const removals = await WinnerUtils.clearEventWinners( + inter.store, + event, + roomIndex != null ? BigInt(roomIndex) : undefined, + ); + + const scope = roomIndex != null ? `room ${roomIndex}` : "all rooms"; + await inter.respond( + `Cleared winners for ${scope} of ${eventMention(event)}. Revoked the role from ${removals.length} member(s).`, + true, + ); + } + // ==================================================================== // /events help // ==================================================================== @@ -1061,6 +1221,14 @@ export class EventsCommand extends AdminCommand { "- `role_on_room_pull` (default `false`) — assign the role when a user is pulled from the room queue\n" + "- `role_in_sub_queue` (default `false`) — assign the role while a user is in the sub queue\n" + "- `role_on_sub_pull` (default `false`) — assign the role when a user is pulled from the sub queue\n\n" + + "**Declaring winners** — crown a room's winner(s) with one shared role that auto-revokes when the event's next occurrence opens:\n" + + `- Configure the role once via \`winner_role\` on ${commandMention("events", "set")}.\n` + + `- ${commandMention("events", "declare-winners")} (\`room_index\`, \`winner_1\`..\`winner_5\`) grants it — additive, ties allowed; call again for >5 winners.\n` + + `- ${commandMention("events", "winners")} lists winners per room; ${commandMention("events", "clear-winners")} (optional \`room_index\`) revokes early.\n\n` + + "**Auto-pull subs at room start:**\n" + + "- `auto_pull_subs_at_room_start_toggle` (default `false`) — at each room's start, lock paired sub and pull subs into the room. Forces room lock at exact `start_time` (ignores `lock_offset`).\n" + + "- `shuffle_subs_before_auto_pull_toggle` (default `false`) — shuffle the sub queue before the pull.\n" + + "- `sub_auto_pull_mode` (default `drain`) — `drain`: standard `/pull` side effects fire. `promote`: move into room queue (bypasses room lock), no sub-side pull effects.\n\n" + "**Extra per-room channels:**\n" + `- ${commandMention("events", "add-room-channel")} adds an extra per-room channel like \`room-code-{N}\`, with optional slowmode.\n` + `- ${commandMention("events", "remove-room-channel")} removes one of those templates and its channels.\n` + diff --git a/src/db/legacy-migration/migrate.ts b/src/db/legacy-migration/migrate.ts index 4307ed95..b468f3c7 100644 --- a/src/db/legacy-migration/migrate.ts +++ b/src/db/legacy-migration/migrate.ts @@ -99,7 +99,6 @@ export async function loadExportData() { await Promise.all(files.map(file => new Promise((resolve, reject) => { const data: any[] = []; fs.createReadStream(`${LEGACY_EXPORT_DIR}/${file}`) - // @ts-ignore .pipe(csv()) .on("data", (row) => { data.push(row); diff --git a/src/db/queries.ts b/src/db/queries.ts index f9dfee02..587520f3 100644 --- a/src/db/queries.ts +++ b/src/db/queries.ts @@ -10,6 +10,7 @@ import { EVENT_BLACKLISTED_TABLE, EVENT_DEFAULT_TABLE, EVENT_OCCURRENCE_ROOM_PING_TABLE, + EVENT_OCCURRENCE_ROOM_PULL_TABLE, EVENT_OCCURRENCE_TABLE, EVENT_PRIORITIZED_TABLE, EVENT_QUEUE_TABLE, @@ -17,6 +18,7 @@ import { EVENT_ROOM_CHANNEL_TEMPLATE_TABLE, EVENT_TABLE, EVENT_WHITELISTED_TABLE, + EVENT_WINNER_TABLE, GUILD_BLACKLISTED_TABLE, GUILD_PRIORITIZED_TABLE, GUILD_TABLE, @@ -342,7 +344,7 @@ export namespace Queries { // Guild Blacklisted export function selectManyGuildBlacklisted(by: - { guildId: Snowflake, subjectId?: Snowflake } + { guildId: Snowflake, subjectId?: Snowflake } ) { if ("subjectId" in by) { return selectManyGuildBlacklistedByGuildIdAndSubjectId.all(by); @@ -355,7 +357,7 @@ export namespace Queries { // Guild Whitelisted export function selectManyGuildWhitelisted(by: - { guildId: Snowflake, subjectId?: Snowflake } + { guildId: Snowflake, subjectId?: Snowflake } ) { if ("subjectId" in by) { return selectManyGuildWhitelistedByGuildIdAndSubjectId.all(by); @@ -368,7 +370,7 @@ export namespace Queries { // Guild Prioritized export function selectManyGuildPrioritized(by: - { guildId: Snowflake, subjectId?: Snowflake } + { guildId: Snowflake, subjectId?: Snowflake } ) { if ("subjectId" in by) { return selectManyGuildPrioritizedByGuildIdAndSubjectId.all(by); @@ -472,6 +474,12 @@ export namespace Queries { return selectOccurrenceRoomPingsByOccurrenceId.all(by); } + // Event Occurrence Room Pulls + + export function selectOccurrenceRoomPulls(by: { occurrenceId: bigint }) { + return selectOccurrenceRoomPullsByOccurrenceId.all(by); + } + // Event Queues export function selectManyEventQueues(by: { guildId: Snowflake, eventId: bigint }) { @@ -492,6 +500,12 @@ export namespace Queries { return row ? Number(row.count) : 0; } + // Event Winners + + export function selectManyEventWinners(by: { guildId: Snowflake, eventId: bigint }) { + return selectManyEventWinnersByGuildIdAndEventId.all(by); + } + // Event Defaults export function selectEventDefault(by: { guildId: Snowflake, eventId: bigint, queueRole: string }) { @@ -1192,6 +1206,16 @@ export namespace Queries { ) .prepare(); + // Event Occurrence Room Pulls + + const selectOccurrenceRoomPullsByOccurrenceId = db + .select() + .from(EVENT_OCCURRENCE_ROOM_PULL_TABLE) + .where( + eq(EVENT_OCCURRENCE_ROOM_PULL_TABLE.occurrenceId, sql.placeholder("occurrenceId")) + ) + .prepare(); + // Event Queues const selectManyEventQueuesByGuildIdAndEventId = db @@ -1224,6 +1248,17 @@ export namespace Queries { )) .prepare(); + // Event Winners + + const selectManyEventWinnersByGuildIdAndEventId = db + .select() + .from(EVENT_WINNER_TABLE) + .where(and( + eq(EVENT_WINNER_TABLE.guildId, sql.placeholder("guildId")), + eq(EVENT_WINNER_TABLE.eventId, sql.placeholder("eventId")) + )) + .prepare(); + // Event Defaults const selectEventDefaultByEventIdAndRole = db diff --git a/src/db/schema.ts b/src/db/schema.ts index dbb48738..a3a94451 100644 --- a/src/db/schema.ts +++ b/src/db/schema.ts @@ -12,6 +12,7 @@ import { RoomScheduling, ScheduleCommand, Scope, + SubAutoPullMode, TimestampType, } from "../types/db.types.ts"; @@ -184,8 +185,12 @@ export const EVENT_TABLE = sqliteTable("event", ({ roleOnRoomPull: integer("role_on_room_pull", { mode: "boolean" }).notNull().default(false), roleInSubQueue: integer("role_in_sub_queue", { mode: "boolean" }).notNull().default(false), roleOnSubPull: integer("role_on_sub_pull", { mode: "boolean" }).notNull().default(false), + autoPullSubsAtRoomStartToggle: integer("auto_pull_subs_at_room_start_toggle", { mode: "boolean" }).notNull().default(false), + shuffleSubsBeforeAutoPullToggle: integer("shuffle_subs_before_auto_pull_toggle", { mode: "boolean" }).notNull().default(false), + subAutoPullMode: text("sub_auto_pull_mode").$type().notNull().default(SubAutoPullMode.Drain), createDiscordEvent: integer("create_discord_event", { mode: "boolean" }).notNull().default(true), discordEventDescription: text("discord_event_description"), + winnerRoleId: text("winner_role_id").$type(), }), (table) => ({ unq: unique().on(table.name, table.guildId), @@ -233,6 +238,22 @@ export type NewEventOccurrenceRoomPing = typeof EVENT_OCCURRENCE_ROOM_PING_TABLE export type DbEventOccurrenceRoomPing = typeof EVENT_OCCURRENCE_ROOM_PING_TABLE.$inferSelect; +export const EVENT_OCCURRENCE_ROOM_PULL_TABLE = sqliteTable("event_occurrence_room_pull", ({ + occurrenceId: integer("occurrence_id").$type().notNull() + .references(() => EVENT_OCCURRENCE_TABLE.id, { onDelete: "cascade" }), + eventQueueId: integer("event_queue_id").$type().notNull() + .references(() => EVENT_QUEUE_TABLE.id, { onDelete: "cascade" }), + handledAt: integer("handled_at").$type().notNull(), +}), +(table) => ({ + pk: primaryKey({ columns: [table.occurrenceId, table.eventQueueId] }), + occurrenceIdIndex: index("event_occurrence_room_pull_occurrence_id_index").on(table.occurrenceId), +})); + +export type NewEventOccurrenceRoomPull = typeof EVENT_OCCURRENCE_ROOM_PULL_TABLE.$inferInsert; +export type DbEventOccurrenceRoomPull = typeof EVENT_OCCURRENCE_ROOM_PULL_TABLE.$inferSelect; + + export const EVENT_QUEUE_TABLE = sqliteTable("event_queue", ({ id: integer("id").$type().primaryKey({ autoIncrement: true }), @@ -255,6 +276,26 @@ export type NewEventQueue = typeof EVENT_QUEUE_TABLE.$inferInsert; export type DbEventQueue = typeof EVENT_QUEUE_TABLE.$inferSelect; +export const EVENT_WINNER_TABLE = sqliteTable("event_winner", ({ + id: integer("id").$type().primaryKey({ autoIncrement: true }), + + guildId: text("guild_id").$type().notNull().references(() => GUILD_TABLE.guildId, { onDelete: "cascade" }), + eventId: integer("event_id").$type().notNull().references(() => EVENT_TABLE.id, { onDelete: "cascade" }), + roomIndex: integer("room_index").$type().notNull(), + userId: text("user_id").$type().notNull(), + roleId: text("role_id").$type().notNull(), + declaredAt: integer("declared_at").$type().notNull().$defaultFn(() => BigInt(Date.now())), +}), +(table) => ({ + unq: unique().on(table.eventId, table.roomIndex, table.userId), + guildIdIndex: index("event_winner_guild_id_index").on(table.guildId), + eventIdIndex: index("event_winner_event_id_index").on(table.eventId), +})); + +export type NewEventWinner = typeof EVENT_WINNER_TABLE.$inferInsert; +export type DbEventWinner = typeof EVENT_WINNER_TABLE.$inferSelect; + + export const EVENT_DEFAULT_TABLE = sqliteTable("event_default", ({ id: integer("id").$type().primaryKey({ autoIncrement: true }), diff --git a/src/db/store.ts b/src/db/store.ts index 46b50df3..61bdc172 100644 --- a/src/db/store.ts +++ b/src/db/store.ts @@ -30,11 +30,13 @@ import { type DbEventBlacklisted, type DbEventOccurrence, type DbEventOccurrenceRoomPing, + type DbEventOccurrenceRoomPull, type DbEventPrioritized, type DbEventQueue, type DbEventRoomChannel, type DbEventRoomChannelTemplate, type DbEventWhitelisted, + type DbEventWinner, type DbGuildBlacklisted, type DbGuildPrioritized, type DbGuildWhitelisted, @@ -48,6 +50,7 @@ import { EVENT_BLACKLISTED_TABLE, EVENT_DEFAULT_TABLE, EVENT_OCCURRENCE_ROOM_PING_TABLE, + EVENT_OCCURRENCE_ROOM_PULL_TABLE, EVENT_OCCURRENCE_TABLE, EVENT_PRIORITIZED_TABLE, EVENT_QUEUE_TABLE, @@ -55,6 +58,7 @@ import { EVENT_ROOM_CHANNEL_TEMPLATE_TABLE, EVENT_TABLE, EVENT_WHITELISTED_TABLE, + EVENT_WINNER_TABLE, GUILD_BLACKLISTED_TABLE, GUILD_PRIORITIZED_TABLE, GUILD_TABLE, @@ -69,11 +73,13 @@ import { type NewEventDefault, type NewEventOccurrence, type NewEventOccurrenceRoomPing, + type NewEventOccurrenceRoomPull, type NewEventPrioritized, type NewEventQueue, type NewEventRoomChannel, type NewEventRoomChannelTemplate, type NewEventWhitelisted, + type NewEventWinner, type NewGuild, type NewGuildBlacklisted, type NewGuildPrioritized, @@ -582,6 +588,15 @@ export class Store { .returning().get(); } + // idempotent: composite PK conflict is a no-op + insertOccurrenceRoomPull(row: NewEventOccurrenceRoomPull): DbEventOccurrenceRoomPull { + return db + .insert(EVENT_OCCURRENCE_ROOM_PULL_TABLE) + .values(row) + .onConflictDoNothing() + .returning().get(); + } + // upsert on conflict insertEventDefault(newEventDefault: NewEventDefault) { const values = omitBy(newEventDefault, isNil) as NewEventDefault; @@ -615,6 +630,15 @@ export class Store { .returning().get(); } + // idempotent additive declare: (eventId, roomIndex, userId) conflict is a no-op + insertEventWinner(row: NewEventWinner): DbEventWinner { + return db + .insert(EVENT_WINNER_TABLE) + .values(omitBy(row, isNil) as NewEventWinner) + .onConflictDoNothing() + .returning().get(); + } + // ==================================================================== // Condition helper // ==================================================================== @@ -1187,4 +1211,18 @@ export class Store { .where(and(...conds)) .returning().all(); } + + deleteManyEventWinners(by: { eventId: bigint, roomIndex?: bigint }) { + const conds = [ + eq(EVENT_WINNER_TABLE.guildId, this.guild.id), + eq(EVENT_WINNER_TABLE.eventId, by.eventId), + ]; + if (by.roomIndex !== undefined) { + conds.push(eq(EVENT_WINNER_TABLE.roomIndex, by.roomIndex)); + } + return db + .delete(EVENT_WINNER_TABLE) + .where(and(...conds)) + .returning().all(); + } } diff --git a/src/options/options.loader.ts b/src/options/options.loader.ts index 63664912..16c5da14 100644 --- a/src/options/options.loader.ts +++ b/src/options/options.loader.ts @@ -5,6 +5,7 @@ import { AdminOption } from "./options/admin.option.ts"; import { AdminsOption } from "./options/admins.option.ts"; import { AnnouncementChannelOption } from "./options/announcement-channel.option.ts"; import { AnnouncementMessageOption } from "./options/announcement-message.option.ts"; +import { AutoPullSubsAtRoomStartToggleOption } from "./options/auto-pull-subs-at-room-start-toggle.option.ts"; import { AutopullToggleOption } from "./options/autopull-toggle.option.ts"; import { BadgeToggleOption } from "./options/badge-toggle.option.ts"; import { BlacklistedOption } from "./options/blacklisted.option.ts"; @@ -68,6 +69,7 @@ import { RoleOnRoomPullOption } from "./options/role-on-room-pull.option.ts"; import { RoleOnSubPullOption } from "./options/role-on-sub-pull.option.ts"; import { RoomCategoryOption } from "./options/room-category.option.ts"; import { RoomCountOption } from "./options/room-count.option.ts"; +import { RoomIndexOption } from "./options/room-index.option.ts"; import { RoomLengthMinutesOption } from "./options/room-length-minutes.option.ts"; import { RoomPingMessageOption } from "./options/room-ping-message.option.ts"; import { RoomQueuesChannelOption } from "./options/room-queues-channel.option.ts"; @@ -75,10 +77,12 @@ import { RoomSchedulingOption } from "./options/room-scheduling.option.ts"; import { ScheduleOption } from "./options/schedule.option.ts"; import { SchedulesOption } from "./options/schedules.option.ts"; import { ScopeOption } from "./options/scope.option.ts"; +import { ShuffleSubsBeforeAutoPullToggleOption } from "./options/shuffle-subs-before-auto-pull-toggle.option.ts"; import { SizeOption } from "./options/size.option.ts"; import { SlowmodeOption } from "./options/slowmode.option.ts"; import { SlowmodeTimeOption } from "./options/slowmode-time.option.ts"; import { StartTimeOption } from "./options/start-time.option.ts"; +import { SubAutoPullModeOption } from "./options/sub-auto-pull-mode.option.ts"; import { SubQueuesChannelOption } from "./options/sub-queues-channel.option.ts"; import { TimestampTypeOption } from "./options/timestamp-type.option.ts"; import { TimezoneOption } from "./options/timezone.option.ts"; @@ -89,6 +93,7 @@ import { VoiceSourceChannelOption } from "./options/voice-source-channel.option. import { VoicesOption } from "./options/voices.option.ts"; import { WhitelistedOption } from "./options/whitelisted.option.ts"; import { WhitelistedsOption } from "./options/whitelisteds.option.ts"; +import { WinnerRoleOption } from "./options/winner-role.option.ts"; import { YearOption } from "./options/year.option.ts"; export const OPTIONS = new Collection([ @@ -96,6 +101,7 @@ export const OPTIONS = new Collection([ [AdminsOption.ID, new AdminsOption()], [AnnouncementChannelOption.ID, new AnnouncementChannelOption()], [AnnouncementMessageOption.ID, new AnnouncementMessageOption()], + [AutoPullSubsAtRoomStartToggleOption.ID, new AutoPullSubsAtRoomStartToggleOption()], [AutopullToggleOption.ID, new AutopullToggleOption()], [BadgeToggleOption.ID, new BadgeToggleOption()], [BlacklistedOption.ID, new BlacklistedOption()], @@ -156,6 +162,7 @@ export const OPTIONS = new Collection([ [RoleOnSubPullOption.ID, new RoleOnSubPullOption()], [RoomCategoryOption.ID, new RoomCategoryOption()], [RoomCountOption.ID, new RoomCountOption()], + [RoomIndexOption.ID, new RoomIndexOption()], [RoomLengthMinutesOption.ID, new RoomLengthMinutesOption()], [RoomPingMessageOption.ID, new RoomPingMessageOption()], [RoomQueuesChannelOption.ID, new RoomQueuesChannelOption()], @@ -166,10 +173,12 @@ export const OPTIONS = new Collection([ [ScheduleOption.ID, new ScheduleOption()], [SchedulesOption.ID, new SchedulesOption()], [ScopeOption.ID, new ScopeOption()], + [ShuffleSubsBeforeAutoPullToggleOption.ID, new ShuffleSubsBeforeAutoPullToggleOption()], [SizeOption.ID, new SizeOption()], [SlowmodeOption.ID, new SlowmodeOption()], [SlowmodeTimeOption.ID, new SlowmodeTimeOption()], [StartTimeOption.ID, new StartTimeOption()], + [SubAutoPullModeOption.ID, new SubAutoPullModeOption()], [SubQueuesChannelOption.ID, new SubQueuesChannelOption()], [TimestampTypeOption.ID, new TimestampTypeOption()], [TimezoneOption.ID, new TimezoneOption()], @@ -181,5 +190,6 @@ export const OPTIONS = new Collection([ [VoiceOnlyToggleOption.ID, new VoiceOnlyToggleOption()], [WhitelistedOption.ID, new WhitelistedOption()], [WhitelistedsOption.ID, new WhitelistedsOption()], + [WinnerRoleOption.ID, new WinnerRoleOption()], [YearOption.ID, new YearOption()], ]); diff --git a/src/options/options/admins.option.ts b/src/options/options/admins.option.ts index 8592ad0f..3c661255 100644 --- a/src/options/options/admins.option.ts +++ b/src/options/options/admins.option.ts @@ -30,9 +30,10 @@ export class AdminsOption extends CustomOption { return admins; case CHOICE_SOME.value: return await this.getViaSelectMenu(inter as SlashInteraction, admins); - default: + default: { const admin = AdminOption.findAdmin(admins, inputString); return admin ? new Collection([[admin.id, admin]]) : null; + } } } diff --git a/src/options/options/auto-pull-subs-at-room-start-toggle.option.ts b/src/options/options/auto-pull-subs-at-room-start-toggle.option.ts new file mode 100644 index 00000000..cc913f81 --- /dev/null +++ b/src/options/options/auto-pull-subs-at-room-start-toggle.option.ts @@ -0,0 +1,8 @@ +import { EVENT_TABLE } from "../../db/schema.ts"; +import { BooleanOption } from "../base-option.ts"; + +export class AutoPullSubsAtRoomStartToggleOption extends BooleanOption { + static readonly ID = "auto_pull_subs_at_room_start_toggle"; + id = AutoPullSubsAtRoomStartToggleOption.ID; + defaultValue = EVENT_TABLE.autoPullSubsAtRoomStartToggle.default; +} diff --git a/src/options/options/displays.option.ts b/src/options/options/displays.option.ts index 57dde9c1..8ba50c51 100644 --- a/src/options/options/displays.option.ts +++ b/src/options/options/displays.option.ts @@ -31,9 +31,10 @@ export class DisplaysOption extends CustomOption { return displays; case CHOICE_SOME.value: return await this.getViaSelectMenu(inter as SlashInteraction, displays); - default: + default: { const display = DisplayOption.findDisplay(displays, inputString); return display ? new Collection([[display.id, display]]) : null; + } } } diff --git a/src/options/options/events.option.ts b/src/options/options/events.option.ts index 5dd19e36..96269417 100644 --- a/src/options/options/events.option.ts +++ b/src/options/options/events.option.ts @@ -29,9 +29,10 @@ export class EventsOption extends CustomOption { return events; case CHOICE_SOME.value: return await this.getViaSelectMenu(inter as SlashInteraction, events); - default: + default: { const event = EventOption.findEvent(events, inputString); return event ? new Collection([[event.id, event]]) : null; + } } } diff --git a/src/options/options/members.option.ts b/src/options/options/members.option.ts index 9efefabe..daeab56d 100644 --- a/src/options/options/members.option.ts +++ b/src/options/options/members.option.ts @@ -31,9 +31,10 @@ export class MembersOption extends CustomOption { return members; case CHOICE_SOME.value: return await this.getViaSelectMenu(inter as SlashInteraction, members); - default: + default: { const member = MemberOption.findMember(members, inputString); return member ? new Collection([[member.id, member]]) : null; + } } } diff --git a/src/options/options/queues.option.ts b/src/options/options/queues.option.ts index 69e6bcb6..4aa953d9 100644 --- a/src/options/options/queues.option.ts +++ b/src/options/options/queues.option.ts @@ -29,9 +29,10 @@ export class QueuesOption extends CustomOption { return scopedQueues; case CHOICE_SOME.value: return await this.getViaSelectMenu(inter as SlashInteraction, scopedQueues); - default: + default: { const queue = QueueOption.findQueue(scopedQueues, inputString); return queue ? new Collection([[queue.id, queue]]) : null; + } } } diff --git a/src/options/options/room-index.option.ts b/src/options/options/room-index.option.ts new file mode 100644 index 00000000..e7789c0b --- /dev/null +++ b/src/options/options/room-index.option.ts @@ -0,0 +1,7 @@ +import { IntegerOption } from "../base-option.ts"; + +export class RoomIndexOption extends IntegerOption { + static readonly ID = "room_index"; + id = RoomIndexOption.ID; + minValue = 1; +} diff --git a/src/options/options/schedules.option.ts b/src/options/options/schedules.option.ts index bd51c59d..b89252f3 100644 --- a/src/options/options/schedules.option.ts +++ b/src/options/options/schedules.option.ts @@ -31,9 +31,10 @@ export class SchedulesOption extends CustomOption { return schedules; case CHOICE_SOME.value: return await this.getViaSelectMenu(inter as SlashInteraction, schedules); - default: + default: { const schedule = ScheduleOption.findSchedule(schedules, inputString); return schedule ? new Collection([[schedule.id, schedule]]) : null; + } } } diff --git a/src/options/options/shuffle-subs-before-auto-pull-toggle.option.ts b/src/options/options/shuffle-subs-before-auto-pull-toggle.option.ts new file mode 100644 index 00000000..7ba0d62d --- /dev/null +++ b/src/options/options/shuffle-subs-before-auto-pull-toggle.option.ts @@ -0,0 +1,8 @@ +import { EVENT_TABLE } from "../../db/schema.ts"; +import { BooleanOption } from "../base-option.ts"; + +export class ShuffleSubsBeforeAutoPullToggleOption extends BooleanOption { + static readonly ID = "shuffle_subs_before_auto_pull_toggle"; + id = ShuffleSubsBeforeAutoPullToggleOption.ID; + defaultValue = EVENT_TABLE.shuffleSubsBeforeAutoPullToggle.default; +} diff --git a/src/options/options/sub-auto-pull-mode.option.ts b/src/options/options/sub-auto-pull-mode.option.ts new file mode 100644 index 00000000..09199a4b --- /dev/null +++ b/src/options/options/sub-auto-pull-mode.option.ts @@ -0,0 +1,11 @@ +import { SubAutoPullMode } from "../../types/db.types.ts"; +import { StringOption } from "../base-option.ts"; + +export class SubAutoPullModeOption extends StringOption { + static readonly ID = "sub_auto_pull_mode"; + id = SubAutoPullModeOption.ID; + choices = [ + { name: "Drain (standard /pull)", value: SubAutoPullMode.Drain }, + { name: "Promote (move to room queue)", value: SubAutoPullMode.Promote }, + ]; +} diff --git a/src/options/options/timezone.option.ts b/src/options/options/timezone.option.ts index b1b01063..8fec1cc8 100644 --- a/src/options/options/timezone.option.ts +++ b/src/options/options/timezone.option.ts @@ -28,7 +28,7 @@ export class TimezoneOption extends CustomOption { if (filtered.length < MAX_SELECT_MENU_OPTIONS) { sampled = filtered; } - else { + else { const groups = groupBy(filtered, tz => tz.split("/")[0]); for (let i = 0; sampled.length < MAX_SELECT_MENU_OPTIONS; i++) { for (const group of Object.values(groups)) { diff --git a/src/options/options/voices.option.ts b/src/options/options/voices.option.ts index 17b29bb1..f3b0c3a5 100644 --- a/src/options/options/voices.option.ts +++ b/src/options/options/voices.option.ts @@ -31,9 +31,10 @@ export class VoicesOption extends CustomOption { return voices; case CHOICE_SOME.value: return await this.getViaSelectMenu(inter as SlashInteraction, voices); - default: + default: { const voice = VoiceOption.findVoice(voices, inputString); return voice ? new Collection([[voice.id, voice]]) : null; + } } } diff --git a/src/options/options/winner-role.option.ts b/src/options/options/winner-role.option.ts new file mode 100644 index 00000000..ceb92895 --- /dev/null +++ b/src/options/options/winner-role.option.ts @@ -0,0 +1,6 @@ +import { RoleOption } from "../base-option.ts"; + +export class WinnerRoleOption extends RoleOption { + static readonly ID = "winner_role"; + id = WinnerRoleOption.ID; +} diff --git a/src/types/db.types.ts b/src/types/db.types.ts index 57a4240c..8188df18 100644 --- a/src/types/db.types.ts +++ b/src/types/db.types.ts @@ -93,4 +93,9 @@ export enum RoomScheduling { Sequential = "sequential", } +export enum SubAutoPullMode { + Drain = "drain", + Promote = "promote", +} + export type GuildStat = keyof Omit; \ No newline at end of file diff --git a/src/types/interaction.types.ts b/src/types/interaction.types.ts index 360410fe..1785e68a 100644 --- a/src/types/interaction.types.ts +++ b/src/types/interaction.types.ts @@ -19,13 +19,13 @@ interface BaseProperties { type AutocompleteProperties = BaseProperties & { parser: Parser; -} +}; type RespondableProperties = BaseProperties & { parser: Parser; promptConfirmOrCancel?: (message: string) => Promise; respond: (message: InteractionReplyOptions | string, log?: boolean) => Promise; -} +}; type DiscordResponseFn = "send" | "reply" | "followUp"; diff --git a/src/types/misc.types.ts b/src/types/misc.types.ts index 3d97e9cc..eb4c3e1c 100644 --- a/src/types/misc.types.ts +++ b/src/types/misc.types.ts @@ -27,6 +27,6 @@ export type PendingGuildUpdates = { [K in Snowflake]?: { [P in GuildStat]?: number; }; -} +}; export type ArrayOrCollection = V[] | Collection; diff --git a/src/utils/error.utils.ts b/src/utils/error.utils.ts index 549cdc1b..76dd59c4 100644 --- a/src/utils/error.utils.ts +++ b/src/utils/error.utils.ts @@ -154,6 +154,13 @@ export class EventAlreadyExistsWarning extends AbstractWarning { message = "An event with that name already exists in this server"; } +export class WinnerRoleNotSetWarning extends AbstractWarning { + message = "No winner role is configured for this event"; + embeds = [ + new EmbedBuilder().setDescription(`Set one with ${commandMention("events", "set")} (the \`winner_role\` option) before declaring winners.`), + ]; +} + export class OccurrenceAlreadyExistsWarning extends AbstractWarning { message = "An occurrence with that start time already exists for this event"; } diff --git a/src/utils/event.utils.ts b/src/utils/event.utils.ts index 78fc77d2..c0c21c5a 100644 --- a/src/utils/event.utils.ts +++ b/src/utils/event.utils.ts @@ -25,7 +25,7 @@ import { QUEUE_TABLE, } from "../db/schema.ts"; import { Store } from "../db/store.ts"; -import { DisplayUpdateType, EventQueueRole, MemberRemovalReason, RoomScheduling } from "../types/db.types.ts"; +import { DisplayUpdateType, EventQueueRole, MemberRemovalReason, RoomScheduling, SubAutoPullMode } from "../types/db.types.ts"; import { ClientUtils } from "./client.utils.ts"; import { DisplayUtils } from "./display.utils.ts"; import { @@ -40,6 +40,7 @@ import { EventChannelUtils } from "./event-channel.utils.ts"; import { EventSyncLock } from "./event-sync-lock.utils.ts"; import { MemberUtils } from "./member.utils.ts"; import { QueueUtils } from "./queue.utils.ts"; +import { WinnerUtils } from "./winner.utils.ts"; export namespace EventUtils { @@ -52,6 +53,7 @@ export namespace EventUtils { lock?: Job; cleanup?: Job; roomPings: Map; + roomPulls: Map; } const occurrenceIdToJobs = new Map(); @@ -142,7 +144,10 @@ export namespace EventUtils { || update.cleanupOffsetMs !== undefined || update.roomScheduling !== undefined || update.roomLengthMs !== undefined - || update.roomCount !== undefined; + || update.roomCount !== undefined + || update.autoPullSubsAtRoomStartToggle !== undefined + || update.shuffleSubsBeforeAutoPullToggle !== undefined + || update.subAutoPullMode !== undefined; if (timingChanged) { await rearmAllOccurrences(store, updatedEvent); @@ -252,7 +257,6 @@ export namespace EventUtils { let recreatedCount = 0; let reappliedRoomCount = 0; let reappliedSubCount = 0; - let reshownCount = 0; const roomCount = Number(event.roomCount); const roles: EventQueueRole[] = [EventQueueRole.Room, EventQueueRole.Sub]; @@ -338,7 +342,7 @@ export namespace EventUtils { } // Step C — re-show every queue display in queue-index order in the event's display channels. - reshownCount = await reshowEventQueueDisplays(store, event); + const reshownCount = await reshowEventQueueDisplays(store, event); // Step D — reconcile channels + auto-created room roles if (event.roomCategoryId) { @@ -450,6 +454,7 @@ export namespace EventUtils { // True iff any of the event's occurrences has a window (role-dependent) that contains `nowMs`. // Room window: [start − createOffsetMs, start + lockOffsetMs). Sub window extends to cleanup. + // When autoPullSubsAtRoomStartToggle is on, the room lock fires at exact start (lockOffsetMs is ignored). // Empty occurrence list → false (covers `/events add` before any occurrence is scheduled). function shouldEventQueueBeUnlocked( event: DbEvent, @@ -461,19 +466,31 @@ export namespace EventUtils { const start = Number(occ.startTime); const openAt = start - Number(event.createOffsetMs); const closeAt = role === EventQueueRole.Room - ? start + Number(event.lockOffsetMs) + ? (event.autoPullSubsAtRoomStartToggle ? start : start + Number(event.lockOffsetMs)) : getRoomsFinishMs(event, start) + Number(event.cleanupOffsetMs); return nowMs >= openAt && nowMs < closeAt; }); } + function computeRoomPingAt(event: DbEvent, startMs: number, queueIndex: bigint): number { + if (event.roomScheduling === RoomScheduling.Sequential && event.roomLengthMs) { + return startMs + (Number(queueIndex) - 1) * Number(event.roomLengthMs); + } + return startMs; + } + async function armOccurrence(event: DbEvent, occurrence: DbEventOccurrence) { unregisterJobs(occurrence.id); const now = Date.now(); const startMs = Number(occurrence.startTime); const openAt = startMs - Number(event.createOffsetMs); - const lockAt = startMs + Number(event.lockOffsetMs); + // When autoPullSubsAtRoomStartToggle is on, the room queue must lock at exact startTime so the + // per-room auto-pull (which locks the paired sub queue) sees a consistent snapshot. lockOffsetMs + // is preserved on the schema for the legacy path but ignored here. + const lockAt = event.autoPullSubsAtRoomStartToggle + ? startMs + : startMs + Number(event.lockOffsetMs); const cleanupAt = getRoomsFinishMs(event, startMs) + Number(event.cleanupOffsetMs); const guild = await ClientUtils.getGuild(occurrence.guildId); @@ -483,8 +500,11 @@ export namespace EventUtils { const pingedQueueIds = new Set( Queries.selectOccurrenceRoomPings({ occurrenceId: occurrence.id }).map(r => r.eventQueueId) ); + const pulledRoomIds = new Set( + Queries.selectOccurrenceRoomPulls({ occurrenceId: occurrence.id }).map(r => r.eventQueueId) + ); - const jobs: OccurrenceJobs = { roomPings: new Map() }; + const jobs: OccurrenceJobs = { roomPings: new Map(), roomPulls: new Map() }; // Open action jobs.open = await armPhase( @@ -506,18 +526,12 @@ export namespace EventUtils { "lock", ); - // Room pings - const eventQueues = Queries.selectManyEventQueues({ guildId: event.guildId, eventId: event.id }) + // Room pings (and optional room-start auto-pulls) + const roomEventQueues = Queries.selectManyEventQueues({ guildId: event.guildId, eventId: event.id }) .filter(eq => eq.queueRole === EventQueueRole.Room); - for (const eq of eventQueues) { - let pingAt: number; - if (event.roomScheduling === RoomScheduling.Sequential && event.roomLengthMs) { - pingAt = startMs + (Number(eq.queueIndex) - 1) * Number(event.roomLengthMs); - } - else { - pingAt = startMs; - } + for (const eq of roomEventQueues) { + const pingAt = computeRoomPingAt(event, startMs, eq.queueIndex); const pingJob = await armPhase( pingAt, @@ -534,6 +548,26 @@ export namespace EventUtils { if (pingJob) jobs.roomPings.set(eq.id, pingJob); } + if (event.autoPullSubsAtRoomStartToggle) { + for (const eq of roomEventQueues) { + const pullAt = computeRoomPingAt(event, startMs, eq.queueIndex); + + const pullJob = await armPhase( + pullAt, + now, + pulledRoomIds.has(eq.id), + () => runRoomPullAction(occurrence.id, eq), + () => store.insertOccurrenceRoomPull({ + occurrenceId: occurrence.id, + eventQueueId: eq.id, + handledAt: BigInt(Date.now()), + }), + "room pull", + ); + if (pullJob) jobs.roomPulls.set(eq.id, pullJob); + } + } + // Cleanup action — no flag needed; cleanup deletes the row (cascades the junction) if (cleanupAt <= now) { await runCleanupAction(occurrence.id); @@ -555,6 +589,7 @@ export namespace EventUtils { jobs.lock?.cancel(); jobs.cleanup?.cancel(); jobs.roomPings.forEach(job => job.cancel()); + jobs.roomPulls.forEach(job => job.cancel()); occurrenceIdToJobs.delete(occurrenceId); } @@ -656,6 +691,9 @@ export namespace EventUtils { if (!ctx) return; const { occurrence, event, store, queues } = ctx; + // Revoke the previous occurrence's winner roles — the badge lasts only until the next opens. + await WinnerUtils.revokeEventWinners(store, event); + // Unlock all event queues if (queues.length > 0) { await QueueUtils.updateQueues(store, queues, { lockToggle: false } as Partial); @@ -736,6 +774,93 @@ export namespace EventUtils { } } + async function runRoomPullAction(occurrenceId: bigint, roomEventQueue: DbEventQueue) { + const ctx = await getEventContext(occurrenceId); + if (!ctx) return; + const { event, store, eventQueues } = ctx; + + const subEventQueue = eventQueues.find(eq => + eq.queueRole === EventQueueRole.Sub && eq.queueIndex === roomEventQueue.queueIndex + ); + if (!subEventQueue) { + console.warn(`EventUtils.runRoomPullAction: no paired sub event-queue for room index ${roomEventQueue.queueIndex} of event ${event.id} — skipping`); + return; + } + + const roomQueue = Queries.selectQueue({ guildId: store.guild.id, id: roomEventQueue.queueId }); + const subQueue = Queries.selectQueue({ guildId: store.guild.id, id: subEventQueue.queueId }); + if (!roomQueue || !subQueue) { + console.warn(`EventUtils.runRoomPullAction: missing queue rows for event ${event.id} room index ${roomEventQueue.queueIndex} — skipping`); + return; + } + + // Always lock the paired sub queue first — auto-pull bundles sub-lock atomically. + await QueueUtils.updateQueues(store, [subQueue], { lockToggle: true } as Partial); + + if (event.shuffleSubsBeforeAutoPullToggle) { + await MemberUtils.shuffleMembers(store, subQueue, undefined); + } + + const currentRoomCount = Queries.selectManyMembers({ guildId: store.guild.id, queueId: roomQueue.id }).length; + const subAvailable = Queries.selectManyMembers({ guildId: store.guild.id, queueId: subQueue.id }).length; + const count = roomQueue.size == null + ? subAvailable + : Math.min(Number(roomQueue.size) - currentRoomCount, subAvailable); + + if (count <= 0) { + console.log(`EventUtils.runRoomPullAction: nothing to pull for event ${event.id} room index ${roomEventQueue.queueIndex} (currentRoomCount=${currentRoomCount}, subAvailable=${subAvailable}, size=${roomQueue.size}) — skipping pull`); + return; + } + + if (event.subAutoPullMode === SubAutoPullMode.Promote) { + const subMembers = Queries.selectManyMembers({ + guildId: store.guild.id, + queueId: subQueue.id, + count, + }); + for (const subMember of subMembers) { + const jsMember = await store.jsMember(subMember.userId); + if (!jsMember) continue; + + // Delete from sub queue directly via store (skips MemberUtils.deleteMembers messaging, + // DM-on-pull, voice destination, and role-on-pull side effects — we promote silently). + store.deleteMember({ id: subMember.id }, MemberRemovalReason.Pulled); + + if (subQueue.roleInQueueId) { + await MemberUtils.modifyMemberRoles(store, subMember.userId, subQueue.roleInQueueId, "remove") + .catch(e => console.error(`EventUtils.runRoomPullAction: failed to remove sub roleInQueueId from user ${subMember.userId}:`, e)); + } + + try { + // force:true bypasses verifyMemberEligibility so the room queue's lockToggle=true + // (set by runLockAction) does not block this system insert. + await MemberUtils.insertMember({ + store, + queue: roomQueue, + jsMember, + message: subMember.message ?? undefined, + force: true, + }); + } + catch (e) { + console.error(`EventUtils.runRoomPullAction: failed to promote user ${subMember.userId} into room queue ${roomQueue.id}:`, e); + } + } + await DisplayUtils.requestDisplayUpdate({ store, queueId: subQueue.id }); + await DisplayUtils.requestDisplayUpdate({ store, queueId: roomQueue.id }); + } + else { + await MemberUtils.deleteMembers({ + store, + queues: [subQueue], + reason: MemberRemovalReason.Pulled, + by: { count }, + force: true, + }); + await DisplayUtils.requestDisplayUpdate({ store, queueId: roomQueue.id }); + } + } + async function runCleanupAction(occurrenceId: bigint) { const ctx = await getEventContext(occurrenceId); if (!ctx) return; diff --git a/src/utils/winner.logic.test.ts b/src/utils/winner.logic.test.ts new file mode 100644 index 00000000..b5a1e3fa --- /dev/null +++ b/src/utils/winner.logic.test.ts @@ -0,0 +1,72 @@ +import { describe, expect, it } from "vitest"; + +import type { DbEventWinner } from "../db/schema.ts"; +import { computeRoleRemovals, computeWinnersToAdd, groupWinnersByRoom } from "./winner.logic.ts"; + +function winnerRow(overrides: Partial): DbEventWinner { + return { + id: 1n, + guildId: "g", + eventId: 1n, + roomIndex: 1n, + userId: "u", + roleId: "r", + declaredAt: 0n, + ...overrides, + }; +} + +describe("computeWinnersToAdd", () => { + it("dedupes repeated requested users", () => { + expect(computeWinnersToAdd(new Set(), new Set(["a", "a", "b"]))).toEqual(["a", "b"]); + }); + + it("returns [] when every requested user is already a winner", () => { + expect(computeWinnersToAdd(new Set(["a", "b"]), new Set(["a", "b"]))).toEqual([]); + }); + + it("returns only the requested users not already winners", () => { + expect(computeWinnersToAdd(new Set(["a"]), new Set(["a", "b", "c"]))).toEqual(["b", "c"]); + }); +}); + +describe("computeRoleRemovals", () => { + it("does not remove a user who still has a remaining row (multi-room win)", () => { + const deleted = [{ userId: "a", roleId: "r" }]; + const remaining = [{ userId: "a" }]; + expect(computeRoleRemovals(deleted, remaining)).toEqual([]); + }); + + it("removes a user whose only row was deleted, carrying the snapshotted roleId", () => { + const deleted = [{ userId: "b", roleId: "role-123" }]; + expect(computeRoleRemovals(deleted, [])).toEqual([{ userId: "b", roleId: "role-123" }]); + }); + + it("removes everyone exactly once on whole-event delete even when duplicated across rooms", () => { + const deleted = [ + { userId: "a", roleId: "r" }, + { userId: "a", roleId: "r" }, + { userId: "b", roleId: "r" }, + ]; + expect(computeRoleRemovals(deleted, [])).toEqual([ + { userId: "a", roleId: "r" }, + { userId: "b", roleId: "r" }, + ]); + }); +}); + +describe("groupWinnersByRoom", () => { + it("groups winners by room ordered ascending, preserving multiple winners per room", () => { + const rows = [ + winnerRow({ id: 1n, roomIndex: 2n, userId: "x" }), + winnerRow({ id: 2n, roomIndex: 1n, userId: "z" }), + winnerRow({ id: 3n, roomIndex: 2n, userId: "y" }), + ]; + + const grouped = groupWinnersByRoom(rows); + + expect([...grouped.keys()]).toEqual([1n, 2n]); + expect(grouped.get(1n)).toEqual(["z"]); + expect(grouped.get(2n)).toEqual(["x", "y"]); + }); +}); diff --git a/src/utils/winner.logic.ts b/src/utils/winner.logic.ts new file mode 100644 index 00000000..fd0dc166 --- /dev/null +++ b/src/utils/winner.logic.ts @@ -0,0 +1,54 @@ +import type { DbEventWinner } from "../db/schema.ts"; + +/** + * Pure decision functions for the event-winner feature. + * + * No Discord, no DB — plain data in, plain data out — so they unit-test with no mocks. + * The side-effectful orchestration lives in `winner.utils.ts`. + */ + +/** + * Additive union, deduped: the requested userIds that are not already winners of the room. + */ +export function computeWinnersToAdd(existingRoomUserIds: Set, requested: Set): string[] { + return [...requested].filter(userId => !existingRoomUserIds.has(userId)); +} + +/** + * Given the winner rows being deleted and the rows that remain for the event, return the + * (userId, roleId) pairs whose role must be removed — i.e. users with NO remaining row. + * + * Encodes the multi-room-win safety rule: a user who still holds a winning row elsewhere keeps + * the role. Deduped by (userId, roleId) so a user duplicated across rooms is removed exactly once. + */ +export function computeRoleRemovals( + deleted: { userId: string, roleId: string }[], + remaining: { userId: string }[], +): { userId: string, roleId: string }[] { + const remainingUserIds = new Set(remaining.map(row => row.userId)); + const seen = new Set(); + const removals: { userId: string, roleId: string }[] = []; + for (const { userId, roleId } of deleted) { + if (remainingUserIds.has(userId)) continue; + const key = JSON.stringify([userId, roleId]); + if (seen.has(key)) continue; + seen.add(key); + removals.push({ userId, roleId }); + } + return removals; +} + +/** + * For the list command: rows -> ordered map of roomIndex -> userIds (rooms ascending, + * within-room order preserved). + */ +export function groupWinnersByRoom(rows: DbEventWinner[]): Map { + const grouped = new Map(); + const ordered = [...rows].sort((a, b) => Number(a.roomIndex) - Number(b.roomIndex)); + for (const row of ordered) { + const userIds = grouped.get(row.roomIndex) ?? []; + userIds.push(row.userId); + grouped.set(row.roomIndex, userIds); + } + return grouped; +} diff --git a/src/utils/winner.utils.ts b/src/utils/winner.utils.ts new file mode 100644 index 00000000..9ebdccbe --- /dev/null +++ b/src/utils/winner.utils.ts @@ -0,0 +1,88 @@ +import type { Snowflake } from "discord.js"; + +import { Queries } from "../db/queries.ts"; +import type { DbEvent } from "../db/schema.ts"; +import type { Store } from "../db/store.ts"; +import { MemberUtils } from "./member.utils.ts"; +import { computeRoleRemovals, computeWinnersToAdd } from "./winner.logic.ts"; + +/** + * `WinnerUtils` orchestrates the event-winner Store/Queries writes and the Discord role + * side-effects, delegating every non-trivial rule to the pure functions in `winner.logic.ts`. + */ +export namespace WinnerUtils { + + // Add/remove a role for one user. Guards against a user who has left the guild + // (`store.jsMember` returns undefined) and logs — rather than throws — so one missing + // member or permission issue never aborts the rest of a tie. + async function applyRole(store: Store, userId: Snowflake, roleId: Snowflake, modification: "add" | "remove") { + const jsMember = await store.jsMember(userId); + if (!jsMember) return; + try { + await MemberUtils.modifyMemberRoles(store, userId, roleId, modification); + } + catch (e) { + console.error(`WinnerUtils.applyRole: failed to ${modification} role ${roleId} for user ${userId}:`, e); + } + } + + /** + * Additive declaration: grants the event's winner role to the requested users for `roomIndex`, + * skipping any who already win that room. Returns the userIds newly added. + */ + export async function declareRoomWinners( + store: Store, + event: DbEvent, + roomIndex: bigint, + requested: Set, + ): Promise { + const rows = Queries.selectManyEventWinners({ guildId: store.guild.id, eventId: event.id }); + const existingForRoom = new Set(rows.filter(row => row.roomIndex === roomIndex).map(row => row.userId)); + const toAdd = computeWinnersToAdd(existingForRoom, requested); + + for (const userId of toAdd) { + store.insertEventWinner({ + guildId: store.guild.id, + eventId: event.id, + roomIndex, + userId, + roleId: event.winnerRoleId, + }); + await applyRole(store, userId, event.winnerRoleId, "add"); + } + + return toAdd; + } + + /** + * Clears winner rows for the whole event (or a single `roomIndex`), revoking the role only + * from users who no longer hold any winning row. Uses each row's snapshotted `roleId`, so it + * works even if `event.winnerRoleId` was later changed or cleared. Returns the role removals. + */ + export async function clearEventWinners( + store: Store, + event: DbEvent, + roomIndex?: bigint, + ): Promise<{ userId: string, roleId: string }[]> { + const rows = Queries.selectManyEventWinners({ guildId: store.guild.id, eventId: event.id }); + const deleted = roomIndex != null ? rows.filter(row => row.roomIndex === roomIndex) : rows; + const remaining = roomIndex != null ? rows.filter(row => row.roomIndex !== roomIndex) : []; + + store.deleteManyEventWinners(roomIndex != null ? { eventId: event.id, roomIndex } : { eventId: event.id }); + + const removals = computeRoleRemovals(deleted, remaining); + for (const { userId, roleId } of removals) { + await applyRole(store, userId, roleId, "remove"); + } + return removals; + } + + /** + * Revokes all of an event's winners — the single implementation called from the open-phase + * hook so the badge lasts exactly until the next occurrence opens. A redundant call (e.g. a + * restart re-running a handled open) simply finds no rows and is a no-op. + */ + export async function revokeEventWinners(store: Store, event: DbEvent) { + return clearEventWinners(store, event); + } +}