From 664a31c4eeed3f3bcfb89788e427c5c4b03704e2 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 30 Aug 2024 14:40:41 +0100 Subject: [PATCH 01/76] chore: init --- .github/workflows/worker-delete.yml | 44 - .github/workflows/worker-deploy.yml | 51 - .gitignore | 34 + README.md | 5 - manifest.json | 12 +- package.json | 81 +- src/bot/callback-data/change-language.ts | 5 + src/bot/context.ts | 50 + src/bot/features/admin.ts | 19 + src/bot/features/chatid.ts | 19 + src/bot/features/language.ts | 36 + src/bot/features/unhandled.ts | 18 + src/bot/features/user-id.ts | 19 + src/bot/features/welcome.ts | 14 + src/bot/features/workroom.ts | 16 + src/bot/filters/is-admin.ts | 3 + src/bot/handlers/commands/setcommands.ts | 107 + src/bot/handlers/error.ts | 13 + src/bot/helpers/keyboard.ts | 7 + src/bot/helpers/logging.ts | 20 + src/bot/i18n.ts | 12 + src/bot/index.ts | 79 + src/bot/keyboards/change-language.ts | 28 + src/bot/locales/en.ftl | 22 + src/bot/middlewares/session.ts | 12 + src/bot/middlewares/update-logger.ts | 32 + src/bot/strings.ts | 5 + src/handlers/github/webhook.ts | 29 + src/handlers/github/workrooms.ts | 45 + src/handlers/hello-world.ts | 59 - src/handlers/telegram/webhook.ts | 16 + src/logger.ts | 5 + src/plugin.ts | 37 +- src/server/environment.ts | 8 + src/server/index.ts | 74 + src/server/middlewares/logger.ts | 13 + src/server/middlewares/request-logger.ts | 25 + src/types/context.ts | 2 +- src/types/env.ts | 39 +- src/types/plugin-inputs.ts | 14 +- src/types/typeguards.ts | 29 +- src/utils/errors.ts | 6 + src/utils/logger.ts | 39 + src/utils/plugin-context-single.ts | 39 + src/utils/smee.ts | 13 + src/utils/telegram-bot-single.ts | 46 + src/worker.ts | 100 +- src/{main.ts => workflow-entry.ts} | 0 tsconfig.json | 122 +- wrangler.toml | 23 +- yarn.lock | 4543 ++++++++++++++++------ 51 files changed, 4475 insertions(+), 1614 deletions(-) delete mode 100644 .github/workflows/worker-delete.yml delete mode 100644 .github/workflows/worker-deploy.yml create mode 100644 src/bot/callback-data/change-language.ts create mode 100644 src/bot/context.ts create mode 100644 src/bot/features/admin.ts create mode 100644 src/bot/features/chatid.ts create mode 100644 src/bot/features/language.ts create mode 100644 src/bot/features/unhandled.ts create mode 100644 src/bot/features/user-id.ts create mode 100644 src/bot/features/welcome.ts create mode 100644 src/bot/features/workroom.ts create mode 100644 src/bot/filters/is-admin.ts create mode 100644 src/bot/handlers/commands/setcommands.ts create mode 100644 src/bot/handlers/error.ts create mode 100644 src/bot/helpers/keyboard.ts create mode 100644 src/bot/helpers/logging.ts create mode 100644 src/bot/i18n.ts create mode 100644 src/bot/index.ts create mode 100644 src/bot/keyboards/change-language.ts create mode 100644 src/bot/locales/en.ftl create mode 100644 src/bot/middlewares/session.ts create mode 100644 src/bot/middlewares/update-logger.ts create mode 100644 src/bot/strings.ts create mode 100644 src/handlers/github/webhook.ts create mode 100644 src/handlers/github/workrooms.ts delete mode 100644 src/handlers/hello-world.ts create mode 100644 src/handlers/telegram/webhook.ts create mode 100644 src/logger.ts create mode 100644 src/server/environment.ts create mode 100644 src/server/index.ts create mode 100644 src/server/middlewares/logger.ts create mode 100644 src/server/middlewares/request-logger.ts create mode 100644 src/utils/errors.ts create mode 100644 src/utils/logger.ts create mode 100644 src/utils/plugin-context-single.ts create mode 100644 src/utils/smee.ts create mode 100644 src/utils/telegram-bot-single.ts rename src/{main.ts => workflow-entry.ts} (100%) diff --git a/.github/workflows/worker-delete.yml b/.github/workflows/worker-delete.yml deleted file mode 100644 index 89d3e23..0000000 --- a/.github/workflows/worker-delete.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Delete Deployment - -on: - delete: - -jobs: - delete: - runs-on: ubuntu-latest - name: Delete Deployment - steps: - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: "20.10.0" - - - name: Enable corepack - run: corepack enable - - - uses: actions/checkout@v4 - - - name: Get Deleted Branch Name - id: get_branch - run: | - branch_name=$(echo '${{ github.event.ref }}' | sed 's#refs/heads/##' | sed 's#[^a-zA-Z0-9]#-#g') - echo "branch_name=$branch_name" >> $GITHUB_ENV - - name: Retrieve and Construct Full Worker Name - id: construct_worker_name - run: | - base_name=$(grep '^name = ' wrangler.toml | sed 's/^name = "\(.*\)"$/\1/') - full_worker_name="${base_name}-${{ env.branch_name }}" - # Make sure that it doesnt exceed 63 characters or it will break RFC 1035 - full_worker_name=$(echo "${full_worker_name}" | cut -c 1-63) - echo "full_worker_name=$full_worker_name" >> $GITHUB_ENV - - name: Delete Deployment with Wrangler - uses: cloudflare/wrangler-action@v3 - with: - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - command: delete --name ${{ env.full_worker_name }} - - - name: Output Deletion Result - run: | - echo "### Deployment URL" >> $GITHUB_STEP_SUMMARY - echo 'Deployment `${{ env.full_worker_name }}` has been deleted.' >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/worker-deploy.yml b/.github/workflows/worker-deploy.yml deleted file mode 100644 index 0a3942c..0000000 --- a/.github/workflows/worker-deploy.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: Deploy Worker - -on: - push: - workflow_dispatch: - -jobs: - deploy: - runs-on: ubuntu-latest - name: Deploy - steps: - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: "20.10.0" - - - name: Enable corepack - run: corepack enable - - - uses: actions/checkout@v4 - - - name: Update wrangler.toml Name Field - run: | - branch_name=$(echo '${{ github.event.ref }}' | sed 's#refs/heads/##' | sed 's#[^a-zA-Z0-9]#-#g') - # Extract base name from wrangler.toml - base_name=$(grep '^name = ' wrangler.toml | sed 's/^name = "\(.*\)"$/\1/') - # Concatenate branch name with base name - new_name="${base_name}-${branch_name}" - # Truncate the new name to 63 characters for RFC 1035 - new_name=$(echo "$new_name" | cut -c 1-63) - # Update the wrangler.toml file - sed -i "s/^name = .*/name = \"$new_name\"/" wrangler.toml - echo "Updated wrangler.toml name to: $new_name" - - name: Deploy with Wrangler - id: wrangler_deploy - uses: cloudflare/wrangler-action@v3 - with: - wranglerVersion: "3.57.0" - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - secrets: | - SUPABASE_URL - SUPABASE_KEY - env: - SUPABASE_URL: ${{ secrets.SUPABASE_URL }} - SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} - - - name: Write Deployment URL to Summary - run: | - echo "### Deployment URL" >> $GITHUB_STEP_SUMMARY - echo "${{ steps.wrangler_deploy.outputs.deployment-url }}" >> $GITHUB_STEP_SUMMARY diff --git a/.gitignore b/.gitignore index 12274bf..46a444b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,37 @@ cypress/screenshots script.ts .wrangler test-dashboard.md + +# prod +dist/ + +# dev +.yarn/ +!.yarn/releases +.vscode/* +!.vscode/launch.json +!.vscode/*.code-snippets +.idea/workspace.xml +.idea/usage.statistics.xml +.idea/shelf + +# deps +node_modules/ +.wrangler + +# env +.env +.env.production +.dev.vars + +# logs +logs/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# misc +.DS_Store diff --git a/README.md b/README.md index 527ff8f..a27db3e 100644 --- a/README.md +++ b/README.md @@ -64,11 +64,6 @@ await fetch("http://localhost:4000/", { A full example can be found [here](https://github.com/ubiquibot/assistive-pricing/blob/623ea3f950f04842f2d003bda3fc7b7684e41378/tests/http/request.http). -#### Deploying the Worker -For testing purposes, the worker can be deployed through the Worker Deploy and Worker Delete workflows. It requires to -create a personal [Cloudflare Account](https://www.cloudflare.com/), and fill the `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_API_TOKEN` within your -GitHub Action Secrets. - ### Action Plugins - Ensure the kernel is running and listening for events. diff --git a/manifest.json b/manifest.json index 83aa3f2..9efc71f 100644 --- a/manifest.json +++ b/manifest.json @@ -1,11 +1,7 @@ { "name": "ts-template", "description": "ts-template for Ubiquibot plugins.", - "ubiquity:listeners": ["issue_comment.created"], - "commands": { - "command1": { - "ubiquity:example": "/command1 argument", - "description": "Command 1 with an argument." - } - } -} + "ubiquity:listeners": [ + "issues.opened" + ] +} \ No newline at end of file diff --git a/package.json b/package.json index 838f3e8..d6884fe 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,17 @@ { - "name": "plugin-template", - "version": "1.0.0", + "name": "telegram-bot", + "version": "0.1.0", "description": "Ubiquibot plugin template repository with TypeScript support.", "author": "Ubiquity DAO", "license": "MIT", "main": "src/worker.ts", + "type": "module", "engines": { "node": ">=20.10.0" }, + "imports": { + "#root/*": "./build/src/*" + }, "scripts": { "format": "run-p format:*", "format:lint": "eslint --fix .", @@ -17,7 +21,12 @@ "knip-ci": "knip --no-exit-code --reporter json --config .github/knip.ts", "prepare": "husky install", "test": "jest --setupFiles dotenv/config --coverage", - "worker": "wrangler dev --env dev --port 4000" + "worker": "wrangler dev --env dev --port 3000", + "dev": "tsc-watch --onSuccess \"tsx ./src/main.ts\"", + "start": "tsx ./src/main.ts", + "deploy": "wrangler deploy --minify src/main.ts", + "build": "npx tsx build/esbuild-build.ts", + "serve": "npx tsx build/esbuild-server.ts" }, "keywords": [ "typescript", @@ -29,43 +38,61 @@ "dependencies": { "@actions/core": "1.10.1", "@actions/github": "6.0.0", - "@octokit/rest": "20.1.1", - "@octokit/webhooks": "13.2.7", - "@sinclair/typebox": "0.32.33", - "@ubiquity-dao/ubiquibot-logger": "^1.3.0", + "@grammyjs/auto-chat-action": "0.1.1", + "@grammyjs/hydrate": "1.4.1", + "@grammyjs/i18n": "1.0.2", + "@grammyjs/parse-mode": "1.10.0", + "@grammyjs/runner": "2.0.3", + "@grammyjs/types": "3.13.0", + "@hono/node-server": "^1.12.1", + "@octokit/rest": "21.0.2", + "@octokit/webhooks": "13.3.0", + "@sinclair/typebox": "0.33.7", + "@ubiquity-dao/ubiquibot-logger": "^1.3.1", + "callback-data": "1.1.1", "dotenv": "16.4.5", - "typebox-validators": "0.3.5" + "grammy": "^1.29.0", + "grammy-guard": "0.5.0", + "hono": "^4.5.9", + "iso-639-1": "3.1.2", + "pino": "9.3.2", + "pino-pretty": "11.2.2", + "typebox-validators": "0.3.5", + "valibot": "0.39.0" }, "devDependencies": { - "@commitlint/cli": "19.3.0", + "@cloudflare/workers-types": "^4.20240529.0", + "@commitlint/cli": "19.4.0", "@commitlint/config-conventional": "19.2.2", "@cspell/dict-node": "5.0.1", - "@cspell/dict-software-terms": "3.4.6", - "@cspell/dict-typescript": "3.1.5", - "@eslint/js": "9.5.0", + "@cspell/dict-software-terms": "4.1.0", + "@cspell/dict-typescript": "3.1.6", + "@eslint/js": "9.9.1", "@jest/globals": "29.7.0", "@mswjs/data": "0.16.1", "@types/jest": "^29.5.12", - "@types/node": "20.14.5", - "cspell": "8.9.0", - "eslint": "9.5.0", + "@types/node": "22.5.0", + "cspell": "8.14.2", + "eslint": "9.9.1", "eslint-config-prettier": "9.1.0", "eslint-plugin-check-file": "2.8.0", - "eslint-plugin-prettier": "5.1.3", - "eslint-plugin-sonarjs": "1.0.3", - "husky": "9.0.11", + "eslint-plugin-prettier": "5.2.1", + "eslint-plugin-sonarjs": "2.0.1", + "husky": "9.1.5", "jest": "29.7.0", "jest-junit": "16.0.0", "jest-md-dashboard": "0.8.0", - "knip": "5.21.2", - "lint-staged": "15.2.7", + "knip": "5.27.4", + "lint-staged": "15.2.9", "npm-run-all": "4.1.5", - "prettier": "3.3.2", - "ts-jest": "29.1.5", - "tsx": "4.15.6", - "typescript": "5.4.5", - "typescript-eslint": "7.13.1", - "wrangler": "3.60.3" + "prettier": "3.3.3", + "smee-client": "^2.0.3", + "ts-jest": "29.2.5", + "tsc-watch": "^6.2.0", + "tsx": "4.18.0", + "typescript": "5.5.4", + "typescript-eslint": "8.3.0", + "wrangler": "3.72.2" }, "lint-staged": { "*.ts": [ @@ -82,4 +109,4 @@ ] }, "packageManager": "yarn@1.22.22" -} +} \ No newline at end of file diff --git a/src/bot/callback-data/change-language.ts b/src/bot/callback-data/change-language.ts new file mode 100644 index 0000000..17ee539 --- /dev/null +++ b/src/bot/callback-data/change-language.ts @@ -0,0 +1,5 @@ +import { createCallbackData } from 'callback-data' + +export const changeLanguageData = createCallbackData('language', { + code: String, +}) diff --git a/src/bot/context.ts b/src/bot/context.ts new file mode 100644 index 0000000..e3b8f0e --- /dev/null +++ b/src/bot/context.ts @@ -0,0 +1,50 @@ +import type { Update, UserFromGetMe } from '@grammyjs/types' +import { type Api, Context as DefaultContext, type SessionFlavor } from 'grammy' +import type { AutoChatActionFlavor } from '@grammyjs/auto-chat-action' +import type { HydrateFlavor } from '@grammyjs/hydrate' +import type { I18nFlavor } from '@grammyjs/i18n' +import type { ParseModeFlavor } from '@grammyjs/parse-mode' +import type { Logger } from '#root/logger.js' +import { Context as UbiquityOsContext } from '../types' + +export interface SessionData { + // field?: string; +} + +interface ExtendedContextFlavor { + logger: Logger + config: UbiquityOsContext["env"] +} + +export type Context = ParseModeFlavor< + HydrateFlavor< + DefaultContext & + ExtendedContextFlavor & + SessionFlavor & + AutoChatActionFlavor + > +> + +interface Dependencies { + logger: Logger + config: UbiquityOsContext["env"] +} + +export function createContextConstructor( + { + logger, + config, + }: Dependencies, +) { + return class extends DefaultContext implements ExtendedContextFlavor { + logger: Logger + config: UbiquityOsContext["env"] + + constructor(update: Update, api: Api, me: UserFromGetMe) { + super(update, api, me) + + this.logger = logger + this.config = config + } + } as unknown as new (update: Update, api: Api, me: UserFromGetMe) => Context +} diff --git a/src/bot/features/admin.ts b/src/bot/features/admin.ts new file mode 100644 index 0000000..40c15bc --- /dev/null +++ b/src/bot/features/admin.ts @@ -0,0 +1,19 @@ +import { chatAction } from '@grammyjs/auto-chat-action' +import { Composer } from 'grammy' +import type { Context } from '#root/bot/context.js' +import { isAdmin } from '#root/bot/filters/is-admin.js' +import { setCommandsHandler } from '#root/bot/handlers/commands/setcommands.js' +import { logHandle } from '#root/bot/helpers/logging.js' + +const composer = new Composer() + +const feature = composer.chatType('private').filter(ctx => isAdmin(ctx.config.BOT_ADMINS)(ctx)) + +feature.command( + 'setcommands', + logHandle('command-setcommands'), + chatAction('typing'), + setCommandsHandler, +) + +export { composer as adminFeature } diff --git a/src/bot/features/chatid.ts b/src/bot/features/chatid.ts new file mode 100644 index 0000000..8e7fa59 --- /dev/null +++ b/src/bot/features/chatid.ts @@ -0,0 +1,19 @@ +import { chatAction } from '@grammyjs/auto-chat-action' +import { Composer } from 'grammy' +import type { Context } from '#root/bot/context.js' +import { logHandle } from '#root/bot/helpers/logging.js' + +const composer = new Composer() + +const feature = composer.chatType('supergroup') + +feature.command( + 'chatid', + logHandle('command-chatid'), + chatAction('typing'), + async (ctx) => { + return ctx.reply(`This chat ID is ${ctx.chat.id}`) + }, +) + +export { composer as chatIdFeature } diff --git a/src/bot/features/language.ts b/src/bot/features/language.ts new file mode 100644 index 0000000..5763a40 --- /dev/null +++ b/src/bot/features/language.ts @@ -0,0 +1,36 @@ +// import { Composer } from 'grammy' +// import { changeLanguageData } from '#root/bot/callback-data/change-language.js' +// import type { Context } from '#root/bot/context.js' +// import { logHandle } from '#root/bot/helpers/logging.js' +// import { i18n } from '#root/bot/i18n.js' +// import { createChangeLanguageKeyboard } from '#root/bot/keyboards/change-language.js' + +// const composer = new Composer() + +// const feature = composer.chatType('private') + +// feature.command('language', logHandle('command-language'), async (ctx) => { +// return ctx.reply(ctx.t('language-select'), { +// reply_markup: await createChangeLanguageKeyboard(ctx), +// }) +// }) + +// feature.callbackQuery( +// changeLanguageData.filter(), +// logHandle('keyboard-language-select'), +// async (ctx) => { +// const { code: languageCode } = changeLanguageData.unpack( +// ctx.callbackQuery.data, +// ) + +// if (i18n.locales.includes(languageCode)) { +// await ctx.i18n.setLocale(languageCode) + +// return ctx.editMessageText(ctx.t('language-changed'), { +// reply_markup: await createChangeLanguageKeyboard(ctx), +// }) +// } +// }, +// ) + +// export { composer as languageFeature } diff --git a/src/bot/features/unhandled.ts b/src/bot/features/unhandled.ts new file mode 100644 index 0000000..e12b7c2 --- /dev/null +++ b/src/bot/features/unhandled.ts @@ -0,0 +1,18 @@ +import { Composer } from 'grammy' +import type { Context } from '#root/bot/context.js' +import { logHandle } from '#root/bot/helpers/logging.js' +import { STRINGS } from '../strings' + +const composer = new Composer() + +const feature = composer.chatType('private') + +feature.on('message', logHandle('unhandled-message'), (ctx) => { + return ctx.reply(STRINGS.UNHANDLED) +}) + +feature.on('callback_query', logHandle('unhandled-callback-query'), (ctx) => { + return ctx.answerCallbackQuery() +}) + +export { composer as unhandledFeature } diff --git a/src/bot/features/user-id.ts b/src/bot/features/user-id.ts new file mode 100644 index 0000000..f249862 --- /dev/null +++ b/src/bot/features/user-id.ts @@ -0,0 +1,19 @@ +import { chatAction } from '@grammyjs/auto-chat-action' +import { Composer } from 'grammy' +import type { Context } from '#root/bot/context.js' +import { logHandle } from '#root/bot/helpers/logging.js' + +const composer = new Composer() + +const feature = composer.chatType('private') + +feature.command( + 'myid', + logHandle('command-myid'), + chatAction('typing'), + async (ctx) => { + return ctx.reply(`Your ID is ${ctx.from.id}`) + }, +) + +export { composer as userIdFeature } diff --git a/src/bot/features/welcome.ts b/src/bot/features/welcome.ts new file mode 100644 index 0000000..4e6f190 --- /dev/null +++ b/src/bot/features/welcome.ts @@ -0,0 +1,14 @@ +import { Composer } from 'grammy' +import type { Context } from '#root/bot/context.js' +import { logHandle } from '#root/bot/helpers/logging.js' +import { STRINGS } from '../strings' + +const composer = new Composer() + +const feature = composer.chatType('private') + +feature.command('start', logHandle('command-start'), (ctx) => { + return ctx.reply(STRINGS.WELCOME) +}) + +export { composer as welcomeFeature } diff --git a/src/bot/features/workroom.ts b/src/bot/features/workroom.ts new file mode 100644 index 0000000..b98cdc6 --- /dev/null +++ b/src/bot/features/workroom.ts @@ -0,0 +1,16 @@ +import { Composer } from 'grammy' +import type { Context } from '#root/bot/context.js' +import { PluginContext } from '#root/utils/plugin-context-single.js' + +const composer = new Composer() + +const feature = composer.chatType("supergroup") + +feature.on(":forum_topic_created", async (ctx) => { + const pluginCtx = PluginContext.getInstance().getContext() + const chatId = pluginCtx.config.supergroupChatId // replace with general or dedicated channel for announcements + const name = ctx.update.message.forum_topic_created.name + return await ctx.api.sendMessage(chatId, `New workroom created: ${name} `) +}) + +export { composer as createForumsFeature } diff --git a/src/bot/filters/is-admin.ts b/src/bot/filters/is-admin.ts new file mode 100644 index 0000000..fe5a249 --- /dev/null +++ b/src/bot/filters/is-admin.ts @@ -0,0 +1,3 @@ +import { isUserHasId } from 'grammy-guard' + +export const isAdmin = (ids: number[]) => isUserHasId(...ids) \ No newline at end of file diff --git a/src/bot/handlers/commands/setcommands.ts b/src/bot/handlers/commands/setcommands.ts new file mode 100644 index 0000000..1a5d99d --- /dev/null +++ b/src/bot/handlers/commands/setcommands.ts @@ -0,0 +1,107 @@ +import type { BotCommand, LanguageCode } from '@grammyjs/types' +import type { CommandContext } from 'grammy' +import type { Context } from '#root/bot/context.js' + +function getLanguageCommand(localeCode: string): BotCommand { + return { + command: 'language', + description: 'language-command-description', + } +} + +function getPrivateChatCommands(localeCode: string): BotCommand[] { + return [ + { + command: 'start', + description: 'start-command-description', + }, + ] +} + +function getPrivateChatAdminCommands(localeCode: string): BotCommand[] { + return [ + { + command: 'setcommands', + description: 'setcommands-command-description', + }, + ] +} + +function getGroupChatCommands(_localeCode: string): BotCommand[] { + return [] +} + +export async function setCommandsHandler(ctx: CommandContext) { + const DEFAULT_LANGUAGE_CODE = 'en' + + // set private chat commands + await ctx.api.setMyCommands( + [ + ...getPrivateChatCommands(DEFAULT_LANGUAGE_CODE), + // ...(isMultipleLocales ? [getLanguageCommand(DEFAULT_LANGUAGE_CODE)] : []), + ], + { + scope: { + type: 'all_private_chats', + }, + }, + ) + + // if (isMultipleLocales) { + // const requests = i18n.locales.map(code => + // ctx.api.setMyCommands( + // [ + // ...getPrivateChatCommands(code), + // ...(isMultipleLocales + // ? [getLanguageCommand(DEFAULT_LANGUAGE_CODE)] + // : []), + // ], + // { + // language_code: code as LanguageCode, + // scope: { + // type: 'all_private_chats', + // }, + // }, + // ), + // ) + + // await Promise.all(requests) + // } + + // set group chat commands + await ctx.api.setMyCommands(getGroupChatCommands(DEFAULT_LANGUAGE_CODE), { + scope: { + type: 'all_group_chats', + }, + }) + + // if (isMultipleLocales) { + // const requests = i18n.locales.map(code => + // ctx.api.setMyCommands(getGroupChatCommands(code), { + // language_code: code as LanguageCode, + // scope: { + // type: 'all_group_chats', + // }, + // }), + // ) + + // await Promise.all(requests) + // } + + // set private chat commands for owner + await ctx.api.setMyCommands( + [ + ...getPrivateChatCommands(DEFAULT_LANGUAGE_CODE), + ...getPrivateChatAdminCommands(DEFAULT_LANGUAGE_CODE), + // ...(isMultipleLocales ? [getLanguageCommand(DEFAULT_LANGUAGE_CODE)] : []), + ], + { + scope: { + type: 'chat', + chat_id: ctx.chat.id, + }, + }, + ) + + return ctx.reply('admin-commands-updated') +} diff --git a/src/bot/handlers/error.ts b/src/bot/handlers/error.ts new file mode 100644 index 0000000..9a9ad78 --- /dev/null +++ b/src/bot/handlers/error.ts @@ -0,0 +1,13 @@ +import type { ErrorHandler } from 'grammy' +import type { Context } from '#root/bot/context.js' +import { getUpdateInfo } from '#root/bot/helpers/logging.js' + +export const errorHandler: ErrorHandler = (error) => { + const { ctx } = error + + ctx.logger.error( + 'Request failed', { + err: error, + update: getUpdateInfo(ctx), + }) +} diff --git a/src/bot/helpers/keyboard.ts b/src/bot/helpers/keyboard.ts new file mode 100644 index 0000000..d97ee33 --- /dev/null +++ b/src/bot/helpers/keyboard.ts @@ -0,0 +1,7 @@ +export function chunk(array: T[], size: number) { + const result = [] + for (let index = 0; index < array.length; index += size) + result.push(array.slice(index, index + size)) + + return result +} diff --git a/src/bot/helpers/logging.ts b/src/bot/helpers/logging.ts new file mode 100644 index 0000000..9c945c2 --- /dev/null +++ b/src/bot/helpers/logging.ts @@ -0,0 +1,20 @@ +import type { Middleware } from 'grammy' +import type { Update } from '@grammyjs/types' +import type { Context } from '#root/bot/context.js' + +export function getUpdateInfo(ctx: Context): Omit { + const { update_id, ...update } = ctx.update + + return update +} + +export function logHandle(id: string): Middleware { + return (ctx, next) => { + ctx.logger.info("Handling update", { + msg: `Handle "${id}"`, + ...(id.startsWith('unhandled') ? { update: getUpdateInfo(ctx) } : {}), + }) + + return next() + } +} diff --git a/src/bot/i18n.ts b/src/bot/i18n.ts new file mode 100644 index 0000000..43d6e75 --- /dev/null +++ b/src/bot/i18n.ts @@ -0,0 +1,12 @@ +import { I18n } from '@grammyjs/i18n' +import type { Context } from '#root/bot/context.js' + +export const i18n = new I18n({ + defaultLocale: 'en', + useSession: true, + fluentBundleOptions: { + useIsolating: false, + }, +}) + +export const isMultipleLocales = i18n.locales.length > 1 diff --git a/src/bot/index.ts b/src/bot/index.ts new file mode 100644 index 0000000..66f6541 --- /dev/null +++ b/src/bot/index.ts @@ -0,0 +1,79 @@ + +import type { BotConfig, StorageAdapter } from 'grammy' +import { Bot as TelegramBot } from 'grammy' +import type { Context, SessionData } from '#root/bot/context.js' +import { createContextConstructor } from '#root/bot/context.js' +import type { Logger } from '#root/logger.js' +import { Context as UbiquityOsContext } from '../types' +import { welcomeFeature } from '#root/bot/features/welcome.js' +import { unhandledFeature } from '#root/bot/features/unhandled.js' +import { errorHandler } from '#root/bot/handlers/error.js' +import { session } from '#root/bot/middlewares/session.js' +import { autoChatAction } from '@grammyjs/auto-chat-action' +import { hydrate } from '@grammyjs/hydrate' +import { hydrateReply, parseMode } from '@grammyjs/parse-mode' +import { i18n } from './i18n' +import { adminFeature } from './features/admin' +import { userIdFeature } from './features/user-id' +import { createForumsFeature } from './features/workroom' +import { chatIdFeature } from './features/chatid' + +interface Dependencies { + config: UbiquityOsContext["env"] + logger: Logger +} + +interface Options { + botSessionStorage?: StorageAdapter + botConfig?: Omit, 'ContextConstructor'> +} + +function getSessionKey(ctx: Omit) { + return ctx.chat?.id.toString() +} + +export function createBot(token: string, dependencies: Dependencies, options: Options = {}) { + const { + config, + logger, + } = dependencies + + const bot = new TelegramBot(token, { + ...options.botConfig, + ContextConstructor: createContextConstructor({ + logger, + config, + }), + }) + const protectedBot = bot.errorBoundary(errorHandler) + + // // Middlewares + bot.api.config.use(parseMode('HTML')) + + protectedBot.use(autoChatAction(bot.api)) + protectedBot.use(hydrateReply) + protectedBot.use(hydrate()) + protectedBot.use(session({ getSessionKey, storage: options.botSessionStorage })) + + // // Handlers + protectedBot.use(welcomeFeature) + protectedBot.use(adminFeature) + protectedBot.use(userIdFeature) + protectedBot.use(chatIdFeature) + protectedBot.use(createForumsFeature) + // if (isMultipleLocales) + // protectedBot.use(languageFeature) + + // // must be the last handler + protectedBot.use(unhandledFeature) + + Reflect.set(bot, 'getContext', createContextConstructor({ logger, config })) + + return bot as typeof bot & { + getContext: () => Context + } +} + +export type Bot = ReturnType & { + getContext: () => Context +} diff --git a/src/bot/keyboards/change-language.ts b/src/bot/keyboards/change-language.ts new file mode 100644 index 0000000..54d32e1 --- /dev/null +++ b/src/bot/keyboards/change-language.ts @@ -0,0 +1,28 @@ +// import { InlineKeyboard } from 'grammy' +// import ISO6391 from 'iso-639-1' +// import { changeLanguageData } from '#root/bot/callback-data/change-language.js' +// import type { Context } from '#root/bot/context.js' +// import { i18n } from '#root/bot/i18n.js' +// import { chunk } from '#root/bot/helpers/keyboard.js' + +// export async function createChangeLanguageKeyboard(ctx: Context) { +// const currentLocaleCode = await ctx.i18n.getLocale() + +// const getLabel = (code: string) => { +// const isActive = code === currentLocaleCode + +// return `${isActive ? '✅ ' : ''}${ISO6391.getNativeName(code)}` +// } + +// return InlineKeyboard.from( +// chunk( +// i18n.locales.map(localeCode => ({ +// text: getLabel(localeCode), +// callback_data: changeLanguageData.pack({ +// code: localeCode, +// }), +// })), +// 2, +// ), +// ) +// } diff --git a/src/bot/locales/en.ftl b/src/bot/locales/en.ftl new file mode 100644 index 0000000..0a9fe88 --- /dev/null +++ b/src/bot/locales/en.ftl @@ -0,0 +1,22 @@ +## Commands + +start - command - description = Start the bot +language - command - description = Change language +setcommands - command - description = Set bot commands + +## Welcome Feature + +welcome = Welcome! + +## Language Feature + +language - select = Please, select your language +language - changed = Language successfully changed! + +## Admin Feature + +admin - commands - updated = Commands updated. + +## Unhandled Feature + +unhandled = Unrecognized command.Try / start \ No newline at end of file diff --git a/src/bot/middlewares/session.ts b/src/bot/middlewares/session.ts new file mode 100644 index 0000000..f05d75e --- /dev/null +++ b/src/bot/middlewares/session.ts @@ -0,0 +1,12 @@ +import { type Middleware, type SessionOptions, session as createSession } from 'grammy' +import type { Context, SessionData } from '#root/bot/context.js' + +type Options = Pick, 'getSessionKey' | 'storage'> + +export function session(options: Options): Middleware { + return createSession({ + getSessionKey: options.getSessionKey, + storage: options.storage, + initial: () => ({}), + }) +} diff --git a/src/bot/middlewares/update-logger.ts b/src/bot/middlewares/update-logger.ts new file mode 100644 index 0000000..5d521b0 --- /dev/null +++ b/src/bot/middlewares/update-logger.ts @@ -0,0 +1,32 @@ +import { performance } from 'node:perf_hooks' +import type { Middleware } from 'grammy' +import type { Context } from '#root/bot/context.js' +import { getUpdateInfo } from '#root/bot/helpers/logging.js' + +export function updateLogger(): Middleware { + return async (ctx, next) => { + ctx.api.config.use((previous, method, payload, signal) => { + ctx.logger.debug("Bot API call", { + method, + payload, + }) + + return previous(method, payload, signal) + }) + + ctx.logger.debug("Update received", { + update: getUpdateInfo(ctx), + }) + + const startTime = performance.now() + try { + await next() + } + finally { + const endTime = performance.now() + ctx.logger.debug("Update processed", { + elapsed: endTime - startTime, + }) + } + } +} diff --git a/src/bot/strings.ts b/src/bot/strings.ts new file mode 100644 index 0000000..41981b5 --- /dev/null +++ b/src/bot/strings.ts @@ -0,0 +1,5 @@ +export const STRINGS = { + WELCOME: "Welcome! I'm a bot that can help you with your daily tasks. You can use the /help command to see what I can do.", + LOG_HANDLE: "Handling update", + UNHANDLED: "I'm sorry, I don't understand that command.", +} \ No newline at end of file diff --git a/src/handlers/github/webhook.ts b/src/handlers/github/webhook.ts new file mode 100644 index 0000000..289cb9a --- /dev/null +++ b/src/handlers/github/webhook.ts @@ -0,0 +1,29 @@ +import { Value } from "@sinclair/typebox/value"; +import { plugin } from "../../plugin"; +import { pluginSettingsSchema, pluginSettingsValidator, PluginInputs, Env } from "../../types"; + +export async function handleGithubWebhook(request: Request, env: Env): Promise { + try { + const webhookPayload = await request.json() as PluginInputs + const settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, webhookPayload.settings)); + + if (!pluginSettingsValidator.test(settings)) { + const errors: string[] = []; + for (const error of pluginSettingsValidator.errors(settings)) { + console.error(error); + errors.push(`${error.path}: ${error.message}`); + } + return new Response(JSON.stringify({ error: `Error: "Invalid settings provided. ${errors.join("; ")}"` }), { + status: 400, + headers: { "content-type": "application/json" }, + }); + } + + webhookPayload.settings = settings; + await plugin(webhookPayload, env); + return new Response(JSON.stringify("OK"), { status: 200, headers: { "content-type": "application/json" } }); + } catch (error) { + console.log("Error in handleGithubWebhook", error); + throw new Error("Error in handleGithubWebhook"); + } +} \ No newline at end of file diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts new file mode 100644 index 0000000..fa82753 --- /dev/null +++ b/src/handlers/github/workrooms.ts @@ -0,0 +1,45 @@ +import { TelegramBotSingleton } from "#root/utils/telegram-bot-single.js"; +import { Context } from "../../types"; + +export async function createChatroom(context: Context) { + const { logger, config } = context; + const bot = TelegramBotSingleton.getInstance().getBot(); + const title = context.payload.issue.title + + logger.info(`Creating chatroom for issue ${title}`); + + let forum; + try { + forum = await bot.api?.createForumTopic(config.supergroupChatId, title); + logger.info(`Created chatroom for issue ${title}: ${forum?.message_thread_id}`); + } catch (er) { + logger.error(`Failed to create chatroom for issue ${title}`, { er }); + } + + if (forum) { + await addCommentToIssue(context, `Workroom created: https://t.me/${config.supergroupChatName}/${forum?.message_thread_id}`); + } else { + await addCommentToIssue(context, logger.error(`Failed to create chatroom for issue ${title}`).logMessage.diff); + } +} + + +async function addCommentToIssue(context: Context, msg: string) { + const { logger, octokit } = context; + const { repository: { full_name }, issue } = context.payload; + const [owner, repo] = full_name.split("/"); + + logger.info(`Adding comment to issue ${issue.number}`); + + try { + await octokit.issues.createComment({ + owner, + repo, + issue_number: issue.number, + body: msg, + }); + logger.info(`Added comment to issue ${issue.number}`); + } catch (er) { + logger.error(`Failed to add comment to issue ${issue.number}`, { er }); + } +} diff --git a/src/handlers/hello-world.ts b/src/handlers/hello-world.ts deleted file mode 100644 index 4c58ae1..0000000 --- a/src/handlers/hello-world.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Context } from "../types"; - -/** - * NOTICE: Remove this file or use it as a template for your own plugins. - * - * This encapsulates the logic for a plugin if the only thing it does is say "Hello, world!". - * - * Try it out by running your local kernel worker and running the `yarn worker` command. - * Comment on an issue in a repository where your GitHub App is installed and see the magic happen! - * - * Logger examples are provided to show how to log different types of data. - */ -export async function helloWorld(context: Context) { - const { - logger, - payload, - octokit, - config: { configurableResponse }, - } = context; - - const sender = payload.comment.user?.login; - const repo = payload.repository.name; - const issueNumber = payload.issue.number; - const owner = payload.repository.owner.login; - const body = payload.comment.body; - - if (!body.match(/hello/i)) { - logger.error(`Invalid use of slash command, use "/hello".`, { body }); - return; - } - - logger.info("Hello, world!"); - logger.debug(`Executing helloWorld:`, { sender, repo, issueNumber, owner }); - - try { - await octokit.issues.createComment({ - owner: payload.repository.owner.login, - repo: payload.repository.name, - issue_number: payload.issue.number, - body: configurableResponse, - }); - } catch (error) { - /** - * logger.fatal should not be used in 9/10 cases. Use logger.error instead. - * - * Below are examples of passing error objects to the logger, only one is needed. - */ - if (error instanceof Error) { - logger.error(`Error creating comment:`, { error: error, stack: error.stack }); - throw error; - } else { - logger.error(`Error creating comment:`, { err: error, error: new Error() }); - throw error; - } - } - - logger.ok(`Successfully created comment!`); - logger.verbose(`Exiting helloWorld`); -} diff --git a/src/handlers/telegram/webhook.ts b/src/handlers/telegram/webhook.ts new file mode 100644 index 0000000..4dba1ee --- /dev/null +++ b/src/handlers/telegram/webhook.ts @@ -0,0 +1,16 @@ +import { Value } from "@sinclair/typebox/value"; +import { envValidator, Env } from "../../types"; +import { TelegramBotSingleton } from "#root/utils/telegram-bot-single.js"; + +export async function handleTelegramWebhook(request: Request, env: Env): Promise { + const result = envValidator.test(env); + if (!result) { + const errors = Array.from(envValidator.errors(env)); + console.error(`Invalid tg bot env: `, errors); + } + const settings = Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)); + + const server = TelegramBotSingleton.getInstance().getServer(); + + return server.fetch(request, settings); +} \ No newline at end of file diff --git a/src/logger.ts b/src/logger.ts new file mode 100644 index 0000000..3f051da --- /dev/null +++ b/src/logger.ts @@ -0,0 +1,5 @@ +import { Logs } from '@ubiquity-dao/ubiquibot-logger' + +export const logger = new Logs("verbose") + +export type Logger = typeof logger diff --git a/src/plugin.ts b/src/plugin.ts index b877b2b..8027d84 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -1,9 +1,8 @@ -import { Octokit } from "@octokit/rest"; import { Env, PluginInputs } from "./types"; import { Context } from "./types"; -import { isIssueCommentEvent } from "./types/typeguards"; -import { helloWorld } from "./handlers/hello-world"; -import { LogLevel, Logs } from "@ubiquity-dao/ubiquibot-logger"; +import { isIssueOpenedEvent } from "./types/typeguards"; +import { createChatroom } from "./handlers/github/workrooms"; +import { PluginContext } from "./utils/plugin-context-single"; /** * The main plugin function. Split for easier testing. @@ -11,8 +10,8 @@ import { LogLevel, Logs } from "@ubiquity-dao/ubiquibot-logger"; export async function runPlugin(context: Context) { const { logger, eventName } = context; - if (isIssueCommentEvent(context)) { - return await helloWorld(context); + if (isIssueOpenedEvent(context)) { + return await createChatroom(context); } logger.error(`Unsupported event: ${eventName}`); @@ -22,27 +21,7 @@ export async function runPlugin(context: Context) { * How a worker executes the plugin. */ export async function plugin(inputs: PluginInputs, env: Env) { - const octokit = new Octokit({ auth: inputs.authToken }); - - const context: Context = { - eventName: inputs.eventName, - payload: inputs.eventPayload, - config: inputs.settings, - octokit, - env, - logger: new Logs("info" as LogLevel), - }; - - /** - * NOTICE: Consider non-database storage solutions unless necessary - * - * Initialize storage adapters here. For example, to use Supabase: - * - * import { createClient } from "@supabase/supabase-js"; - * - * const supabase = createClient(env.SUPABASE_URL, env.SUPABASE_KEY); - * context.adapters = createAdapters(supabase, context); - */ - + PluginContext.initialize(inputs, env) + const context: Context = PluginContext.getInstance().getContext() return runPlugin(context); -} +} \ No newline at end of file diff --git a/src/server/environment.ts b/src/server/environment.ts new file mode 100644 index 0000000..9d16d36 --- /dev/null +++ b/src/server/environment.ts @@ -0,0 +1,8 @@ +import type { Logger } from '#root/logger.js' + +export interface Env { + Variables: { + requestId: string + logger: Logger + } +} diff --git a/src/server/index.ts b/src/server/index.ts new file mode 100644 index 0000000..8de4cbd --- /dev/null +++ b/src/server/index.ts @@ -0,0 +1,74 @@ +import { Hono } from 'hono' +import { HTTPException } from 'hono/http-exception' +import { webhookCallback } from 'grammy' +import { getPath } from 'hono/utils/url' +import { setLogger } from '#root/server/middlewares/logger.js' +import type { Env } from '#root/server/environment.js' +import type { Bot } from '#root/bot/index.js' +import { requestLogger } from '#root/server/middlewares/request-logger.js' +import type { Logger } from '#root/logger.js' +import { Context as UbiquityOsContext } from '../types' + +interface Dependencies { + bot: Bot + config: UbiquityOsContext["env"] + logger: Logger +} + + +export function createServer(dependencies: Dependencies) { + const { + bot, + config, + logger, + } = dependencies + + const server = new Hono() + + server.use(setLogger(logger)) + server.use(requestLogger()) + + server.onError(async (error, c) => { + console.error(c) + if (error instanceof HTTPException) { + if (error.status < 500) + c.var.logger.info( + 'Request info failed', { + err: error, + }) + else + c.var.logger.fatal( + 'Request failed', { + err: error, + }) + + return error.getResponse() + } + + // unexpected error + c.var.logger.error( + 'Unexpected error occurred', { + err: error, + method: c.req.raw.method, + path: getPath(c.req.raw), + }) + return c.json( + { + error: 'Oops! Something went wrong.', + }, + 500, + ) + }) + + server.get('/', c => c.json({ status: true })) + server.post( + '/webhook', + webhookCallback(bot, 'hono', { + secretToken: config.BOT_WEBHOOK_SECRET, + }), + ) + + return server +} + +export type Server = Awaited> \ No newline at end of file diff --git a/src/server/middlewares/logger.ts b/src/server/middlewares/logger.ts new file mode 100644 index 0000000..b257dee --- /dev/null +++ b/src/server/middlewares/logger.ts @@ -0,0 +1,13 @@ +import type { MiddlewareHandler } from 'hono' +import type { Logger } from '#root/logger.js' + +export function setLogger(logger: Logger): MiddlewareHandler { + return async (c, next) => { + c.set( + 'logger', + logger + ) + + await next() + } +} diff --git a/src/server/middlewares/request-logger.ts b/src/server/middlewares/request-logger.ts new file mode 100644 index 0000000..0a71c95 --- /dev/null +++ b/src/server/middlewares/request-logger.ts @@ -0,0 +1,25 @@ +import type { MiddlewareHandler } from 'hono' +import { getPath } from 'hono/utils/url' + +export function requestLogger(): MiddlewareHandler { + return async (c, next) => { + const { method } = c.req + const path = getPath(c.req.raw) + + c.var.logger.debug('Incoming request', { + method, + path, + }) + const startTime = performance.now() + + await next() + + const endTime = performance.now() + c.var.logger.debug('Request completed', { + method, + path, + status: c.res.status, + elapsed: endTime - startTime, + }) + } +} diff --git a/src/types/context.ts b/src/types/context.ts index 0a59f93..5f24919 100644 --- a/src/types/context.ts +++ b/src/types/context.ts @@ -9,7 +9,7 @@ import { Logs } from "@ubiquity-dao/ubiquibot-logger"; * * ubiquity:listeners: ["issue_comment.created", ...] */ -export type SupportedEventsU = "issue_comment.created"; +export type SupportedEventsU = "issues.opened" export type SupportedEvents = { [K in SupportedEventsU]: K extends WebhookEventName ? WebhookEvent : never; diff --git a/src/types/env.ts b/src/types/env.ts index 45e200e..5b82c16 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -3,15 +3,34 @@ import { StaticDecode } from "@sinclair/typebox"; import "dotenv/config"; import { StandardValidator } from "typebox-validators"; -/** - * Define sensitive environment variables here. - * - * These are fed into the worker/workflow as `env` and are - * taken from either `dev.vars` or repository secrets. - * They are used with `process.env` but are type-safe. - */ -export const envSchema = T.Object({}); +const allowedUpdates = T.Object({ + message: T.String(), + poll: T.String(), + edited_message: T.String(), + channel_post: T.String(), + edited_channel_post: T.String(), + business_connection: T.String(), + business_message: T.String(), + edited_business_message: T.String(), + deleted_business_messages: T.String(), + message_reaction_count: T.String(), +}); -export const envValidator = new StandardValidator(envSchema); +export const env = T.Object({ + BOT_TOKEN: T.String(), + BOT_MODE: T.String(), + LOG_LEVEL: T.String(), + DEBUG: T.Transform(T.String()).Decode((str) => str === "true").Encode((bool) => bool ? "true" : "false"), + BOT_WEBHOOK: T.String(), + BOT_WEBHOOK_SECRET: T.String(), + SERVER_HOST: T.String(), + SERVER_PORT: T.Transform(T.String()).Decode((str) => parseInt(str)).Encode((num) => num.toString()), + BOT_ADMINS: T.Transform(T.String()).Decode((str) => JSON.parse(str)).Encode((arr) => JSON.stringify(arr)), + ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))) +}); -export type Env = StaticDecode; +/** + * These are the same right now but they will diverge in the future. + */ +export type Env = StaticDecode; +export const envValidator = new StandardValidator(env); \ No newline at end of file diff --git a/src/types/plugin-inputs.ts b/src/types/plugin-inputs.ts index 1c8a30a..c745529 100644 --- a/src/types/plugin-inputs.ts +++ b/src/types/plugin-inputs.ts @@ -18,12 +18,14 @@ export interface PluginInputs { + return context.eventName === "issues.opened"; +} + +export function isTelegramPayload(payload: any): payload is Update { + try { + return payload.update_id !== undefined; + } catch (e) { + return false; + } +} -/** - * Restricts the scope of `context` to the `issue_comment.created` payload. - */ -export function isIssueCommentEvent(context: Context): context is Context<"issue_comment.created"> { - return context.eventName === "issue_comment.created"; +export function isGithubPayload(inputs: any): inputs is PluginInputs { + try { + return inputs.eventName !== undefined + } catch (e) { + return false; + } } diff --git a/src/utils/errors.ts b/src/utils/errors.ts new file mode 100644 index 0000000..921330e --- /dev/null +++ b/src/utils/errors.ts @@ -0,0 +1,6 @@ + +export function handleUncaughtError(error: unknown) { + console.error(error); + const status = 500; + return new Response(JSON.stringify({ error }), { status: status, headers: { "content-type": "application/json" } }); +} \ No newline at end of file diff --git a/src/utils/logger.ts b/src/utils/logger.ts new file mode 100644 index 0000000..8a25fd1 --- /dev/null +++ b/src/utils/logger.ts @@ -0,0 +1,39 @@ +import { LogReturn, Logs, Metadata } from "@ubiquity-dao/ubiquibot-logger"; + +export class Logger extends Logs { + updateId: number | string; + + constructor(updateId: number | string) { + super("verbose"); + this.updateId = updateId; + } + + storeUpdateId(updateId: number | string): Logger { + this.updateId = updateId; + return this; + } + + debug(log: string, metadata?: Metadata): LogReturn { + return super.debug(`[update_id: ${this.updateId}] ${log}`, metadata); + } + + error(log: string, metadata?: Metadata): LogReturn { + return super.error(`[update_id: ${this.updateId}] ${log}`, metadata); + } + + fatal(log: string, metadata?: Metadata): LogReturn { + return super.fatal(`[update_id: ${this.updateId}] ${log}`, metadata); + } + + info(log: string, metadata?: Metadata): LogReturn { + return super.info(`[update_id: ${this.updateId}] ${log}`, metadata); + } + + ok(log: string, metadata?: Metadata): LogReturn { + return super.ok(`[update_id: ${this.updateId}] ${log}`, metadata); + } + + verbose(log: string, metadata?: Metadata): LogReturn { + return super.verbose(`[update_id: ${this.updateId}] ${log}`, metadata); + } +} \ No newline at end of file diff --git a/src/utils/plugin-context-single.ts b/src/utils/plugin-context-single.ts new file mode 100644 index 0000000..074eeb4 --- /dev/null +++ b/src/utils/plugin-context-single.ts @@ -0,0 +1,39 @@ +import { Context, Env, PluginInputs } from "#root/types"; +import { Octokit } from "@octokit/rest"; +import { Logs } from "@ubiquity-dao/ubiquibot-logger"; + +export class PluginContext { + private static instance: PluginContext; + + private constructor( + public readonly inputs: PluginInputs, + public readonly env: Env, + ) { } + + static initialize(inputs: PluginInputs, env: Env): Context { + if (!PluginContext.instance) { + PluginContext.instance = new PluginContext(inputs, env); + } + return PluginContext.instance.getContext(); + } + + static getInstance(): PluginContext { + if (!PluginContext.instance) { + throw new Error("PluginContext is not initialized. Call initialize() first."); + } + return PluginContext.instance; + } + + getContext(): Context { + const octokit = new Octokit({ auth: this.inputs.authToken }); + + return { + eventName: this.inputs.eventName, + payload: this.inputs.eventPayload, + config: this.inputs.settings, + octokit, + env: this.env, + logger: new Logs("info"), + }; + } +} \ No newline at end of file diff --git a/src/utils/smee.ts b/src/utils/smee.ts new file mode 100644 index 0000000..02460e2 --- /dev/null +++ b/src/utils/smee.ts @@ -0,0 +1,13 @@ +import dotenv from "dotenv"; +import SmeeClient from "smee-client"; +dotenv.config({ + path: ".dev.vars" +}); + +const smee = new SmeeClient({ + source: process.env.WEBHOOK_PROXY_URL || "https://smee.io/new", + target: "http://localhost:8787/events", + logger: console, +}); + +smee.start(); \ No newline at end of file diff --git a/src/utils/telegram-bot-single.ts b/src/utils/telegram-bot-single.ts new file mode 100644 index 0000000..a3f30e8 --- /dev/null +++ b/src/utils/telegram-bot-single.ts @@ -0,0 +1,46 @@ +import { Value } from "@sinclair/typebox/value"; +import { Env, envValidator } from "../types"; +import { Bot, createBot } from "../bot"; +import { createServer } from "../server"; +import { logger } from "../logger"; + +export class TelegramBotSingleton { + private static instance: TelegramBotSingleton; + private static bot: Bot; + private static server: ReturnType; + + private constructor( + ) { } + + static initialize(env: Env): TelegramBotSingleton { + if (!TelegramBotSingleton.instance) { + TelegramBotSingleton.instance = new TelegramBotSingleton(); + TelegramBotSingleton.bot = createBot(env.BOT_TOKEN, { + config: Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)), + logger, + }); + TelegramBotSingleton.server = createServer({ + bot: TelegramBotSingleton.bot, + config: Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)), + logger + }); + } + return TelegramBotSingleton.instance; + } + + static getInstance(): TelegramBotSingleton { + if (!TelegramBotSingleton.instance) { + throw new Error("TelegramBotSingleton is not initialized. Call initialize() first."); + } + return TelegramBotSingleton.instance; + } + + getBot(): Bot { + return TelegramBotSingleton.bot; + } + + getServer(): ReturnType { + return TelegramBotSingleton.server; + } + +} diff --git a/src/worker.ts b/src/worker.ts index 40df400..1aa0f65 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,70 +1,66 @@ -import { Value } from "@sinclair/typebox/value"; -import { plugin } from "./plugin"; -import { Env, envValidator, pluginSettingsSchema, pluginSettingsValidator } from "./types"; +import { Env, PluginInputs } from "./types"; +import { isGithubPayload, isTelegramPayload } from "./types/typeguards"; +import { handleGithubWebhook } from "./handlers/github/webhook"; +import { handleTelegramWebhook } from "./handlers/telegram/webhook"; import manifest from "../manifest.json"; +import { handleUncaughtError } from "./utils/errors"; +import { TelegramBotSingleton } from "./utils/telegram-bot-single"; +import { PluginContext } from "./utils/plugin-context-single"; export default { async fetch(request: Request, env: Env): Promise { - try { - if (request.method === "GET") { - const url = new URL(request.url); - if (url.pathname === "/manifest.json") { - return new Response(JSON.stringify(manifest), { - headers: { "content-type": "application/json" }, - }); - } - } - if (request.method !== "POST") { - return new Response(JSON.stringify({ error: `Only POST requests are supported.` }), { - status: 405, - headers: { "content-type": "application/json", Allow: "POST" }, - }); - } - const contentType = request.headers.get("content-type"); - if (contentType !== "application/json") { - return new Response(JSON.stringify({ error: `Error: ${contentType} is not a valid content type` }), { - status: 400, + if (request.method === "GET") { + const url = new URL(request.url); + if (url.pathname === "/manifest.json") { + return new Response(JSON.stringify(manifest), { headers: { "content-type": "application/json" }, }); } + } - const webhookPayload = await request.json(); - const settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, webhookPayload.settings)); + if (request.method !== "POST") { + return new Response(JSON.stringify({ error: `Only POST requests are supported.` }), { + status: 405, + headers: { "content-type": "application/json", Allow: "POST" }, + }); + } + const contentType = request.headers.get("content-type"); + if (contentType !== "application/json") { + return new Response(JSON.stringify({ error: `Error: ${contentType} is not a valid content type` }), { + status: 400, + headers: { "content-type": "application/json" }, + }); + } + let payload; - if (!pluginSettingsValidator.test(settings)) { - const errors: string[] = []; - for (const error of pluginSettingsValidator.errors(settings)) { - console.error(error); - errors.push(`${error.path}: ${error.message}`); - } - return new Response(JSON.stringify({ error: `Error: "Invalid settings provided. ${errors.join("; ")}"` }), { - status: 400, - headers: { "content-type": "application/json" }, - }); - } - if (!envValidator.test(env)) { - const errors: string[] = []; - for (const error of envValidator.errors(env)) { - console.error(error); - errors.push(`${error.path}: ${error.message}`); - } - return new Response(JSON.stringify({ error: `Error: "Invalid environment provided. ${errors.join("; ")}"` }), { + try { + payload = await request.clone().json(); + } catch (err) { + return new Response(JSON.stringify({ error: "Invalid JSON payload" }), { + status: 400, + headers: { "content-type": "application/json" }, + }); + } + + TelegramBotSingleton.initialize(env); + + try { + if (isGithubPayload(payload)) { + PluginContext.initialize(payload, env); + await handleGithubWebhook(request, env); + } else if (isTelegramPayload(payload)) { + await handleTelegramWebhook(request, env); + } else { + return new Response(JSON.stringify({ error: "Invalid environment provided" }), { status: 400, headers: { "content-type": "application/json" }, }); } - webhookPayload.settings = settings; - await plugin(webhookPayload, env); - return new Response(JSON.stringify("OK"), { status: 200, headers: { "content-type": "application/json" } }); - } catch (error) { - return handleUncaughtError(error); + return new Response("OK", { status: 200, headers: { "content-type": "application/json" } }); + } catch (err) { + return handleUncaughtError(err); } }, }; -function handleUncaughtError(error: unknown) { - console.error(error); - const status = 500; - return new Response(JSON.stringify({ error }), { status: status, headers: { "content-type": "application/json" } }); -} diff --git a/src/main.ts b/src/workflow-entry.ts similarity index 100% rename from src/main.ts rename to src/workflow-entry.ts diff --git a/tsconfig.json b/tsconfig.json index ba9d6b3..2964ef5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,102 +1,32 @@ { "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - /* Language and Environment */ - "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - /* Modules */ - "module": "commonjs" /* Specify what module code is generated. */, - // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - "types": ["jest", "node"] /* Specify type package names to be included without being referenced in a source file. */, - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ - // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ - // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ - // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "paths": { + "#root/*": [ + "./src/*" + ] + }, + "types": [ + "jest", + "node", + "@cloudflare/workers-types/2023-07-01" + ] /* Specify type package names to be included without being referenced in a source file. */, + "lib": [ + "ESNext" + ], "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, - /* Type Checking */ "strict": true /* Enable all strict type-checking options. */, - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ "skipLibCheck": true /* Skip type checking all .d.ts files. */, - "resolveJsonModule": true - } -} + "resolveJsonModule": true, + "noEmit": true, + "outDir": "build", + "sourceMap": true, + "preserveWatchOutput": true, + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file diff --git a/wrangler.toml b/wrangler.toml index 5a0953a..e14cbbe 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,7 +1,26 @@ name = "your-plugin-name" main = "src/worker.ts" -compatibility_date = "2024-05-23" +compatibility_date = "2024-08-26" node_compat = true [env.dev] -[env.prod] \ No newline at end of file +[env.prod] + +# [vars] +# MY_VAR = "my-variable" + +# [[kv_namespaces]] +# binding = "MY_KV_NAMESPACE" +# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +# [[r2_buckets]] +# binding = "MY_BUCKET" +# bucket_name = "my-bucket" + +# [[d1_databases]] +# binding = "DB" +# database_name = "my-database" +# database_id = "" + +# [ai] +# binding = "AI" \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 85dc5db..62c607e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21,9 +21,9 @@ "@octokit/plugin-rest-endpoint-methods" "^10.0.0" "@actions/http-client@^2.0.1", "@actions/http-client@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.2.1.tgz#ed3fe7a5a6d317ac1d39886b0bb999ded229bb38" - integrity sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw== + version "2.2.3" + resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.2.3.tgz#31fc0b25c0e665754ed39a9f19a8611fc6dab674" + integrity sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA== dependencies: tunnel "^0.0.6" undici "^5.25.4" @@ -36,155 +36,297 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.6.tgz#ab88da19344445c3d8889af2216606d3329f3ef2" - integrity sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.2", "@babel/code-frame@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== dependencies: - "@babel/highlight" "^7.24.6" + "@babel/highlight" "^7.24.7" picocolors "^1.0.0" -"@babel/compat-data@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.6.tgz#b3600217688cabb26e25f8e467019e66d71b7ae2" - integrity sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ== +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.24.1", "@babel/compat-data@^7.25.2": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.4.tgz#7d2a80ce229890edcf4cc259d4d696cb4dae2fcb" + integrity sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ== -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.6.tgz#8650e0e4b03589ebe886c4e4a60398db0a7ec787" - integrity sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ== +"@babel/core@7.24.3": + version "7.24.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.3.tgz#568864247ea10fbd4eff04dda1e05f9e2ea985c3" + integrity sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.6" - "@babel/generator" "^7.24.6" - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helpers" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/template" "^7.24.6" - "@babel/traverse" "^7.24.6" - "@babel/types" "^7.24.6" + "@babel/code-frame" "^7.24.2" + "@babel/generator" "^7.24.1" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.24.1" + "@babel/parser" "^7.24.1" + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.1" + "@babel/types" "^7.24.0" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.24.6", "@babel/generator@^7.7.2": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.6.tgz#dfac82a228582a9d30c959fe50ad28951d4737a7" - integrity sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg== +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.25.2.tgz#ed8eec275118d7613e77a352894cd12ded8eba77" + integrity sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA== dependencies: - "@babel/types" "^7.24.6" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.25.0" + "@babel/helper-compilation-targets" "^7.25.2" + "@babel/helper-module-transforms" "^7.25.2" + "@babel/helpers" "^7.25.0" + "@babel/parser" "^7.25.0" + "@babel/template" "^7.25.0" + "@babel/traverse" "^7.25.2" + "@babel/types" "^7.25.2" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" -"@babel/helper-compilation-targets@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz#4a51d681f7680043d38e212715e2a7b1ad29cb51" - integrity sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg== +"@babel/eslint-parser@7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz#e27eee93ed1d271637165ef3a86e2b9332395c32" + integrity sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ== dependencies: - "@babel/compat-data" "^7.24.6" - "@babel/helper-validator-option" "^7.24.6" - browserslist "^4.22.2" - lru-cache "^5.1.1" + "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" + eslint-visitor-keys "^2.1.0" semver "^6.3.1" -"@babel/helper-environment-visitor@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz#ac7ad5517821641550f6698dd5468f8cef78620d" - integrity sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g== - -"@babel/helper-function-name@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz#cebdd063386fdb95d511d84b117e51fc68fec0c8" - integrity sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w== +"@babel/generator@^7.24.1", "@babel/generator@^7.25.0", "@babel/generator@^7.25.4", "@babel/generator@^7.7.2": + version "7.25.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.25.5.tgz#b31cf05b3fe8c32d206b6dad03bb0aacbde73450" + integrity sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w== dependencies: - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" + "@babel/types" "^7.25.4" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^2.5.1" -"@babel/helper-hoist-variables@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz#8a7ece8c26756826b6ffcdd0e3cf65de275af7f9" - integrity sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA== +"@babel/helper-annotate-as-pure@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab" + integrity sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg== dependencies: - "@babel/types" "^7.24.6" + "@babel/types" "^7.24.7" -"@babel/helper-module-imports@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz#65e54ffceed6a268dc4ce11f0433b82cfff57852" - integrity sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz#37d66feb012024f2422b762b9b2a7cfe27c7fba3" + integrity sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA== dependencies: - "@babel/types" "^7.24.6" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" -"@babel/helper-module-transforms@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz#22346ed9df44ce84dee850d7433c5b73fab1fe4e" - integrity sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA== +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6", "@babel/helper-compilation-targets@^7.24.7", "@babel/helper-compilation-targets@^7.24.8", "@babel/helper-compilation-targets@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz#e1d9410a90974a3a5a66e84ff55ef62e3c02d06c" + integrity sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw== dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-module-imports" "^7.24.6" - "@babel/helper-simple-access" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" + "@babel/compat-data" "^7.25.2" + "@babel/helper-validator-option" "^7.24.8" + browserslist "^4.23.1" + lru-cache "^5.1.1" + semver "^6.3.1" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.24.6", "@babel/helper-plugin-utils@^7.8.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz#fa02a32410a15a6e8f8185bcbf608f10528d2a24" - integrity sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg== +"@babel/helper-create-class-features-plugin@^7.24.1", "@babel/helper-create-class-features-plugin@^7.24.7", "@babel/helper-create-class-features-plugin@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.4.tgz#57eaf1af38be4224a9d9dd01ddde05b741f50e14" + integrity sha512-ro/bFs3/84MDgDmMwbcHgDa8/E6J3QKNTk4xJJnVeFtGE+tL0K26E3pNxhYz2b67fJpt7Aphw5XcploKXuCvCQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.8" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/helper-replace-supers" "^7.25.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/traverse" "^7.25.4" + semver "^6.3.1" -"@babel/helper-simple-access@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz#1d6e04d468bba4fc963b4906f6dac6286cfedff1" - integrity sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g== +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.7", "@babel/helper-create-regexp-features-plugin@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz#24c75974ed74183797ffd5f134169316cd1808d9" + integrity sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g== dependencies: - "@babel/types" "^7.24.6" + "@babel/helper-annotate-as-pure" "^7.24.7" + regexpu-core "^5.3.1" + semver "^6.3.1" -"@babel/helper-split-export-declaration@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz#e830068f7ba8861c53b7421c284da30ae656d7a3" - integrity sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw== +"@babel/helper-define-polyfill-provider@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" + integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== dependencies: - "@babel/types" "^7.24.6" + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + +"@babel/helper-member-expression-to-functions@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz#6155e079c913357d24a4c20480db7c712a5c3fb6" + integrity sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA== + dependencies: + "@babel/traverse" "^7.24.8" + "@babel/types" "^7.24.8" + +"@babel/helper-module-imports@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-module-transforms@^7.23.3", "@babel/helper-module-transforms@^7.24.7", "@babel/helper-module-transforms@^7.24.8", "@babel/helper-module-transforms@^7.25.0", "@babel/helper-module-transforms@^7.25.2": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz#ee713c29768100f2776edf04d4eb23b8d27a66e6" + integrity sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ== + dependencies: + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" + "@babel/traverse" "^7.25.2" + +"@babel/helper-optimise-call-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz#8b0a0456c92f6b323d27cfd00d1d664e76692a0f" + integrity sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.24.8", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz#94ee67e8ec0e5d44ea7baeb51e571bd26af07878" + integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg== + +"@babel/helper-remap-async-to-generator@^7.24.7", "@babel/helper-remap-async-to-generator@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz#d2f0fbba059a42d68e5e378feaf181ef6055365e" + integrity sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-wrap-function" "^7.25.0" + "@babel/traverse" "^7.25.0" + +"@babel/helper-replace-supers@^7.24.7", "@babel/helper-replace-supers@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.25.0.tgz#ff44deac1c9f619523fe2ca1fd650773792000a9" + integrity sha512-q688zIvQVYtZu+i2PsdIu/uWGRpfxzr5WESsfpShfZECkO+d2o+WROWezCi/Q6kJ0tfPa5+pUGUlfx2HhrA3Bg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.24.8" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/traverse" "^7.25.0" + +"@babel/helper-simple-access@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-skip-transparent-expression-wrappers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz#5f8fa83b69ed5c27adc56044f8be2b3ea96669d9" + integrity sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/helper-string-parser@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" + integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== + +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/helper-validator-option@^7.23.5", "@babel/helper-validator-option@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" + integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q== + +"@babel/helper-wrap-function@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz#dab12f0f593d6ca48c0062c28bcfb14ebe812f81" + integrity sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ== + dependencies: + "@babel/template" "^7.25.0" + "@babel/traverse" "^7.25.0" + "@babel/types" "^7.25.0" + +"@babel/helpers@^7.24.1", "@babel/helpers@^7.25.0": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.25.0.tgz#e69beb7841cb93a6505531ede34f34e6a073650a" + integrity sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw== + dependencies: + "@babel/template" "^7.25.0" + "@babel/types" "^7.25.0" + +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" -"@babel/helper-string-parser@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz#28583c28b15f2a3339cfafafeaad42f9a0e828df" - integrity sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.1", "@babel/parser@^7.25.0", "@babel/parser@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.4.tgz#af4f2df7d02440286b7de57b1c21acfb2a6f257a" + integrity sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA== + dependencies: + "@babel/types" "^7.25.4" -"@babel/helper-validator-identifier@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz#08bb6612b11bdec78f3feed3db196da682454a5e" - integrity sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.1": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz#749bde80356b295390954643de7635e0dffabe73" + integrity sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" -"@babel/helper-validator-option@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz#59d8e81c40b7d9109ab7e74457393442177f460a" - integrity sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz#e4eabdd5109acc399b38d7999b2ef66fc2022f89" + integrity sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.7" -"@babel/helpers@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.6.tgz#cd124245299e494bd4e00edda0e4ea3545c2c176" - integrity sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA== +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.1": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz#3a82a70e7cb7294ad2559465ebcb871dfbf078fb" + integrity sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw== dependencies: - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/traverse" "^7.25.0" -"@babel/highlight@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.6.tgz#6d610c1ebd2c6e061cade0153bf69b0590b7b3df" - integrity sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ== +"@babel/plugin-proposal-decorators@7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.1.tgz#bab2b9e174a2680f0a80f341f3ec70f809f8bb4b" + integrity sha512-zPEvzFijn+hRvJuX2Vu3KbEBN39LN3f7tW3MQO2LsIs57B26KU+kUc82BdAktS1VCM6libzh45eKGI65lg0cpA== dependencies: - "@babel/helper-validator-identifier" "^7.24.6" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" + "@babel/helper-create-class-features-plugin" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-decorators" "^7.24.1" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.6.tgz#5e030f440c3c6c78d195528c3b688b101a365328" - integrity sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q== +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -200,14 +342,63 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.8.3": +"@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" -"@babel/plugin-syntax-import-meta@^7.8.3": +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-decorators@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.7.tgz#e4f8a0a8778ccec669611cd5aed1ed8e6e3a6fcf" + integrity sha512-Ui4uLJJrRV1lb38zg1yYTmRKmiZLiftDEvZN2iq3kd9kUFU+PttmzTbAFC2ucRk/XJmtek6G23gPsuZbhrT8fQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-flow@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz#d1759e84dd4b437cf9fae69b4c06c41d7625bfb7" + integrity sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-assertions@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz#2a0b406b5871a20a841240586b1300ce2088a778" + integrity sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-attributes@^7.24.1", "@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz#b4f9ea95a79e6912480c4b626739f86a076624ca" + integrity sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-meta@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== @@ -221,14 +412,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.7.2": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.6.tgz#bcca2964150437f88f65e3679e3d68762287b9c8" - integrity sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw== +"@babel/plugin-syntax-jsx@^7.24.7", "@babel/plugin-syntax-jsx@^7.7.2": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz#39a1fa4a7e3d3d7f34e2acc6be585b718d30e02d" + integrity sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== @@ -242,7 +433,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== @@ -270,7 +461,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== @@ -278,51 +476,603 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.6.tgz#769daf2982d60308bc83d8936eaecb7582463c87" - integrity sha512-TzCtxGgVTEJWWwcYwQhCIQ6WaKlo80/B+Onsk4RRCcYqpYGFcG9etPW94VToGte5AAcxRrhjPUFvUS3Y2qKi4A== + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.4.tgz#04db9ce5a9043d9c635e75ae7969a2cd50ca97ff" + integrity sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-arrow-functions@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz#4f6886c11e423bd69f3ce51dbf42424a5f275514" + integrity sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-async-generator-functions@^7.24.3": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz#2afd4e639e2d055776c9f091b6c0c180ed8cf083" + integrity sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-remap-async-to-generator" "^7.25.0" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/traverse" "^7.25.4" + +"@babel/plugin-transform-async-to-generator@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz#72a3af6c451d575842a7e9b5a02863414355bdcc" + integrity sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA== + dependencies: + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" + +"@babel/plugin-transform-block-scoped-functions@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz#a4251d98ea0c0f399dafe1a35801eaba455bbf1f" + integrity sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-block-scoping@^7.24.1": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz#23a6ed92e6b006d26b1869b1c91d1b917c2ea2ac" + integrity sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-class-properties@^7.24.1": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz#bae7dbfcdcc2e8667355cd1fb5eda298f05189fd" + integrity sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.25.4" + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-class-static-block@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz#c82027ebb7010bc33c116d4b5044fbbf8c05484d" + integrity sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-transform-classes@^7.24.1": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz#d29dbb6a72d79f359952ad0b66d88518d65ef89a" + integrity sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-compilation-targets" "^7.25.2" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-replace-supers" "^7.25.0" + "@babel/traverse" "^7.25.4" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz#4cab3214e80bc71fae3853238d13d097b004c707" + integrity sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/template" "^7.24.7" + +"@babel/plugin-transform-destructuring@^7.24.1": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz#c828e814dbe42a2718a838c2a2e16a408e055550" + integrity sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-dotall-regex@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz#5f8bf8a680f2116a7207e16288a5f974ad47a7a0" + integrity sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-duplicate-keys@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz#dd20102897c9a2324e5adfffb67ff3610359a8ee" + integrity sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-dynamic-import@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz#4d8b95e3bae2b037673091aa09cd33fecd6419f4" + integrity sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-transform-exponentiation-operator@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz#b629ee22645f412024297d5245bce425c31f9b0d" + integrity sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-export-namespace-from@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz#176d52d8d8ed516aeae7013ee9556d540c53f197" + integrity sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-transform-flow-strip-types@^7.24.1": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.25.2.tgz#b3aa251db44959b7a7c82abcd6b4225dec7d2258" + integrity sha512-InBZ0O8tew5V0K6cHcQ+wgxlrjOw1W4wDXLkOTjLRD8GYhTSkxTVBtdy3MMtvYBrbAWa1Qm3hNoTc1620Yj+Mg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/plugin-syntax-flow" "^7.24.7" + +"@babel/plugin-transform-for-of@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz#f25b33f72df1d8be76399e1b8f3f9d366eb5bc70" + integrity sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + +"@babel/plugin-transform-function-name@^7.24.1": + version "7.25.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz#b85e773097526c1a4fc4ba27322748643f26fc37" + integrity sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA== + dependencies: + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/traverse" "^7.25.1" + +"@babel/plugin-transform-json-strings@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz#f3e9c37c0a373fee86e36880d45b3664cedaf73a" + integrity sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-transform-literals@^7.24.1": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz#deb1ad14fc5490b9a65ed830e025bca849d8b5f3" + integrity sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-logical-assignment-operators@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz#a58fb6eda16c9dc8f9ff1c7b1ba6deb7f4694cb0" + integrity sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-transform-member-expression-literals@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz#3b4454fb0e302e18ba4945ba3246acb1248315df" + integrity sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-modules-amd@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz#65090ed493c4a834976a3ca1cde776e6ccff32d7" + integrity sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg== + dependencies: + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-modules-commonjs@^7.24.1": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz#ab6421e564b717cb475d6fff70ae7f103536ea3c" + integrity sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA== + dependencies: + "@babel/helper-module-transforms" "^7.24.8" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-simple-access" "^7.24.7" + +"@babel/plugin-transform-modules-systemjs@^7.24.1": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz#8f46cdc5f9e5af74f3bd019485a6cbe59685ea33" + integrity sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw== + dependencies: + "@babel/helper-module-transforms" "^7.25.0" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" + "@babel/traverse" "^7.25.0" + +"@babel/plugin-transform-modules-umd@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz#edd9f43ec549099620df7df24e7ba13b5c76efc8" + integrity sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A== + dependencies: + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz#9042e9b856bc6b3688c0c2e4060e9e10b1460923" + integrity sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-new-target@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz#31ff54c4e0555cc549d5816e4ab39241dfb6ab00" + integrity sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz#1de4534c590af9596f53d67f52a92f12db984120" + integrity sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz#bea62b538c80605d8a0fac9b40f48e97efa7de63" + integrity sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-transform-object-rest-spread@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz#d13a2b93435aeb8a197e115221cab266ba6e55d6" + integrity sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q== + dependencies: + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.24.7" + +"@babel/plugin-transform-object-super@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz#66eeaff7830bba945dd8989b632a40c04ed625be" + integrity sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + +"@babel/plugin-transform-optional-catch-binding@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz#00eabd883d0dd6a60c1c557548785919b6e717b4" + integrity sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-transform-optional-chaining@^7.24.1", "@babel/plugin-transform-optional-chaining@^7.24.7": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz#bb02a67b60ff0406085c13d104c99a835cdf365d" + integrity sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.24.1", "@babel/plugin-transform-parameters@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz#5881f0ae21018400e320fc7eb817e529d1254b68" + integrity sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-private-methods@^7.24.1": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz#9bbefbe3649f470d681997e0b64a4b254d877242" + integrity sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.25.4" + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-private-property-in-object@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz#4eec6bc701288c1fab5f72e6a4bbc9d67faca061" + integrity sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-transform-property-literals@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz#f0d2ed8380dfbed949c42d4d790266525d63bbdc" + integrity sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-react-display-name@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz#9caff79836803bc666bcfe210aeb6626230c293b" + integrity sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-react-jsx-development@^7.22.5": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz#eaee12f15a93f6496d852509a850085e6361470b" + integrity sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.24.7" + +"@babel/plugin-transform-react-jsx@^7.23.4", "@babel/plugin-transform-react-jsx@^7.24.7": + version "7.25.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.2.tgz#e37e8ebfa77e9f0b16ba07fadcb6adb47412227a" + integrity sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.8" + "@babel/plugin-syntax-jsx" "^7.24.7" + "@babel/types" "^7.25.2" + +"@babel/plugin-transform-react-pure-annotations@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz#bdd9d140d1c318b4f28b29a00fb94f97ecab1595" + integrity sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-regenerator@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz#021562de4534d8b4b1851759fd7af4e05d2c47f8" + integrity sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + regenerator-transform "^0.15.2" + +"@babel/plugin-transform-reserved-words@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz#80037fe4fbf031fc1125022178ff3938bb3743a4" + integrity sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-shorthand-properties@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz#85448c6b996e122fa9e289746140aaa99da64e73" + integrity sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-spread@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz#e8a38c0fde7882e0fb8f160378f74bd885cc7bb3" + integrity sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + +"@babel/plugin-transform-sticky-regex@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz#96ae80d7a7e5251f657b5cf18f1ea6bf926f5feb" + integrity sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-template-literals@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz#a05debb4a9072ae8f985bcf77f3f215434c8f8c8" + integrity sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-typeof-symbol@^7.24.1": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz#383dab37fb073f5bfe6e60c654caac309f92ba1c" + integrity sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/plugin-transform-unicode-escapes@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz#2023a82ced1fb4971630a2e079764502c4148e0e" + integrity sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" -"@babel/runtime@^7.21.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.6.tgz#5b76eb89ad45e2e4a0a8db54c456251469a3358e" - integrity sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw== +"@babel/plugin-transform-unicode-property-regex@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz#9073a4cd13b86ea71c3264659590ac086605bbcd" + integrity sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-regex@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz#dfc3d4a51127108099b19817c0963be6a2adf19f" + integrity sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-sets-regex@^7.24.1": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz#be664c2a0697ffacd3423595d5edef6049e8946c" + integrity sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.25.2" + "@babel/helper-plugin-utils" "^7.24.8" + +"@babel/preset-env@7.24.3": + version "7.24.3" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.3.tgz#f3f138c844ffeeac372597b29c51b5259e8323a3" + integrity sha512-fSk430k5c2ff8536JcPvPWK4tZDwehWLGlBp0wrsBUjZVdeQV6lePbwKWZaZfK2vnh/1kQX1PzAJWsnBmVgGJA== + dependencies: + "@babel/compat-data" "^7.24.1" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-validator-option" "^7.23.5" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.1" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.1" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.1" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.24.1" + "@babel/plugin-syntax-import-attributes" "^7.24.1" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.24.1" + "@babel/plugin-transform-async-generator-functions" "^7.24.3" + "@babel/plugin-transform-async-to-generator" "^7.24.1" + "@babel/plugin-transform-block-scoped-functions" "^7.24.1" + "@babel/plugin-transform-block-scoping" "^7.24.1" + "@babel/plugin-transform-class-properties" "^7.24.1" + "@babel/plugin-transform-class-static-block" "^7.24.1" + "@babel/plugin-transform-classes" "^7.24.1" + "@babel/plugin-transform-computed-properties" "^7.24.1" + "@babel/plugin-transform-destructuring" "^7.24.1" + "@babel/plugin-transform-dotall-regex" "^7.24.1" + "@babel/plugin-transform-duplicate-keys" "^7.24.1" + "@babel/plugin-transform-dynamic-import" "^7.24.1" + "@babel/plugin-transform-exponentiation-operator" "^7.24.1" + "@babel/plugin-transform-export-namespace-from" "^7.24.1" + "@babel/plugin-transform-for-of" "^7.24.1" + "@babel/plugin-transform-function-name" "^7.24.1" + "@babel/plugin-transform-json-strings" "^7.24.1" + "@babel/plugin-transform-literals" "^7.24.1" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.1" + "@babel/plugin-transform-member-expression-literals" "^7.24.1" + "@babel/plugin-transform-modules-amd" "^7.24.1" + "@babel/plugin-transform-modules-commonjs" "^7.24.1" + "@babel/plugin-transform-modules-systemjs" "^7.24.1" + "@babel/plugin-transform-modules-umd" "^7.24.1" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" + "@babel/plugin-transform-new-target" "^7.24.1" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.1" + "@babel/plugin-transform-numeric-separator" "^7.24.1" + "@babel/plugin-transform-object-rest-spread" "^7.24.1" + "@babel/plugin-transform-object-super" "^7.24.1" + "@babel/plugin-transform-optional-catch-binding" "^7.24.1" + "@babel/plugin-transform-optional-chaining" "^7.24.1" + "@babel/plugin-transform-parameters" "^7.24.1" + "@babel/plugin-transform-private-methods" "^7.24.1" + "@babel/plugin-transform-private-property-in-object" "^7.24.1" + "@babel/plugin-transform-property-literals" "^7.24.1" + "@babel/plugin-transform-regenerator" "^7.24.1" + "@babel/plugin-transform-reserved-words" "^7.24.1" + "@babel/plugin-transform-shorthand-properties" "^7.24.1" + "@babel/plugin-transform-spread" "^7.24.1" + "@babel/plugin-transform-sticky-regex" "^7.24.1" + "@babel/plugin-transform-template-literals" "^7.24.1" + "@babel/plugin-transform-typeof-symbol" "^7.24.1" + "@babel/plugin-transform-unicode-escapes" "^7.24.1" + "@babel/plugin-transform-unicode-property-regex" "^7.24.1" + "@babel/plugin-transform-unicode-regex" "^7.24.1" + "@babel/plugin-transform-unicode-sets-regex" "^7.24.1" + "@babel/preset-modules" "0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.4" + babel-plugin-polyfill-regenerator "^0.6.1" + core-js-compat "^3.31.0" + semver "^6.3.1" + +"@babel/preset-flow@7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.24.1.tgz#da7196c20c2d7dd4e98cfd8b192fe53b5eb6f0bb" + integrity sha512-sWCV2G9pcqZf+JHyv/RyqEIpFypxdCSxWIxQjpdaQxenNog7cN1pr76hg8u0Fz8Qgg0H4ETkGcJnXL8d4j0PPA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-validator-option" "^7.23.5" + "@babel/plugin-transform-flow-strip-types" "^7.24.1" + +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.1.tgz#2450c2ac5cc498ef6101a6ca5474de251e33aa95" + integrity sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-validator-option" "^7.23.5" + "@babel/plugin-transform-react-display-name" "^7.24.1" + "@babel/plugin-transform-react-jsx" "^7.23.4" + "@babel/plugin-transform-react-jsx-development" "^7.22.5" + "@babel/plugin-transform-react-pure-annotations" "^7.24.1" + +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + +"@babel/runtime@^7.21.0", "@babel/runtime@^7.8.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.4.tgz#6ef37d678428306e7d75f054d5b1bdb8cf8aa8ee" + integrity sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w== dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.24.6", "@babel/template@^7.3.3": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.6.tgz#048c347b2787a6072b24c723664c8d02b67a44f9" - integrity sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw== - dependencies: - "@babel/code-frame" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/traverse@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.6.tgz#0941ec50cdeaeacad0911eb67ae227a4f8424edc" - integrity sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw== - dependencies: - "@babel/code-frame" "^7.24.6" - "@babel/generator" "^7.24.6" - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-function-name" "^7.24.6" - "@babel/helper-hoist-variables" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/types" "^7.24.6" +"@babel/template@^7.24.0", "@babel/template@^7.24.7", "@babel/template@^7.25.0", "@babel/template@^7.3.3": + version "7.25.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.0.tgz#e733dc3134b4fede528c15bc95e89cb98c52592a" + integrity sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.25.0" + "@babel/types" "^7.25.0" + +"@babel/traverse@^7.24.1", "@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8", "@babel/traverse@^7.25.0", "@babel/traverse@^7.25.1", "@babel/traverse@^7.25.2", "@babel/traverse@^7.25.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.4.tgz#648678046990f2957407e3086e97044f13c3e18e" + integrity sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.25.4" + "@babel/parser" "^7.25.4" + "@babel/template" "^7.25.0" + "@babel/types" "^7.25.4" debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.6", "@babel/types@^7.3.3": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.6.tgz#ba4e1f59870c10dc2fa95a274ac4feec23b21912" - integrity sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ== +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.0", "@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.25.4", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.25.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.4.tgz#6bcb46c72fdf1012a209d016c07f769e10adcb5f" + integrity sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ== dependencies: - "@babel/helper-string-parser" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" + "@babel/helper-string-parser" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": @@ -344,47 +1094,65 @@ dependencies: statuses "^2.0.1" -"@cloudflare/kv-asset-handler@0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.2.tgz#06437b75664729823ac9033b89f06a3b078e4f55" - integrity sha512-EeEjMobfuJrwoctj7FA1y1KEbM0+Q1xSjobIEyie9k4haVEBB7vkDvsasw1pM3rO39mL2akxIAzLMUAtrMHZhA== +"@bundled-es-modules/tough-cookie@^0.1.6": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@bundled-es-modules/tough-cookie/-/tough-cookie-0.1.6.tgz#fa9cd3cedfeecd6783e8b0d378b4a99e52bde5d3" + integrity sha512-dvMHbL464C0zI+Yqxbz6kZ5TOEp7GLW+pry/RWndAR8MJQAXZ2rPmIs8tziTZjeIyhSNZgZbCePtfSbdWqStJw== + dependencies: + "@types/tough-cookie" "^4.0.5" + tough-cookie "^4.1.4" + +"@cloudflare/kv-asset-handler@0.3.4": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.4.tgz#5cc152847c8ae4d280ec5d7f4f6ba8c976b585c3" + integrity sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q== dependencies: mime "^3.0.0" -"@cloudflare/workerd-darwin-64@1.20240610.1": - version "1.20240610.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240610.1.tgz#417d18708664ec9662d74280f1f78cd50c209035" - integrity sha512-YanZ1iXgMGaUWlleB5cswSE6qbzyjQ8O7ENWZcPAcZZ6BfuL7q3CWi0t9iM1cv2qx92rRztsRTyjcfq099++XQ== +"@cloudflare/workerd-darwin-64@1.20240821.1": + version "1.20240821.1" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240821.1.tgz#06b8fcd372ab5ceb44c2b30892edccaa8cd97003" + integrity sha512-CDBpfZKrSy4YrIdqS84z67r3Tzal2pOhjCsIb63IuCnvVes59/ft1qhczBzk9EffeOE2iTCrA4YBT7Sbn7USew== -"@cloudflare/workerd-darwin-arm64@1.20240610.1": - version "1.20240610.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240610.1.tgz#740764dc991414c247cb72dd2c74985196937fa2" - integrity sha512-bRe/y/LKjIgp3L2EHjc+CvoCzfHhf4aFTtOBkv2zW+VToNJ4KlXridndf7LvR9urfsFRRo9r4TXCssuKaU+ypQ== +"@cloudflare/workerd-darwin-arm64@1.20240821.1": + version "1.20240821.1" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240821.1.tgz#b277d276d016ea41686ba44bf43735f6563bb91f" + integrity sha512-Q+9RedvNbPcEt/dKni1oN94OxbvuNAeJkgHmrLFTGF8zu21wzOhVkQeRNxcYxrMa9mfStc457NAg13OVCj2kHQ== -"@cloudflare/workerd-linux-64@1.20240610.1": - version "1.20240610.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240610.1.tgz#62ed716e4b216fd9ca5e40c8fcecf20c16d8fb1b" - integrity sha512-2zDcadR7+Gs9SjcMXmwsMji2Xs+yASGNA2cEHDuFc4NMUup+eL1mkzxc/QzvFjyBck98e92rBjMZt2dVscpGKg== +"@cloudflare/workerd-linux-64@1.20240821.1": + version "1.20240821.1" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240821.1.tgz#9e16da0858674d1bb0ece41b482fb161f9da6646" + integrity sha512-j6z3KsPtawrscoLuP985LbqFrmsJL6q1mvSXOXTqXGODAHIzGBipHARdOjms3UQqovzvqB2lQaQsZtLBwCZxtA== -"@cloudflare/workerd-linux-arm64@1.20240610.1": - version "1.20240610.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240610.1.tgz#c93d924618d69c8eddfe126da321d2efc3865ed0" - integrity sha512-7y41rPi5xmIYJN8CY+t3RHnjLL0xx/WYmaTd/j552k1qSr02eTE2o/TGyWZmGUC+lWnwdPQJla0mXbvdqgRdQg== +"@cloudflare/workerd-linux-arm64@1.20240821.1": + version "1.20240821.1" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240821.1.tgz#c9eec3f830a4bbf1f80b3c828783db8025de69d9" + integrity sha512-I9bHgZOxJQW0CV5gTdilyxzTG7ILzbTirehQWgfPx9X77E/7eIbR9sboOMgyeC69W4he0SKtpx0sYZuTJu4ERw== -"@cloudflare/workerd-windows-64@1.20240610.1": - version "1.20240610.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240610.1.tgz#6e55ba3c253e33c94cf0d2e2f0ac8f7e30e072bb" - integrity sha512-B0LyT3DB6rXHWNptnntYHPaoJIy0rXnGfeDBM3nEVV8JIsQrx8MEFn2F2jYioH1FkUVavsaqKO/zUosY3tZXVA== +"@cloudflare/workerd-windows-64@1.20240821.1": + version "1.20240821.1" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240821.1.tgz#256d61b5dd327f2b86fa4a522fe977f97aa188a2" + integrity sha512-keC97QPArs6LWbPejQM7/Y8Jy8QqyaZow4/ZdsGo+QjlOLiZRDpAenfZx3CBUoWwEeFwQTl2FLO+8hV1SWFFYw== -"@commitlint/cli@19.3.0": - version "19.3.0" - resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-19.3.0.tgz#44e6da9823a01f0cdcc43054bbefdd2c6c5ddf39" - integrity sha512-LgYWOwuDR7BSTQ9OLZ12m7F/qhNY+NpAyPBgo4YNMkACE7lGuUnuQq1yi9hz1KA4+3VqpOYl8H1rY/LYK43v7g== +"@cloudflare/workers-shared@0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workers-shared/-/workers-shared-0.3.0.tgz#38e462925a2fbe974cd8108ca0a39756509c8e8f" + integrity sha512-cqtLW1QiBC/ABaZIhAdyGCsnHHY6pAb6hsVUZg82Co2gQtf/faxRYV1FgpCwUYroTdk6A66xUMSTmFqreKCJow== + +"@cloudflare/workers-types@^4.20240529.0": + version "4.20240821.1" + resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-4.20240821.1.tgz#d60219e1054f0f73e325dd11c1081df1c0d851c4" + integrity sha512-icAkbnAqgVl6ef9lgLTom8na+kj2RBw2ViPAQ586hbdj0xZcnrjK7P46Eu08OU9D/lNDgN2sKU/sxhe2iK/gIg== + +"@commitlint/cli@19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-19.4.0.tgz#9f93d3ed07e531fcfa371015c8c87e0aa26d974f" + integrity sha512-sJX4J9UioVwZHq7JWM9tjT5bgWYaIN3rC4FP7YwfEwBYiIO+wMyRttRvQLNkow0vCdM0D67r9NEWU0Ui03I4Eg== dependencies: "@commitlint/format" "^19.3.0" "@commitlint/lint" "^19.2.2" - "@commitlint/load" "^19.2.0" - "@commitlint/read" "^19.2.1" + "@commitlint/load" "^19.4.0" + "@commitlint/read" "^19.4.0" "@commitlint/types" "^19.0.3" execa "^8.0.1" yargs "^17.0.0" @@ -448,10 +1216,10 @@ "@commitlint/rules" "^19.0.3" "@commitlint/types" "^19.0.3" -"@commitlint/load@^19.2.0": - version "19.2.0" - resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-19.2.0.tgz#3ca51fdead4f1e1e09c9c7df343306412b1ef295" - integrity sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ== +"@commitlint/load@^19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-19.4.0.tgz#7df034e226e300fd577d3f63a72d790d5c821f53" + integrity sha512-I4lCWaEZYQJ1y+Y+gdvbGAx9pYPavqZAZ3/7/8BpWh+QjscAn8AjsUpLV2PycBsEx7gupq5gM4BViV9xwTIJuw== dependencies: "@commitlint/config-validator" "^19.0.3" "@commitlint/execute-rule" "^19.0.0" @@ -478,10 +1246,10 @@ conventional-changelog-angular "^7.0.0" conventional-commits-parser "^5.0.0" -"@commitlint/read@^19.2.1": - version "19.2.1" - resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-19.2.1.tgz#7296b99c9a989e60e5927fff8388a1dd44299c2f" - integrity sha512-qETc4+PL0EUv7Q36lJbPG+NJiBOGg7SSC7B5BsPWOmei+Dyif80ErfWQ0qXoW9oCh7GTpTNRoaVhiI8RbhuaNw== +"@commitlint/read@^19.4.0": + version "19.4.0" + resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-19.4.0.tgz#3866b1f9a272ef6a388986efa349d24228fc8b00" + integrity sha512-r95jLOEZzKDakXtnQub+zR3xjdnrl2XzerPwm7ch1/cc5JGq04tyaNpa6ty0CRCWdVrk4CZHhqHozb8yZwy2+g== dependencies: "@commitlint/top-level" "^19.0.0" "@commitlint/types" "^19.0.3" @@ -532,31 +1300,31 @@ "@types/conventional-commits-parser" "^5.0.0" chalk "^5.3.0" -"@cspell/cspell-bundled-dicts@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.9.0.tgz#4c9ecb62a824bd8b21ffd4470302eba20e47c988" - integrity sha512-Dxfuva7zlcI2X/PulDI7bfJBB1De4OuulR2prVpDuGLk3zAiFO7t4d2bmdWxfowhtm1agSqY03uZOTk8fTppuQ== +"@cspell/cspell-bundled-dicts@8.14.2": + version "8.14.2" + resolved "https://registry.yarnpkg.com/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.14.2.tgz#746706485228e055ff342a66191cb6b9e58e748a" + integrity sha512-Kv2Utj/RTSxfufGXkkoTZ/3ErCsYWpCijtDFr/FwSsM7mC0PzLpdlcD9xjtgrJO5Kwp7T47iTG21U4Mwddyi8Q== dependencies: "@cspell/dict-ada" "^4.0.2" - "@cspell/dict-aws" "^4.0.2" + "@cspell/dict-aws" "^4.0.3" "@cspell/dict-bash" "^4.1.3" - "@cspell/dict-companies" "^3.1.2" - "@cspell/dict-cpp" "^5.1.10" + "@cspell/dict-companies" "^3.1.4" + "@cspell/dict-cpp" "^5.1.12" "@cspell/dict-cryptocurrencies" "^5.0.0" "@cspell/dict-csharp" "^4.0.2" - "@cspell/dict-css" "^4.0.12" + "@cspell/dict-css" "^4.0.13" "@cspell/dict-dart" "^2.0.3" "@cspell/dict-django" "^4.1.0" "@cspell/dict-docker" "^1.1.7" "@cspell/dict-dotnet" "^5.0.2" "@cspell/dict-elixir" "^4.0.3" - "@cspell/dict-en-common-misspellings" "^2.0.2" + "@cspell/dict-en-common-misspellings" "^2.0.4" "@cspell/dict-en-gb" "1.1.33" - "@cspell/dict-en_us" "^4.3.22" + "@cspell/dict-en_us" "^4.3.23" "@cspell/dict-filetypes" "^3.0.4" "@cspell/dict-fonts" "^4.0.0" "@cspell/dict-fsharp" "^1.0.1" - "@cspell/dict-fullstack" "^3.1.8" + "@cspell/dict-fullstack" "^3.2.0" "@cspell/dict-gaming-terms" "^1.0.5" "@cspell/dict-git" "^3.0.0" "@cspell/dict-golang" "^6.0.9" @@ -566,83 +1334,83 @@ "@cspell/dict-html-symbol-entities" "^4.0.0" "@cspell/dict-java" "^5.0.7" "@cspell/dict-julia" "^1.0.1" - "@cspell/dict-k8s" "^1.0.5" + "@cspell/dict-k8s" "^1.0.6" "@cspell/dict-latex" "^4.0.0" "@cspell/dict-lorem-ipsum" "^4.0.0" "@cspell/dict-lua" "^4.0.3" "@cspell/dict-makefile" "^1.0.0" "@cspell/dict-monkeyc" "^1.0.6" "@cspell/dict-node" "^5.0.1" - "@cspell/dict-npm" "^5.0.16" + "@cspell/dict-npm" "^5.0.18" "@cspell/dict-php" "^4.0.8" - "@cspell/dict-powershell" "^5.0.4" + "@cspell/dict-powershell" "^5.0.5" "@cspell/dict-public-licenses" "^2.0.7" - "@cspell/dict-python" "^4.2.1" + "@cspell/dict-python" "^4.2.4" "@cspell/dict-r" "^2.0.1" "@cspell/dict-ruby" "^5.0.2" - "@cspell/dict-rust" "^4.0.4" - "@cspell/dict-scala" "^5.0.2" - "@cspell/dict-software-terms" "^3.4.6" - "@cspell/dict-sql" "^2.1.3" + "@cspell/dict-rust" "^4.0.5" + "@cspell/dict-scala" "^5.0.3" + "@cspell/dict-software-terms" "^4.0.6" + "@cspell/dict-sql" "^2.1.5" "@cspell/dict-svelte" "^1.0.2" "@cspell/dict-swift" "^2.0.1" "@cspell/dict-terraform" "^1.0.0" - "@cspell/dict-typescript" "^3.1.5" + "@cspell/dict-typescript" "^3.1.6" "@cspell/dict-vue" "^3.0.0" -"@cspell/cspell-json-reporter@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.9.0.tgz#7ddaa8ba860346f077c641fb71892fc8c04e1be5" - integrity sha512-+m2HoYTqdI76Zt27CyCpFCAxEUlTMnJnC76MpuQEd21C72qXWmaYdcVzJ7GnVXtTY6cofefUy/X3zgkUBW/bqg== +"@cspell/cspell-json-reporter@8.14.2": + version "8.14.2" + resolved "https://registry.yarnpkg.com/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.14.2.tgz#c05e6e0d6e63072e3f416c9b3088aa8329de19a1" + integrity sha512-TZavcnNIZKX1xC/GNj80RgFVKHCT4pHT0qm9jCsQFH2QJfyCrUlkEvotKGSQ04lAyCwWg6Enq95qhouF8YbKUQ== dependencies: - "@cspell/cspell-types" "8.9.0" + "@cspell/cspell-types" "8.14.2" -"@cspell/cspell-pipe@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-pipe/-/cspell-pipe-8.9.0.tgz#207d4bc993c235dfaa6085473ef150e46905a23c" - integrity sha512-N3Nv9F/1LyUabd1lda+N7tU+UpY7lp8mZvG7ZTxhoB8vfw/Yf3f8NlQ5awSYear2Q+N0RoGyyLaaqUY6nUQvOQ== +"@cspell/cspell-pipe@8.14.2": + version "8.14.2" + resolved "https://registry.yarnpkg.com/@cspell/cspell-pipe/-/cspell-pipe-8.14.2.tgz#8f9df27fff5c6c55e29fa6967768a38b5494a665" + integrity sha512-aWMoXZAXEre0/M9AYWOW33YyOJZ06i4vvsEpWBDWpHpWQEmsR/7cMMgld8Pp3wlEjIUclUAKTYmrZ61PFWU/og== -"@cspell/cspell-resolver@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-resolver/-/cspell-resolver-8.9.0.tgz#96909ab32714e53c3b2e60ade3b44afecfebd83a" - integrity sha512-52FCYcrZZhdAKkGoHss000nUk2mHkujxHJOfh+KMh2p15igmPW0AR7/VFKSS7zVkkLfAhQfWxoqQLkoE+yvccA== +"@cspell/cspell-resolver@8.14.2": + version "8.14.2" + resolved "https://registry.yarnpkg.com/@cspell/cspell-resolver/-/cspell-resolver-8.14.2.tgz#0cfaa0d0f613feab76ddb30a1d0a60d428726a0c" + integrity sha512-pSyBsAvslaN0dx0pHdvECJEuFDDBJGAD6G8U4BVbIyj2OPk0Ox0HrZIj6csYxxoJERAgNO/q7yCPwa4j9NNFXg== dependencies: global-directory "^4.0.1" -"@cspell/cspell-service-bus@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-service-bus/-/cspell-service-bus-8.9.0.tgz#d2ad4c1327392f38333a98e01be974800f8fff1e" - integrity sha512-R8MlY3dp4my/VZp2xhvkUcXbLsTZUSNuxsOFzpPYLQhtrei0ReEcaDTg2JEU1wfHnREGG8GYlWh9BEryx8AZYA== +"@cspell/cspell-service-bus@8.14.2": + version "8.14.2" + resolved "https://registry.yarnpkg.com/@cspell/cspell-service-bus/-/cspell-service-bus-8.14.2.tgz#f0d317fd4de99700b2b7f10b05d88dc2ea55d7f8" + integrity sha512-WUF7xf3YgXYIqjmBwLcVugYIrYL4WfXchgSo9rmbbnOcAArzsK+HKfzb4AniZAJ1unxcIQ0JnVlRmnCAKPjjLg== -"@cspell/cspell-types@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-types/-/cspell-types-8.9.0.tgz#7b1c3987634391d2c4e0da34497782c51d23d00d" - integrity sha512-YeL14G+tIh92WvO5K9+WBCjckRQAApeSNkIavx+7+IF+MUoGPvVbTA881q15zwoPRPtOJQ8wEbI6zJH5ykKFfw== +"@cspell/cspell-types@8.14.2": + version "8.14.2" + resolved "https://registry.yarnpkg.com/@cspell/cspell-types/-/cspell-types-8.14.2.tgz#e1bae42766b43ff6d943b57bb7830bc873f25c94" + integrity sha512-MRY8MjBNOKGMDSkxAKueYAgVL43miO+lDcLCBBP+7cNXqHiUFMIZteONcGp3kJT0dWS04dN6lKAXvaNF0aWcng== "@cspell/dict-ada@^4.0.2": version "4.0.2" resolved "https://registry.yarnpkg.com/@cspell/dict-ada/-/dict-ada-4.0.2.tgz#8da2216660aeb831a0d9055399a364a01db5805a" integrity sha512-0kENOWQeHjUlfyId/aCM/mKXtkEgV0Zu2RhUXCBr4hHo9F9vph+Uu8Ww2b0i5a4ZixoIkudGA+eJvyxrG1jUpA== -"@cspell/dict-aws@^4.0.2": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-aws/-/dict-aws-4.0.2.tgz#6498f1c983c80499054bb31b772aa9562f3aaaed" - integrity sha512-aNGHWSV7dRLTIn8WJemzLoMF62qOaiUQlgnsCwH5fRCD/00gsWCwg106pnbkmK4AyabyxzneOV4dfecDJWkSxw== +"@cspell/dict-aws@^4.0.3": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@cspell/dict-aws/-/dict-aws-4.0.3.tgz#7d36d4d5439d1c39b815e0ae19f79e48a823e047" + integrity sha512-0C0RQ4EM29fH0tIYv+EgDQEum0QI6OrmjENC9u98pB8UcnYxGG/SqinuPxo+TgcEuInj0Q73MsBpJ1l5xUnrsw== "@cspell/dict-bash@^4.1.3": version "4.1.3" resolved "https://registry.yarnpkg.com/@cspell/dict-bash/-/dict-bash-4.1.3.tgz#25fba40825ac10083676ab2c777e471c3f71b36e" integrity sha512-tOdI3QVJDbQSwPjUkOiQFhYcu2eedmX/PtEpVWg0aFps/r6AyjUQINtTgpqMYnYuq8O1QUIQqnpx21aovcgZCw== -"@cspell/dict-companies@^3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-companies/-/dict-companies-3.1.2.tgz#b335fe5b8847a23673bc4b964ca584339ca669a2" - integrity sha512-OwR5i1xbYuJX7FtHQySmTy3iJtPV1rZQ3jFCxFGwrA1xRQ4rtRcDQ+sTXBCIAoJHkXa84f9J3zsngOKmMGyS/w== +"@cspell/dict-companies@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@cspell/dict-companies/-/dict-companies-3.1.4.tgz#2e7094416432b8547ec335683f5aac9a49dce47e" + integrity sha512-y9e0amzEK36EiiKx3VAA+SHQJPpf2Qv5cCt5eTUSggpTkiFkCh6gRKQ97rVlrKh5GJrqinDwYIJtTsxuh2vy2Q== -"@cspell/dict-cpp@^5.1.10": - version "5.1.10" - resolved "https://registry.yarnpkg.com/@cspell/dict-cpp/-/dict-cpp-5.1.10.tgz#457881ad9425ea0af71e4c1f9b108677a555fe79" - integrity sha512-BmIF0sAz2BgGEOwzYIeEm9ALneDjd1tcTbFbo+A1Hcq3zOKP8yViSgxS9CEN30KOZIyph6Tldp531UPEpoEl0Q== +"@cspell/dict-cpp@^5.1.12": + version "5.1.16" + resolved "https://registry.yarnpkg.com/@cspell/dict-cpp/-/dict-cpp-5.1.16.tgz#e6557d5b916ebff02045b60f7016749e085921b0" + integrity sha512-32fU5RkuOM55IRcxjByiSoKbjr+C4danDfYjHaQNRWdvjzJzci3fLDGA2wTXiclkgDODxGiV8LCTUwCz+3TNWA== "@cspell/dict-cryptocurrencies@^5.0.0": version "5.0.0" @@ -654,10 +1422,10 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-csharp/-/dict-csharp-4.0.2.tgz#e55659dbe594e744d86b1baf0f3397fe57b1e283" integrity sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g== -"@cspell/dict-css@^4.0.12": - version "4.0.12" - resolved "https://registry.yarnpkg.com/@cspell/dict-css/-/dict-css-4.0.12.tgz#59abf3512ae729835c933c38f64a3d8a5f09ce3d" - integrity sha512-vGBgPM92MkHQF5/2jsWcnaahOZ+C6OE/fPvd5ScBP72oFY9tn5GLuomcyO0z8vWCr2e0nUSX1OGimPtcQAlvSw== +"@cspell/dict-css@^4.0.13": + version "4.0.13" + resolved "https://registry.yarnpkg.com/@cspell/dict-css/-/dict-css-4.0.13.tgz#b95310ba67694d25bcb055786dde65e091621d14" + integrity sha512-WfOQkqlAJTo8eIQeztaH0N0P+iF5hsJVKFuhy4jmARPISy8Efcv8QXk2/IVbmjJH0/ZV7dKRdnY5JFVXuVz37g== "@cspell/dict-dart@^2.0.3": version "2.0.3" @@ -680,29 +1448,29 @@ integrity sha512-XlXHAr822euV36GGsl2J1CkBIVg3fZ6879ZOg5dxTIssuhUOCiV2BuzKZmt6aIFmcdPmR14+9i9Xq+3zuxeX0A== "@cspell/dict-dotnet@^5.0.2": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-dotnet/-/dict-dotnet-5.0.2.tgz#d89ca8fa2e546b5e1b1f1288746d26bb627d9f38" - integrity sha512-UD/pO2A2zia/YZJ8Kck/F6YyDSpCMq0YvItpd4YbtDVzPREfTZ48FjZsbYi4Jhzwfvc6o8R56JusAE58P+4sNQ== + version "5.0.5" + resolved "https://registry.yarnpkg.com/@cspell/dict-dotnet/-/dict-dotnet-5.0.5.tgz#0f614ef6fa052e7598a6fe20770a1e5bb19f0de1" + integrity sha512-gjg0L97ee146wX47dnA698cHm85e7EOpf9mVrJD8DmEaqoo/k1oPy2g7c7LgKxK9XnqwoXxhLNnngPrwXOoEtQ== "@cspell/dict-elixir@^4.0.3": version "4.0.3" resolved "https://registry.yarnpkg.com/@cspell/dict-elixir/-/dict-elixir-4.0.3.tgz#57c25843e46cf3463f97da72d9ef8e37c818296f" integrity sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q== -"@cspell/dict-en-common-misspellings@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.2.tgz#7620dcfa9b4244b1c044f38c7e123d06b52c81a6" - integrity sha512-LA8BO0RaoJD+ExHzK5mz+t9RQ0HaBPDxgR4JTfG8YKJP5keO+pFMH9ZMZphKPjW46QYUZb6Ta1HIRikBEOZfYw== +"@cspell/dict-en-common-misspellings@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.4.tgz#725c5b2c83faff71fcd2183dd04a154c78eed674" + integrity sha512-lvOiRjV/FG4pAGZL3PN2GCVHSTCE92cwhfLGGkOsQtxSmef6WCHfHwp9auafkBlX0yFQSKDfq6/TlpQbjbJBtQ== "@cspell/dict-en-gb@1.1.33": version "1.1.33" resolved "https://registry.yarnpkg.com/@cspell/dict-en-gb/-/dict-en-gb-1.1.33.tgz#7f1fd90fc364a5cb77111b5438fc9fcf9cc6da0e" integrity sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g== -"@cspell/dict-en_us@^4.3.22": - version "4.3.22" - resolved "https://registry.yarnpkg.com/@cspell/dict-en_us/-/dict-en_us-4.3.22.tgz#66aa9de60d97bc58112c68007a145d02f108c428" - integrity sha512-UegkIQhKkTLGarpYNV5ybW2JHzuxhDMOF9q9TW37iG8YoHp5jeVW3C0p3cH9nHWMwEjPinJFfxBd1LPRxGv5dQ== +"@cspell/dict-en_us@^4.3.23": + version "4.3.23" + resolved "https://registry.yarnpkg.com/@cspell/dict-en_us/-/dict-en_us-4.3.23.tgz#3362b75a5051405816728ea1bb5ce997582ed383" + integrity sha512-l0SoEQBsi3zDSl3OuL4/apBkxjuj4hLIg/oy6+gZ7LWh03rKdF6VNtSZNXWAmMY+pmb1cGA3ouleTiJIglbsIg== "@cspell/dict-filetypes@^3.0.4": version "3.0.4" @@ -719,10 +1487,10 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-fsharp/-/dict-fsharp-1.0.1.tgz#d62c699550a39174f182f23c8c1330a795ab5f53" integrity sha512-23xyPcD+j+NnqOjRHgW3IU7Li912SX9wmeefcY0QxukbAxJ/vAN4rBpjSwwYZeQPAn3fxdfdNZs03fg+UM+4yQ== -"@cspell/dict-fullstack@^3.1.8": - version "3.1.8" - resolved "https://registry.yarnpkg.com/@cspell/dict-fullstack/-/dict-fullstack-3.1.8.tgz#1bbfa0a165346f6eff9894cf965bf3ce26552797" - integrity sha512-YRlZupL7uqMCtEBK0bDP9BrcPnjDhz7m4GBqCc1EYqfXauHbLmDT8ELha7T/E7wsFKniHSjzwDZzhNXo2lusRQ== +"@cspell/dict-fullstack@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-fullstack/-/dict-fullstack-3.2.0.tgz#16dd2bd3f03166c8f48600ef032ae1ce184c7b8e" + integrity sha512-sIGQwU6G3rLTo+nx0GKyirR5dQSFeTIzFTOrURw51ISf+jKG9a3OmvsVtc2OANfvEAOLOC9Wfd8WYhmsO8KRDQ== "@cspell/dict-gaming-terms@^1.0.5": version "1.0.5" @@ -735,9 +1503,9 @@ integrity sha512-simGS/lIiXbEaqJu9E2VPoYW1OTC2xrwPPXNXFMa2uo/50av56qOuaxDrZ5eH1LidFXwoc8HROCHYeKoNrDLSw== "@cspell/dict-golang@^6.0.9": - version "6.0.9" - resolved "https://registry.yarnpkg.com/@cspell/dict-golang/-/dict-golang-6.0.9.tgz#b26ee13fb34a8cd40fb22380de8a46b25739fcab" - integrity sha512-etDt2WQauyEQDA+qPS5QtkYTb2I9l5IfQftAllVoB1aOrT6bxxpHvMEpJ0Hsn/vezxrCqa/BmtUbRxllIxIuSg== + version "6.0.12" + resolved "https://registry.yarnpkg.com/@cspell/dict-golang/-/dict-golang-6.0.12.tgz#a9d4c53edfec34d06a226a9af6af0df899bd720f" + integrity sha512-LEPeoqd+4O+vceHF73S7D7+LYfrAjOvp4Dqzh4MT30ruzlQ77yHRSuYOJtrFN1GK5ntAt/ILSVOKg9sgsz1Llg== "@cspell/dict-google@^1.0.1": version "1.0.1" @@ -769,10 +1537,10 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-julia/-/dict-julia-1.0.1.tgz#900001417f1c4ea689530adfcc034c848458a0aa" integrity sha512-4JsCLCRhhLMLiaHpmR7zHFjj1qOauzDI5ZzCNQS31TUMfsOo26jAKDfo0jljFAKgw5M2fEG7sKr8IlPpQAYrmQ== -"@cspell/dict-k8s@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@cspell/dict-k8s/-/dict-k8s-1.0.5.tgz#4a4011d9f2f3ab628658573c5f16c0e6dbe30c29" - integrity sha512-Cj+/ZV4S+MKlwfocSJZqe/2UAd/sY8YtlZjbK25VN1nCnrsKrBjfkX29vclwSj1U9aJg4Z9jw/uMjoaKu9ZrpQ== +"@cspell/dict-k8s@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@cspell/dict-k8s/-/dict-k8s-1.0.6.tgz#d46c97136f1504b65dfb6a188005d4ac81d3f461" + integrity sha512-srhVDtwrd799uxMpsPOQqeDJY+gEocgZpoK06EFrb4GRYGhv7lXo9Fb+xQMyQytzOW9dw4DNOEck++nacDuymg== "@cspell/dict-latex@^4.0.0": version "4.0.0" @@ -804,30 +1572,30 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-node/-/dict-node-5.0.1.tgz#77e17c576a897a3391fce01c1cc5da60bb4c2268" integrity sha512-lax/jGz9h3Dv83v8LHa5G0bf6wm8YVRMzbjJPG/9rp7cAGPtdrga+XANFq+B7bY5+jiSA3zvj10LUFCFjnnCCg== -"@cspell/dict-npm@^5.0.16": - version "5.0.16" - resolved "https://registry.yarnpkg.com/@cspell/dict-npm/-/dict-npm-5.0.16.tgz#696883918a9876ffd20d5f975bde74a03d27d80e" - integrity sha512-ZWPnLAziEcSCvV0c8k9Qj88pfMu+wZwM5Qks87ShsfBgI8uLZ9tGHravA7gmjH1Gd7Bgxy2ulvXtSqIWPh1lew== +"@cspell/dict-npm@^5.0.18": + version "5.0.18" + resolved "https://registry.yarnpkg.com/@cspell/dict-npm/-/dict-npm-5.0.18.tgz#7ec5640c97bd25a64de0c9e74eb19dda86fba025" + integrity sha512-weMTyxWpzz19q4wv9n183BtFvdD5fCjtze+bFKpl+4rO/YlPhHL2cXLAeexJz/VDSBecwX4ybTZYoknd1h2J4w== "@cspell/dict-php@^4.0.8": - version "4.0.8" - resolved "https://registry.yarnpkg.com/@cspell/dict-php/-/dict-php-4.0.8.tgz#fedce3109dff13a0f3d8d88ba604d6edd2b9fb70" - integrity sha512-TBw3won4MCBQ2wdu7kvgOCR3dY2Tb+LJHgDUpuquy3WnzGiSDJ4AVelrZdE1xu7mjFJUr4q48aB21YT5uQqPZA== + version "4.0.10" + resolved "https://registry.yarnpkg.com/@cspell/dict-php/-/dict-php-4.0.10.tgz#e2ad4d3e30ec009824d9663a795f6281ae39caaf" + integrity sha512-NfTZdp6kcZDF1PvgQ6cY0zE4FUO5rSwNmBH/iwCBuaLfJAFQ97rgjxo+D2bic4CFwNjyHutnHPtjJBRANO5XQw== -"@cspell/dict-powershell@^5.0.4": - version "5.0.4" - resolved "https://registry.yarnpkg.com/@cspell/dict-powershell/-/dict-powershell-5.0.4.tgz#db2bc6a86700a2f829dc1b3b04f6cb3a916fd928" - integrity sha512-eosDShapDgBWN9ULF7+sRNdUtzRnUdsfEdBSchDm8FZA4HOqxUSZy3b/cX/Rdw0Fnw0AKgk0kzgXw7tS6vwJMQ== +"@cspell/dict-powershell@^5.0.5": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@cspell/dict-powershell/-/dict-powershell-5.0.6.tgz#3f2810068f9383554090d379b8b00ec7c5996eac" + integrity sha512-BSi9tmnT7jgNsH5SaHSg70aw+4YwTjkkZBfhHtin0r6AMV2RaiLzsBPvzZGXOcm0yTvl975HYoKMqflXIlk2RA== "@cspell/dict-public-licenses@^2.0.7": - version "2.0.7" - resolved "https://registry.yarnpkg.com/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.7.tgz#ccd67a91a6bd5ed4b5117c2f34e9361accebfcb7" - integrity sha512-KlBXuGcN3LE7tQi/GEqKiDewWGGuopiAD0zRK1QilOx5Co8XAvs044gk4MNIQftc8r0nHeUI+irJKLGcR36DIQ== + version "2.0.8" + resolved "https://registry.yarnpkg.com/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.8.tgz#ed8c3b5b22f28129cf3517821740599f05733b68" + integrity sha512-Sup+tFS7cDV0fgpoKtUqEZ6+fA/H+XUgBiqQ/Fbs6vUE3WCjJHOIVsP+udHuyMH7iBfJ4UFYOYeORcY4EaKdMg== -"@cspell/dict-python@^4.2.1": - version "4.2.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-python/-/dict-python-4.2.1.tgz#ef0c4cc1b6d096e8ff65faee3fe15eaf6457a92e" - integrity sha512-9X2jRgyM0cxBoFQRo4Zc8oacyWnXi+0/bMI5FGibZNZV4y/o9UoFEr6agjU260/cXHTjIdkX233nN7eb7dtyRg== +"@cspell/dict-python@^4.2.4": + version "4.2.5" + resolved "https://registry.yarnpkg.com/@cspell/dict-python/-/dict-python-4.2.5.tgz#f527c8f8886b080329709247b06acb48430cb8b1" + integrity sha512-HJ7xY2kg1Lg1lB4zFnniqvICFx8mj5f0Ij42HcRrUt980loFFml/MXnYR8Zn9sPzNyH4AYe1ZyLI/oPHH6TYqA== dependencies: "@cspell/dict-data-science" "^2.0.1" @@ -837,29 +1605,29 @@ integrity sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA== "@cspell/dict-ruby@^5.0.2": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-ruby/-/dict-ruby-5.0.2.tgz#cf1a71380c633dec0857143d3270cb503b10679a" - integrity sha512-cIh8KTjpldzFzKGgrqUX4bFyav5lC52hXDKo4LbRuMVncs3zg4hcSf4HtURY+f2AfEZzN6ZKzXafQpThq3dl2g== + version "5.0.3" + resolved "https://registry.yarnpkg.com/@cspell/dict-ruby/-/dict-ruby-5.0.3.tgz#614e9a3d4dcd720e750c037b9dfb6001da8b25e0" + integrity sha512-V1xzv9hN6u8r6SM4CkYdsxs4ov8gjXXo0Twfx5kWhLXbEVxTXDMt7ohLTqpy2XlF5mutixZdbHMeFiAww8v+Ug== -"@cspell/dict-rust@^4.0.4": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@cspell/dict-rust/-/dict-rust-4.0.4.tgz#72f21d18aa46288b7da00e7d91b3ed4a23b386e8" - integrity sha512-v9/LcZknt/Xq7m1jdTWiQEtmkVVKdE1etAfGL2sgcWpZYewEa459HeWndNA0gfzQrpWX9sYay18mt7pqClJEdA== +"@cspell/dict-rust@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@cspell/dict-rust/-/dict-rust-4.0.5.tgz#41f3e26fdd3d121c3a24c122d4a703abbb48c4c3" + integrity sha512-DIvlPRDemjKQy8rCqftAgGNZxY5Bg+Ps7qAIJjxkSjmMETyDgl0KTVuaJPt7EK4jJt6uCZ4ILy96npsHDPwoXA== -"@cspell/dict-scala@^5.0.2": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-scala/-/dict-scala-5.0.2.tgz#d732ab24610cc9f6916fb8148f6ef5bdd945fc47" - integrity sha512-v97ClgidZt99JUm7OjhQugDHmhx4U8fcgunHvD/BsXWjXNj4cTr0m0YjofyZoL44WpICsNuFV9F/sv9OM5HUEw== +"@cspell/dict-scala@^5.0.3": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@cspell/dict-scala/-/dict-scala-5.0.3.tgz#85a469b2d139766b6307befc89243928e3d82b39" + integrity sha512-4yGb4AInT99rqprxVNT9TYb1YSpq58Owzq7zi3ZS5T0u899Y4VsxsBiOgHnQ/4W+ygi+sp+oqef8w8nABR2lkg== -"@cspell/dict-software-terms@3.4.6", "@cspell/dict-software-terms@^3.4.6": - version "3.4.6" - resolved "https://registry.yarnpkg.com/@cspell/dict-software-terms/-/dict-software-terms-3.4.6.tgz#892562e12acc85b6de849b9390e53765c8a3cbe3" - integrity sha512-Cap+WL4iM9NgwxdVIa93aDEGKGNm1t+DLJTnjoWkGHXxSBPG8Kcbnlss6mTtwLv9/NYPmQsmJi5qHXruuHx2ow== +"@cspell/dict-software-terms@4.1.0", "@cspell/dict-software-terms@^4.0.6": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-software-terms/-/dict-software-terms-4.1.0.tgz#a577b665f821cf7c3cd3f3e6e383705ffed166d1" + integrity sha512-PSnC2kNyg7HBG+neIuFDCH4PETWPkZaFEOvqjfKueoO4Fa3M8nQrYN9jNxAAbdPoL9rxSPdncSvvEnJs1ng/uw== -"@cspell/dict-sql@^2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@cspell/dict-sql/-/dict-sql-2.1.3.tgz#8d9666a82e35b310d0be4064032c0d891fbd2702" - integrity sha512-SEyTNKJrjqD6PAzZ9WpdSu6P7wgdNtGV2RV8Kpuw1x6bV+YsSptuClYG+JSdRExBTE6LwIe1bTklejUp3ZP8TQ== +"@cspell/dict-sql@^2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@cspell/dict-sql/-/dict-sql-2.1.5.tgz#068c7a8840d75418fd46a0b062c0ed2d5742f2b8" + integrity sha512-FmxanytHXss7GAWAXmgaxl3icTCW7YxlimyOSPNfm+njqeUDjw3kEv4mFNDDObBJv8Ec5AWCbUDkWIpkE3IpKg== "@cspell/dict-svelte@^1.0.2": version "1.0.2" @@ -876,32 +1644,37 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-terraform/-/dict-terraform-1.0.0.tgz#c7b073bb3a03683f64cc70ccaa55ce9742c46086" integrity sha512-Ak+vy4HP/bOgzf06BAMC30+ZvL9mzv21xLM2XtfnBLTDJGdxlk/nK0U6QT8VfFLqJ0ZZSpyOxGsUebWDCTr/zQ== -"@cspell/dict-typescript@3.1.5", "@cspell/dict-typescript@^3.1.5": - version "3.1.5" - resolved "https://registry.yarnpkg.com/@cspell/dict-typescript/-/dict-typescript-3.1.5.tgz#15bd74651fb2cf0eff1150f07afee9543206bfab" - integrity sha512-EkIwwNV/xqEoBPJml2S16RXj65h1kvly8dfDLgXerrKw6puybZdvAHerAph6/uPTYdtLcsPyJYkPt5ISOJYrtw== +"@cspell/dict-typescript@3.1.6", "@cspell/dict-typescript@^3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@cspell/dict-typescript/-/dict-typescript-3.1.6.tgz#2d5351786787bf3609da65ba17d9bc345995a36d" + integrity sha512-1beC6O4P/j23VuxX+i0+F7XqPVc3hhiAzGJHEKqnWf5cWAXQtg0xz3xQJ5MvYx2a7iLaSa+lu7+05vG9UHyu9Q== "@cspell/dict-vue@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@cspell/dict-vue/-/dict-vue-3.0.0.tgz#68ccb432ad93fcb0fd665352d075ae9a64ea9250" integrity sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A== -"@cspell/dynamic-import@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@cspell/dynamic-import/-/dynamic-import-8.9.0.tgz#232d49b6372ff8ece4d5ffce149f988e9350065c" - integrity sha512-UYa2Xlf/Bg9b7lUlKn59Z6XhHtE00z5kgzkKCGAdS0W27i2qUZJHW3FfiKfknWLNLzfj7cVUAq2IHjbumbx9ow== +"@cspell/dynamic-import@8.14.2": + version "8.14.2" + resolved "https://registry.yarnpkg.com/@cspell/dynamic-import/-/dynamic-import-8.14.2.tgz#4968d1b6b20806f9bb78b92c628300cad288072f" + integrity sha512-5MbqtIligU7yPwHWU/5yFCgMvur4i1bRAF1Cy8y2dDtHsa204S/w/SaXs+51EFLp2eNbCiBisCBrwJFT7R1RxA== dependencies: import-meta-resolve "^4.1.0" -"@cspell/strong-weak-map@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@cspell/strong-weak-map/-/strong-weak-map-8.9.0.tgz#5aedd8f556c362b444f0a8dc9ed532831bed3c95" - integrity sha512-HE0rkwtJ4/4QuXpJW1r4GIK+jhs2SYK4IACf3EE2mJufOWF4YxgfWwKBgztKE/0RDMJcxyvn/ubLUCnNClNfdg== +"@cspell/filetypes@8.14.2": + version "8.14.2" + resolved "https://registry.yarnpkg.com/@cspell/filetypes/-/filetypes-8.14.2.tgz#e05d48a504efa72d9cebd9fb45b666e116673335" + integrity sha512-ZevArA0mWeVTTqHicxCPZIAeCibpY3NwWK/x6d1Lgu7RPk/daoGAM546Q2SLChFu+r10tIH7pRG212A6Q9ihPA== -"@cspell/url@8.9.0": - version "8.9.0" - resolved "https://registry.yarnpkg.com/@cspell/url/-/url-8.9.0.tgz#313ccde44570b3158cb7baa3eb53e54572d7263f" - integrity sha512-FaHTEx6OBVKlkX7VgAPofBZ5vIdxNWYalb0uZwJ5FCc/PCMIF5l91DQGQxRMas3qzRACR911kJamPdeK/3qilw== +"@cspell/strong-weak-map@8.14.2": + version "8.14.2" + resolved "https://registry.yarnpkg.com/@cspell/strong-weak-map/-/strong-weak-map-8.14.2.tgz#4fd8fd616690125775c0f7a596a1295b03e9a43d" + integrity sha512-7sRzJc392CQYNNrtdPEfOHJdRqsqf6nASCtbS5A9hL2UrdWQ4uN7r/D+Y1HpuizwY9eOkZvarcFfsYt5wE0Pug== + +"@cspell/url@8.14.2": + version "8.14.2" + resolved "https://registry.yarnpkg.com/@cspell/url/-/url-8.14.2.tgz#8a6d30011596ccefb48a6135225554011c46dc03" + integrity sha512-YmWW+B/2XQcCynLpiAQF77Bitm5Cynw3/BICZkbdveKjJkUzEmXB+U2qWuwXOyU8xUYuwkP63YM8McnI567rUA== "@cspotcode/source-map-support@0.8.1": version "0.8.1" @@ -910,28 +1683,18 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@ericcornelissen/bash-parser@0.5.3": - version "0.5.3" - resolved "https://registry.yarnpkg.com/@ericcornelissen/bash-parser/-/bash-parser-0.5.3.tgz#cda9f0e9ed3bcf62c29c277de778726425e03b0a" - integrity sha512-9Z0sGuXqf6En19qmwB0Syi1Mc8TYl756dNuuaYal9mrypKa0Jq/IX6aJfh6Rk2S3z66KBisWTqloDo7weYj4zg== - dependencies: - array-last "^1.1.1" - babylon "^6.9.1" - compose-function "^3.0.3" - filter-obj "^1.1.0" - has-own-property "^0.1.0" - identity-function "^1.0.0" - is-iterable "^1.1.0" - iterable-lookahead "^1.0.0" - lodash.curry "^4.1.1" - magic-string "^0.16.0" - map-obj "^2.0.0" - object-pairs "^0.1.0" - object-values "^1.0.0" - reverse-arguments "^1.0.0" - shell-quote-word "^1.0.1" - to-pascal-case "^1.0.0" - unescape-js "^1.0.5" +"@deno/shim-deno-test@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@deno/shim-deno-test/-/shim-deno-test-0.5.0.tgz#7d5dd221c736d182e587b8fd9bfca49b4dc0aa79" + integrity sha512-4nMhecpGlPi0cSzT67L+Tm+GOJqvuk8gqHBziqcUQOarnuIax1z96/gJHCSIz2Z0zhxE6Rzwb3IZXPtFh51j+w== + +"@deno/shim-deno@~0.18.0": + version "0.18.2" + resolved "https://registry.yarnpkg.com/@deno/shim-deno/-/shim-deno-0.18.2.tgz#9fe2fe7c91062bf2d127204f3110c09806cbef92" + integrity sha512-oQ0CVmOio63wlhwQF75zA4ioolPvOwAoK0yuzcS5bDC1JUvH3y1GS8xPh8EOpcoDQRU4FTG8OQfxhpR+c6DrzA== + dependencies: + "@deno/shim-deno-test" "^0.5.0" + which "^4.0.0" "@esbuild-plugins/node-globals-polyfill@^0.2.3": version "0.2.3" @@ -946,230 +1709,235 @@ escape-string-regexp "^4.0.0" rollup-plugin-node-polyfills "^0.2.1" -"@esbuild/aix-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" - integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== +"@esbuild/aix-ppc64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz#51299374de171dbd80bb7d838e1cfce9af36f353" + integrity sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ== "@esbuild/android-arm64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz#bafb75234a5d3d1b690e7c2956a599345e84a2fd" integrity sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA== -"@esbuild/android-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" - integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== +"@esbuild/android-arm64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz#58565291a1fe548638adb9c584237449e5e14018" + integrity sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw== "@esbuild/android-arm@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.19.tgz#5898f7832c2298bc7d0ab53701c57beb74d78b4d" integrity sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A== -"@esbuild/android-arm@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" - integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== +"@esbuild/android-arm@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.23.1.tgz#5eb8c652d4c82a2421e3395b808e6d9c42c862ee" + integrity sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ== "@esbuild/android-x64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.19.tgz#658368ef92067866d95fb268719f98f363d13ae1" integrity sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww== -"@esbuild/android-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" - integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== +"@esbuild/android-x64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.23.1.tgz#ae19d665d2f06f0f48a6ac9a224b3f672e65d517" + integrity sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg== "@esbuild/darwin-arm64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz#584c34c5991b95d4d48d333300b1a4e2ff7be276" integrity sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg== -"@esbuild/darwin-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" - integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== +"@esbuild/darwin-arm64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz#05b17f91a87e557b468a9c75e9d85ab10c121b16" + integrity sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q== "@esbuild/darwin-x64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz#7751d236dfe6ce136cce343dce69f52d76b7f6cb" integrity sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw== -"@esbuild/darwin-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" - integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== +"@esbuild/darwin-x64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz#c58353b982f4e04f0d022284b8ba2733f5ff0931" + integrity sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw== "@esbuild/freebsd-arm64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz#cacd171665dd1d500f45c167d50c6b7e539d5fd2" integrity sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ== -"@esbuild/freebsd-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" - integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== +"@esbuild/freebsd-arm64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz#f9220dc65f80f03635e1ef96cfad5da1f446f3bc" + integrity sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA== "@esbuild/freebsd-x64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz#0769456eee2a08b8d925d7c00b79e861cb3162e4" integrity sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ== -"@esbuild/freebsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" - integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== +"@esbuild/freebsd-x64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz#69bd8511fa013b59f0226d1609ac43f7ce489730" + integrity sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g== "@esbuild/linux-arm64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz#38e162ecb723862c6be1c27d6389f48960b68edb" integrity sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg== -"@esbuild/linux-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" - integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== +"@esbuild/linux-arm64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz#8050af6d51ddb388c75653ef9871f5ccd8f12383" + integrity sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g== "@esbuild/linux-arm@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz#1a2cd399c50040184a805174a6d89097d9d1559a" integrity sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA== -"@esbuild/linux-arm@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" - integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== +"@esbuild/linux-arm@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz#ecaabd1c23b701070484990db9a82f382f99e771" + integrity sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ== "@esbuild/linux-ia32@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz#e28c25266b036ce1cabca3c30155222841dc035a" integrity sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ== -"@esbuild/linux-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" - integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== +"@esbuild/linux-ia32@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz#3ed2273214178109741c09bd0687098a0243b333" + integrity sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ== "@esbuild/linux-loong64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz#0f887b8bb3f90658d1a0117283e55dbd4c9dcf72" integrity sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ== -"@esbuild/linux-loong64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" - integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== +"@esbuild/linux-loong64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz#a0fdf440b5485c81b0fbb316b08933d217f5d3ac" + integrity sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw== "@esbuild/linux-mips64el@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz#f5d2a0b8047ea9a5d9f592a178ea054053a70289" integrity sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A== -"@esbuild/linux-mips64el@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" - integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== +"@esbuild/linux-mips64el@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz#e11a2806346db8375b18f5e104c5a9d4e81807f6" + integrity sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q== "@esbuild/linux-ppc64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz#876590e3acbd9fa7f57a2c7d86f83717dbbac8c7" integrity sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg== -"@esbuild/linux-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" - integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== +"@esbuild/linux-ppc64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz#06a2744c5eaf562b1a90937855b4d6cf7c75ec96" + integrity sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw== "@esbuild/linux-riscv64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz#7f49373df463cd9f41dc34f9b2262d771688bf09" integrity sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA== -"@esbuild/linux-riscv64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" - integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== +"@esbuild/linux-riscv64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz#65b46a2892fc0d1af4ba342af3fe0fa4a8fe08e7" + integrity sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA== "@esbuild/linux-s390x@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz#e2afd1afcaf63afe2c7d9ceacd28ec57c77f8829" integrity sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q== -"@esbuild/linux-s390x@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" - integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== +"@esbuild/linux-s390x@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz#e71ea18c70c3f604e241d16e4e5ab193a9785d6f" + integrity sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw== "@esbuild/linux-x64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz#8a0e9738b1635f0c53389e515ae83826dec22aa4" integrity sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw== -"@esbuild/linux-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" - integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== +"@esbuild/linux-x64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz#d47f97391e80690d4dfe811a2e7d6927ad9eed24" + integrity sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ== "@esbuild/netbsd-x64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz#c29fb2453c6b7ddef9a35e2c18b37bda1ae5c462" integrity sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q== -"@esbuild/netbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" - integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== +"@esbuild/netbsd-x64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz#44e743c9778d57a8ace4b72f3c6b839a3b74a653" + integrity sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA== + +"@esbuild/openbsd-arm64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz#05c5a1faf67b9881834758c69f3e51b7dee015d7" + integrity sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q== "@esbuild/openbsd-x64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz#95e75a391403cb10297280d524d66ce04c920691" integrity sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g== -"@esbuild/openbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" - integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== +"@esbuild/openbsd-x64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz#2e58ae511bacf67d19f9f2dcd9e8c5a93f00c273" + integrity sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA== "@esbuild/sunos-x64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz#722eaf057b83c2575937d3ffe5aeb16540da7273" integrity sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg== -"@esbuild/sunos-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" - integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== +"@esbuild/sunos-x64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz#adb022b959d18d3389ac70769cef5a03d3abd403" + integrity sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA== "@esbuild/win32-arm64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz#9aa9dc074399288bdcdd283443e9aeb6b9552b6f" integrity sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag== -"@esbuild/win32-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" - integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== +"@esbuild/win32-arm64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz#84906f50c212b72ec360f48461d43202f4c8b9a2" + integrity sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A== "@esbuild/win32-ia32@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz#95ad43c62ad62485e210f6299c7b2571e48d2b03" integrity sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw== -"@esbuild/win32-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" - integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== +"@esbuild/win32-ia32@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz#5e3eacc515820ff729e90d0cb463183128e82fac" + integrity sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ== "@esbuild/win32-x64@0.17.19": version "0.17.19" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz#8cfaf2ff603e9aabb910e9c0558c26cf32744061" integrity sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA== -"@esbuild/win32-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" - integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== +"@esbuild/win32-x64@0.23.1": + version "0.23.1" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz#81fd50d11e2c32b2d6241470e3185b70c7b30699" + integrity sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" @@ -1178,19 +1946,24 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": +"@eslint-community/regexpp@4.10.0": version "4.10.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== -"@eslint/config-array@^0.16.0": - version "0.16.0" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.16.0.tgz#bb3364fc39ee84ec3a62abdc4b8d988d99dfd706" - integrity sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg== +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.11.0", "@eslint-community/regexpp@^4.8.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" + integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== + +"@eslint/config-array@^0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.18.0.tgz#37d8fe656e0d5e3dbaea7758ea56540867fd074d" + integrity sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw== dependencies: "@eslint/object-schema" "^2.1.4" debug "^4.3.1" - minimatch "^3.0.5" + minimatch "^3.1.2" "@eslint/eslintrc@^3.1.0": version "3.1.0" @@ -1207,10 +1980,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.5.0": - version "9.5.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.5.0.tgz#0e9c24a670b8a5c86bff97b40be13d8d8f238045" - integrity sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w== +"@eslint/js@9.9.1": + version "9.9.1" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.9.1.tgz#4a97e85e982099d6c7ee8410aacb55adaa576f06" + integrity sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ== "@eslint/object-schema@^2.1.4": version "2.1.4" @@ -1222,6 +1995,59 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== +"@fluent/bundle@^0.17.1": + version "0.17.1" + resolved "https://registry.yarnpkg.com/@fluent/bundle/-/bundle-0.17.1.tgz#239388f55f115dca593f268d48a5ab8936dc9556" + integrity sha512-CRFNT9QcSFAeFDneTF59eyv3JXFGhIIN4boUO2y22YmsuuKLyDk+N1I/NQUYz9Ab63e6V7T6vItoZIG/2oOOuw== + +"@fluent/langneg@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@fluent/langneg/-/langneg-0.6.2.tgz#95e5261c27c7f3cb6237deb62aa1b7006a9bd17d" + integrity sha512-YF4gZ4sLYRQfctpUR2uhb5UyPUYY5n/bi3OaED/Q4awKjPjlaF8tInO3uja7pnLQcmLTURkZL7L9zxv2Z5NDwg== + +"@grammyjs/auto-chat-action@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@grammyjs/auto-chat-action/-/auto-chat-action-0.1.1.tgz#2c70faca0e317ac3e742ea241181cedaa4231081" + integrity sha512-70Jdy+keIri4452tluaZpKtHag5gD8pNczoXqajsnsx7pJC5wg3DAQ5unpt0xJb8KsVBAGWuJb298SBl3TVecg== + +"@grammyjs/hydrate@1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@grammyjs/hydrate/-/hydrate-1.4.1.tgz#9fa56ef2c57fa996863584c3840489df2fea6cdc" + integrity sha512-xvd7XXoVHEhxBV2M8UHDRYkZlv32JioHfs+0l+eN34mkJJJBchuRDgRY3fkVJko8o1hGFHHLAJJTlEs2OAMolA== + dependencies: + abort-controller "^3.0.0" + +"@grammyjs/i18n@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@grammyjs/i18n/-/i18n-1.0.2.tgz#6b2763e78554d3ba19bd4416fd601c5f0abcf855" + integrity sha512-F/6jBB+afp8N3aXLmxTqdlffqD20EZBMFrPiVQNz6YoiKvjAe4Q8rSrU0Y4eQXkUj4e+UNl7yvYvvPSa1h4guw== + dependencies: + "@deno/shim-deno" "~0.18.0" + "@fluent/bundle" "^0.17.1" + "@fluent/langneg" "^0.6.2" + +"@grammyjs/parse-mode@1.10.0": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@grammyjs/parse-mode/-/parse-mode-1.10.0.tgz#41256924b9f4465cc53630a0a9f3d8788da0f1f9" + integrity sha512-ZjbY2Ax0b4Nf8lPz3NV0cWDxUC10kOkzgxws+iTdgG+hAiPQVUnP/oJnAKrW1ZQOWULZYQ4GOR/+aCZHyUuLQA== + +"@grammyjs/runner@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@grammyjs/runner/-/runner-2.0.3.tgz#cfb08958fd563ce1e0eda5754a40b3d632c4eaa1" + integrity sha512-nckmTs1dPWfVQteK9cxqxzE+0m1VRvluLWB8UgFzsjg62w3qthPJt0TYtJBEdG7OedvfQq4vnFAyE6iaMkR42A== + dependencies: + abort-controller "^3.0.0" + +"@grammyjs/types@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@grammyjs/types/-/types-3.13.0.tgz#3316a809b4faf6cc61cff0c7d7a5a671ec0bd776" + integrity sha512-Oyq6fBuVPyX6iWvxT/0SxJvNisC9GHUEkhZ60qJBHRmwNX4hIcOfhrNEahicn3K9SYyreGPVw3d9wlLRds83cw== + +"@hono/node-server@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.12.1.tgz#bc5528ba5a9542ec20ae1dbe6ccdc078ddea72ab" + integrity sha512-C9l+08O8xtXB7Ppmy8DjBFH1hYji7JKzsU32Yt1poIIbdPp6S7aOI8IldDHD9YFJ55lv2c21ovNrmxatlHfhAg== + "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" @@ -1233,41 +2059,43 @@ integrity sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew== "@inquirer/confirm@^3.0.0": - version "3.1.9" - resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-3.1.9.tgz#1bc384bc8267827ec75d0684e189692bb4dda38b" - integrity sha512-UF09aejxCi4Xqm6N/jJAiFXArXfi9al52AFaSD+2uIHnhZGtd1d6lIGTRMPouVSJxbGEi+HkOWSYaiEY/+szUw== + version "3.1.22" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-3.1.22.tgz#23990624c11f60c6f7a5b0558c7505c35076a037" + integrity sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg== dependencies: - "@inquirer/core" "^8.2.2" - "@inquirer/type" "^1.3.3" + "@inquirer/core" "^9.0.10" + "@inquirer/type" "^1.5.2" -"@inquirer/core@^8.2.2": - version "8.2.2" - resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-8.2.2.tgz#797b1e71b920c9788b9d26d89c8b334149852d52" - integrity sha512-K8SuNX45jEFlX3EBJpu9B+S2TISzMPGXZIuJ9ME924SqbdW6Pt6fIkKvXg7mOEOKJ4WxpQsxj0UTfcL/A434Ww== +"@inquirer/core@^9.0.10": + version "9.0.10" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-9.0.10.tgz#4270191e2ad3bea6223530a093dd9479bcbc7dd0" + integrity sha512-TdESOKSVwf6+YWDz8GhS6nKscwzkIyakEzCLJ5Vh6O3Co2ClhCJ0A4MG909MUWfaWdpJm7DE45ii51/2Kat9tA== dependencies: - "@inquirer/figures" "^1.0.3" - "@inquirer/type" "^1.3.3" + "@inquirer/figures" "^1.0.5" + "@inquirer/type" "^1.5.2" "@types/mute-stream" "^0.0.4" - "@types/node" "^20.12.13" + "@types/node" "^22.1.0" "@types/wrap-ansi" "^3.0.0" ansi-escapes "^4.3.2" - chalk "^4.1.2" cli-spinners "^2.9.2" cli-width "^4.1.0" mute-stream "^1.0.0" signal-exit "^4.1.0" strip-ansi "^6.0.1" wrap-ansi "^6.2.0" + yoctocolors-cjs "^2.1.2" -"@inquirer/figures@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.3.tgz#1227cc980f88e6d6ab85abadbf164f5038041edd" - integrity sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw== +"@inquirer/figures@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.5.tgz#57f9a996d64d3e3345d2a3ca04d36912e94f8790" + integrity sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA== -"@inquirer/type@^1.3.3": - version "1.3.3" - resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-1.3.3.tgz#26b2628630fd2381c7fa1e3ab396feb9bbc575da" - integrity sha512-xTUt0NulylX27/zMx04ZYar/kr1raaiFTVvQ5feljQsiAgdm0WPj4S73/ye0fbslh+15QrIuDvfCXTek7pMY5A== +"@inquirer/type@^1.5.2": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-1.5.2.tgz#15f5e4a4dae02c4203650cb07c8a000cdd423939" + integrity sha512-w9qFkumYDCNyDZmNQjf/n6qQuvQ4dMC3BJesY4oF+yr0CxR5vxujflAVeIcS6U336uzi9GM0kAfZlLrZ9UTkpA== + dependencies: + mute-stream "^1.0.0" "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" @@ -1497,9 +2325,9 @@ integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" @@ -1517,11 +2345,6 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@mswjs/cookies@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@mswjs/cookies/-/cookies-1.1.0.tgz#1528eb43630caf83a1d75d5332b30e75e9bb1b5b" - integrity sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw== - "@mswjs/data@0.16.1": version "0.16.1" resolved "https://registry.yarnpkg.com/@mswjs/data/-/data-0.16.1.tgz#ee41b95b8f2e954a07b0eb54154592a2459064d1" @@ -1555,6 +2378,13 @@ outvariant "^1.2.1" strict-event-emitter "^0.5.1" +"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": + version "5.1.1-v1" + resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" + integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg== + dependencies: + eslint-scope "5.1.1" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1563,33 +2393,12 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.scandir@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-3.0.0.tgz#91c0a33e1aeaedcd4bab2bf31be5d1962a55d2a7" - integrity sha512-ktI9+PxfHYtKjF3cLTUAh2N+b8MijCRPNwKJNqTVdL0gB0QxLU2rIRaZ1t71oEa3YBDE6bukH1sR0+CDnpp/Mg== - dependencies: - "@nodelib/fs.stat" "3.0.0" - run-parallel "^1.2.0" - "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.stat@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-3.0.0.tgz#ef6c829f2b05f42595d88854ebd777d4335ff0a9" - integrity sha512-2tQOI38s19P9i7X/Drt0v8iMA+KMsgdhB/dyPER+e+2Y8L1Z7QvnuRdW/uLuf5YRFUYmnj4bMA6qCuZHFI1GDQ== - -"@nodelib/fs.walk@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-2.0.0.tgz#10499ac2210f6399770b465ba728adafc7d44bb1" - integrity sha512-54voNDBobGdMl3BUXSu7UaDh1P85PGHWlJ5e0XhPugo1JulOyCtp2I+5ri4wplGDJ8QGwPEQW7/x3yTLU7yF1A== - dependencies: - "@nodelib/fs.scandir" "3.0.0" - fastq "^1.15.0" - -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": +"@nodelib/fs.walk@1.2.8", "@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -1602,7 +2411,12 @@ resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-4.0.0.tgz#40d203ea827b9f17f42a29c6afb93b7745ef80c7" integrity sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA== -"@octokit/core@^5.0.1", "@octokit/core@^5.0.2": +"@octokit/auth-token@^5.0.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-5.1.1.tgz#3bbfe905111332a17f72d80bd0b51a3e2fa2cf07" + integrity sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA== + +"@octokit/core@^5.0.1": version "5.2.0" resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.2.0.tgz#ddbeaefc6b44a39834e1bb2e58a49a117672a7ea" integrity sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg== @@ -1615,6 +2429,27 @@ before-after-hook "^2.2.0" universal-user-agent "^6.0.0" +"@octokit/core@^6.1.2": + version "6.1.2" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-6.1.2.tgz#20442d0a97c411612da206411e356014d1d1bd17" + integrity sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg== + dependencies: + "@octokit/auth-token" "^5.0.0" + "@octokit/graphql" "^8.0.0" + "@octokit/request" "^9.0.0" + "@octokit/request-error" "^6.0.1" + "@octokit/types" "^13.0.0" + before-after-hook "^3.0.2" + universal-user-agent "^7.0.0" + +"@octokit/endpoint@^10.0.0": + version "10.1.1" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-10.1.1.tgz#1a9694e7aef6aa9d854dc78dd062945945869bcc" + integrity sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q== + dependencies: + "@octokit/types" "^13.0.0" + universal-user-agent "^7.0.2" + "@octokit/endpoint@^9.0.1": version "9.0.5" resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-9.0.5.tgz#e6c0ee684e307614c02fc6ac12274c50da465c44" @@ -1632,6 +2467,15 @@ "@octokit/types" "^13.0.0" universal-user-agent "^6.0.0" +"@octokit/graphql@^8.0.0": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-8.1.1.tgz#3cacab5f2e55d91c733e3bf481d3a3f8a5f639c4" + integrity sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg== + dependencies: + "@octokit/request" "^9.0.0" + "@octokit/types" "^13.0.0" + universal-user-agent "^7.0.0" + "@octokit/openapi-types@^20.0.0": version "20.0.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-20.0.0.tgz#9ec2daa0090eeb865ee147636e0c00f73790c6e5" @@ -1642,15 +2486,15 @@ resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-22.2.0.tgz#75aa7dcd440821d99def6a60b5f014207ae4968e" integrity sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg== -"@octokit/openapi-webhooks-types@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-8.2.1.tgz#08b974f1e83a75c4d3ce23f798c7667b433bf4cd" - integrity sha512-msAU1oTSm0ZmvAE0xDemuF4tVs5i0xNnNGtNmr4EuATi+1Rn8cZDetj6NXioSf5LwnxEc209COa/WOSbjuhLUA== +"@octokit/openapi-webhooks-types@8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-8.3.0.tgz#a7a4da00c0f27f7f5708eb3fcebefa08f8d51125" + integrity sha512-vKLsoR4xQxg4Z+6rU/F65ItTUz/EXbD+j/d4mlq2GW8TsA4Tc8Kdma2JTAAJ5hrKWUQzkR/Esn2fjsqiVRYaQg== -"@octokit/plugin-paginate-rest@11.3.1": - version "11.3.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.1.tgz#fe92d04b49f134165d6fbb716e765c2f313ad364" - integrity sha512-ryqobs26cLtM1kQxqeZui4v8FeznirUsksiA+RYemMPJ7Micju0WSkv50dBksTuZks9O5cg4wp+t8fZ/cLY56g== +"@octokit/plugin-paginate-rest@^11.0.0": + version "11.3.3" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.3.tgz#efc97ba66aae6797e2807a082f99b9cfc0e05aba" + integrity sha512-o4WRoOJZlKqEEgj+i9CpcmnByvtzoUYC6I8PD2SA95M+BJ2x8h7oLcVOg9qcowWXBOdcTRsMZiwvM3EyLm9AfA== dependencies: "@octokit/types" "^13.5.0" @@ -1661,17 +2505,10 @@ dependencies: "@octokit/types" "^12.6.0" -"@octokit/plugin-request-log@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz#98a3ca96e0b107380664708111864cb96551f958" - integrity sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA== - -"@octokit/plugin-rest-endpoint-methods@13.2.2": - version "13.2.2" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.2.tgz#af8e5dd2cddfea576f92ffaf9cb84659f302a638" - integrity sha512-EI7kXWidkt3Xlok5uN43suK99VWqc8OaIMktY9d9+RNKl69juoTyxmLoWPIZgJYzi41qj/9zU7G/ljnNOJ5AFA== - dependencies: - "@octokit/types" "^13.5.0" +"@octokit/plugin-request-log@^5.3.1": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz#ccb75d9705de769b2aa82bcd105cc96eb0c00f69" + integrity sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw== "@octokit/plugin-rest-endpoint-methods@^10.0.0": version "10.4.1" @@ -1680,6 +2517,13 @@ dependencies: "@octokit/types" "^12.6.0" +"@octokit/plugin-rest-endpoint-methods@^13.0.0": + version "13.2.4" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.4.tgz#543add032d3fe3f5d2839bfd619cf66d85469f01" + integrity sha512-gusyAVgTrPiuXOdfqOySMDztQHv6928PQ3E4dqVGEtOvRXAKRbJR4b1zQyniIT9waqaWk/UDaoJ2dyPr7Bk7Iw== + dependencies: + "@octokit/types" "^13.5.0" + "@octokit/request-error@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-5.1.0.tgz#ee4138538d08c81a60be3f320cd71063064a3b30" @@ -1690,9 +2534,9 @@ once "^1.4.0" "@octokit/request-error@^6.0.1": - version "6.1.1" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-6.1.1.tgz#bed1b5f52ce7fefb1077a92bf42124ff36f73f2c" - integrity sha512-1mw1gqT3fR/WFvnoVpY/zUM2o/XkMs/2AszUUG9I69xn0JFLv6PGkPhNk5lbfvROs79wiS0bqiJNxfCZcRJJdg== + version "6.1.4" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-6.1.4.tgz#ad96e29148d19edc2ba8009fc2b5a24a36c90f16" + integrity sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg== dependencies: "@octokit/types" "^13.0.0" @@ -1706,15 +2550,25 @@ "@octokit/types" "^13.1.0" universal-user-agent "^6.0.0" -"@octokit/rest@20.1.1": - version "20.1.1" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-20.1.1.tgz#ec775864f53fb42037a954b9a40d4f5275b3dc95" - integrity sha512-MB4AYDsM5jhIHro/dq4ix1iWTLGToIGk6cWF5L6vanFaMble5jTX/UBQyiv05HsWnwUtY8JrfHy2LWfKwihqMw== +"@octokit/request@^9.0.0": + version "9.1.3" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-9.1.3.tgz#42b693bc06238f43af3c037ebfd35621c6457838" + integrity sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA== dependencies: - "@octokit/core" "^5.0.2" - "@octokit/plugin-paginate-rest" "11.3.1" - "@octokit/plugin-request-log" "^4.0.0" - "@octokit/plugin-rest-endpoint-methods" "13.2.2" + "@octokit/endpoint" "^10.0.0" + "@octokit/request-error" "^6.0.1" + "@octokit/types" "^13.1.0" + universal-user-agent "^7.0.2" + +"@octokit/rest@21.0.2": + version "21.0.2" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-21.0.2.tgz#9b767dbc1098daea8310fd8b76bf7a97215d5972" + integrity sha512-+CiLisCoyWmYicH25y1cDfCrv41kRSvTq6pPWtRroRJzhsCZWZyCqGyI8foJT5LmScADSwRAnr/xo+eewL04wQ== + dependencies: + "@octokit/core" "^6.1.2" + "@octokit/plugin-paginate-rest" "^11.0.0" + "@octokit/plugin-request-log" "^5.3.1" + "@octokit/plugin-rest-endpoint-methods" "^13.0.0" "@octokit/types@^12.6.0": version "12.6.0" @@ -1735,15 +2589,14 @@ resolved "https://registry.yarnpkg.com/@octokit/webhooks-methods/-/webhooks-methods-5.1.0.tgz#13b6c08f89902c1ab0ddf31c6eeeec9c2772cfe6" integrity sha512-yFZa3UH11VIxYnnoOYCVoJ3q4ChuSOk2IVBBQ0O3xtKX4x9bmKb/1t+Mxixv2iUhzMdOl1qeWJqEhouXXzB3rQ== -"@octokit/webhooks@13.2.7": - version "13.2.7" - resolved "https://registry.yarnpkg.com/@octokit/webhooks/-/webhooks-13.2.7.tgz#03f89b278cd63f271eba3062f0b75ddd18a82252" - integrity sha512-sPHCyi9uZuCs1gg0yF53FFocM+GsiiBEhQQV/itGzzQ8gjyv2GMJ1YvgdDY4lC0ePZeiV3juEw4GbS6w1VHhRw== +"@octokit/webhooks@13.3.0": + version "13.3.0" + resolved "https://registry.yarnpkg.com/@octokit/webhooks/-/webhooks-13.3.0.tgz#fd5d54d47c789c75d60a00eb04e982152d7c654a" + integrity sha512-TUkJLtI163Bz5+JK0O+zDkQpn4gKwN+BovclUvCj6pI/6RXrFqQvUMRS2M+Rt8Rv0qR3wjoMoOPmpJKeOh0nBg== dependencies: - "@octokit/openapi-webhooks-types" "8.2.1" + "@octokit/openapi-webhooks-types" "8.3.0" "@octokit/request-error" "^6.0.1" "@octokit/webhooks-methods" "^5.0.0" - aggregate-error "^5.0.0" "@open-draft/deferred-promise@^2.2.0": version "2.2.0" @@ -1768,10 +2621,10 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== -"@sinclair/typebox@0.32.33": - version "0.32.33" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.32.33.tgz#823af450f6f1571a85c12e2b1f2a0b134f61920f" - integrity sha512-jM50BfkKA0fwfj0uRRO6asfNfbU0oZipJIb/bL2+BUH/THjuEf2BMiqBOvKfBji5Z9t59NboZQGNfKZbdV50Iw== +"@sinclair/typebox@0.33.7": + version "0.33.7" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.33.7.tgz#4356b69f566ef8862848c24dabb5cd64ba025111" + integrity sha512-et38XPs6GMoB6XugH+Spp/HRv5gHYffw7rXC3caen/dIKC7Q6sqs6eEH9Yd9UKziUkOQdrLr9OXUULAc+pRMng== "@sinclair/typebox@^0.27.8": version "0.27.8" @@ -1846,6 +2699,19 @@ resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== +"@types/eslint@8.56.10": + version "8.56.10" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.10.tgz#eb2370a73bf04a901eeba8f22595c7ee0f7eb58d" + integrity sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== + "@types/graceful-fs@^4.1.3": version "4.1.9" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" @@ -1880,10 +2746,20 @@ expect "^29.0.0" pretty-format "^29.0.0" +"@types/json-schema@*": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + "@types/lodash@^4.14.172": - version "4.17.4" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.4.tgz#0303b64958ee070059e3a7184048a55159fe20b7" - integrity sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ== + version "4.17.7" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.7.tgz#2f776bcb53adc9e13b2c0dfd493dfcbd7de43612" + integrity sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA== "@types/md5@^2.3.0": version "2.3.5" @@ -1904,19 +2780,12 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@^20.12.13": - version "20.13.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.13.0.tgz#011a76bc1e71ae9a026dddcfd7039084f752c4b6" - integrity sha512-FM6AOb3khNkNIXPnHFDYaHerSv8uN22C91z098AnGccVu+Pcdhi+pNUFDi0iLmPIsVE0JBD0KVS7mzUYt4nRzQ== - dependencies: - undici-types "~5.26.4" - -"@types/node@20.14.5": - version "20.14.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.5.tgz#fe35e3022ebe58b8f201580eb24e1fcfc0f2487d" - integrity sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA== +"@types/node@*", "@types/node@22.5.0", "@types/node@^22.1.0": + version "22.5.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.0.tgz#10f01fe9465166b4cab72e75f60d8b99d019f958" + integrity sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg== dependencies: - undici-types "~5.26.4" + undici-types "~6.19.2" "@types/pluralize@^0.0.29": version "0.0.29" @@ -1933,6 +2802,11 @@ resolved "https://registry.yarnpkg.com/@types/statuses/-/statuses-2.0.5.tgz#f61ab46d5352fd73c863a1ea4e1cef3b0b51ae63" integrity sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A== +"@types/tough-cookie@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" + integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== + "@types/uuid@^8.3.0": version "8.3.4" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" @@ -1949,68 +2823,119 @@ integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== "@types/yargs@^17.0.8": - version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" - integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + version "17.0.33" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.33.tgz#8c32303da83eec050a84b3c7ae7b9f922d13e32d" + integrity sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA== dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz#cdc521c8bca38b55585cf30db787fb2abad3f9fd" - integrity sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg== +"@typescript-eslint/eslint-plugin@7.16.1": + version "7.16.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.1.tgz#f5f5da52db674b1f2cdb9d5f3644e5b2ec750465" + integrity sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "7.16.1" + "@typescript-eslint/type-utils" "7.16.1" + "@typescript-eslint/utils" "7.16.1" + "@typescript-eslint/visitor-keys" "7.16.1" + graphemer "^1.4.0" + ignore "^5.3.1" + natural-compare "^1.4.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/eslint-plugin@8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz#726627fad16d41d20539637efee8c2329fe6be32" + integrity sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "7.13.1" - "@typescript-eslint/type-utils" "7.13.1" - "@typescript-eslint/utils" "7.13.1" - "@typescript-eslint/visitor-keys" "7.13.1" + "@typescript-eslint/scope-manager" "8.3.0" + "@typescript-eslint/type-utils" "8.3.0" + "@typescript-eslint/utils" "8.3.0" + "@typescript-eslint/visitor-keys" "8.3.0" graphemer "^1.4.0" ignore "^5.3.1" natural-compare "^1.4.0" ts-api-utils "^1.3.0" -"@typescript-eslint/parser@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.13.1.tgz#fac57811b3e519185f7259bac312291f7b9c4e72" - integrity sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A== +"@typescript-eslint/parser@8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.3.0.tgz#3c72c32bc909cb91ce3569e7d11d729ad84deafa" + integrity sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ== dependencies: - "@typescript-eslint/scope-manager" "7.13.1" - "@typescript-eslint/types" "7.13.1" - "@typescript-eslint/typescript-estree" "7.13.1" - "@typescript-eslint/visitor-keys" "7.13.1" + "@typescript-eslint/scope-manager" "8.3.0" + "@typescript-eslint/types" "8.3.0" + "@typescript-eslint/typescript-estree" "8.3.0" + "@typescript-eslint/visitor-keys" "8.3.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz#c08041206904bf36f0e6997efdb0ca775e0c452e" - integrity sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg== +"@typescript-eslint/scope-manager@7.16.1": + version "7.16.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.16.1.tgz#2b43041caabf8ddd74512b8b550b9fc53ca3afa1" + integrity sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw== + dependencies: + "@typescript-eslint/types" "7.16.1" + "@typescript-eslint/visitor-keys" "7.16.1" + +"@typescript-eslint/scope-manager@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz#c928e7a9fc2c0b3ed92ab3112c614d6bd9951c83" + integrity sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA== + dependencies: + "@typescript-eslint/types" "7.18.0" + "@typescript-eslint/visitor-keys" "7.18.0" + +"@typescript-eslint/scope-manager@8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz#834301d2e70baf924c26818b911bdc40086f7468" + integrity sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg== + dependencies: + "@typescript-eslint/types" "8.3.0" + "@typescript-eslint/visitor-keys" "8.3.0" + +"@typescript-eslint/type-utils@7.16.1": + version "7.16.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.16.1.tgz#4d7ae4f3d9e3c8cbdabae91609b1a431de6aa6ca" + integrity sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA== dependencies: - "@typescript-eslint/types" "7.13.1" - "@typescript-eslint/visitor-keys" "7.13.1" + "@typescript-eslint/typescript-estree" "7.16.1" + "@typescript-eslint/utils" "7.16.1" + debug "^4.3.4" + ts-api-utils "^1.3.0" -"@typescript-eslint/type-utils@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz#63bec3f1fb43cf0bc409cbdb88ef96d118ca8632" - integrity sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg== +"@typescript-eslint/type-utils@8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz#c1ae6af8c21a27254321016b052af67ddb44a9ac" + integrity sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg== dependencies: - "@typescript-eslint/typescript-estree" "7.13.1" - "@typescript-eslint/utils" "7.13.1" + "@typescript-eslint/typescript-estree" "8.3.0" + "@typescript-eslint/utils" "8.3.0" debug "^4.3.4" ts-api-utils "^1.3.0" -"@typescript-eslint/types@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.13.1.tgz#787db283bd0b58751094c90d5b58bbf5e9fc9bd8" - integrity sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw== +"@typescript-eslint/types@7.16.1": + version "7.16.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.16.1.tgz#bbab066276d18e398bc64067b23f1ce84dfc6d8c" + integrity sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ== + +"@typescript-eslint/types@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.18.0.tgz#b90a57ccdea71797ffffa0321e744f379ec838c9" + integrity sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ== -"@typescript-eslint/typescript-estree@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz#3412841b130e070db2f675e3d9b8cb1ae49e1c3f" - integrity sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw== +"@typescript-eslint/types@8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.3.0.tgz#378e62447c2d7028236e55a81d3391026600563b" + integrity sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw== + +"@typescript-eslint/typescript-estree@7.16.1": + version "7.16.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz#9b145ba4fd1dde1986697e1ce57dc501a1736dd3" + integrity sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ== dependencies: - "@typescript-eslint/types" "7.13.1" - "@typescript-eslint/visitor-keys" "7.13.1" + "@typescript-eslint/types" "7.16.1" + "@typescript-eslint/visitor-keys" "7.16.1" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -2018,28 +2943,92 @@ semver "^7.6.0" ts-api-utils "^1.3.0" -"@typescript-eslint/utils@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.13.1.tgz#611083379caa0d3a2c09d126c65065a3e4337ba2" - integrity sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ== +"@typescript-eslint/typescript-estree@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz#b5868d486c51ce8f312309ba79bdb9f331b37931" + integrity sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA== + 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" + +"@typescript-eslint/typescript-estree@8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz#3e3d38af101ba61a8568f034733b72bfc9f176b9" + integrity sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA== + dependencies: + "@typescript-eslint/types" "8.3.0" + "@typescript-eslint/visitor-keys" "8.3.0" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" + +"@typescript-eslint/utils@7.16.1": + version "7.16.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.16.1.tgz#df42dc8ca5a4603016fd102db0346cdab415cdb7" + integrity sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "7.13.1" - "@typescript-eslint/types" "7.13.1" - "@typescript-eslint/typescript-estree" "7.13.1" + "@typescript-eslint/scope-manager" "7.16.1" + "@typescript-eslint/types" "7.16.1" + "@typescript-eslint/typescript-estree" "7.16.1" -"@typescript-eslint/visitor-keys@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz#9c229a795a919db61f2d7f2337ef584ac05fbe96" - integrity sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA== +"@typescript-eslint/utils@8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.3.0.tgz#b10972319deac5959c7a7075d0cf2b5e1de7ec08" + integrity sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA== dependencies: - "@typescript-eslint/types" "7.13.1" + "@eslint-community/eslint-utils" "^4.4.0" + "@typescript-eslint/scope-manager" "8.3.0" + "@typescript-eslint/types" "8.3.0" + "@typescript-eslint/typescript-estree" "8.3.0" + +"@typescript-eslint/utils@^7.16.1": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.18.0.tgz#bca01cde77f95fc6a8d5b0dbcbfb3d6ca4be451f" + integrity sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw== + 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" + +"@typescript-eslint/visitor-keys@7.16.1": + version "7.16.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz#4287bcf44c34df811ff3bb4d269be6cfc7d8c74b" + integrity sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg== + dependencies: + "@typescript-eslint/types" "7.16.1" eslint-visitor-keys "^3.4.3" -"@ubiquity-dao/ubiquibot-logger@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@ubiquity-dao/ubiquibot-logger/-/ubiquibot-logger-1.3.0.tgz#b07364658be95b3be3876305c66b2adc906e9590" - integrity sha512-ifkd7fB2OMTSt3OL9L14bCIvCMXV+IHFdJYU5S8FUzE2U88b4xKxuEAYDFX+DX3wwDEswFAVUwx5aP3QcMIRWA== +"@typescript-eslint/visitor-keys@7.18.0": + version "7.18.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz#0564629b6124d67607378d0f0332a0495b25e7d7" + integrity sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg== + dependencies: + "@typescript-eslint/types" "7.18.0" + eslint-visitor-keys "^3.4.3" + +"@typescript-eslint/visitor-keys@8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz#320d747d107af1eef1eb43fbc4ccdbddda13068b" + integrity sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA== + dependencies: + "@typescript-eslint/types" "8.3.0" + eslint-visitor-keys "^3.4.3" + +"@ubiquity-dao/ubiquibot-logger@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@ubiquity-dao/ubiquibot-logger/-/ubiquibot-logger-1.3.1.tgz#c3f45d70014dcc2551442c28101046e1c8ea6886" + integrity sha512-kDLnVP87Y3yZV6NnqIEDAOz+92IW0nIcccML2lUn93uZ5ada78vfdTPtwPJo8tkXl1Z9qMKAqqHkwBMp1Ksnag== JSONStream@^1.3.5: version "1.3.5" @@ -2049,25 +3038,29 @@ JSONStream@^1.3.5: jsonparse "^1.2.0" through ">=2.2.7 <3" +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.2.0: - version "8.3.2" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" - integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== - -acorn@^8.12.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c" - integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw== + version "8.3.3" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" + integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw== + dependencies: + acorn "^8.11.0" -acorn@^8.8.0: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +acorn@^8.11.0, acorn@^8.12.0, acorn@^8.8.0, acorn@^8.9.0: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== aggregate-error@^3.0.0: version "3.1.0" @@ -2077,14 +3070,6 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -aggregate-error@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-5.0.0.tgz#ffe15045d7521c51c9d618e3d7f37c13f29b3fd3" - integrity sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw== - dependencies: - clean-stack "^5.2.0" - indent-string "^5.0.0" - ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -2096,14 +3081,14 @@ ajv@^6.12.4: uri-js "^4.2.2" ajv@^8.11.0: - version "8.14.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.14.0.tgz#f514ddfd4756abb200e1704414963620a625ebbb" - integrity sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA== + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== dependencies: fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" - uri-js "^4.4.1" ansi-escapes@^4.2.1, ansi-escapes@^4.3.2: version "4.3.2" @@ -2112,10 +3097,12 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.2: dependencies: type-fest "^0.21.3" -ansi-escapes@^6.2.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-6.2.1.tgz#76c54ce9b081dad39acec4b5d53377913825fb0f" - integrity sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig== +ansi-escapes@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.0.0.tgz#00fc19f491bbb18e1d481b97868204f92109bfe7" + integrity sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw== + dependencies: + environment "^1.0.0" ansi-regex@^5.0.1: version "5.0.1" @@ -2171,12 +3158,14 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -arity-n@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/arity-n/-/arity-n-1.0.4.tgz#d9e76b11733e08569c0847ae7b39b2860b30b745" - integrity sha512-fExL2kFDC1Q2DUOx3whE/9KoN66IzkY4b4zUHUBFM1ojEYjZZYDcUW3bek/ufGionX9giIKDC5redH2IlGqcQQ== +aria-query@~5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e" + integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ== + dependencies: + deep-equal "^2.0.5" -array-buffer-byte-length@^1.0.1: +array-buffer-byte-length@^1.0.0, array-buffer-byte-length@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== @@ -2189,12 +3178,17 @@ array-ify@^1.0.0: resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng== -array-last@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/array-last/-/array-last-1.3.0.tgz#7aa77073fec565ddab2493f5f88185f404a9d336" - integrity sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg== +array-includes@^3.1.6, array-includes@^3.1.7, array-includes@^3.1.8: + version "3.1.8" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" + integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== dependencies: - is-number "^4.0.0" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" + is-string "^1.0.7" array-timsort@^1.0.3: version "1.0.3" @@ -2206,6 +3200,61 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +array.prototype.findlast@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" + integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" + +array.prototype.findlastindex@^1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d" + integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" + +array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.tosorted@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" + integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" + arraybuffer.prototype.slice@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" @@ -2227,11 +3276,26 @@ as-table@^1.0.36: dependencies: printable-characters "^1.0.42" +ast-types-flow@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6" + integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ== + async-lock@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.4.1.tgz#56b8718915a9b68b10fce2f2a9a3dddf765ef53f" integrity sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ== +async@^3.2.3: + version "3.2.6" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" + integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== + +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" @@ -2239,6 +3303,18 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" +axe-core@^4.9.1: + version "4.10.0" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.0.tgz#d9e56ab0147278272739a000880196cdfe113b59" + integrity sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g== + +axobject-query@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.1.1.tgz#3b6e5c6d4e43ca7ba51c5babf99d22a9c68485e1" + integrity sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg== + dependencies: + deep-equal "^2.0.5" + babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" @@ -2273,23 +3349,50 @@ babel-plugin-jest-hoist@^29.6.3: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.11" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" + integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.2" + semver "^6.3.1" + +babel-plugin-polyfill-corejs3@^0.10.4: + version "0.10.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7" + integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.2" + core-js-compat "^3.38.0" + +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" + integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.2" + babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + version "1.1.0" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz#9a929eafece419612ef4ae4f60b1862ebad8ef30" + integrity sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" babel-preset-jest@^29.6.3: version "29.6.3" @@ -2299,21 +3402,26 @@ babel-preset-jest@^29.6.3: babel-plugin-jest-hoist "^29.6.3" babel-preset-current-node-syntax "^1.0.0" -babylon@^6.9.1: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + before-after-hook@^2.2.0: version "2.2.3" resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== +before-after-hook@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-3.0.2.tgz#d5665a5fa8b62294a5aa0a499f933f4a1016195d" + integrity sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A== + binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" @@ -2346,17 +3454,17 @@ braces@^3.0.3, braces@~3.0.2: dependencies: fill-range "^7.1.1" -browserslist@^4.22.2: - version "4.23.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" - integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== +browserslist@^4.23.1, browserslist@^4.23.3: + version "4.23.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.3.tgz#debb029d3c93ebc97ffbc8d9cbb03403e227c800" + integrity sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA== dependencies: - caniuse-lite "^1.0.30001587" - electron-to-chromium "^1.4.668" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" + caniuse-lite "^1.0.30001646" + electron-to-chromium "^1.5.4" + node-releases "^2.0.18" + update-browserslist-db "^1.1.0" -bs-logger@0.x: +bs-logger@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== @@ -2375,6 +3483,24 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +builtin-modules@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" @@ -2386,6 +3512,11 @@ call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: get-intrinsic "^1.2.4" set-function-length "^1.2.1" +callback-data@1.1.1, callback-data@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/callback-data/-/callback-data-1.1.1.tgz#0d4f70995df97ec039cea08985623a7205ac080c" + integrity sha512-1XoQQTsTkuU0/Ee2vRS64d+mKmM+zfEWgarI3ETPfYV3R5UvArM7C0sXSGPff+Aztea1Vrom6LDs9HQWSZucXQ== + callsites@^3.0.0, callsites@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -2401,10 +3532,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001587: - version "1.0.30001626" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001626.tgz#328623664a28493b4a9019af7ce03ea39fbe898c" - integrity sha512-JRW7kAH8PFJzoPCJhLSHgDgKg5348hsQ68aqb+slnzuB5QFERv846oA/mRChmlLAOdEDeOkRn3ynb1gSFnjt3w== +caniuse-lite@^1.0.30001646: + version "1.0.30001653" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001653.tgz#b8af452f8f33b1c77f122780a4aecebea0caca56" + integrity sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw== capnp-ts@^0.7.0: version "0.7.0" @@ -2430,7 +3561,7 @@ chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.2: +chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2474,9 +3605,9 @@ ci-info@^3.2.0: integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== cjs-module-lexer@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz#c485341ae8fd999ca4ee5af2d7a1c9ae01e0099c" - integrity sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q== + version "1.4.0" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.0.tgz#677de7ed7efff67cc40c9bf1897fea79d41b5215" + integrity sha512-N1NGmowPlGBLsOZLPvm48StN04V4YvQRL0i6b7ctrVY3epjP/ct7hFLOItz6pDIvRjwpfPxi52a2UWV2ziir8g== clean-git-ref@^2.0.1: version "2.0.1" @@ -2488,13 +3619,6 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -clean-stack@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-5.2.0.tgz#c7a0c91939c7caace30a3bf254e8a8ac276d1189" - integrity sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ== - dependencies: - escape-string-regexp "5.0.0" - clear-module@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/clear-module/-/clear-module-4.1.2.tgz#5a58a5c9f8dccf363545ad7284cad3c887352a80" @@ -2503,12 +3627,12 @@ clear-module@^4.1.2: parent-module "^2.0.0" resolve-from "^5.0.0" -cli-cursor@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" - integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg== +cli-cursor@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-5.0.0.tgz#24a4831ecf5a6b01ddeb32fb71a4b2088b0dce38" + integrity sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw== dependencies: - restore-cursor "^4.0.0" + restore-cursor "^5.0.0" cli-spinners@^2.9.2: version "2.9.2" @@ -2576,12 +3700,12 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^2.0.20: +colorette@^2.0.20, colorette@^2.0.7: version "2.0.20" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== -commander@^12.1.0, commander@~12.1.0: +commander@^12.0.0, commander@^12.1.0, commander@~12.1.0: version "12.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== @@ -2591,10 +3715,10 @@ commander@^4.1.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -comment-json@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/comment-json/-/comment-json-4.2.3.tgz#50b487ebbf43abe44431f575ebda07d30d015365" - integrity sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw== +comment-json@^4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/comment-json/-/comment-json-4.2.5.tgz#482e085f759c2704b60bc6f97f55b8c01bc41e70" + integrity sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw== dependencies: array-timsort "^1.0.3" core-util-is "^1.0.3" @@ -2610,13 +3734,6 @@ compare-func@^2.0.0: array-ify "^1.0.0" dot-prop "^5.1.0" -compose-function@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/compose-function/-/compose-function-3.0.3.tgz#9ed675f13cc54501d30950a486ff6a7ba3ab185f" - integrity sha512-xzhzTJ5eC+gmIzvZq+C3kCJHsp9os6tJkrigDRZclyGtOKINbZtE8n1Tzmeh32jW+BUDPbvZpibwvJHBLGMVwg== - dependencies: - arity-n "^1.0.4" - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2661,6 +3778,13 @@ cookie@^0.5.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +core-js-compat@^3.31.0, core-js-compat@^3.38.0: + version "3.38.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.38.1.tgz#2bc7a298746ca5a7bcb9c164bcb120f2ebc09a09" + integrity sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw== + dependencies: + browserslist "^4.23.3" + core-util-is@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -2726,118 +3850,127 @@ crypt@0.0.2: resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== -cspell-config-lib@8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/cspell-config-lib/-/cspell-config-lib-8.9.0.tgz#df256d9228cdfdc4a081eecec1706b3dd8e4de57" - integrity sha512-1FQketvqo6IktnyC2ishEIzfqSX2DNhsfpb0MIG/nNeG5KvbjSeozOZpfyrALVqhPUJZVWfMP3+N0/hj3AzH+g== +cspell-config-lib@8.14.2: + version "8.14.2" + resolved "https://registry.yarnpkg.com/cspell-config-lib/-/cspell-config-lib-8.14.2.tgz#cc401080c14dab7b355bda4e90a22b7dfb05ffd6" + integrity sha512-yHP1BdcH5dbjb8qiZr6+bxEnJ+rxTULQ00wBz3eBPWCghJywEAYYvMWoYuxVtPpndlkKYC1wJAHsyNkweQyepA== dependencies: - "@cspell/cspell-types" "8.9.0" - comment-json "^4.2.3" - yaml "^2.4.5" + "@cspell/cspell-types" "8.14.2" + comment-json "^4.2.5" + yaml "^2.5.0" -cspell-dictionary@8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/cspell-dictionary/-/cspell-dictionary-8.9.0.tgz#57ec639760f4b27cc568c4905f1cd35595655f91" - integrity sha512-IsFyWsn9P979xoJ0PgWHdyjxVcDYe5nVmHMgJRecQ5LLhl2gFkOmsu+aYIh2qlHCLmcbzH31Me2x7Fd+jA6AXw== +cspell-dictionary@8.14.2: + version "8.14.2" + resolved "https://registry.yarnpkg.com/cspell-dictionary/-/cspell-dictionary-8.14.2.tgz#0268d437eed78bfcf6eadc3674a3e3104e010d7a" + integrity sha512-gWuAvf6queGGUvGbfAxxUq55cZ0OevWPbjnCrSB0PpJ4tqdFd8dLcvVrIKzoE2sBXKPw2NDkmoEngs6iGavC0w== dependencies: - "@cspell/cspell-pipe" "8.9.0" - "@cspell/cspell-types" "8.9.0" - cspell-trie-lib "8.9.0" + "@cspell/cspell-pipe" "8.14.2" + "@cspell/cspell-types" "8.14.2" + cspell-trie-lib "8.14.2" fast-equals "^5.0.1" - gensequence "^7.0.0" -cspell-gitignore@8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/cspell-gitignore/-/cspell-gitignore-8.9.0.tgz#1814a4b3ebdbf995aa1fe2be04c80a45766e5811" - integrity sha512-/iw+iqFLgySqW7xJ+kDHtC0mRjajDM1/jvnu4pUoxU9cRanCEqg2IAA/BET+n3ZEs/etsl8P4MB0lgWE98Z15g== +cspell-gitignore@8.14.2: + version "8.14.2" + resolved "https://registry.yarnpkg.com/cspell-gitignore/-/cspell-gitignore-8.14.2.tgz#239995ac11652a9978126ec35b12d663010a90f3" + integrity sha512-lrO/49NaKBpkR7vFxv4OOY+oHmsG5+gNQejrBBWD9Nv9vvjJtz/G36X/rcN6M6tFcQQMWwa01kf04nxz8Ejuhg== dependencies: - cspell-glob "8.9.0" + "@cspell/url" "8.14.2" + cspell-glob "8.14.2" + cspell-io "8.14.2" find-up-simple "^1.0.0" -cspell-glob@8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/cspell-glob/-/cspell-glob-8.9.0.tgz#a28b85732abd82e7293bb9d84a05d1f5d3dddf8a" - integrity sha512-j96SMMzT5Nz0nKCUECLkoyPEEms4hXKm/S7Vj80A356TFglTJD/yYiMKfWUamCVPm8UYODCz7W0s/liR7gSBSw== +cspell-glob@8.14.2: + version "8.14.2" + resolved "https://registry.yarnpkg.com/cspell-glob/-/cspell-glob-8.14.2.tgz#09f53191e58db113837a088a7a9ea7a181f2deb7" + integrity sha512-9Q1Kgoo1ev3fKTpp9y5n8M4RLxd8B0f5o4y5FQe4dBU0j/bt+/YDrLZNWDm77JViV606XQ6fimG1FTTq6pT9/g== dependencies: + "@cspell/url" "8.14.2" micromatch "^4.0.7" -cspell-grammar@8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/cspell-grammar/-/cspell-grammar-8.9.0.tgz#2d22fbcdab8980eae9ab3344d4ab2d76dcc3b3ba" - integrity sha512-oZEOE64lLc0clLGOJeqc5d1Yzc1fUtXQAAeLIrS+uoVM7nA1SqgIEv1JBjp3R++8jQKLjS5n7v16VW5A/yk67w== - dependencies: - "@cspell/cspell-pipe" "8.9.0" - "@cspell/cspell-types" "8.9.0" - -cspell-io@8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/cspell-io/-/cspell-io-8.9.0.tgz#7b2ffa99af96b742ec584dbc10fab2bc9517a60c" - integrity sha512-8KHERgqlg8KKpn04Owg2VY1Di2dSiwV/v63bUFxsGb8ORGIQ1VcydxtANwWuugUrZvtVrSFsbuU2fK/LRmAnoQ== - dependencies: - "@cspell/cspell-service-bus" "8.9.0" - "@cspell/url" "8.9.0" - -cspell-lib@8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/cspell-lib/-/cspell-lib-8.9.0.tgz#b843d7c97360d22df93bea701f7d9eed1b72f934" - integrity sha512-k347TQs1QRUyyHWHYQxPJddApos/irFousr9W/M/jEkYTTKzMMfaXK8m20kBSnlJ+BOUMa+f8d+KPEw6QLwtJQ== - dependencies: - "@cspell/cspell-bundled-dicts" "8.9.0" - "@cspell/cspell-pipe" "8.9.0" - "@cspell/cspell-resolver" "8.9.0" - "@cspell/cspell-types" "8.9.0" - "@cspell/dynamic-import" "8.9.0" - "@cspell/strong-weak-map" "8.9.0" - "@cspell/url" "8.9.0" +cspell-grammar@8.14.2: + version "8.14.2" + resolved "https://registry.yarnpkg.com/cspell-grammar/-/cspell-grammar-8.14.2.tgz#a37e4f6ce6aae8eba2ba57822a4cfe0cd7fd8909" + integrity sha512-eYwceVP80FGYVJenE42ALnvEKOXaXjq4yVbb1Ni1umO/9qamLWNCQ1RP6rRACy5e/cXviAbhrQ5Mtw6n+pyPEQ== + dependencies: + "@cspell/cspell-pipe" "8.14.2" + "@cspell/cspell-types" "8.14.2" + +cspell-io@8.14.2: + version "8.14.2" + resolved "https://registry.yarnpkg.com/cspell-io/-/cspell-io-8.14.2.tgz#501b26c630f6d8e9fc89fce1ad806c10b440723a" + integrity sha512-uaKpHiY3DAgfdzgKMQml6U8F8o9udMuYxGqYa5FVfN7D5Ap7B2edQzSLTUYwxrFEn4skSfp6XY73+nzJvxzH4Q== + dependencies: + "@cspell/cspell-service-bus" "8.14.2" + "@cspell/url" "8.14.2" + +cspell-lib@8.14.2: + version "8.14.2" + resolved "https://registry.yarnpkg.com/cspell-lib/-/cspell-lib-8.14.2.tgz#ca404ad026c7150c96426a11faa5c9f761015bbb" + integrity sha512-d2oiIXHXnADmnhIuFLOdNE63L7OUfzgpLbYaqAWbkImCUDkevfGrOgnX8TJ03fUgZID4nvQ+3kgu/n2j4eLZjQ== + dependencies: + "@cspell/cspell-bundled-dicts" "8.14.2" + "@cspell/cspell-pipe" "8.14.2" + "@cspell/cspell-resolver" "8.14.2" + "@cspell/cspell-types" "8.14.2" + "@cspell/dynamic-import" "8.14.2" + "@cspell/filetypes" "8.14.2" + "@cspell/strong-weak-map" "8.14.2" + "@cspell/url" "8.14.2" clear-module "^4.1.2" - comment-json "^4.2.3" - cspell-config-lib "8.9.0" - cspell-dictionary "8.9.0" - cspell-glob "8.9.0" - cspell-grammar "8.9.0" - cspell-io "8.9.0" - cspell-trie-lib "8.9.0" + comment-json "^4.2.5" + cspell-config-lib "8.14.2" + cspell-dictionary "8.14.2" + cspell-glob "8.14.2" + cspell-grammar "8.14.2" + cspell-io "8.14.2" + cspell-trie-lib "8.14.2" env-paths "^3.0.0" fast-equals "^5.0.1" gensequence "^7.0.0" import-fresh "^3.3.0" resolve-from "^5.0.0" - vscode-languageserver-textdocument "^1.0.11" + vscode-languageserver-textdocument "^1.0.12" vscode-uri "^3.0.8" xdg-basedir "^5.1.0" -cspell-trie-lib@8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/cspell-trie-lib/-/cspell-trie-lib-8.9.0.tgz#266a1bdf248f075a61851d7cd4bd082458a1780f" - integrity sha512-fQNQyFoeZA7b66jvhGaUYPzsS6gmPRJa6RcEpw2onP41S+IyLO6egubUu/qq8Hn1ebgJe/0Pc4fzkgv6MfV3tQ== +cspell-trie-lib@8.14.2: + version "8.14.2" + resolved "https://registry.yarnpkg.com/cspell-trie-lib/-/cspell-trie-lib-8.14.2.tgz#3748544d4f6ca85c3d72a1f2eb72b930c898865b" + integrity sha512-rZMbaEBGoyy4/zxKECaMyVyGLbuUxYmZ5jlEgiA3xPtEdWwJ4iWRTo5G6dWbQsXoxPYdAXXZ0/q0GQ2y6Jt0kw== dependencies: - "@cspell/cspell-pipe" "8.9.0" - "@cspell/cspell-types" "8.9.0" + "@cspell/cspell-pipe" "8.14.2" + "@cspell/cspell-types" "8.14.2" gensequence "^7.0.0" -cspell@8.9.0: - version "8.9.0" - resolved "https://registry.yarnpkg.com/cspell/-/cspell-8.9.0.tgz#f8a1faa99cc266b94b38744708417ea58e136ffd" - integrity sha512-lDYu5p/XU3rqiNjMV46s92yJ7SfVyzAy03OtCJ94fopegZwFLjqZvqoy509ccP/0sHmiv83oTed8LP6Fm3kjpw== +cspell@8.14.2: + version "8.14.2" + resolved "https://registry.yarnpkg.com/cspell/-/cspell-8.14.2.tgz#d1434bc66831113121a91427c39dc22802dc4c31" + integrity sha512-ii/W7fwO4chNQVYl1C/8k7RW8EXzLb69rvg08p8mSJx8B2UasVJ9tuJpTH2Spo1jX6N3H0dKPWUbd1fAmdAhPg== dependencies: - "@cspell/cspell-json-reporter" "8.9.0" - "@cspell/cspell-pipe" "8.9.0" - "@cspell/cspell-types" "8.9.0" - "@cspell/dynamic-import" "8.9.0" + "@cspell/cspell-json-reporter" "8.14.2" + "@cspell/cspell-pipe" "8.14.2" + "@cspell/cspell-types" "8.14.2" + "@cspell/dynamic-import" "8.14.2" + "@cspell/url" "8.14.2" chalk "^5.3.0" chalk-template "^1.1.0" commander "^12.1.0" - cspell-gitignore "8.9.0" - cspell-glob "8.9.0" - cspell-io "8.9.0" - cspell-lib "8.9.0" + cspell-dictionary "8.14.2" + cspell-gitignore "8.14.2" + cspell-glob "8.14.2" + cspell-io "8.14.2" + cspell-lib "8.14.2" fast-glob "^3.3.2" fast-json-stable-stringify "^2.1.0" - file-entry-cache "^8.0.0" + file-entry-cache "^9.0.0" get-stdin "^9.0.0" - semver "^7.6.2" + semver "^7.6.3" strip-ansi "^7.1.0" - vscode-uri "^3.0.8" + +damerau-levenshtein@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" + integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== dargs@^8.0.0: version "8.1.0" @@ -2883,10 +4016,27 @@ date-fns@^2.21.1: dependencies: "@babel/runtime" "^7.21.0" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== +date-fns@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-3.6.0.tgz#f20ca4fe94f8b754951b24240676e8618c0206bf" + integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww== + +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.6: + version "4.3.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" + integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== dependencies: ms "2.1.2" @@ -2902,6 +4052,30 @@ dedent@^1.0.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.3.tgz#99aee19eb9bae55a67327717b6e848d0bf777e5a" integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== +deep-equal@^2.0.5: + version "2.2.3" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1" + integrity sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.5" + es-get-iterator "^1.1.3" + get-intrinsic "^1.2.2" + is-arguments "^1.1.1" + is-array-buffer "^3.0.2" + is-date-object "^1.0.5" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + isarray "^2.0.5" + object-is "^1.1.5" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.1" + side-channel "^1.0.4" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.1" + which-typed-array "^1.1.13" + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -2928,7 +4102,7 @@ define-data-property@^1.0.1, define-data-property@^1.1.4: es-errors "^1.3.0" gopd "^1.0.1" -define-properties@^1.2.0, define-properties@^1.2.1: +define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== @@ -2969,6 +4143,13 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + dot-prop@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" @@ -2981,6 +4162,11 @@ dotenv@16.4.5: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== +duplexer@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + easy-table@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/easy-table/-/easy-table-1.2.0.tgz#ba9225d7138fee307bfd4f0b5bc3c04bdc7c54eb" @@ -2990,10 +4176,17 @@ easy-table@1.2.0: optionalDependencies: wcwidth "^1.0.1" -electron-to-chromium@^1.4.668: - version "1.4.788" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.788.tgz#a3545959d5cfa0a266d3e551386c040be34e7e06" - integrity sha512-ubp5+Ev/VV8KuRoWnfP2QF2Bg+O2ZFdb49DiiNbz2VmgkIqrnyYaqIOqj8A6K/3p1xV0QcU5hBQ1+BmB6ot1OA== +ejs@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" + integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== + dependencies: + jake "^10.8.5" + +electron-to-chromium@^1.5.4: + version "1.5.13" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz#1abf0410c5344b2b829b7247e031f02810d442e6" + integrity sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q== emittery@^0.13.1: version "0.13.1" @@ -3001,15 +4194,35 @@ emittery@^0.13.1: integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== emoji-regex@^10.3.0: - version "10.3.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.3.0.tgz#76998b9268409eb3dae3de989254d456e70cfe23" - integrity sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw== + version "10.4.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.4.0.tgz#03553afea80b3975749cfcb36f776ca268e413d4" + integrity sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw== emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enhanced-resolve@^5.17.1: + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + env-paths@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" @@ -3020,6 +4233,11 @@ env-paths@^3.0.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-3.0.0.tgz#2f1e89c2f6dbd3408e1b1711dd82d62e317f58da" integrity sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A== +environment@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" + integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -3027,7 +4245,7 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2: +es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: version "1.23.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== @@ -3091,6 +4309,41 @@ es-errors@^1.2.1, es-errors@^1.3.0: resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== +es-get-iterator@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6" + integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + has-symbols "^1.0.3" + is-arguments "^1.1.1" + is-map "^2.0.2" + is-set "^2.0.2" + is-string "^1.0.7" + isarray "^2.0.5" + stop-iteration-iterator "^1.0.0" + +es-iterator-helpers@^1.0.19: + version "1.0.19" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8" + integrity sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.3" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + globalthis "^1.0.3" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + internal-slot "^1.0.7" + iterator.prototype "^1.1.2" + safe-array-concat "^1.1.2" + es-object-atoms@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" @@ -3107,6 +4360,13 @@ es-set-tostringtag@^2.0.3: has-tostringtag "^1.0.2" hasown "^2.0.1" +es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== + dependencies: + hasown "^2.0.0" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -3144,45 +4404,41 @@ esbuild@0.17.19: "@esbuild/win32-ia32" "0.17.19" "@esbuild/win32-x64" "0.17.19" -esbuild@~0.21.4: - version "0.21.5" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" - integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== +esbuild@~0.23.0: + version "0.23.1" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.23.1.tgz#40fdc3f9265ec0beae6f59824ade1bd3d3d2dab8" + integrity sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg== optionalDependencies: - "@esbuild/aix-ppc64" "0.21.5" - "@esbuild/android-arm" "0.21.5" - "@esbuild/android-arm64" "0.21.5" - "@esbuild/android-x64" "0.21.5" - "@esbuild/darwin-arm64" "0.21.5" - "@esbuild/darwin-x64" "0.21.5" - "@esbuild/freebsd-arm64" "0.21.5" - "@esbuild/freebsd-x64" "0.21.5" - "@esbuild/linux-arm" "0.21.5" - "@esbuild/linux-arm64" "0.21.5" - "@esbuild/linux-ia32" "0.21.5" - "@esbuild/linux-loong64" "0.21.5" - "@esbuild/linux-mips64el" "0.21.5" - "@esbuild/linux-ppc64" "0.21.5" - "@esbuild/linux-riscv64" "0.21.5" - "@esbuild/linux-s390x" "0.21.5" - "@esbuild/linux-x64" "0.21.5" - "@esbuild/netbsd-x64" "0.21.5" - "@esbuild/openbsd-x64" "0.21.5" - "@esbuild/sunos-x64" "0.21.5" - "@esbuild/win32-arm64" "0.21.5" - "@esbuild/win32-ia32" "0.21.5" - "@esbuild/win32-x64" "0.21.5" + "@esbuild/aix-ppc64" "0.23.1" + "@esbuild/android-arm" "0.23.1" + "@esbuild/android-arm64" "0.23.1" + "@esbuild/android-x64" "0.23.1" + "@esbuild/darwin-arm64" "0.23.1" + "@esbuild/darwin-x64" "0.23.1" + "@esbuild/freebsd-arm64" "0.23.1" + "@esbuild/freebsd-x64" "0.23.1" + "@esbuild/linux-arm" "0.23.1" + "@esbuild/linux-arm64" "0.23.1" + "@esbuild/linux-ia32" "0.23.1" + "@esbuild/linux-loong64" "0.23.1" + "@esbuild/linux-mips64el" "0.23.1" + "@esbuild/linux-ppc64" "0.23.1" + "@esbuild/linux-riscv64" "0.23.1" + "@esbuild/linux-s390x" "0.23.1" + "@esbuild/linux-x64" "0.23.1" + "@esbuild/netbsd-x64" "0.23.1" + "@esbuild/openbsd-arm64" "0.23.1" + "@esbuild/openbsd-x64" "0.23.1" + "@esbuild/sunos-x64" "0.23.1" + "@esbuild/win32-arm64" "0.23.1" + "@esbuild/win32-ia32" "0.23.1" + "@esbuild/win32-x64" "0.23.1" escalade@^3.1.1, escalade@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== -escape-string-regexp@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" - integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== - escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -3203,6 +4459,22 @@ eslint-config-prettier@9.1.0: resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== +eslint-import-resolver-node@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== + dependencies: + debug "^3.2.7" + is-core-module "^2.13.0" + resolve "^1.22.4" + +eslint-module-utils@^2.8.0: + version "2.8.2" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.2.tgz#2ecad69d71e1fa81f17f7f24d5d3e46b168de663" + integrity sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg== + dependencies: + debug "^3.2.7" + eslint-plugin-check-file@2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/eslint-plugin-check-file/-/eslint-plugin-check-file-2.8.0.tgz#6f93f28b25376ca9a7b0d741ca56a726d59f8db7" @@ -3211,20 +4483,127 @@ eslint-plugin-check-file@2.8.0: is-glob "^4.0.3" micromatch "^4.0.5" -eslint-plugin-prettier@5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz#17cfade9e732cef32b5f5be53bd4e07afd8e67e1" - integrity sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw== +eslint-plugin-import@^2.29.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" + integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== + dependencies: + array-includes "^3.1.7" + array.prototype.findlastindex "^1.2.3" + array.prototype.flat "^1.3.2" + array.prototype.flatmap "^1.3.2" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.9" + eslint-module-utils "^2.8.0" + hasown "^2.0.0" + is-core-module "^2.13.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.fromentries "^2.0.7" + object.groupby "^1.0.1" + object.values "^1.1.7" + semver "^6.3.1" + tsconfig-paths "^3.15.0" + +eslint-plugin-jsx-a11y@^6.8.0: + version "6.9.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz#67ab8ff460d4d3d6a0b4a570e9c1670a0a8245c8" + integrity sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g== + dependencies: + aria-query "~5.1.3" + array-includes "^3.1.8" + array.prototype.flatmap "^1.3.2" + ast-types-flow "^0.0.8" + axe-core "^4.9.1" + axobject-query "~3.1.1" + damerau-levenshtein "^1.0.8" + emoji-regex "^9.2.2" + es-iterator-helpers "^1.0.19" + hasown "^2.0.2" + jsx-ast-utils "^3.3.5" + language-tags "^1.0.9" + minimatch "^3.1.2" + object.fromentries "^2.0.8" + safe-regex-test "^1.0.3" + string.prototype.includes "^2.0.0" + +eslint-plugin-prettier@5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz#d1c8f972d8f60e414c25465c163d16f209411f95" + integrity sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw== dependencies: prettier-linter-helpers "^1.0.0" - synckit "^0.8.6" + synckit "^0.9.1" -eslint-plugin-sonarjs@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-1.0.3.tgz#423de6f9244c886633ff36183c6fbc9fb1ed867d" - integrity sha512-6s41HLPYPyDrp+5+7Db5yFYbod6h9pC7yx+xfcNwHRcLe1EZwbbQT/tdOAkR7ekVUkNGEvN3GmYakIoQUX7dEg== +eslint-plugin-react-hooks@4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" + integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== + +eslint-plugin-react@^7.35.0: + version "7.35.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz#00b1e4559896710e58af6358898f2ff917ea4c41" + integrity sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA== + dependencies: + array-includes "^3.1.8" + array.prototype.findlast "^1.2.5" + array.prototype.flatmap "^1.3.2" + array.prototype.tosorted "^1.1.4" + doctrine "^2.1.0" + es-iterator-helpers "^1.0.19" + estraverse "^5.3.0" + hasown "^2.0.2" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.8" + object.fromentries "^2.0.8" + object.values "^1.2.0" + prop-types "^15.8.1" + resolve "^2.0.0-next.5" + semver "^6.3.1" + string.prototype.matchall "^4.0.11" + string.prototype.repeat "^1.0.0" + +eslint-plugin-sonarjs@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-2.0.1.tgz#a1904db954f9eb841f29b3033cdccec989e9f3b9" + integrity sha512-hkiM2yJakXsEzdBhCzCvjd0DfdVL7w1JFSFYp08KEzlwu7SZtP5QKbDU7Hf8VI3Jkve3/py/yUGuT46+juSk6Q== + dependencies: + "@babel/core" "7.24.3" + "@babel/eslint-parser" "7.24.1" + "@babel/plugin-proposal-decorators" "7.24.1" + "@babel/preset-env" "7.24.3" + "@babel/preset-flow" "7.24.1" + "@babel/preset-react" "7.24.1" + "@eslint-community/regexpp" "4.10.0" + "@types/eslint" "8.56.10" + "@typescript-eslint/eslint-plugin" "7.16.1" + "@typescript-eslint/utils" "^7.16.1" + builtin-modules "3.3.0" + bytes "3.1.2" + eslint-plugin-import "^2.29.1" + eslint-plugin-jsx-a11y "^6.8.0" + eslint-plugin-react "^7.35.0" + eslint-plugin-react-hooks "4.6.0" + eslint-scope "8.0.1" + functional-red-black-tree "1.0.1" + jsx-ast-utils "^3.3.5" + minimatch "^9.0.3" + scslre "0.3.0" + semver "7.6.0" + typescript "5.4.3" + vue-eslint-parser "9.4.3" + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" -eslint-scope@^8.0.1: +eslint-scope@8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.1.tgz#a9601e4b81a0b9171657c343fb13111688963cfc" integrity sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og== @@ -3232,7 +4611,28 @@ eslint-scope@^8.0.1: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.3: +eslint-scope@^7.1.1: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-scope@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.2.tgz#5cbb33d4384c9136083a71190d548158fe128f94" + integrity sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== @@ -3242,16 +4642,16 @@ eslint-visitor-keys@^4.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== -eslint@9.5.0: - version "9.5.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.5.0.tgz#11856034b94a9e1a02cfcc7e96a9f0956963cd2f" - integrity sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw== +eslint@9.9.1: + version "9.9.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.9.1.tgz#147ac9305d56696fb84cf5bdecafd6517ddc77ec" + integrity sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg== dependencies: "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/config-array" "^0.16.0" + "@eslint-community/regexpp" "^4.11.0" + "@eslint/config-array" "^0.18.0" "@eslint/eslintrc" "^3.1.0" - "@eslint/js" "9.5.0" + "@eslint/js" "9.9.1" "@humanwhocodes/module-importer" "^1.0.1" "@humanwhocodes/retry" "^0.3.0" "@nodelib/fs.walk" "^1.2.8" @@ -3260,9 +4660,9 @@ eslint@9.5.0: cross-spawn "^7.0.2" debug "^4.3.2" escape-string-regexp "^4.0.0" - eslint-scope "^8.0.1" + eslint-scope "^8.0.2" eslint-visitor-keys "^4.0.0" - espree "^10.0.1" + espree "^10.1.0" esquery "^1.5.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -3282,7 +4682,7 @@ eslint@9.5.0: strip-ansi "^6.0.1" text-table "^0.2.0" -espree@^10.0.1: +espree@^10.0.1, espree@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/espree/-/espree-10.1.0.tgz#8788dae611574c0f070691f522e4116c5a11fc56" integrity sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA== @@ -3291,15 +4691,24 @@ espree@^10.0.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^4.0.0" +espree@^9.3.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== +esquery@^1.4.0, esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== dependencies: estraverse "^5.1.0" @@ -3310,7 +4719,12 @@ esrecurse@^4.3.0: dependencies: estraverse "^5.2.0" -estraverse@^5.1.0, estraverse@^5.2.0: +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== @@ -3325,11 +4739,39 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +event-stream@=3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" + integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g== + dependencies: + duplexer "~0.1.1" + from "~0" + map-stream "~0.1.0" + pause-stream "0.0.11" + split "0.3" + stream-combiner "~0.0.4" + through "~2.3.1" + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + eventemitter3@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +eventsource@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-2.0.2.tgz#76dfcc02930fb2ff339520b6d290da573a9e8508" + integrity sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA== + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -3381,6 +4823,11 @@ expect@^29.0.0, expect@^29.7.0: jest-message-util "^29.7.0" jest-util "^29.7.0" +fast-copy@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.2.tgz#59c68f59ccbcac82050ba992e0d5c389097c9d35" + integrity sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -3417,7 +4864,22 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== -fastq@^1.15.0, fastq@^1.6.0: +fast-redact@^3.1.1: + version "3.5.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" + integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== + +fast-safe-stringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + +fast-uri@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.1.tgz#cddd2eecfc83a71c1be2cc2ef2061331be8a7134" + integrity sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw== + +fastq@^1.6.0: version "1.17.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== @@ -3431,13 +4893,27 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" -file-entry-cache@8.0.0, file-entry-cache@^8.0.0: +file-entry-cache@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== dependencies: flat-cache "^4.0.0" +file-entry-cache@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-9.0.0.tgz#4478e7ceaa5191fa9676a2daa7030211c31b1e7e" + integrity sha512-6MgEugi8p2tiUhqO7GnPsmbCCzj0YRCwwaTbpGRyKZesjRSzkqkAE9fPp7V2yMs5hwfgbQLgdvSSkGNg1s5Uvw== + dependencies: + flat-cache "^5.0.0" + +filelist@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" + integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q== + dependencies: + minimatch "^5.0.1" + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -3445,11 +4921,6 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -filter-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" - integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== - find-up-simple@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/find-up-simple/-/find-up-simple-1.0.0.tgz#21d035fde9fdbd56c8f4d2f63f32fd93a1cfc368" @@ -3488,7 +4959,15 @@ flat-cache@^4.0.0: flatted "^3.2.9" keyv "^4.5.4" -flatted@^3.2.9: +flat-cache@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-5.0.0.tgz#26c4da7b0f288b408bb2b506b2cb66c240ddf062" + integrity sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ== + dependencies: + flatted "^3.3.1" + keyv "^4.5.4" + +flatted@^3.2.9, flatted@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== @@ -3500,6 +4979,11 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +from@~0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" + integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g== + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -3525,6 +5009,11 @@ function.prototype.name@^1.1.6: es-abstract "^1.22.1" functions-have-names "^1.2.3" +functional-red-black-tree@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + functions-have-names@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" @@ -3550,7 +5039,7 @@ get-east-asian-width@^1.0.0: resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz#5e6ebd9baee6fb8b7b6bd505221065f0cd91f64e" integrity sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA== -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: +get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== @@ -3599,9 +5088,9 @@ get-symbol-description@^1.0.2: get-intrinsic "^1.2.4" get-tsconfig@^4.7.5: - version "4.7.5" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.5.tgz#5e012498579e9a6947511ed0cd403272c7acbbaf" - integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw== + version "4.7.6" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.6.tgz#118fd5b7b9bae234cc7705a00cd771d7eb65d62a" + integrity sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA== dependencies: resolve-pkg-maps "^1.0.0" @@ -3689,20 +5178,37 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.2, graceful-fs@^4.2.9: +graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== +grammy-guard@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/grammy-guard/-/grammy-guard-0.5.0.tgz#de2cb448f627fb9861648354f604ad6406aad475" + integrity sha512-vGqrEJPpm5XnaTkklkb/luLdo+qNZX78Fr9CwLdPFEUymYByqlxU/h+NKEmzsNHzC9lc+rS8oR+xQo1Wo5Ogxg== + dependencies: + callback-data "^1.0.0" + +grammy@^1.29.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/grammy/-/grammy-1.29.0.tgz#5413af877fc031c4f4a7db78dccb3717fa2209dc" + integrity sha512-lj/6K6TGmVAdOpHj0PVFK7N37EGe76bpkbgvN+yqCqXYBIwuQosTe7qLhCls7/4pbDxf2+UVSqSXcOILgGGKWQ== + dependencies: + "@grammyjs/types" "3.13.0" + abort-controller "^3.0.0" + debug "^4.3.4" + node-fetch "^2.7.0" + graphemer@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== graphql@^16.8.1: - version "16.8.1" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" - integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw== + version "16.9.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.9.0.tgz#1c310e63f16a49ce1fbb230bd0a000e99f6f115f" + integrity sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw== has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" @@ -3724,11 +5230,6 @@ has-own-prop@^2.0.0: resolved "https://registry.yarnpkg.com/has-own-prop/-/has-own-prop-2.0.0.tgz#f0f95d58f65804f5d218db32563bb85b8e0417af" integrity sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ== -has-own-property@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-own-property/-/has-own-property-0.1.0.tgz#992b0f5bb3a25416f8d4d0cde53f497b9d7b1ea5" - integrity sha512-14qdBKoonU99XDhWcFKZTShK+QV47qU97u8zzoVo9cL5TZ3BmBHXogItSt9qJjR0KUMFRhcCW8uGIGl8nkl7Aw== - has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" @@ -3765,6 +5266,16 @@ headers-polyfill@^4.0.2: resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.3.tgz#922a0155de30ecc1f785bcf04be77844ca95ad07" integrity sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ== +help-me@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" + integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== + +hono@^4.5.9: + version "4.5.9" + resolved "https://registry.yarnpkg.com/hono/-/hono-4.5.9.tgz#2627c55c4c97ae826973dddac857ba4476fde6c6" + integrity sha512-zz8ktqMDRrZETjxBrv8C5PQRFbrTRCLNVAjD1SNQyOzv4VjmX68Uxw83xQ6oxdAB60HiWnGEatiKA8V3SZLDkQ== + hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -3785,20 +5296,20 @@ human-signals@^5.0.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== -husky@9.0.11: - version "9.0.11" - resolved "https://registry.yarnpkg.com/husky/-/husky-9.0.11.tgz#fc91df4c756050de41b3e478b2158b87c1e79af9" - integrity sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw== +husky@9.1.5: + version "9.1.5" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.5.tgz#2b6edede53ee1adbbd3a3da490628a23f5243b83" + integrity sha512-rowAVRUBfI0b4+niA4SJMhfQwc107VLkBUgEYYAOQAbqDCnra1nYh83hF/MDmhYs9t9n1E3DuKOrs2LYNC+0Ag== -identity-function@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/identity-function/-/identity-function-1.0.0.tgz#bea1159f0985239be3ca348edf40ce2f0dd2c21d" - integrity sha512-kNrgUK0qI+9qLTBidsH85HjDLpZfrrS0ElquKKe/fJFdB3D7VeKdXXEvOPDUHSHOzdZKCAAaQIWWyp0l2yq6pw== +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== ignore@^5.1.4, ignore@^5.1.8, ignore@^5.2.0, ignore@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" @@ -3809,9 +5320,9 @@ import-fresh@^3.2.1, import-fresh@^3.3.0: resolve-from "^4.0.0" import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" @@ -3831,11 +5342,6 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -indent-string@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-5.0.0.tgz#4fd2980fccaf8622d14c64d694f4cf33c81951a5" - integrity sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg== - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -3854,7 +5360,7 @@ ini@4.1.1: resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" integrity sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g== -internal-slot@^1.0.7: +internal-slot@^1.0.4, internal-slot@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== @@ -3863,7 +5369,15 @@ internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" -is-array-buffer@^3.0.4: +is-arguments@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-array-buffer@^3.0.2, is-array-buffer@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== @@ -3876,6 +5390,13 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== +is-async-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" + integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== + dependencies: + has-tostringtag "^1.0.0" + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -3908,12 +5429,12 @@ is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== +is-core-module@^2.13.0, is-core-module@^2.13.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" + integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== dependencies: - hasown "^2.0.0" + hasown "^2.0.2" is-data-view@^1.0.1: version "1.0.1" @@ -3922,7 +5443,7 @@ is-data-view@^1.0.1: dependencies: is-typed-array "^1.1.13" -is-date-object@^1.0.1: +is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== @@ -3934,6 +5455,13 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-finalizationregistry@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" + integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== + dependencies: + call-bind "^1.0.2" + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -3956,6 +5484,13 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-generator-function@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -3963,10 +5498,10 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-iterable@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-iterable/-/is-iterable-1.1.1.tgz#71f9aa6f113e1d968ebe1d41cff4c8fb23a817bc" - integrity sha512-EdOZCr0NsGE00Pot+x1ZFx9MJK3C6wy91geZpXwvwexDLJvA4nzYyZf7r+EIwSeVsOLDdBz7ATg9NqKTzuNYuQ== +is-map@^2.0.2, is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== is-negative-zero@^2.0.3: version "2.0.3" @@ -3985,11 +5520,6 @@ is-number-object@^1.0.4: dependencies: has-tostringtag "^1.0.0" -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -4013,6 +5543,11 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-set@^2.0.2, is-set@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== + is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" @@ -4058,6 +5593,11 @@ is-typed-array@^1.1.13: dependencies: which-typed-array "^1.1.14" +is-weakmap@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" + integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== + is-weakref@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -4065,6 +5605,14 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" +is-weakset@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" + integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" + isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" @@ -4075,10 +5623,20 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isexe@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d" + integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ== + +iso-639-1@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/iso-639-1/-/iso-639-1-3.1.2.tgz#86a53dcce056e0d856b17c022eb059eb16a35426" + integrity sha512-Le7BRl3Jt9URvaiEHJCDEdvPZCfhiQoXnFgLAWNRhzFMwRFdWO7/5tLRQbiPzE394I9xd7KdRCM7S6qdOhwG5A== + isomorphic-git@^1.25.6: - version "1.25.10" - resolved "https://registry.yarnpkg.com/isomorphic-git/-/isomorphic-git-1.25.10.tgz#59ff7af88773b126f2b273ef3c536c08308b6d36" - integrity sha512-IxGiaKBwAdcgBXwIcxJU6rHLk+NrzYaaPKXXQffcA0GW3IUrQXdUPDXDo+hkGVcYruuz/7JlGBiuaeTCgIgivQ== + version "1.27.1" + resolved "https://registry.yarnpkg.com/isomorphic-git/-/isomorphic-git-1.27.1.tgz#a2752fce23a09f04baa590c41cfaf61e973405b3" + integrity sha512-X32ph5zIWfT75QAqW2l3JCIqnx9/GWd17bRRehmn3qmWc34OYbSXY6Cxv0o9bIIY+CWugoN4nQFHNA+2uYf2nA== dependencies: async-lock "^1.4.1" clean-git-ref "^2.0.1" @@ -4109,9 +5667,9 @@ istanbul-lib-instrument@^5.0.4: semver "^6.3.0" istanbul-lib-instrument@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz#91655936cf7380e4e473383081e38478b69993b1" - integrity sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw== + version "6.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== dependencies: "@babel/core" "^7.23.9" "@babel/parser" "^7.23.9" @@ -4145,10 +5703,26 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -iterable-lookahead@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/iterable-lookahead/-/iterable-lookahead-1.0.0.tgz#896dfcb78680bdb50036e97edb034c8b68a9737f" - integrity sha512-hJnEP2Xk4+44DDwJqUQGdXal5VbyeWLaPyDl2AQc242Zr7iqz4DgpQOrEzglWVMGHMDCkguLHEKxd1+rOsmgSQ== +iterator.prototype@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" + integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== + dependencies: + define-properties "^1.2.1" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + reflect.getprototypeof "^1.0.4" + set-function-name "^2.0.1" + +jake@^10.8.5: + version "10.9.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f" + integrity sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA== + dependencies: + async "^3.2.3" + chalk "^4.0.2" + filelist "^1.0.4" + minimatch "^3.1.2" jest-changed-files@^29.7.0: version "29.7.0" @@ -4525,17 +6099,17 @@ jest@29.7.0: import-local "^3.0.2" jest-cli "^29.7.0" -jiti@^1.19.1: - version "1.21.0" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" - integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== - -jiti@^1.21.0: +jiti@^1.19.1, jiti@^1.21.6: version "1.21.6" resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== -js-tokens@^4.0.0: +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -4560,6 +6134,11 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" @@ -4590,7 +6169,14 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json5@^2.2.2, json5@^2.2.3: +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + +json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -4600,6 +6186,16 @@ jsonparse@^1.2.0: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5: + version "3.3.5" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a" + integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ== + dependencies: + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + object.assign "^4.1.4" + object.values "^1.1.6" + keyv@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -4612,31 +6208,40 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -knip@5.21.2: - version "5.21.2" - resolved "https://registry.yarnpkg.com/knip/-/knip-5.21.2.tgz#0b25001ee645882784c652cd14c3a3e7ff50ec37" - integrity sha512-V8bzHWjQyhkN0cxajxyHqaD8CPOkNtSwo4+Zue3z//4fbWO79xXLVp61fuaaTcT9O7I7E2ZjuHENtRkBrjSzCg== +knip@5.27.4: + version "5.27.4" + resolved "https://registry.yarnpkg.com/knip/-/knip-5.27.4.tgz#37442bacd88520ef1af2c2429e0e5d1be127ee68" + integrity sha512-7t1yqIKxaVGYD1cLI4raVLWi9cNqv+JNbngc8mgvTVJbomnxOg1pjxgCGEztB7eVgD+6VEwf7Jg5WHXzk+Kbpw== dependencies: - "@ericcornelissen/bash-parser" "0.5.3" - "@nodelib/fs.walk" "2.0.0" + "@nodelib/fs.walk" "1.2.8" "@snyk/github-codeowners" "1.1.0" easy-table "1.2.0" + enhanced-resolve "^5.17.1" fast-glob "^3.3.2" - file-entry-cache "8.0.0" - jiti "^1.21.0" + jiti "^1.21.6" js-yaml "^4.1.0" minimist "^1.2.8" picocolors "^1.0.0" picomatch "^4.0.1" pretty-ms "^9.0.0" - resolve "^1.22.8" smol-toml "^1.1.4" strip-json-comments "5.0.1" summary "2.1.0" - tsconfig-paths "^4.2.0" zod "^3.22.4" zod-validation-error "^3.0.3" +language-subtag-registry@^0.3.20: + version "0.3.23" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" + integrity sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ== + +language-tags@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777" + integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA== + dependencies: + language-subtag-registry "^0.3.20" + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -4650,42 +6255,42 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lilconfig@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.1.tgz#9d8a246fa753106cfc205fd2d77042faca56e5e3" - integrity sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ== +lilconfig@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" + integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -lint-staged@15.2.7: - version "15.2.7" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.2.7.tgz#97867e29ed632820c0fb90be06cd9ed384025649" - integrity sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw== +lint-staged@15.2.9: + version "15.2.9" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.2.9.tgz#bf70d40b6b192df6ad756fb89822211615e0f4da" + integrity sha512-BZAt8Lk3sEnxw7tfxM7jeZlPRuT4M68O0/CwZhhaw6eeWu0Lz5eERE3m386InivXB64fp/mDID452h48tvKlRQ== dependencies: chalk "~5.3.0" commander "~12.1.0" - debug "~4.3.4" + debug "~4.3.6" execa "~8.0.1" - lilconfig "~3.1.1" - listr2 "~8.2.1" + lilconfig "~3.1.2" + listr2 "~8.2.4" micromatch "~4.0.7" pidtree "~0.6.0" string-argv "~0.3.2" - yaml "~2.4.2" + yaml "~2.5.0" -listr2@~8.2.1: - version "8.2.1" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.2.1.tgz#06a1a6efe85f23c5324180d7c1ddbd96b5eefd6d" - integrity sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g== +listr2@~8.2.4: + version "8.2.4" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.2.4.tgz#486b51cbdb41889108cb7e2c90eeb44519f5a77f" + integrity sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g== dependencies: cli-truncate "^4.0.0" colorette "^2.0.20" eventemitter3 "^5.0.1" - log-update "^6.0.0" - rfdc "^1.3.1" + log-update "^6.1.0" + rfdc "^1.4.1" wrap-ansi "^9.0.0" load-json-file@^4.0.0: @@ -4724,10 +6329,10 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== -lodash.curry@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170" - integrity sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA== +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== lodash.isplainobject@^4.0.6: version "4.0.6" @@ -4739,7 +6344,7 @@ lodash.kebabcase@^4.1.1: resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" integrity sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g== -lodash.memoize@4.x: +lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== @@ -4779,17 +6384,24 @@ lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-update@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.0.0.tgz#0ddeb7ac6ad658c944c1de902993fce7c33f5e59" - integrity sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw== +log-update@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.1.0.tgz#1a04ff38166f94647ae1af562f4bd6a15b1b7cd4" + integrity sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w== dependencies: - ansi-escapes "^6.2.0" - cli-cursor "^4.0.0" - slice-ansi "^7.0.0" + ansi-escapes "^7.0.0" + cli-cursor "^5.0.0" + slice-ansi "^7.1.0" strip-ansi "^7.1.0" wrap-ansi "^9.0.0" +loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -4797,12 +6409,12 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -magic-string@^0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.16.0.tgz#970ebb0da7193301285fb1aa650f39bdd81eb45a" - integrity sha512-c4BEos3y6G2qO0B9X7K0FVLOPT9uGrjYwYRLFmDqyl5YMboUviyecnXWp94fJTSMwPw2/sf+CEYt5AGpmklkkQ== +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: - vlq "^0.2.1" + yallist "^4.0.0" magic-string@^0.25.3: version "0.25.9" @@ -4818,7 +6430,7 @@ make-dir@^4.0.0: dependencies: semver "^7.5.3" -make-error@1.x: +make-error@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -4830,10 +6442,10 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" -map-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" - integrity sha512-TzQSV2DiMYgoF5RycneKVUzIa9bQsj/B3tTgsE3dOGqlzHnGIDaC7XBE7grnA+8kZPnfqSGFe95VHc2oc0VFUQ== +map-stream@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" + integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g== md5@^2.3.0: version "2.3.0" @@ -4865,9 +6477,9 @@ merge2@^1.3.0, merge2@^1.4.1: integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.7, micromatch@~4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: braces "^3.0.3" picomatch "^2.3.1" @@ -4887,15 +6499,20 @@ mimic-fn@^4.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== +mimic-function@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mimic-function/-/mimic-function-5.0.1.tgz#acbe2b3349f99b9deaca7fb70e48b83e94e67076" + integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== + mimic-response@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== -miniflare@3.20240610.0: - version "3.20240610.0" - resolved "https://registry.yarnpkg.com/miniflare/-/miniflare-3.20240610.0.tgz#6efeb60f3ba2e658a3e0395538010228fac0e719" - integrity sha512-J6aXmkII5gcq+kC4TurxKiR4rC++apPST/K8P/YjqoQQgrJ+NRPacBhf6iVh8R3ujnXYXaq+Ae+gm+LM0XHK/w== +miniflare@3.20240821.0: + version "3.20240821.0" + resolved "https://registry.yarnpkg.com/miniflare/-/miniflare-3.20240821.0.tgz#d4fc648ca20c033c4143a8d0ef061dedccad7c2d" + integrity sha512-4BhLGpssQxM/O6TZmJ10GkT3wBJK6emFkZ3V87/HyvQmVt8zMxEBvyw5uv6kdtp+7F54Nw6IKFJjPUL8rFVQrQ== dependencies: "@cspotcode/source-map-support" "0.8.1" acorn "^8.8.0" @@ -4904,27 +6521,34 @@ miniflare@3.20240610.0: exit-hook "^2.2.1" glob-to-regexp "^0.4.1" stoppable "^1.1.0" - undici "^5.28.2" - workerd "1.20240610.1" - ws "^8.11.0" + undici "^5.28.4" + workerd "1.20240821.1" + ws "^8.17.1" youch "^3.2.2" - zod "^3.20.6" + zod "^3.22.3" -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimatch@^9.0.4: - version "9.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== +minimatch@^5.0.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.3, minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== dependencies: brace-expansion "^2.0.1" -minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8: +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -4946,15 +6570,20 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + msw@^2.0.8: - version "2.3.1" - resolved "https://registry.yarnpkg.com/msw/-/msw-2.3.1.tgz#bfc73e256ffc2c74ec4381b604abb258df35f32b" - integrity sha512-ocgvBCLn/5l3jpl1lssIb3cniuACJLoOfZu01e3n5dbJrpA5PeeWn28jCLgQDNt6d7QT8tF2fYRzm9JoEHtiig== + version "2.3.5" + resolved "https://registry.yarnpkg.com/msw/-/msw-2.3.5.tgz#424ad91b20a548d6b77fc26aca0c789e5cbc4764" + integrity sha512-+GUI4gX5YC5Bv33epBrD+BGdmDvBg2XGruiWnI3GbIbRmMMBeZ5gs3mJ51OWSGHgJKztZ8AtZeYMMNMVrje2/Q== dependencies: "@bundled-es-modules/cookie" "^2.0.0" "@bundled-es-modules/statuses" "^1.0.1" + "@bundled-es-modules/tough-cookie" "^0.1.6" "@inquirer/confirm" "^3.0.0" - "@mswjs/cookies" "^1.1.0" "@mswjs/interceptors" "^0.29.0" "@open-draft/until" "^2.1.0" "@types/cookie" "^0.6.0" @@ -4994,11 +6623,23 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-cleanup@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/node-cleanup/-/node-cleanup-2.1.2.tgz#7ac19abd297e09a7f72a71545d951b517e4dde2c" + integrity sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw== + node-fetch-native@^1.6.4: version "1.6.4" resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.4.tgz#679fc8fd8111266d47d7e72c379f1bed9acff06e" integrity sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ== +node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -5009,10 +6650,10 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== normalize-package-data@^2.3.2: version "2.5.0" @@ -5058,27 +6699,30 @@ npm-run-path@^5.1.0: dependencies: path-key "^4.0.0" +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== + +object-is@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-pairs@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-pairs/-/object-pairs-0.1.0.tgz#8276eed81d60b8549d69c5f73a682ab9da4ff32f" - integrity sha512-3ECr6K831I4xX/Mduxr9UC+HPOz/d6WKKYj9p4cmC8Lg8p7g8gitzsxNX5IWlSIgFWN/a4JgrJaoAMKn20oKwA== - -object-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/object-values/-/object-values-1.0.0.tgz#72af839630119e5b98c3b02bb8c27e3237158105" - integrity sha512-+8hwcz/JnQ9EpLIXzN0Rs7DLsBpJNT/xYehtB/jU93tHYr5BFEO8E+JGQNOSqE7opVzz5cGksKFHt7uUJVLSjQ== - -object.assign@^4.1.5: +object.assign@^4.1.4, object.assign@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== @@ -5088,6 +6732,48 @@ object.assign@^4.1.5: has-symbols "^1.0.3" object-keys "^1.1.1" +object.entries@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" + integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +object.fromentries@^2.0.7, object.fromentries@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" + integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + +object.groupby@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" + integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + +object.values@^1.1.6, object.values@^1.1.7, object.values@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" + integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -5095,7 +6781,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0, onetime@^5.1.2: +onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -5109,6 +6795,13 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" +onetime@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-7.0.0.tgz#9f16c92d8c9ef5120e3acd9dd9957cceecc1ab60" + integrity sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ== + dependencies: + mimic-function "^5.0.0" + optionator@^0.9.3: version "0.9.4" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" @@ -5122,9 +6815,9 @@ optionator@^0.9.3: word-wrap "^1.2.5" outvariant@^1.2.1, outvariant@^1.4.0, outvariant@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.2.tgz#f54f19240eeb7f15b28263d5147405752d8e2066" - integrity sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ== + version "1.4.3" + resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.3.tgz#221c1bfc093e8fec7075497e7799fdbf43d14873" + integrity sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA== p-limit@^2.2.0: version "2.3.0" @@ -5279,6 +6972,13 @@ pathe@^1.1.2: resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== +pause-stream@0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" + integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A== + dependencies: + through "~2.3" + picocolors@^1.0.0, picocolors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" @@ -5314,6 +7014,56 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== +pino-abstract-transport@^1.0.0, pino-abstract-transport@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz#97f9f2631931e242da531b5c66d3079c12c9d1b5" + integrity sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q== + dependencies: + readable-stream "^4.0.0" + split2 "^4.0.0" + +pino-pretty@11.2.2: + version "11.2.2" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-11.2.2.tgz#5e8ec69b31e90eb187715af07b1d29a544e60d39" + integrity sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A== + dependencies: + colorette "^2.0.7" + dateformat "^4.6.3" + fast-copy "^3.0.2" + fast-safe-stringify "^2.1.1" + help-me "^5.0.0" + joycon "^3.1.1" + minimist "^1.2.6" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^1.0.0" + pump "^3.0.0" + readable-stream "^4.0.0" + secure-json-parse "^2.4.0" + sonic-boom "^4.0.1" + strip-json-comments "^3.1.1" + +pino-std-serializers@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b" + integrity sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA== + +pino@9.3.2: + version "9.3.2" + resolved "https://registry.yarnpkg.com/pino/-/pino-9.3.2.tgz#a530d6d28f1d954b6f54416a218cbb616f52f901" + integrity sha512-WtARBjgZ7LNEkrGWxMBN/jvlFiE17LTbBoH0konmBU684Kd0uIiDwBXlcTCW7iJnA6HfIKwUssS/2AC6cDEanw== + dependencies: + atomic-sleep "^1.0.0" + fast-redact "^3.1.1" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^1.2.0" + pino-std-serializers "^7.0.0" + process-warning "^4.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.2.0" + safe-stable-stringify "^2.3.1" + sonic-boom "^4.0.1" + thread-stream "^3.0.0" + pirates@^4.0.4: version "4.0.6" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" @@ -5348,10 +7098,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a" - integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA== +prettier@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.3.tgz#30c54fe0be0d8d12e6ae61dbb10109ea00d53105" + integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew== pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" @@ -5363,9 +7113,9 @@ pretty-format@^29.0.0, pretty-format@^29.7.0: react-is "^18.0.0" pretty-ms@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-9.0.0.tgz#53c57f81171c53be7ce3fd20bdd4265422bc5929" - integrity sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng== + version "9.1.0" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-9.1.0.tgz#0ad44de6086454f48a168e5abb3c26f8db1b3253" + integrity sha512-o1piW0n3tgKIKCwk2vpM/vOV13zjJzvP37Ioze54YlTHE06m4tjEbzg9WsKkvTuyYln2DHjo5pY4qrZGI0otpw== dependencies: parse-ms "^4.0.0" @@ -5374,6 +7124,16 @@ printable-characters@^1.0.42: resolved "https://registry.yarnpkg.com/printable-characters/-/printable-characters-1.0.42.tgz#3f18e977a9bd8eb37fcc4ff5659d7be90868b3d8" integrity sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ== +process-warning@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-4.0.0.tgz#581e3a7a1fb456c5f4fd239f76bce75897682d5a" + integrity sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -5382,7 +7142,36 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -punycode@^2.1.0: +prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +ps-tree@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" + integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA== + dependencies: + event-stream "=3.3.4" + +psl@^1.1.33: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^2.1.0, punycode@^2.1.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -5392,11 +7181,26 @@ pure-rand@^6.0.0: resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + +react-is@^16.13.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + react-is@^18.0.0: version "18.3.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" @@ -5420,6 +7224,17 @@ readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^4.0.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09" + integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -5427,12 +7242,64 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +real-require@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== + +refa@^0.12.0, refa@^0.12.1: + version "0.12.1" + resolved "https://registry.yarnpkg.com/refa/-/refa-0.12.1.tgz#dac13c4782dc22b6bae6cce81a2b863888ea39c6" + integrity sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g== + dependencies: + "@eslint-community/regexpp" "^4.8.0" + +reflect.getprototypeof@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" + integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.1" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + globalthis "^1.0.3" + which-builtin-type "^1.1.3" + +regenerate-unicode-properties@^10.1.0: + version "10.1.1" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" + integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + regenerator-runtime@^0.14.0: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== -regexp.prototype.flags@^1.5.2: +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== + dependencies: + "@babel/runtime" "^7.8.4" + +regexp-ast-analysis@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/regexp-ast-analysis/-/regexp-ast-analysis-0.7.1.tgz#c0e24cb2a90f6eadd4cbaaba129317e29d29c482" + integrity sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A== + dependencies: + "@eslint-community/regexpp" "^4.8.0" + refa "^0.12.1" + +regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== @@ -5442,6 +7309,25 @@ regexp.prototype.flags@^1.5.2: es-errors "^1.3.0" set-function-name "^2.0.1" +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== + dependencies: + "@babel/regjsgen" "^0.8.0" + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + +regjsparser@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" + integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== + dependencies: + jsesc "~0.5.0" + repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" @@ -5457,6 +7343,11 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -5484,7 +7375,7 @@ resolve.exports@^2.0.0, resolve.exports@^2.0.2: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== -resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.8: +resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.4, resolve@^1.22.8: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -5493,28 +7384,32 @@ resolve@^1.10.0, resolve@^1.20.0, resolve@^1.22.8: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -restore-cursor@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" - integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg== +resolve@^2.0.0-next.5: + version "2.0.0-next.5" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +restore-cursor@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-5.1.0.tgz#0766d95699efacb14150993f55baf0953ea1ebe7" + integrity sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA== + dependencies: + onetime "^7.0.0" + signal-exit "^4.1.0" reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -reverse-arguments@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/reverse-arguments/-/reverse-arguments-1.0.0.tgz#c28095a3a921ac715d61834ddece9027992667cd" - integrity sha512-/x8uIPdTafBqakK0TmPNJzgkLP+3H+yxpUJhCQHsLBg1rYEVNR2D8BRYNWQhVBjyOd7oo1dZRVzIkwMY2oqfYQ== - -rfdc@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f" - integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg== +rfdc@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== rollup-plugin-inject@^3.0.0: version "3.0.2" @@ -5539,7 +7434,7 @@ rollup-pluginutils@^2.8.1: dependencies: estree-walker "^0.6.1" -run-parallel@^1.1.9, run-parallel@^1.2.0: +run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== @@ -5570,6 +7465,25 @@ safe-regex-test@^1.0.3: es-errors "^1.3.0" is-regex "^1.1.4" +safe-stable-stringify@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + +scslre@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/scslre/-/scslre-0.3.0.tgz#c3211e9bfc5547fc86b1eabaa34ed1a657060155" + integrity sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ== + dependencies: + "@eslint-community/regexpp" "^4.8.0" + refa "^0.12.0" + regexp-ast-analysis "^0.7.0" + +secure-json-parse@^2.4.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" + integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== + selfsigned@^2.0.1: version "2.4.1" resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" @@ -5583,15 +7497,22 @@ selfsigned@^2.0.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== +semver@7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== +semver@^7.3.6, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== set-function-length@^1.2.1: version "1.2.2" @@ -5605,7 +7526,7 @@ set-function-length@^1.2.1: gopd "^1.0.1" has-property-descriptors "^1.0.2" -set-function-name@^2.0.1: +set-function-name@^2.0.1, set-function-name@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== @@ -5647,17 +7568,12 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote-word@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/shell-quote-word/-/shell-quote-word-1.0.1.tgz#e2bdfd22d599fd68886491677e38f560f9d469c9" - integrity sha512-lT297f1WLAdq0A4O+AknIFRP6kkiI3s8C913eJ0XqBxJbZPGWUNkRQk2u8zk4bEAjUJ5i+fSLwB6z1HzeT+DEg== - shell-quote@^1.6.1: version "1.8.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== -side-channel@^1.0.4: +side-channel@^1.0.4, side-channel@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== @@ -5667,7 +7583,7 @@ side-channel@^1.0.4: get-intrinsic "^1.2.4" object-inspect "^1.13.1" -signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: +signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -5709,7 +7625,7 @@ slice-ansi@^5.0.0: ansi-styles "^6.0.0" is-fullwidth-code-point "^4.0.0" -slice-ansi@^7.0.0: +slice-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.0.tgz#cd6b4655e298a8d1bdeb04250a433094b347b9a9" integrity sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg== @@ -5717,10 +7633,26 @@ slice-ansi@^7.0.0: ansi-styles "^6.2.1" is-fullwidth-code-point "^5.0.0" +smee-client@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/smee-client/-/smee-client-2.0.3.tgz#de57d90a2531af136e0f0496a88599376ad53fa8" + integrity sha512-W5tQKHzZFe+IMBlaAJ8Ho32Y2wbUbzriHAA2DAFXpITId+0dYHJJbAX36a/HMrGjW7yFjhcKCNPwRBAiIrlZGQ== + dependencies: + commander "^12.0.0" + eventsource "^2.0.2" + validator "^13.11.0" + smol-toml@^1.1.4: - version "1.2.1" - resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.2.1.tgz#6216334548763d4aac76cafff19f8914937ee13a" - integrity sha512-OtZKrVrGIT+m++lxyF0z5n68nkwdgZotPhy89bfA4T7nSWe0xeQtfbjM1z5VLTilJdWXH46g8i0oAcpQNkzZTg== + version "1.3.0" + resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.3.0.tgz#5200e251fffadbb72570c84e9776d2a3eca48143" + integrity sha512-tWpi2TsODPScmi48b/OQZGi2lgUmBCHy6SZrhi/FdnnHiU1GwebbCfuQuxsC3nHaLwtYeJGPrDZDIeodDOc4pA== + +sonic-boom@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.0.1.tgz#515b7cef2c9290cb362c4536388ddeece07aed30" + integrity sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ== + dependencies: + atomic-sleep "^1.0.0" source-map-support@0.5.13: version "0.5.13" @@ -5730,7 +7662,7 @@ source-map-support@0.5.13: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1: +source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -5762,15 +7694,22 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.18" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" - integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== + version "3.0.20" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz#e44ed19ed318dd1e5888f93325cee800f0f51b89" + integrity sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw== split2@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== +split@0.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" + integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA== + dependencies: + through "2" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -5796,17 +7735,31 @@ statuses@^2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +stop-iteration-iterator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" + integrity sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ== + dependencies: + internal-slot "^1.0.4" + stoppable@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/stoppable/-/stoppable-1.1.0.tgz#32da568e83ea488b08e4d7ea2c3bcc9d75015d5b" integrity sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw== +stream-combiner@~0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" + integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw== + dependencies: + duplexer "~0.1.1" + strict-event-emitter@^0.5.0, strict-event-emitter@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== -string-argv@~0.3.2: +string-argv@^0.3.1, string-argv@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== @@ -5829,18 +7782,39 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: strip-ansi "^6.0.1" string-width@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.1.0.tgz#d994252935224729ea3719c49f7206dc9c46550a" - integrity sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw== + version "7.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" + integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== dependencies: emoji-regex "^10.3.0" get-east-asian-width "^1.0.0" strip-ansi "^7.1.0" -string.fromcodepoint@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/string.fromcodepoint/-/string.fromcodepoint-0.2.1.tgz#8d978333c0bc92538f50f383e4888f3e5619d653" - integrity sha512-n69H31OnxSGSZyZbgBlvYIXlrMhJQ0dQAX1js1QDhpaUH6zmU3QYlj07bCwCNlPOu3oRXIubGPl2gDGnHsiCqg== +string.prototype.includes@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz#8986d57aee66d5460c144620a6d873778ad7289f" + integrity sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.matchall@^4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" + integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.7" + regexp.prototype.flags "^1.5.2" + set-function-name "^2.0.2" + side-channel "^1.0.6" string.prototype.padend@^3.0.0: version "3.1.6" @@ -5852,6 +7826,14 @@ string.prototype.padend@^3.0.0: es-abstract "^1.23.2" es-object-atoms "^1.0.0" +string.prototype.repeat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz#e90872ee0308b29435aa26275f6e1b762daee01a" + integrity sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.trim@^1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" @@ -5880,7 +7862,7 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -string_decoder@^1.1.1: +string_decoder@^1.1.1, string_decoder@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -5962,14 +7944,19 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -synckit@^0.8.6: - version "0.8.8" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7" - integrity sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ== +synckit@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.1.tgz#febbfbb6649979450131f64735aa3f6c14575c88" + integrity sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A== dependencies: "@pkgr/core" "^0.1.0" tslib "^2.6.2" +tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -5989,7 +7976,14 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -"through@>=2.2.7 <3": +thread-stream@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1" + integrity sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A== + dependencies: + real-require "^0.2.0" + +through@2, "through@>=2.2.7 <3", through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== @@ -6004,18 +7998,6 @@ to-fast-properties@^2.0.0: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== -to-no-case@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/to-no-case/-/to-no-case-1.0.2.tgz#c722907164ef6b178132c8e69930212d1b4aa16a" - integrity sha512-Z3g735FxuZY8rodxV4gH7LxClE4H0hTIyHNIHdk+vpQxjLm0cwnKXq/OFVZ76SOQmto7txVcwSCwkU5kqp+FKg== - -to-pascal-case@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-pascal-case/-/to-pascal-case-1.0.0.tgz#0bbdc8df448886ba01535e543327048d0aa1ce78" - integrity sha512-QGMWHqM6xPrcQW57S23c5/3BbYb0Tbe9p+ur98ckRnGDwD4wbbtDiYI38CfmMKNB5Iv0REjs5SNDntTwvDxzZA== - dependencies: - to-space-case "^1.0.0" - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -6023,52 +8005,72 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -to-space-case@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-space-case/-/to-space-case-1.0.0.tgz#b052daafb1b2b29dc770cea0163e5ec0ebc9fc17" - integrity sha512-rLdvwXZ39VOn1IxGL3V6ZstoTbwLRckQmn/U8ZDLuWwIXNpuZDhQ3AiRUlhTbOXFVE9C+dR51wM0CBDhk31VcA== +tough-cookie@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== dependencies: - to-no-case "^1.0.0" + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== -ts-jest@29.1.5: - version "29.1.5" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.5.tgz#d6c0471cc78bffa2cb4664a0a6741ef36cfe8f69" - integrity sha512-UuClSYxM7byvvYfyWdFI+/2UxMmwNyJb0NPkZPQE2hew3RurV7l7zURgOHAd/1I1ZdPpe3GUsXNXAcN8TFKSIg== +ts-jest@29.2.5: + version "29.2.5" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.2.5.tgz#591a3c108e1f5ebd013d3152142cb5472b399d63" + integrity sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA== dependencies: - bs-logger "0.x" - fast-json-stable-stringify "2.x" + bs-logger "^0.2.6" + ejs "^3.1.10" + fast-json-stable-stringify "^2.1.0" jest-util "^29.0.0" json5 "^2.2.3" - lodash.memoize "4.x" - make-error "1.x" - semver "^7.5.3" - yargs-parser "^21.0.1" + lodash.memoize "^4.1.2" + make-error "^1.3.6" + semver "^7.6.3" + yargs-parser "^21.1.1" -tsconfig-paths@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" - integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== +tsc-watch@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/tsc-watch/-/tsc-watch-6.2.0.tgz#4b191c36c6ed24c2bf6e721013af0825cd73d217" + integrity sha512-2LBhf9kjKXnz7KQ/puLHlozMzzUNHAdYBNMkg3eksQJ9GBAgMg8czznM83T5PmsoUvDnXzfIeQn2lNcIYDr8LA== + dependencies: + cross-spawn "^7.0.3" + node-cleanup "^2.1.2" + ps-tree "^1.2.0" + string-argv "^0.3.1" + +tsconfig-paths@^3.15.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== dependencies: - json5 "^2.2.2" + "@types/json5" "^0.0.29" + json5 "^1.0.2" minimist "^1.2.6" strip-bom "^3.0.0" tslib@^2.2.0, tslib@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== -tsx@4.15.6: - version "4.15.6" - resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.15.6.tgz#4522ed093f7fa54f031a7a999274e8b35dbf3165" - integrity sha512-is0VQQlfNZRHEuSSTKA6m4xw74IU4AizmuB6lAYLRt9XtuyeQnyJYexhNZOPCB59SqC4JzmSzPnHGBXxf3k0hA== +tsx@4.18.0: + version "4.18.0" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.18.0.tgz#c5c6e8af9e7d162446ed22dc7b53dc4792bf920b" + integrity sha512-a1jaKBSVQkd6yEc1/NI7G6yHFfefIcuf3QJST7ZEyn4oQnxLYrZR5uZAM8UrwUa3Ge8suiZHcNS1gNrEvmobqg== dependencies: - esbuild "~0.21.4" + esbuild "~0.23.0" get-tsconfig "^4.7.5" optionalDependencies: fsevents "~2.3.3" @@ -6096,9 +8098,9 @@ type-fest@^0.21.3: integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== type-fest@^4.9.0: - version "4.18.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.18.3.tgz#5249f96e7c2c3f0f1561625f54050e343f1c8f68" - integrity sha512-Q08/0IrpvM+NMY9PA2rti9Jb+JejTddwmwmVQGskAlhtcrw1wsRzoR6ode6mR+OAabNa75w/dxedSUY2mlphaQ== + version "4.25.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.25.0.tgz#b190374f969631866889bbdb01ece17ca424ee60" + integrity sha512-bRkIGlXsnGBRBQRAY56UXBm//9qH4bmJfFvq83gSz41N282df+fjy8ofcEgc1sM8geNt5cl6mC2g9Fht1cs8Aw== typebox-validators@0.3.5: version "0.3.5" @@ -6149,24 +8151,29 @@ typed-array-length@^1.0.6: is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" -typescript-eslint@7.13.1: - version "7.13.1" - resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-7.13.1.tgz#8bbcc4b59b6bb0c457505ee17a356b1868c3fcd5" - integrity sha512-pvLEuRs8iS9s3Cnp/Wt//hpK8nKc8hVa3cLljHqzaJJQYP8oys8GUyIFqtlev+2lT/fqMPcyQko+HJ6iYK3nFA== +typescript-eslint@8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.3.0.tgz#f4d9c5ba71f6bead03ec41ecb2bece1de511e49f" + integrity sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA== dependencies: - "@typescript-eslint/eslint-plugin" "7.13.1" - "@typescript-eslint/parser" "7.13.1" - "@typescript-eslint/utils" "7.13.1" + "@typescript-eslint/eslint-plugin" "8.3.0" + "@typescript-eslint/parser" "8.3.0" + "@typescript-eslint/utils" "8.3.0" -typescript@5.4.5: - version "5.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== +typescript@5.4.3: + version "5.4.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" + integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== + +typescript@5.5.4: + version "5.5.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" + integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== ufo@^1.5.3: - version "1.5.3" - resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.3.tgz#3325bd3c977b6c6cd3160bf4ff52989adc9d3344" - integrity sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw== + version "1.5.4" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.4.tgz#16d6949674ca0c9e0fbbae1fa20a71d7b1ded754" + integrity sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ== unbox-primitive@^1.0.2: version "1.0.2" @@ -6178,12 +8185,12 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== -undici@^5.25.4, undici@^5.28.2: +undici@^5.25.4, undici@^5.28.4: version "5.28.4" resolved "https://registry.yarnpkg.com/undici/-/undici-5.28.4.tgz#6b280408edb6a1a604a9b20340f45b422e373068" integrity sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g== @@ -6202,12 +8209,28 @@ undici@^5.25.4, undici@^5.28.2: pathe "^1.1.2" ufo "^1.5.3" -unescape-js@^1.0.5: - version "1.1.4" - resolved "https://registry.yarnpkg.com/unescape-js/-/unescape-js-1.1.4.tgz#4bc6389c499cb055a98364a0b3094e1c3d5da395" - integrity sha512-42SD8NOQEhdYntEiUQdYq/1V/YHwr1HLwlHuTJB5InVVdOSbgI6xu8jK5q65yIzuFCfczzyDF/7hbGzVbyCw0g== +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== dependencies: - string.fromcodepoint "^0.2.1" + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== unicorn-magic@^0.1.0: version "0.1.0" @@ -6219,21 +8242,39 @@ universal-user-agent@^6.0.0: resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.1.tgz#15f20f55da3c930c57bddbf1734c6654d5fd35aa" integrity sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ== -update-browserslist-db@^1.0.13: - version "1.0.16" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" - integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== +universal-user-agent@^7.0.0, universal-user-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-7.0.2.tgz#52e7d0e9b3dc4df06cc33cb2b9fd79041a54827e" + integrity sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q== + +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + +update-browserslist-db@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== dependencies: escalade "^3.1.2" picocolors "^1.0.1" -uri-js@^4.2.2, uri-js@^4.4.1: +uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -6245,14 +8286,19 @@ uuid@^8.3.1, uuid@^8.3.2: integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== v8-to-istanbul@^9.0.1: - version "9.2.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" - integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== + version "9.3.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" + integrity sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA== dependencies: "@jridgewell/trace-mapping" "^0.3.12" "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^2.0.0" +valibot@0.39.0: + version "0.39.0" + resolved "https://registry.yarnpkg.com/valibot/-/valibot-0.39.0.tgz#b6c42566fa362ca406339d8b24e4e3051ae4bc86" + integrity sha512-d+vE8SDRNy9zKg6No5MHz2tdz8H6CW8X3OdqYdmlhnoqQmEoM6Hu0hJUrZv3tPSVrzZkIIMCtdCQtMzcM6NCWw== + validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -6261,21 +8307,34 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -vlq@^0.2.1: - version "0.2.3" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" - integrity sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow== +validator@^13.11.0: + version "13.12.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.12.0.tgz#7d78e76ba85504da3fee4fd1922b385914d4b35f" + integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg== -vscode-languageserver-textdocument@^1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz#0822a000e7d4dc083312580d7575fe9e3ba2e2bf" - integrity sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA== +vscode-languageserver-textdocument@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz#457ee04271ab38998a093c68c2342f53f6e4a631" + integrity sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA== vscode-uri@^3.0.8: version "3.0.8" resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f" integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw== +vue-eslint-parser@9.4.3: + version "9.4.3" + resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz#9b04b22c71401f1e8bca9be7c3e3416a4bde76a8" + integrity sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg== + dependencies: + debug "^4.3.4" + eslint-scope "^7.1.1" + eslint-visitor-keys "^3.3.0" + espree "^9.3.1" + esquery "^1.4.0" + lodash "^4.17.21" + semver "^7.3.6" + walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -6290,6 +8349,19 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -6301,7 +8373,35 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-typed-array@^1.1.14, which-typed-array@^1.1.15: +which-builtin-type@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.4.tgz#592796260602fc3514a1b5ee7fa29319b72380c3" + integrity sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w== + dependencies: + function.prototype.name "^1.1.6" + has-tostringtag "^1.0.2" + is-async-function "^2.0.0" + is-date-object "^1.0.5" + is-finalizationregistry "^1.0.2" + is-generator-function "^1.0.10" + is-regex "^1.1.4" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.2" + which-typed-array "^1.1.15" + +which-collection@^1.0.1, which-collection@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== + dependencies: + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" + +which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15: version "1.1.15" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== @@ -6326,41 +8426,51 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +which@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/which/-/which-4.0.0.tgz#cd60b5e74503a3fbcfbf6cd6b4138a8bae644c1a" + integrity sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg== + dependencies: + isexe "^3.1.1" + word-wrap@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -workerd@1.20240610.1: - version "1.20240610.1" - resolved "https://registry.yarnpkg.com/workerd/-/workerd-1.20240610.1.tgz#a73718a0f2daff39b2c03e0be143ad007d13c60e" - integrity sha512-Rtut5GrsODQMh6YU43b9WZ980Wd05Ov1/ds88pT/SoetmXFBvkBzdRfiHiATv+azmGX8KveE0i/Eqzk/yI01ug== +workerd@1.20240821.1: + version "1.20240821.1" + resolved "https://registry.yarnpkg.com/workerd/-/workerd-1.20240821.1.tgz#783115daabb3f5e51e3833117ac83548f6fd79f9" + integrity sha512-y4phjCnEG96u8ZkgkkHB+gSw0i6uMNo23rBmixylWpjxDklB+LWD8dztasvsu7xGaZbLoTxQESdEw956F7VJDA== optionalDependencies: - "@cloudflare/workerd-darwin-64" "1.20240610.1" - "@cloudflare/workerd-darwin-arm64" "1.20240610.1" - "@cloudflare/workerd-linux-64" "1.20240610.1" - "@cloudflare/workerd-linux-arm64" "1.20240610.1" - "@cloudflare/workerd-windows-64" "1.20240610.1" - -wrangler@3.60.3: - version "3.60.3" - resolved "https://registry.yarnpkg.com/wrangler/-/wrangler-3.60.3.tgz#1b2ebd2214e10e42a143e47b425480cbe7b7be21" - integrity sha512-a6zn/KFnYaYp3nxJR/aP0TeaBvJDkrrfI89KoxUtx28H7zpya/5/VLu3CxQ3PRspEojJGF0s6f3/pddRy3F+BQ== - dependencies: - "@cloudflare/kv-asset-handler" "0.3.2" + "@cloudflare/workerd-darwin-64" "1.20240821.1" + "@cloudflare/workerd-darwin-arm64" "1.20240821.1" + "@cloudflare/workerd-linux-64" "1.20240821.1" + "@cloudflare/workerd-linux-arm64" "1.20240821.1" + "@cloudflare/workerd-windows-64" "1.20240821.1" + +wrangler@3.72.2: + version "3.72.2" + resolved "https://registry.yarnpkg.com/wrangler/-/wrangler-3.72.2.tgz#606224878a25f383422010b3bfac1494aa78c798" + integrity sha512-7nxkJ4md+KtESNJ/0DwTM7bHZP+uNRpJT5gMDT9WllP9UVzYdtXCTF+p4CHtxIReUpe6pOi7tb05hK9/Q6WaiA== + dependencies: + "@cloudflare/kv-asset-handler" "0.3.4" + "@cloudflare/workers-shared" "0.3.0" "@esbuild-plugins/node-globals-polyfill" "^0.2.3" "@esbuild-plugins/node-modules-polyfill" "^0.2.2" blake3-wasm "^2.1.5" chokidar "^3.5.3" + date-fns "^3.6.0" esbuild "0.17.19" - miniflare "3.20240610.0" + miniflare "3.20240821.0" nanoid "^3.3.3" path-to-regexp "^6.2.0" resolve "^1.22.8" resolve.exports "^2.0.2" selfsigned "^2.0.1" - source-map "0.6.1" + source-map "^0.6.1" unenv "npm:unenv-nightly@1.10.0-1717606461.a117952" + workerd "1.20240821.1" xxhash-wasm "^1.0.1" optionalDependencies: fsevents "~2.3.2" @@ -6405,10 +8515,10 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" -ws@^8.11.0: - version "8.17.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.0.tgz#d145d18eca2ed25aaf791a183903f7be5e295fea" - integrity sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow== +ws@^8.17.1: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== xdg-basedir@^5.1.0: version "5.1.0" @@ -6435,17 +8545,17 @@ yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yaml@^2.4.5: - version "2.4.5" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.5.tgz#60630b206dd6d84df97003d33fc1ddf6296cca5e" - integrity sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@~2.4.2: - version "2.4.3" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.3.tgz#0777516b8c7880bcaa0f426a5410e8d6b0be1f3d" - integrity sha512-sntgmxj8o7DE7g/Qi60cqpLBA3HG3STcDA0kO+WfB05jEKhZMbY7umNm2rBpQvsmZ16/lPXCJGW2672dgOUkrg== +yaml@^2.5.0, yaml@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.0.tgz#c6165a721cf8000e91c36490a41d7be25176cf5d" + integrity sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw== -yargs-parser@^21.0.1, yargs-parser@^21.1.1: +yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== @@ -6469,9 +8579,14 @@ yocto-queue@^0.1.0: integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== yocto-queue@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" - integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== + version "1.1.1" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110" + integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g== + +yoctocolors-cjs@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242" + integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA== youch@^3.2.2: version "3.3.3" @@ -6483,11 +8598,11 @@ youch@^3.2.2: stacktracey "^2.1.8" zod-validation-error@^3.0.3: - version "3.3.0" - resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-3.3.0.tgz#2cfe81b62d044e0453d1aa3ae7c32a2f36dde9af" - integrity sha512-Syib9oumw1NTqEv4LT0e6U83Td9aVRk9iTXPUQr1otyV1PuXQKOvOwhMNqZIq5hluzHP2pMgnOmHEo7kPdI2mw== + version "3.3.1" + resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-3.3.1.tgz#86adc781129d1a7fed3c3e567e8dbe7c4a15eaa4" + integrity sha512-uFzCZz7FQis256dqw4AhPQgD6f3pzNca/Zh62RNELavlumQB3nDIUFbF5JQfFLcMbO1s02Q7Xg/gpcOBlEnYZA== -zod@^3.20.6, zod@^3.22.4: +zod@^3.22.3, zod@^3.22.4: version "3.23.8" resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g== From 6023f85ffb78a1def3448b70da2c33fcb23aa958 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun, 1 Sep 2024 22:23:01 +0100 Subject: [PATCH 02/76] chore: attempts at MTProto auth > failed > moving on --- package.json | 3 +- prepend-node-imports.ts | 56 +++++ src/bot/auth/bot-auth.ts | 99 ++++++++ src/bot/features/mtproto/create-group.ts | 18 ++ src/bot/features/workroom.ts | 1 + src/bot/index.ts | 12 +- src/handlers/github/workrooms.ts | 42 ++-- src/types/env.ts | 12 +- src/utils/plugin-context-single.ts | 14 +- src/worker.ts | 17 +- yarn.lock | 306 ++++++++++++++++++++++- 11 files changed, 539 insertions(+), 41 deletions(-) create mode 100644 prepend-node-imports.ts create mode 100644 src/bot/auth/bot-auth.ts create mode 100644 src/bot/features/mtproto/create-group.ts diff --git a/package.json b/package.json index d6884fe..353d420 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,6 @@ "@grammyjs/parse-mode": "1.10.0", "@grammyjs/runner": "2.0.3", "@grammyjs/types": "3.13.0", - "@hono/node-server": "^1.12.1", "@octokit/rest": "21.0.2", "@octokit/webhooks": "13.3.0", "@sinclair/typebox": "0.33.7", @@ -57,6 +56,7 @@ "iso-639-1": "3.1.2", "pino": "9.3.2", "pino-pretty": "11.2.2", + "telegram": "^2.24.11", "typebox-validators": "0.3.5", "valibot": "0.39.0" }, @@ -72,6 +72,7 @@ "@mswjs/data": "0.16.1", "@types/jest": "^29.5.12", "@types/node": "22.5.0", + "@types/tdweb": "^1.4.5", "cspell": "8.14.2", "eslint": "9.9.1", "eslint-config-prettier": "9.1.0", diff --git a/prepend-node-imports.ts b/prepend-node-imports.ts new file mode 100644 index 0000000..8d1bd2e --- /dev/null +++ b/prepend-node-imports.ts @@ -0,0 +1,56 @@ +const fs = require("fs"); +const path = require("path"); + +const builtInModules = [ + "assert", + "buffer", + "child_process", + "cluster", + "crypto", + "dgram", + "dns", + "domain", + "events", + "fs", + "http", + "https", + "net", + "os", + "path", + "punycode", + "querystring", + "readline", + "stream", + "string_decoder", + "timers", + "tls", + "tty", + "url", + "util", + "v8", + "vm", + "zlib", +]; + +const srcDir = path.join(__dirname, "node_modules"); +function updateImports(filePath) { + let content = fs.readFileSync(filePath, "utf8"); + builtInModules.forEach((module) => { + const regex = new RegExp(`(import\\s+.*\\s+from\\s+['"])${module}(['"];?)`, "g"); + content = content.replace(regex, `$1node:${module}$2`); + }); + fs.writeFileSync(filePath, content, "utf8"); +} + +function processDirectory(directory) { + fs.readdirSync(directory).forEach((file) => { + const fullPath = path.join(directory, file); + if (fs.lstatSync(fullPath).isDirectory()) { + processDirectory(fullPath); + } else if (fullPath.endsWith(".ts") || fullPath.endsWith(".js")) { + updateImports(fullPath); + } + }); +} + +processDirectory(srcDir); diff --git a/src/bot/auth/bot-auth.ts b/src/bot/auth/bot-auth.ts new file mode 100644 index 0000000..aabae16 --- /dev/null +++ b/src/bot/auth/bot-auth.ts @@ -0,0 +1,99 @@ +import { Context } from '#root/types/context.js'; +import { PluginContext } from '#root/utils/plugin-context-single.js'; +import { TelegramClient } from 'telegram'; +import { Api } from 'telegram/tl'; +import { MemorySession } from 'telegram/sessions'; +import { TelegramClientParams, TelegramBaseClient } from 'telegram/client/telegramBaseClient'; + +export class MtProtoSingleton { + private static instance: MtProtoSingleton; + private static client: TelegramClient; + private static api: typeof Api; + + private constructor() { } + + static async initialize(env: Context["env"]) { + if (!MtProtoSingleton.instance) { + MtProtoSingleton.instance = new MtProtoSingleton(); + MtProtoSingleton.api = Api; + MtProtoSingleton.client = await mtProtoInit(env, MtProtoSingleton.api); + } + return MtProtoSingleton.instance; + } + + static getInstance(env: Context["env"]) { + if (!MtProtoSingleton.instance) { + return this.initialize(env) + } + return MtProtoSingleton.instance; + } + + getClient() { + return MtProtoSingleton.client; + } + + getApi() { + return MtProtoSingleton.api; + } +} + +import crypto from 'node:crypto'; + +async function mtProtoInit(env: Context["env"], api: typeof Api) { + const crpytoFns = Object.keys(crypto); + console.log("crypto functions", crpytoFns); + try { + const b = crypto.randomBytes(16); + console.log("BBBB, ", b); + } catch (error) { + console.error('Error using crypto.getRandomValues:', error); + } + + + const { TELEGRAM_API_HASH, TELEGRAM_APP_ID, BOT_TOKEN } = env + + if (!TELEGRAM_API_HASH || !TELEGRAM_APP_ID || !BOT_TOKEN) { + throw new Error("Missing required environment variables for Telegram API") + } + + const session = new MemorySession(); + session.save(); + + const osVersion = "Windows NT 11.0; Win64; x64"; + + const clientParams: TelegramClientParams = { + connectionRetries: 5, + systemVersion: osVersion, + appVersion: "1.0.0", + deviceModel: "PC", + } + + const client = new TelegramClient( + session, + TELEGRAM_APP_ID || 23868159, + TELEGRAM_API_HASH, + clientParams + ); + client.invoke(new api.auth.ImportBotAuthorization({ + apiId: TELEGRAM_APP_ID || 23868159, + apiHash: TELEGRAM_API_HASH, + botAuthToken: BOT_TOKEN, + })); + + await client.connect(); + + // const me = await client.getMe(); + // console.log(`Logged in as ${me.username}`); + + // const dialogs = await client.getDialogs(); + // console.log(`You have ${dialogs.length} chats`); + + // const newGroup = await client.invoke(new api.messages.CreateChat({ + // title: "New Group", + // users: [me.id], + // })); + + // console.log(`Created new group: `, { newGroup }); + + return client; +} \ No newline at end of file diff --git a/src/bot/features/mtproto/create-group.ts b/src/bot/features/mtproto/create-group.ts new file mode 100644 index 0000000..16ca398 --- /dev/null +++ b/src/bot/features/mtproto/create-group.ts @@ -0,0 +1,18 @@ +import { MtProtoSingleton } from "#root/bot/auth/bot-auth.js" +import { Context } from "#root/types/context.js" +import { Api } from "telegram" + +export async function createGroup(env: Context["env"]) { + const client = (await MtProtoSingleton.initialize(env)).getClient() + + const me = await client.getMe() + + console.log("got me details: ", me) + const newChat = await client.invoke(new Api.messages.CreateChat({ + title: "Test Chat", + users: [me.id] + })) + + console.log("newChat", newChat) + return newChat +} \ No newline at end of file diff --git a/src/bot/features/workroom.ts b/src/bot/features/workroom.ts index b98cdc6..642629a 100644 --- a/src/bot/features/workroom.ts +++ b/src/bot/features/workroom.ts @@ -1,6 +1,7 @@ import { Composer } from 'grammy' import type { Context } from '#root/bot/context.js' import { PluginContext } from '#root/utils/plugin-context-single.js' +import { Bot as TelegramBot, RawApi } from 'grammy' const composer = new Composer() diff --git a/src/bot/index.ts b/src/bot/index.ts index 66f6541..3031197 100644 --- a/src/bot/index.ts +++ b/src/bot/index.ts @@ -1,6 +1,6 @@ import type { BotConfig, StorageAdapter } from 'grammy' -import { Bot as TelegramBot } from 'grammy' +import { Bot as TelegramBot, Api } from 'grammy' import type { Context, SessionData } from '#root/bot/context.js' import { createContextConstructor } from '#root/bot/context.js' import type { Logger } from '#root/logger.js' @@ -67,13 +67,7 @@ export function createBot(token: string, dependencies: Dependencies, options: Op // // must be the last handler protectedBot.use(unhandledFeature) - Reflect.set(bot, 'getContext', createContextConstructor({ logger, config })) - - return bot as typeof bot & { - getContext: () => Context - } + return bot } -export type Bot = ReturnType & { - getContext: () => Context -} +export type Bot = ReturnType diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts index fa82753..235a150 100644 --- a/src/handlers/github/workrooms.ts +++ b/src/handlers/github/workrooms.ts @@ -1,26 +1,36 @@ +import { createGroup } from "#root/bot/features/mtproto/create-group.js"; import { TelegramBotSingleton } from "#root/utils/telegram-bot-single.js"; import { Context } from "../../types"; + export async function createChatroom(context: Context) { - const { logger, config } = context; - const bot = TelegramBotSingleton.getInstance().getBot(); - const title = context.payload.issue.title + const { logger, config, env } = context; - logger.info(`Creating chatroom for issue ${title}`); + logger.info("Creating chatroom for issue"); + const group = await createGroup(env); - let forum; - try { - forum = await bot.api?.createForumTopic(config.supergroupChatId, title); - logger.info(`Created chatroom for issue ${title}: ${forum?.message_thread_id}`); - } catch (er) { - logger.error(`Failed to create chatroom for issue ${title}`, { er }); - } + console.log("group created", group); - if (forum) { - await addCommentToIssue(context, `Workroom created: https://t.me/${config.supergroupChatName}/${forum?.message_thread_id}`); - } else { - await addCommentToIssue(context, logger.error(`Failed to create chatroom for issue ${title}`).logMessage.diff); - } + + + + // let forum; + // try { + // forum = await bot.api?.createForumTopic(config.supergroupChatId, title); + // bot.on(":forum_topic_created", async (event) => { + // logger.info(`Forum topic created: ${event.update.message?.message_thread_id}`); + // forum = event; + // }); + // logger.info(`Created chatroom for issue ${title}: ${forum?.message_thread_id}`); + // } catch (er) { + // logger.error(`Failed to create chatroom for issue ${title}`, { er }); + // } + + // if (forum) { + // await addCommentToIssue(context, `Workroom created: https://t.me/${config.supergroupChatName}/${forum?.message_thread_id}`); + // } else { + // await addCommentToIssue(context, logger.error(`Failed to create chatroom for issue ${title}`).logMessage.diff); + // } } diff --git a/src/types/env.ts b/src/types/env.ts index 5b82c16..2c00ba5 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -20,13 +20,17 @@ export const env = T.Object({ BOT_TOKEN: T.String(), BOT_MODE: T.String(), LOG_LEVEL: T.String(), - DEBUG: T.Transform(T.String()).Decode((str) => str === "true").Encode((bool) => bool ? "true" : "false"), + DEBUG: T.Transform(T.Union([T.String(), T.Boolean()])).Decode((str) => str === "true" || str === "false" ? str === "true" : str).Encode((bool) => bool.toString()), BOT_WEBHOOK: T.String(), BOT_WEBHOOK_SECRET: T.String(), SERVER_HOST: T.String(), - SERVER_PORT: T.Transform(T.String()).Decode((str) => parseInt(str)).Encode((num) => num.toString()), - BOT_ADMINS: T.Transform(T.String()).Decode((str) => JSON.parse(str)).Encode((arr) => JSON.stringify(arr)), - ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))) + SERVER_PORT: T.Transform(T.Union([T.String(), T.Number()])).Decode((str) => Number(str)).Encode((num) => num.toString()), + BOT_ADMINS: T.Transform(T.Union([T.String(), T.Array(T.String())])).Decode((str) => Array.isArray(str) ? str : [str]).Encode((arr) => arr.length === 1 ? arr[0] : arr), + ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))), + + // Taken from a personal telegram account not from the bot auth above + TELEGRAM_APP_ID: T.Transform(T.Union([T.String(), T.Number()])).Decode((str) => Number(str)).Encode((num) => num.toString()), + TELEGRAM_API_HASH: T.String(), }); /** diff --git a/src/utils/plugin-context-single.ts b/src/utils/plugin-context-single.ts index 074eeb4..7c8349e 100644 --- a/src/utils/plugin-context-single.ts +++ b/src/utils/plugin-context-single.ts @@ -1,5 +1,6 @@ -import { Context, Env, PluginInputs } from "#root/types"; +import { Context, Env, envValidator, PluginInputs } from "#root/types"; import { Octokit } from "@octokit/rest"; +import { Value } from "@sinclair/typebox/value"; import { Logs } from "@ubiquity-dao/ubiquibot-logger"; export class PluginContext { @@ -7,9 +8,16 @@ export class PluginContext { private constructor( public readonly inputs: PluginInputs, - public readonly env: Env, + public _env: Env, ) { } + get env() { + return Value.Decode(envValidator.schema, Value.Default(envValidator.schema, this._env)); + } + set env(env: Env) { + this._env = env; + } + static initialize(inputs: PluginInputs, env: Env): Context { if (!PluginContext.instance) { PluginContext.instance = new PluginContext(inputs, env); @@ -19,7 +27,7 @@ export class PluginContext { static getInstance(): PluginContext { if (!PluginContext.instance) { - throw new Error("PluginContext is not initialized. Call initialize() first."); + throw new Error("PluginContext not initialized"); } return PluginContext.instance; } diff --git a/src/worker.ts b/src/worker.ts index 1aa0f65..ca600d6 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,4 +1,4 @@ -import { Env, PluginInputs } from "./types"; +import { Env, envValidator, PluginInputs } from "./types"; import { isGithubPayload, isTelegramPayload } from "./types/typeguards"; import { handleGithubWebhook } from "./handlers/github/webhook"; import { handleTelegramWebhook } from "./handlers/telegram/webhook"; @@ -6,6 +6,7 @@ import manifest from "../manifest.json"; import { handleUncaughtError } from "./utils/errors"; import { TelegramBotSingleton } from "./utils/telegram-bot-single"; import { PluginContext } from "./utils/plugin-context-single"; +import { Value } from "@sinclair/typebox/value"; export default { async fetch(request: Request, env: Env): Promise { @@ -42,6 +43,20 @@ export default { }); } + const envSettings = Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)); + + if (!envValidator.test(envSettings)) { + const errors: string[] = []; + for (const error of envValidator.errors(envSettings)) { + console.error(error); + errors.push(`${error.path}: ${error.message}`); + } + return new Response(JSON.stringify({ error: `Error: "Invalid environment provided. ${errors.join("; ")}"` }), { + status: 400, + headers: { "content-type": "application/json" }, + }); + } + TelegramBotSingleton.initialize(env); try { diff --git a/yarn.lock b/yarn.lock index 62c607e..a9d2a0f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1300,6 +1300,11 @@ "@types/conventional-commits-parser" "^5.0.0" chalk "^5.3.0" +"@cryptography/aes@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@cryptography/aes/-/aes-0.1.1.tgz#0096726a6a2a2cfc2e8bddf3997e98e49f1a224d" + integrity sha512-PcYz4FDGblO6tM2kSC+VzhhK62vml6k6/YAkiWtyPvrgJVfnDRoHGDtKn5UiaRRUrvUTTocBpvc2rRgTCqxjsg== + "@cspell/cspell-bundled-dicts@8.14.2": version "8.14.2" resolved "https://registry.yarnpkg.com/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.14.2.tgz#746706485228e055ff342a66191cb6b9e58e748a" @@ -2043,11 +2048,6 @@ resolved "https://registry.yarnpkg.com/@grammyjs/types/-/types-3.13.0.tgz#3316a809b4faf6cc61cff0c7d7a5a671ec0bd776" integrity sha512-Oyq6fBuVPyX6iWvxT/0SxJvNisC9GHUEkhZ60qJBHRmwNX4hIcOfhrNEahicn3K9SYyreGPVw3d9wlLRds83cw== -"@hono/node-server@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.12.1.tgz#bc5528ba5a9542ec20ae1dbe6ccdc078ddea72ab" - integrity sha512-C9l+08O8xtXB7Ppmy8DjBFH1hYji7JKzsU32Yt1poIIbdPp6S7aOI8IldDHD9YFJ55lv2c21ovNrmxatlHfhAg== - "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" @@ -2802,6 +2802,11 @@ resolved "https://registry.yarnpkg.com/@types/statuses/-/statuses-2.0.5.tgz#f61ab46d5352fd73c863a1ea4e1cef3b0b51ae63" integrity sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A== +"@types/tdweb@^1.4.5": + version "1.4.5" + resolved "https://registry.yarnpkg.com/@types/tdweb/-/tdweb-1.4.5.tgz#4a5c3085fdf99de9fae7b87eaad16bc8271c93d5" + integrity sha512-6rFeIo6iofNkNz6Jn2BR9BWtOcjEsDdhJeQ7oYPXg865vOOeI6etPE7x1B2KtU1CE/A04c5jL6CRKhd/ut22xA== + "@types/tough-cookie@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" @@ -3286,6 +3291,13 @@ async-lock@^1.4.1: resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.4.1.tgz#56b8718915a9b68b10fce2f2a9a3dddf765ef53f" integrity sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ== +async-mutex@^0.3.0: + version "0.3.2" + resolved "https://registry.yarnpkg.com/async-mutex/-/async-mutex-0.3.2.tgz#1485eda5bda1b0ec7c8df1ac2e815757ad1831df" + integrity sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA== + dependencies: + tslib "^2.3.1" + async@^3.2.3: version "3.2.6" resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" @@ -3422,6 +3434,11 @@ before-after-hook@^3.0.2: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-3.0.2.tgz#d5665a5fa8b62294a5aa0a499f933f4a1016195d" integrity sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A== +big-integer@^1.6.48: + version "1.6.52" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" + integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== + binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" @@ -3491,6 +3508,13 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" +bufferutil@^4.0.1, bufferutil@^4.0.3: + version "4.0.8" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.8.tgz#1de6a71092d65d7766c4d8a522b261a6e787e8ea" + integrity sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw== + dependencies: + node-gyp-build "^4.3.0" + builtin-modules@3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" @@ -3967,6 +3991,14 @@ cspell@8.14.2: semver "^7.6.3" strip-ansi "^7.1.0" +d@1, d@^1.0.1, d@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.2.tgz#2aefd554b81981e7dccf72d6842ae725cb17e5de" + integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== + dependencies: + es5-ext "^0.10.64" + type "^2.7.2" + damerau-levenshtein@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" @@ -4026,6 +4058,13 @@ dateformat@^4.6.3: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== +debug@^2.2.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -4150,6 +4189,36 @@ doctrine@^2.1.0: dependencies: esutils "^2.0.2" +dom-serializer@^1.0.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@^4.0.0, domhandler@^4.2.0: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== + dependencies: + domelementtype "^2.2.0" + +domutils@^2.5.2: + version "2.8.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + dot-prop@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" @@ -4223,6 +4292,11 @@ enhanced-resolve@^5.17.1: graceful-fs "^4.2.4" tapable "^2.2.0" +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + env-paths@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" @@ -4376,6 +4450,33 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es5-ext@^0.10.35, es5-ext@^0.10.62, es5-ext@^0.10.63, es5-ext@^0.10.64, es5-ext@~0.10.14: + version "0.10.64" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714" + integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + esniff "^2.0.1" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.4" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.4.tgz#f4e7d28013770b4208ecbf3e0bf14d3bcb557b8c" + integrity sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg== + dependencies: + d "^1.0.2" + ext "^1.7.0" + esbuild@0.17.19: version "0.17.19" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.19.tgz#087a727e98299f0462a3d0bcdd9cd7ff100bd955" @@ -4682,6 +4783,16 @@ eslint@9.9.1: strip-ansi "^6.0.1" text-table "^0.2.0" +esniff@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" + integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== + dependencies: + d "^1.0.1" + es5-ext "^0.10.62" + event-emitter "^0.3.5" + type "^2.7.2" + espree@^10.0.1, espree@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/espree/-/espree-10.1.0.tgz#8788dae611574c0f070691f522e4116c5a11fc56" @@ -4739,6 +4850,14 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + event-stream@=3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" @@ -4823,6 +4942,13 @@ expect@^29.0.0, expect@^29.7.0: jest-message-util "^29.7.0" jest-util "^29.7.0" +ext@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + fast-copy@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.2.tgz#59c68f59ccbcac82050ba992e0d5c389097c9d35" @@ -5178,7 +5304,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -5286,6 +5412,16 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== +htmlparser2@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" + integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + domutils "^2.5.2" + entities "^2.0.0" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -5369,6 +5505,14 @@ internal-slot@^1.0.4, internal-slot@^1.0.7: hasown "^2.0.0" side-channel "^1.0.4" +ip-address@^9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a" + integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g== + dependencies: + jsbn "1.1.0" + sprintf-js "^1.1.3" + is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -5593,6 +5737,11 @@ is-typed-array@^1.1.13: dependencies: which-typed-array "^1.1.14" +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + is-weakmap@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" @@ -6129,6 +6278,11 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jsbn@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" + integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -6565,6 +6719,11 @@ mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -6618,6 +6777,11 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -6645,11 +6809,23 @@ node-forge@^1: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== +node-gyp-build@^4.3.0: + version "4.8.2" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.2.tgz#4f802b71c1ab2ca16af830e6c1ea7dd1ad9496fa" + integrity sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== +node-localstorage@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-localstorage/-/node-localstorage-2.2.1.tgz#869723550a4883e426cb391d2df0b563a51c7c1c" + integrity sha512-vv8fJuOUCCvSPjDjBLlMqYMHob4aGjkmrkaE42/mZr0VT+ZAU10jRF8oTnX9+pgU9/vYJ8P7YT3Vd6ajkmzSCw== + dependencies: + write-file-atomic "^1.1.4" + node-releases@^2.0.18: version "2.0.18" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" @@ -6878,6 +7054,11 @@ pako@^1.0.10: resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== +pako@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" + integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -6915,6 +7096,11 @@ parse-ms@^4.0.0: resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-4.0.0.tgz#c0c058edd47c2a590151a718990533fd62803df4" integrity sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw== +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -7242,6 +7428,11 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +real-cancellable-promise@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/real-cancellable-promise/-/real-cancellable-promise-1.2.0.tgz#f365e78b29c6a2303584f2c308959b415401056a" + integrity sha512-FYhmx1FVSgoPRjneoTjh+EKZcNb8ijl/dyatTzase5eujYhVrLNDOiIY6AgQq7GU1kOoLgEd9jLVbhFg8k8dOQ== + real-require@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" @@ -7633,6 +7824,16 @@ slice-ansi@^7.1.0: ansi-styles "^6.2.1" is-fullwidth-code-point "^5.0.0" +slide@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + integrity sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw== + +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + smee-client@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/smee-client/-/smee-client-2.0.3.tgz#de57d90a2531af136e0f0496a88599376ad53fa8" @@ -7647,6 +7848,14 @@ smol-toml@^1.1.4: resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.3.0.tgz#5200e251fffadbb72570c84e9776d2a3eca48143" integrity sha512-tWpi2TsODPScmi48b/OQZGi2lgUmBCHy6SZrhi/FdnnHiU1GwebbCfuQuxsC3nHaLwtYeJGPrDZDIeodDOc4pA== +socks@^2.6.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.3.tgz#1ebd0f09c52ba95a09750afe3f3f9f724a800cb5" + integrity sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw== + dependencies: + ip-address "^9.0.5" + smart-buffer "^4.2.0" + sonic-boom@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.0.1.tgz#515b7cef2c9290cb362c4536388ddeece07aed30" @@ -7710,6 +7919,11 @@ split@0.3: dependencies: through "2" +sprintf-js@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" + integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -7747,6 +7961,11 @@ stoppable@^1.1.0: resolved "https://registry.yarnpkg.com/stoppable/-/stoppable-1.1.0.tgz#32da568e83ea488b08e4d7ea2c3bcc9d75015d5b" integrity sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw== +store2@^2.13.0: + version "2.14.3" + resolved "https://registry.yarnpkg.com/store2/-/store2-2.14.3.tgz#24077d7ba110711864e4f691d2af941ec533deb5" + integrity sha512-4QcZ+yx7nzEFiV4BMLnr/pRa5HYzNITX2ri0Zh6sT9EyQHbBHacC6YigllUPU9X3D0f/22QCgfokpKs52YRrUg== + stream-combiner@~0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" @@ -7957,6 +8176,29 @@ tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +telegram@^2.24.11: + version "2.24.11" + resolved "https://registry.yarnpkg.com/telegram/-/telegram-2.24.11.tgz#2b0238a2cead8cf63adea23d362de34f85fe4124" + integrity sha512-d4rqMeOI7itNzLXRIcRHdZrCXXV8K6h/aFiJXdMVNWhl0PsCePytsdtjpgmgAuO1tQ8k6jW+aR/DoZk5nE0x9g== + dependencies: + "@cryptography/aes" "^0.1.1" + async-mutex "^0.3.0" + big-integer "^1.6.48" + buffer "^6.0.3" + htmlparser2 "^6.1.0" + mime "^3.0.0" + node-localstorage "^2.2.1" + pako "^2.0.3" + path-browserify "^1.0.1" + real-cancellable-promise "^1.1.1" + socks "^2.6.2" + store2 "^2.13.0" + ts-custom-error "^3.2.0" + websocket "^1.0.34" + optionalDependencies: + bufferutil "^4.0.3" + utf-8-validate "^5.0.5" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -8025,6 +8267,11 @@ ts-api-utils@^1.3.0: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== +ts-custom-error@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/ts-custom-error/-/ts-custom-error-3.3.1.tgz#8bd3c8fc6b8dc8e1cb329267c45200f1e17a65d1" + integrity sha512-5OX1tzOjxWEgsr/YEUWSuPrQ00deKLh6D7OTWcvNHm12/7QPyRh8SYpyWvA4IZv8H/+GQWQEh/kwo95Q9OVW1A== + ts-jest@29.2.5: version "29.2.5" resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.2.5.tgz#591a3c108e1f5ebd013d3152142cb5472b399d63" @@ -8060,7 +8307,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.2.0, tslib@^2.6.2: +tslib@^2.2.0, tslib@^2.3.1, tslib@^2.6.2: version "2.7.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== @@ -8102,6 +8349,11 @@ type-fest@^4.9.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.25.0.tgz#b190374f969631866889bbdb01ece17ca424ee60" integrity sha512-bRkIGlXsnGBRBQRAY56UXBm//9qH4bmJfFvq83gSz41N282df+fjy8ofcEgc1sM8geNt5cl6mC2g9Fht1cs8Aw== +type@^2.7.2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.3.tgz#436981652129285cc3ba94f392886c2637ea0486" + integrity sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ== + typebox-validators@0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/typebox-validators/-/typebox-validators-0.3.5.tgz#b913bad0a87571ffe0edd01d2b6090a268e1ecc9" @@ -8151,6 +8403,13 @@ typed-array-length@^1.0.6: is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + typescript-eslint@8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.3.0.tgz#f4d9c5ba71f6bead03ec41ecb2bece1de511e49f" @@ -8275,6 +8534,13 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" +utf-8-validate@^5.0.2, utf-8-validate@^5.0.5: + version "5.0.10" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== + dependencies: + node-gyp-build "^4.3.0" + util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -8354,6 +8620,18 @@ webidl-conversions@^3.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== +websocket@^1.0.34: + version "1.0.35" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.35.tgz#374197207d7d4cc4c36cbf8a1bb886ee52a07885" + integrity sha512-/REy6amwPZl44DDzvRCkaI1q1bIiQB0mEFQLUrhz3z2EK91cp3n72rAjUlrTP0zV22HJIUOVHQGPxhFRjxjt+Q== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.63" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -8507,6 +8785,15 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +write-file-atomic@^1.1.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" + integrity sha512-SdrHoC/yVBPpV0Xq/mUZQIpW2sWXAShb/V4pomcJXh92RuaO+f3UTWItiR3Px+pLnV2PvC2/bfn5cwr5X6Vfxw== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" + write-file-atomic@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" @@ -8540,6 +8827,11 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug== + yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" From 58ba05e9bc5536b3eb32f49732aa3780698bf633 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun, 1 Sep 2024 23:36:54 +0100 Subject: [PATCH 03/76] chore: repo structure, remove unused --- prepend-node-imports.ts | 56 ----------- src/bot/auth/bot-auth.ts | 99 ------------------- src/bot/features/{ => admin}/admin.ts | 0 src/bot/features/{ => helpers}/chatid.ts | 0 src/bot/features/{ => helpers}/language.ts | 0 src/bot/features/{ => helpers}/unhandled.ts | 2 +- src/bot/features/{ => helpers}/user-id.ts | 0 src/bot/features/mtproto/create-group.ts | 18 ---- .../{workroom.ts => on/forum-created.ts} | 5 +- src/bot/index.ts | 10 +- .../github/utils/add-comment-to-issues.ts | 18 ++++ src/types/context.ts | 7 +- src/types/env.ts | 6 +- 13 files changed, 30 insertions(+), 191 deletions(-) delete mode 100644 prepend-node-imports.ts delete mode 100644 src/bot/auth/bot-auth.ts rename src/bot/features/{ => admin}/admin.ts (100%) rename src/bot/features/{ => helpers}/chatid.ts (100%) rename src/bot/features/{ => helpers}/language.ts (100%) rename src/bot/features/{ => helpers}/unhandled.ts (92%) rename src/bot/features/{ => helpers}/user-id.ts (100%) delete mode 100644 src/bot/features/mtproto/create-group.ts rename src/bot/features/{workroom.ts => on/forum-created.ts} (70%) create mode 100644 src/handlers/github/utils/add-comment-to-issues.ts diff --git a/prepend-node-imports.ts b/prepend-node-imports.ts deleted file mode 100644 index 8d1bd2e..0000000 --- a/prepend-node-imports.ts +++ /dev/null @@ -1,56 +0,0 @@ -const fs = require("fs"); -const path = require("path"); - -const builtInModules = [ - "assert", - "buffer", - "child_process", - "cluster", - "crypto", - "dgram", - "dns", - "domain", - "events", - "fs", - "http", - "https", - "net", - "os", - "path", - "punycode", - "querystring", - "readline", - "stream", - "string_decoder", - "timers", - "tls", - "tty", - "url", - "util", - "v8", - "vm", - "zlib", -]; - -const srcDir = path.join(__dirname, "node_modules"); -function updateImports(filePath) { - let content = fs.readFileSync(filePath, "utf8"); - builtInModules.forEach((module) => { - const regex = new RegExp(`(import\\s+.*\\s+from\\s+['"])${module}(['"];?)`, "g"); - content = content.replace(regex, `$1node:${module}$2`); - }); - fs.writeFileSync(filePath, content, "utf8"); -} - -function processDirectory(directory) { - fs.readdirSync(directory).forEach((file) => { - const fullPath = path.join(directory, file); - if (fs.lstatSync(fullPath).isDirectory()) { - processDirectory(fullPath); - } else if (fullPath.endsWith(".ts") || fullPath.endsWith(".js")) { - updateImports(fullPath); - } - }); -} - -processDirectory(srcDir); diff --git a/src/bot/auth/bot-auth.ts b/src/bot/auth/bot-auth.ts deleted file mode 100644 index aabae16..0000000 --- a/src/bot/auth/bot-auth.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Context } from '#root/types/context.js'; -import { PluginContext } from '#root/utils/plugin-context-single.js'; -import { TelegramClient } from 'telegram'; -import { Api } from 'telegram/tl'; -import { MemorySession } from 'telegram/sessions'; -import { TelegramClientParams, TelegramBaseClient } from 'telegram/client/telegramBaseClient'; - -export class MtProtoSingleton { - private static instance: MtProtoSingleton; - private static client: TelegramClient; - private static api: typeof Api; - - private constructor() { } - - static async initialize(env: Context["env"]) { - if (!MtProtoSingleton.instance) { - MtProtoSingleton.instance = new MtProtoSingleton(); - MtProtoSingleton.api = Api; - MtProtoSingleton.client = await mtProtoInit(env, MtProtoSingleton.api); - } - return MtProtoSingleton.instance; - } - - static getInstance(env: Context["env"]) { - if (!MtProtoSingleton.instance) { - return this.initialize(env) - } - return MtProtoSingleton.instance; - } - - getClient() { - return MtProtoSingleton.client; - } - - getApi() { - return MtProtoSingleton.api; - } -} - -import crypto from 'node:crypto'; - -async function mtProtoInit(env: Context["env"], api: typeof Api) { - const crpytoFns = Object.keys(crypto); - console.log("crypto functions", crpytoFns); - try { - const b = crypto.randomBytes(16); - console.log("BBBB, ", b); - } catch (error) { - console.error('Error using crypto.getRandomValues:', error); - } - - - const { TELEGRAM_API_HASH, TELEGRAM_APP_ID, BOT_TOKEN } = env - - if (!TELEGRAM_API_HASH || !TELEGRAM_APP_ID || !BOT_TOKEN) { - throw new Error("Missing required environment variables for Telegram API") - } - - const session = new MemorySession(); - session.save(); - - const osVersion = "Windows NT 11.0; Win64; x64"; - - const clientParams: TelegramClientParams = { - connectionRetries: 5, - systemVersion: osVersion, - appVersion: "1.0.0", - deviceModel: "PC", - } - - const client = new TelegramClient( - session, - TELEGRAM_APP_ID || 23868159, - TELEGRAM_API_HASH, - clientParams - ); - client.invoke(new api.auth.ImportBotAuthorization({ - apiId: TELEGRAM_APP_ID || 23868159, - apiHash: TELEGRAM_API_HASH, - botAuthToken: BOT_TOKEN, - })); - - await client.connect(); - - // const me = await client.getMe(); - // console.log(`Logged in as ${me.username}`); - - // const dialogs = await client.getDialogs(); - // console.log(`You have ${dialogs.length} chats`); - - // const newGroup = await client.invoke(new api.messages.CreateChat({ - // title: "New Group", - // users: [me.id], - // })); - - // console.log(`Created new group: `, { newGroup }); - - return client; -} \ No newline at end of file diff --git a/src/bot/features/admin.ts b/src/bot/features/admin/admin.ts similarity index 100% rename from src/bot/features/admin.ts rename to src/bot/features/admin/admin.ts diff --git a/src/bot/features/chatid.ts b/src/bot/features/helpers/chatid.ts similarity index 100% rename from src/bot/features/chatid.ts rename to src/bot/features/helpers/chatid.ts diff --git a/src/bot/features/language.ts b/src/bot/features/helpers/language.ts similarity index 100% rename from src/bot/features/language.ts rename to src/bot/features/helpers/language.ts diff --git a/src/bot/features/unhandled.ts b/src/bot/features/helpers/unhandled.ts similarity index 92% rename from src/bot/features/unhandled.ts rename to src/bot/features/helpers/unhandled.ts index e12b7c2..9a4c7d9 100644 --- a/src/bot/features/unhandled.ts +++ b/src/bot/features/helpers/unhandled.ts @@ -1,7 +1,7 @@ import { Composer } from 'grammy' import type { Context } from '#root/bot/context.js' import { logHandle } from '#root/bot/helpers/logging.js' -import { STRINGS } from '../strings' +import { STRINGS } from '../../strings' const composer = new Composer() diff --git a/src/bot/features/user-id.ts b/src/bot/features/helpers/user-id.ts similarity index 100% rename from src/bot/features/user-id.ts rename to src/bot/features/helpers/user-id.ts diff --git a/src/bot/features/mtproto/create-group.ts b/src/bot/features/mtproto/create-group.ts deleted file mode 100644 index 16ca398..0000000 --- a/src/bot/features/mtproto/create-group.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { MtProtoSingleton } from "#root/bot/auth/bot-auth.js" -import { Context } from "#root/types/context.js" -import { Api } from "telegram" - -export async function createGroup(env: Context["env"]) { - const client = (await MtProtoSingleton.initialize(env)).getClient() - - const me = await client.getMe() - - console.log("got me details: ", me) - const newChat = await client.invoke(new Api.messages.CreateChat({ - title: "Test Chat", - users: [me.id] - })) - - console.log("newChat", newChat) - return newChat -} \ No newline at end of file diff --git a/src/bot/features/workroom.ts b/src/bot/features/on/forum-created.ts similarity index 70% rename from src/bot/features/workroom.ts rename to src/bot/features/on/forum-created.ts index 642629a..bd3b690 100644 --- a/src/bot/features/workroom.ts +++ b/src/bot/features/on/forum-created.ts @@ -1,7 +1,6 @@ import { Composer } from 'grammy' import type { Context } from '#root/bot/context.js' import { PluginContext } from '#root/utils/plugin-context-single.js' -import { Bot as TelegramBot, RawApi } from 'grammy' const composer = new Composer() @@ -9,9 +8,9 @@ const feature = composer.chatType("supergroup") feature.on(":forum_topic_created", async (ctx) => { const pluginCtx = PluginContext.getInstance().getContext() - const chatId = pluginCtx.config.supergroupChatId // replace with general or dedicated channel for announcements + const chatId = pluginCtx.config.supergroupChatId const name = ctx.update.message.forum_topic_created.name return await ctx.api.sendMessage(chatId, `New workroom created: ${name} `) }) -export { composer as createForumsFeature } +export { composer as createForumsFeature } \ No newline at end of file diff --git a/src/bot/index.ts b/src/bot/index.ts index 3031197..197ac36 100644 --- a/src/bot/index.ts +++ b/src/bot/index.ts @@ -6,17 +6,17 @@ import { createContextConstructor } from '#root/bot/context.js' import type { Logger } from '#root/logger.js' import { Context as UbiquityOsContext } from '../types' import { welcomeFeature } from '#root/bot/features/welcome.js' -import { unhandledFeature } from '#root/bot/features/unhandled.js' +import { unhandledFeature } from '#root/bot/features/helpers/unhandled.js' import { errorHandler } from '#root/bot/handlers/error.js' import { session } from '#root/bot/middlewares/session.js' import { autoChatAction } from '@grammyjs/auto-chat-action' import { hydrate } from '@grammyjs/hydrate' import { hydrateReply, parseMode } from '@grammyjs/parse-mode' import { i18n } from './i18n' -import { adminFeature } from './features/admin' -import { userIdFeature } from './features/user-id' -import { createForumsFeature } from './features/workroom' -import { chatIdFeature } from './features/chatid' +import { adminFeature } from './features/admin/admin' +import { userIdFeature } from './features/helpers/user-id' +import { createForumsFeature } from './features/on/forum-created' +import { chatIdFeature } from './features/helpers/chatid' interface Dependencies { config: UbiquityOsContext["env"] diff --git a/src/handlers/github/utils/add-comment-to-issues.ts b/src/handlers/github/utils/add-comment-to-issues.ts new file mode 100644 index 0000000..2767d60 --- /dev/null +++ b/src/handlers/github/utils/add-comment-to-issues.ts @@ -0,0 +1,18 @@ +import { Context } from "#root/types/context.js"; + +export async function addCommentToIssue(context: Context, msg: string, owner: string, repo: string, issueNumber: number) { + const { logger, octokit } = context; + logger.info(`Adding comment to issue ${issueNumber}`); + + try { + await octokit.issues.createComment({ + owner, + repo, + issue_number: issueNumber, + body: msg, + }); + logger.info(`Added comment to issue ${issueNumber}`); + } catch (er) { + logger.error(`Failed to add comment to issue ${issueNumber}`, { er }); + } +} \ No newline at end of file diff --git a/src/types/context.ts b/src/types/context.ts index 5f24919..f1d78af 100644 --- a/src/types/context.ts +++ b/src/types/context.ts @@ -5,11 +5,10 @@ import { PluginSettings } from "./plugin-inputs"; import { Logs } from "@ubiquity-dao/ubiquibot-logger"; /** - * Update `manifest.json` with any events you want to support like so: - * - * ubiquity:listeners: ["issue_comment.created", ...] + * If we let this run on all events it'll be easier to handle multiple + * "plugins" in the future. */ -export type SupportedEventsU = "issues.opened" +export type SupportedEventsU = WebhookEventName export type SupportedEvents = { [K in SupportedEventsU]: K extends WebhookEventName ? WebhookEvent : never; diff --git a/src/types/env.ts b/src/types/env.ts index 2c00ba5..439d194 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -25,12 +25,8 @@ export const env = T.Object({ BOT_WEBHOOK_SECRET: T.String(), SERVER_HOST: T.String(), SERVER_PORT: T.Transform(T.Union([T.String(), T.Number()])).Decode((str) => Number(str)).Encode((num) => num.toString()), - BOT_ADMINS: T.Transform(T.Union([T.String(), T.Array(T.String())])).Decode((str) => Array.isArray(str) ? str : [str]).Encode((arr) => arr.length === 1 ? arr[0] : arr), + BOT_ADMINS: T.Transform(T.Union([T.String(), T.Array(T.String())])).Decode((str) => Array.isArray(str) ? str.map(Number) : [Number(str)]).Encode((arr) => arr.map(String)), ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))), - - // Taken from a personal telegram account not from the bot auth above - TELEGRAM_APP_ID: T.Transform(T.Union([T.String(), T.Number()])).Decode((str) => Number(str)).Encode((num) => num.toString()), - TELEGRAM_API_HASH: T.String(), }); /** From 067380691740ae30f26834cb6caec496e088ea5d Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 2 Sep 2024 00:49:43 +0100 Subject: [PATCH 04/76] feat: callback proxy --- src/handlers/callbacks-proxy.ts | 93 +++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/handlers/callbacks-proxy.ts diff --git a/src/handlers/callbacks-proxy.ts b/src/handlers/callbacks-proxy.ts new file mode 100644 index 0000000..fc0a7d7 --- /dev/null +++ b/src/handlers/callbacks-proxy.ts @@ -0,0 +1,93 @@ +import { Context, SupportedEvents, SupportedEventsU } from "../types"; +import { createChatroom } from "./github/workrooms"; + +type Result = { status: "success" } | { status: string; reason: string; content?: string | Record }; + +/** + * The `Context` type is a generic type defined as `Context`, + * where `TEvent` is a string representing the event name (e.g., "issues.labeled") + * and `TPayload` is the webhook payload type for that event, derived from + * the `SupportedEvents` type map. + * + * The `ProxyCallbacks` type is defined using `Partial` to allow + * optional callbacks for each event type. This is useful because not all events + * may have associated callbacks. + * + * The expected function signature for callbacks looks like this: + * + * ```typescript + * fn(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise + * ``` + */ + +type ProxyCallbacks = Partial; +type ProxyTypeHelper = { + [K in SupportedEventsU]: Array<(context: Context) => Promise>; +}; + +/** + * Why do we need this wrapper function? + * + * By using a generic `Function` type for the callback parameter, we bypass strict type + * checking temporarily. This allows us to pass a standard `Context` object, which we know + * contains the correct event and payload types, to the callback safely. + * + * We can trust that the `ProxyCallbacks` type has already ensured that each callback function + * matches the expected event and payload types, so this function provides a safe and + * flexible way to handle callbacks without introducing type or logic errors. + */ +function handleCallback(callback: Function, context: Context) { + return callback(context); +} + +/** + * The `callbacks` object defines an array of callback functions for each supported event type. + * + * Since multiple callbacks might need to be executed for a single event, we store each + * callback in an array. This design allows for extensibility and flexibility, enabling + * us to add more callbacks for a particular event without modifying the core logic. + */ +const callbacks: ProxyCallbacks = { + "issues.labeled": [ + createChatroom, + ] +}; + +/** + * The `proxyCallbacks` function returns a Proxy object that intercepts access to the + * `callbacks` object. This Proxy enables dynamic handling of event callbacks, including: + * + * - **Event Handling:** When an event occurs, the Proxy looks up the corresponding + * callbacks in the `callbacks` object. If no callbacks are found for the event, + * it returns a `skipped` status. + * + * - **Error Handling:** If an error occurs while processing a callback, the Proxy + * logs the error and returns a `failed` status. + * + * The Proxy uses the `get` trap to intercept attempts to access properties on the + * `callbacks` object. This trap allows us to asynchronously execute the appropriate + * callbacks based on the event type, ensuring that the correct context is passed to + * each callback. + */ +export function proxyCallbacks({ logger }: Context) { + return new Proxy(callbacks, { + get(target, prop: SupportedEventsU) { + return async (context: Context) => { + if (!target[prop]) { + return { status: "skipped", reason: "unsupported_event" }; + } + try { + for (const callback of target[prop]) { + await handleCallback(callback, context); + } + + // @TODO: better handling for returning the outcome of multiple callbacks + return { status: "success" }; + } catch (er) { + logger.error(`Failed to handle event ${prop}`, { er }); + return { status: "failed", reason: "callback_error" }; + } + }; + }, + }); +} From cd59b43ae8a9fc442eb6d227309e02c9e73cae3f Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 2 Sep 2024 01:46:03 +0100 Subject: [PATCH 05/76] chore: supabase --- package.json | 3 +- src/adapters/supabase/helpers/chats.ts | 56 ++++++++++++++++++ src/adapters/supabase/helpers/supabase.ts | 12 ++++ src/adapters/supabase/helpers/user.ts | 24 ++++++++ yarn.lock | 71 ++++++++++++++++++++++- 5 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 src/adapters/supabase/helpers/chats.ts create mode 100644 src/adapters/supabase/helpers/supabase.ts create mode 100644 src/adapters/supabase/helpers/user.ts diff --git a/package.json b/package.json index 353d420..347beff 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "@octokit/rest": "21.0.2", "@octokit/webhooks": "13.3.0", "@sinclair/typebox": "0.33.7", + "@supabase/supabase-js": "^2.45.3", "@ubiquity-dao/ubiquibot-logger": "^1.3.1", "callback-data": "1.1.1", "dotenv": "16.4.5", @@ -110,4 +111,4 @@ ] }, "packageManager": "yarn@1.22.22" -} \ No newline at end of file +} diff --git a/src/adapters/supabase/helpers/chats.ts b/src/adapters/supabase/helpers/chats.ts new file mode 100644 index 0000000..585dee9 --- /dev/null +++ b/src/adapters/supabase/helpers/chats.ts @@ -0,0 +1,56 @@ +import { SupabaseClient } from "@supabase/supabase-js"; +import { Super } from "./supabase"; +import { Context } from "../../../types/context"; + +/** + * Handles all telegram chat storage and retrieval + */ +export class Chats extends Super { + constructor(supabase: SupabaseClient, context: Context) { + super(supabase, context); + } + + async getChatById(chatId: number) { + const { data, error } = (await this.supabase.from("chats").select("*").eq("id", chatId).single()) as { data: unknown; error: unknown }; + if (error || !data) { + this.context.logger.error("No chat found", { chatId }); + } else { + this.context.logger.info("Successfully fetched chat", { chatId }); + } + + return data; + } + + async getChatByName(chatName: string) { + const { data, error } = (await this.supabase.from("chats").select("*").eq("name", chatName).single()) as { data: unknown; error: unknown }; + if (error || !data) { + this.context.logger.error("No chat found", { chatName }); + } else { + this.context.logger.info("Successfully fetched chat", { chatName }); + } + + return data; + } + + async saveChat(chatId: number, chatName: string) { + const { data, error } = (await this.supabase.from("chats").upsert({ id: chatId, name: chatName })) as { data: unknown; error: unknown }; + if (error || !data) { + this.context.logger.error("Failed to save chat", { chatId, chatName }); + } else { + this.context.logger.info("Successfully saved chat", { chatId, chatName }); + } + + return data; + } + + async updateChat(chatId: number, chatName: string) { + const { data, error } = (await this.supabase.from("chats").update({ name: chatName }).eq("id", chatId)) as { data: unknown; error: unknown }; + if (error || !data) { + this.context.logger.error("Failed to update chat", { chatId, chatName }); + } else { + this.context.logger.info("Successfully updated chat", { chatId, chatName }); + } + + return data; + } +} \ No newline at end of file diff --git a/src/adapters/supabase/helpers/supabase.ts b/src/adapters/supabase/helpers/supabase.ts new file mode 100644 index 0000000..7a13b85 --- /dev/null +++ b/src/adapters/supabase/helpers/supabase.ts @@ -0,0 +1,12 @@ +import { SupabaseClient } from "@supabase/supabase-js"; +import { Context } from "../../../types/context"; + +export class Super { + protected supabase: SupabaseClient; + protected context: Context; + + constructor(supabase: SupabaseClient, context: Context) { + this.supabase = supabase; + this.context = context; + } +} diff --git a/src/adapters/supabase/helpers/user.ts b/src/adapters/supabase/helpers/user.ts new file mode 100644 index 0000000..8f18cd4 --- /dev/null +++ b/src/adapters/supabase/helpers/user.ts @@ -0,0 +1,24 @@ +import { SupabaseClient } from "@supabase/supabase-js"; +import { Super } from "./supabase"; +import { Context } from "../../../types/context"; + +type Wallet = { + address: string; +}; + +export class User extends Super { + constructor(supabase: SupabaseClient, context: Context) { + super(supabase, context); + } + + async getWalletByUserId(userId: number, issueNumber: number) { + const { data, error } = (await this.supabase.from("users").select("wallets(*)").eq("id", userId).single()) as { data: { wallets: Wallet }; error: unknown }; + if ((error && !data) || !data.wallets?.address) { + this.context.logger.error("No wallet address found", { userId, issueNumber }); + } else { + this.context.logger.info("Successfully fetched wallet", { userId, address: data.wallets?.address }); + } + + return data?.wallets?.address || null; + } +} diff --git a/yarn.lock b/yarn.lock index a9d2a0f..f5eb332 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2654,6 +2654,63 @@ ignore "^5.1.8" p-map "^4.0.0" +"@supabase/auth-js@2.65.0": + version "2.65.0" + resolved "https://registry.yarnpkg.com/@supabase/auth-js/-/auth-js-2.65.0.tgz#e345c492f8cbc31cd6289968eae0e349ff0f39e9" + integrity sha512-+wboHfZufAE2Y612OsKeVP4rVOeGZzzMLD/Ac3HrTQkkY4qXNjI6Af9gtmxwccE5nFvTiF114FEbIQ1hRq5uUw== + dependencies: + "@supabase/node-fetch" "^2.6.14" + +"@supabase/functions-js@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@supabase/functions-js/-/functions-js-2.4.1.tgz#373e75f8d3453bacd71fb64f88d7a341d7b53ad7" + integrity sha512-8sZ2ibwHlf+WkHDUZJUXqqmPvWQ3UHN0W30behOJngVh/qHHekhJLCFbh0AjkE9/FqqXtf9eoVvmYgfCLk5tNA== + dependencies: + "@supabase/node-fetch" "^2.6.14" + +"@supabase/node-fetch@2.6.15", "@supabase/node-fetch@^2.6.14": + version "2.6.15" + resolved "https://registry.yarnpkg.com/@supabase/node-fetch/-/node-fetch-2.6.15.tgz#731271430e276983191930816303c44159e7226c" + integrity sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ== + dependencies: + whatwg-url "^5.0.0" + +"@supabase/postgrest-js@1.15.8": + version "1.15.8" + resolved "https://registry.yarnpkg.com/@supabase/postgrest-js/-/postgrest-js-1.15.8.tgz#827aaa408cdbc89e67d0a758e7a545ac86e34312" + integrity sha512-YunjXpoQjQ0a0/7vGAvGZA2dlMABXFdVI/8TuVKtlePxyT71sl6ERl6ay1fmIeZcqxiuFQuZw/LXUuStUG9bbg== + dependencies: + "@supabase/node-fetch" "^2.6.14" + +"@supabase/realtime-js@2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@supabase/realtime-js/-/realtime-js-2.10.2.tgz#c2b42d17d723d2d2a9146cfad61dc3df1ce3127e" + integrity sha512-qyCQaNg90HmJstsvr2aJNxK2zgoKh9ZZA8oqb7UT2LCh3mj9zpa3Iwu167AuyNxsxrUE8eEJ2yH6wLCij4EApA== + dependencies: + "@supabase/node-fetch" "^2.6.14" + "@types/phoenix" "^1.5.4" + "@types/ws" "^8.5.10" + ws "^8.14.2" + +"@supabase/storage-js@2.7.0": + version "2.7.0" + resolved "https://registry.yarnpkg.com/@supabase/storage-js/-/storage-js-2.7.0.tgz#9ff322d2c3b141087aa34115cf14205e4980ce75" + integrity sha512-iZenEdO6Mx9iTR6T7wC7sk6KKsoDPLq8rdu5VRy7+JiT1i8fnqfcOr6mfF2Eaqky9VQzhP8zZKQYjzozB65Rig== + dependencies: + "@supabase/node-fetch" "^2.6.14" + +"@supabase/supabase-js@^2.45.3": + version "2.45.3" + resolved "https://registry.yarnpkg.com/@supabase/supabase-js/-/supabase-js-2.45.3.tgz#d32b7a7b379958a10dcce32af1182f82b5b82218" + integrity sha512-4wAux6cuVMrdH/qUjKn6p3p3L9AtAO3Une6ojIrtpCj1RaXKVoyIATiacSRAI+pKff6XZBVCGC29v+z4Jo/uSw== + dependencies: + "@supabase/auth-js" "2.65.0" + "@supabase/functions-js" "2.4.1" + "@supabase/node-fetch" "2.6.15" + "@supabase/postgrest-js" "1.15.8" + "@supabase/realtime-js" "2.10.2" + "@supabase/storage-js" "2.7.0" + "@types/babel__core@^7.1.14": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -2787,6 +2844,11 @@ dependencies: undici-types "~6.19.2" +"@types/phoenix@^1.5.4": + version "1.6.5" + resolved "https://registry.yarnpkg.com/@types/phoenix/-/phoenix-1.6.5.tgz#5654e14ec7ad25334a157a20015996b6d7d2075e" + integrity sha512-xegpDuR+z0UqG9fwHqNoy3rI7JDlvaPh2TY47Fl80oq6g+hXT+c/LEuE43X48clZ6lOfANl5WrPur9fYO1RJ/w== + "@types/pluralize@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/pluralize/-/pluralize-0.0.29.tgz#6ffa33ed1fc8813c469b859681d09707eb40d03c" @@ -2822,6 +2884,13 @@ resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd" integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g== +"@types/ws@^8.5.10": + version "8.5.12" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.12.tgz#619475fe98f35ccca2a2f6c137702d85ec247b7e" + integrity sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ== + dependencies: + "@types/node" "*" + "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" @@ -8802,7 +8871,7 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" -ws@^8.17.1: +ws@^8.14.2, ws@^8.17.1: version "8.18.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== From 0bea908e482ef54a21022cdc4cf3a9c0ae0bfa87 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 2 Sep 2024 01:49:08 +0100 Subject: [PATCH 06/76] chore: use callbacks, error logging and env --- src/adapters/index.ts | 13 +++++++++ .../{github/webhook.ts => github-webhook.ts} | 4 +-- .../webhook.ts => telegram-webhook.ts} | 2 +- src/plugin.ts | 28 +++++++++++++++---- src/types/context.ts | 2 ++ src/types/env.ts | 3 ++ src/worker.ts | 4 +-- 7 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 src/adapters/index.ts rename src/handlers/{github/webhook.ts => github-webhook.ts} (94%) rename src/handlers/{telegram/webhook.ts => telegram-webhook.ts} (92%) diff --git a/src/adapters/index.ts b/src/adapters/index.ts new file mode 100644 index 0000000..424f9be --- /dev/null +++ b/src/adapters/index.ts @@ -0,0 +1,13 @@ +import { SupabaseClient } from "@supabase/supabase-js"; +import { Context } from "../types/context"; +import { User } from "./supabase/helpers/user"; +import { Chats } from "./supabase/helpers/chats"; + +export function createAdapters(supabaseClient: SupabaseClient, context: Context) { + return { + supabase: { + user: new User(supabaseClient, context), + chats: new Chats(supabaseClient, context), + }, + }; +} diff --git a/src/handlers/github/webhook.ts b/src/handlers/github-webhook.ts similarity index 94% rename from src/handlers/github/webhook.ts rename to src/handlers/github-webhook.ts index 289cb9a..8c2a4de 100644 --- a/src/handlers/github/webhook.ts +++ b/src/handlers/github-webhook.ts @@ -1,6 +1,6 @@ import { Value } from "@sinclair/typebox/value"; -import { plugin } from "../../plugin"; -import { pluginSettingsSchema, pluginSettingsValidator, PluginInputs, Env } from "../../types"; +import { plugin } from "../plugin"; +import { pluginSettingsSchema, pluginSettingsValidator, PluginInputs, Env } from "../types"; export async function handleGithubWebhook(request: Request, env: Env): Promise { try { diff --git a/src/handlers/telegram/webhook.ts b/src/handlers/telegram-webhook.ts similarity index 92% rename from src/handlers/telegram/webhook.ts rename to src/handlers/telegram-webhook.ts index 4dba1ee..c5bb57e 100644 --- a/src/handlers/telegram/webhook.ts +++ b/src/handlers/telegram-webhook.ts @@ -1,5 +1,5 @@ import { Value } from "@sinclair/typebox/value"; -import { envValidator, Env } from "../../types"; +import { envValidator, Env } from "../types"; import { TelegramBotSingleton } from "#root/utils/telegram-bot-single.js"; export async function handleTelegramWebhook(request: Request, env: Env): Promise { diff --git a/src/plugin.ts b/src/plugin.ts index 8027d84..e976f48 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -1,8 +1,9 @@ -import { Env, PluginInputs } from "./types"; +import { Env, PluginInputs, SupportedEvents, SupportedEventsU } from "./types"; import { Context } from "./types"; -import { isIssueOpenedEvent } from "./types/typeguards"; -import { createChatroom } from "./handlers/github/workrooms"; import { PluginContext } from "./utils/plugin-context-single"; +import { proxyCallbacks } from "./handlers/callbacks-proxy"; +import { LogReturn } from "@ubiquity-dao/ubiquibot-logger"; +import { addCommentToIssue } from "./handlers/github/utils/add-comment-to-issues"; /** * The main plugin function. Split for easier testing. @@ -10,18 +11,33 @@ import { PluginContext } from "./utils/plugin-context-single"; export async function runPlugin(context: Context) { const { logger, eventName } = context; - if (isIssueOpenedEvent(context)) { - return await createChatroom(context); + try { + return proxyCallbacks(context)[eventName] + } catch (err) { + let errorMessage; + if (err instanceof LogReturn) { + errorMessage = err; + } else if (err instanceof Error) { + errorMessage = context.logger.error(err.message, { error: err }); + } else { + errorMessage = context.logger.error("An error occurred", { err }); + } + await addCommentToIssue(context, `${errorMessage?.logMessage.diff}\n`); } logger.error(`Unsupported event: ${eventName}`); } + +function sanitizeMetadata(obj: LogReturn["metadata"]): string { + return JSON.stringify(obj, null, 2).replace(//g, ">").replace(/--/g, "--"); +} + /** * How a worker executes the plugin. */ export async function plugin(inputs: PluginInputs, env: Env) { PluginContext.initialize(inputs, env) - const context: Context = PluginContext.getInstance().getContext() + const context = PluginContext.getInstance().getContext() return runPlugin(context); } \ No newline at end of file diff --git a/src/types/context.ts b/src/types/context.ts index f1d78af..1a12d8b 100644 --- a/src/types/context.ts +++ b/src/types/context.ts @@ -3,6 +3,7 @@ import { EmitterWebhookEvent as WebhookEvent, EmitterWebhookEventName as Webhook import { Env } from "./env"; import { PluginSettings } from "./plugin-inputs"; import { Logs } from "@ubiquity-dao/ubiquibot-logger"; +import { createAdapters } from "../adapters"; /** * If we let this run on all events it'll be easier to handle multiple @@ -21,4 +22,5 @@ export interface Context; } diff --git a/src/types/env.ts b/src/types/env.ts index 439d194..01fd55c 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -27,6 +27,9 @@ export const env = T.Object({ SERVER_PORT: T.Transform(T.Union([T.String(), T.Number()])).Decode((str) => Number(str)).Encode((num) => num.toString()), BOT_ADMINS: T.Transform(T.Union([T.String(), T.Array(T.String())])).Decode((str) => Array.isArray(str) ? str.map(Number) : [Number(str)]).Encode((arr) => arr.map(String)), ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))), + + SUPABASE_URL: T.String(), + SUPABASE_KEY: T.String(), }); /** diff --git a/src/worker.ts b/src/worker.ts index ca600d6..ef3247f 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,7 +1,7 @@ import { Env, envValidator, PluginInputs } from "./types"; import { isGithubPayload, isTelegramPayload } from "./types/typeguards"; -import { handleGithubWebhook } from "./handlers/github/webhook"; -import { handleTelegramWebhook } from "./handlers/telegram/webhook"; +import { handleGithubWebhook } from "./handlers/github-webhook"; +import { handleTelegramWebhook } from "./handlers/telegram-webhook"; import manifest from "../manifest.json"; import { handleUncaughtError } from "./utils/errors"; import { TelegramBotSingleton } from "./utils/telegram-bot-single"; From 19fc70c68a33a90de8bb32e5769f4e1bf231b24b Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 2 Sep 2024 01:51:01 +0100 Subject: [PATCH 07/76] chore: getDeepVal util and close workroom on issues.closed --- .../github/utils/add-comment-to-issues.ts | 14 +++- src/handlers/github/workrooms.ts | 84 +++++++++---------- src/utils/get-deep-value.ts | 23 +++++ src/utils/plugin-context-single.ts | 10 ++- 4 files changed, 86 insertions(+), 45 deletions(-) create mode 100644 src/utils/get-deep-value.ts diff --git a/src/handlers/github/utils/add-comment-to-issues.ts b/src/handlers/github/utils/add-comment-to-issues.ts index 2767d60..fa011a6 100644 --- a/src/handlers/github/utils/add-comment-to-issues.ts +++ b/src/handlers/github/utils/add-comment-to-issues.ts @@ -1,9 +1,21 @@ import { Context } from "#root/types/context.js"; +import { getDeepValue } from "#root/utils/get-deep-value.js"; -export async function addCommentToIssue(context: Context, msg: string, owner: string, repo: string, issueNumber: number) { +export async function addCommentToIssue(context: Context, msg: string, owner?: string, repo?: string, issueNumber?: number) { const { logger, octokit } = context; logger.info(`Adding comment to issue ${issueNumber}`); + + if (!owner || !repo || !issueNumber) { + owner = getDeepValue(context, "payload.repository.owner.login"); + repo = getDeepValue(context, "payload.repository.name"); + issueNumber = getDeepValue(context, "payload.issue.number"); + } + + if (!owner || !repo || !issueNumber) { + throw new Error(logger.error("Missing owner, repo, or issue number", { owner, repo, issueNumber }).logMessage.raw); + } + try { await octokit.issues.createComment({ owner, diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts index 235a150..f7404d0 100644 --- a/src/handlers/github/workrooms.ts +++ b/src/handlers/github/workrooms.ts @@ -1,55 +1,55 @@ -import { createGroup } from "#root/bot/features/mtproto/create-group.js"; import { TelegramBotSingleton } from "#root/utils/telegram-bot-single.js"; -import { Context } from "../../types"; - - -export async function createChatroom(context: Context) { - const { logger, config, env } = context; - - logger.info("Creating chatroom for issue"); - const group = await createGroup(env); - - console.log("group created", group); - - +import { Context, SupportedEvents } from "../../types"; +import { addCommentToIssue } from "./utils/add-comment-to-issues"; + +export async function createChatroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>) { + const { logger, config } = context; + const bot = TelegramBotSingleton.getInstance().getBot(); + const title = context.payload.issue.title + const { issue, repository } = context.payload; + const { full_name } = repository; + const [owner, repo] = full_name.split("/"); + logger.info(`Creating chatroom for issue ${title}`); - // let forum; - // try { - // forum = await bot.api?.createForumTopic(config.supergroupChatId, title); - // bot.on(":forum_topic_created", async (event) => { - // logger.info(`Forum topic created: ${event.update.message?.message_thread_id}`); - // forum = event; - // }); - // logger.info(`Created chatroom for issue ${title}: ${forum?.message_thread_id}`); - // } catch (er) { - // logger.error(`Failed to create chatroom for issue ${title}`, { er }); - // } + let forum; + try { + forum = await bot.api?.createForumTopic(config.supergroupChatId, title); + bot.on(":forum_topic_created", async (event) => { + logger.info(`Forum topic created: ${event.update.message?.message_thread_id}`); + forum = event; + }); + await addCommentToIssue(context, `Workroom created: https://t.me/${config.supergroupChatName}/${forum?.message_thread_id}`, owner, repo, issue.number); + } catch (er) { + await addCommentToIssue(context, logger.error(`Failed to create chatroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); + } - // if (forum) { - // await addCommentToIssue(context, `Workroom created: https://t.me/${config.supergroupChatName}/${forum?.message_thread_id}`); - // } else { - // await addCommentToIssue(context, logger.error(`Failed to create chatroom for issue ${title}`).logMessage.diff); - // } + if (!forum) { + return { status: "failed", reason: "chatroom_creation_failed" }; + } else { + return { status: "success", content: forum, reason: "chatroom_created" }; + } } - -async function addCommentToIssue(context: Context, msg: string) { - const { logger, octokit } = context; - const { repository: { full_name }, issue } = context.payload; +export async function closeChatroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>) { + const { logger, config } = context; + const bot = TelegramBotSingleton.getInstance().getBot(); + const title = context.payload.issue.title + const { issue, repository } = context.payload; + const { full_name } = repository; const [owner, repo] = full_name.split("/"); - logger.info(`Adding comment to issue ${issue.number}`); + logger.info(`Closing chatroom for issue ${title}`); + + const id = 11111 // @TODO: Supabase try { - await octokit.issues.createComment({ - owner, - repo, - issue_number: issue.number, - body: msg, - }); - logger.info(`Added comment to issue ${issue.number}`); + await bot.api?.closeForumTopic(config.supergroupChatId, id); + await addCommentToIssue(context, `Workroom closed for issue ${title}`, owner, repo, issue.number); } catch (er) { - logger.error(`Failed to add comment to issue ${issue.number}`, { er }); + await addCommentToIssue(context, logger.error(`Failed to close chatroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); } + + return { status: "success", reason: "chatroom_closed" }; } + diff --git a/src/utils/get-deep-value.ts b/src/utils/get-deep-value.ts new file mode 100644 index 0000000..2eceb6b --- /dev/null +++ b/src/utils/get-deep-value.ts @@ -0,0 +1,23 @@ + +/** + * While hacky, this is probably the best way to handle our use case. + * + * This function is a utility that allows us to access deeply nested properties in an object + * primarily for use with the context.payload object. It should not be overused and the developer + * should be aware of the potential performance implications of using this function. + * + * Example usage: + * getDeepValue(context, "payload.repository.owner.login") will return the owner + * getDeepValue(context, ["payload", "repository", "owner", "login"]) will return the owner + * + * @param obj The object to access the property from + * @param path The path to the property, either as a string or an array of strings + * @returns The value of the property if it exists, or undefined if it does not + */ +export function getDeepValue(obj: T, path: K | K[]) { + if (!obj || !path) return undefined; + + const pathArray = Array.isArray(path) ? path : path.split('.'); + + return pathArray.reduce((prev, key) => prev && prev[key], obj as any); +} \ No newline at end of file diff --git a/src/utils/plugin-context-single.ts b/src/utils/plugin-context-single.ts index 7c8349e..821fbfd 100644 --- a/src/utils/plugin-context-single.ts +++ b/src/utils/plugin-context-single.ts @@ -2,6 +2,8 @@ import { Context, Env, envValidator, PluginInputs } from "#root/types"; import { Octokit } from "@octokit/rest"; import { Value } from "@sinclair/typebox/value"; import { Logs } from "@ubiquity-dao/ubiquibot-logger"; +import { createAdapters } from "../adapters"; +import { createClient } from "@supabase/supabase-js"; export class PluginContext { private static instance: PluginContext; @@ -34,14 +36,18 @@ export class PluginContext { getContext(): Context { const octokit = new Octokit({ auth: this.inputs.authToken }); - - return { + const ctx: Context = { eventName: this.inputs.eventName, payload: this.inputs.eventPayload, config: this.inputs.settings, octokit, env: this.env, logger: new Logs("info"), + adapters: {} as ReturnType, }; + + ctx.adapters = createAdapters(createClient(ctx.env.SUPABASE_URL, ctx.env.SUPABASE_KEY), ctx); + + return ctx; } } \ No newline at end of file From 1846d98b7436cf0c9b7257a4ecf95a10bd3dcde5 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 2 Sep 2024 02:09:04 +0100 Subject: [PATCH 08/76] chore: supa chats and closed on issues.closed --- src/adapters/supabase/helpers/chats.ts | 61 +++++++++++++++++++------- src/handlers/callbacks-proxy.ts | 7 ++- src/handlers/github/workrooms.ts | 36 ++++++++------- 3 files changed, 71 insertions(+), 33 deletions(-) diff --git a/src/adapters/supabase/helpers/chats.ts b/src/adapters/supabase/helpers/chats.ts index 585dee9..9c0acc8 100644 --- a/src/adapters/supabase/helpers/chats.ts +++ b/src/adapters/supabase/helpers/chats.ts @@ -10,45 +10,74 @@ export class Chats extends Super { super(supabase, context); } - async getChatById(chatId: number) { - const { data, error } = (await this.supabase.from("chats").select("*").eq("id", chatId).single()) as { data: unknown; error: unknown }; + async updateChatStatus(status: string, taskNodeId?: string, chatId?: number) { + if (!taskNodeId && !chatId) { + this.context.logger.error("No taskNodeId or chatId provided to update chat status"); + return; + } + + let chat; + + if (taskNodeId) { + chat = await this.getChatByTaskNodeId(taskNodeId); + } else if (chatId) { + chat = await this.getChatByChatId(chatId); + } + + if (!chat) { + this.context.logger.error("No chat found to update chat status"); + return; + } + + const { data, error } = (await this.supabase.from("chats").upsert({ ...chat, status })) as { data: unknown; error: unknown }; + if (error || !data) { - this.context.logger.error("No chat found", { chatId }); + this.context.logger.error("Failed to update chat status", { chatId, taskNodeId }); } else { - this.context.logger.info("Successfully fetched chat", { chatId }); + this.context.logger.info("Successfully updated chat status", { chatId, taskNodeId }); + } + } + + + async saveChat(chatId: number, chatName: string, taskNodeId: string) { + const { data, error } = (await this.supabase.from("chats").upsert({ chatId, chatName, taskNodeId })) as { data: unknown; error: unknown }; + if (error || !data) { + this.context.logger.error("Failed to save chat", { chatId, chatName }); + } else { + this.context.logger.info("Successfully saved chat", { chatId, chatName }); } return data; } - async getChatByName(chatName: string) { - const { data, error } = (await this.supabase.from("chats").select("*").eq("name", chatName).single()) as { data: unknown; error: unknown }; + async getChatByChatId(chatId: number) { + const { data, error } = (await this.supabase.from("chats").select("*").eq("chatId", chatId).single()) as { data: unknown; error: unknown }; if (error || !data) { - this.context.logger.error("No chat found", { chatName }); + this.context.logger.error("No chat found", { chatId }); } else { - this.context.logger.info("Successfully fetched chat", { chatName }); + this.context.logger.info("Successfully fetched chat", { chatId }); } return data; } - async saveChat(chatId: number, chatName: string) { - const { data, error } = (await this.supabase.from("chats").upsert({ id: chatId, name: chatName })) as { data: unknown; error: unknown }; + async getChatByChatName(chatName: string) { + const { data, error } = (await this.supabase.from("chats").select("*").eq("chatName", chatName).single()) as { data: unknown; error: unknown }; if (error || !data) { - this.context.logger.error("Failed to save chat", { chatId, chatName }); + this.context.logger.error("No chat found", { chatName }); } else { - this.context.logger.info("Successfully saved chat", { chatId, chatName }); + this.context.logger.info("Successfully fetched chat", { chatName }); } return data; } - async updateChat(chatId: number, chatName: string) { - const { data, error } = (await this.supabase.from("chats").update({ name: chatName }).eq("id", chatId)) as { data: unknown; error: unknown }; + async getChatByTaskNodeId(taskNodeId: string) { + const { data, error } = (await this.supabase.from("chats").select("*").eq("taskNodeId", taskNodeId).single()) as { data: unknown; error: unknown }; if (error || !data) { - this.context.logger.error("Failed to update chat", { chatId, chatName }); + this.context.logger.error("No chat found", { taskNodeId }); } else { - this.context.logger.info("Successfully updated chat", { chatId, chatName }); + this.context.logger.info("Successfully fetched chat", { taskNodeId }); } return data; diff --git a/src/handlers/callbacks-proxy.ts b/src/handlers/callbacks-proxy.ts index fc0a7d7..8279915 100644 --- a/src/handlers/callbacks-proxy.ts +++ b/src/handlers/callbacks-proxy.ts @@ -1,5 +1,5 @@ import { Context, SupportedEvents, SupportedEventsU } from "../types"; -import { createChatroom } from "./github/workrooms"; +import { closeChatroom, createChatroom } from "./github/workrooms"; type Result = { status: "success" } | { status: string; reason: string; content?: string | Record }; @@ -50,7 +50,10 @@ function handleCallback(callback: Function, context: Context) { const callbacks: ProxyCallbacks = { "issues.labeled": [ createChatroom, - ] + ], + "issues.closed": [ + closeChatroom + ], }; /** diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts index f7404d0..4bcb4e0 100644 --- a/src/handlers/github/workrooms.ts +++ b/src/handlers/github/workrooms.ts @@ -3,36 +3,37 @@ import { Context, SupportedEvents } from "../../types"; import { addCommentToIssue } from "./utils/add-comment-to-issues"; export async function createChatroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>) { - const { logger, config } = context; + const { logger, config, adapters: { supabase: { chats } } } = context; const bot = TelegramBotSingleton.getInstance().getBot(); const title = context.payload.issue.title const { issue, repository } = context.payload; const { full_name } = repository; const [owner, repo] = full_name.split("/"); + const chatroom = await chats.getChatByTaskNodeId(issue.node_id); + + if (chatroom) { + return { status: "skipped", reason: "chatroom_exists" }; + } + logger.info(`Creating chatroom for issue ${title}`); - let forum; try { - forum = await bot.api?.createForumTopic(config.supergroupChatId, title); - bot.on(":forum_topic_created", async (event) => { - logger.info(`Forum topic created: ${event.update.message?.message_thread_id}`); - forum = event; - }); + const forum = await bot.api?.createForumTopic(config.supergroupChatId, title); await addCommentToIssue(context, `Workroom created: https://t.me/${config.supergroupChatName}/${forum?.message_thread_id}`, owner, repo, issue.number); + + await chats.saveChat(forum?.message_thread_id, title, issue.node_id); + + return { status: "success", content: forum, reason: "chatroom_created" }; } catch (er) { await addCommentToIssue(context, logger.error(`Failed to create chatroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); - } - - if (!forum) { return { status: "failed", reason: "chatroom_creation_failed" }; - } else { - return { status: "success", content: forum, reason: "chatroom_created" }; } + } export async function closeChatroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>) { - const { logger, config } = context; + const { logger, config, adapters: { supabase: { chats } } } = context; const bot = TelegramBotSingleton.getInstance().getBot(); const title = context.payload.issue.title const { issue, repository } = context.payload; @@ -41,10 +42,15 @@ export async function closeChatroom(context: Context<"issues.closed", SupportedE logger.info(`Closing chatroom for issue ${title}`); - const id = 11111 // @TODO: Supabase + const chatroom = await chats.getChatByTaskNodeId(issue.node_id); + + if (!chatroom) { + return { status: "skipped", reason: "chatroom_not_found" }; + } try { - await bot.api?.closeForumTopic(config.supergroupChatId, id); + await bot.api?.closeForumTopic(config.supergroupChatId, chatroom.chatId); + await chats.updateChatStatus("closed", issue.node_id); await addCommentToIssue(context, `Workroom closed for issue ${title}`, owner, repo, issue.number); } catch (er) { await addCommentToIssue(context, logger.error(`Failed to close chatroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); From 61f1da83fabf61c2b87427163971855e49d579c4 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 2 Sep 2024 02:13:34 +0100 Subject: [PATCH 09/76] chore: supa chats and closed on issues.closed --- src/adapters/supabase/helpers/chats.ts | 7 +++++++ src/handlers/github/workrooms.ts | 7 ++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/adapters/supabase/helpers/chats.ts b/src/adapters/supabase/helpers/chats.ts index 9c0acc8..c2ac8e3 100644 --- a/src/adapters/supabase/helpers/chats.ts +++ b/src/adapters/supabase/helpers/chats.ts @@ -2,6 +2,13 @@ import { SupabaseClient } from "@supabase/supabase-js"; import { Super } from "./supabase"; import { Context } from "../../../types/context"; +export type Chat = { + chatId: number; + chatName: string; + taskNodeId: string; + status: string; +} + /** * Handles all telegram chat storage and retrieval */ diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts index 4bcb4e0..335587c 100644 --- a/src/handlers/github/workrooms.ts +++ b/src/handlers/github/workrooms.ts @@ -1,3 +1,4 @@ +import { Chat } from "#root/adapters/supabase/helpers/chats.js"; import { TelegramBotSingleton } from "#root/utils/telegram-bot-single.js"; import { Context, SupportedEvents } from "../../types"; import { addCommentToIssue } from "./utils/add-comment-to-issues"; @@ -42,7 +43,7 @@ export async function closeChatroom(context: Context<"issues.closed", SupportedE logger.info(`Closing chatroom for issue ${title}`); - const chatroom = await chats.getChatByTaskNodeId(issue.node_id); + const chatroom = await chats.getChatByTaskNodeId(issue.node_id) as Chat if (!chatroom) { return { status: "skipped", reason: "chatroom_not_found" }; @@ -52,10 +53,10 @@ export async function closeChatroom(context: Context<"issues.closed", SupportedE await bot.api?.closeForumTopic(config.supergroupChatId, chatroom.chatId); await chats.updateChatStatus("closed", issue.node_id); await addCommentToIssue(context, `Workroom closed for issue ${title}`, owner, repo, issue.number); + return { status: "success", reason: "chatroom_closed" }; } catch (er) { await addCommentToIssue(context, logger.error(`Failed to close chatroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); + return { status: "failed", reason: "chatroom_closing_failed" }; } - - return { status: "success", reason: "chatroom_closed" }; } From bd321d634340b86862bb89dd52a4bb75601d7413 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 2 Sep 2024 02:24:18 +0100 Subject: [PATCH 10/76] chore: use numeric status response --- src/handlers/callbacks-proxy.ts | 11 +++++------ src/handlers/github/workrooms.ts | 17 +++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/handlers/callbacks-proxy.ts b/src/handlers/callbacks-proxy.ts index 8279915..eb49654 100644 --- a/src/handlers/callbacks-proxy.ts +++ b/src/handlers/callbacks-proxy.ts @@ -1,7 +1,7 @@ import { Context, SupportedEvents, SupportedEventsU } from "../types"; import { closeChatroom, createChatroom } from "./github/workrooms"; -type Result = { status: "success" } | { status: string; reason: string; content?: string | Record }; +export type CallbackResult = { status: 200 | 201 | 204 | 404 | 500, reason: string; content?: string | Record }; /** * The `Context` type is a generic type defined as `Context`, @@ -22,7 +22,7 @@ type Result = { status: "success" } | { status: string; reason: string; content? type ProxyCallbacks = Partial; type ProxyTypeHelper = { - [K in SupportedEventsU]: Array<(context: Context) => Promise>; + [K in SupportedEventsU]: Array<(context: Context) => Promise>; }; /** @@ -77,18 +77,17 @@ export function proxyCallbacks({ logger }: Context) { get(target, prop: SupportedEventsU) { return async (context: Context) => { if (!target[prop]) { - return { status: "skipped", reason: "unsupported_event" }; + logger.info(`No callbacks found for event ${prop}`); + return { status: 204, reason: "skipped" }; } try { for (const callback of target[prop]) { await handleCallback(callback, context); } - // @TODO: better handling for returning the outcome of multiple callbacks - return { status: "success" }; } catch (er) { logger.error(`Failed to handle event ${prop}`, { er }); - return { status: "failed", reason: "callback_error" }; + return { status: 500, reason: "failed" }; } }; }, diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts index 335587c..0ac9c29 100644 --- a/src/handlers/github/workrooms.ts +++ b/src/handlers/github/workrooms.ts @@ -1,9 +1,10 @@ import { Chat } from "#root/adapters/supabase/helpers/chats.js"; import { TelegramBotSingleton } from "#root/utils/telegram-bot-single.js"; import { Context, SupportedEvents } from "../../types"; +import { CallbackResult } from "../callbacks-proxy"; import { addCommentToIssue } from "./utils/add-comment-to-issues"; -export async function createChatroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>) { +export async function createChatroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { const { logger, config, adapters: { supabase: { chats } } } = context; const bot = TelegramBotSingleton.getInstance().getBot(); const title = context.payload.issue.title @@ -14,7 +15,7 @@ export async function createChatroom(context: Context<"issues.labeled", Supporte const chatroom = await chats.getChatByTaskNodeId(issue.node_id); if (chatroom) { - return { status: "skipped", reason: "chatroom_exists" }; + return { status: 404, reason: "chatroom_already_exists" }; } logger.info(`Creating chatroom for issue ${title}`); @@ -25,15 +26,15 @@ export async function createChatroom(context: Context<"issues.labeled", Supporte await chats.saveChat(forum?.message_thread_id, title, issue.node_id); - return { status: "success", content: forum, reason: "chatroom_created" }; + return { status: 201, reason: "chatroom_created" }; } catch (er) { await addCommentToIssue(context, logger.error(`Failed to create chatroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); - return { status: "failed", reason: "chatroom_creation_failed" }; + return { status: 500, reason: "chatroom_creation_failed" }; } } -export async function closeChatroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>) { +export async function closeChatroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { const { logger, config, adapters: { supabase: { chats } } } = context; const bot = TelegramBotSingleton.getInstance().getBot(); const title = context.payload.issue.title @@ -46,17 +47,17 @@ export async function closeChatroom(context: Context<"issues.closed", SupportedE const chatroom = await chats.getChatByTaskNodeId(issue.node_id) as Chat if (!chatroom) { - return { status: "skipped", reason: "chatroom_not_found" }; + return { status: 404, reason: "chatroom_not_found" }; } try { await bot.api?.closeForumTopic(config.supergroupChatId, chatroom.chatId); await chats.updateChatStatus("closed", issue.node_id); await addCommentToIssue(context, `Workroom closed for issue ${title}`, owner, repo, issue.number); - return { status: "success", reason: "chatroom_closed" }; + return { status: 200, reason: "chatroom_closed" }; } catch (er) { await addCommentToIssue(context, logger.error(`Failed to close chatroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); - return { status: "failed", reason: "chatroom_closing_failed" }; + return { status: 500, reason: "chatroom_closing_failed" }; } } From e212e2bf81cbb696b0061ba4587e258d34d940ce Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 2 Sep 2024 02:29:39 +0100 Subject: [PATCH 11/76] chore: reopen chatroom on issues.reopen --- src/handlers/callbacks-proxy.ts | 5 ++++- src/handlers/github/workrooms.ts | 38 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/handlers/callbacks-proxy.ts b/src/handlers/callbacks-proxy.ts index eb49654..de5f5fa 100644 --- a/src/handlers/callbacks-proxy.ts +++ b/src/handlers/callbacks-proxy.ts @@ -1,5 +1,5 @@ import { Context, SupportedEvents, SupportedEventsU } from "../types"; -import { closeChatroom, createChatroom } from "./github/workrooms"; +import { closeChatroom, createChatroom, reOpenChatroom } from "./github/workrooms"; export type CallbackResult = { status: 200 | 201 | 204 | 404 | 500, reason: string; content?: string | Record }; @@ -54,6 +54,9 @@ const callbacks: ProxyCallbacks = { "issues.closed": [ closeChatroom ], + "issues.reopened": [ + reOpenChatroom + ] }; /** diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts index 0ac9c29..7d295c2 100644 --- a/src/handlers/github/workrooms.ts +++ b/src/handlers/github/workrooms.ts @@ -4,6 +4,18 @@ import { Context, SupportedEvents } from "../../types"; import { CallbackResult } from "../callbacks-proxy"; import { addCommentToIssue } from "./utils/add-comment-to-issues"; +/** + * V1 specifications for the `createChatroom` feature. + * + * - A "workroom" (chatroom) is created when an issue is labeled. + * - The chatroom is created in a Telegram supergroup as a forum topic, not a new group. + * - The chatroom is associated with the issue by storing the issue's node_id. + * - The chatroom is closed when the issue is closed. + * - The chatroom is closed by closing the forum topic in the supergroup. + * - The chatroom status is updated to "closed" in the database. + * - A comment is added to the issue when the chatroom is created or closed. + */ + export async function createChatroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { const { logger, config, adapters: { supabase: { chats } } } = context; const bot = TelegramBotSingleton.getInstance().getBot(); @@ -61,3 +73,29 @@ export async function closeChatroom(context: Context<"issues.closed", SupportedE } } +export async function reOpenChatroom(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { + const { config, logger, adapters: { supabase: { chats } } } = context; + const bot = TelegramBotSingleton.getInstance().getBot(); + const title = context.payload.issue.title + const { issue, repository } = context.payload; + const { full_name } = repository; + const [owner, repo] = full_name.split("/"); + + logger.info(`Reopening chatroom for issue ${title}`); + + const chatroom = await chats.getChatByTaskNodeId(issue.node_id) as Chat + + if (!chatroom) { + return { status: 404, reason: "chatroom_not_found" }; + } + + try { + await bot.api?.reopenForumTopic(config.supergroupChatId, chatroom.chatId); + await chats.updateChatStatus("open", issue.node_id); + await addCommentToIssue(context, `Workroom reopened for issue ${title}`, owner, repo, issue.number); + return { status: 200, reason: "chatroom_reopened" }; + } catch (er) { + await addCommentToIssue(context, logger.error(`Failed to reopen chatroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); + return { status: 500, reason: "chatroom_reopening_failed" }; + } +} From 2b46d55a8dc8f93c7f2d29fd2eb35170fa3306f1 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 2 Sep 2024 16:28:37 +0100 Subject: [PATCH 12/76] chore: fix bot_admins schema, use workroom vs chatroom names --- src/handlers/callbacks-proxy.ts | 8 +-- .../github/utils/add-comment-to-issues.ts | 5 +- src/handlers/github/workrooms.ts | 71 ++++++++++--------- src/types/env.ts | 5 +- src/utils/get-deep-value.ts | 10 ++- 5 files changed, 51 insertions(+), 48 deletions(-) diff --git a/src/handlers/callbacks-proxy.ts b/src/handlers/callbacks-proxy.ts index de5f5fa..b7fe297 100644 --- a/src/handlers/callbacks-proxy.ts +++ b/src/handlers/callbacks-proxy.ts @@ -1,5 +1,5 @@ import { Context, SupportedEvents, SupportedEventsU } from "../types"; -import { closeChatroom, createChatroom, reOpenChatroom } from "./github/workrooms"; +import { closeWorkroom, createWorkroom, reOpenWorkroom } from "./github/workrooms"; export type CallbackResult = { status: 200 | 201 | 204 | 404 | 500, reason: string; content?: string | Record }; @@ -49,13 +49,13 @@ function handleCallback(callback: Function, context: Context) { */ const callbacks: ProxyCallbacks = { "issues.labeled": [ - createChatroom, + createWorkroom, ], "issues.closed": [ - closeChatroom + closeWorkroom ], "issues.reopened": [ - reOpenChatroom + reOpenWorkroom ] }; diff --git a/src/handlers/github/utils/add-comment-to-issues.ts b/src/handlers/github/utils/add-comment-to-issues.ts index fa011a6..ecd135f 100644 --- a/src/handlers/github/utils/add-comment-to-issues.ts +++ b/src/handlers/github/utils/add-comment-to-issues.ts @@ -1,11 +1,14 @@ import { Context } from "#root/types/context.js"; import { getDeepValue } from "#root/utils/get-deep-value.js"; +/** + * Ideally pass in owner, repo, and issueNumber, but if not provided, + * attempt to get them from the context. + */ export async function addCommentToIssue(context: Context, msg: string, owner?: string, repo?: string, issueNumber?: number) { const { logger, octokit } = context; logger.info(`Adding comment to issue ${issueNumber}`); - if (!owner || !repo || !issueNumber) { owner = getDeepValue(context, "payload.repository.owner.login"); repo = getDeepValue(context, "payload.repository.name"); diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts index 7d295c2..b03d882 100644 --- a/src/handlers/github/workrooms.ts +++ b/src/handlers/github/workrooms.ts @@ -5,18 +5,21 @@ import { CallbackResult } from "../callbacks-proxy"; import { addCommentToIssue } from "./utils/add-comment-to-issues"; /** - * V1 specifications for the `createChatroom` feature. + * V1 specifications for the `workrooms` feature. * - * - A "workroom" (chatroom) is created when an issue is labeled. - * - The chatroom is created in a Telegram supergroup as a forum topic, not a new group. - * - The chatroom is associated with the issue by storing the issue's node_id. - * - The chatroom is closed when the issue is closed. - * - The chatroom is closed by closing the forum topic in the supergroup. - * - The chatroom status is updated to "closed" in the database. - * - A comment is added to the issue when the chatroom is created or closed. + * - A workroom is created when an issue is labeled. + * - The workroom is created in a Telegram supergroup as a forum topic, not a new group. + * - The workroom is associated with the issue by storing the issue's node_id. + * - The workroom is closed when the issue is closed. + * - The workroom status is updated to "closed" in the database. + * - A comment is added to the issue when the workroom is created or closed. + * + * V2 specifications: + * + * - Replace the `Bot` api with the `MTProto` api in order to create new group chats. */ -export async function createChatroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { +export async function createWorkroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { const { logger, config, adapters: { supabase: { chats } } } = context; const bot = TelegramBotSingleton.getInstance().getBot(); const title = context.payload.issue.title @@ -24,13 +27,13 @@ export async function createChatroom(context: Context<"issues.labeled", Supporte const { full_name } = repository; const [owner, repo] = full_name.split("/"); - const chatroom = await chats.getChatByTaskNodeId(issue.node_id); + const workroom = await chats.getChatByTaskNodeId(issue.node_id); - if (chatroom) { - return { status: 404, reason: "chatroom_already_exists" }; + if (workroom) { + return { status: 404, reason: "workroom_already_exists" }; } - logger.info(`Creating chatroom for issue ${title}`); + logger.info(`Creating workroom for issue ${title}`); try { const forum = await bot.api?.createForumTopic(config.supergroupChatId, title); @@ -38,15 +41,15 @@ export async function createChatroom(context: Context<"issues.labeled", Supporte await chats.saveChat(forum?.message_thread_id, title, issue.node_id); - return { status: 201, reason: "chatroom_created" }; + return { status: 201, reason: "workroom_created" }; } catch (er) { - await addCommentToIssue(context, logger.error(`Failed to create chatroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); - return { status: 500, reason: "chatroom_creation_failed" }; + await addCommentToIssue(context, logger.error(`Failed to create workroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); + return { status: 500, reason: "workroom_creation_failed" }; } } -export async function closeChatroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { +export async function closeWorkroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { const { logger, config, adapters: { supabase: { chats } } } = context; const bot = TelegramBotSingleton.getInstance().getBot(); const title = context.payload.issue.title @@ -54,26 +57,26 @@ export async function closeChatroom(context: Context<"issues.closed", SupportedE const { full_name } = repository; const [owner, repo] = full_name.split("/"); - logger.info(`Closing chatroom for issue ${title}`); + logger.info(`Closing workroom for issue ${title}`); - const chatroom = await chats.getChatByTaskNodeId(issue.node_id) as Chat + const workroom = await chats.getChatByTaskNodeId(issue.node_id) as Chat - if (!chatroom) { - return { status: 404, reason: "chatroom_not_found" }; + if (!workroom) { + return { status: 404, reason: "workroom_not_found" }; } try { - await bot.api?.closeForumTopic(config.supergroupChatId, chatroom.chatId); + await bot.api?.closeForumTopic(config.supergroupChatId, workroom.chatId); await chats.updateChatStatus("closed", issue.node_id); await addCommentToIssue(context, `Workroom closed for issue ${title}`, owner, repo, issue.number); - return { status: 200, reason: "chatroom_closed" }; + return { status: 200, reason: "workroom_closed" }; } catch (er) { - await addCommentToIssue(context, logger.error(`Failed to close chatroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); - return { status: 500, reason: "chatroom_closing_failed" }; + await addCommentToIssue(context, logger.error(`Failed to close workroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); + return { status: 500, reason: "workroom_closing_failed" }; } } -export async function reOpenChatroom(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { +export async function reOpenWorkroom(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { const { config, logger, adapters: { supabase: { chats } } } = context; const bot = TelegramBotSingleton.getInstance().getBot(); const title = context.payload.issue.title @@ -81,21 +84,21 @@ export async function reOpenChatroom(context: Context<"issues.reopened", Support const { full_name } = repository; const [owner, repo] = full_name.split("/"); - logger.info(`Reopening chatroom for issue ${title}`); + logger.info(`Reopening workroom for issue ${title}`); - const chatroom = await chats.getChatByTaskNodeId(issue.node_id) as Chat + const workroom = await chats.getChatByTaskNodeId(issue.node_id) as Chat - if (!chatroom) { - return { status: 404, reason: "chatroom_not_found" }; + if (!workroom) { + return { status: 404, reason: "workroom_not_found" }; } try { - await bot.api?.reopenForumTopic(config.supergroupChatId, chatroom.chatId); + await bot.api?.reopenForumTopic(config.supergroupChatId, workroom.chatId); await chats.updateChatStatus("open", issue.node_id); await addCommentToIssue(context, `Workroom reopened for issue ${title}`, owner, repo, issue.number); - return { status: 200, reason: "chatroom_reopened" }; + return { status: 200, reason: "workroom_reopened" }; } catch (er) { - await addCommentToIssue(context, logger.error(`Failed to reopen chatroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); - return { status: 500, reason: "chatroom_reopening_failed" }; + await addCommentToIssue(context, logger.error(`Failed to reopen workroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); + return { status: 500, reason: "workroom_reopening_failed" }; } } diff --git a/src/types/env.ts b/src/types/env.ts index 01fd55c..1f86fdf 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -24,10 +24,9 @@ export const env = T.Object({ BOT_WEBHOOK: T.String(), BOT_WEBHOOK_SECRET: T.String(), SERVER_HOST: T.String(), - SERVER_PORT: T.Transform(T.Union([T.String(), T.Number()])).Decode((str) => Number(str)).Encode((num) => num.toString()), - BOT_ADMINS: T.Transform(T.Union([T.String(), T.Array(T.String())])).Decode((str) => Array.isArray(str) ? str.map(Number) : [Number(str)]).Encode((arr) => arr.map(String)), + SERVER_PORT: T.Transform(T.Unknown()).Decode((str) => Number(str)).Encode((num) => num.toString()), + BOT_ADMINS: T.Transform(T.Unknown()).Decode((str) => Array.isArray(str) ? str.map(Number) : [Number(str)]).Encode((arr) => arr.toString()), ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))), - SUPABASE_URL: T.String(), SUPABASE_KEY: T.String(), }); diff --git a/src/utils/get-deep-value.ts b/src/utils/get-deep-value.ts index 2eceb6b..9c7fa52 100644 --- a/src/utils/get-deep-value.ts +++ b/src/utils/get-deep-value.ts @@ -1,18 +1,16 @@ /** - * While hacky, this is probably the best way to handle our use case. + * While hacky, this is probably the best way to handle our use case + * and is cleaner than countless "for-in" and "if" statements. * * This function is a utility that allows us to access deeply nested properties in an object * primarily for use with the context.payload object. It should not be overused and the developer * should be aware of the potential performance implications of using this function. * * Example usage: - * getDeepValue(context, "payload.repository.owner.login") will return the owner - * getDeepValue(context, ["payload", "repository", "owner", "login"]) will return the owner * - * @param obj The object to access the property from - * @param path The path to the property, either as a string or an array of strings - * @returns The value of the property if it exists, or undefined if it does not + * - `getDeepValue(context, "payload.repository.owner.login")` will return the owner + * - `getDeepValue(context, ["payload", "repository", "owner", "login"])` will return the owner */ export function getDeepValue(obj: T, path: K | K[]) { if (!obj || !path) return undefined; From bf8dee418132a1f58ff6a9ab59734d2f2436de93 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 2 Sep 2024 18:13:43 +0100 Subject: [PATCH 13/76] fix: proxy usage, event support for labeled/close/reopen with storage --- manifest.json | 5 ++++- src/adapters/supabase/helpers/chats.ts | 24 ++++++++++++++--------- src/bot/index.ts | 4 ++-- src/handlers/callbacks-proxy.ts | 27 ++++++++++++-------------- src/handlers/github-webhook.ts | 5 ++++- src/handlers/github/workrooms.ts | 5 ++--- src/plugin.ts | 8 +++----- src/utils/plugin-context-single.ts | 2 +- src/worker.ts | 5 ++++- 9 files changed, 47 insertions(+), 38 deletions(-) diff --git a/manifest.json b/manifest.json index 9efc71f..d91848e 100644 --- a/manifest.json +++ b/manifest.json @@ -2,6 +2,9 @@ "name": "ts-template", "description": "ts-template for Ubiquibot plugins.", "ubiquity:listeners": [ - "issues.opened" + "issues.opened", + "issues.labeled", + "issues.closed", + "issues.reopened" ] } \ No newline at end of file diff --git a/src/adapters/supabase/helpers/chats.ts b/src/adapters/supabase/helpers/chats.ts index c2ac8e3..c34a00f 100644 --- a/src/adapters/supabase/helpers/chats.ts +++ b/src/adapters/supabase/helpers/chats.ts @@ -47,9 +47,9 @@ export class Chats extends Super { async saveChat(chatId: number, chatName: string, taskNodeId: string) { - const { data, error } = (await this.supabase.from("chats").upsert({ chatId, chatName, taskNodeId })) as { data: unknown; error: unknown }; - if (error || !data) { - this.context.logger.error("Failed to save chat", { chatId, chatName }); + const { data, error } = (await this.supabase.from("chats").insert([{ chatId, chatName, taskNodeId, status: "open" }]) as { data: unknown; error: unknown }); + if (error) { + this.context.logger.error("Failed to save chat", { chatId, chatName, taskNodeId, er: error }); } else { this.context.logger.info("Successfully saved chat", { chatId, chatName }); } @@ -80,13 +80,19 @@ export class Chats extends Super { } async getChatByTaskNodeId(taskNodeId: string) { - const { data, error } = (await this.supabase.from("chats").select("*").eq("taskNodeId", taskNodeId).single()) as { data: unknown; error: unknown }; - if (error || !data) { - this.context.logger.error("No chat found", { taskNodeId }); - } else { - this.context.logger.info("Successfully fetched chat", { taskNodeId }); + try { + const { data, error } = await this.supabase.from("chats").select("*").eq("taskNodeId", taskNodeId).single() + if (error || !data) { + this.context.logger.error("No chat found", { taskNodeId }); + } else { + this.context.logger.info("Successfully fetched chat", { taskNodeId }); + } + + return data; + } catch (e) { + console.error(e) + throw new Error("Failed to fetch chat by task node id") } - return data; } } \ No newline at end of file diff --git a/src/bot/index.ts b/src/bot/index.ts index 197ac36..76e672c 100644 --- a/src/bot/index.ts +++ b/src/bot/index.ts @@ -47,7 +47,7 @@ export function createBot(token: string, dependencies: Dependencies, options: Op }) const protectedBot = bot.errorBoundary(errorHandler) - // // Middlewares + // // createForumsFeature bot.api.config.use(parseMode('HTML')) protectedBot.use(autoChatAction(bot.api)) @@ -60,7 +60,7 @@ export function createBot(token: string, dependencies: Dependencies, options: Op protectedBot.use(adminFeature) protectedBot.use(userIdFeature) protectedBot.use(chatIdFeature) - protectedBot.use(createForumsFeature) + // protectedBot.use(createForumsFeature) // if (isMultipleLocales) // protectedBot.use(languageFeature) diff --git a/src/handlers/callbacks-proxy.ts b/src/handlers/callbacks-proxy.ts index b7fe297..055eb65 100644 --- a/src/handlers/callbacks-proxy.ts +++ b/src/handlers/callbacks-proxy.ts @@ -20,7 +20,7 @@ export type CallbackResult = { status: 200 | 201 | 204 | 404 | 500, reason: stri * ``` */ -type ProxyCallbacks = Partial; +type ProxyCallbacks = ProxyTypeHelper; type ProxyTypeHelper = { [K in SupportedEventsU]: Array<(context: Context) => Promise>; }; @@ -47,7 +47,7 @@ function handleCallback(callback: Function, context: Context) { * callback in an array. This design allows for extensibility and flexibility, enabling * us to add more callbacks for a particular event without modifying the core logic. */ -const callbacks: ProxyCallbacks = { +const callbacks = { "issues.labeled": [ createWorkroom, ], @@ -57,7 +57,7 @@ const callbacks: ProxyCallbacks = { "issues.reopened": [ reOpenWorkroom ] -}; +} as ProxyCallbacks; /** * The `proxyCallbacks` function returns a Proxy object that intercepts access to the @@ -75,24 +75,21 @@ const callbacks: ProxyCallbacks = { * callbacks based on the event type, ensuring that the correct context is passed to * each callback. */ -export function proxyCallbacks({ logger }: Context) { +export function proxyCallbacks(context: Context): ProxyCallbacks { return new Proxy(callbacks, { get(target, prop: SupportedEventsU) { - return async (context: Context) => { - if (!target[prop]) { - logger.info(`No callbacks found for event ${prop}`); - return { status: 204, reason: "skipped" }; - } + if (!target[prop]) { + context.logger.info(`No callbacks found for event ${prop}`); + return { status: 204, reason: "skipped" }; + } + return (async () => { try { - for (const callback of target[prop]) { - await handleCallback(callback, context); - } - // @TODO: better handling for returning the outcome of multiple callbacks + return await Promise.all(target[prop].map((callback) => handleCallback(callback, context))); } catch (er) { - logger.error(`Failed to handle event ${prop}`, { er }); + context.logger.error(`Failed to handle event ${prop}`, { er }); return { status: 500, reason: "failed" }; } - }; + })(); }, }); } diff --git a/src/handlers/github-webhook.ts b/src/handlers/github-webhook.ts index 8c2a4de..7f8fdb6 100644 --- a/src/handlers/github-webhook.ts +++ b/src/handlers/github-webhook.ts @@ -21,7 +21,10 @@ export async function handleGithubWebhook(request: Request, env: Env): Promise, }; diff --git a/src/worker.ts b/src/worker.ts index ef3247f..a6f551d 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -72,7 +72,10 @@ export default { }); } - return new Response("OK", { status: 200, headers: { "content-type": "application/json" } }); + return new Response(JSON.stringify({ success: true }), { + status: 200, + headers: { "content-type": "application/json" }, + }); } catch (err) { return handleUncaughtError(err); } From c6e7af5586581f10409bc48610ad9b91624cbea8 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Tue, 3 Sep 2024 18:29:36 +0100 Subject: [PATCH 14/76] chore: test --- .github/workflows/create-chat.yml | 60 ++++++++++++++++++++++++++ package.json | 6 +-- src/types/env.ts | 2 + src/utils/logger.ts | 39 ----------------- src/workflows/README.md | 6 +++ src/workflows/bot.ts | 68 ++++++++++++++++++++++++++++++ src/workflows/create-chat/index.ts | 19 +++++++++ 7 files changed, 157 insertions(+), 43 deletions(-) create mode 100644 .github/workflows/create-chat.yml delete mode 100644 src/utils/logger.ts create mode 100644 src/workflows/README.md create mode 100644 src/workflows/bot.ts create mode 100644 src/workflows/create-chat/index.ts diff --git a/.github/workflows/create-chat.yml b/.github/workflows/create-chat.yml new file mode 100644 index 0000000..2508b7a --- /dev/null +++ b/.github/workflows/create-chat.yml @@ -0,0 +1,60 @@ +name: "create-telegram-chat" + +on: + repository_dispatch: + types: [create-telegram-chat] + +jobs: + create-telegram-chat: + name: "Create Telegram Chat" + runs-on: ubuntu-latest + permissions: write-all + env: + BOT_TOKEN: ${{ secrets.BOT_TOKEN }} + BOT_MODE: ${{ secrets.BOT_MODE }} + BOT_ADMINS: ${{ secrets.BOT_ADMINS }} + BOT_WEBHOOK: ${{ secrets.BOT_WEBHOOK }} + BOT_WEBHOOK_SECRET: ${{ secrets.BOT_WEBHOOK_SECRET }} + + TELEGRAM_APP_ID: ${{ secrets.TELEGRAM_APP_ID }} + TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }} + + SUPABASE_URL: ${{ secrets.SUPABASE_URL }} + SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} + + LOG_LEVEL: ${{ secrets.LOG_LEVEL }} + DEBUG: ${{ secrets.DEBUG }} + SERVER_HOST: ${{ secrets.SERVER_HOST }} + SERVER_PORT: ${{ secrets.SERVER_PORT }} + + steps: + - uses: actions/checkout@v4 + + - name: setup node + uses: actions/setup-node@v4 + with: + node-version: "20.10.0" + + - name: install dependencies + run: yarn + + - name: execute directive + run: npx tsx ./src/workflows/create-chat/index.ts + id: create-telegram-chat + env: + BOT_TOKEN: ${{ secrets.BOT_TOKEN }} + BOT_MODE: ${{ secrets.BOT_MODE }} + BOT_ADMINS: ${{ secrets.BOT_ADMINS }} + BOT_WEBHOOK: ${{ secrets.BOT_WEBHOOK }} + BOT_WEBHOOK_SECRET: ${{ secrets.BOT_WEBHOOK_SECRET }} + + TELEGRAM_APP_ID: ${{ secrets.TELEGRAM_APP_ID }} + TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }} + + SUPABASE_URL: ${{ secrets.SUPABASE_URL }} + SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} + + LOG_LEVEL: ${{ secrets.LOG_LEVEL }} + DEBUG: ${{ secrets.DEBUG }} + SERVER_HOST: ${{ secrets.SERVER_HOST }} + SERVER_PORT: ${{ secrets.SERVER_PORT }} \ No newline at end of file diff --git a/package.json b/package.json index 347beff..ad8d89b 100644 --- a/package.json +++ b/package.json @@ -24,9 +24,7 @@ "worker": "wrangler dev --env dev --port 3000", "dev": "tsc-watch --onSuccess \"tsx ./src/main.ts\"", "start": "tsx ./src/main.ts", - "deploy": "wrangler deploy --minify src/main.ts", - "build": "npx tsx build/esbuild-build.ts", - "serve": "npx tsx build/esbuild-server.ts" + "deploy": "wrangler deploy --minify src/main.ts" }, "keywords": [ "typescript", @@ -111,4 +109,4 @@ ] }, "packageManager": "yarn@1.22.22" -} +} \ No newline at end of file diff --git a/src/types/env.ts b/src/types/env.ts index 1f86fdf..d6164eb 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -29,6 +29,8 @@ export const env = T.Object({ ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))), SUPABASE_URL: T.String(), SUPABASE_KEY: T.String(), + TELEGRAM_APP_ID: T.Transform(T.Unknown()).Decode((str) => Number(str)).Encode((num) => num.toString()), + TELEGRAM_API_HASH: T.String(), }); /** diff --git a/src/utils/logger.ts b/src/utils/logger.ts deleted file mode 100644 index 8a25fd1..0000000 --- a/src/utils/logger.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { LogReturn, Logs, Metadata } from "@ubiquity-dao/ubiquibot-logger"; - -export class Logger extends Logs { - updateId: number | string; - - constructor(updateId: number | string) { - super("verbose"); - this.updateId = updateId; - } - - storeUpdateId(updateId: number | string): Logger { - this.updateId = updateId; - return this; - } - - debug(log: string, metadata?: Metadata): LogReturn { - return super.debug(`[update_id: ${this.updateId}] ${log}`, metadata); - } - - error(log: string, metadata?: Metadata): LogReturn { - return super.error(`[update_id: ${this.updateId}] ${log}`, metadata); - } - - fatal(log: string, metadata?: Metadata): LogReturn { - return super.fatal(`[update_id: ${this.updateId}] ${log}`, metadata); - } - - info(log: string, metadata?: Metadata): LogReturn { - return super.info(`[update_id: ${this.updateId}] ${log}`, metadata); - } - - ok(log: string, metadata?: Metadata): LogReturn { - return super.ok(`[update_id: ${this.updateId}] ${log}`, metadata); - } - - verbose(log: string, metadata?: Metadata): LogReturn { - return super.verbose(`[update_id: ${this.updateId}] ${log}`, metadata); - } -} \ No newline at end of file diff --git a/src/workflows/README.md b/src/workflows/README.md new file mode 100644 index 0000000..4d5c116 --- /dev/null +++ b/src/workflows/README.md @@ -0,0 +1,6 @@ +These are intended to be an extension of the worker's functionalities due to the restrictions of Cloudflare workers. They are not meant to be a replacement for the worker itself. They are meant to be used in conjunction with the worker. + +The worker should `repository_dispatch` to the workflow to trigger it. The workflow will then run it's logic and return the result to the worker if necessary. + + +... \ No newline at end of file diff --git a/src/workflows/bot.ts b/src/workflows/bot.ts new file mode 100644 index 0000000..ed4daac --- /dev/null +++ b/src/workflows/bot.ts @@ -0,0 +1,68 @@ +import { Context } from '#root/types/context.js'; +import { TelegramClient } from 'telegram'; +import { Api } from 'telegram/tl'; +import { MemorySession } from 'telegram/sessions'; +import { TelegramClientParams } from 'telegram/client/telegramBaseClient'; + +export class MtProtoSingleton { + private static instance: MtProtoSingleton; + private static client: TelegramClient; + private static api: typeof Api; + + private constructor() { } + + static async initialize(env: Context["env"]) { + if (!MtProtoSingleton.instance) { + MtProtoSingleton.instance = new MtProtoSingleton(); + MtProtoSingleton.api = Api; + MtProtoSingleton.client = await mtProtoInit(env, MtProtoSingleton.api); + } + return MtProtoSingleton.instance; + } + + static getInstance(env: Context["env"]) { + if (!MtProtoSingleton.instance) { + return this.initialize(env) + } + return MtProtoSingleton.instance; + } + + getClient() { + return MtProtoSingleton.client; + } + + getApi() { + return MtProtoSingleton.api; + } +} + +async function mtProtoInit(env: Context["env"], api: typeof Api) { + const { TELEGRAM_API_HASH, TELEGRAM_APP_ID, BOT_TOKEN } = env + + if (!TELEGRAM_API_HASH || !TELEGRAM_APP_ID || !BOT_TOKEN) { + throw new Error("Missing required environment variables for Telegram API") + } + + const session = new MemorySession(); + session.save(); + + const clientParams: TelegramClientParams = { + connectionRetries: 5, + } + + const client = new TelegramClient( + session, + TELEGRAM_APP_ID, + TELEGRAM_API_HASH, + clientParams + ); + client.invoke(new api.auth.ImportBotAuthorization({ + apiId: TELEGRAM_APP_ID, + apiHash: TELEGRAM_API_HASH, + botAuthToken: BOT_TOKEN, + })); + + await client.connect(); + + return client; +} \ No newline at end of file diff --git a/src/workflows/create-chat/index.ts b/src/workflows/create-chat/index.ts new file mode 100644 index 0000000..266fffb --- /dev/null +++ b/src/workflows/create-chat/index.ts @@ -0,0 +1,19 @@ +import { Context } from "#root/types/context"; +import { MtProtoSingleton } from "../bot"; + +export async function createChat(env: Context["env"], chatName: string) { + const mtProto = await MtProtoSingleton.getInstance(env); + const client = mtProto.getClient(); + const api = mtProto.getApi(); + console.log("Creating chat with name: ", chatName); + const chat = await client.invoke( + new api.channels.CreateChannel({ + title: chatName, + broadcast: false, + }) + ); + + console.log("Chat created: ", chat); + + return chat; +} From a94a2e33ae53a61ae48d69ae459ca318900fb7ea Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:33:44 +0100 Subject: [PATCH 15/76] chore: workflow functions --- .../README.md | 0 src/{workflows => workflow-functions}/bot.ts | 5 ++++ src/workflow-functions/create-chat.ts | 29 +++++++++++++++++++ src/workflow-functions/index.ts | 5 ++++ src/workflows/create-chat/index.ts | 19 ------------ 5 files changed, 39 insertions(+), 19 deletions(-) rename src/{workflows => workflow-functions}/README.md (100%) rename src/{workflows => workflow-functions}/bot.ts (89%) create mode 100644 src/workflow-functions/create-chat.ts create mode 100644 src/workflow-functions/index.ts delete mode 100644 src/workflows/create-chat/index.ts diff --git a/src/workflows/README.md b/src/workflow-functions/README.md similarity index 100% rename from src/workflows/README.md rename to src/workflow-functions/README.md diff --git a/src/workflows/bot.ts b/src/workflow-functions/bot.ts similarity index 89% rename from src/workflows/bot.ts rename to src/workflow-functions/bot.ts index ed4daac..1ef4593 100644 --- a/src/workflows/bot.ts +++ b/src/workflow-functions/bot.ts @@ -4,6 +4,11 @@ import { Api } from 'telegram/tl'; import { MemorySession } from 'telegram/sessions'; import { TelegramClientParams } from 'telegram/client/telegramBaseClient'; +/** + * This is a different client from the worker instance. This requires a Node + * environment to run and is used to interact with the Telegram API as + * opposed to just the Bot API that the worker instance uses. + */ export class MtProtoSingleton { private static instance: MtProtoSingleton; private static client: TelegramClient; diff --git a/src/workflow-functions/create-chat.ts b/src/workflow-functions/create-chat.ts new file mode 100644 index 0000000..fd25d82 --- /dev/null +++ b/src/workflow-functions/create-chat.ts @@ -0,0 +1,29 @@ +import { Context, SupportedEvents } from "#root/types/context"; +import { CallbackResult } from "#root/types/proxy.js"; +import { MtProtoSingleton } from "./bot"; + +export async function createChat(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { + try { + const { payload, env } = context; + const chatName = payload.issue.title; + + const mtProto = await MtProtoSingleton.getInstance(env); + const client = mtProto.getClient(); + const api = mtProto.getApi(); + console.log("Creating chat with name: ", chatName); + const chat = await client.invoke( + new api.channels.CreateChannel({ + title: chatName, + broadcast: false, + }) + ); + + console.log("Chat created: ", chat); + + return { status: 200, reason: "chat_created" }; + } catch (er) { + context.logger.error("Failed to create chat", { er }); + return { status: 500, reason: "chat_creation_failed", content: { error: er } }; + } + +} diff --git a/src/workflow-functions/index.ts b/src/workflow-functions/index.ts new file mode 100644 index 0000000..6e8973d --- /dev/null +++ b/src/workflow-functions/index.ts @@ -0,0 +1,5 @@ +export const WORKFLOW_FUNCTIONS = { + CREATE_CHAT: "create-telegram-chat", +} as const; + +export type WorkflowFunction = typeof WORKFLOW_FUNCTIONS[keyof typeof WORKFLOW_FUNCTIONS]; \ No newline at end of file diff --git a/src/workflows/create-chat/index.ts b/src/workflows/create-chat/index.ts deleted file mode 100644 index 266fffb..0000000 --- a/src/workflows/create-chat/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Context } from "#root/types/context"; -import { MtProtoSingleton } from "../bot"; - -export async function createChat(env: Context["env"], chatName: string) { - const mtProto = await MtProtoSingleton.getInstance(env); - const client = mtProto.getClient(); - const api = mtProto.getApi(); - console.log("Creating chat with name: ", chatName); - const chat = await client.invoke( - new api.channels.CreateChannel({ - title: chatName, - broadcast: false, - }) - ); - - console.log("Chat created: ", chat); - - return chat; -} From 36124fa774a4aefe1b1bf63c90f73c262bb2b0b5 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:35:37 +0100 Subject: [PATCH 16/76] chore: typeguards and error helpers --- src/plugin.ts | 22 +++------------------- src/types/typeguards.ts | 10 ++++++++++ src/utils/errors.ts | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/plugin.ts b/src/plugin.ts index 7f84716..e858f2d 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -2,32 +2,16 @@ import { Env, PluginInputs } from "./types"; import { Context } from "./types"; import { PluginContext } from "./utils/plugin-context-single"; import { proxyCallbacks } from "./handlers/callbacks-proxy"; -import { LogReturn } from "@ubiquity-dao/ubiquibot-logger"; -import { addCommentToIssue } from "./handlers/github/utils/add-comment-to-issues"; +import { bubbleUpErrorComment, sanitizeMetadata } from "./utils/errors"; export async function runPlugin(context: Context) { - const { logger, eventName } = context; + const { eventName } = context; try { return proxyCallbacks(context)[eventName] } catch (err) { - let errorMessage; - if (err instanceof LogReturn) { - errorMessage = err; - } else if (err instanceof Error) { - errorMessage = context.logger.error(err.message, { error: err }); - } else { - errorMessage = context.logger.error("An error occurred", { err }); - } - await addCommentToIssue(context, `${errorMessage?.logMessage.diff}\n`); + return bubbleUpErrorComment(context, err) } - - logger.error(`Unsupported event: ${eventName}`); -} - - -function sanitizeMetadata(obj: LogReturn["metadata"]): string { - return JSON.stringify(obj, null, 2).replace(//g, ">").replace(/--/g, "--"); } /** diff --git a/src/types/typeguards.ts b/src/types/typeguards.ts index d25d056..84c1a9d 100644 --- a/src/types/typeguards.ts +++ b/src/types/typeguards.ts @@ -1,6 +1,7 @@ import { Update } from "@grammyjs/types"; import { Context } from "./context"; import { PluginInputs } from "./plugin-inputs"; +import { WORKFLOW_FUNCTIONS } from "../workflow-functions"; export function isIssueOpenedEvent(context: Context): context is Context<"issues.opened"> { return context.eventName === "issues.opened"; @@ -21,3 +22,12 @@ export function isGithubPayload(inputs: any): inputs is PluginInputs { return false; } } + + +export function isIssueLabeledEvent(context: Context): context is Context<"issues.labeled"> { + return context.eventName === "issues.labeled"; +} + +export function isWorkflowFunction(event: string): event is keyof typeof WORKFLOW_FUNCTIONS { + return Object.keys(WORKFLOW_FUNCTIONS).includes(event); +} \ No newline at end of file diff --git a/src/utils/errors.ts b/src/utils/errors.ts index 921330e..530f9de 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -1,6 +1,24 @@ +import { LogReturn } from "@ubiquity-dao/ubiquibot-logger"; +import { Context } from "../types"; +import { addCommentToIssue } from "#root/handlers/github/utils/add-comment-to-issues.js"; export function handleUncaughtError(error: unknown) { console.error(error); const status = 500; return new Response(JSON.stringify({ error }), { status: status, headers: { "content-type": "application/json" } }); +} +export function sanitizeMetadata(obj: LogReturn["metadata"]): string { + return JSON.stringify(obj, null, 2).replace(//g, ">").replace(/--/g, "--"); +} + +export async function bubbleUpErrorComment(context: Context, err: unknown) { + let errorMessage; + if (err instanceof LogReturn) { + errorMessage = err; + } else if (err instanceof Error) { + errorMessage = context.logger.error(err.message, { error: err }); + } else { + errorMessage = context.logger.error("An error occurred", { err }); + } + await addCommentToIssue(context, `${errorMessage?.logMessage.diff}\n`); } \ No newline at end of file From 43e13ab640502d1e5f71df301a62939c78a0d306 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:36:34 +0100 Subject: [PATCH 17/76] chore: proxy types and new env vars --- src/types/env.ts | 2 ++ src/types/proxy.ts | 52 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/types/proxy.ts diff --git a/src/types/env.ts b/src/types/env.ts index d6164eb..669baee 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -31,6 +31,8 @@ export const env = T.Object({ SUPABASE_KEY: T.String(), TELEGRAM_APP_ID: T.Transform(T.Unknown()).Decode((str) => Number(str)).Encode((num) => num.toString()), TELEGRAM_API_HASH: T.String(), + APP_ID: T.Transform(T.Unknown()).Decode((str) => Number(str)).Encode((num) => num.toString()), + APP_PRIVATE_KEY: T.String(), }); /** diff --git a/src/types/proxy.ts b/src/types/proxy.ts new file mode 100644 index 0000000..c477765 --- /dev/null +++ b/src/types/proxy.ts @@ -0,0 +1,52 @@ +import { WorkflowFunction } from "../workflow-functions"; +import { Context, SupportedEvents, SupportedEventsU } from "./context"; + +export type CallbackResult = { status: 200 | 201 | 204 | 404 | 500, reason: string; content?: string | Record }; + +/** + * The `Context` type is a generic type defined as `Context`, + * where `TEvent` is a string representing the event name (e.g., "issues.labeled") + * and `TPayload` is the webhook payload type for that event, derived from + * the `SupportedEvents` type map. + * + * The `ProxyCallbacks` object is cast to allow optional callbacks + * for each event type. This is useful because not all events may have associated callbacks. + * As opposed to Partial which could mean an undefined object. + * + * The expected function signature for callbacks looks like this: + * + * ```typescript + * fn(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise + * ``` + */ + +type ProxyTypeHelper = { + [K in SupportedEventsU]: Array<(context: Context) => Promise>; +}; +export type ProxyCallbacks = ProxyTypeHelper; + +/** + * Was unable to figure a way to make this work elegantly to avoid having to use + * typeguards in the workflow functions like we have in `ProxyCallbacks`. + * + * Something in the lines of: + * Each callback would define a generic type `T` that would be just that event type as to + * restrict inference in Context to only that webhook although it infers all payloads in + * all of my attempts. + * + * Would be handy as we could avoid having to use typeguards in the workflow functions. + */ +type WorkflowTypeHelper = { + [K in SupportedEventsU]: { + [P in WorkflowFunction]: Array<(context: Context) => Promise>; + } +}; + +/** + * * The expected function signature for callbacks looks like this: + * + * ```typescript + * fn(context: Context): Promise + * ``` + */ +export type WorkflowCallbacks = WorkflowTypeHelper; \ No newline at end of file From d266dfd531040a7ed6ef4be57168157490b7e98a Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:42:55 +0100 Subject: [PATCH 18/76] chore: repo dispatch approach --- src/handlers/callbacks-proxy.ts | 76 ++++++++++++++++++---------- src/handlers/github/workrooms.ts | 31 ++---------- src/handlers/repository-dispatch.ts | 44 ++++++++++++++++ src/helpers/authenticated-octokit.ts | 15 ++++++ src/utils/plugin-context-single.ts | 4 ++ src/workflow-entry.ts | 44 +++++++++------- 6 files changed, 143 insertions(+), 71 deletions(-) create mode 100644 src/handlers/repository-dispatch.ts create mode 100644 src/helpers/authenticated-octokit.ts diff --git a/src/handlers/callbacks-proxy.ts b/src/handlers/callbacks-proxy.ts index 055eb65..c1646c5 100644 --- a/src/handlers/callbacks-proxy.ts +++ b/src/handlers/callbacks-proxy.ts @@ -1,29 +1,8 @@ -import { Context, SupportedEvents, SupportedEventsU } from "../types"; +import { ProxyCallbacks, WorkflowCallbacks } from "#root/types/proxy.js"; +import { Context, SupportedEventsU } from "../types"; +import { createChat } from "../workflow-functions/create-chat"; import { closeWorkroom, createWorkroom, reOpenWorkroom } from "./github/workrooms"; - -export type CallbackResult = { status: 200 | 201 | 204 | 404 | 500, reason: string; content?: string | Record }; - -/** - * The `Context` type is a generic type defined as `Context`, - * where `TEvent` is a string representing the event name (e.g., "issues.labeled") - * and `TPayload` is the webhook payload type for that event, derived from - * the `SupportedEvents` type map. - * - * The `ProxyCallbacks` type is defined using `Partial` to allow - * optional callbacks for each event type. This is useful because not all events - * may have associated callbacks. - * - * The expected function signature for callbacks looks like this: - * - * ```typescript - * fn(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise - * ``` - */ - -type ProxyCallbacks = ProxyTypeHelper; -type ProxyTypeHelper = { - [K in SupportedEventsU]: Array<(context: Context) => Promise>; -}; +import { WorkflowFunction } from "../workflow-functions"; /** * Why do we need this wrapper function? @@ -39,7 +18,6 @@ type ProxyTypeHelper = { function handleCallback(callback: Function, context: Context) { return callback(context); } - /** * The `callbacks` object defines an array of callback functions for each supported event type. * @@ -93,3 +71,49 @@ export function proxyCallbacks(context: Context): ProxyCallbacks { }, }); } + +/** + * These are function which get dispatched by this worker to fire off workflows + * in the repository. We enter through the main `compute.yml` just like a typical + * action plugin would, we forward the same payload that the worker received to + * the workflow the same way that the kernel does. + * + * - First event fires, `issues.labeled` and the worker catches it. + * - The worker then dispatches a workflow to `compute.yml` with the event name as the input. + * - The workflow receives a `issues.labeled` payload but eventName is now WorkflowFunction (`create-telegram-chat`). + * - The workflow then runs the `createChat` function which needs a node env to run. + * + * I.e we're essentially running the first dual action/worker plugin which is + * ideal for telegram-bot as it's a bot that needs to be able to be super flexible. + * + * TODO: Might not need to do specify the workflow function and instead just pass the payload? + */ +const workflowCallbacks = { + "issues.labeled": { + "create-telegram-chat": [ + createChat + ] + } +} as WorkflowCallbacks; + +export function proxyWorkflowCallbacks(context: Context): WorkflowCallbacks { + return new Proxy(workflowCallbacks, { + get(target, prop: WorkflowFunction) { + return (async () => { + try { + return await Promise.all(Object.keys(target).map((event) => { + const eventCallbacks = target[event as SupportedEventsU][prop]; + if (!eventCallbacks) { + context.logger.info(`No callbacks found for event ${event}`); + return { status: 204, reason: "skipped" }; + } + return Promise.all(eventCallbacks.map((callback) => handleCallback(callback, context))); + })); + } catch (er) { + context.logger.error(`Failed to handle event ${prop}`, { er }); + return { status: 500, reason: "failed" }; + } + })(); + }, + }); +} diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts index d934e6c..9fff909 100644 --- a/src/handlers/github/workrooms.ts +++ b/src/handlers/github/workrooms.ts @@ -1,7 +1,8 @@ import { Chat } from "#root/adapters/supabase/helpers/chats.js"; +import { CallbackResult } from "#root/types/proxy.js"; import { TelegramBotSingleton } from "#root/utils/telegram-bot-single.js"; import { Context, SupportedEvents } from "../../types"; -import { CallbackResult } from "../callbacks-proxy"; +import { repositoryDispatch } from "../repository-dispatch"; import { addCommentToIssue } from "./utils/add-comment-to-issues"; /** @@ -20,32 +21,8 @@ import { addCommentToIssue } from "./utils/add-comment-to-issues"; */ export async function createWorkroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { - const { logger, config, adapters: { supabase: { chats } } } = context; - const bot = TelegramBotSingleton.getInstance().getBot(); - const title = context.payload.issue.title - const { issue, repository } = context.payload; - const { full_name } = repository; - const [owner, repo] = full_name.split("/"); - - const workroom = await chats.getChatByTaskNodeId(issue.node_id); - - if (workroom) { - logger.debug("Workroom already exists for issue", { title }); - return { status: 404, reason: "workroom_already_exists" }; - } - - logger.info(`Creating workroom for issue ${title}`); - - try { - const forum = await bot.api?.createForumTopic(config.supergroupChatId, title); - await addCommentToIssue(context, `Workroom created: https://t.me/${config.supergroupChatName}/${forum?.message_thread_id}`, owner, repo, issue.number); - await chats.saveChat(forum?.message_thread_id, title, issue.node_id); - return { status: 201, reason: "workroom_created" }; - } catch (er) { - await addCommentToIssue(context, logger.error(`Failed to create workroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); - return { status: 500, reason: "workroom_creation_failed" }; - } - + repositoryDispatch(context, "create-telegram-chat").catch(console.error); + return { status: 200, reason: "workflow_dispatched" }; } export async function closeWorkroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts new file mode 100644 index 0000000..4fdd894 --- /dev/null +++ b/src/handlers/repository-dispatch.ts @@ -0,0 +1,44 @@ +import { getAppOctokit } from "#root/helpers/authenticated-octokit.js"; +import { PluginContext } from "#root/utils/plugin-context-single.js"; +import { Context } from "../types"; +import { WorkflowFunction } from "../workflow-functions"; + +/** + * Used by the worker instance to kick off workflows within it's own repository. + * + * These workflows are extensions of the worker allowing for more complex operations + * to be performed outside of Cloudflare Workers' limitations. + * + * @param env The environment variables for the worker instance. These + * will be taken from the repository's secrets. + * @param args The arguments passed to the workflow. + * + */ + + +export async function repositoryDispatch(context: Context, workflow: WorkflowFunction) { + const inputs = PluginContext.getInstance().getInputs(); + const { logger } = context; + const repository = "telegram--bot"; + const owner = "ubq-testing"; + const branch = "workflows"; + const octokit = await getAppOctokit(context); + + logger.info(`Dispatching workflow function: ${workflow}`); + + /** + * We'll hit the main workflow entry and pass in the same inputs so + * that it essentially runs on the same context as the worker. + */ + return await octokit.rest.actions.createWorkflowDispatch({ + owner, + repo: repository, + workflow_id: "compute.yml", + ref: branch, + inputs: { + ...inputs, + workflowFunction: workflow + } + }); +} + diff --git a/src/helpers/authenticated-octokit.ts b/src/helpers/authenticated-octokit.ts new file mode 100644 index 0000000..51cb49a --- /dev/null +++ b/src/helpers/authenticated-octokit.ts @@ -0,0 +1,15 @@ +import { Octokit } from "@octokit/rest"; +import { Context } from "../types"; + +export async function getAppOctokit(context: Context) { + const { env } = context; + const { APP_ID, APP_PRIVATE_KEY } = env; + const appOctokit = new Octokit({ + auth: { + appId: APP_ID, + privateKey: APP_PRIVATE_KEY, + }, + }); + + return appOctokit; +} \ No newline at end of file diff --git a/src/utils/plugin-context-single.ts b/src/utils/plugin-context-single.ts index 879b683..d210a75 100644 --- a/src/utils/plugin-context-single.ts +++ b/src/utils/plugin-context-single.ts @@ -34,6 +34,10 @@ export class PluginContext { return PluginContext.instance; } + getInputs(): PluginInputs { + return this.inputs; + } + getContext(): Context { const octokit = new Octokit({ auth: this.inputs.authToken }); const ctx: Context = { diff --git a/src/workflow-entry.ts b/src/workflow-entry.ts index b46765e..fc5e774 100644 --- a/src/workflow-entry.ts +++ b/src/workflow-entry.ts @@ -1,9 +1,10 @@ import * as core from "@actions/core"; import * as github from "@actions/github"; -import { Octokit } from "@octokit/rest"; import { Value } from "@sinclair/typebox/value"; -import { envSchema, pluginSettingsSchema, PluginInputs, pluginSettingsValidator } from "./types"; -import { plugin } from "./plugin"; +import { envValidator, pluginSettingsSchema, PluginInputs, pluginSettingsValidator } from "./types"; +import { PluginContext } from "./utils/plugin-context-single"; +import { proxyWorkflowCallbacks } from "./handlers/callbacks-proxy"; +import { bubbleUpErrorComment, sanitizeMetadata } from "./utils/errors"; /** * How a GitHub action executes the plugin. @@ -11,7 +12,7 @@ import { plugin } from "./plugin"; export async function run() { const payload = github.context.payload.inputs; - const env = Value.Decode(envSchema, payload.env); + const env = Value.Decode(envValidator.schema, payload.env); const settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, JSON.parse(payload.settings))); if (!pluginSettingsValidator.test(settings)) { @@ -27,24 +28,31 @@ export async function run() { ref: payload.ref, }; - await plugin(inputs, env); + PluginContext.initialize(inputs, env); - return returnDataToKernel(inputs.authToken, inputs.stateId, {}); -} + const context = PluginContext.getInstance().getContext(); -async function returnDataToKernel(repoToken: string, stateId: string, output: object) { - const octokit = new Octokit({ auth: repoToken }); - await octokit.repos.createDispatchEvent({ - owner: github.context.repo.owner, - repo: github.context.repo.repo, - event_type: "return_data_to_ubiquibot_kernel", - client_payload: { - state_id: stateId, - output: JSON.stringify(output), - }, - }); + try { + return proxyWorkflowCallbacks(context)[inputs.eventName]; + } catch (err) { + return bubbleUpErrorComment(context, err) + } } +// Might use this later to receive data back from it's own workflows +// async function returnDataToKernel(repoToken: string, stateId: string, output: object) { +// const octokit = new Octokit({ auth: repoToken }); +// await octokit.repos.createDispatchEvent({ +// owner: github.context.repo.owner, +// repo: github.context.repo.repo, +// event_type: "return_data_to_ubiquibot_kernel", +// client_payload: { +// state_id: stateId, +// output: JSON.stringify(output), +// }, +// }); +// } + run() .then((result) => { core.setOutput("result", result); From 1c2398096115a0d8148319d0af7c08df6f87a432 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:47:26 +0100 Subject: [PATCH 19/76] chore: remove need to specify workflow function --- src/handlers/callbacks-proxy.ts | 35 +++++++++++---------------- src/handlers/github/workrooms.ts | 2 +- src/handlers/repository-dispatch.ts | 3 +-- src/types/proxy.ts | 8 +----- src/workflow-functions/create-chat.ts | 1 + 5 files changed, 18 insertions(+), 31 deletions(-) diff --git a/src/handlers/callbacks-proxy.ts b/src/handlers/callbacks-proxy.ts index c1646c5..8138c0b 100644 --- a/src/handlers/callbacks-proxy.ts +++ b/src/handlers/callbacks-proxy.ts @@ -1,8 +1,7 @@ -import { ProxyCallbacks, WorkflowCallbacks } from "#root/types/proxy.js"; +import { ProxyCallbacks } from "#root/types/proxy.js"; import { Context, SupportedEventsU } from "../types"; import { createChat } from "../workflow-functions/create-chat"; import { closeWorkroom, createWorkroom, reOpenWorkroom } from "./github/workrooms"; -import { WorkflowFunction } from "../workflow-functions"; /** * Why do we need this wrapper function? @@ -85,30 +84,24 @@ export function proxyCallbacks(context: Context): ProxyCallbacks { * * I.e we're essentially running the first dual action/worker plugin which is * ideal for telegram-bot as it's a bot that needs to be able to be super flexible. - * - * TODO: Might not need to do specify the workflow function and instead just pass the payload? */ const workflowCallbacks = { - "issues.labeled": { - "create-telegram-chat": [ - createChat - ] - } -} as WorkflowCallbacks; + "issues.labeled": [ + createChat + ] +} as ProxyCallbacks; + -export function proxyWorkflowCallbacks(context: Context): WorkflowCallbacks { +export function proxyWorkflowCallbacks(context: Context): ProxyCallbacks { return new Proxy(workflowCallbacks, { - get(target, prop: WorkflowFunction) { + get(target, prop: SupportedEventsU) { + if (!target[prop]) { + context.logger.info(`No callbacks found for event ${prop}`); + return { status: 204, reason: "skipped" }; + } return (async () => { try { - return await Promise.all(Object.keys(target).map((event) => { - const eventCallbacks = target[event as SupportedEventsU][prop]; - if (!eventCallbacks) { - context.logger.info(`No callbacks found for event ${event}`); - return { status: 204, reason: "skipped" }; - } - return Promise.all(eventCallbacks.map((callback) => handleCallback(callback, context))); - })); + return await Promise.all(target[prop].map((callback) => handleCallback(callback, context))); } catch (er) { context.logger.error(`Failed to handle event ${prop}`, { er }); return { status: 500, reason: "failed" }; @@ -116,4 +109,4 @@ export function proxyWorkflowCallbacks(context: Context): WorkflowCallbacks { })(); }, }); -} +} \ No newline at end of file diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts index 9fff909..e5a9833 100644 --- a/src/handlers/github/workrooms.ts +++ b/src/handlers/github/workrooms.ts @@ -21,7 +21,7 @@ import { addCommentToIssue } from "./utils/add-comment-to-issues"; */ export async function createWorkroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { - repositoryDispatch(context, "create-telegram-chat").catch(console.error); + await repositoryDispatch(context, "create-telegram-chat").catch(console.error); return { status: 200, reason: "workflow_dispatched" }; } diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts index 4fdd894..d1c1146 100644 --- a/src/handlers/repository-dispatch.ts +++ b/src/handlers/repository-dispatch.ts @@ -15,7 +15,6 @@ import { WorkflowFunction } from "../workflow-functions"; * */ - export async function repositoryDispatch(context: Context, workflow: WorkflowFunction) { const inputs = PluginContext.getInstance().getInputs(); const { logger } = context; @@ -37,7 +36,7 @@ export async function repositoryDispatch(context: Context, workflow: WorkflowFun ref: branch, inputs: { ...inputs, - workflowFunction: workflow + workflowFunction: workflow // here for the workflow logs, not used in the workflow } }); } diff --git a/src/types/proxy.ts b/src/types/proxy.ts index c477765..2c61c1d 100644 --- a/src/types/proxy.ts +++ b/src/types/proxy.ts @@ -36,11 +36,6 @@ export type ProxyCallbacks = ProxyTypeHelper; * * Would be handy as we could avoid having to use typeguards in the workflow functions. */ -type WorkflowTypeHelper = { - [K in SupportedEventsU]: { - [P in WorkflowFunction]: Array<(context: Context) => Promise>; - } -}; /** * * The expected function signature for callbacks looks like this: @@ -48,5 +43,4 @@ type WorkflowTypeHelper = { * ```typescript * fn(context: Context): Promise * ``` - */ -export type WorkflowCallbacks = WorkflowTypeHelper; \ No newline at end of file + */ \ No newline at end of file diff --git a/src/workflow-functions/create-chat.ts b/src/workflow-functions/create-chat.ts index fd25d82..ca7ef6a 100644 --- a/src/workflow-functions/create-chat.ts +++ b/src/workflow-functions/create-chat.ts @@ -3,6 +3,7 @@ import { CallbackResult } from "#root/types/proxy.js"; import { MtProtoSingleton } from "./bot"; export async function createChat(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { + console.log("Creating chat"); try { const { payload, env } = context; const chatName = payload.issue.title; From fdb01f27611dca48793e97342521981ad469a9ff Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:50:27 +0100 Subject: [PATCH 20/76] chore: deleting files --- .github/workflows/create-chat.yml | 60 ------------------------------- src/types/proxy.ts | 23 +----------- src/types/typeguards.ts | 5 --- src/workflow-functions/index.ts | 5 --- 4 files changed, 1 insertion(+), 92 deletions(-) delete mode 100644 .github/workflows/create-chat.yml delete mode 100644 src/workflow-functions/index.ts diff --git a/.github/workflows/create-chat.yml b/.github/workflows/create-chat.yml deleted file mode 100644 index 2508b7a..0000000 --- a/.github/workflows/create-chat.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: "create-telegram-chat" - -on: - repository_dispatch: - types: [create-telegram-chat] - -jobs: - create-telegram-chat: - name: "Create Telegram Chat" - runs-on: ubuntu-latest - permissions: write-all - env: - BOT_TOKEN: ${{ secrets.BOT_TOKEN }} - BOT_MODE: ${{ secrets.BOT_MODE }} - BOT_ADMINS: ${{ secrets.BOT_ADMINS }} - BOT_WEBHOOK: ${{ secrets.BOT_WEBHOOK }} - BOT_WEBHOOK_SECRET: ${{ secrets.BOT_WEBHOOK_SECRET }} - - TELEGRAM_APP_ID: ${{ secrets.TELEGRAM_APP_ID }} - TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }} - - SUPABASE_URL: ${{ secrets.SUPABASE_URL }} - SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} - - LOG_LEVEL: ${{ secrets.LOG_LEVEL }} - DEBUG: ${{ secrets.DEBUG }} - SERVER_HOST: ${{ secrets.SERVER_HOST }} - SERVER_PORT: ${{ secrets.SERVER_PORT }} - - steps: - - uses: actions/checkout@v4 - - - name: setup node - uses: actions/setup-node@v4 - with: - node-version: "20.10.0" - - - name: install dependencies - run: yarn - - - name: execute directive - run: npx tsx ./src/workflows/create-chat/index.ts - id: create-telegram-chat - env: - BOT_TOKEN: ${{ secrets.BOT_TOKEN }} - BOT_MODE: ${{ secrets.BOT_MODE }} - BOT_ADMINS: ${{ secrets.BOT_ADMINS }} - BOT_WEBHOOK: ${{ secrets.BOT_WEBHOOK }} - BOT_WEBHOOK_SECRET: ${{ secrets.BOT_WEBHOOK_SECRET }} - - TELEGRAM_APP_ID: ${{ secrets.TELEGRAM_APP_ID }} - TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }} - - SUPABASE_URL: ${{ secrets.SUPABASE_URL }} - SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} - - LOG_LEVEL: ${{ secrets.LOG_LEVEL }} - DEBUG: ${{ secrets.DEBUG }} - SERVER_HOST: ${{ secrets.SERVER_HOST }} - SERVER_PORT: ${{ secrets.SERVER_PORT }} \ No newline at end of file diff --git a/src/types/proxy.ts b/src/types/proxy.ts index 2c61c1d..e021116 100644 --- a/src/types/proxy.ts +++ b/src/types/proxy.ts @@ -1,4 +1,3 @@ -import { WorkflowFunction } from "../workflow-functions"; import { Context, SupportedEvents, SupportedEventsU } from "./context"; export type CallbackResult = { status: 200 | 201 | 204 | 404 | 500, reason: string; content?: string | Record }; @@ -23,24 +22,4 @@ export type CallbackResult = { status: 200 | 201 | 204 | 404 | 500, reason: stri type ProxyTypeHelper = { [K in SupportedEventsU]: Array<(context: Context) => Promise>; }; -export type ProxyCallbacks = ProxyTypeHelper; - -/** - * Was unable to figure a way to make this work elegantly to avoid having to use - * typeguards in the workflow functions like we have in `ProxyCallbacks`. - * - * Something in the lines of: - * Each callback would define a generic type `T` that would be just that event type as to - * restrict inference in Context to only that webhook although it infers all payloads in - * all of my attempts. - * - * Would be handy as we could avoid having to use typeguards in the workflow functions. - */ - -/** - * * The expected function signature for callbacks looks like this: - * - * ```typescript - * fn(context: Context): Promise - * ``` - */ \ No newline at end of file +export type ProxyCallbacks = ProxyTypeHelper; \ No newline at end of file diff --git a/src/types/typeguards.ts b/src/types/typeguards.ts index 84c1a9d..5e21818 100644 --- a/src/types/typeguards.ts +++ b/src/types/typeguards.ts @@ -1,7 +1,6 @@ import { Update } from "@grammyjs/types"; import { Context } from "./context"; import { PluginInputs } from "./plugin-inputs"; -import { WORKFLOW_FUNCTIONS } from "../workflow-functions"; export function isIssueOpenedEvent(context: Context): context is Context<"issues.opened"> { return context.eventName === "issues.opened"; @@ -26,8 +25,4 @@ export function isGithubPayload(inputs: any): inputs is PluginInputs { export function isIssueLabeledEvent(context: Context): context is Context<"issues.labeled"> { return context.eventName === "issues.labeled"; -} - -export function isWorkflowFunction(event: string): event is keyof typeof WORKFLOW_FUNCTIONS { - return Object.keys(WORKFLOW_FUNCTIONS).includes(event); } \ No newline at end of file diff --git a/src/workflow-functions/index.ts b/src/workflow-functions/index.ts deleted file mode 100644 index 6e8973d..0000000 --- a/src/workflow-functions/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const WORKFLOW_FUNCTIONS = { - CREATE_CHAT: "create-telegram-chat", -} as const; - -export type WorkflowFunction = typeof WORKFLOW_FUNCTIONS[keyof typeof WORKFLOW_FUNCTIONS]; \ No newline at end of file From 96990a5e28f277c7116f765297b965d8f2a12e4b Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Tue, 3 Sep 2024 21:11:08 +0100 Subject: [PATCH 21/76] chore: remove server post and host env --- .github/workflows/compute.yml | 24 ++++++++++++++++++++++++ src/types/env.ts | 2 -- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 3d204b1..9070237 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -24,6 +24,18 @@ jobs: env: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} + + BOT_TOKEN: ${{ secrets.BOT_TOKEN }} + BOT_MODE: ${{ secrets.BOT_MODE }} + BOT_ADMINS: ${{ secrets.BOT_ADMINS }} + BOT_WEBHOOK: ${{ secrets.BOT_WEBHOOK }} + BOT_WEBHOOK_SECRET: ${{ secrets.BOT_WEBHOOK_SECRET }} + + TELEGRAM_APP_ID: ${{ secrets.TELEGRAM_APP_ID }} + TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }} + + LOG_LEVEL: ${{ secrets.LOG_LEVEL }} + DEBUG: ${{ secrets.DEBUG }} steps: - uses: actions/checkout@v4 @@ -42,3 +54,15 @@ jobs: env: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} + + BOT_TOKEN: ${{ secrets.BOT_TOKEN }} + BOT_MODE: ${{ secrets.BOT_MODE }} + BOT_ADMINS: ${{ secrets.BOT_ADMINS }} + BOT_WEBHOOK: ${{ secrets.BOT_WEBHOOK }} + BOT_WEBHOOK_SECRET: ${{ secrets.BOT_WEBHOOK_SECRET }} + + TELEGRAM_APP_ID: ${{ secrets.TELEGRAM_APP_ID }} + TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }} + + LOG_LEVEL: ${{ secrets.LOG_LEVEL }} + DEBUG: ${{ secrets.DEBUG }} \ No newline at end of file diff --git a/src/types/env.ts b/src/types/env.ts index 669baee..3593ffb 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -23,8 +23,6 @@ export const env = T.Object({ DEBUG: T.Transform(T.Union([T.String(), T.Boolean()])).Decode((str) => str === "true" || str === "false" ? str === "true" : str).Encode((bool) => bool.toString()), BOT_WEBHOOK: T.String(), BOT_WEBHOOK_SECRET: T.String(), - SERVER_HOST: T.String(), - SERVER_PORT: T.Transform(T.Unknown()).Decode((str) => Number(str)).Encode((num) => num.toString()), BOT_ADMINS: T.Transform(T.Unknown()).Decode((str) => Array.isArray(str) ? str.map(Number) : [Number(str)]).Encode((arr) => arr.toString()), ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))), SUPABASE_URL: T.String(), From ec8dca5bc38fb71a7895ce2639621682a1290030 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 14:06:13 +0100 Subject: [PATCH 22/76] chore: add octokit for app auth --- package.json | 3 +- src/handlers/repository-dispatch.ts | 3 +- src/helpers/authenticated-octokit.ts | 14 +-- yarn.lock | 164 ++++++++++++++++++++++++++- 4 files changed, 168 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index ad8d89b..eeb2289 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "grammy-guard": "0.5.0", "hono": "^4.5.9", "iso-639-1": "3.1.2", + "octokit": "^4.0.2", "pino": "9.3.2", "pino-pretty": "11.2.2", "telegram": "^2.24.11", @@ -109,4 +110,4 @@ ] }, "packageManager": "yarn@1.22.22" -} \ No newline at end of file +} diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts index d1c1146..0260ab7 100644 --- a/src/handlers/repository-dispatch.ts +++ b/src/handlers/repository-dispatch.ts @@ -1,7 +1,6 @@ import { getAppOctokit } from "#root/helpers/authenticated-octokit.js"; import { PluginContext } from "#root/utils/plugin-context-single.js"; import { Context } from "../types"; -import { WorkflowFunction } from "../workflow-functions"; /** * Used by the worker instance to kick off workflows within it's own repository. @@ -15,7 +14,7 @@ import { WorkflowFunction } from "../workflow-functions"; * */ -export async function repositoryDispatch(context: Context, workflow: WorkflowFunction) { +export async function repositoryDispatch(context: Context, workflow: string) { const inputs = PluginContext.getInstance().getInputs(); const { logger } = context; const repository = "telegram--bot"; diff --git a/src/helpers/authenticated-octokit.ts b/src/helpers/authenticated-octokit.ts index 51cb49a..b79c01e 100644 --- a/src/helpers/authenticated-octokit.ts +++ b/src/helpers/authenticated-octokit.ts @@ -1,15 +1,13 @@ -import { Octokit } from "@octokit/rest"; +import { App } from "octokit"; import { Context } from "../types"; export async function getAppOctokit(context: Context) { const { env } = context; const { APP_ID, APP_PRIVATE_KEY } = env; - const appOctokit = new Octokit({ - auth: { - appId: APP_ID, - privateKey: APP_PRIVATE_KEY, - }, - }); + const app = new App({ + appId: APP_ID, + privateKey: APP_PRIVATE_KEY, + }) - return appOctokit; + return app.octokit; } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index f5eb332..180e8f4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2406,6 +2406,65 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@octokit/app@^15.0.0": + version "15.1.0" + resolved "https://registry.yarnpkg.com/@octokit/app/-/app-15.1.0.tgz#b330d8826be088ec8d1d43a59dc27ef57d1232b2" + integrity sha512-TkBr7QgOmE6ORxvIAhDbZsqPkF7RSqTY4pLTtUQCvr6dTXqvi2fFo46q3h1lxlk/sGMQjqyZ0kEahkD/NyzOHg== + dependencies: + "@octokit/auth-app" "^7.0.0" + "@octokit/auth-unauthenticated" "^6.0.0" + "@octokit/core" "^6.1.2" + "@octokit/oauth-app" "^7.0.0" + "@octokit/plugin-paginate-rest" "^11.0.0" + "@octokit/types" "^13.0.0" + "@octokit/webhooks" "^13.0.0" + +"@octokit/auth-app@^7.0.0": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-app/-/auth-app-7.1.1.tgz#d8916ad01e6ffb0a0a50507aa613e91fe7a49b93" + integrity sha512-kRAd6yelV9OgvlEJE88H0VLlQdZcag9UlLr7dV0YYP37X8PPDvhgiTy66QVhDXdyoT0AleFN2w/qXkPdrSzINg== + dependencies: + "@octokit/auth-oauth-app" "^8.1.0" + "@octokit/auth-oauth-user" "^5.1.0" + "@octokit/request" "^9.1.1" + "@octokit/request-error" "^6.1.1" + "@octokit/types" "^13.4.1" + lru-cache "^10.0.0" + universal-github-app-jwt "^2.2.0" + universal-user-agent "^7.0.0" + +"@octokit/auth-oauth-app@^8.0.0", "@octokit/auth-oauth-app@^8.1.0": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-app/-/auth-oauth-app-8.1.1.tgz#6204affa6e86f535016799cadf2af9befe5e893c" + integrity sha512-5UtmxXAvU2wfcHIPPDWzVSAWXVJzG3NWsxb7zCFplCWEmMCArSZV0UQu5jw5goLQXbFyOr5onzEH37UJB3zQQg== + dependencies: + "@octokit/auth-oauth-device" "^7.0.0" + "@octokit/auth-oauth-user" "^5.0.1" + "@octokit/request" "^9.0.0" + "@octokit/types" "^13.0.0" + universal-user-agent "^7.0.0" + +"@octokit/auth-oauth-device@^7.0.0", "@octokit/auth-oauth-device@^7.0.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-device/-/auth-oauth-device-7.1.1.tgz#7b4f8f97cbcadbe9894d48cde4406dbdef39875a" + integrity sha512-HWl8lYueHonuyjrKKIup/1tiy0xcmQCdq5ikvMO1YwkNNkxb6DXfrPjrMYItNLyCP/o2H87WuijuE+SlBTT8eg== + dependencies: + "@octokit/oauth-methods" "^5.0.0" + "@octokit/request" "^9.0.0" + "@octokit/types" "^13.0.0" + universal-user-agent "^7.0.0" + +"@octokit/auth-oauth-user@^5.0.1", "@octokit/auth-oauth-user@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-user/-/auth-oauth-user-5.1.1.tgz#4f1570c6ee15bb9ddc3dcca83308dcaa159e3848" + integrity sha512-rRkMz0ErOppdvEfnemHJXgZ9vTPhBuC6yASeFaB7I2yLMd7QpjfrL1mnvRPlyKo+M6eeLxrKanXJ9Qte29SRsw== + dependencies: + "@octokit/auth-oauth-device" "^7.0.1" + "@octokit/oauth-methods" "^5.0.0" + "@octokit/request" "^9.0.1" + "@octokit/types" "^13.0.0" + universal-user-agent "^7.0.0" + "@octokit/auth-token@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-4.0.0.tgz#40d203ea827b9f17f42a29c6afb93b7745ef80c7" @@ -2416,6 +2475,14 @@ resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-5.1.1.tgz#3bbfe905111332a17f72d80bd0b51a3e2fa2cf07" integrity sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA== +"@octokit/auth-unauthenticated@^6.0.0", "@octokit/auth-unauthenticated@^6.0.0-beta.1": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@octokit/auth-unauthenticated/-/auth-unauthenticated-6.1.0.tgz#de0fe923bb06ed93aea526ab99972a98c546d0bf" + integrity sha512-zPSmfrUAcspZH/lOFQnVnvjQZsIvmfApQH6GzJrkIunDooU1Su2qt2FfMTSVPRp7WLTQyC20Kd55lF+mIYaohQ== + dependencies: + "@octokit/request-error" "^6.0.1" + "@octokit/types" "^13.0.0" + "@octokit/core@^5.0.1": version "5.2.0" resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.2.0.tgz#ddbeaefc6b44a39834e1bb2e58a49a117672a7ea" @@ -2429,7 +2496,7 @@ before-after-hook "^2.2.0" universal-user-agent "^6.0.0" -"@octokit/core@^6.1.2": +"@octokit/core@^6.0.0", "@octokit/core@^6.1.2": version "6.1.2" resolved "https://registry.yarnpkg.com/@octokit/core/-/core-6.1.2.tgz#20442d0a97c411612da206411e356014d1d1bd17" integrity sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg== @@ -2476,6 +2543,35 @@ "@octokit/types" "^13.0.0" universal-user-agent "^7.0.0" +"@octokit/oauth-app@^7.0.0": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@octokit/oauth-app/-/oauth-app-7.1.3.tgz#a0f256dd185e7c00bfbc3e6bc3c5aad66e42c609" + integrity sha512-EHXbOpBkSGVVGF1W+NLMmsnSsJRkcrnVmDKt0TQYRBb6xWfWzoi9sBD4DIqZ8jGhOWO/V8t4fqFyJ4vDQDn9bg== + dependencies: + "@octokit/auth-oauth-app" "^8.0.0" + "@octokit/auth-oauth-user" "^5.0.1" + "@octokit/auth-unauthenticated" "^6.0.0-beta.1" + "@octokit/core" "^6.0.0" + "@octokit/oauth-authorization-url" "^7.0.0" + "@octokit/oauth-methods" "^5.0.0" + "@types/aws-lambda" "^8.10.83" + universal-user-agent "^7.0.0" + +"@octokit/oauth-authorization-url@^7.0.0": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@octokit/oauth-authorization-url/-/oauth-authorization-url-7.1.1.tgz#0e17c2225eb66b58ec902d02b6f1315ffe9ff04b" + integrity sha512-ooXV8GBSabSWyhLUowlMIVd9l1s2nsOGQdlP2SQ4LnkEsGXzeCvbSbCPdZThXhEFzleGPwbapT0Sb+YhXRyjCA== + +"@octokit/oauth-methods@^5.0.0": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@octokit/oauth-methods/-/oauth-methods-5.1.2.tgz#fd31d2a69f4c91d1abc1ed1814dda5252c697e02" + integrity sha512-C5lglRD+sBlbrhCUTxgJAFjWgJlmTx5bQ7Ch0+2uqRjYv7Cfb5xpX4WuSC9UgQna3sqRGBL9EImX9PvTpMaQ7g== + dependencies: + "@octokit/oauth-authorization-url" "^7.0.0" + "@octokit/request" "^9.1.0" + "@octokit/request-error" "^6.1.0" + "@octokit/types" "^13.0.0" + "@octokit/openapi-types@^20.0.0": version "20.0.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-20.0.0.tgz#9ec2daa0090eeb865ee147636e0c00f73790c6e5" @@ -2491,6 +2587,11 @@ resolved "https://registry.yarnpkg.com/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-8.3.0.tgz#a7a4da00c0f27f7f5708eb3fcebefa08f8d51125" integrity sha512-vKLsoR4xQxg4Z+6rU/F65ItTUz/EXbD+j/d4mlq2GW8TsA4Tc8Kdma2JTAAJ5hrKWUQzkR/Esn2fjsqiVRYaQg== +"@octokit/plugin-paginate-graphql@^5.0.0": + version "5.2.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-5.2.2.tgz#54e2afef55bb204eb945a891b85a169b9ddad1f8" + integrity sha512-7znSVvlNAOJisCqAnjN1FtEziweOHSjPGAuc5W58NeGNAr/ZB57yCsjQbXDlWsVryA7hHQaEQPcBbJYFawlkyg== + "@octokit/plugin-paginate-rest@^11.0.0": version "11.3.3" resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.3.tgz#efc97ba66aae6797e2807a082f99b9cfc0e05aba" @@ -2524,6 +2625,23 @@ dependencies: "@octokit/types" "^13.5.0" +"@octokit/plugin-retry@^7.0.0": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-retry/-/plugin-retry-7.1.1.tgz#a84483e4afdd068dd71da81abe206a9e442c1288" + integrity sha512-G9Ue+x2odcb8E1XIPhaFBnTTIrrUDfXN05iFXiqhR+SeeeDMMILcAnysOsxUpEWcQp2e5Ft397FCXTcPkiPkLw== + dependencies: + "@octokit/request-error" "^6.0.0" + "@octokit/types" "^13.0.0" + bottleneck "^2.15.3" + +"@octokit/plugin-throttling@^9.0.0": + version "9.3.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-throttling/-/plugin-throttling-9.3.1.tgz#5648165e1e70e861625f3a16af6c55cafe861061" + integrity sha512-Qd91H4liUBhwLB2h6jZ99bsxoQdhgPk6TdwnClPyTBSDAdviGPceViEgUwj+pcQDmB/rfAXAXK7MTochpHM3yQ== + dependencies: + "@octokit/types" "^13.0.0" + bottleneck "^2.15.3" + "@octokit/request-error@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-5.1.0.tgz#ee4138538d08c81a60be3f320cd71063064a3b30" @@ -2533,7 +2651,7 @@ deprecation "^2.0.0" once "^1.4.0" -"@octokit/request-error@^6.0.1": +"@octokit/request-error@^6.0.0", "@octokit/request-error@^6.0.1", "@octokit/request-error@^6.1.0", "@octokit/request-error@^6.1.1": version "6.1.4" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-6.1.4.tgz#ad96e29148d19edc2ba8009fc2b5a24a36c90f16" integrity sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg== @@ -2550,7 +2668,7 @@ "@octokit/types" "^13.1.0" universal-user-agent "^6.0.0" -"@octokit/request@^9.0.0": +"@octokit/request@^9.0.0", "@octokit/request@^9.0.1", "@octokit/request@^9.1.0", "@octokit/request@^9.1.1": version "9.1.3" resolved "https://registry.yarnpkg.com/@octokit/request/-/request-9.1.3.tgz#42b693bc06238f43af3c037ebfd35621c6457838" integrity sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA== @@ -2577,7 +2695,7 @@ dependencies: "@octokit/openapi-types" "^20.0.0" -"@octokit/types@^13.0.0", "@octokit/types@^13.1.0", "@octokit/types@^13.5.0": +"@octokit/types@^13.0.0", "@octokit/types@^13.1.0", "@octokit/types@^13.4.1", "@octokit/types@^13.5.0": version "13.5.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-13.5.0.tgz#4796e56b7b267ebc7c921dcec262b3d5bfb18883" integrity sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ== @@ -2589,7 +2707,7 @@ resolved "https://registry.yarnpkg.com/@octokit/webhooks-methods/-/webhooks-methods-5.1.0.tgz#13b6c08f89902c1ab0ddf31c6eeeec9c2772cfe6" integrity sha512-yFZa3UH11VIxYnnoOYCVoJ3q4ChuSOk2IVBBQ0O3xtKX4x9bmKb/1t+Mxixv2iUhzMdOl1qeWJqEhouXXzB3rQ== -"@octokit/webhooks@13.3.0": +"@octokit/webhooks@13.3.0", "@octokit/webhooks@^13.0.0": version "13.3.0" resolved "https://registry.yarnpkg.com/@octokit/webhooks/-/webhooks-13.3.0.tgz#fd5d54d47c789c75d60a00eb04e982152d7c654a" integrity sha512-TUkJLtI163Bz5+JK0O+zDkQpn4gKwN+BovclUvCj6pI/6RXrFqQvUMRS2M+Rt8Rv0qR3wjoMoOPmpJKeOh0nBg== @@ -2711,6 +2829,11 @@ "@supabase/realtime-js" "2.10.2" "@supabase/storage-js" "2.7.0" +"@types/aws-lambda@^8.10.83": + version "8.10.145" + resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.145.tgz#b2d31a987f4888e5553ff1819f57cafa475594d9" + integrity sha512-dtByW6WiFk5W5Jfgz1VM+YPA21xMXTuSFoLYIDY0L44jDLLflVPtZkYuu3/YxpGcvjzKFBZLU+GyKjR0HOYtyw== + "@types/babel__core@^7.1.14": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -3518,6 +3641,11 @@ blake3-wasm@^2.1.5: resolved "https://registry.yarnpkg.com/blake3-wasm/-/blake3-wasm-2.1.5.tgz#b22dbb84bc9419ed0159caa76af4b1b132e6ba52" integrity sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g== +bottleneck@^2.15.3: + version "2.19.5" + resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" + integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -6625,6 +6753,11 @@ loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lru-cache@^10.0.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -7014,6 +7147,22 @@ object.values@^1.1.6, object.values@^1.1.7, object.values@^1.2.0: define-properties "^1.2.1" es-object-atoms "^1.0.0" +octokit@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/octokit/-/octokit-4.0.2.tgz#775d68d363cdaec69d7b73d3dc82ae909d30f59b" + integrity sha512-wbqF4uc1YbcldtiBFfkSnquHtECEIpYD78YUXI6ri1Im5OO2NLo6ZVpRdbJpdnpZ05zMrVPssNiEo6JQtea+Qg== + dependencies: + "@octokit/app" "^15.0.0" + "@octokit/core" "^6.0.0" + "@octokit/oauth-app" "^7.0.0" + "@octokit/plugin-paginate-graphql" "^5.0.0" + "@octokit/plugin-paginate-rest" "^11.0.0" + "@octokit/plugin-rest-endpoint-methods" "^13.0.0" + "@octokit/plugin-retry" "^7.0.0" + "@octokit/plugin-throttling" "^9.0.0" + "@octokit/request-error" "^6.0.0" + "@octokit/types" "^13.0.0" + on-exit-leak-free@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" @@ -8565,6 +8714,11 @@ unicorn-magic@^0.1.0: resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.1.0.tgz#1bb9a51c823aaf9d73a8bfcd3d1a23dde94b0ce4" integrity sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ== +universal-github-app-jwt@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-2.2.0.tgz#dc6c8929e76f1996a766ba2a08fb420f73365d77" + integrity sha512-G5o6f95b5BggDGuUfKDApKaCgNYy2x7OdHY0zSMF081O0EJobw+1130VONhrA7ezGSV2FNOGyM+KQpQZAr9bIQ== + universal-user-agent@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.1.tgz#15f20f55da3c930c57bddbf1734c6654d5fd35aa" From db9dcb000563b0077603e7f38a8279534f9b854d Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 14:51:08 +0100 Subject: [PATCH 23/76] chore: test --- .github/workflows/compute.yml | 2 +- src/handlers/repository-dispatch.ts | 14 ++++++++++++-- src/helpers/authenticated-octokit.ts | 10 ++-------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 9070237..7d778b5 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -49,7 +49,7 @@ jobs: run: yarn - name: execute directive - run: npx tsx ./src/main.ts + run: npx tsx ./src/workflow-entry.ts id: plugin-name env: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts index 0260ab7..f9d7e3e 100644 --- a/src/handlers/repository-dispatch.ts +++ b/src/handlers/repository-dispatch.ts @@ -20,14 +20,23 @@ export async function repositoryDispatch(context: Context, workflow: string) { const repository = "telegram--bot"; const owner = "ubq-testing"; const branch = "workflows"; - const octokit = await getAppOctokit(context); + const app = await getAppOctokit(context); + const installation = await app.octokit.rest.apps.getRepoInstallation({ owner, repo: repository }); + + // Set the installation id for the octokit instance + + const octokit = await app.getInstallationOctokit(installation.data.id); logger.info(`Dispatching workflow function: ${workflow}`); + /** * We'll hit the main workflow entry and pass in the same inputs so * that it essentially runs on the same context as the worker. */ + + Reflect.deleteProperty(inputs, "signature"); + return await octokit.rest.actions.createWorkflowDispatch({ owner, repo: repository, @@ -35,7 +44,8 @@ export async function repositoryDispatch(context: Context, workflow: string) { ref: branch, inputs: { ...inputs, - workflowFunction: workflow // here for the workflow logs, not used in the workflow + eventPayload: JSON.stringify(context.payload), + settings: JSON.stringify(context.config), } }); } diff --git a/src/helpers/authenticated-octokit.ts b/src/helpers/authenticated-octokit.ts index b79c01e..7df5d36 100644 --- a/src/helpers/authenticated-octokit.ts +++ b/src/helpers/authenticated-octokit.ts @@ -2,12 +2,6 @@ import { App } from "octokit"; import { Context } from "../types"; export async function getAppOctokit(context: Context) { - const { env } = context; - const { APP_ID, APP_PRIVATE_KEY } = env; - const app = new App({ - appId: APP_ID, - privateKey: APP_PRIVATE_KEY, - }) - - return app.octokit; + const { env: { APP_ID, APP_PRIVATE_KEY } } = context; + return new App({ appId: APP_ID, privateKey: APP_PRIVATE_KEY }); } \ No newline at end of file From 8986d67089816ad56ba5d64c08283adf1dcd35d1 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:04:10 +0100 Subject: [PATCH 24/76] chore: typebox debug --- src/workflow-entry.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/workflow-entry.ts b/src/workflow-entry.ts index fc5e774..62ac050 100644 --- a/src/workflow-entry.ts +++ b/src/workflow-entry.ts @@ -11,9 +11,22 @@ import { bubbleUpErrorComment, sanitizeMetadata } from "./utils/errors"; */ export async function run() { const payload = github.context.payload.inputs; + let env, settings; + try { + env = Value.Decode(envValidator.schema, payload.env); + } catch (err) { + console.log("Error decoding env: ", err); + } + + try { + settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, JSON.parse(payload.settings))); + } catch (err) { + console.log("Error decoding settings: ", err); + } - const env = Value.Decode(envValidator.schema, payload.env); - const settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, JSON.parse(payload.settings))); + if (!(settings && env)) { + throw new Error("Invalid settings or env provided"); + } if (!pluginSettingsValidator.test(settings)) { throw new Error("Invalid settings provided"); From 3293d36353e6a598823ee7f51e663b5c2d64daa7 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:11:15 +0100 Subject: [PATCH 25/76] chore: use process.env for workflow --- src/workflow-entry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workflow-entry.ts b/src/workflow-entry.ts index 62ac050..f77b5f2 100644 --- a/src/workflow-entry.ts +++ b/src/workflow-entry.ts @@ -13,7 +13,7 @@ export async function run() { const payload = github.context.payload.inputs; let env, settings; try { - env = Value.Decode(envValidator.schema, payload.env); + env = Value.Decode(envValidator.schema, process.env); } catch (err) { console.log("Error decoding env: ", err); } From 3f8c1da5daac2fdcff93c10e9236dc51fbf6657b Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:14:42 +0100 Subject: [PATCH 26/76] chore: use dotenv --- src/workflow-entry.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/workflow-entry.ts b/src/workflow-entry.ts index f77b5f2..aa810e0 100644 --- a/src/workflow-entry.ts +++ b/src/workflow-entry.ts @@ -5,6 +5,9 @@ import { envValidator, pluginSettingsSchema, PluginInputs, pluginSettingsValidat import { PluginContext } from "./utils/plugin-context-single"; import { proxyWorkflowCallbacks } from "./handlers/callbacks-proxy"; import { bubbleUpErrorComment, sanitizeMetadata } from "./utils/errors"; +import dotenv from "dotenv"; +dotenv.config(); + /** * How a GitHub action executes the plugin. From 1368fe14a2ba4d9abd6799f4ea6b195f31ed1c2f Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:20:04 +0100 Subject: [PATCH 27/76] chore: build separate env --- src/workflow-entry.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/workflow-entry.ts b/src/workflow-entry.ts index aa810e0..f606254 100644 --- a/src/workflow-entry.ts +++ b/src/workflow-entry.ts @@ -6,6 +6,7 @@ import { PluginContext } from "./utils/plugin-context-single"; import { proxyWorkflowCallbacks } from "./handlers/callbacks-proxy"; import { bubbleUpErrorComment, sanitizeMetadata } from "./utils/errors"; import dotenv from "dotenv"; +import { LOG_LEVEL } from "@ubiquity-dao/ubiquibot-logger"; dotenv.config(); @@ -14,9 +15,27 @@ dotenv.config(); */ export async function run() { const payload = github.context.payload.inputs; + let env, settings; + + const payloadEnv = { + BOT_TOKEN: process.env.BOT_TOKEN, + BOT_MODE: process.env.BOT_MODE, + LOG_LEVEL: process.env.LOG_LEVEL, + DEBUG: process.env.DEBUG, + BOT_WEBHOOK: process.env.BOT_WEBHOOK, + BOT_WEBHOOK_SECRET: process.env.BOT_WEBHOOK_SECRET, + BOT_ADMINS: process.env.BOT_ADMINS, + TELEGRAM_APP_ID: process.env.TELEGRAM_APP_ID, + TELEGRAM_API_HASH: process.env.TELEGRAM_API_HASH, + SUPABASE_URL: process.env.SUPABASE_URL, + SUPABASE_KEY: process.env.SUPABASE_KEY, + APP_PRIVATE_KEY: process.env.APP_PRIVATE_KEY, + APP_ID: process.env.APP_ID, + } + try { - env = Value.Decode(envValidator.schema, process.env); + env = Value.Decode(envValidator.schema, payloadEnv); } catch (err) { console.log("Error decoding env: ", err); } From 75de906c7956ced4fe195a444cb9c1750d4efecb Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:34:32 +0100 Subject: [PATCH 28/76] chore: test --- src/types/env.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/env.ts b/src/types/env.ts index 3593ffb..9cee110 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -30,7 +30,7 @@ export const env = T.Object({ TELEGRAM_APP_ID: T.Transform(T.Unknown()).Decode((str) => Number(str)).Encode((num) => num.toString()), TELEGRAM_API_HASH: T.String(), APP_ID: T.Transform(T.Unknown()).Decode((str) => Number(str)).Encode((num) => num.toString()), - APP_PRIVATE_KEY: T.String(), + APP_PRIVATE_KEY: T.Transform(T.Unknown()).Decode((str) => String(str)).Encode((str) => str), }); /** From a2decc83815eae2b271637374cae8fffde6bdf6d Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:36:51 +0100 Subject: [PATCH 29/76] chore: reduce to 10 env items --- src/types/env.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/types/env.ts b/src/types/env.ts index 9cee110..a950a2e 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -18,9 +18,6 @@ const allowedUpdates = T.Object({ export const env = T.Object({ BOT_TOKEN: T.String(), - BOT_MODE: T.String(), - LOG_LEVEL: T.String(), - DEBUG: T.Transform(T.Union([T.String(), T.Boolean()])).Decode((str) => str === "true" || str === "false" ? str === "true" : str).Encode((bool) => bool.toString()), BOT_WEBHOOK: T.String(), BOT_WEBHOOK_SECRET: T.String(), BOT_ADMINS: T.Transform(T.Unknown()).Decode((str) => Array.isArray(str) ? str.map(Number) : [Number(str)]).Encode((arr) => arr.toString()), From 98d3b8d5d4edb491019a22f6f0c1a3f0472e9475 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:40:02 +0100 Subject: [PATCH 30/76] chore:add connect event --- src/workflow-functions/bot.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/workflow-functions/bot.ts b/src/workflow-functions/bot.ts index 1ef4593..102df49 100644 --- a/src/workflow-functions/bot.ts +++ b/src/workflow-functions/bot.ts @@ -21,6 +21,7 @@ export class MtProtoSingleton { MtProtoSingleton.instance = new MtProtoSingleton(); MtProtoSingleton.api = Api; MtProtoSingleton.client = await mtProtoInit(env, MtProtoSingleton.api); + await MtProtoSingleton.client.connect(); } return MtProtoSingleton.instance; } From 0eef0d13e0ef112796d04a56676274690fcd3623 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:43:48 +0100 Subject: [PATCH 31/76] chore: move connect to before api invoke --- src/workflow-functions/bot.ts | 1 - src/workflow-functions/create-chat.ts | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workflow-functions/bot.ts b/src/workflow-functions/bot.ts index 102df49..1ef4593 100644 --- a/src/workflow-functions/bot.ts +++ b/src/workflow-functions/bot.ts @@ -21,7 +21,6 @@ export class MtProtoSingleton { MtProtoSingleton.instance = new MtProtoSingleton(); MtProtoSingleton.api = Api; MtProtoSingleton.client = await mtProtoInit(env, MtProtoSingleton.api); - await MtProtoSingleton.client.connect(); } return MtProtoSingleton.instance; } diff --git a/src/workflow-functions/create-chat.ts b/src/workflow-functions/create-chat.ts index ca7ef6a..ade01e9 100644 --- a/src/workflow-functions/create-chat.ts +++ b/src/workflow-functions/create-chat.ts @@ -10,6 +10,7 @@ export async function createChat(context: Context<"issues.labeled", SupportedEve const mtProto = await MtProtoSingleton.getInstance(env); const client = mtProto.getClient(); + await client.connect(); const api = mtProto.getApi(); console.log("Creating chat with name: ", chatName); const chat = await client.invoke( From 97b8cffde67eb4d85bebff2cd1722cd245cb7d08 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:46:43 +0100 Subject: [PATCH 32/76] chore: correct connect in init fn --- src/workflow-functions/bot.ts | 3 ++- src/workflow-functions/create-chat.ts | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/workflow-functions/bot.ts b/src/workflow-functions/bot.ts index 1ef4593..81befae 100644 --- a/src/workflow-functions/bot.ts +++ b/src/workflow-functions/bot.ts @@ -61,13 +61,14 @@ async function mtProtoInit(env: Context["env"], api: typeof Api) { TELEGRAM_API_HASH, clientParams ); + await client.connect(); + client.invoke(new api.auth.ImportBotAuthorization({ apiId: TELEGRAM_APP_ID, apiHash: TELEGRAM_API_HASH, botAuthToken: BOT_TOKEN, })); - await client.connect(); return client; } \ No newline at end of file diff --git a/src/workflow-functions/create-chat.ts b/src/workflow-functions/create-chat.ts index ade01e9..ca7ef6a 100644 --- a/src/workflow-functions/create-chat.ts +++ b/src/workflow-functions/create-chat.ts @@ -10,7 +10,6 @@ export async function createChat(context: Context<"issues.labeled", SupportedEve const mtProto = await MtProtoSingleton.getInstance(env); const client = mtProto.getClient(); - await client.connect(); const api = mtProto.getApi(); console.log("Creating chat with name: ", chatName); const chat = await client.invoke( From 995bddac78c3fb29a5b27fc80fbcbde64bd6312a Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 15:50:48 +0100 Subject: [PATCH 33/76] chore: use messages.createChat --- .github/workflows/compute.yml | 6 +++--- src/workflow-functions/create-chat.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 7d778b5..85e12f3 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -1,4 +1,4 @@ -name: "the name of the plugin" +name: "Workflow Functions" on: workflow_dispatch: @@ -18,7 +18,7 @@ on: jobs: compute: - name: "plugin name" + name: "Telegram-Bot" runs-on: ubuntu-latest permissions: write-all env: @@ -50,7 +50,7 @@ jobs: - name: execute directive run: npx tsx ./src/workflow-entry.ts - id: plugin-name + id: telegram-bot env: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} diff --git a/src/workflow-functions/create-chat.ts b/src/workflow-functions/create-chat.ts index ca7ef6a..73b8b39 100644 --- a/src/workflow-functions/create-chat.ts +++ b/src/workflow-functions/create-chat.ts @@ -13,9 +13,9 @@ export async function createChat(context: Context<"issues.labeled", SupportedEve const api = mtProto.getApi(); console.log("Creating chat with name: ", chatName); const chat = await client.invoke( - new api.channels.CreateChannel({ + new api.messages.CreateChat({ title: chatName, - broadcast: false, + users: [], }) ); From 3e0bc58392f0a36cdb873c6179ebb080cd3afa06 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 4 Sep 2024 16:04:26 +0100 Subject: [PATCH 34/76] chore: revert to channels.createChannell --- src/workflow-functions/create-chat.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/workflow-functions/create-chat.ts b/src/workflow-functions/create-chat.ts index 73b8b39..7269fea 100644 --- a/src/workflow-functions/create-chat.ts +++ b/src/workflow-functions/create-chat.ts @@ -13,9 +13,10 @@ export async function createChat(context: Context<"issues.labeled", SupportedEve const api = mtProto.getApi(); console.log("Creating chat with name: ", chatName); const chat = await client.invoke( - new api.messages.CreateChat({ + new api.channels.CreateChannel({ title: chatName, - users: [], + broadcast: true, + about: payload.issue.body || "No description provided", }) ); From 21176eb371a66b568439e0763dc2f5febf5ad86b Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun, 8 Sep 2024 20:09:38 +0100 Subject: [PATCH 35/76] chore: squashed Workflows --- .dev.vars.example | 14 +- .github/workflows/compute.yml | 14 +- package.json | 6 +- src/adapters/supabase/helpers/chats.ts | 16 +- src/bot/callback-data/change-language.ts | 5 - src/bot/features/admin/admin.ts | 2 +- src/bot/features/commands/bot-id.ts | 20 ++ .../chatid.ts => commands/chat-id.ts} | 2 +- .../features/{helpers => commands}/user-id.ts | 2 +- src/bot/features/helpers/language.ts | 36 ---- src/bot/features/helpers/unhandled.ts | 2 +- src/bot/features/on/forum-created.ts | 16 -- src/bot/features/welcome.ts | 2 +- src/bot/{context.ts => grammy-context.ts} | 1 - src/bot/handlers/commands/setcommands.ts | 62 +----- src/bot/handlers/error.ts | 2 +- src/bot/helpers/keyboard.ts | 7 - src/bot/helpers/logging.ts | 2 +- src/bot/i18n.ts | 12 -- src/bot/index.ts | 20 +- src/bot/keyboards/change-language.ts | 28 --- src/bot/locales/en.ftl | 22 -- src/bot/middlewares/session.ts | 2 +- src/bot/middlewares/update-logger.ts | 32 --- .../mtproto-api}/README.md | 0 src/bot/mtproto-api/bot/mtproto.ts | 46 +++++ .../bot/scripts/sms-auth/auth-handler.ts | 66 ++++++ .../bot/scripts/sms-auth/base-mtproto.ts | 56 ++++++ .../bot/scripts/sms-auth/sms-auth.ts | 10 + src/bot/mtproto-api/bot/session.ts | 49 +++++ src/bot/mtproto-api/workrooms.ts | 187 +++++++++++++++++ src/handlers/callbacks-proxy.ts | 94 +++++---- src/handlers/github/workrooms.ts | 70 +------ src/handlers/repository-dispatch.ts | 11 +- .../add-comment-to-issues.ts | 2 +- src/helpers/authenticated-octokit.ts | 7 - src/types/env.ts | 2 +- src/types/plugin-inputs.ts | 2 + src/utils/errors.ts | 2 +- src/utils/plugin-context-single.ts | 6 +- src/workflow-entry.ts | 6 +- src/workflow-functions/bot.ts | 74 ------- src/workflow-functions/create-chat.ts | 31 --- yarn.lock | 190 +++++++++++++++++- 44 files changed, 748 insertions(+), 490 deletions(-) delete mode 100644 src/bot/callback-data/change-language.ts create mode 100644 src/bot/features/commands/bot-id.ts rename src/bot/features/{helpers/chatid.ts => commands/chat-id.ts} (88%) rename src/bot/features/{helpers => commands}/user-id.ts (88%) delete mode 100644 src/bot/features/helpers/language.ts delete mode 100644 src/bot/features/on/forum-created.ts rename src/bot/{context.ts => grammy-context.ts} (96%) delete mode 100644 src/bot/helpers/keyboard.ts delete mode 100644 src/bot/i18n.ts delete mode 100644 src/bot/keyboards/change-language.ts delete mode 100644 src/bot/locales/en.ftl delete mode 100644 src/bot/middlewares/update-logger.ts rename src/{workflow-functions => bot/mtproto-api}/README.md (100%) create mode 100644 src/bot/mtproto-api/bot/mtproto.ts create mode 100644 src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts create mode 100644 src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts create mode 100644 src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts create mode 100644 src/bot/mtproto-api/bot/session.ts create mode 100644 src/bot/mtproto-api/workrooms.ts rename src/{handlers/github/utils => helpers}/add-comment-to-issues.ts (94%) delete mode 100644 src/helpers/authenticated-octokit.ts delete mode 100644 src/workflow-functions/bot.ts delete mode 100644 src/workflow-functions/create-chat.ts diff --git a/.dev.vars.example b/.dev.vars.example index e49d79a..0a4712f 100644 --- a/.dev.vars.example +++ b/.dev.vars.example @@ -1 +1,13 @@ -MY_SECRET="MY_SECRET" +BOT_TOKEN=123:xyz +BOT_WEBHOOK=... +BOT_WEBHOOK_SECRET=... +BOT_ADMINS=[1234,5678] + +SUPABASE_URL=... +SUPABASE_SERVICE_KEY=... + +TELEGRAM_APP_ID=12345678 +TELEGRAM_API_HASH=... + +APP_PRIVATE_KEY=... +APP_ID=123456 \ No newline at end of file diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 85e12f3..bb2649d 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -23,10 +23,9 @@ jobs: permissions: write-all env: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} - SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} + SUPABASE_SERVICE_KEY: ${{ secrets.SUPABASE_SERVICE_KEY }} BOT_TOKEN: ${{ secrets.BOT_TOKEN }} - BOT_MODE: ${{ secrets.BOT_MODE }} BOT_ADMINS: ${{ secrets.BOT_ADMINS }} BOT_WEBHOOK: ${{ secrets.BOT_WEBHOOK }} BOT_WEBHOOK_SECRET: ${{ secrets.BOT_WEBHOOK_SECRET }} @@ -34,8 +33,8 @@ jobs: TELEGRAM_APP_ID: ${{ secrets.TELEGRAM_APP_ID }} TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }} - LOG_LEVEL: ${{ secrets.LOG_LEVEL }} - DEBUG: ${{ secrets.DEBUG }} + APP_ID: ${{ secrets.APP_ID }} + APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} steps: - uses: actions/checkout@v4 @@ -53,10 +52,9 @@ jobs: id: telegram-bot env: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} - SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }} + SUPABASE_SERVICE_KEY: ${{ secrets.SUPABASE_SERVICE_KEY }} BOT_TOKEN: ${{ secrets.BOT_TOKEN }} - BOT_MODE: ${{ secrets.BOT_MODE }} BOT_ADMINS: ${{ secrets.BOT_ADMINS }} BOT_WEBHOOK: ${{ secrets.BOT_WEBHOOK }} BOT_WEBHOOK_SECRET: ${{ secrets.BOT_WEBHOOK_SECRET }} @@ -64,5 +62,5 @@ jobs: TELEGRAM_APP_ID: ${{ secrets.TELEGRAM_APP_ID }} TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }} - LOG_LEVEL: ${{ secrets.LOG_LEVEL }} - DEBUG: ${{ secrets.DEBUG }} \ No newline at end of file + APP_ID: ${{ secrets.APP_ID }} + APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} \ No newline at end of file diff --git a/package.json b/package.json index eeb2289..6b894a9 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "worker": "wrangler dev --env dev --port 3000", "dev": "tsc-watch --onSuccess \"tsx ./src/main.ts\"", "start": "tsx ./src/main.ts", - "deploy": "wrangler deploy --minify src/main.ts" + "deploy": "wrangler deploy --minify src/main.ts", + "sms-auth": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts" }, "keywords": [ "typescript", @@ -80,6 +81,7 @@ "eslint-plugin-prettier": "5.2.1", "eslint-plugin-sonarjs": "2.0.1", "husky": "9.1.5", + "input": "^1.0.1", "jest": "29.7.0", "jest-junit": "16.0.0", "jest-md-dashboard": "0.8.0", @@ -110,4 +112,4 @@ ] }, "packageManager": "yarn@1.22.22" -} +} \ No newline at end of file diff --git a/src/adapters/supabase/helpers/chats.ts b/src/adapters/supabase/helpers/chats.ts index c34a00f..8ef9db6 100644 --- a/src/adapters/supabase/helpers/chats.ts +++ b/src/adapters/supabase/helpers/chats.ts @@ -36,10 +36,10 @@ export class Chats extends Super { return; } - const { data, error } = (await this.supabase.from("chats").upsert({ ...chat, status })) as { data: unknown; error: unknown }; + const { error } = (await this.supabase.from("chats").upsert({ ...chat, status })) - if (error || !data) { - this.context.logger.error("Failed to update chat status", { chatId, taskNodeId }); + if (error) { + this.context.logger.error("Failed to update chat status", { chatId, taskNodeId, er: error }); } else { this.context.logger.info("Successfully updated chat status", { chatId, taskNodeId }); } @@ -47,18 +47,16 @@ export class Chats extends Super { async saveChat(chatId: number, chatName: string, taskNodeId: string) { - const { data, error } = (await this.supabase.from("chats").insert([{ chatId, chatName, taskNodeId, status: "open" }]) as { data: unknown; error: unknown }); + const { error } = await this.supabase.from("chats").insert([{ chatId, chatName, taskNodeId, status: "open" }]) if (error) { this.context.logger.error("Failed to save chat", { chatId, chatName, taskNodeId, er: error }); } else { this.context.logger.info("Successfully saved chat", { chatId, chatName }); } - - return data; } async getChatByChatId(chatId: number) { - const { data, error } = (await this.supabase.from("chats").select("*").eq("chatId", chatId).single()) as { data: unknown; error: unknown }; + const { data, error } = (await this.supabase.from("chats").select("*").eq("chatId", chatId).single()) if (error || !data) { this.context.logger.error("No chat found", { chatId }); } else { @@ -69,7 +67,7 @@ export class Chats extends Super { } async getChatByChatName(chatName: string) { - const { data, error } = (await this.supabase.from("chats").select("*").eq("chatName", chatName).single()) as { data: unknown; error: unknown }; + const { data, error } = (await this.supabase.from("chats").select("*").eq("chatName", chatName).single()) if (error || !data) { this.context.logger.error("No chat found", { chatName }); } else { @@ -88,7 +86,7 @@ export class Chats extends Super { this.context.logger.info("Successfully fetched chat", { taskNodeId }); } - return data; + return data } catch (e) { console.error(e) throw new Error("Failed to fetch chat by task node id") diff --git a/src/bot/callback-data/change-language.ts b/src/bot/callback-data/change-language.ts deleted file mode 100644 index 17ee539..0000000 --- a/src/bot/callback-data/change-language.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createCallbackData } from 'callback-data' - -export const changeLanguageData = createCallbackData('language', { - code: String, -}) diff --git a/src/bot/features/admin/admin.ts b/src/bot/features/admin/admin.ts index 40c15bc..9d5dc17 100644 --- a/src/bot/features/admin/admin.ts +++ b/src/bot/features/admin/admin.ts @@ -1,6 +1,6 @@ import { chatAction } from '@grammyjs/auto-chat-action' import { Composer } from 'grammy' -import type { Context } from '#root/bot/context.js' +import type { Context } from '#root/bot/grammy-context.js' import { isAdmin } from '#root/bot/filters/is-admin.js' import { setCommandsHandler } from '#root/bot/handlers/commands/setcommands.js' import { logHandle } from '#root/bot/helpers/logging.js' diff --git a/src/bot/features/commands/bot-id.ts b/src/bot/features/commands/bot-id.ts new file mode 100644 index 0000000..6668ddb --- /dev/null +++ b/src/bot/features/commands/bot-id.ts @@ -0,0 +1,20 @@ +import { chatAction } from '@grammyjs/auto-chat-action' +import { Composer } from 'grammy' +import type { Context } from '#root/bot/grammy-context.js' +import { logHandle } from '#root/bot/helpers/logging.js' + +const composer = new Composer() + +const feature = composer.chatType('private') + +feature.command( + 'botid', + logHandle('command-botid'), + chatAction('typing'), + async (ctx) => { + const botID = ctx.me.id + await ctx.reply(`My ID is ${botID}`) + }, +) + +export { composer as botIdFeature } diff --git a/src/bot/features/helpers/chatid.ts b/src/bot/features/commands/chat-id.ts similarity index 88% rename from src/bot/features/helpers/chatid.ts rename to src/bot/features/commands/chat-id.ts index 8e7fa59..05aaa8e 100644 --- a/src/bot/features/helpers/chatid.ts +++ b/src/bot/features/commands/chat-id.ts @@ -1,6 +1,6 @@ import { chatAction } from '@grammyjs/auto-chat-action' import { Composer } from 'grammy' -import type { Context } from '#root/bot/context.js' +import type { Context } from '#root/bot/grammy-context.js' import { logHandle } from '#root/bot/helpers/logging.js' const composer = new Composer() diff --git a/src/bot/features/helpers/user-id.ts b/src/bot/features/commands/user-id.ts similarity index 88% rename from src/bot/features/helpers/user-id.ts rename to src/bot/features/commands/user-id.ts index f249862..981b60d 100644 --- a/src/bot/features/helpers/user-id.ts +++ b/src/bot/features/commands/user-id.ts @@ -1,6 +1,6 @@ import { chatAction } from '@grammyjs/auto-chat-action' import { Composer } from 'grammy' -import type { Context } from '#root/bot/context.js' +import type { Context } from '#root/bot/grammy-context.js' import { logHandle } from '#root/bot/helpers/logging.js' const composer = new Composer() diff --git a/src/bot/features/helpers/language.ts b/src/bot/features/helpers/language.ts deleted file mode 100644 index 5763a40..0000000 --- a/src/bot/features/helpers/language.ts +++ /dev/null @@ -1,36 +0,0 @@ -// import { Composer } from 'grammy' -// import { changeLanguageData } from '#root/bot/callback-data/change-language.js' -// import type { Context } from '#root/bot/context.js' -// import { logHandle } from '#root/bot/helpers/logging.js' -// import { i18n } from '#root/bot/i18n.js' -// import { createChangeLanguageKeyboard } from '#root/bot/keyboards/change-language.js' - -// const composer = new Composer() - -// const feature = composer.chatType('private') - -// feature.command('language', logHandle('command-language'), async (ctx) => { -// return ctx.reply(ctx.t('language-select'), { -// reply_markup: await createChangeLanguageKeyboard(ctx), -// }) -// }) - -// feature.callbackQuery( -// changeLanguageData.filter(), -// logHandle('keyboard-language-select'), -// async (ctx) => { -// const { code: languageCode } = changeLanguageData.unpack( -// ctx.callbackQuery.data, -// ) - -// if (i18n.locales.includes(languageCode)) { -// await ctx.i18n.setLocale(languageCode) - -// return ctx.editMessageText(ctx.t('language-changed'), { -// reply_markup: await createChangeLanguageKeyboard(ctx), -// }) -// } -// }, -// ) - -// export { composer as languageFeature } diff --git a/src/bot/features/helpers/unhandled.ts b/src/bot/features/helpers/unhandled.ts index 9a4c7d9..b96e572 100644 --- a/src/bot/features/helpers/unhandled.ts +++ b/src/bot/features/helpers/unhandled.ts @@ -1,5 +1,5 @@ import { Composer } from 'grammy' -import type { Context } from '#root/bot/context.js' +import type { Context } from '#root/bot/grammy-context.js' import { logHandle } from '#root/bot/helpers/logging.js' import { STRINGS } from '../../strings' diff --git a/src/bot/features/on/forum-created.ts b/src/bot/features/on/forum-created.ts deleted file mode 100644 index bd3b690..0000000 --- a/src/bot/features/on/forum-created.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Composer } from 'grammy' -import type { Context } from '#root/bot/context.js' -import { PluginContext } from '#root/utils/plugin-context-single.js' - -const composer = new Composer() - -const feature = composer.chatType("supergroup") - -feature.on(":forum_topic_created", async (ctx) => { - const pluginCtx = PluginContext.getInstance().getContext() - const chatId = pluginCtx.config.supergroupChatId - const name = ctx.update.message.forum_topic_created.name - return await ctx.api.sendMessage(chatId, `New workroom created: ${name} `) -}) - -export { composer as createForumsFeature } \ No newline at end of file diff --git a/src/bot/features/welcome.ts b/src/bot/features/welcome.ts index 4e6f190..b68bbf1 100644 --- a/src/bot/features/welcome.ts +++ b/src/bot/features/welcome.ts @@ -1,5 +1,5 @@ import { Composer } from 'grammy' -import type { Context } from '#root/bot/context.js' +import type { Context } from '#root/bot/grammy-context.js' import { logHandle } from '#root/bot/helpers/logging.js' import { STRINGS } from '../strings' diff --git a/src/bot/context.ts b/src/bot/grammy-context.ts similarity index 96% rename from src/bot/context.ts rename to src/bot/grammy-context.ts index e3b8f0e..37dc60d 100644 --- a/src/bot/context.ts +++ b/src/bot/grammy-context.ts @@ -2,7 +2,6 @@ import type { Update, UserFromGetMe } from '@grammyjs/types' import { type Api, Context as DefaultContext, type SessionFlavor } from 'grammy' import type { AutoChatActionFlavor } from '@grammyjs/auto-chat-action' import type { HydrateFlavor } from '@grammyjs/hydrate' -import type { I18nFlavor } from '@grammyjs/i18n' import type { ParseModeFlavor } from '@grammyjs/parse-mode' import type { Logger } from '#root/logger.js' import { Context as UbiquityOsContext } from '../types' diff --git a/src/bot/handlers/commands/setcommands.ts b/src/bot/handlers/commands/setcommands.ts index 1a5d99d..fc9b22c 100644 --- a/src/bot/handlers/commands/setcommands.ts +++ b/src/bot/handlers/commands/setcommands.ts @@ -1,15 +1,8 @@ -import type { BotCommand, LanguageCode } from '@grammyjs/types' +import type { BotCommand } from '@grammyjs/types' import type { CommandContext } from 'grammy' -import type { Context } from '#root/bot/context.js' +import type { Context } from '#root/bot/grammy-context.js' -function getLanguageCommand(localeCode: string): BotCommand { - return { - command: 'language', - description: 'language-command-description', - } -} - -function getPrivateChatCommands(localeCode: string): BotCommand[] { +function getPrivateChatCommands(): BotCommand[] { return [ { command: 'start', @@ -18,7 +11,7 @@ function getPrivateChatCommands(localeCode: string): BotCommand[] { ] } -function getPrivateChatAdminCommands(localeCode: string): BotCommand[] { +function getPrivateChatAdminCommands(): BotCommand[] { return [ { command: 'setcommands', @@ -27,18 +20,15 @@ function getPrivateChatAdminCommands(localeCode: string): BotCommand[] { ] } -function getGroupChatCommands(_localeCode: string): BotCommand[] { +function getGroupChatCommands(): BotCommand[] { return [] } export async function setCommandsHandler(ctx: CommandContext) { - const DEFAULT_LANGUAGE_CODE = 'en' - // set private chat commands await ctx.api.setMyCommands( [ - ...getPrivateChatCommands(DEFAULT_LANGUAGE_CODE), - // ...(isMultipleLocales ? [getLanguageCommand(DEFAULT_LANGUAGE_CODE)] : []), + ...getPrivateChatCommands(), ], { scope: { @@ -47,53 +37,19 @@ export async function setCommandsHandler(ctx: CommandContext) { }, ) - // if (isMultipleLocales) { - // const requests = i18n.locales.map(code => - // ctx.api.setMyCommands( - // [ - // ...getPrivateChatCommands(code), - // ...(isMultipleLocales - // ? [getLanguageCommand(DEFAULT_LANGUAGE_CODE)] - // : []), - // ], - // { - // language_code: code as LanguageCode, - // scope: { - // type: 'all_private_chats', - // }, - // }, - // ), - // ) - - // await Promise.all(requests) - // } // set group chat commands - await ctx.api.setMyCommands(getGroupChatCommands(DEFAULT_LANGUAGE_CODE), { + await ctx.api.setMyCommands(getGroupChatCommands(), { scope: { type: 'all_group_chats', }, }) - // if (isMultipleLocales) { - // const requests = i18n.locales.map(code => - // ctx.api.setMyCommands(getGroupChatCommands(code), { - // language_code: code as LanguageCode, - // scope: { - // type: 'all_group_chats', - // }, - // }), - // ) - - // await Promise.all(requests) - // } - // set private chat commands for owner await ctx.api.setMyCommands( [ - ...getPrivateChatCommands(DEFAULT_LANGUAGE_CODE), - ...getPrivateChatAdminCommands(DEFAULT_LANGUAGE_CODE), - // ...(isMultipleLocales ? [getLanguageCommand(DEFAULT_LANGUAGE_CODE)] : []), + ...getPrivateChatCommands(), + ...getPrivateChatAdminCommands(), ], { scope: { diff --git a/src/bot/handlers/error.ts b/src/bot/handlers/error.ts index 9a9ad78..c5ba581 100644 --- a/src/bot/handlers/error.ts +++ b/src/bot/handlers/error.ts @@ -1,5 +1,5 @@ import type { ErrorHandler } from 'grammy' -import type { Context } from '#root/bot/context.js' +import type { Context } from '#root/bot/grammy-context.js' import { getUpdateInfo } from '#root/bot/helpers/logging.js' export const errorHandler: ErrorHandler = (error) => { diff --git a/src/bot/helpers/keyboard.ts b/src/bot/helpers/keyboard.ts deleted file mode 100644 index d97ee33..0000000 --- a/src/bot/helpers/keyboard.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function chunk(array: T[], size: number) { - const result = [] - for (let index = 0; index < array.length; index += size) - result.push(array.slice(index, index + size)) - - return result -} diff --git a/src/bot/helpers/logging.ts b/src/bot/helpers/logging.ts index 9c945c2..e082c85 100644 --- a/src/bot/helpers/logging.ts +++ b/src/bot/helpers/logging.ts @@ -1,6 +1,6 @@ import type { Middleware } from 'grammy' import type { Update } from '@grammyjs/types' -import type { Context } from '#root/bot/context.js' +import type { Context } from '#root/bot/grammy-context.js' export function getUpdateInfo(ctx: Context): Omit { const { update_id, ...update } = ctx.update diff --git a/src/bot/i18n.ts b/src/bot/i18n.ts deleted file mode 100644 index 43d6e75..0000000 --- a/src/bot/i18n.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { I18n } from '@grammyjs/i18n' -import type { Context } from '#root/bot/context.js' - -export const i18n = new I18n({ - defaultLocale: 'en', - useSession: true, - fluentBundleOptions: { - useIsolating: false, - }, -}) - -export const isMultipleLocales = i18n.locales.length > 1 diff --git a/src/bot/index.ts b/src/bot/index.ts index 76e672c..85b0066 100644 --- a/src/bot/index.ts +++ b/src/bot/index.ts @@ -1,8 +1,8 @@ import type { BotConfig, StorageAdapter } from 'grammy' import { Bot as TelegramBot, Api } from 'grammy' -import type { Context, SessionData } from '#root/bot/context.js' -import { createContextConstructor } from '#root/bot/context.js' +import type { Context, SessionData } from '#root/bot/grammy-context.js' +import { createContextConstructor } from '#root/bot/grammy-context.js' import type { Logger } from '#root/logger.js' import { Context as UbiquityOsContext } from '../types' import { welcomeFeature } from '#root/bot/features/welcome.js' @@ -12,11 +12,10 @@ import { session } from '#root/bot/middlewares/session.js' import { autoChatAction } from '@grammyjs/auto-chat-action' import { hydrate } from '@grammyjs/hydrate' import { hydrateReply, parseMode } from '@grammyjs/parse-mode' -import { i18n } from './i18n' import { adminFeature } from './features/admin/admin' -import { userIdFeature } from './features/helpers/user-id' -import { createForumsFeature } from './features/on/forum-created' -import { chatIdFeature } from './features/helpers/chatid' +import { userIdFeature } from './features/commands/user-id' +import { chatIdFeature } from './features/commands/chat-id' +import { botIdFeature } from './features/commands/bot-id' interface Dependencies { config: UbiquityOsContext["env"] @@ -47,7 +46,6 @@ export function createBot(token: string, dependencies: Dependencies, options: Op }) const protectedBot = bot.errorBoundary(errorHandler) - // // createForumsFeature bot.api.config.use(parseMode('HTML')) protectedBot.use(autoChatAction(bot.api)) @@ -55,16 +53,14 @@ export function createBot(token: string, dependencies: Dependencies, options: Op protectedBot.use(hydrate()) protectedBot.use(session({ getSessionKey, storage: options.botSessionStorage })) - // // Handlers + // Handlers protectedBot.use(welcomeFeature) protectedBot.use(adminFeature) protectedBot.use(userIdFeature) protectedBot.use(chatIdFeature) - // protectedBot.use(createForumsFeature) - // if (isMultipleLocales) - // protectedBot.use(languageFeature) + protectedBot.use(botIdFeature) - // // must be the last handler + // must be the last handler protectedBot.use(unhandledFeature) return bot diff --git a/src/bot/keyboards/change-language.ts b/src/bot/keyboards/change-language.ts deleted file mode 100644 index 54d32e1..0000000 --- a/src/bot/keyboards/change-language.ts +++ /dev/null @@ -1,28 +0,0 @@ -// import { InlineKeyboard } from 'grammy' -// import ISO6391 from 'iso-639-1' -// import { changeLanguageData } from '#root/bot/callback-data/change-language.js' -// import type { Context } from '#root/bot/context.js' -// import { i18n } from '#root/bot/i18n.js' -// import { chunk } from '#root/bot/helpers/keyboard.js' - -// export async function createChangeLanguageKeyboard(ctx: Context) { -// const currentLocaleCode = await ctx.i18n.getLocale() - -// const getLabel = (code: string) => { -// const isActive = code === currentLocaleCode - -// return `${isActive ? '✅ ' : ''}${ISO6391.getNativeName(code)}` -// } - -// return InlineKeyboard.from( -// chunk( -// i18n.locales.map(localeCode => ({ -// text: getLabel(localeCode), -// callback_data: changeLanguageData.pack({ -// code: localeCode, -// }), -// })), -// 2, -// ), -// ) -// } diff --git a/src/bot/locales/en.ftl b/src/bot/locales/en.ftl deleted file mode 100644 index 0a9fe88..0000000 --- a/src/bot/locales/en.ftl +++ /dev/null @@ -1,22 +0,0 @@ -## Commands - -start - command - description = Start the bot -language - command - description = Change language -setcommands - command - description = Set bot commands - -## Welcome Feature - -welcome = Welcome! - -## Language Feature - -language - select = Please, select your language -language - changed = Language successfully changed! - -## Admin Feature - -admin - commands - updated = Commands updated. - -## Unhandled Feature - -unhandled = Unrecognized command.Try / start \ No newline at end of file diff --git a/src/bot/middlewares/session.ts b/src/bot/middlewares/session.ts index f05d75e..7b856fb 100644 --- a/src/bot/middlewares/session.ts +++ b/src/bot/middlewares/session.ts @@ -1,5 +1,5 @@ import { type Middleware, type SessionOptions, session as createSession } from 'grammy' -import type { Context, SessionData } from '#root/bot/context.js' +import type { Context, SessionData } from '#root/bot/grammy-context.js' type Options = Pick, 'getSessionKey' | 'storage'> diff --git a/src/bot/middlewares/update-logger.ts b/src/bot/middlewares/update-logger.ts deleted file mode 100644 index 5d521b0..0000000 --- a/src/bot/middlewares/update-logger.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { performance } from 'node:perf_hooks' -import type { Middleware } from 'grammy' -import type { Context } from '#root/bot/context.js' -import { getUpdateInfo } from '#root/bot/helpers/logging.js' - -export function updateLogger(): Middleware { - return async (ctx, next) => { - ctx.api.config.use((previous, method, payload, signal) => { - ctx.logger.debug("Bot API call", { - method, - payload, - }) - - return previous(method, payload, signal) - }) - - ctx.logger.debug("Update received", { - update: getUpdateInfo(ctx), - }) - - const startTime = performance.now() - try { - await next() - } - finally { - const endTime = performance.now() - ctx.logger.debug("Update processed", { - elapsed: endTime - startTime, - }) - } - } -} diff --git a/src/workflow-functions/README.md b/src/bot/mtproto-api/README.md similarity index 100% rename from src/workflow-functions/README.md rename to src/bot/mtproto-api/README.md diff --git a/src/bot/mtproto-api/bot/mtproto.ts b/src/bot/mtproto-api/bot/mtproto.ts new file mode 100644 index 0000000..ab3cd64 --- /dev/null +++ b/src/bot/mtproto-api/bot/mtproto.ts @@ -0,0 +1,46 @@ +import { Context } from '#root/types/context.js'; +import dotenv from "dotenv"; +import { BaseMtProto } from './scripts/sms-auth/base-mtproto'; +import { SupabaseSession } from './session'; +import { createClient, SupabaseClient } from '@supabase/supabase-js'; +dotenv.config(); + +export class MtProto extends BaseMtProto { + private supabase: SupabaseClient | null = null; + private context: Context; + _session: SupabaseSession; + + constructor(context: Context) { + super(); + + const key = context.env.SUPABASE_SERVICE_KEY; + const url = context.env.SUPABASE_URL; + + if (!key || !url) { + throw new Error("Missing required environment variables for Supabase") + } + + this.supabase = createClient(url, key); + this.context = context; + this._session = new SupabaseSession(this.supabase, this.context); + } + + async initialize() { + const session = await this._session.getSession(); + await super.initialize(this.context.env, session); + } + + async saveSession() { + await this._session.saveSession(); + } + + async deleteSession() { + await this._session.deleteSession(); + } + + async loadSession() { + await this._session.loadSession(); + } +} + + diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts new file mode 100644 index 0000000..d638f38 --- /dev/null +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts @@ -0,0 +1,66 @@ +// @ts-expect-error no types for this package +import input from 'input'; +import dotenv from "dotenv"; +import { createClient, SupabaseClient } from '@supabase/supabase-js'; +import { BaseMtProto } from './base-mtproto'; +dotenv.config(); + +/** + * The account holder must run this script (to my knowledge only once) to login, + * this will give us the necessary session information to login in the future. + */ + +export class AuthHandler { + private supabase: SupabaseClient | null = null; + private env = { + TELEGRAM_API_HASH: "", + TELEGRAM_APP_ID: 0, + BOT_TOKEN: "", + } + + constructor() { + const key = process.env.SUPABASE_SERVICE_KEY; + const url = process.env.SUPABASE_URL; + if (!key || !url) { + throw new Error("Missing required environment variables for Supabase") + } + this.supabase = createClient(url, key); + + const hash = process.env.TELEGRAM_API_HASH + const tgAppId = process.env.TELEGRAM_APP_ID + const botToken = process.env.BOT_TOKEN + + if (!hash || !tgAppId || !botToken) { + throw new Error("Missing required environment variables for Telegram API") + } + + this.env = { + TELEGRAM_API_HASH: hash, + TELEGRAM_APP_ID: Number(tgAppId), + BOT_TOKEN: botToken + } + } + + /** + * This method will handle the SMS login process. + */ + async smsLogin() { + const mtProto = new BaseMtProto(); + await mtProto.initialize(this.env, ""); + try { + // Start the login process + await mtProto.client?.start({ + phoneNumber: async () => await input.text('Enter your phone number:'), + password: async () => await input.text('Enter your password if required:'), + phoneCode: async () => await input.text('Enter the code you received:'), + onError: (err: unknown) => console.error('Error during login:', err), + }); + + await this.supabase?.from('tg-bot-sessions').insert([ + { session_data: mtProto.session?.save() }, + ]); + } catch (error) { + console.error('Failed to log in:', error); + } + } +} \ No newline at end of file diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts new file mode 100644 index 0000000..4852c69 --- /dev/null +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts @@ -0,0 +1,56 @@ +import { TelegramClient } from 'telegram'; +import { Api } from 'telegram/tl'; +import { TelegramClientParams } from 'telegram/client/telegramBaseClient'; +import dotenv from "dotenv"; +import { StringSession } from 'telegram/sessions'; +dotenv.config(); + +type Env = { + TELEGRAM_API_HASH: string; + TELEGRAM_APP_ID: number; + BOT_TOKEN: string; +} + +export class BaseMtProto { + // @ts-expect-error properties not defined in constructor, not required in baseclass + _client: TelegramClient; _api: typeof Api; + _session: StringSession | null = null; + + async initialize(env: Env, session: string) { + this._api = Api; + this._session = new StringSession(session) + this._client = await this.mtProtoInit(env, this._session); + } + + get api() { + return this._api; + } + + get client() { + return this._client; + } + + get session() { + return this._session; + } + + private async mtProtoInit(env: Env, session: StringSession) { + const { TELEGRAM_API_HASH, TELEGRAM_APP_ID, BOT_TOKEN } = env + + if (!TELEGRAM_API_HASH || !TELEGRAM_APP_ID || !BOT_TOKEN) { + throw new Error("Missing required environment variables for Telegram API") + } + const clientParams: TelegramClientParams = { + connectionRetries: 5, + } + const client = new TelegramClient( + session, + TELEGRAM_APP_ID, + TELEGRAM_API_HASH, + clientParams + ); + await client.connect(); + return client; + } +} + diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts new file mode 100644 index 0000000..bdaa9a2 --- /dev/null +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts @@ -0,0 +1,10 @@ +import { AuthHandler } from "./auth-handler"; +import dotenv from "dotenv"; +dotenv.config(); + +async function main() { + const authHandler = new AuthHandler(); + await authHandler.smsLogin(); +} + +main().catch(console.error); \ No newline at end of file diff --git a/src/bot/mtproto-api/bot/session.ts b/src/bot/mtproto-api/bot/session.ts new file mode 100644 index 0000000..85550ed --- /dev/null +++ b/src/bot/mtproto-api/bot/session.ts @@ -0,0 +1,49 @@ +import { Context } from "#root/types/context.js"; +import { SupabaseClient } from "@supabase/supabase-js"; +import { StringSession } from "telegram/sessions"; + +/** + * This class extends the StringSession class from the Telegram library. + * + * It adds the ability to save and load the session data from Supabase. + */ +export class SupabaseSession extends StringSession { + supabase: SupabaseClient; + context: Context; + + constructor(supabase: SupabaseClient, context: Context, session?: string) { + super(session); + this.supabase = supabase + this.context = context + } + + async saveSession(): Promise { + await this.supabase?.from('tg-bot-sessions').insert([ + { session_data: super.save() }, + ]); + } + + async loadSession(): Promise { + const session = await this.supabase?.from('tg-bot-sessions').select('session_data').single() + + if (session.data) { + return new SupabaseSession(this.supabase, this.context, session.data.session_data) + } else { + throw new Error("No session found. Please run the SMS Login script first.") + } + } + + async getSession(): Promise { + const session = await this.supabase?.from('tg-bot-sessions').select('session_data').single() + + if (session.data) { + return session.data.session_data + } else { + throw new Error("No session found. Please run the SMS Login script first.") + } + } + + async deleteSession(): Promise { + await this.supabase?.from('tg-bot-sessions').delete() + } +} \ No newline at end of file diff --git a/src/bot/mtproto-api/workrooms.ts b/src/bot/mtproto-api/workrooms.ts new file mode 100644 index 0000000..ccb9efc --- /dev/null +++ b/src/bot/mtproto-api/workrooms.ts @@ -0,0 +1,187 @@ +import { Context, SupportedEvents } from "#root/types/context"; +import { CallbackResult } from "#root/types/proxy.js"; +import { MtProto } from "./bot/mtproto"; +import { Api } from "telegram"; +import { addCommentToIssue } from "#root/helpers/add-comment-to-issues.js"; + +function isPriceLabelChange(label: string): boolean { + return label.toLowerCase().includes("price"); +} + +export async function createChat(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { + const { payload, config, logger } = context; + const chatName = payload.issue.title; + + const labelName = payload.label?.name; + + if (!labelName || !isPriceLabelChange(labelName)) { + return { status: 200, reason: "skipped" }; + } + + const mtProto = new MtProto(context); + await mtProto.initialize(); + let chatId: number; + logger.info("Creating chat with name: ", { chatName }); + + try { + const botIdString = await mtProto.client.getPeerId(config.botUsername, true); + + const chat = await mtProto.client.invoke( + new mtProto.api.messages.CreateChat({ + title: chatName, + users: [botIdString], + }) + ); + let inviteLink; + + if ("chats" in chat.updates) { + chatId = chat.updates.chats[0].id.toJSNumber(); + } else { + throw new Error("Failed to create chat"); + } + + if (chat.updates.chats[0].className === "Chat") { + inviteLink = await mtProto.client.invoke( + new mtProto.api.messages.ExportChatInvite({ + peer: new mtProto.api.InputPeerChat({ chatId: chat.updates.chats[0].id }), + }) + ); + } + + if (inviteLink) { + const [owner, repo] = payload.repository.full_name.split("/"); + let link; + + if ("link" in inviteLink) { + link = inviteLink.link; + } + + await addCommentToIssue(context, `A new workroom has been created for this task. [Join chat](${link})`, owner, repo, payload.issue.number); + } + + const promoteBotToAdmin = await mtProto.client.invoke( + new mtProto.api.messages.EditChatAdmin({ + chatId: chat.updates.chats[0].id, + isAdmin: true, + userId: botIdString, + }) + ); + + if (!promoteBotToAdmin) { + throw new Error("Failed to promote bot to admin"); + } + } catch (er) { + logger.error("Error in creating chat: ", { er }); + return { status: 500, reason: "chat_create_failed", content: { error: er } }; + } + + await context.adapters.supabase.chats.saveChat(chatId, payload.issue.title, payload.issue.node_id); + return { status: 200, reason: "chat_created" }; +} + +export async function closeChat(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { + const { payload, adapters: { supabase: { chats } }, logger } = context; + try { + const mtProto = new MtProto(context); + await mtProto.initialize(); + + logger.info("Closing chat with name: ", { chatName: payload.issue.title }); + const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); + + const fetchChat = await mtProto.client.invoke( + new mtProto.api.messages.GetFullChat({ + chatId: chat.chatId, + }) + ); + + if (!fetchChat) { + throw new Error("Failed to fetch chat"); + } + + let chatParticipants; + + if ("participants" in fetchChat.fullChat) { + chatParticipants = fetchChat.fullChat.participants; + } else { + throw new Error("Failed to fetch chat participants"); + } + + + if (chatParticipants.className === "ChatParticipants") { + + await mtProto.client.invoke( + new mtProto.api.messages.SendMessage({ + message: "This task has been closed and this chat has been archived.", + peer: new mtProto.api.InputPeerChat({ chatId: chat.chatId }), + }) + ); + + const userIDs = chatParticipants.participants.map((participant) => { + return participant.userId; + }); + + for (let i = 0; i < userIDs.length; i++) { + if (userIDs[i].toJSNumber() === context.config.botId) { + continue; + } + await mtProto.client.invoke( + new mtProto.api.messages.DeleteChatUser({ + chatId: chat.chatId, + userId: userIDs[i], + }) + ); + } + } + + await chats.updateChatStatus("closed", payload.issue.node_id); + + return { status: 200, reason: "chat_closed" }; + } catch (er) { + logger.error("Failed to close chat", { er }); + return { status: 500, reason: "chat_close_failed", content: { error: er } }; + } +} + +export async function reopenChat(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { + const { payload, adapters: { supabase: { chats } }, logger } = context; + try { + const mtProto = new MtProto(context); + await mtProto.initialize(); + + logger.info("Reopening chat with name: ", { chatName: payload.issue.title }); + const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); + + const fetchChat = await mtProto.client.invoke( + new mtProto.api.messages.GetFullChat({ + chatId: chat.chatId, + }) + ); + + if (!fetchChat) { + throw new Error("Failed to fetch chat"); + } + + const chatFull = fetchChat.fullChat as Api.ChatFull + const participants = chatFull.participants as Api.ChatParticipants; + + console.log("Participants: ", participants); + + for (const participant of participants.participants) { + if (participant instanceof mtProto.api.ChatParticipant) { + await mtProto.client.invoke( + new mtProto.api.messages.AddChatUser({ + chatId: chat.chatId, + userId: participant.userId, + fwdLimit: 50, + }) + ); + } + } + + return { status: 200, reason: "chat_reopened" }; + } catch (er) { + console.log(er); + logger.error("Failed to reopen chat", { er }); + return { status: 500, reason: "chat_reopen_failed", content: { error: er } }; + } +} diff --git a/src/handlers/callbacks-proxy.ts b/src/handlers/callbacks-proxy.ts index 8138c0b..b589224 100644 --- a/src/handlers/callbacks-proxy.ts +++ b/src/handlers/callbacks-proxy.ts @@ -1,22 +1,8 @@ +import { closeChat, createChat, reopenChat } from "#root/bot/mtproto-api/workrooms.js"; import { ProxyCallbacks } from "#root/types/proxy.js"; import { Context, SupportedEventsU } from "../types"; -import { createChat } from "../workflow-functions/create-chat"; import { closeWorkroom, createWorkroom, reOpenWorkroom } from "./github/workrooms"; -/** - * Why do we need this wrapper function? - * - * By using a generic `Function` type for the callback parameter, we bypass strict type - * checking temporarily. This allows us to pass a standard `Context` object, which we know - * contains the correct event and payload types, to the callback safely. - * - * We can trust that the `ProxyCallbacks` type has already ensured that each callback function - * matches the expected event and payload types, so this function provides a safe and - * flexible way to handle callbacks without introducing type or logic errors. - */ -function handleCallback(callback: Function, context: Context) { - return callback(context); -} /** * The `callbacks` object defines an array of callback functions for each supported event type. * @@ -36,6 +22,34 @@ const callbacks = { ] } as ProxyCallbacks; + +/** + * These are function which get dispatched by this worker to fire off workflows + * in the repository. We enter through the main `compute.yml` just like a typical + * action plugin would, we forward the same payload that the worker received to + * the workflow the same way that the kernel does. + * + * - First event fires, `issues.labeled` and the worker catches it. + * - The worker then dispatches a workflow to `compute.yml` with the event name as the input. + * - The workflow receives a `issues.labeled` payload but eventName is now WorkflowFunction (`create-telegram-chat`). + * - The workflow then runs the `createChat` function which needs a node env to run. + * + * I.e we're essentially running the first dual action/worker plugin which is + * ideal for telegram-bot as it's a bot that needs to be able to be super flexible. + */ +const workflowCallbacks = { + "issues.labeled": [ + createChat + ], + "issues.closed": [ + closeChat + ], + "issues.reopened": [ + reopenChat + ] +} as ProxyCallbacks; + + /** * The `proxyCallbacks` function returns a Proxy object that intercepts access to the * `callbacks` object. This Proxy enables dynamic handling of event callbacks, including: @@ -71,26 +85,6 @@ export function proxyCallbacks(context: Context): ProxyCallbacks { }); } -/** - * These are function which get dispatched by this worker to fire off workflows - * in the repository. We enter through the main `compute.yml` just like a typical - * action plugin would, we forward the same payload that the worker received to - * the workflow the same way that the kernel does. - * - * - First event fires, `issues.labeled` and the worker catches it. - * - The worker then dispatches a workflow to `compute.yml` with the event name as the input. - * - The workflow receives a `issues.labeled` payload but eventName is now WorkflowFunction (`create-telegram-chat`). - * - The workflow then runs the `createChat` function which needs a node env to run. - * - * I.e we're essentially running the first dual action/worker plugin which is - * ideal for telegram-bot as it's a bot that needs to be able to be super flexible. - */ -const workflowCallbacks = { - "issues.labeled": [ - createChat - ] -} as ProxyCallbacks; - export function proxyWorkflowCallbacks(context: Context): ProxyCallbacks { return new Proxy(workflowCallbacks, { @@ -101,12 +95,38 @@ export function proxyWorkflowCallbacks(context: Context): ProxyCallbacks { } return (async () => { try { - return await Promise.all(target[prop].map((callback) => handleCallback(callback, context))); + await Promise.all(target[prop].map((callback) => handleCallback(callback, context))); } catch (er) { context.logger.error(`Failed to handle event ${prop}`, { er }); - return { status: 500, reason: "failed" }; + await exit(1); } + await exit(0); })(); }, }); +} + +/** + * Why do we need this wrapper function? + * + * By using a generic `Function` type for the callback parameter, we bypass strict type + * checking temporarily. This allows us to pass a standard `Context` object, which we know + * contains the correct event and payload types, to the callback safely. + * + * We can trust that the `ProxyCallbacks` type has already ensured that each callback function + * matches the expected event and payload types, so this function provides a safe and + * flexible way to handle callbacks without introducing type or logic errors. + */ +function handleCallback(callback: Function, context: Context) { + return callback(context); +} + +/** + * Will be used to exit the process with a status code. + * + * 0 - Success + * 1 - Failure + */ +async function exit(status: number = 0) { + process.exit(status); } \ No newline at end of file diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts index e5a9833..0c04f76 100644 --- a/src/handlers/github/workrooms.ts +++ b/src/handlers/github/workrooms.ts @@ -1,24 +1,6 @@ -import { Chat } from "#root/adapters/supabase/helpers/chats.js"; import { CallbackResult } from "#root/types/proxy.js"; -import { TelegramBotSingleton } from "#root/utils/telegram-bot-single.js"; import { Context, SupportedEvents } from "../../types"; import { repositoryDispatch } from "../repository-dispatch"; -import { addCommentToIssue } from "./utils/add-comment-to-issues"; - -/** - * V1 specifications for the `workrooms` feature. - * - * - A workroom is created when an issue is labeled. - * - The workroom is created in a Telegram supergroup as a forum topic, not a new group. - * - The workroom is associated with the issue by storing the issue's node_id. - * - The workroom is closed when the issue is closed. - * - The workroom status is updated to "closed" in the database. - * - A comment is added to the issue when the workroom is created or closed. - * - * V2 specifications: - * - * - Replace the `Bot` api with the `MTProto` api in order to create new group chats. - */ export async function createWorkroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { await repositoryDispatch(context, "create-telegram-chat").catch(console.error); @@ -26,55 +8,11 @@ export async function createWorkroom(context: Context<"issues.labeled", Supporte } export async function closeWorkroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { - const { logger, config, adapters: { supabase: { chats } } } = context; - const bot = TelegramBotSingleton.getInstance().getBot(); - const title = context.payload.issue.title - const { issue, repository } = context.payload; - const { full_name } = repository; - const [owner, repo] = full_name.split("/"); - - logger.info(`Closing workroom for issue ${title}`); - - const workroom = await chats.getChatByTaskNodeId(issue.node_id) as Chat - - if (!workroom) { - return { status: 404, reason: "workroom_not_found" }; - } - - try { - await bot.api?.closeForumTopic(config.supergroupChatId, workroom.chatId); - await chats.updateChatStatus("closed", issue.node_id); - await addCommentToIssue(context, `Workroom closed for issue ${title}`, owner, repo, issue.number); - return { status: 200, reason: "workroom_closed" }; - } catch (er) { - await addCommentToIssue(context, logger.error(`Failed to close workroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); - return { status: 500, reason: "workroom_closing_failed" }; - } + await repositoryDispatch(context, "close-telegram-chat").catch(console.error); + return { status: 200, reason: "workflow_dispatched" }; } export async function reOpenWorkroom(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { - const { config, logger, adapters: { supabase: { chats } } } = context; - const bot = TelegramBotSingleton.getInstance().getBot(); - const title = context.payload.issue.title - const { issue, repository } = context.payload; - const { full_name } = repository; - const [owner, repo] = full_name.split("/"); - - logger.info(`Reopening workroom for issue ${title}`); - - const workroom = await chats.getChatByTaskNodeId(issue.node_id) as Chat - - if (!workroom) { - return { status: 404, reason: "workroom_not_found" }; - } - - try { - await bot.api?.reopenForumTopic(config.supergroupChatId, workroom.chatId); - await chats.updateChatStatus("reopened", issue.node_id); - await addCommentToIssue(context, `Workroom reopened for issue ${title}`, owner, repo, issue.number); - return { status: 200, reason: "workroom_reopened" }; - } catch (er) { - await addCommentToIssue(context, logger.error(`Failed to reopen workroom for issue ${title}`, { er }).logMessage.diff, owner, repo, issue.number); - return { status: 500, reason: "workroom_reopening_failed" }; - } + await repositoryDispatch(context, "reopen-telegram-chat").catch(console.error); + return { status: 200, reason: "workflow_dispatched" }; } diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts index f9d7e3e..5c6b9b6 100644 --- a/src/handlers/repository-dispatch.ts +++ b/src/handlers/repository-dispatch.ts @@ -1,5 +1,5 @@ -import { getAppOctokit } from "#root/helpers/authenticated-octokit.js"; import { PluginContext } from "#root/utils/plugin-context-single.js"; +import { App } from "octokit"; import { Context } from "../types"; /** @@ -7,11 +7,6 @@ import { Context } from "../types"; * * These workflows are extensions of the worker allowing for more complex operations * to be performed outside of Cloudflare Workers' limitations. - * - * @param env The environment variables for the worker instance. These - * will be taken from the repository's secrets. - * @param args The arguments passed to the workflow. - * */ export async function repositoryDispatch(context: Context, workflow: string) { @@ -20,7 +15,8 @@ export async function repositoryDispatch(context: Context, workflow: string) { const repository = "telegram--bot"; const owner = "ubq-testing"; const branch = "workflows"; - const app = await getAppOctokit(context); + const { env: { APP_ID, APP_PRIVATE_KEY } } = context; + const app = new App({ appId: APP_ID, privateKey: APP_PRIVATE_KEY }); const installation = await app.octokit.rest.apps.getRepoInstallation({ owner, repo: repository }); // Set the installation id for the octokit instance @@ -29,7 +25,6 @@ export async function repositoryDispatch(context: Context, workflow: string) { logger.info(`Dispatching workflow function: ${workflow}`); - /** * We'll hit the main workflow entry and pass in the same inputs so * that it essentially runs on the same context as the worker. diff --git a/src/handlers/github/utils/add-comment-to-issues.ts b/src/helpers/add-comment-to-issues.ts similarity index 94% rename from src/handlers/github/utils/add-comment-to-issues.ts rename to src/helpers/add-comment-to-issues.ts index ecd135f..7e446aa 100644 --- a/src/handlers/github/utils/add-comment-to-issues.ts +++ b/src/helpers/add-comment-to-issues.ts @@ -7,7 +7,7 @@ import { getDeepValue } from "#root/utils/get-deep-value.js"; */ export async function addCommentToIssue(context: Context, msg: string, owner?: string, repo?: string, issueNumber?: number) { const { logger, octokit } = context; - logger.info(`Adding comment to issue ${issueNumber}`); + logger.info(`Adding comment to ${owner}/${repo}#${issueNumber}`); if (!owner || !repo || !issueNumber) { owner = getDeepValue(context, "payload.repository.owner.login"); diff --git a/src/helpers/authenticated-octokit.ts b/src/helpers/authenticated-octokit.ts deleted file mode 100644 index 7df5d36..0000000 --- a/src/helpers/authenticated-octokit.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { App } from "octokit"; -import { Context } from "../types"; - -export async function getAppOctokit(context: Context) { - const { env: { APP_ID, APP_PRIVATE_KEY } } = context; - return new App({ appId: APP_ID, privateKey: APP_PRIVATE_KEY }); -} \ No newline at end of file diff --git a/src/types/env.ts b/src/types/env.ts index a950a2e..8b5fd7a 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -23,7 +23,7 @@ export const env = T.Object({ BOT_ADMINS: T.Transform(T.Unknown()).Decode((str) => Array.isArray(str) ? str.map(Number) : [Number(str)]).Encode((arr) => arr.toString()), ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))), SUPABASE_URL: T.String(), - SUPABASE_KEY: T.String(), + SUPABASE_SERVICE_KEY: T.String(), TELEGRAM_APP_ID: T.Transform(T.Unknown()).Decode((str) => Number(str)).Encode((num) => num.toString()), TELEGRAM_API_HASH: T.String(), APP_ID: T.Transform(T.Unknown()).Decode((str) => Number(str)).Encode((num) => num.toString()), diff --git a/src/types/plugin-inputs.ts b/src/types/plugin-inputs.ts index c745529..b2370ac 100644 --- a/src/types/plugin-inputs.ts +++ b/src/types/plugin-inputs.ts @@ -25,6 +25,8 @@ export const pluginSettingsSchema = T.Object({ */ supergroupChatId: T.Integer(), supergroupChatName: T.String(), + botId: T.Transform(T.Unknown()).Decode((value) => Number(value)).Encode((value) => value.toString()), + botUsername: T.String(), }); export const pluginSettingsValidator = new StandardValidator(pluginSettingsSchema); diff --git a/src/utils/errors.ts b/src/utils/errors.ts index 530f9de..8b2c490 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -1,6 +1,6 @@ import { LogReturn } from "@ubiquity-dao/ubiquibot-logger"; import { Context } from "../types"; -import { addCommentToIssue } from "#root/handlers/github/utils/add-comment-to-issues.js"; +import { addCommentToIssue } from "#root/helpers/add-comment-to-issues.js"; export function handleUncaughtError(error: unknown) { console.error(error); diff --git a/src/utils/plugin-context-single.ts b/src/utils/plugin-context-single.ts index d210a75..c5476fb 100644 --- a/src/utils/plugin-context-single.ts +++ b/src/utils/plugin-context-single.ts @@ -21,9 +21,7 @@ export class PluginContext { } static initialize(inputs: PluginInputs, env: Env): Context { - if (!PluginContext.instance) { - PluginContext.instance = new PluginContext(inputs, env); - } + PluginContext.instance = new PluginContext(inputs, env); return PluginContext.instance.getContext(); } @@ -50,7 +48,7 @@ export class PluginContext { adapters: {} as ReturnType, }; - ctx.adapters = createAdapters(createClient(ctx.env.SUPABASE_URL, ctx.env.SUPABASE_KEY), ctx); + ctx.adapters = createAdapters(createClient(ctx.env.SUPABASE_URL, ctx.env.SUPABASE_SERVICE_KEY), ctx); return ctx; } diff --git a/src/workflow-entry.ts b/src/workflow-entry.ts index f606254..d42f7c4 100644 --- a/src/workflow-entry.ts +++ b/src/workflow-entry.ts @@ -4,12 +4,10 @@ import { Value } from "@sinclair/typebox/value"; import { envValidator, pluginSettingsSchema, PluginInputs, pluginSettingsValidator } from "./types"; import { PluginContext } from "./utils/plugin-context-single"; import { proxyWorkflowCallbacks } from "./handlers/callbacks-proxy"; -import { bubbleUpErrorComment, sanitizeMetadata } from "./utils/errors"; +import { bubbleUpErrorComment } from "./utils/errors"; import dotenv from "dotenv"; -import { LOG_LEVEL } from "@ubiquity-dao/ubiquibot-logger"; dotenv.config(); - /** * How a GitHub action executes the plugin. */ @@ -29,7 +27,7 @@ export async function run() { TELEGRAM_APP_ID: process.env.TELEGRAM_APP_ID, TELEGRAM_API_HASH: process.env.TELEGRAM_API_HASH, SUPABASE_URL: process.env.SUPABASE_URL, - SUPABASE_KEY: process.env.SUPABASE_KEY, + SUPABASE_SERVICE_KEY: process.env.SUPABASE_SERVICE_KEY, APP_PRIVATE_KEY: process.env.APP_PRIVATE_KEY, APP_ID: process.env.APP_ID, } diff --git a/src/workflow-functions/bot.ts b/src/workflow-functions/bot.ts deleted file mode 100644 index 81befae..0000000 --- a/src/workflow-functions/bot.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Context } from '#root/types/context.js'; -import { TelegramClient } from 'telegram'; -import { Api } from 'telegram/tl'; -import { MemorySession } from 'telegram/sessions'; -import { TelegramClientParams } from 'telegram/client/telegramBaseClient'; - -/** - * This is a different client from the worker instance. This requires a Node - * environment to run and is used to interact with the Telegram API as - * opposed to just the Bot API that the worker instance uses. - */ -export class MtProtoSingleton { - private static instance: MtProtoSingleton; - private static client: TelegramClient; - private static api: typeof Api; - - private constructor() { } - - static async initialize(env: Context["env"]) { - if (!MtProtoSingleton.instance) { - MtProtoSingleton.instance = new MtProtoSingleton(); - MtProtoSingleton.api = Api; - MtProtoSingleton.client = await mtProtoInit(env, MtProtoSingleton.api); - } - return MtProtoSingleton.instance; - } - - static getInstance(env: Context["env"]) { - if (!MtProtoSingleton.instance) { - return this.initialize(env) - } - return MtProtoSingleton.instance; - } - - getClient() { - return MtProtoSingleton.client; - } - - getApi() { - return MtProtoSingleton.api; - } -} - -async function mtProtoInit(env: Context["env"], api: typeof Api) { - const { TELEGRAM_API_HASH, TELEGRAM_APP_ID, BOT_TOKEN } = env - - if (!TELEGRAM_API_HASH || !TELEGRAM_APP_ID || !BOT_TOKEN) { - throw new Error("Missing required environment variables for Telegram API") - } - - const session = new MemorySession(); - session.save(); - - const clientParams: TelegramClientParams = { - connectionRetries: 5, - } - - const client = new TelegramClient( - session, - TELEGRAM_APP_ID, - TELEGRAM_API_HASH, - clientParams - ); - await client.connect(); - - client.invoke(new api.auth.ImportBotAuthorization({ - apiId: TELEGRAM_APP_ID, - apiHash: TELEGRAM_API_HASH, - botAuthToken: BOT_TOKEN, - })); - - - return client; -} \ No newline at end of file diff --git a/src/workflow-functions/create-chat.ts b/src/workflow-functions/create-chat.ts deleted file mode 100644 index 7269fea..0000000 --- a/src/workflow-functions/create-chat.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Context, SupportedEvents } from "#root/types/context"; -import { CallbackResult } from "#root/types/proxy.js"; -import { MtProtoSingleton } from "./bot"; - -export async function createChat(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { - console.log("Creating chat"); - try { - const { payload, env } = context; - const chatName = payload.issue.title; - - const mtProto = await MtProtoSingleton.getInstance(env); - const client = mtProto.getClient(); - const api = mtProto.getApi(); - console.log("Creating chat with name: ", chatName); - const chat = await client.invoke( - new api.channels.CreateChannel({ - title: chatName, - broadcast: true, - about: payload.issue.body || "No description provided", - }) - ); - - console.log("Chat created: ", chat); - - return { status: 200, reason: "chat_created" }; - } catch (er) { - context.logger.error("Failed to create chat", { er }); - return { status: 500, reason: "chat_creation_failed", content: { error: er } }; - } - -} diff --git a/yarn.lock b/yarn.lock index 180e8f4..acd05ee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3287,6 +3287,11 @@ ajv@^8.11.0: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" +ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + integrity sha512-wiXutNjDUlNEDWHcYH3jtZUhd3c4/VojassD8zHdHCY13xbZy2XbW+NKQwA0tWGBVzDA9qEzYwfoSsWmviidhw== + ansi-escapes@^4.2.1, ansi-escapes@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -3301,6 +3306,11 @@ ansi-escapes@^7.0.0: dependencies: environment "^1.0.0" +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -3311,6 +3321,11 @@ ansi-regex@^6.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -3606,6 +3621,14 @@ babel-preset-jest@^29.6.3: babel-plugin-jest-hoist "^29.6.3" babel-preset-current-node-syntax "^1.0.0" +babel-runtime@^6.6.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -3773,6 +3796,17 @@ chalk-template@^1.1.0: dependencies: chalk "^5.2.0" +chalk@^1.0.0, chalk@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -3848,6 +3882,13 @@ clear-module@^4.1.2: parent-module "^2.0.0" resolve-from "^5.0.0" +cli-cursor@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + integrity sha512-25tABq090YNKkF6JH7lcwO0zFJTRke4Jcq9iX2nr/Sz0Cjjv4gckmwlW6Ty/aoyFd6z3ysR2hMGC2GFugmBo6A== + dependencies: + restore-cursor "^1.0.1" + cli-cursor@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-5.0.0.tgz#24a4831ecf5a6b01ddeb32fb71a4b2088b0dce38" @@ -3868,6 +3909,11 @@ cli-truncate@^4.0.0: slice-ansi "^5.0.0" string-width "^7.0.0" +cli-width@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" + integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== + cli-width@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" @@ -3892,6 +3938,11 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA== + collect-v8-coverage@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" @@ -4006,6 +4057,11 @@ core-js-compat@^3.31.0, core-js-compat@^3.38.0: dependencies: browserslist "^4.23.3" +core-js@^2.4.0: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + core-util-is@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -4737,7 +4793,7 @@ escalade@^3.1.1, escalade@^3.1.2: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== -escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== @@ -5118,6 +5174,11 @@ execa@^8.0.1, execa@~8.0.1: signal-exit "^4.1.0" strip-final-newline "^3.0.0" +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + integrity sha512-MsG3prOVw1WtLXAZbM3KiYtooKR1LvxHh3VHsVtIy0uiUu8usxgB/94DP2HxtD/661lLdB6yzQ09lGJSQr6nkg== + exit-hook@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-2.2.1.tgz#007b2d92c6428eda2b76e7016a34351586934593" @@ -5216,6 +5277,14 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +figures@^1.3.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + integrity sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ== + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + file-entry-cache@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" @@ -5533,6 +5602,13 @@ graphql@^16.8.1: resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.9.0.tgz#1c310e63f16a49ce1fbb230bd0a000e99f6f115f" integrity sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw== +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== + dependencies: + ansi-regex "^2.0.0" + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -5693,6 +5769,35 @@ ini@4.1.1: resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" integrity sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g== +input@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/input/-/input-1.0.1.tgz#26bfb5315959c403e9317175cf8f9894e97e5742" + integrity sha512-5DKQKQ7Nm/CaPGYKF74uUvk5ftC3S04fLYWcDrNG2rOVhhRgB4E2J8JNb7AAh+RlQ/954ukas4bEbrRQ3/kPGA== + dependencies: + babel-runtime "^6.6.1" + chalk "^1.1.1" + inquirer "^0.12.0" + lodash "^4.6.1" + +inquirer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" + integrity sha512-bOetEz5+/WpgaW4D1NYOk1aD+JCqRjqu/FwRFgnIfiP7FC/zinsrfyO1vlS3nyH/R7S0IH3BIHBu4DBIDSqiGQ== + dependencies: + ansi-escapes "^1.1.0" + ansi-regex "^2.0.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^2.0.0" + figures "^1.3.5" + lodash "^4.3.0" + readline2 "^1.0.1" + run-async "^0.1.0" + rx-lite "^3.1.2" + string-width "^1.0.1" + strip-ansi "^3.0.0" + through "^2.3.6" + internal-slot@^1.0.4, internal-slot@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" @@ -5803,6 +5908,13 @@ is-finalizationregistry@^1.0.2: dependencies: call-bind "^1.0.2" +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw== + dependencies: + number-is-nan "^1.0.0" + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -6730,7 +6842,7 @@ lodash.upperfirst@^4.3.1: resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== -lodash@^4.17.21: +lodash@^4.17.21, lodash@^4.3.0, lodash@^4.6.1: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -6964,6 +7076,11 @@ mustache@^4.2.0: resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== +mute-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" + integrity sha512-EbrziT4s8cWPmzr47eYVW3wimS4HsvlnV5ri1xw1aR6JQo/OrJX5rkl32K/QQHdxeabJETtfeaROGhd8W7uBgg== + mute-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" @@ -7077,7 +7194,12 @@ npm-run-path@^5.1.0: dependencies: path-key "^4.0.0" -object-assign@^4.1.1: +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== + +object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -7175,6 +7297,11 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +onetime@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + integrity sha512-GZ+g4jayMqzCRMgB2sol7GiCLjKfS1PINkjmx8spcKce1LiVqcbQreXwqs2YAFXC6R03VIG28ZS31t8M866v6A== + onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -7646,6 +7773,15 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +readline2@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" + integrity sha512-8/td4MmwUB6PkZUbV25uKz7dfrmjYWxsW8DVfibWdlHRk/l/DfHKn4pU+dfcoGLFgWOdyGCzINRQD7jn+Bv+/g== + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + mute-stream "0.0.5" + real-cancellable-promise@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/real-cancellable-promise/-/real-cancellable-promise-1.2.0.tgz#f365e78b29c6a2303584f2c308959b415401056a" @@ -7688,6 +7824,11 @@ regenerate@^1.4.2: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + regenerator-runtime@^0.14.0: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" @@ -7802,6 +7943,14 @@ resolve@^2.0.0-next.5: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + integrity sha512-reSjH4HuiFlxlaBaFCiS6O76ZGG2ygKoSlCsipKdaZuKSPx/+bt9mULkn4l0asVzbEfQQmXRg6Wp6gv6m0wElw== + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + restore-cursor@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-5.1.0.tgz#0766d95699efacb14150993f55baf0953ea1ebe7" @@ -7843,6 +7992,13 @@ rollup-pluginutils@^2.8.1: dependencies: estree-walker "^0.6.1" +run-async@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" + integrity sha512-qOX+w+IxFgpUpJfkv2oGN0+ExPs68F4sZHfaRRx4dDexAQkG83atugKVEylyT5ARees3HBbfmuvnjbrd8j9Wjw== + dependencies: + once "^1.3.0" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -7850,6 +8006,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rx-lite@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" + integrity sha512-1I1+G2gteLB8Tkt8YI1sJvSIfa0lWuRtC8GjvtyPBcLSF5jBCCJJqKrpER5JU5r6Bhe+i9/pK3VMuUcXu0kdwQ== + safe-array-concat@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" @@ -8209,6 +8370,15 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw== + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -8306,6 +8476,13 @@ string_decoder@^1.1.1, string_decoder@^1.3.0: dependencies: safe-buffer "~5.2.0" +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -8355,6 +8532,11 @@ summary@2.1.0: resolved "https://registry.yarnpkg.com/summary/-/summary-2.1.0.tgz#be8a49a0aa34eb6ceea56042cae88f8add4b0885" integrity sha512-nMIjMrd5Z2nuB2RZCKJfFMjgS3fygbeyGk9PxPPaJR1RIcyN9yn4A63Isovzm3ZtQuEkLBVgMdPup8UeLH7aQw== +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -8443,7 +8625,7 @@ thread-stream@^3.0.0: dependencies: real-require "^0.2.0" -through@2, "through@>=2.2.7 <3", through@~2.3, through@~2.3.1: +through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== From 5f5f1097f62df4f00d4bc38e709b9537a4738d38 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 12 Sep 2024 00:47:23 +0100 Subject: [PATCH 36/76] chore: squashed workflows --- .cspell.json | 13 +- .github/workflows/compute.yml | 3 +- README.md | 195 +++++++---- eslint.config.mjs | 3 +- manifest.json | 13 +- package.json | 6 +- src/adapters/supabase/helpers/chats.ts | 166 ++++++---- src/bot/features/admin/admin.ts | 25 +- src/bot/features/commands/bot-id.ts | 26 +- src/bot/features/commands/chat-id.ts | 25 +- src/bot/features/commands/user-id.ts | 25 +- src/bot/features/helpers/unhandled.ts | 26 +- src/bot/features/welcome.ts | 20 +- src/bot/filters/is-admin.ts | 6 +- src/bot/grammy-context.ts | 52 ++- src/bot/handlers/commands/setcommands.ts | 56 ++-- src/bot/handlers/error.ts | 21 +- src/bot/helpers/grammy-context.ts | 37 +++ src/bot/helpers/logging.ts | 20 +- src/bot/index.ts | 82 +++-- src/bot/middlewares/session.ts | 8 +- src/bot/mtproto-api/README.md | 6 - src/bot/mtproto-api/bot/mtproto.ts | 71 ++-- .../bot/scripts/sms-auth/auth-handler.ts | 112 ++++--- .../bot/scripts/sms-auth/base-mtproto.ts | 99 +++--- .../bot/scripts/sms-auth/sms-auth.ts | 9 +- src/bot/mtproto-api/bot/session.ts | 68 ++-- src/bot/mtproto-api/workrooms.ts | 306 +++++++++--------- src/bot/mtproto-api/workrooms/close-chat.ts | 139 ++++++++ src/bot/mtproto-api/workrooms/create-chat.ts | 79 +++++ src/bot/mtproto-api/workrooms/reopen-chat.ts | 93 ++++++ src/bot/strings.ts | 8 +- src/handlers/callbacks-proxy.ts | 146 ++++----- src/handlers/github-webhook.ts | 50 +-- src/handlers/github/workrooms.ts | 12 +- src/handlers/repository-dispatch.ts | 72 ++--- src/handlers/telegram-webhook.ts | 21 +- src/handlers/worker-proxy.ts | 67 ++++ src/handlers/workflow-functions.ts | 54 ++++ src/handlers/workflow-proxy.ts | 54 ++++ src/helpers/add-comment-to-issues.ts | 44 +-- src/logger.ts | 5 - src/plugin.ts | 19 +- src/server/environment.ts | 8 - src/server/index.ts | 89 +++-- src/server/middlewares/logger.ts | 13 +- src/server/middlewares/request-logger.ts | 24 +- src/types/context.ts | 6 +- src/types/env.ts | 91 ++++-- src/types/plugin-context-single.ts | 61 ++++ src/types/plugin-inputs.ts | 19 +- src/types/proxy.ts | 13 +- src/types/telegram-bot-single.ts | 54 ++++ src/types/typeguards.ts | 11 +- src/utils/add-comment-to-issues.ts | 33 ++ src/utils/errors.ts | 30 +- src/utils/get-deep-value.ts | 21 +- src/utils/logger.ts | 5 + src/utils/plugin-context-single.ts | 92 +++--- src/utils/smee.ts | 10 +- src/utils/telegram-bot-single.ts | 46 --- src/worker.ts | 13 +- src/workflow-entry.ts | 10 +- supabase/migrations.sql | 20 ++ tsconfig.json | 17 +- 65 files changed, 1885 insertions(+), 1163 deletions(-) create mode 100644 src/bot/helpers/grammy-context.ts delete mode 100644 src/bot/mtproto-api/README.md create mode 100644 src/bot/mtproto-api/workrooms/close-chat.ts create mode 100644 src/bot/mtproto-api/workrooms/create-chat.ts create mode 100644 src/bot/mtproto-api/workrooms/reopen-chat.ts create mode 100644 src/handlers/worker-proxy.ts create mode 100644 src/handlers/workflow-functions.ts create mode 100644 src/handlers/workflow-proxy.ts delete mode 100644 src/logger.ts delete mode 100644 src/server/environment.ts create mode 100644 src/types/plugin-context-single.ts create mode 100644 src/types/telegram-bot-single.ts create mode 100644 src/utils/add-comment-to-issues.ts create mode 100644 src/utils/logger.ts delete mode 100644 src/utils/telegram-bot-single.ts create mode 100644 supabase/migrations.sql diff --git a/.cspell.json b/.cspell.json index c2b732e..d95b08b 100644 --- a/.cspell.json +++ b/.cspell.json @@ -20,7 +20,18 @@ "Typeguards", "sonarjs", "knip", - "mischeck" + "mischeck", + "Hono", + "hono", + "mtproto", + "grammyjs", + "setcommands", + "grammyjs", + "botid", + "chatid", + "myid", + "baseclass", + "unarchived" ], "dictionaries": ["typescript", "node", "software-terms"], "import": ["@cspell/dict-typescript/cspell-ext.json", "@cspell/dict-node/cspell-ext.json", "@cspell/dict-software-terms"], diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index bb2649d..491439b 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -24,7 +24,6 @@ jobs: env: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} SUPABASE_SERVICE_KEY: ${{ secrets.SUPABASE_SERVICE_KEY }} - BOT_TOKEN: ${{ secrets.BOT_TOKEN }} BOT_ADMINS: ${{ secrets.BOT_ADMINS }} BOT_WEBHOOK: ${{ secrets.BOT_WEBHOOK }} @@ -63,4 +62,4 @@ jobs: TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }} APP_ID: ${{ secrets.APP_ID }} - APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} \ No newline at end of file + APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} diff --git a/README.md b/README.md index a27db3e..117a42a 100644 --- a/README.md +++ b/README.md @@ -1,86 +1,157 @@ -# `@ubiquibot/plugin-template` +# `@ubiquity-os/telegram-bot` -## Prerequisites +A dual-architecture Telegram bot for Ubiquity OS, uniquely combining Cloudflare Workers and GitHub Actions to deliver seamless integration with both Telegram and GitHub. This hybrid plugin is the first of its kind to support both worker and workflow functionality, running across Cloudflare V8 and Node.js environments for enhanced flexibility and performance across multiple runtimes. -- A good understanding of how the [kernel](https://github.com/ubiquity/ubiquibot-kernel) works and how to interact with it. -- A basic understanding of the Ubiquibot configuration and how to define your plugin's settings. +## Table of Contents -## Getting Started +- [High-Level Overview](#high-level-overview) + - [Architecture Breakdown](#architecture-breakdown) + - [Telegram Bot Components](#telegram-bot-components) + - [Ubiquity OS Plugin](#ubiquity-os-plugin) + - [Worker Instance](#worker-instance) + - [Workflow Instance](#workflow-instance) +- [Getting Started](#getting-started) + - [Prerequisites](#prerequisites) + - [Installation](#installation) + - [Environment Variables](#environment-variables) + - [Supabase Configuration](#supabase-configuration) + - [Telegram Configuration](#telegram-configuration) + - [GitHub Configuration](#github-configuration) + - [Usage](#usage) + - [Commands](#commands) +- [Repository Structure](#repository-structure) +- [Considerations](#considerations) -1. Create a new repository using this template. -2. Clone the repository to your local machine. -3. Install the dependencies preferably using `yarn` or `bun`. +## High-Level Overview -## Creating a new plugin +This bot operates in two parts: -- If your plugin is to be used as a slash command which should have faster response times as opposed to longer running GitHub action tasks, you should use the `worker` type. +- **Bot API**: Hosted on Cloudflare Workers, interacts with the Telegram Bot API. +- **Client API**: Runs in a Node.js environment (GitHub Actions) and interacts with the MTProto API via a Telegram User account. -1. Ensure you understand and have setup the [kernel](https://github.com/ubiquity/ubiquibot-kernel). -2. Update [compute.yml](./.github/workflows/compute.yml) with your plugin's name and update the `id`. -3. Update [context.ts](./src/types/context.ts) with the events that your plugin will fire on. -4. Update [manifest.json](./manifest.json) with a proper description of your plugin. -5. Update [plugin-inputs.ts](./src/types/plugin-inputs.ts) to match the `with:` settings in your org or repo level configuration. +### Architecture Breakdown -- Your plugin config should look similar to this: +#### Telegram Bot Components -```yml -plugins: - - name: hello-world - id: hello-world - uses: - - plugin: http://localhost:4000 - with: - # Define configurable items here and the kernel will pass these to the plugin. - configurableResponse: "Hello, is it me you are looking for?" -``` +- **Worker Instance**: Runs Bot API methods on Cloudflare Workers. Handles bot commands, events, and chat interactions using a Telegram Bot created via BotFather. +- **Client Instance**: Runs Client API methods on GitHub Actions, responsible for features unavailable to the bot, like creating groups or sending messages as a user. + +#### Ubiquity OS Plugin + +- **Worker Plugin**: This is a worker plugin with workflow capabilities, allowing it to run on both Cloudflare Workers and GitHub Actions. +- **Actions as a Feature**: By forwarding worker requests to the workflows, we enable collaboration between the two, maximizing functionality. +- **Hybrid Architecture**: Combines the best of both worlds, leveraging Cloudflare Workers for speed and GitHub Actions for long-running features or those that require a Node.js environment. +- **Bridges the Gap**: Connects our GitHub events to our Telegram bot instantaneously, enabling real-time interactions and seamless integration. -###### At this stage, your plugin will fire on your defined events with the required settings passed in from the kernel. You can now start writing your plugin's logic. +### Worker Instance -6. Start building your plugin by adding your logic to the [plugin.ts](./src/plugin.ts) file. +1. **Hono App**: Handles webhook payloads from Telegram, manages bot commands and event reactions. +2. **GrammyJS**: Utilizes GrammyJS for interacting with the Telegram Bot API, responsible for sending/editing messages, handling commands, and more. Learn more [here](https://grammy.dev). + +### Workflow Instance + +1. **NodeJS Server**: Handles tasks beyond the bot’s capabilities, such as managing Telegram groups or sending direct messages. +2. **GramJS**: Built on top of [Telethon](https://docs.telethon.dev/en/stable/), interacts with the MTProto API for more advanced Telegram functionalities. Learn more [here](https://gram.js.org/beta/). + +## Getting Started -## Testing a plugin +### Prerequisites -### Worker Plugins +- Personal Telegram account +- Telegram Bot Token (via BotFather) +- Ubiquity OS Kernel -- `yarn/bun worker` - to run the worker locally. -- To trigger the worker, `POST` requests to http://localhost:4000/ with an event payload similar to: +### Installation -```ts -await fetch("http://localhost:4000/", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - stateId: "", - eventName: "", - eventPayload: "", - settings: "", - ref: "", - authToken: "", - }), -}); +#### Environment Variables + +Define these in both `dev.vars` and your GitHub repository secrets: + +```bash +BOT_TOKEN=123:xyz # Telegram Bot Token from BotFather +BOT_WEBHOOK=... # Cloudflare Worker URL +BOT_WEBHOOK_SECRET=... # Cloudflare Worker Secret +BOT_ADMINS=[1234,5678] # Telegram User IDs +SUPABASE_URL=... # Supabase URL +SUPABASE_SERVICE_KEY=... # Supabase Service Key +TELEGRAM_APP_ID=12345678 # Telegram App ID +TELEGRAM_API_HASH=... # Telegram API Hash +APP_PRIVATE_KEY=... # GitHub App Private Key +APP_ID=123456 # GitHub App ID ``` -A full example can be found [here](https://github.com/ubiquibot/assistive-pricing/blob/623ea3f950f04842f2d003bda3fc7b7684e41378/tests/http/request.http). +#### Supabase Configuration + +1. Create or use an existing Supabase project. +2. Copy and run the SQL migration file from `./supabase/migrations` in the Supabase dashboard. +3. Add your `SUPABASE_URL` and `SUPABASE_SERVICE_KEY` to your environment variables. + +#### Telegram Configuration -### Action Plugins +1. Create a new bot using [BotFather](https://t.me/BotFather). +2. Add your `BOT_TOKEN`, `TELEGRAM_APP_ID`, `TELEGRAM_API_HASH`, and `BOT_ADMINS` to the environment variables. +3. Use [Smee.io](https://smee.io/new) to create a webhook and add the URL as `BOT_WEBHOOK`. +4. Generate a secret for `BOT_WEBHOOK_SECRET` to verify webhook requests. -- Ensure the kernel is running and listening for events. -- Fire an event in/to the repo where the kernel is installed. This can be done in a number of ways, the easiest being via the GitHub UI or using the GitHub API, such as posting a comment, opening an issue, etc in the org/repo where the kernel is installed. -- The kernel will process the event and dispatch it using the settings defined in your `.ubiquibot-config.yml`. -- The `compute.yml` workflow will run and execute your plugin's logic. -- You can view the logs in the Actions tab of your repo. +#### GitHub Configuration -[Nektos Act](https://github.com/nektos/act) - a tool for running GitHub Actions locally. +1. Ensure your Ubiquity OS Kernel is set up. +2. Add `APP_PRIVATE_KEY` and `APP_ID` to your environment variables. +3. Configure the plugin in your private organization’s repository: -## More information +```yaml +- uses: + - plugin: http://localhost:3000 + runsOn: ["issues.opened", "issues.labeled", "issues.reopened", "issues.closed"] + skipBotEvents: false + with: + botId: 00000000 + botUsername: yourBotName +``` + +### Usage + +1. Follow each part of the environment setup to configure your bot. +2. Start your Ubiquity OS Kernel with the plugin installed in your repository. +3. Run `yarn sms-auth` to authenticate your personal Telegram account with MTProto. +4. Start the worker instance with `yarn worker`. +5. In another terminal, run `smee -u https://smee.io/your-webhook-url -P "/webhook"` to receive Telegram webhook payloads locally. +6. Interact with the bot in Telegram chats or trigger GitHub webhooks as defined in `manifest.json`. + +### Commands + +TODO: Commands are not fully implemented yet. A couple of helper commands for obtaining IDs etc are available. + +## Repository Structure + +```plaintext +. +├── .github/ # GitHub Actions workflows (CI/CD, not for workflow-function logic) +├── manifest.json # Plugin manifest for Ubiquity OS Kernel +├── supabase/ # SQL migration files for Supabase schema +├── src/ # Source code +│ ├── adapters/ # Storage adapters (e.g., Supabase integrations) +│ ├── bot/ # Core Telegram bot functionality (Worker and Workflow) +│ │ ├── features/ # Bot features, including commands and event handlers +│ │ ├── filters/ # Grammy filters (e.g., isAdmin, isPrivateChat) +│ │ ├── handlers/ # Stateful command handlers based on chat types or user privileges +│ │ ├── helpers/ # Utility functions like logging and custom Grammy contexts +│ │ ├── middlewares/ # Middleware functions (e.g., rate limiting, session management) +│ │ ├── mtproto-api/ # MTProto API client for advanced Telegram features +│ │ │ ├── bot/ # MTProto API session management, 2FA auth scripts, Telegram client setup +│ │ │ ├── workrooms/ # A collection of Workflow-functions leveraging MTProto API +│ │ ├── index/ # Bot initialization, where commands and features are registered +│ ├── handlers/ # General plugin handlers (e.g., GitHub API functions, webhook processing) +│ ├── server/ # Hono app for managing Cloudflare Worker instance of the bot +│ ├── types/ # Typebox schemas, TypeScript types, Singleton classes +│ ├── utils/ # General utility functions and helpers +│ ├── worker.ts # Main entry point, routes events (GitHub or Telegram) to appropriate handlers +│ ├── plugin.ts # GitHub event handler, forwards events to `workflow-entry.ts` or processes them +│ ├── workflow-entry.ts # Handles forwarded GitHub events, MTProto API interactions, and workflow logic +``` -- [Full Ubiquibot Configuration](https://github.com/ubiquity/ubiquibot/blob/0fde7551585499b1e0618ec8ea5e826f11271c9c/src/types/configuration-types.ts#L62) - helpful for defining your plugin's settings as they are strongly typed and will be validated by the kernel. -- [Ubiquibot V1](https://github.com/ubiquity/ubiquibot) - helpful for porting V1 functionality to V2, helper/utility functions, types, etc. Everything is based on the V1 codebase but with a more modular approach. When using V1 code, keep in mind that most all code will need refactored to work with the new V2 architecture. +## Considerations -## Examples +The bot has two "branches" due to Cloudflare Workers' limitations in handling long-running processes. The **Worker** handles most bot commands and API interactions, while the **Workflow** manages features the bot cannot perform. -- [Start/Stop Slash Command](https://github.com/ubq-testing/start-stop-module) - simple -- [Assistive Pricing Plugin](https://github.com/ubiquibot/assistive-pricing) - complex -- [Conversation Rewards](https://github.com/ubiquibot/conversation-rewards) - really complex +Most functionality is handled by the **Bot API**; the **Client API** is only used for advanced tasks. Due to the nature of the MTProto API, the owner of the personal account must run `yarn sms-auth` to authenticate the bot once, after which it can run uninterrupted. It is not fool-proof and it can be "knocked out" by erroneous auth replacement ceremonies. diff --git a/eslint.config.mjs b/eslint.config.mjs index e53d263..e04c686 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -9,7 +9,7 @@ export default tsEslint.config({ "@typescript-eslint": tsEslint.plugin, "check-file": checkFile, }, - ignores: [".github/knip.ts"], + ignores: [".github/knip.ts", "tests/**/*.ts", "eslint.config.mjs"], extends: [eslint.configs.recommended, ...tsEslint.configs.recommended, sonarjs.configs.recommended], languageOptions: { parser: tsEslint.parser, @@ -65,6 +65,7 @@ export default tsEslint.config({ "sonarjs/no-element-overwrite": "error", "sonarjs/no-identical-conditions": "error", "sonarjs/no-identical-expressions": "error", + "sonarjs/new-cap": "off", "@typescript-eslint/naming-convention": [ "error", { diff --git a/manifest.json b/manifest.json index d91848e..075f5f1 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,5 @@ { - "name": "ts-template", - "description": "ts-template for Ubiquibot plugins.", - "ubiquity:listeners": [ - "issues.opened", - "issues.labeled", - "issues.closed", - "issues.reopened" - ] -} \ No newline at end of file + "name": "ubiquity-os/telegram-bot", + "description": "Part kernel plugin, part Telegram kernel. This bot is designed to be a bridge between UbiquityOS and Telegram.", + "ubiquity:listeners": ["issues.opened", "issues.labeled", "issues.closed", "issues.reopened"] +} diff --git a/package.json b/package.json index 6b894a9..c05add9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "telegram-bot", + "name": "@ubiquity-os/telegram-bot", "version": "0.1.0", - "description": "Ubiquibot plugin template repository with TypeScript support.", + "description": "Part kernel plugin, part Telegram kernel. This bot is designed to be a bridge between UbiquityOS and Telegram.", "author": "Ubiquity DAO", "license": "MIT", "main": "src/worker.ts", @@ -112,4 +112,4 @@ ] }, "packageManager": "yarn@1.22.22" -} \ No newline at end of file +} diff --git a/src/adapters/supabase/helpers/chats.ts b/src/adapters/supabase/helpers/chats.ts index 8ef9db6..39546fe 100644 --- a/src/adapters/supabase/helpers/chats.ts +++ b/src/adapters/supabase/helpers/chats.ts @@ -3,94 +3,120 @@ import { Super } from "./supabase"; import { Context } from "../../../types/context"; export type Chat = { - chatId: number; - chatName: string; - taskNodeId: string; - status: string; -} + chatId: number; + chatName: string; + taskNodeId: string; + status: string; +}; /** * Handles all telegram chat storage and retrieval */ export class Chats extends Super { - constructor(supabase: SupabaseClient, context: Context) { - super(supabase, context); + constructor(supabase: SupabaseClient, context: Context) { + super(supabase, context); + } + + /** + * Used for storing the userIds of a chat before we + * ban all of them and archive the chat. + */ + async userSnapshot(chatId: number, userIds: number[]) { + const chat = await this.getChatByChatId(chatId); + const { error } = await this.supabase.from("chats").upsert({ ...chat, user_ids: userIds }); + if (error) { + this.context.logger.error("Failed to save chat users", { chatId, userIds, er: error }); + } else { + this.context.logger.info("Successfully saved chat users", { chatId, userIds }); + } + } + + /** + * Returns the userIds of a previously closed chat otherwise an empty array. + */ + async getChatUsers(chatId: number) { + const { data, error } = await this.supabase.from("chats").select("user_ids").eq("chat_id", chatId).single(); + if (error || !data) { + this.context.logger.error("No chat users found", { chatId }); + } else { + this.context.logger.info("Successfully fetched chat users", { chatId }); } - async updateChatStatus(status: string, taskNodeId?: string, chatId?: number) { - if (!taskNodeId && !chatId) { - this.context.logger.error("No taskNodeId or chatId provided to update chat status"); - return; - } - - let chat; - - if (taskNodeId) { - chat = await this.getChatByTaskNodeId(taskNodeId); - } else if (chatId) { - chat = await this.getChatByChatId(chatId); - } + return data; + } - if (!chat) { - this.context.logger.error("No chat found to update chat status"); - return; - } + async updateChatStatus(status: "open" | "closed" | "reopened", taskNodeId?: string, chatId?: number) { + if (!taskNodeId && !chatId) { + this.context.logger.error("No taskNodeId or chatId provided to update chat status"); + return; + } - const { error } = (await this.supabase.from("chats").upsert({ ...chat, status })) + let chat; - if (error) { - this.context.logger.error("Failed to update chat status", { chatId, taskNodeId, er: error }); - } else { - this.context.logger.info("Successfully updated chat status", { chatId, taskNodeId }); - } + if (taskNodeId) { + chat = await this.getChatByTaskNodeId(taskNodeId); + } else if (chatId) { + chat = await this.getChatByChatId(chatId); } - - async saveChat(chatId: number, chatName: string, taskNodeId: string) { - const { error } = await this.supabase.from("chats").insert([{ chatId, chatName, taskNodeId, status: "open" }]) - if (error) { - this.context.logger.error("Failed to save chat", { chatId, chatName, taskNodeId, er: error }); - } else { - this.context.logger.info("Successfully saved chat", { chatId, chatName }); - } + if (!chat) { + this.context.logger.error("No chat found to update chat status"); + return; } - async getChatByChatId(chatId: number) { - const { data, error } = (await this.supabase.from("chats").select("*").eq("chatId", chatId).single()) - if (error || !data) { - this.context.logger.error("No chat found", { chatId }); - } else { - this.context.logger.info("Successfully fetched chat", { chatId }); - } + const { error } = await this.supabase.from("chats").upsert({ ...chat, status }); - return data; + if (error) { + this.context.logger.error("Failed to update chat status", { chatId, taskNodeId, er: error }); + } else { + this.context.logger.info("Successfully updated chat status", { chatId, taskNodeId }); + } + } + + async saveChat(chatId: number, chatName: string, taskNodeId: string) { + const { error } = await this.supabase.from("chats").insert([{ chat_id: chatId, chat_name: chatName, task_node_id: taskNodeId, status: "open" }]); + if (error) { + this.context.logger.error("Failed to save chat", { chatId, chatName, taskNodeId, er: error }); + } else { + this.context.logger.info("Successfully saved chat", { chatId, chatName }); + } + } + + async getChatByChatId(chatId: number) { + const { data, error } = await this.supabase.from("chats").select("*").eq("chat_id", chatId).single(); + if (error || !data) { + this.context.logger.error("No chat found", { chatId }); + } else { + this.context.logger.info("Successfully fetched chat", { chatId }); } - async getChatByChatName(chatName: string) { - const { data, error } = (await this.supabase.from("chats").select("*").eq("chatName", chatName).single()) - if (error || !data) { - this.context.logger.error("No chat found", { chatName }); - } else { - this.context.logger.info("Successfully fetched chat", { chatName }); - } + return data; + } - return data; + async getChatByChatName(chatName: string) { + const { data, error } = await this.supabase.from("chats").select("*").eq("chat_name", chatName).single(); + if (error || !data) { + this.context.logger.error("No chat found", { chatName }); + } else { + this.context.logger.info("Successfully fetched chat", { chatName }); } - async getChatByTaskNodeId(taskNodeId: string) { - try { - const { data, error } = await this.supabase.from("chats").select("*").eq("taskNodeId", taskNodeId).single() - if (error || !data) { - this.context.logger.error("No chat found", { taskNodeId }); - } else { - this.context.logger.info("Successfully fetched chat", { taskNodeId }); - } - - return data - } catch (e) { - console.error(e) - throw new Error("Failed to fetch chat by task node id") - } - + return data; + } + + async getChatByTaskNodeId(taskNodeId: string) { + try { + const { data, error } = await this.supabase.from("chats").select("*").eq("task_node_id", taskNodeId).single(); + if (error || !data) { + this.context.logger.error("No chat found", { taskNodeId }); + } else { + this.context.logger.info("Successfully fetched chat", { taskNodeId }); + } + + return data; + } catch (e) { + console.error(e); + throw new Error("Failed to fetch chat by task node id"); } -} \ No newline at end of file + } +} diff --git a/src/bot/features/admin/admin.ts b/src/bot/features/admin/admin.ts index 9d5dc17..884eff3 100644 --- a/src/bot/features/admin/admin.ts +++ b/src/bot/features/admin/admin.ts @@ -1,19 +1,14 @@ -import { chatAction } from '@grammyjs/auto-chat-action' -import { Composer } from 'grammy' -import type { Context } from '#root/bot/grammy-context.js' -import { isAdmin } from '#root/bot/filters/is-admin.js' -import { setCommandsHandler } from '#root/bot/handlers/commands/setcommands.js' -import { logHandle } from '#root/bot/helpers/logging.js' +import { chatAction } from "@grammyjs/auto-chat-action"; +import { Composer } from "grammy"; +import type { Context } from "#root/bot/helpers/grammy-context.js"; +import { isAdmin } from "#root/bot/filters/is-admin.js"; +import { setCommandsHandler } from "#root/bot/handlers/commands/setcommands.js"; +import { logHandle } from "#root/bot/helpers/logging.js"; -const composer = new Composer() +const composer = new Composer(); -const feature = composer.chatType('private').filter(ctx => isAdmin(ctx.config.BOT_ADMINS)(ctx)) +const feature = composer.chatType("private").filter((ctx) => isAdmin(ctx.config.BOT_ADMINS)(ctx)); -feature.command( - 'setcommands', - logHandle('command-setcommands'), - chatAction('typing'), - setCommandsHandler, -) +feature.command("setcommands", logHandle("command-setcommands"), chatAction("typing"), setCommandsHandler); -export { composer as adminFeature } +export { composer as adminFeature }; diff --git a/src/bot/features/commands/bot-id.ts b/src/bot/features/commands/bot-id.ts index 6668ddb..3493a64 100644 --- a/src/bot/features/commands/bot-id.ts +++ b/src/bot/features/commands/bot-id.ts @@ -1,20 +1,14 @@ -import { chatAction } from '@grammyjs/auto-chat-action' -import { Composer } from 'grammy' -import type { Context } from '#root/bot/grammy-context.js' -import { logHandle } from '#root/bot/helpers/logging.js' +import { chatAction } from "@grammyjs/auto-chat-action"; +import { Composer } from "grammy"; +import type { Context } from "#root/bot/helpers/grammy-context.js"; +import { logHandle } from "#root/bot/helpers/logging.js"; -const composer = new Composer() +const composer = new Composer(); -const feature = composer.chatType('private') +const feature = composer.chatType("private"); -feature.command( - 'botid', - logHandle('command-botid'), - chatAction('typing'), - async (ctx) => { - const botID = ctx.me.id - await ctx.reply(`My ID is ${botID}`) - }, -) +feature.command("botid", logHandle("command-botid"), chatAction("typing"), async (ctx) => { + await ctx.reply(`My ID is ${ctx.me.id}`); +}); -export { composer as botIdFeature } +export { composer as botIdFeature }; diff --git a/src/bot/features/commands/chat-id.ts b/src/bot/features/commands/chat-id.ts index 05aaa8e..87f4e5e 100644 --- a/src/bot/features/commands/chat-id.ts +++ b/src/bot/features/commands/chat-id.ts @@ -1,19 +1,14 @@ -import { chatAction } from '@grammyjs/auto-chat-action' -import { Composer } from 'grammy' -import type { Context } from '#root/bot/grammy-context.js' -import { logHandle } from '#root/bot/helpers/logging.js' +import { chatAction } from "@grammyjs/auto-chat-action"; +import { Composer } from "grammy"; +import type { Context } from "#root/bot/helpers/grammy-context.js"; +import { logHandle } from "#root/bot/helpers/logging.js"; -const composer = new Composer() +const composer = new Composer(); -const feature = composer.chatType('supergroup') +const feature = composer.chatType("group"); -feature.command( - 'chatid', - logHandle('command-chatid'), - chatAction('typing'), - async (ctx) => { - return ctx.reply(`This chat ID is ${ctx.chat.id}`) - }, -) +feature.command("chatid", logHandle("command-chatid"), chatAction("typing"), async (ctx) => { + return ctx.reply(`This chat ID is ${ctx.chat.id}`); +}); -export { composer as chatIdFeature } +export { composer as chatIdFeature }; diff --git a/src/bot/features/commands/user-id.ts b/src/bot/features/commands/user-id.ts index 981b60d..c8a1848 100644 --- a/src/bot/features/commands/user-id.ts +++ b/src/bot/features/commands/user-id.ts @@ -1,19 +1,14 @@ -import { chatAction } from '@grammyjs/auto-chat-action' -import { Composer } from 'grammy' -import type { Context } from '#root/bot/grammy-context.js' -import { logHandle } from '#root/bot/helpers/logging.js' +import { chatAction } from "@grammyjs/auto-chat-action"; +import { Composer } from "grammy"; +import type { Context } from "#root/bot/helpers/grammy-context.js"; +import { logHandle } from "#root/bot/helpers/logging.js"; -const composer = new Composer() +const composer = new Composer(); -const feature = composer.chatType('private') +const feature = composer.chatType("private"); -feature.command( - 'myid', - logHandle('command-myid'), - chatAction('typing'), - async (ctx) => { - return ctx.reply(`Your ID is ${ctx.from.id}`) - }, -) +feature.command("myid", logHandle("command-myid"), chatAction("typing"), async (ctx) => { + return ctx.reply(`Your ID is ${ctx.from.id}`); +}); -export { composer as userIdFeature } +export { composer as userIdFeature }; diff --git a/src/bot/features/helpers/unhandled.ts b/src/bot/features/helpers/unhandled.ts index b96e572..2bad5f0 100644 --- a/src/bot/features/helpers/unhandled.ts +++ b/src/bot/features/helpers/unhandled.ts @@ -1,18 +1,18 @@ -import { Composer } from 'grammy' -import type { Context } from '#root/bot/grammy-context.js' -import { logHandle } from '#root/bot/helpers/logging.js' -import { STRINGS } from '../../strings' +import { Composer } from "grammy"; +import type { Context } from "#root/bot/helpers/grammy-context.js"; +import { logHandle } from "#root/bot/helpers/logging.js"; +import { STRINGS } from "../../strings"; -const composer = new Composer() +const composer = new Composer(); -const feature = composer.chatType('private') +const feature = composer.chatType("private"); -feature.on('message', logHandle('unhandled-message'), (ctx) => { - return ctx.reply(STRINGS.UNHANDLED) -}) +feature.on("message", logHandle("unhandled-message"), (ctx) => { + return ctx.reply(STRINGS.UNHANDLED); +}); -feature.on('callback_query', logHandle('unhandled-callback-query'), (ctx) => { - return ctx.answerCallbackQuery() -}) +feature.on("callback_query", logHandle("unhandled-callback-query"), (ctx) => { + return ctx.answerCallbackQuery(); +}); -export { composer as unhandledFeature } +export { composer as unhandledFeature }; diff --git a/src/bot/features/welcome.ts b/src/bot/features/welcome.ts index b68bbf1..cd92a56 100644 --- a/src/bot/features/welcome.ts +++ b/src/bot/features/welcome.ts @@ -1,14 +1,14 @@ -import { Composer } from 'grammy' -import type { Context } from '#root/bot/grammy-context.js' -import { logHandle } from '#root/bot/helpers/logging.js' -import { STRINGS } from '../strings' +import { Composer } from "grammy"; +import type { Context } from "#root/bot/helpers/grammy-context.js"; +import { logHandle } from "#root/bot/helpers/logging.js"; +import { STRINGS } from "../strings"; -const composer = new Composer() +const composer = new Composer(); -const feature = composer.chatType('private') +const feature = composer.chatType("private"); -feature.command('start', logHandle('command-start'), (ctx) => { - return ctx.reply(STRINGS.WELCOME) -}) +feature.command("start", logHandle("command-start"), (ctx) => { + return ctx.reply(STRINGS.WELCOME); +}); -export { composer as welcomeFeature } +export { composer as welcomeFeature }; diff --git a/src/bot/filters/is-admin.ts b/src/bot/filters/is-admin.ts index fe5a249..ba8d8e2 100644 --- a/src/bot/filters/is-admin.ts +++ b/src/bot/filters/is-admin.ts @@ -1,3 +1,5 @@ -import { isUserHasId } from 'grammy-guard' +import { isUserHasId } from "grammy-guard"; -export const isAdmin = (ids: number[]) => isUserHasId(...ids) \ No newline at end of file +export function isAdmin() { + return (ids: number[]) => isUserHasId(...ids); +} diff --git a/src/bot/grammy-context.ts b/src/bot/grammy-context.ts index 37dc60d..81d594c 100644 --- a/src/bot/grammy-context.ts +++ b/src/bot/grammy-context.ts @@ -1,49 +1,37 @@ -import type { Update, UserFromGetMe } from '@grammyjs/types' -import { type Api, Context as DefaultContext, type SessionFlavor } from 'grammy' -import type { AutoChatActionFlavor } from '@grammyjs/auto-chat-action' -import type { HydrateFlavor } from '@grammyjs/hydrate' -import type { ParseModeFlavor } from '@grammyjs/parse-mode' -import type { Logger } from '#root/logger.js' -import { Context as UbiquityOsContext } from '../types' +import type { Update, UserFromGetMe } from "@grammyjs/types"; +import { type Api, Context as DefaultContext, type SessionFlavor } from "grammy"; +import type { AutoChatActionFlavor } from "@grammyjs/auto-chat-action"; +import type { HydrateFlavor } from "@grammyjs/hydrate"; +import type { ParseModeFlavor } from "@grammyjs/parse-mode"; +import { Context as UbiquityOsContext } from "../types"; +import { Logger } from "#root/utils/logger.js"; export interface SessionData { - // field?: string; + field?: string; } interface ExtendedContextFlavor { - logger: Logger - config: UbiquityOsContext["env"] + logger: Logger; + config: UbiquityOsContext["env"]; } -export type Context = ParseModeFlavor< - HydrateFlavor< - DefaultContext & - ExtendedContextFlavor & - SessionFlavor & - AutoChatActionFlavor - > -> +export type Context = ParseModeFlavor & AutoChatActionFlavor>>; interface Dependencies { - logger: Logger - config: UbiquityOsContext["env"] + logger: Logger; + config: UbiquityOsContext["env"]; } -export function createContextConstructor( - { - logger, - config, - }: Dependencies, -) { +export function createContextConstructor({ logger, config }: Dependencies) { return class extends DefaultContext implements ExtendedContextFlavor { - logger: Logger - config: UbiquityOsContext["env"] + logger: Logger; + config: UbiquityOsContext["env"]; constructor(update: Update, api: Api, me: UserFromGetMe) { - super(update, api, me) + super(update, api, me); - this.logger = logger - this.config = config + this.logger = logger; + this.config = config; } - } as unknown as new (update: Update, api: Api, me: UserFromGetMe) => Context + } as unknown as new (update: Update, api: Api, me: UserFromGetMe) => Context; } diff --git a/src/bot/handlers/commands/setcommands.ts b/src/bot/handlers/commands/setcommands.ts index fc9b22c..3b58d3e 100644 --- a/src/bot/handlers/commands/setcommands.ts +++ b/src/bot/handlers/commands/setcommands.ts @@ -1,63 +1,51 @@ -import type { BotCommand } from '@grammyjs/types' -import type { CommandContext } from 'grammy' -import type { Context } from '#root/bot/grammy-context.js' +import type { BotCommand } from "@grammyjs/types"; +import type { CommandContext } from "grammy"; +import type { Context } from "#root/bot/helpers/grammy-context.js"; function getPrivateChatCommands(): BotCommand[] { return [ { - command: 'start', - description: 'start-command-description', + command: "start", + description: "start-command-description", }, - ] + ]; } function getPrivateChatAdminCommands(): BotCommand[] { return [ { - command: 'setcommands', - description: 'setcommands-command-description', + command: "setcommands", + description: "setcommands-command-description", }, - ] + ]; } function getGroupChatCommands(): BotCommand[] { - return [] + return []; } export async function setCommandsHandler(ctx: CommandContext) { // set private chat commands - await ctx.api.setMyCommands( - [ - ...getPrivateChatCommands(), - ], - { - scope: { - type: 'all_private_chats', - }, + await ctx.api.setMyCommands([...getPrivateChatCommands()], { + scope: { + type: "all_private_chats", }, - ) - + }); // set group chat commands await ctx.api.setMyCommands(getGroupChatCommands(), { scope: { - type: 'all_group_chats', + type: "all_group_chats", }, - }) + }); // set private chat commands for owner - await ctx.api.setMyCommands( - [ - ...getPrivateChatCommands(), - ...getPrivateChatAdminCommands(), - ], - { - scope: { - type: 'chat', - chat_id: ctx.chat.id, - }, + await ctx.api.setMyCommands([...getPrivateChatCommands(), ...getPrivateChatAdminCommands()], { + scope: { + type: "chat", + chat_id: ctx.chat.id, }, - ) + }); - return ctx.reply('admin-commands-updated') + return ctx.reply("admin-commands-updated"); } diff --git a/src/bot/handlers/error.ts b/src/bot/handlers/error.ts index c5ba581..e74ae61 100644 --- a/src/bot/handlers/error.ts +++ b/src/bot/handlers/error.ts @@ -1,13 +1,14 @@ -import type { ErrorHandler } from 'grammy' -import type { Context } from '#root/bot/grammy-context.js' -import { getUpdateInfo } from '#root/bot/helpers/logging.js' +import type { ErrorHandler } from "grammy"; +import type { Context } from "#root/bot/helpers/grammy-context.js"; +import { getUpdateInfo } from "#root/bot/helpers/logging.js"; -export const errorHandler: ErrorHandler = (error) => { - const { ctx } = error +export function errorHandler(): ErrorHandler { + return (error) => { + const { ctx } = error; - ctx.logger.error( - 'Request failed', { - err: error, - update: getUpdateInfo(ctx), - }) + ctx.logger.error("Request failed", { + err: error, + update: getUpdateInfo(ctx), + }); + }; } diff --git a/src/bot/helpers/grammy-context.ts b/src/bot/helpers/grammy-context.ts new file mode 100644 index 0000000..0cb51fb --- /dev/null +++ b/src/bot/helpers/grammy-context.ts @@ -0,0 +1,37 @@ +import type { Update, UserFromGetMe } from "@grammyjs/types"; +import { type Api, Context as DefaultContext, type SessionFlavor } from "grammy"; +import type { AutoChatActionFlavor } from "@grammyjs/auto-chat-action"; +import type { HydrateFlavor } from "@grammyjs/hydrate"; +import type { ParseModeFlavor } from "@grammyjs/parse-mode"; +import type { Logger } from "#root/utils/logger.js"; +import { Context as UbiquityOsContext } from "../../types"; + +export interface SessionData { + field?: string; +} + +interface ExtendedContextFlavor { + logger: Logger; + config: UbiquityOsContext["env"]; +} + +export type Context = ParseModeFlavor & AutoChatActionFlavor>>; + +interface Dependencies { + logger: Logger; + config: UbiquityOsContext["env"]; +} + +export function createContextConstructor({ logger, config }: Dependencies) { + return class extends DefaultContext implements ExtendedContextFlavor { + logger: Logger; + config: UbiquityOsContext["env"]; + + constructor(update: Update, api: Api, me: UserFromGetMe) { + super(update, api, me); + + this.logger = logger; + this.config = config; + } + } as unknown as new (update: Update, api: Api, me: UserFromGetMe) => Context; +} diff --git a/src/bot/helpers/logging.ts b/src/bot/helpers/logging.ts index e082c85..c688e3c 100644 --- a/src/bot/helpers/logging.ts +++ b/src/bot/helpers/logging.ts @@ -1,20 +1,20 @@ -import type { Middleware } from 'grammy' -import type { Update } from '@grammyjs/types' -import type { Context } from '#root/bot/grammy-context.js' +import type { Middleware } from "grammy"; +import type { Update } from "@grammyjs/types"; +import type { Context } from "#root/bot/helpers/grammy-context.js"; -export function getUpdateInfo(ctx: Context): Omit { - const { update_id, ...update } = ctx.update +export function getUpdateInfo(ctx: Context): Omit { + const { update_id, ...update } = ctx.update; - return update + return update; } export function logHandle(id: string): Middleware { return (ctx, next) => { ctx.logger.info("Handling update", { msg: `Handle "${id}"`, - ...(id.startsWith('unhandled') ? { update: getUpdateInfo(ctx) } : {}), - }) + ...(id.startsWith("unhandled") ? { update: getUpdateInfo(ctx) } : {}), + }); - return next() - } + return next(); + }; } diff --git a/src/bot/index.ts b/src/bot/index.ts index 85b0066..0627b2f 100644 --- a/src/bot/index.ts +++ b/src/bot/index.ts @@ -1,41 +1,37 @@ - -import type { BotConfig, StorageAdapter } from 'grammy' -import { Bot as TelegramBot, Api } from 'grammy' -import type { Context, SessionData } from '#root/bot/grammy-context.js' -import { createContextConstructor } from '#root/bot/grammy-context.js' -import type { Logger } from '#root/logger.js' -import { Context as UbiquityOsContext } from '../types' -import { welcomeFeature } from '#root/bot/features/welcome.js' -import { unhandledFeature } from '#root/bot/features/helpers/unhandled.js' -import { errorHandler } from '#root/bot/handlers/error.js' -import { session } from '#root/bot/middlewares/session.js' -import { autoChatAction } from '@grammyjs/auto-chat-action' -import { hydrate } from '@grammyjs/hydrate' -import { hydrateReply, parseMode } from '@grammyjs/parse-mode' -import { adminFeature } from './features/admin/admin' -import { userIdFeature } from './features/commands/user-id' -import { chatIdFeature } from './features/commands/chat-id' -import { botIdFeature } from './features/commands/bot-id' +import type { BotConfig, StorageAdapter } from "grammy"; +import { Bot as TelegramBot } from "grammy"; +import type { Context, SessionData } from "#root/bot/helpers/grammy-context.js"; +import { createContextConstructor } from "#root/bot/helpers/grammy-context.js"; +import type { Logger } from "#root/utils/logger.js"; +import { Context as UbiquityOsContext } from "../types"; +import { welcomeFeature } from "#root/bot/features/welcome.js"; +import { unhandledFeature } from "#root/bot/features/helpers/unhandled.js"; +import { errorHandler } from "#root/bot/handlers/error.js"; +import { session } from "#root/bot/middlewares/session.js"; +import { autoChatAction } from "@grammyjs/auto-chat-action"; +import { hydrate } from "@grammyjs/hydrate"; +import { hydrateReply, parseMode } from "@grammyjs/parse-mode"; +import { adminFeature } from "./features/admin/admin"; +import { userIdFeature } from "./features/commands/user-id"; +import { chatIdFeature } from "./features/commands/chat-id"; +import { botIdFeature } from "./features/commands/bot-id"; interface Dependencies { - config: UbiquityOsContext["env"] - logger: Logger + config: UbiquityOsContext["env"]; + logger: Logger; } interface Options { - botSessionStorage?: StorageAdapter - botConfig?: Omit, 'ContextConstructor'> + botSessionStorage?: StorageAdapter; + botConfig?: Omit, "ContextConstructor">; } -function getSessionKey(ctx: Omit) { - return ctx.chat?.id.toString() +function getSessionKey(ctx: Omit) { + return ctx.chat?.id.toString(); } export function createBot(token: string, dependencies: Dependencies, options: Options = {}) { - const { - config, - logger, - } = dependencies + const { config, logger } = dependencies; const bot = new TelegramBot(token, { ...options.botConfig, @@ -43,27 +39,27 @@ export function createBot(token: string, dependencies: Dependencies, options: Op logger, config, }), - }) - const protectedBot = bot.errorBoundary(errorHandler) + }); + const protectedBot = bot.errorBoundary(errorHandler); - bot.api.config.use(parseMode('HTML')) + bot.api.config.use(parseMode("HTML")); - protectedBot.use(autoChatAction(bot.api)) - protectedBot.use(hydrateReply) - protectedBot.use(hydrate()) - protectedBot.use(session({ getSessionKey, storage: options.botSessionStorage })) + protectedBot.use(autoChatAction(bot.api)); + protectedBot.use(hydrateReply); + protectedBot.use(hydrate()); + protectedBot.use(session({ getSessionKey, storage: options.botSessionStorage })); // Handlers - protectedBot.use(welcomeFeature) - protectedBot.use(adminFeature) - protectedBot.use(userIdFeature) - protectedBot.use(chatIdFeature) - protectedBot.use(botIdFeature) + protectedBot.use(welcomeFeature); + protectedBot.use(adminFeature); + protectedBot.use(userIdFeature); + protectedBot.use(chatIdFeature); + protectedBot.use(botIdFeature); // must be the last handler - protectedBot.use(unhandledFeature) + protectedBot.use(unhandledFeature); - return bot + return bot; } -export type Bot = ReturnType +export type Bot = ReturnType; diff --git a/src/bot/middlewares/session.ts b/src/bot/middlewares/session.ts index 7b856fb..53f60fe 100644 --- a/src/bot/middlewares/session.ts +++ b/src/bot/middlewares/session.ts @@ -1,12 +1,12 @@ -import { type Middleware, type SessionOptions, session as createSession } from 'grammy' -import type { Context, SessionData } from '#root/bot/grammy-context.js' +import { type Middleware, type SessionOptions, session as createSession } from "grammy"; +import type { Context, SessionData } from "#root/bot/helpers/grammy-context.js"; -type Options = Pick, 'getSessionKey' | 'storage'> +type Options = Pick, "getSessionKey" | "storage">; export function session(options: Options): Middleware { return createSession({ getSessionKey: options.getSessionKey, storage: options.storage, initial: () => ({}), - }) + }); } diff --git a/src/bot/mtproto-api/README.md b/src/bot/mtproto-api/README.md deleted file mode 100644 index 4d5c116..0000000 --- a/src/bot/mtproto-api/README.md +++ /dev/null @@ -1,6 +0,0 @@ -These are intended to be an extension of the worker's functionalities due to the restrictions of Cloudflare workers. They are not meant to be a replacement for the worker itself. They are meant to be used in conjunction with the worker. - -The worker should `repository_dispatch` to the workflow to trigger it. The workflow will then run it's logic and return the result to the worker if necessary. - - -... \ No newline at end of file diff --git a/src/bot/mtproto-api/bot/mtproto.ts b/src/bot/mtproto-api/bot/mtproto.ts index ab3cd64..063f8aa 100644 --- a/src/bot/mtproto-api/bot/mtproto.ts +++ b/src/bot/mtproto-api/bot/mtproto.ts @@ -1,46 +1,51 @@ -import { Context } from '#root/types/context.js'; +import { Context } from "#root/types/context.js"; import dotenv from "dotenv"; -import { BaseMtProto } from './scripts/sms-auth/base-mtproto'; -import { SupabaseSession } from './session'; -import { createClient, SupabaseClient } from '@supabase/supabase-js'; +import { BaseMtProto } from "./scripts/sms-auth/base-mtproto"; +import { SupabaseSession } from "./session"; +import { createClient, SupabaseClient } from "@supabase/supabase-js"; dotenv.config(); +/** + * This class MUST ONLY be used in the context of workflow-functions as + * it requires a Node.js environment which is not available with Cloudflare Workers. + * + * An extension of the BaseMtProto class that integrates with the Supabase based + * session management. + */ export class MtProto extends BaseMtProto { - private supabase: SupabaseClient | null = null; - private context: Context; - _session: SupabaseSession; + private _supabase: SupabaseClient | null = null; + private _context: Context; + _session: SupabaseSession; - constructor(context: Context) { - super(); + constructor(context: Context) { + super(); - const key = context.env.SUPABASE_SERVICE_KEY; - const url = context.env.SUPABASE_URL; + const key = context.env.SUPABASE_SERVICE_KEY; + const url = context.env.SUPABASE_URL; - if (!key || !url) { - throw new Error("Missing required environment variables for Supabase") - } - - this.supabase = createClient(url, key); - this.context = context; - this._session = new SupabaseSession(this.supabase, this.context); - } - - async initialize() { - const session = await this._session.getSession(); - await super.initialize(this.context.env, session); + if (!key || !url) { + throw new Error("Missing required environment variables for Supabase"); } - async saveSession() { - await this._session.saveSession(); - } + this._supabase = createClient(url, key); + this._context = context; + this._session = new SupabaseSession(this._supabase, this._context); + } - async deleteSession() { - await this._session.deleteSession(); - } + async initialize() { + const session = await this._session.getSession(); + await super.initialize(this._context.env, session); + } - async loadSession() { - await this._session.loadSession(); - } -} + async saveSession() { + await this._session.saveSession(); + } + async deleteSession() { + await this._session.deleteSession(); + } + async loadSession() { + await this._session.loadSession(); + } +} diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts index d638f38..21ae752 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts @@ -1,66 +1,80 @@ // @ts-expect-error no types for this package -import input from 'input'; +import input from "input"; import dotenv from "dotenv"; -import { createClient, SupabaseClient } from '@supabase/supabase-js'; -import { BaseMtProto } from './base-mtproto'; +import { createClient, SupabaseClient } from "@supabase/supabase-js"; +import { BaseMtProto } from "./base-mtproto"; dotenv.config(); /** * The account holder must run this script (to my knowledge only once) to login, * this will give us the necessary session information to login in the future. */ - export class AuthHandler { - private supabase: SupabaseClient | null = null; - private env = { - TELEGRAM_API_HASH: "", - TELEGRAM_APP_ID: 0, - BOT_TOKEN: "", + private _supabase: SupabaseClient | null = null; + private _env = { + TELEGRAM_API_HASH: "", + TELEGRAM_APP_ID: 0, + BOT_TOKEN: "", + }; + + constructor() { + const key = process.env.SUPABASE_SERVICE_KEY; + const url = process.env.SUPABASE_URL; + if (!key || !url) { + throw new Error("Missing required environment variables for Supabase"); } + this._supabase = createClient(url, key); - constructor() { - const key = process.env.SUPABASE_SERVICE_KEY; - const url = process.env.SUPABASE_URL; - if (!key || !url) { - throw new Error("Missing required environment variables for Supabase") - } - this.supabase = createClient(url, key); + const hash = process.env.TELEGRAM_API_HASH; + const tgAppId = process.env.TELEGRAM_APP_ID; + const botToken = process.env.BOT_TOKEN; - const hash = process.env.TELEGRAM_API_HASH - const tgAppId = process.env.TELEGRAM_APP_ID - const botToken = process.env.BOT_TOKEN + if (!hash || !tgAppId || !botToken) { + throw new Error("Missing required environment variables for Telegram API"); + } - if (!hash || !tgAppId || !botToken) { - throw new Error("Missing required environment variables for Telegram API") - } + this._env = { + TELEGRAM_API_HASH: hash, + TELEGRAM_APP_ID: Number(tgAppId), + BOT_TOKEN: botToken, + }; + } - this.env = { - TELEGRAM_API_HASH: hash, - TELEGRAM_APP_ID: Number(tgAppId), - BOT_TOKEN: botToken - } - } + /** + * You should only need to run this once. + * + * You will be prompted in your terminal to enter the following: + * - Phone number + * - Code received + * - Password (if required) + * + * In that order and the code will be sent to a Telegram instance + * which the associated phone number is logged in. + * + * The session data will be saved to Supabase for future use. + */ + async smsLogin() { + const mtProto = new BaseMtProto(); + // empty string as it's a new session + await mtProto.initialize(this._env, ""); + try { + await mtProto.client?.start({ + phoneNumber: async () => await input.text("Enter your phone number:"), + password: async () => await input.text("Enter your password if required:"), + phoneCode: async () => await input.text("Enter the code you received:"), + onError: (err: unknown) => console.error("Error during login:", err), + }); + + const data = await this._supabase?.from("tg-bot-sessions").insert([{ session_data: mtProto.session?.save() }]); - /** - * This method will handle the SMS login process. - */ - async smsLogin() { - const mtProto = new BaseMtProto(); - await mtProto.initialize(this.env, ""); - try { - // Start the login process - await mtProto.client?.start({ - phoneNumber: async () => await input.text('Enter your phone number:'), - password: async () => await input.text('Enter your password if required:'), - phoneCode: async () => await input.text('Enter the code you received:'), - onError: (err: unknown) => console.error('Error during login:', err), - }); + if (data?.error) { + throw new Error("Failed to save session data to Supabase."); + } - await this.supabase?.from('tg-bot-sessions').insert([ - { session_data: mtProto.session?.save() }, - ]); - } catch (error) { - console.error('Failed to log in:', error); - } + console.log("Successfully logged in and saved session data. You can now run the bot."); + process.exit(0); + } catch (error) { + console.error("Failed to log in:", error); } -} \ No newline at end of file + } +} diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts index 4852c69..6771181 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts @@ -1,56 +1,57 @@ -import { TelegramClient } from 'telegram'; -import { Api } from 'telegram/tl'; -import { TelegramClientParams } from 'telegram/client/telegramBaseClient'; +import { TelegramClient } from "telegram"; +import { Api } from "telegram/tl"; +import { TelegramClientParams } from "telegram/client/telegramBaseClient"; import dotenv from "dotenv"; -import { StringSession } from 'telegram/sessions'; +import { StringSession } from "telegram/sessions"; dotenv.config(); type Env = { - TELEGRAM_API_HASH: string; - TELEGRAM_APP_ID: number; - BOT_TOKEN: string; -} - + TELEGRAM_API_HASH: string; + TELEGRAM_APP_ID: number; + BOT_TOKEN: string; +}; + +/** + * @dev Not abstract because we need it to be instantiated for sms-auth + * + * Base class for initializing the Telegram client and API used for + * handling the sms-auth aspect of configuring the bot. + */ export class BaseMtProto { - // @ts-expect-error properties not defined in constructor, not required in baseclass - _client: TelegramClient; _api: typeof Api; - _session: StringSession | null = null; - - async initialize(env: Env, session: string) { - this._api = Api; - this._session = new StringSession(session) - this._client = await this.mtProtoInit(env, this._session); - } - - get api() { - return this._api; - } - - get client() { - return this._client; - } - - get session() { - return this._session; - } - - private async mtProtoInit(env: Env, session: StringSession) { - const { TELEGRAM_API_HASH, TELEGRAM_APP_ID, BOT_TOKEN } = env - - if (!TELEGRAM_API_HASH || !TELEGRAM_APP_ID || !BOT_TOKEN) { - throw new Error("Missing required environment variables for Telegram API") - } - const clientParams: TelegramClientParams = { - connectionRetries: 5, - } - const client = new TelegramClient( - session, - TELEGRAM_APP_ID, - TELEGRAM_API_HASH, - clientParams - ); - await client.connect(); - return client; + // @ts-expect-error properties not defined in constructor, not required in baseclass + _client: TelegramClient; + _api: typeof Api = Api; + _session: StringSession | null = null; + + async initialize(env: Env, session: string) { + this._api = Api; + this._session = new StringSession(session); + this._client = await this._mtProtoInit(env, this._session); + } + + get api() { + return this._api; + } + + get client() { + return this._client; + } + + get session() { + return this._session; + } + + private async _mtProtoInit(env: Env, session: StringSession) { + const { TELEGRAM_API_HASH, TELEGRAM_APP_ID } = env; + + if (!TELEGRAM_API_HASH || !TELEGRAM_APP_ID) { + throw new Error("Missing required environment variables for Telegram API"); } + const clientParams: TelegramClientParams = { + connectionRetries: 5, + }; + const client = new TelegramClient(session, TELEGRAM_APP_ID, TELEGRAM_API_HASH, clientParams); + await client.connect(); + return client; + } } - diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts index bdaa9a2..67ea7a8 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts @@ -2,9 +2,12 @@ import { AuthHandler } from "./auth-handler"; import dotenv from "dotenv"; dotenv.config(); +/** + * Run with `yarn sms-auth` + */ async function main() { - const authHandler = new AuthHandler(); - await authHandler.smsLogin(); + const authHandler = new AuthHandler(); + await authHandler.smsLogin(); } -main().catch(console.error); \ No newline at end of file +main().catch(console.error); diff --git a/src/bot/mtproto-api/bot/session.ts b/src/bot/mtproto-api/bot/session.ts index 85550ed..2a1e466 100644 --- a/src/bot/mtproto-api/bot/session.ts +++ b/src/bot/mtproto-api/bot/session.ts @@ -4,46 +4,44 @@ import { StringSession } from "telegram/sessions"; /** * This class extends the StringSession class from the Telegram library. - * + * * It adds the ability to save and load the session data from Supabase. */ export class SupabaseSession extends StringSession { - supabase: SupabaseClient; - context: Context; - - constructor(supabase: SupabaseClient, context: Context, session?: string) { - super(session); - this.supabase = supabase - this.context = context - } - - async saveSession(): Promise { - await this.supabase?.from('tg-bot-sessions').insert([ - { session_data: super.save() }, - ]); + supabase: SupabaseClient; + context: Context; + + constructor(supabase: SupabaseClient, context: Context, session?: string) { + super(session); + this.supabase = supabase; + this.context = context; + } + + async saveSession(): Promise { + await this.supabase?.from("tg-bot-sessions").insert([{ session_data: super.save() }]); + } + + async loadSession(): Promise { + const session = await this.supabase?.from("tg-bot-sessions").select("session_data").single(); + + if (session.data) { + return new SupabaseSession(this.supabase, this.context, session.data.session_data); + } else { + throw new Error("No session found. Please run the SMS Login script first."); } + } - async loadSession(): Promise { - const session = await this.supabase?.from('tg-bot-sessions').select('session_data').single() + async getSession(): Promise { + const session = await this.supabase?.from("tg-bot-sessions").select("session_data").single(); - if (session.data) { - return new SupabaseSession(this.supabase, this.context, session.data.session_data) - } else { - throw new Error("No session found. Please run the SMS Login script first.") - } + if (session.data) { + return session.data.session_data; + } else { + throw new Error("No session found. Please run the SMS Login script first."); } + } - async getSession(): Promise { - const session = await this.supabase?.from('tg-bot-sessions').select('session_data').single() - - if (session.data) { - return session.data.session_data - } else { - throw new Error("No session found. Please run the SMS Login script first.") - } - } - - async deleteSession(): Promise { - await this.supabase?.from('tg-bot-sessions').delete() - } -} \ No newline at end of file + async deleteSession(): Promise { + await this.supabase?.from("tg-bot-sessions").delete(); + } +} diff --git a/src/bot/mtproto-api/workrooms.ts b/src/bot/mtproto-api/workrooms.ts index ccb9efc..229d071 100644 --- a/src/bot/mtproto-api/workrooms.ts +++ b/src/bot/mtproto-api/workrooms.ts @@ -5,183 +5,193 @@ import { Api } from "telegram"; import { addCommentToIssue } from "#root/helpers/add-comment-to-issues.js"; function isPriceLabelChange(label: string): boolean { - return label.toLowerCase().includes("price"); + return label.toLowerCase().includes("price"); } export async function createChat(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { - const { payload, config, logger } = context; - const chatName = payload.issue.title; - - const labelName = payload.label?.name; + const { payload, config, logger } = context; + const chatName = payload.issue.title; + + const labelName = payload.label?.name; + + if (!labelName || !isPriceLabelChange(labelName)) { + return { status: 200, reason: "skipped" }; + } + + const mtProto = new MtProto(context); + await mtProto.initialize(); + let chatId: number; + logger.info("Creating chat with name: ", { chatName }); + + try { + const botIdString = await mtProto.client.getPeerId(config.botUsername, true); + + const chat = await mtProto.client.invoke( + new mtProto.api.messages.CreateChat({ + title: chatName, + users: [botIdString], + }) + ); + let inviteLink; + + if ("chats" in chat.updates) { + chatId = chat.updates.chats[0].id.toJSNumber(); + } else { + throw new Error("Failed to create chat"); + } - if (!labelName || !isPriceLabelChange(labelName)) { - return { status: 200, reason: "skipped" }; + if (chat.updates.chats[0].className === "Chat") { + inviteLink = await mtProto.client.invoke( + new mtProto.api.messages.ExportChatInvite({ + peer: new mtProto.api.InputPeerChat({ chatId: chat.updates.chats[0].id }), + }) + ); } - const mtProto = new MtProto(context); - await mtProto.initialize(); - let chatId: number; - logger.info("Creating chat with name: ", { chatName }); + if (inviteLink) { + const [owner, repo] = payload.repository.full_name.split("/"); + let link; - try { - const botIdString = await mtProto.client.getPeerId(config.botUsername, true); + if ("link" in inviteLink) { + link = inviteLink.link; + } - const chat = await mtProto.client.invoke( - new mtProto.api.messages.CreateChat({ - title: chatName, - users: [botIdString], - }) - ); - let inviteLink; + await addCommentToIssue(context, `A new workroom has been created for this task. [Join chat](${link})`, owner, repo, payload.issue.number); + } - if ("chats" in chat.updates) { - chatId = chat.updates.chats[0].id.toJSNumber(); - } else { - throw new Error("Failed to create chat"); - } + const isPromoted = await mtProto.client.invoke( + new mtProto.api.messages.EditChatAdmin({ + chatId: chat.updates.chats[0].id, + isAdmin: true, + userId: botIdString, + }) + ); - if (chat.updates.chats[0].className === "Chat") { - inviteLink = await mtProto.client.invoke( - new mtProto.api.messages.ExportChatInvite({ - peer: new mtProto.api.InputPeerChat({ chatId: chat.updates.chats[0].id }), - }) - ); - } + if (!isPromoted) { + throw new Error("Failed to promote bot to admin"); + } + } catch (er) { + logger.error("Error in creating chat: ", { er }); + return { status: 500, reason: "chat_create_failed", content: { error: er } }; + } - if (inviteLink) { - const [owner, repo] = payload.repository.full_name.split("/"); - let link; + await context.adapters.supabase.chats.saveChat(chatId, payload.issue.title, payload.issue.node_id); + return { status: 200, reason: "chat_created" }; +} - if ("link" in inviteLink) { - link = inviteLink.link; - } +export async function closeChat(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { + const { + payload, + adapters: { + supabase: { chats }, + }, + logger, + } = context; + try { + const mtProto = new MtProto(context); + await mtProto.initialize(); - await addCommentToIssue(context, `A new workroom has been created for this task. [Join chat](${link})`, owner, repo, payload.issue.number); - } + logger.info("Closing chat with name: ", { chatName: payload.issue.title }); + const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); - const promoteBotToAdmin = await mtProto.client.invoke( - new mtProto.api.messages.EditChatAdmin({ - chatId: chat.updates.chats[0].id, - isAdmin: true, - userId: botIdString, - }) - ); + const fetchChat = await mtProto.client.invoke( + new mtProto.api.messages.GetFullChat({ + chatId: chat.chatId, + }) + ); - if (!promoteBotToAdmin) { - throw new Error("Failed to promote bot to admin"); - } - } catch (er) { - logger.error("Error in creating chat: ", { er }); - return { status: 500, reason: "chat_create_failed", content: { error: er } }; + if (!fetchChat) { + throw new Error("Failed to fetch chat"); } - await context.adapters.supabase.chats.saveChat(chatId, payload.issue.title, payload.issue.node_id); - return { status: 200, reason: "chat_created" }; -} + let chatParticipants; -export async function closeChat(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { - const { payload, adapters: { supabase: { chats } }, logger } = context; - try { - const mtProto = new MtProto(context); - await mtProto.initialize(); - - logger.info("Closing chat with name: ", { chatName: payload.issue.title }); - const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); - - const fetchChat = await mtProto.client.invoke( - new mtProto.api.messages.GetFullChat({ - chatId: chat.chatId, - }) - ); + if ("participants" in fetchChat.fullChat) { + chatParticipants = fetchChat.fullChat.participants; + } else { + throw new Error("Failed to fetch chat participants"); + } - if (!fetchChat) { - throw new Error("Failed to fetch chat"); + if (chatParticipants.className === "ChatParticipants") { + await mtProto.client.invoke( + new mtProto.api.messages.SendMessage({ + message: "This task has been closed and this chat has been archived.", + peer: new mtProto.api.InputPeerChat({ chatId: chat.chatId }), + }) + ); + + const userIds = chatParticipants.participants.map((participant) => { + return participant.userId; + }); + + for (const userId of userIds) { + if (userId.toJSNumber() === context.config.botId) { + continue; } + await mtProto.client.invoke( + new mtProto.api.messages.DeleteChatUser({ + chatId: chat.chatId, + userId: userId, + }) + ); + } + } - let chatParticipants; + await chats.updateChatStatus("closed", payload.issue.node_id); - if ("participants" in fetchChat.fullChat) { - chatParticipants = fetchChat.fullChat.participants; - } else { - throw new Error("Failed to fetch chat participants"); - } + return { status: 200, reason: "chat_closed" }; + } catch (er) { + logger.error("Failed to close chat", { er }); + return { status: 500, reason: "chat_close_failed", content: { error: er } }; + } +} +export async function reopenChat(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { + const { + payload, + adapters: { + supabase: { chats }, + }, + logger, + } = context; + try { + const mtProto = new MtProto(context); + await mtProto.initialize(); - if (chatParticipants.className === "ChatParticipants") { - - await mtProto.client.invoke( - new mtProto.api.messages.SendMessage({ - message: "This task has been closed and this chat has been archived.", - peer: new mtProto.api.InputPeerChat({ chatId: chat.chatId }), - }) - ); - - const userIDs = chatParticipants.participants.map((participant) => { - return participant.userId; - }); - - for (let i = 0; i < userIDs.length; i++) { - if (userIDs[i].toJSNumber() === context.config.botId) { - continue; - } - await mtProto.client.invoke( - new mtProto.api.messages.DeleteChatUser({ - chatId: chat.chatId, - userId: userIDs[i], - }) - ); - } - } + logger.info("Reopening chat with name: ", { chatName: payload.issue.title }); + const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); - await chats.updateChatStatus("closed", payload.issue.node_id); + const fetchChat = await mtProto.client.invoke( + new mtProto.api.messages.GetFullChat({ + chatId: chat.chatId, + }) + ); - return { status: 200, reason: "chat_closed" }; - } catch (er) { - logger.error("Failed to close chat", { er }); - return { status: 500, reason: "chat_close_failed", content: { error: er } }; + if (!fetchChat) { + throw new Error("Failed to fetch chat"); } -} -export async function reopenChat(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { - const { payload, adapters: { supabase: { chats } }, logger } = context; - try { - const mtProto = new MtProto(context); - await mtProto.initialize(); - - logger.info("Reopening chat with name: ", { chatName: payload.issue.title }); - const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); - - const fetchChat = await mtProto.client.invoke( - new mtProto.api.messages.GetFullChat({ - chatId: chat.chatId, - }) - ); + const chatFull = fetchChat.fullChat as Api.ChatFull; + const participants = chatFull.participants as Api.ChatParticipants; - if (!fetchChat) { - throw new Error("Failed to fetch chat"); - } + console.log("Participants: ", participants); - const chatFull = fetchChat.fullChat as Api.ChatFull - const participants = chatFull.participants as Api.ChatParticipants; - - console.log("Participants: ", participants); - - for (const participant of participants.participants) { - if (participant instanceof mtProto.api.ChatParticipant) { - await mtProto.client.invoke( - new mtProto.api.messages.AddChatUser({ - chatId: chat.chatId, - userId: participant.userId, - fwdLimit: 50, - }) - ); - } - } - - return { status: 200, reason: "chat_reopened" }; - } catch (er) { - console.log(er); - logger.error("Failed to reopen chat", { er }); - return { status: 500, reason: "chat_reopen_failed", content: { error: er } }; + for (const participant of participants.participants) { + if (participant instanceof mtProto.api.ChatParticipant) { + await mtProto.client.invoke( + new mtProto.api.messages.AddChatUser({ + chatId: chat.chatId, + userId: participant.userId, + fwdLimit: 50, + }) + ); + } } + + return { status: 200, reason: "chat_reopened" }; + } catch (er) { + console.log(er); + logger.error("Failed to reopen chat", { er }); + return { status: 500, reason: "chat_reopen_failed", content: { error: er } }; + } } diff --git a/src/bot/mtproto-api/workrooms/close-chat.ts b/src/bot/mtproto-api/workrooms/close-chat.ts new file mode 100644 index 0000000..b15c74e --- /dev/null +++ b/src/bot/mtproto-api/workrooms/close-chat.ts @@ -0,0 +1,139 @@ +import { Context, SupportedEvents } from "#root/types/context"; +import { CallbackResult } from "#root/types/proxy.js"; +import { MtProto } from "../bot/mtproto"; +import { Api } from "telegram"; +import bigInt from "big-integer"; + +export async function closeChat(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { + const { + payload, + adapters: { + supabase: { chats }, + }, + logger, + } = context; + const mtProto = new MtProto(context); + await mtProto.initialize(); + + logger.info("Closing chat with name: ", { chatName: payload.issue.title }); + const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); + + const fetchChat = await mtProto.client.invoke( + new mtProto.api.messages.GetFullChat({ + chatId: chat.chatId, + }) + ); + + if (!fetchChat) { + throw new Error("Failed to fetch chat"); + } + + let chatParticipants; + + if ("participants" in fetchChat.fullChat) { + chatParticipants = fetchChat.fullChat.participants; + } else { + throw new Error("Failed to fetch chat participants"); + } + + // archive it + await mtProto.client.invoke( + new mtProto.api.folders.EditPeerFolders({ + folderPeers: [ + new mtProto.api.InputFolderPeer({ + peer: new mtProto.api.InputPeerChat({ chatId: chat.chatId }), + folderId: 1, // 0 is active, 1 is archived + }), + ], + }) + ); + + if (chatParticipants.className === "ChatParticipants") { + await mtProto.client.invoke( + new mtProto.api.messages.SendMessage({ + message: "This task has been closed and this chat has been archived.", + peer: new mtProto.api.InputPeerChat({ chatId: chat.chatId }), + }) + ); + + const participants = chatParticipants.participants; + let creatorId; + + const userIds = participants + .map((participant) => { + if (participant.className === "ChatParticipantCreator") { + creatorId = participant.userId; + return undefined; + } + return participant.userId; + }) + .filter((id) => id !== undefined); + + if (!creatorId) { + throw new Error("Failed to get chat creator"); + } + + userIds.push(creatorId); + const chatInput = await mtProto.client.getInputEntity(chat.chatId); + + await chats.userSnapshot( + chat.chatId, + userIds.map((id) => id.toJSNumber()) + ); + + let generator = deleteChatUsers(mtProto, userIds, context, chatInput); + let result = await generator.next(); + + while (!result.done) { + if (!result.value.success) { + const seconds = result.value.error?.seconds ?? 300; + logger.info("Retrying...", { seconds, er: result.value.error }); + + await intervalLogger(seconds, 60, logger, new Promise((resolve) => setTimeout(resolve, seconds * 1000))); + + generator = deleteChatUsers(mtProto, userIds.slice(result.value.index), context, chatInput); + } + result = await generator.next(); + } + } + + await chats.updateChatStatus("closed", payload.issue.node_id); + return { status: 200, reason: "chat_closed" }; +} + +async function* deleteChatUsers( + mtProto: MtProto, + userIds: bigInt.BigInteger[], + context: Context, + chatInput: Api.TypeInputPeer +): AsyncGenerator<{ success: boolean; index: number; error?: { errorMessage: string; seconds: number } }> { + for (let i = 0; i < userIds.length; i++) { + if (userIds[i].toJSNumber() === context.config.botId) { + continue; + } + + try { + await mtProto.client.invoke( + new mtProto.api.messages.DeleteChatUser({ + revokeHistory: false, + chatId: chatInput.className === "InputPeerChat" ? chatInput.chatId : undefined, + userId: userIds[i], + }) + ); + yield { success: true, index: i }; + } catch (error) { + yield { success: false, index: i, error } as { success: false; index: number; error: { errorMessage: string; seconds: number } }; + } + } +} + +async function intervalLogger(seconds: number, interval: number, logger: Context["logger"], promise: Promise) { + let timeLeft = seconds; + const intervalId = setInterval(() => { + timeLeft -= interval; + logger.info(`Retrying in ${timeLeft} seconds...`); + }, interval * 1000); + + await promise; + clearInterval(intervalId); +} diff --git a/src/bot/mtproto-api/workrooms/create-chat.ts b/src/bot/mtproto-api/workrooms/create-chat.ts new file mode 100644 index 0000000..0d9e44a --- /dev/null +++ b/src/bot/mtproto-api/workrooms/create-chat.ts @@ -0,0 +1,79 @@ +import { Context, SupportedEvents } from "#root/types/context"; +import { CallbackResult } from "#root/types/proxy.js"; +import { MtProto } from "../bot/mtproto"; +import { addCommentToIssue } from "#root/utils/add-comment-to-issues.js"; +import bigInt from "big-integer"; + +export async function createChat(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { + const { payload, config, logger } = context; + const chatName = "@" + payload.repository.full_name + "#" + payload.issue.number; + + const labelName = payload.label?.name; + + if (!labelName?.toLowerCase().includes("price")) { + return { status: 200, reason: "skipped" }; + } + + const mtProto = new MtProto(context); + await mtProto.initialize(); + let chatId: number; + let chatIdBigInt: bigInt.BigInteger; + logger.info("Creating chat with name: ", { chatName }); + + try { + const botIdString = await mtProto.client.getPeerId(config.botUsername, true); + + const chat = await mtProto.client.invoke( + new mtProto.api.messages.CreateChat({ + title: chatName, + users: [botIdString], + }) + ); + + let inviteLink; + + if ("chats" in chat.updates) { + chatId = chat.updates.chats[0].id.toJSNumber(); + chatIdBigInt = chat.updates.chats[0].id; + } else { + throw new Error("Failed to create chat"); + } + + if (chat.updates.chats[0].className === "Chat") { + inviteLink = await mtProto.client.invoke( + new mtProto.api.messages.ExportChatInvite({ + peer: new mtProto.api.InputPeerChat({ chatId: chatIdBigInt }), + }) + ); + } + + if (inviteLink) { + const [owner, repo] = payload.repository.full_name.split("/"); + let link; + + if ("link" in inviteLink) { + link = inviteLink.link; + } + + await addCommentToIssue(context, `A new workroom has been created for this task. [Join chat](${link})`, owner, repo, payload.issue.number); + } + + const isPromoted = await mtProto.client.invoke( + new mtProto.api.messages.EditChatAdmin({ + chatId: chatIdBigInt, + isAdmin: true, + userId: botIdString, + }) + ); + + if (!isPromoted) { + throw new Error("Failed to promote bot to admin"); + } + } catch (er) { + logger.error("Error in creating chat: ", { er }); + return { status: 500, reason: "chat_create_failed", content: { error: er } }; + } + + await context.adapters.supabase.chats.saveChat(chatId, payload.issue.title, payload.issue.node_id); + return { status: 200, reason: "chat_created" }; +} diff --git a/src/bot/mtproto-api/workrooms/reopen-chat.ts b/src/bot/mtproto-api/workrooms/reopen-chat.ts new file mode 100644 index 0000000..4743002 --- /dev/null +++ b/src/bot/mtproto-api/workrooms/reopen-chat.ts @@ -0,0 +1,93 @@ +import { Context, SupportedEvents } from "#root/types/context"; +import { CallbackResult } from "#root/types/proxy.js"; +import { MtProto } from "../bot/mtproto"; +import { Api } from "telegram"; + +export async function reopenChat(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { + const { + payload, + adapters: { + supabase: { chats }, + }, + logger, + } = context; + + const mtProto = new MtProto(context); + await mtProto.initialize(); + + logger.info("Reopening chat with name: ", { chatName: payload.issue.title }); + const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); + + const fetchChat = await mtProto.client.invoke( + new mtProto.api.messages.GetFullChat({ + chatId: chat.chatId, + }) + ); + + if (!fetchChat) { + throw new Error("Failed to fetch chat"); + } + + await mtProto.client.invoke( + new mtProto.api.folders.EditPeerFolders({ + folderPeers: [ + new mtProto.api.InputFolderPeer({ + peer: new mtProto.api.InputPeerChat({ chatId: chat.chatId }), + folderId: 0, + }), + ], + }) + ); + + const chatFull = fetchChat.fullChat as Api.ChatFull; + const participants = chatFull.participants as Api.ChatParticipantsForbidden; + + const chatCreator = participants.selfParticipant?.userId; + if (!chatCreator) { + throw new Error("Failed to get chat creator"); + } + + await mtProto.client.invoke( + new mtProto.api.messages.AddChatUser({ + chatId: chat.chatId, + userId: chatCreator, + fwdLimit: 50, + }) + ); + + await chats.updateChatStatus("reopened", payload.issue.node_id); + const users = await chats.getChatUsers(chat.chatId); + if (!users) { + throw new Error("Failed to get chat users"); + } + + const { user_ids: userIds } = users; + const chatInput = await mtProto.client.getInputEntity(chat.chatId); + + for (const userId of userIds) { + await mtProto.client.getDialogs(); + try { + if (userId === context.config.botId || userId === chatCreator) { + continue; + } + + await mtProto.client.invoke( + new mtProto.api.messages.AddChatUser({ + chatId: chatInput.className === "InputPeerChat" ? chatInput.chatId : undefined, + userId: userId, + fwdLimit: 50, + }) + ); + } catch (er) { + logger.error("Failed to add chat users", { er }); + } + } + + await mtProto.client.invoke( + new mtProto.api.messages.SendMessage({ + message: "This task has been reopened and this chat has been unarchived.", + peer: new mtProto.api.InputPeerChat({ chatId: chat.chatId }), + }) + ); + return { status: 200, reason: "chat_reopened" }; +} diff --git a/src/bot/strings.ts b/src/bot/strings.ts index 41981b5..7116323 100644 --- a/src/bot/strings.ts +++ b/src/bot/strings.ts @@ -1,5 +1,5 @@ export const STRINGS = { - WELCOME: "Welcome! I'm a bot that can help you with your daily tasks. You can use the /help command to see what I can do.", - LOG_HANDLE: "Handling update", - UNHANDLED: "I'm sorry, I don't understand that command.", -} \ No newline at end of file + WELCOME: "Welcome! I'm a bot that can help you with your daily tasks. You can use the /help command to see what I can do.", + LOG_HANDLE: "Handling update", + UNHANDLED: "I'm sorry, I don't understand that command.", +}; diff --git a/src/handlers/callbacks-proxy.ts b/src/handlers/callbacks-proxy.ts index b589224..a69561a 100644 --- a/src/handlers/callbacks-proxy.ts +++ b/src/handlers/callbacks-proxy.ts @@ -5,128 +5,114 @@ import { closeWorkroom, createWorkroom, reOpenWorkroom } from "./github/workroom /** * The `callbacks` object defines an array of callback functions for each supported event type. - * - * Since multiple callbacks might need to be executed for a single event, we store each - * callback in an array. This design allows for extensibility and flexibility, enabling + * + * Since multiple callbacks might need to be executed for a single event, we store each + * callback in an array. This design allows for extensibility and flexibility, enabling * us to add more callbacks for a particular event without modifying the core logic. */ const callbacks = { - "issues.labeled": [ - createWorkroom, - ], - "issues.closed": [ - closeWorkroom - ], - "issues.reopened": [ - reOpenWorkroom - ] + "issues.labeled": [createWorkroom], + "issues.closed": [closeWorkroom], + "issues.reopened": [reOpenWorkroom], } as ProxyCallbacks; - /** * These are function which get dispatched by this worker to fire off workflows * in the repository. We enter through the main `compute.yml` just like a typical * action plugin would, we forward the same payload that the worker received to - * the workflow the same way that the kernel does. - * + * the workflow the same way that the kernel does. + * * - First event fires, `issues.labeled` and the worker catches it. * - The worker then dispatches a workflow to `compute.yml` with the event name as the input. * - The workflow receives a `issues.labeled` payload but eventName is now WorkflowFunction (`create-telegram-chat`). * - The workflow then runs the `createChat` function which needs a node env to run. - * + * * I.e we're essentially running the first dual action/worker plugin which is * ideal for telegram-bot as it's a bot that needs to be able to be super flexible. */ const workflowCallbacks = { - "issues.labeled": [ - createChat - ], - "issues.closed": [ - closeChat - ], - "issues.reopened": [ - reopenChat - ] + "issues.labeled": [createChat], + "issues.closed": [closeChat], + "issues.reopened": [reopenChat], } as ProxyCallbacks; - /** - * The `proxyCallbacks` function returns a Proxy object that intercepts access to the + * The `proxyCallbacks` function returns a Proxy object that intercepts access to the * `callbacks` object. This Proxy enables dynamic handling of event callbacks, including: - * - * - **Event Handling:** When an event occurs, the Proxy looks up the corresponding - * callbacks in the `callbacks` object. If no callbacks are found for the event, + * + * - **Event Handling:** When an event occurs, the Proxy looks up the corresponding + * callbacks in the `callbacks` object. If no callbacks are found for the event, * it returns a `skipped` status. - * - * - **Error Handling:** If an error occurs while processing a callback, the Proxy + * + * - **Error Handling:** If an error occurs while processing a callback, the Proxy * logs the error and returns a `failed` status. - * - * The Proxy uses the `get` trap to intercept attempts to access properties on the - * `callbacks` object. This trap allows us to asynchronously execute the appropriate - * callbacks based on the event type, ensuring that the correct context is passed to + * + * The Proxy uses the `get` trap to intercept attempts to access properties on the + * `callbacks` object. This trap allows us to asynchronously execute the appropriate + * callbacks based on the event type, ensuring that the correct context is passed to * each callback. */ export function proxyCallbacks(context: Context): ProxyCallbacks { - return new Proxy(callbacks, { - get(target, prop: SupportedEventsU) { - if (!target[prop]) { - context.logger.info(`No callbacks found for event ${prop}`); - return { status: 204, reason: "skipped" }; - } - return (async () => { - try { - return await Promise.all(target[prop].map((callback) => handleCallback(callback, context))); - } catch (er) { - context.logger.error(`Failed to handle event ${prop}`, { er }); - return { status: 500, reason: "failed" }; - } - })(); - }, - }); + return new Proxy(callbacks, { + get(target, prop: SupportedEventsU) { + if (!target[prop]) { + context.logger.info(`No callbacks found for event ${prop}`); + return { status: 204, reason: "skipped" }; + } + return (async () => { + try { + return await Promise.all(target[prop].map((callback) => handleCallback(callback, context))); + } catch (er) { + context.logger.error(`Failed to handle event ${prop}`, { er }); + return { status: 500, reason: "failed" }; + } + })(); + }, + }); } - export function proxyWorkflowCallbacks(context: Context): ProxyCallbacks { - return new Proxy(workflowCallbacks, { - get(target, prop: SupportedEventsU) { - if (!target[prop]) { - context.logger.info(`No callbacks found for event ${prop}`); - return { status: 204, reason: "skipped" }; - } - return (async () => { - try { - await Promise.all(target[prop].map((callback) => handleCallback(callback, context))); - } catch (er) { - context.logger.error(`Failed to handle event ${prop}`, { er }); - await exit(1); - } - await exit(0); - })(); - }, - }); + return new Proxy(workflowCallbacks, { + get(target, prop: SupportedEventsU) { + if (!target[prop]) { + context.logger.info(`No callbacks found for event ${prop}`); + return { status: 204, reason: "skipped" }; + } + return (async () => { + try { + await Promise.all(target[prop].map((callback) => handleCallback(callback, context))); + } catch (er) { + context.logger.error(`Failed to handle event ${prop}`, { er }); + await exit(1); + } + await exit(0); + })(); + }, + }); } /** * Why do we need this wrapper function? - * - * By using a generic `Function` type for the callback parameter, we bypass strict type + * + * By using a generic `Function` type for the callback parameter, we bypass strict type * checking temporarily. This allows us to pass a standard `Context` object, which we know - * contains the correct event and payload types, to the callback safely. - * - * We can trust that the `ProxyCallbacks` type has already ensured that each callback function - * matches the expected event and payload types, so this function provides a safe and + * contains the correct event and payload types, to the callback safely. + * + * We can trust that the `ProxyCallbacks` type has already ensured that each callback function + * matches the expected event and payload types, so this function provides a safe and * flexible way to handle callbacks without introducing type or logic errors. */ +// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type function handleCallback(callback: Function, context: Context) { - return callback(context); + return callback(context); } /** * Will be used to exit the process with a status code. - * + * * 0 - Success * 1 - Failure */ async function exit(status: number = 0) { - process.exit(status); -} \ No newline at end of file + process.exit(status); +} diff --git a/src/handlers/github-webhook.ts b/src/handlers/github-webhook.ts index 7f8fdb6..1fac904 100644 --- a/src/handlers/github-webhook.ts +++ b/src/handlers/github-webhook.ts @@ -3,30 +3,30 @@ import { plugin } from "../plugin"; import { pluginSettingsSchema, pluginSettingsValidator, PluginInputs, Env } from "../types"; export async function handleGithubWebhook(request: Request, env: Env): Promise { - try { - const webhookPayload = await request.json() as PluginInputs - const settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, webhookPayload.settings)); + try { + const webhookPayload = (await request.json()) as PluginInputs; - if (!pluginSettingsValidator.test(settings)) { - const errors: string[] = []; - for (const error of pluginSettingsValidator.errors(settings)) { - console.error(error); - errors.push(`${error.path}: ${error.message}`); - } - return new Response(JSON.stringify({ error: `Error: "Invalid settings provided. ${errors.join("; ")}"` }), { - status: 400, - headers: { "content-type": "application/json" }, - }); - } - - webhookPayload.settings = settings; - await plugin(webhookPayload, env); - return new Response(JSON.stringify({ success: true }), { - status: 200, - headers: { "content-type": "application/json" }, - }); - } catch (error) { - console.log("Error in handleGithubWebhook", error); - throw new Error("Error in handleGithubWebhook"); + const settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, webhookPayload.settings)); + if (!pluginSettingsValidator.test(settings)) { + const errors: string[] = []; + for (const error of pluginSettingsValidator.errors(settings)) { + console.error(error); + errors.push(`${error.path}: ${error.message}`); + } + return new Response(JSON.stringify({ error: `Error: "Invalid settings provided. ${errors.join("; ")}"` }), { + status: 400, + headers: { "content-type": "application/json" }, + }); } -} \ No newline at end of file + + webhookPayload.settings = settings; + await plugin(webhookPayload, env); + return new Response(JSON.stringify({ success: true }), { + status: 200, + headers: { "content-type": "application/json" }, + }); + } catch (error) { + console.log("Error in handleGithubWebhook", error); + throw new Error("Error in handleGithubWebhook"); + } +} diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts index 0c04f76..3a19d13 100644 --- a/src/handlers/github/workrooms.ts +++ b/src/handlers/github/workrooms.ts @@ -3,16 +3,16 @@ import { Context, SupportedEvents } from "../../types"; import { repositoryDispatch } from "../repository-dispatch"; export async function createWorkroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { - await repositoryDispatch(context, "create-telegram-chat").catch(console.error); - return { status: 200, reason: "workflow_dispatched" }; + await repositoryDispatch(context, "create-telegram-chat").catch(console.error); + return { status: 200, reason: "workflow_dispatched" }; } export async function closeWorkroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { - await repositoryDispatch(context, "close-telegram-chat").catch(console.error); - return { status: 200, reason: "workflow_dispatched" }; + await repositoryDispatch(context, "close-telegram-chat").catch(console.error); + return { status: 200, reason: "workflow_dispatched" }; } export async function reOpenWorkroom(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { - await repositoryDispatch(context, "reopen-telegram-chat").catch(console.error); - return { status: 200, reason: "workflow_dispatched" }; + await repositoryDispatch(context, "reopen-telegram-chat").catch(console.error); + return { status: 200, reason: "workflow_dispatched" }; } diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts index 5c6b9b6..c91e6ae 100644 --- a/src/handlers/repository-dispatch.ts +++ b/src/handlers/repository-dispatch.ts @@ -1,47 +1,45 @@ -import { PluginContext } from "#root/utils/plugin-context-single.js"; +import { PluginContext } from "#root/types/plugin-context-single.js"; import { App } from "octokit"; import { Context } from "../types"; /** * Used by the worker instance to kick off workflows within it's own repository. - * + * * These workflows are extensions of the worker allowing for more complex operations * to be performed outside of Cloudflare Workers' limitations. */ - export async function repositoryDispatch(context: Context, workflow: string) { - const inputs = PluginContext.getInstance().getInputs(); - const { logger } = context; - const repository = "telegram--bot"; - const owner = "ubq-testing"; - const branch = "workflows"; - const { env: { APP_ID, APP_PRIVATE_KEY } } = context; - const app = new App({ appId: APP_ID, privateKey: APP_PRIVATE_KEY }); - const installation = await app.octokit.rest.apps.getRepoInstallation({ owner, repo: repository }); - - // Set the installation id for the octokit instance - - const octokit = await app.getInstallationOctokit(installation.data.id); - - logger.info(`Dispatching workflow function: ${workflow}`); - - /** - * We'll hit the main workflow entry and pass in the same inputs so - * that it essentially runs on the same context as the worker. - */ - - Reflect.deleteProperty(inputs, "signature"); - - return await octokit.rest.actions.createWorkflowDispatch({ - owner, - repo: repository, - workflow_id: "compute.yml", - ref: branch, - inputs: { - ...inputs, - eventPayload: JSON.stringify(context.payload), - settings: JSON.stringify(context.config), - } - }); + const inputs = PluginContext.getInstance().getInputs(); + const { logger } = context; + const repository = "telegram--bot"; + const owner = "ubq-testing"; + const branch = "workflows"; + const { + env: { APP_ID, APP_PRIVATE_KEY }, + } = context; + const app = new App({ appId: APP_ID, privateKey: APP_PRIVATE_KEY }); + const installation = await app.octokit.rest.apps.getRepoInstallation({ owner, repo: repository }); + + const octokit = await app.getInstallationOctokit(installation.data.id); + + logger.info(`Dispatching workflow function: ${workflow}`); + + /** + * We'll hit the main workflow entry and pass in the same inputs so + * that it essentially runs on the same context as the worker. + */ + + Reflect.deleteProperty(inputs, "signature"); + + return await octokit.rest.actions.createWorkflowDispatch({ + owner, + repo: repository, + workflow_id: "compute.yml", + ref: branch, + inputs: { + ...inputs, + eventPayload: JSON.stringify(context.payload), + settings: JSON.stringify(context.config), + }, + }); } - diff --git a/src/handlers/telegram-webhook.ts b/src/handlers/telegram-webhook.ts index c5bb57e..92086e3 100644 --- a/src/handlers/telegram-webhook.ts +++ b/src/handlers/telegram-webhook.ts @@ -1,16 +1,17 @@ import { Value } from "@sinclair/typebox/value"; import { envValidator, Env } from "../types"; -import { TelegramBotSingleton } from "#root/utils/telegram-bot-single.js"; +import { TelegramBotSingleton } from "#root/types/telegram-bot-single.js"; export async function handleTelegramWebhook(request: Request, env: Env): Promise { - const result = envValidator.test(env); - if (!result) { - const errors = Array.from(envValidator.errors(env)); - console.error(`Invalid tg bot env: `, errors); - } - const settings = Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)); + const isOk = envValidator.test(env); + if (!isOk) { + const errors = Array.from(envValidator.errors(env)); + console.error(`Invalid bot env: `, errors); + } - const server = TelegramBotSingleton.getInstance().getServer(); + const settings = Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)); - return server.fetch(request, settings); -} \ No newline at end of file + const server = TelegramBotSingleton.getInstance().getServer(); + + return server.fetch(request, settings); +} diff --git a/src/handlers/worker-proxy.ts b/src/handlers/worker-proxy.ts new file mode 100644 index 0000000..7ba2701 --- /dev/null +++ b/src/handlers/worker-proxy.ts @@ -0,0 +1,67 @@ +import { ProxyCallbacks } from "#root/types/proxy.js"; +import { Context, SupportedEventsU } from "../types"; +import { closeWorkroom, createWorkroom, reOpenWorkroom } from "./workflow-functions"; + +/** + * The `callbacks` object defines an array of callback functions for each supported event type. + * + * Since multiple callbacks might need to be executed for a single event, we store each + * callback in an array. This design allows for extensibility and flexibility, enabling + * us to add more callbacks for a particular event without modifying the core logic. + */ +const callbacks = { + "issues.labeled": [createWorkroom], + "issues.closed": [closeWorkroom], + "issues.reopened": [reOpenWorkroom], +} as ProxyCallbacks; + +/** + * The `proxyCallbacks` function returns a Proxy object that intercepts access to the + * `callbacks` object. This Proxy enables dynamic handling of event callbacks, including: + * + * - **Event Handling:** When an event occurs, the Proxy looks up the corresponding + * callbacks in the `callbacks` object. If no callbacks are found for the event, + * it returns a `skipped` status. + * + * - **Error Handling:** If an error occurs while processing a callback, the Proxy + * logs the error and returns a `failed` status. + * + * The Proxy uses the `get` trap to intercept attempts to access properties on the + * `callbacks` object. This trap allows us to asynchronously execute the appropriate + * callbacks based on the event type, ensuring that the correct context is passed to + * each callback. + */ +export function proxyCallbacks(context: Context): ProxyCallbacks { + return new Proxy(callbacks, { + get(target, prop: SupportedEventsU) { + if (!target[prop]) { + context.logger.info(`No callbacks found for event ${prop}`); + return { status: 204, reason: "skipped" }; + } + return (async () => { + try { + return await Promise.all(target[prop].map((callback) => handleCallback(callback, context))); + } catch (er) { + context.logger.error(`Failed to handle event ${prop}`, { er }); + return { status: 500, reason: "failed" }; + } + })(); + }, + }); +} + +/** + * Why do we need this wrapper function? + * + * By using a generic `Function` type for the callback parameter, we bypass strict type + * checking temporarily. This allows us to pass a standard `Context` object, which we know + * contains the correct event and payload types, to the callback safely. + * + * We can trust that the `ProxyCallbacks` type has already ensured that each callback function + * matches the expected event and payload types, so this function provides a safe and + * flexible way to handle callbacks without introducing type or logic errors. + */ +// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type +export function handleCallback(callback: Function, context: Context) { + return callback(context); +} diff --git a/src/handlers/workflow-functions.ts b/src/handlers/workflow-functions.ts new file mode 100644 index 0000000..61edd34 --- /dev/null +++ b/src/handlers/workflow-functions.ts @@ -0,0 +1,54 @@ +import { CallbackResult } from "#root/types/proxy.js"; +import { Context, SupportedEvents } from "../types"; +import { repositoryDispatch } from "./repository-dispatch"; + +/** + * It is expected that these workflows being dispatched are in the same repository + * as the worker. + * + * Each workflow enters through `compute.yml` like a typical action plugin with + * the worker forwarding the payload to the appropriate workflow event handler. + * + * The workflow instance has access and more privileges than the worker instance + * because it is connected through the MTProto API vs the Bot rest API. + * + * Consider the following: + * + * - The worker is a bot that can only perform actions that are allowed by the + * Telegram Bot API. + * + * - The workflow is a personal user account that can perform any action that is + * allowed by the Telegram API. + * + * - If the worker needs to perform an action that is not allowed by the Bot API, + * it should dispatch a workflow to perform the action instead. + */ + +/** + * NOTICE: + * Please follow the comment pattern below to make it easier to track + * the logic of the workflow functions across the codebase. + */ + +/** + * The logic this function can be found in [../bot/mtproto-api/workrooms/create-chat.ts](../bot/mtproto-api/workrooms/create-chat.ts) + */ +export async function createWorkroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { + await repositoryDispatch(context, "create-telegram-chat").catch(console.error); + return { status: 200, reason: "workflow_dispatched" }; +} +/** + * The logic this function can be found in [../bot/mtproto-api/workrooms/close-chat.ts](../bot/mtproto-api/workrooms/close-chat.ts) + */ +export async function closeWorkroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { + await repositoryDispatch(context, "close-telegram-chat").catch(console.error); + return { status: 200, reason: "workflow_dispatched" }; +} + +/** + * The logic this function can be found in [../bot/mtproto-api/workrooms/reopen-chat.ts](../bot/mtproto-api/workrooms/reopen-chat.ts) + */ +export async function reOpenWorkroom(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { + await repositoryDispatch(context, "reopen-telegram-chat").catch(console.error); + return { status: 200, reason: "workflow_dispatched" }; +} diff --git a/src/handlers/workflow-proxy.ts b/src/handlers/workflow-proxy.ts new file mode 100644 index 0000000..3a7280e --- /dev/null +++ b/src/handlers/workflow-proxy.ts @@ -0,0 +1,54 @@ +import { closeChat } from "#root/bot/mtproto-api/workrooms/close-chat.js"; +import { createChat } from "#root/bot/mtproto-api/workrooms/create-chat.js"; +import { reopenChat } from "#root/bot/mtproto-api/workrooms/reopen-chat.js"; +import { ProxyCallbacks } from "#root/types/proxy.js"; +import { Context, SupportedEventsU } from "../types"; +import { handleCallback } from "./worker-proxy"; + +/** + * These are function which get dispatched by this worker to fire off workflows + * in the repository. We enter through the main `compute.yml` just like a typical + * action plugin would, we forward the same payload that the worker received to + * the workflow the same way that the kernel does. + * + * - First event fires, `issues.labeled` and the worker catches it. + * - The worker then dispatches a workflow to `compute.yml` with the event name as the input. + * - The workflow receives a `issues.labeled` payload but eventName is now WorkflowFunction (`create-telegram-chat`). + * - The workflow then runs the `createChat` function which needs a node env to run. + * + * I.e we're essentially running the first dual action/worker plugin which is + * ideal for telegram-bot as it's a bot that needs to be able to be super flexible. + */ +export const workflowCallbacks = { + "issues.labeled": [createChat], + "issues.closed": [closeChat], + "issues.reopened": [reopenChat], +} as ProxyCallbacks; + +export function proxyWorkflowCallbacks(context: Context): ProxyCallbacks { + return new Proxy(workflowCallbacks, { + get(target, prop: SupportedEventsU) { + if (!target[prop]) { + context.logger.info(`No callbacks found for event ${prop}`); + return { status: 204, reason: "skipped" }; + } + + return (async () => { + await Promise.all(target[prop].map((callback) => handleCallback(callback, context))); + await exit(0); + })(); + }, + }); +} + +/** + * Workflows will hang if we don't force an exit here. We do not want + * to end the session, logout or anything else. We just want the workflow + * to perform it's action and then exit. + * + * 0 - Success + * 1 - Failure + */ +async function exit(status: number = 0) { + process.exit(status); +} diff --git a/src/helpers/add-comment-to-issues.ts b/src/helpers/add-comment-to-issues.ts index 7e446aa..b9416ed 100644 --- a/src/helpers/add-comment-to-issues.ts +++ b/src/helpers/add-comment-to-issues.ts @@ -6,28 +6,28 @@ import { getDeepValue } from "#root/utils/get-deep-value.js"; * attempt to get them from the context. */ export async function addCommentToIssue(context: Context, msg: string, owner?: string, repo?: string, issueNumber?: number) { - const { logger, octokit } = context; - logger.info(`Adding comment to ${owner}/${repo}#${issueNumber}`); + const { logger, octokit } = context; + logger.info(`Adding comment to ${owner}/${repo}#${issueNumber}`); - if (!owner || !repo || !issueNumber) { - owner = getDeepValue(context, "payload.repository.owner.login"); - repo = getDeepValue(context, "payload.repository.name"); - issueNumber = getDeepValue(context, "payload.issue.number"); - } + if (!owner || !repo || !issueNumber) { + owner = getDeepValue(context, "payload.repository.owner.login"); + repo = getDeepValue(context, "payload.repository.name"); + issueNumber = getDeepValue(context, "payload.issue.number"); + } - if (!owner || !repo || !issueNumber) { - throw new Error(logger.error("Missing owner, repo, or issue number", { owner, repo, issueNumber }).logMessage.raw); - } + if (!owner || !repo || !issueNumber) { + throw new Error(logger.error("Missing owner, repo, or issue number", { owner, repo, issueNumber }).logMessage.raw); + } - try { - await octokit.issues.createComment({ - owner, - repo, - issue_number: issueNumber, - body: msg, - }); - logger.info(`Added comment to issue ${issueNumber}`); - } catch (er) { - logger.error(`Failed to add comment to issue ${issueNumber}`, { er }); - } -} \ No newline at end of file + try { + await octokit.issues.createComment({ + owner, + repo, + issue_number: issueNumber, + body: msg, + }); + logger.info(`Added comment to issue ${issueNumber}`); + } catch (er) { + logger.error(`Failed to add comment to issue ${issueNumber}`, { er }); + } +} diff --git a/src/logger.ts b/src/logger.ts deleted file mode 100644 index 3f051da..0000000 --- a/src/logger.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Logs } from '@ubiquity-dao/ubiquibot-logger' - -export const logger = new Logs("verbose") - -export type Logger = typeof logger diff --git a/src/plugin.ts b/src/plugin.ts index e858f2d..e1a456f 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -1,25 +1,22 @@ import { Env, PluginInputs } from "./types"; import { Context } from "./types"; -import { PluginContext } from "./utils/plugin-context-single"; -import { proxyCallbacks } from "./handlers/callbacks-proxy"; -import { bubbleUpErrorComment, sanitizeMetadata } from "./utils/errors"; +import { PluginContext } from "./types/plugin-context-single"; +import { proxyCallbacks } from "./handlers/worker-proxy"; +import { bubbleUpErrorComment } from "./utils/errors"; export async function runPlugin(context: Context) { const { eventName } = context; try { - return proxyCallbacks(context)[eventName] + return proxyCallbacks(context)[eventName]; } catch (err) { - return bubbleUpErrorComment(context, err) + return bubbleUpErrorComment(context, err); } } -/** - * How a worker executes the plugin. - */ export async function plugin(inputs: PluginInputs, env: Env) { - PluginContext.initialize(inputs, env) - const context = PluginContext.getInstance().getContext() + PluginContext.initialize(inputs, env); + const context = PluginContext.getInstance().getContext(); const res = await runPlugin(context); return res; -} \ No newline at end of file +} diff --git a/src/server/environment.ts b/src/server/environment.ts deleted file mode 100644 index 9d16d36..0000000 --- a/src/server/environment.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { Logger } from '#root/logger.js' - -export interface Env { - Variables: { - requestId: string - logger: Logger - } -} diff --git a/src/server/index.ts b/src/server/index.ts index 8de4cbd..30e89fb 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,74 +1,73 @@ -import { Hono } from 'hono' -import { HTTPException } from 'hono/http-exception' -import { webhookCallback } from 'grammy' -import { getPath } from 'hono/utils/url' -import { setLogger } from '#root/server/middlewares/logger.js' -import type { Env } from '#root/server/environment.js' -import type { Bot } from '#root/bot/index.js' -import { requestLogger } from '#root/server/middlewares/request-logger.js' -import type { Logger } from '#root/logger.js' -import { Context as UbiquityOsContext } from '../types' +import { Hono } from "hono"; +import { HTTPException } from "hono/http-exception"; +import { webhookCallback } from "grammy"; +import { getPath } from "hono/utils/url"; +import { setLogger } from "#root/server/middlewares/logger.js"; +import type { Bot } from "#root/bot/index.js"; +import { requestLogger } from "#root/server/middlewares/request-logger.js"; +import type { Logger } from "#root/utils/logger.js"; +import { Context as UbiquityOsContext } from "../types"; interface Dependencies { - bot: Bot - config: UbiquityOsContext["env"] - logger: Logger + bot: Bot; + config: UbiquityOsContext["env"]; + logger: Logger; } - +interface HonoEnv { + Variables: { + requestId: string; + logger: Logger; + }; +} +/** + * Creates the Hono server instance for handling Bot API requests. + */ export function createServer(dependencies: Dependencies) { - const { - bot, - config, - logger, - } = dependencies + const { bot, config, logger } = dependencies; - const server = new Hono() + const server = new Hono(); - server.use(setLogger(logger)) - server.use(requestLogger()) + server.use(setLogger(logger)); + server.use(requestLogger()); server.onError(async (error, c) => { - console.error(c) + console.error(c); if (error instanceof HTTPException) { if (error.status < 500) - c.var.logger.info( - 'Request info failed', { + c.var.logger.info("Request info failed", { err: error, - }) + }); else - c.var.logger.fatal( - 'Request failed', { + c.var.logger.fatal("Request failed", { err: error, - }) + }); - return error.getResponse() + return error.getResponse(); } - // unexpected error - c.var.logger.error( - 'Unexpected error occurred', { + c.var.logger.error("Unexpected error occurred", { err: error, method: c.req.raw.method, path: getPath(c.req.raw), - }) + }); return c.json( { - error: 'Oops! Something went wrong.', + error: "Oops! Something went wrong.", }, - 500, - ) - }) + 500 + ); + }); - server.get('/', c => c.json({ status: true })) + server.get("/", (c) => c.json({ status: true })); server.post( - '/webhook', - webhookCallback(bot, 'hono', { + "/webhook", + webhookCallback(bot, "hono", { secretToken: config.BOT_WEBHOOK_SECRET, - }), - ) + }) + ); - return server + return server; } -export type Server = Awaited> \ No newline at end of file +export type Server = Awaited>; diff --git a/src/server/middlewares/logger.ts b/src/server/middlewares/logger.ts index b257dee..483c71c 100644 --- a/src/server/middlewares/logger.ts +++ b/src/server/middlewares/logger.ts @@ -1,13 +1,10 @@ -import type { MiddlewareHandler } from 'hono' -import type { Logger } from '#root/logger.js' +import type { MiddlewareHandler } from "hono"; +import type { Logger } from "#root/utils/logger.js"; export function setLogger(logger: Logger): MiddlewareHandler { return async (c, next) => { - c.set( - 'logger', - logger - ) + c.set("logger", logger); - await next() - } + await next(); + }; } diff --git a/src/server/middlewares/request-logger.ts b/src/server/middlewares/request-logger.ts index 0a71c95..9805da5 100644 --- a/src/server/middlewares/request-logger.ts +++ b/src/server/middlewares/request-logger.ts @@ -1,25 +1,25 @@ -import type { MiddlewareHandler } from 'hono' -import { getPath } from 'hono/utils/url' +import type { MiddlewareHandler } from "hono"; +import { getPath } from "hono/utils/url"; export function requestLogger(): MiddlewareHandler { return async (c, next) => { - const { method } = c.req - const path = getPath(c.req.raw) + const { method } = c.req; + const path = getPath(c.req.raw); - c.var.logger.debug('Incoming request', { + c.var.logger.debug("Incoming request", { method, path, - }) - const startTime = performance.now() + }); + const startTime = performance.now(); - await next() + await next(); - const endTime = performance.now() - c.var.logger.debug('Request completed', { + const endTime = performance.now(); + c.var.logger.debug("Request completed", { method, path, status: c.res.status, elapsed: endTime - startTime, - }) - } + }); + }; } diff --git a/src/types/context.ts b/src/types/context.ts index 1a12d8b..22c2fd6 100644 --- a/src/types/context.ts +++ b/src/types/context.ts @@ -5,11 +5,7 @@ import { PluginSettings } from "./plugin-inputs"; import { Logs } from "@ubiquity-dao/ubiquibot-logger"; import { createAdapters } from "../adapters"; -/** - * If we let this run on all events it'll be easier to handle multiple - * "plugins" in the future. - */ -export type SupportedEventsU = WebhookEventName +export type SupportedEventsU = WebhookEventName; export type SupportedEvents = { [K in SupportedEventsU]: K extends WebhookEventName ? WebhookEvent : never; diff --git a/src/types/env.ts b/src/types/env.ts index 8b5fd7a..6a44ed8 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -3,35 +3,76 @@ import { StaticDecode } from "@sinclair/typebox"; import "dotenv/config"; import { StandardValidator } from "typebox-validators"; +/** + * We can restrict which updates the BotFather bot will receive. + */ const allowedUpdates = T.Object({ - message: T.String(), - poll: T.String(), - edited_message: T.String(), - channel_post: T.String(), - edited_channel_post: T.String(), - business_connection: T.String(), - business_message: T.String(), - edited_business_message: T.String(), - deleted_business_messages: T.String(), - message_reaction_count: T.String(), + message: T.String(), + poll: T.String(), + edited_message: T.String(), + channel_post: T.String(), + edited_channel_post: T.String(), + business_connection: T.String(), + business_message: T.String(), + edited_business_message: T.String(), + deleted_business_messages: T.String(), + message_reaction_count: T.String(), }); export const env = T.Object({ - BOT_TOKEN: T.String(), - BOT_WEBHOOK: T.String(), - BOT_WEBHOOK_SECRET: T.String(), - BOT_ADMINS: T.Transform(T.Unknown()).Decode((str) => Array.isArray(str) ? str.map(Number) : [Number(str)]).Encode((arr) => arr.toString()), - ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))), - SUPABASE_URL: T.String(), - SUPABASE_SERVICE_KEY: T.String(), - TELEGRAM_APP_ID: T.Transform(T.Unknown()).Decode((str) => Number(str)).Encode((num) => num.toString()), - TELEGRAM_API_HASH: T.String(), - APP_ID: T.Transform(T.Unknown()).Decode((str) => Number(str)).Encode((num) => num.toString()), - APP_PRIVATE_KEY: T.Transform(T.Unknown()).Decode((str) => String(str)).Encode((str) => str), + /** + * The token for the bot given by the BotFather. + */ + BOT_TOKEN: T.String(), + /** + * The url to forward updates to. + */ + BOT_WEBHOOK: T.String(), + /** + * The secret to use when forwarding updates. + */ + BOT_WEBHOOK_SECRET: T.String(), + /** + * Ids of the users who are allowed to use admin commands. + */ + BOT_ADMINS: T.Transform(T.Unknown()) + .Decode((str) => (Array.isArray(str) ? str.map(Number) : [Number(str)])) + .Encode((arr) => arr.toString()), + /** + * Which updates the bot should receive, defaults to all. + */ + ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))), + /** + * The supabase instance url for storing chats, sessions, etc. + */ + SUPABASE_URL: T.String(), + /** + * The supabase service key for storing chats, sessions, etc. + */ + SUPABASE_SERVICE_KEY: T.String(), + /** + * Obtained from https://my.telegram.org/apps + */ + TELEGRAM_APP_ID: T.Transform(T.Unknown()) + .Decode((str) => Number(str)) + .Encode((num) => num.toString()), + /** + * Obtained from https://my.telegram.org/apps + */ + TELEGRAM_API_HASH: T.String(), + /** + * Your UbiquityOS app id + */ + APP_ID: T.Transform(T.Unknown()) + .Decode((str) => Number(str)) + .Encode((num) => num.toString()), + /** + * Your UbiquityOS private key + */ + APP_PRIVATE_KEY: T.Transform(T.Unknown()) + .Decode((str) => String(str)) + .Encode((str) => str), }); -/** - * These are the same right now but they will diverge in the future. - */ export type Env = StaticDecode; -export const envValidator = new StandardValidator(env); \ No newline at end of file +export const envValidator = new StandardValidator(env); diff --git a/src/types/plugin-context-single.ts b/src/types/plugin-context-single.ts new file mode 100644 index 0000000..e81788e --- /dev/null +++ b/src/types/plugin-context-single.ts @@ -0,0 +1,61 @@ +import { Context, Env, envValidator, PluginInputs } from "#root/types"; +import { Octokit } from "@octokit/rest"; +import { Value } from "@sinclair/typebox/value"; +import { Logs } from "@ubiquity-dao/ubiquibot-logger"; +import { createAdapters } from "../adapters"; +import { createClient } from "@supabase/supabase-js"; + +/** + * Singleton for the plugin context making accessing it throughout + * the "two branches" of the codebase easier. + * + * This is used with both the worker and the workflows. + */ +export class PluginContext { + private static _instance: PluginContext; + + private constructor( + public readonly inputs: PluginInputs, + public _env: Env + ) {} + + get env() { + return Value.Decode(envValidator.schema, Value.Default(envValidator.schema, this._env)); + } + set env(env: Env) { + this._env = env; + } + + static initialize(inputs: PluginInputs, env: Env): Context { + PluginContext._instance = new PluginContext(inputs, env); + return PluginContext._instance.getContext(); + } + + static getInstance(): PluginContext { + if (!PluginContext._instance) { + throw new Error("PluginContext not initialized"); + } + return PluginContext._instance; + } + + getInputs(): PluginInputs { + return this.inputs; + } + + getContext(): Context { + const octokit = new Octokit({ auth: this.inputs.authToken }); + const ctx: Context = { + eventName: this.inputs.eventName, + payload: this.inputs.eventPayload, + config: this.inputs.settings, + octokit, + env: this.env, + logger: new Logs("verbose"), + adapters: {} as ReturnType, + }; + + ctx.adapters = createAdapters(createClient(ctx.env.SUPABASE_URL, ctx.env.SUPABASE_SERVICE_KEY), ctx); + + return ctx; + } +} diff --git a/src/types/plugin-inputs.ts b/src/types/plugin-inputs.ts index b2370ac..1287a49 100644 --- a/src/types/plugin-inputs.ts +++ b/src/types/plugin-inputs.ts @@ -11,21 +11,16 @@ export interface PluginInputs Number(value)) + .Encode((value) => value.toString()), + /** + * The bot username, NOT the username of the personal account. */ - supergroupChatId: T.Integer(), - supergroupChatName: T.String(), - botId: T.Transform(T.Unknown()).Decode((value) => Number(value)).Encode((value) => value.toString()), botUsername: T.String(), }); diff --git a/src/types/proxy.ts b/src/types/proxy.ts index e021116..b770913 100644 --- a/src/types/proxy.ts +++ b/src/types/proxy.ts @@ -1,25 +1,24 @@ import { Context, SupportedEvents, SupportedEventsU } from "./context"; -export type CallbackResult = { status: 200 | 201 | 204 | 404 | 500, reason: string; content?: string | Record }; +export type CallbackResult = { status: 200 | 201 | 204 | 404 | 500; reason: string; content?: string | Record }; /** * The `Context` type is a generic type defined as `Context`, * where `TEvent` is a string representing the event name (e.g., "issues.labeled") * and `TPayload` is the webhook payload type for that event, derived from * the `SupportedEvents` type map. - * + * * The `ProxyCallbacks` object is cast to allow optional callbacks * for each event type. This is useful because not all events may have associated callbacks. * As opposed to Partial which could mean an undefined object. - * + * * The expected function signature for callbacks looks like this: - * + * * ```typescript * fn(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise * ``` */ -type ProxyTypeHelper = { - [K in SupportedEventsU]: Array<(context: Context) => Promise>; +export type ProxyCallbacks = { + [K in SupportedEventsU]: Array<(context: Context) => Promise>; }; -export type ProxyCallbacks = ProxyTypeHelper; \ No newline at end of file diff --git a/src/types/telegram-bot-single.ts b/src/types/telegram-bot-single.ts new file mode 100644 index 0000000..b1dac0d --- /dev/null +++ b/src/types/telegram-bot-single.ts @@ -0,0 +1,54 @@ +import { Value } from "@sinclair/typebox/value"; +import { Env, envValidator } from "."; +import { Bot, createBot } from "../bot"; +import { createServer } from "../server"; +import { logger } from "../utils/logger"; + +/** + * Singleton for the worker instance of the telegram bot + * + * This is for use with the BotFather bot and not the "user" account. + */ +export class TelegramBotSingleton { + private static _instance: TelegramBotSingleton; + private static _bot: Bot; + private static _server: ReturnType; + + static async initialize(env: Env): Promise { + if (!TelegramBotSingleton._instance) { + TelegramBotSingleton._instance = new TelegramBotSingleton(); + TelegramBotSingleton._bot = createBot(env.BOT_TOKEN, { + config: Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)), + logger, + }); + + await TelegramBotSingleton._bot.api.setWebhook(env.BOT_WEBHOOK, { + allowed_updates: env.ALLOWED_UPDATES, + drop_pending_updates: true, + }); + + TelegramBotSingleton._server = createServer({ + bot: TelegramBotSingleton._bot, + config: Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)), + logger, + }); + } + + return TelegramBotSingleton._instance; + } + + static getInstance(): TelegramBotSingleton { + if (!TelegramBotSingleton._instance) { + throw new Error("TelegramBotSingleton is not initialized. Call initialize() first."); + } + return TelegramBotSingleton._instance; + } + + getBot(): Bot { + return TelegramBotSingleton._bot; + } + + getServer(): ReturnType { + return TelegramBotSingleton._server; + } +} diff --git a/src/types/typeguards.ts b/src/types/typeguards.ts index 5e21818..0f35460 100644 --- a/src/types/typeguards.ts +++ b/src/types/typeguards.ts @@ -6,23 +6,24 @@ export function isIssueOpenedEvent(context: Context): context is Context<"issues return context.eventName === "issues.opened"; } +// eslint-disable-next-line @typescript-eslint/no-explicit-any export function isTelegramPayload(payload: any): payload is Update { try { return payload.update_id !== undefined; - } catch (e) { + } catch { return false; } } +// eslint-disable-next-line @typescript-eslint/no-explicit-any export function isGithubPayload(inputs: any): inputs is PluginInputs { try { - return inputs.eventName !== undefined - } catch (e) { + return inputs.eventName !== undefined; + } catch { return false; } } - export function isIssueLabeledEvent(context: Context): context is Context<"issues.labeled"> { return context.eventName === "issues.labeled"; -} \ No newline at end of file +} diff --git a/src/utils/add-comment-to-issues.ts b/src/utils/add-comment-to-issues.ts new file mode 100644 index 0000000..b9416ed --- /dev/null +++ b/src/utils/add-comment-to-issues.ts @@ -0,0 +1,33 @@ +import { Context } from "#root/types/context.js"; +import { getDeepValue } from "#root/utils/get-deep-value.js"; + +/** + * Ideally pass in owner, repo, and issueNumber, but if not provided, + * attempt to get them from the context. + */ +export async function addCommentToIssue(context: Context, msg: string, owner?: string, repo?: string, issueNumber?: number) { + const { logger, octokit } = context; + logger.info(`Adding comment to ${owner}/${repo}#${issueNumber}`); + + if (!owner || !repo || !issueNumber) { + owner = getDeepValue(context, "payload.repository.owner.login"); + repo = getDeepValue(context, "payload.repository.name"); + issueNumber = getDeepValue(context, "payload.issue.number"); + } + + if (!owner || !repo || !issueNumber) { + throw new Error(logger.error("Missing owner, repo, or issue number", { owner, repo, issueNumber }).logMessage.raw); + } + + try { + await octokit.issues.createComment({ + owner, + repo, + issue_number: issueNumber, + body: msg, + }); + logger.info(`Added comment to issue ${issueNumber}`); + } catch (er) { + logger.error(`Failed to add comment to issue ${issueNumber}`, { er }); + } +} diff --git a/src/utils/errors.ts b/src/utils/errors.ts index 8b2c490..c5c00c8 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -1,24 +1,24 @@ import { LogReturn } from "@ubiquity-dao/ubiquibot-logger"; import { Context } from "../types"; -import { addCommentToIssue } from "#root/helpers/add-comment-to-issues.js"; +import { addCommentToIssue } from "#root/utils/add-comment-to-issues.js"; export function handleUncaughtError(error: unknown) { - console.error(error); - const status = 500; - return new Response(JSON.stringify({ error }), { status: status, headers: { "content-type": "application/json" } }); + console.error(error); + const status = 500; + return new Response(JSON.stringify({ error }), { status: status, headers: { "content-type": "application/json" } }); } export function sanitizeMetadata(obj: LogReturn["metadata"]): string { - return JSON.stringify(obj, null, 2).replace(//g, ">").replace(/--/g, "--"); + return JSON.stringify(obj, null, 2).replace(//g, ">").replace(/--/g, "--"); } export async function bubbleUpErrorComment(context: Context, err: unknown) { - let errorMessage; - if (err instanceof LogReturn) { - errorMessage = err; - } else if (err instanceof Error) { - errorMessage = context.logger.error(err.message, { error: err }); - } else { - errorMessage = context.logger.error("An error occurred", { err }); - } - await addCommentToIssue(context, `${errorMessage?.logMessage.diff}\n`); -} \ No newline at end of file + let errorMessage; + if (err instanceof LogReturn) { + errorMessage = err; + } else if (err instanceof Error) { + errorMessage = context.logger.error(err.message, { error: err }); + } else { + errorMessage = context.logger.error("An error occurred", { err }); + } + await addCommentToIssue(context, `${errorMessage?.logMessage.diff}\n`); +} diff --git a/src/utils/get-deep-value.ts b/src/utils/get-deep-value.ts index 9c7fa52..ff99483 100644 --- a/src/utils/get-deep-value.ts +++ b/src/utils/get-deep-value.ts @@ -1,21 +1,18 @@ - /** - * While hacky, this is probably the best way to handle our use case - * and is cleaner than countless "for-in" and "if" statements. - * * This function is a utility that allows us to access deeply nested properties in an object * primarily for use with the context.payload object. It should not be overused and the developer * should be aware of the potential performance implications of using this function. - * - * Example usage: - * + * + * Example usage: + * * - `getDeepValue(context, "payload.repository.owner.login")` will return the owner * - `getDeepValue(context, ["payload", "repository", "owner", "login"])` will return the owner */ -export function getDeepValue(obj: T, path: K | K[]) { - if (!obj || !path) return undefined; +export function getDeepValue(obj: T, path: TK | TK[]) { + if (!obj || !path) return undefined; - const pathArray = Array.isArray(path) ? path : path.split('.'); + const pathArray = Array.isArray(path) ? path : path.split("."); - return pathArray.reduce((prev, key) => prev && prev[key], obj as any); -} \ No newline at end of file + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return pathArray.reduce((prev, key) => prev?.[key], obj as any); +} diff --git a/src/utils/logger.ts b/src/utils/logger.ts new file mode 100644 index 0000000..e1998d7 --- /dev/null +++ b/src/utils/logger.ts @@ -0,0 +1,5 @@ +import { Logs } from "@ubiquity-dao/ubiquibot-logger"; + +export const logger = new Logs("verbose"); + +export type Logger = typeof logger; diff --git a/src/utils/plugin-context-single.ts b/src/utils/plugin-context-single.ts index c5476fb..35c15ce 100644 --- a/src/utils/plugin-context-single.ts +++ b/src/utils/plugin-context-single.ts @@ -6,50 +6,50 @@ import { createAdapters } from "../adapters"; import { createClient } from "@supabase/supabase-js"; export class PluginContext { - private static instance: PluginContext; - - private constructor( - public readonly inputs: PluginInputs, - public _env: Env, - ) { } - - get env() { - return Value.Decode(envValidator.schema, Value.Default(envValidator.schema, this._env)); - } - set env(env: Env) { - this._env = env; - } - - static initialize(inputs: PluginInputs, env: Env): Context { - PluginContext.instance = new PluginContext(inputs, env); - return PluginContext.instance.getContext(); - } - - static getInstance(): PluginContext { - if (!PluginContext.instance) { - throw new Error("PluginContext not initialized"); - } - return PluginContext.instance; - } - - getInputs(): PluginInputs { - return this.inputs; - } - - getContext(): Context { - const octokit = new Octokit({ auth: this.inputs.authToken }); - const ctx: Context = { - eventName: this.inputs.eventName, - payload: this.inputs.eventPayload, - config: this.inputs.settings, - octokit, - env: this.env, - logger: new Logs("verbose"), - adapters: {} as ReturnType, - }; - - ctx.adapters = createAdapters(createClient(ctx.env.SUPABASE_URL, ctx.env.SUPABASE_SERVICE_KEY), ctx); - - return ctx; + private static _instance: PluginContext; + + private constructor( + public readonly inputs: PluginInputs, + public _env: Env + ) {} + + get env() { + return Value.Decode(envValidator.schema, Value.Default(envValidator.schema, this._env)); + } + set env(env: Env) { + this._env = env; + } + + static initialize(inputs: PluginInputs, env: Env): Context { + PluginContext._instance = new PluginContext(inputs, env); + return PluginContext._instance.getContext(); + } + + static getInstance(): PluginContext { + if (!PluginContext._instance) { + throw new Error("PluginContext not initialized"); } -} \ No newline at end of file + return PluginContext._instance; + } + + getInputs(): PluginInputs { + return this.inputs; + } + + getContext(): Context { + const octokit = new Octokit({ auth: this.inputs.authToken }); + const ctx: Context = { + eventName: this.inputs.eventName, + payload: this.inputs.eventPayload, + config: this.inputs.settings, + octokit, + env: this.env, + logger: new Logs("verbose"), + adapters: {} as ReturnType, + }; + + ctx.adapters = createAdapters(createClient(ctx.env.SUPABASE_URL, ctx.env.SUPABASE_SERVICE_KEY), ctx); + + return ctx; + } +} diff --git a/src/utils/smee.ts b/src/utils/smee.ts index 02460e2..64993f0 100644 --- a/src/utils/smee.ts +++ b/src/utils/smee.ts @@ -1,13 +1,13 @@ import dotenv from "dotenv"; import SmeeClient from "smee-client"; dotenv.config({ - path: ".dev.vars" + path: ".dev.vars", }); const smee = new SmeeClient({ - source: process.env.WEBHOOK_PROXY_URL || "https://smee.io/new", - target: "http://localhost:8787/events", - logger: console, + source: process.env.WEBHOOK_PROXY_URL ?? "https://smee.io/new", + target: "http://localhost:8787/events", + logger: console, }); -smee.start(); \ No newline at end of file +smee.start(); diff --git a/src/utils/telegram-bot-single.ts b/src/utils/telegram-bot-single.ts deleted file mode 100644 index a3f30e8..0000000 --- a/src/utils/telegram-bot-single.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Value } from "@sinclair/typebox/value"; -import { Env, envValidator } from "../types"; -import { Bot, createBot } from "../bot"; -import { createServer } from "../server"; -import { logger } from "../logger"; - -export class TelegramBotSingleton { - private static instance: TelegramBotSingleton; - private static bot: Bot; - private static server: ReturnType; - - private constructor( - ) { } - - static initialize(env: Env): TelegramBotSingleton { - if (!TelegramBotSingleton.instance) { - TelegramBotSingleton.instance = new TelegramBotSingleton(); - TelegramBotSingleton.bot = createBot(env.BOT_TOKEN, { - config: Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)), - logger, - }); - TelegramBotSingleton.server = createServer({ - bot: TelegramBotSingleton.bot, - config: Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)), - logger - }); - } - return TelegramBotSingleton.instance; - } - - static getInstance(): TelegramBotSingleton { - if (!TelegramBotSingleton.instance) { - throw new Error("TelegramBotSingleton is not initialized. Call initialize() first."); - } - return TelegramBotSingleton.instance; - } - - getBot(): Bot { - return TelegramBotSingleton.bot; - } - - getServer(): ReturnType { - return TelegramBotSingleton.server; - } - -} diff --git a/src/worker.ts b/src/worker.ts index a6f551d..fedd20a 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,11 +1,11 @@ -import { Env, envValidator, PluginInputs } from "./types"; +import { Env, envValidator } from "./types"; import { isGithubPayload, isTelegramPayload } from "./types/typeguards"; import { handleGithubWebhook } from "./handlers/github-webhook"; import { handleTelegramWebhook } from "./handlers/telegram-webhook"; import manifest from "../manifest.json"; import { handleUncaughtError } from "./utils/errors"; -import { TelegramBotSingleton } from "./utils/telegram-bot-single"; -import { PluginContext } from "./utils/plugin-context-single"; +import { TelegramBotSingleton } from "./types/telegram-bot-single"; +import { PluginContext } from "./types/plugin-context-single"; import { Value } from "@sinclair/typebox/value"; export default { @@ -37,7 +37,7 @@ export default { try { payload = await request.clone().json(); } catch (err) { - return new Response(JSON.stringify({ error: "Invalid JSON payload" }), { + return new Response(JSON.stringify({ error: "Invalid JSON payload", err }), { status: 400, headers: { "content-type": "application/json" }, }); @@ -57,10 +57,12 @@ export default { }); } - TelegramBotSingleton.initialize(env); + // inits the worker with the telegram bot + await TelegramBotSingleton.initialize(env); try { if (isGithubPayload(payload)) { + // inits the worker with the plugin context for this call PluginContext.initialize(payload, env); await handleGithubWebhook(request, env); } else if (isTelegramPayload(payload)) { @@ -81,4 +83,3 @@ export default { } }, }; - diff --git a/src/workflow-entry.ts b/src/workflow-entry.ts index d42f7c4..bf77410 100644 --- a/src/workflow-entry.ts +++ b/src/workflow-entry.ts @@ -2,14 +2,14 @@ import * as core from "@actions/core"; import * as github from "@actions/github"; import { Value } from "@sinclair/typebox/value"; import { envValidator, pluginSettingsSchema, PluginInputs, pluginSettingsValidator } from "./types"; -import { PluginContext } from "./utils/plugin-context-single"; -import { proxyWorkflowCallbacks } from "./handlers/callbacks-proxy"; +import { PluginContext } from "./types/plugin-context-single"; import { bubbleUpErrorComment } from "./utils/errors"; import dotenv from "dotenv"; +import { proxyWorkflowCallbacks } from "./handlers/workflow-proxy"; dotenv.config(); /** - * How a GitHub action executes the plugin. + * Main entry point for the workflow functions */ export async function run() { const payload = github.context.payload.inputs; @@ -30,7 +30,7 @@ export async function run() { SUPABASE_SERVICE_KEY: process.env.SUPABASE_SERVICE_KEY, APP_PRIVATE_KEY: process.env.APP_PRIVATE_KEY, APP_ID: process.env.APP_ID, - } + }; try { env = Value.Decode(envValidator.schema, payloadEnv); @@ -68,7 +68,7 @@ export async function run() { try { return proxyWorkflowCallbacks(context)[inputs.eventName]; } catch (err) { - return bubbleUpErrorComment(context, err) + return bubbleUpErrorComment(context, err); } } diff --git a/supabase/migrations.sql b/supabase/migrations.sql new file mode 100644 index 0000000..f8788e8 --- /dev/null +++ b/supabase/migrations.sql @@ -0,0 +1,20 @@ +CREATE TABLE IF NOT EXISTS "chats" ( + id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + created_at TIMESTAMPTZ DEFAULT now(), + updated_at TIMESTAMPTZ DEFAULT now(), + chat_id BIGINT NOT NULL, + task_node_id TEXT UNIQUE NOT NULL, + status TEXT NOT NULL CHECK (status IN ('open', 'closed', 'reopened')), + user_ids BIGINT[] +); + +CREATE TABLE IF NOT EXISTS "tg-bot-sessions" ( + id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + session_data TEXT NOT NULL +); + +REVOKE ALL ON "tg-bot-sessions" FROM PUBLIC; +REVOKE ALL ON "chats" FROM PUBLIC; + +REVOKE ALL ON "tg-bot-sessions" FROM authenticated; +REVOKE ALL ON "chats" FROM authenticated; \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 2964ef5..1bcbb7d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,18 +4,14 @@ "module": "ESNext", "moduleResolution": "Bundler", "paths": { - "#root/*": [ - "./src/*" - ] + "#root/*": ["./src/*"] }, "types": [ "jest", "node", "@cloudflare/workers-types/2023-07-01" ] /* Specify type package names to be included without being referenced in a source file. */, - "lib": [ - "ESNext" - ], + "lib": ["ESNext"], "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, "strict": true /* Enable all strict type-checking options. */, @@ -24,9 +20,8 @@ "noEmit": true, "outDir": "build", "sourceMap": true, - "preserveWatchOutput": true, + "preserveWatchOutput": true }, - "include": [ - "src/**/*" - ] -} \ No newline at end of file + "include": ["src/**/*"], + "exclude": ["node_modules", "build", "tests", "eslint.config.mjs"] +} From 8c2b26776ce64f6d0b3190c30aeff36935890530 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 12 Sep 2024 01:10:21 +0100 Subject: [PATCH 37/76] Squashed commit of the following: commit 5a8dd2b40709e509adad8642db3a558bf98e6def Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu Sep 12 00:33:00 2024 +0100 chore: eslint commit 85b052340076207c663a9da6c4983bbe01c85de0 Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu Sep 12 00:01:17 2024 +0100 chore: prettier commit 2e57506f900b670ecd865b5dc00a81a8234e0624 Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed Sep 11 23:57:08 2024 +0100 feat: documentation (80x) chore: test commit ec53f82feec96ef71cff7fd98152b2174939184f Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun Sep 8 14:52:13 2024 +0100 chore: remember to save the chat commit 7b10cbcd1e368d8758f4c7082db4053c04e7d362 Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun Sep 8 14:37:28 2024 +0100 chore: send message after closing chat commit 7dd5559ed42ec653da56bd13e29bafaebc559eed Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun Sep 8 14:20:22 2024 +0100 chore: close room commit ed47c8e8e6f7be037711861d480810174c07bc72 Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun Sep 8 02:05:56 2024 +0100 chore: moving all workroom fn into mtproto commit 0b4e971087998f8ae19dfdd443f1a2edc1c1eec8 Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun Sep 8 01:39:23 2024 +0100 chore: use new config item botId commit fbe8e790b337725fec8d2d5bf0a1a988412f9b7d Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun Sep 8 01:38:04 2024 +0100 chore: lots of minor fixes commit 304706d0ee2650364d60f1e2b1a84e15c183b5e3 Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun Sep 8 01:36:38 2024 +0100 chore: move and remove some more commit 8b07280d634cf3c59aca62aeadd7eea60d846134 Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun Sep 8 01:26:53 2024 +0100 chore: move and remove some commit 93f1eea972dbb0a4d0df657c35e0851cce40bcef Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun Sep 8 01:00:26 2024 +0100 chore: repo secrets commit 889f350e7123a7e962786669b23df373209879ab Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun Sep 8 00:57:13 2024 +0100 chore: repo secrets commit 3ea8747a4ec2c93b2ba7f5d173fbb5657491cbf6 Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun Sep 8 00:42:25 2024 +0100 chore: tidying up classes with new init commit 80db60484774e49815daefe614f1747e01abe563 Author: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sat Sep 7 23:47:20 2024 +0100 chore: re-auth working finally --- .github/workflows/compute.yml | 1 + src/handlers/callbacks-proxy.ts | 118 ----------------------------- src/handlers/github/workrooms.ts | 18 ----- src/utils/plugin-context-single.ts | 55 -------------- 4 files changed, 1 insertion(+), 191 deletions(-) delete mode 100644 src/handlers/callbacks-proxy.ts delete mode 100644 src/handlers/github/workrooms.ts delete mode 100644 src/utils/plugin-context-single.ts diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 491439b..61df489 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -24,6 +24,7 @@ jobs: env: SUPABASE_URL: ${{ secrets.SUPABASE_URL }} SUPABASE_SERVICE_KEY: ${{ secrets.SUPABASE_SERVICE_KEY }} + BOT_TOKEN: ${{ secrets.BOT_TOKEN }} BOT_ADMINS: ${{ secrets.BOT_ADMINS }} BOT_WEBHOOK: ${{ secrets.BOT_WEBHOOK }} diff --git a/src/handlers/callbacks-proxy.ts b/src/handlers/callbacks-proxy.ts deleted file mode 100644 index a69561a..0000000 --- a/src/handlers/callbacks-proxy.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { closeChat, createChat, reopenChat } from "#root/bot/mtproto-api/workrooms.js"; -import { ProxyCallbacks } from "#root/types/proxy.js"; -import { Context, SupportedEventsU } from "../types"; -import { closeWorkroom, createWorkroom, reOpenWorkroom } from "./github/workrooms"; - -/** - * The `callbacks` object defines an array of callback functions for each supported event type. - * - * Since multiple callbacks might need to be executed for a single event, we store each - * callback in an array. This design allows for extensibility and flexibility, enabling - * us to add more callbacks for a particular event without modifying the core logic. - */ -const callbacks = { - "issues.labeled": [createWorkroom], - "issues.closed": [closeWorkroom], - "issues.reopened": [reOpenWorkroom], -} as ProxyCallbacks; - -/** - * These are function which get dispatched by this worker to fire off workflows - * in the repository. We enter through the main `compute.yml` just like a typical - * action plugin would, we forward the same payload that the worker received to - * the workflow the same way that the kernel does. - * - * - First event fires, `issues.labeled` and the worker catches it. - * - The worker then dispatches a workflow to `compute.yml` with the event name as the input. - * - The workflow receives a `issues.labeled` payload but eventName is now WorkflowFunction (`create-telegram-chat`). - * - The workflow then runs the `createChat` function which needs a node env to run. - * - * I.e we're essentially running the first dual action/worker plugin which is - * ideal for telegram-bot as it's a bot that needs to be able to be super flexible. - */ -const workflowCallbacks = { - "issues.labeled": [createChat], - "issues.closed": [closeChat], - "issues.reopened": [reopenChat], -} as ProxyCallbacks; - -/** - * The `proxyCallbacks` function returns a Proxy object that intercepts access to the - * `callbacks` object. This Proxy enables dynamic handling of event callbacks, including: - * - * - **Event Handling:** When an event occurs, the Proxy looks up the corresponding - * callbacks in the `callbacks` object. If no callbacks are found for the event, - * it returns a `skipped` status. - * - * - **Error Handling:** If an error occurs while processing a callback, the Proxy - * logs the error and returns a `failed` status. - * - * The Proxy uses the `get` trap to intercept attempts to access properties on the - * `callbacks` object. This trap allows us to asynchronously execute the appropriate - * callbacks based on the event type, ensuring that the correct context is passed to - * each callback. - */ -export function proxyCallbacks(context: Context): ProxyCallbacks { - return new Proxy(callbacks, { - get(target, prop: SupportedEventsU) { - if (!target[prop]) { - context.logger.info(`No callbacks found for event ${prop}`); - return { status: 204, reason: "skipped" }; - } - return (async () => { - try { - return await Promise.all(target[prop].map((callback) => handleCallback(callback, context))); - } catch (er) { - context.logger.error(`Failed to handle event ${prop}`, { er }); - return { status: 500, reason: "failed" }; - } - })(); - }, - }); -} - -export function proxyWorkflowCallbacks(context: Context): ProxyCallbacks { - return new Proxy(workflowCallbacks, { - get(target, prop: SupportedEventsU) { - if (!target[prop]) { - context.logger.info(`No callbacks found for event ${prop}`); - return { status: 204, reason: "skipped" }; - } - return (async () => { - try { - await Promise.all(target[prop].map((callback) => handleCallback(callback, context))); - } catch (er) { - context.logger.error(`Failed to handle event ${prop}`, { er }); - await exit(1); - } - await exit(0); - })(); - }, - }); -} - -/** - * Why do we need this wrapper function? - * - * By using a generic `Function` type for the callback parameter, we bypass strict type - * checking temporarily. This allows us to pass a standard `Context` object, which we know - * contains the correct event and payload types, to the callback safely. - * - * We can trust that the `ProxyCallbacks` type has already ensured that each callback function - * matches the expected event and payload types, so this function provides a safe and - * flexible way to handle callbacks without introducing type or logic errors. - */ -// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type -function handleCallback(callback: Function, context: Context) { - return callback(context); -} - -/** - * Will be used to exit the process with a status code. - * - * 0 - Success - * 1 - Failure - */ -async function exit(status: number = 0) { - process.exit(status); -} diff --git a/src/handlers/github/workrooms.ts b/src/handlers/github/workrooms.ts deleted file mode 100644 index 3a19d13..0000000 --- a/src/handlers/github/workrooms.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { CallbackResult } from "#root/types/proxy.js"; -import { Context, SupportedEvents } from "../../types"; -import { repositoryDispatch } from "../repository-dispatch"; - -export async function createWorkroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { - await repositoryDispatch(context, "create-telegram-chat").catch(console.error); - return { status: 200, reason: "workflow_dispatched" }; -} - -export async function closeWorkroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { - await repositoryDispatch(context, "close-telegram-chat").catch(console.error); - return { status: 200, reason: "workflow_dispatched" }; -} - -export async function reOpenWorkroom(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { - await repositoryDispatch(context, "reopen-telegram-chat").catch(console.error); - return { status: 200, reason: "workflow_dispatched" }; -} diff --git a/src/utils/plugin-context-single.ts b/src/utils/plugin-context-single.ts deleted file mode 100644 index 35c15ce..0000000 --- a/src/utils/plugin-context-single.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Context, Env, envValidator, PluginInputs } from "#root/types"; -import { Octokit } from "@octokit/rest"; -import { Value } from "@sinclair/typebox/value"; -import { Logs } from "@ubiquity-dao/ubiquibot-logger"; -import { createAdapters } from "../adapters"; -import { createClient } from "@supabase/supabase-js"; - -export class PluginContext { - private static _instance: PluginContext; - - private constructor( - public readonly inputs: PluginInputs, - public _env: Env - ) {} - - get env() { - return Value.Decode(envValidator.schema, Value.Default(envValidator.schema, this._env)); - } - set env(env: Env) { - this._env = env; - } - - static initialize(inputs: PluginInputs, env: Env): Context { - PluginContext._instance = new PluginContext(inputs, env); - return PluginContext._instance.getContext(); - } - - static getInstance(): PluginContext { - if (!PluginContext._instance) { - throw new Error("PluginContext not initialized"); - } - return PluginContext._instance; - } - - getInputs(): PluginInputs { - return this.inputs; - } - - getContext(): Context { - const octokit = new Octokit({ auth: this.inputs.authToken }); - const ctx: Context = { - eventName: this.inputs.eventName, - payload: this.inputs.eventPayload, - config: this.inputs.settings, - octokit, - env: this.env, - logger: new Logs("verbose"), - adapters: {} as ReturnType, - }; - - ctx.adapters = createAdapters(createClient(ctx.env.SUPABASE_URL, ctx.env.SUPABASE_SERVICE_KEY), ctx); - - return ctx; - } -} From 0286fd599a5876b602de770cfe583a68d4e7cacc Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 12 Sep 2024 19:29:11 +0100 Subject: [PATCH 38/76] chore: remove bad squash, alias type for Update --- src/bot/filters/is-admin.ts | 4 +- src/bot/grammy-context.ts | 37 ---- src/bot/helpers/grammy-context.ts | 6 +- src/bot/helpers/logging.ts | 5 +- src/bot/mtproto-api/workrooms.ts | 197 ------------------- src/bot/mtproto-api/workrooms/create-chat.ts | 2 +- src/helpers/add-comment-to-issues.ts | 33 ---- src/types/plugin-inputs.ts | 4 - src/types/typeguards.ts | 20 +- src/utils/smee.ts | 13 -- 10 files changed, 14 insertions(+), 307 deletions(-) delete mode 100644 src/bot/grammy-context.ts delete mode 100644 src/bot/mtproto-api/workrooms.ts delete mode 100644 src/helpers/add-comment-to-issues.ts delete mode 100644 src/utils/smee.ts diff --git a/src/bot/filters/is-admin.ts b/src/bot/filters/is-admin.ts index ba8d8e2..e53119f 100644 --- a/src/bot/filters/is-admin.ts +++ b/src/bot/filters/is-admin.ts @@ -1,5 +1,5 @@ import { isUserHasId } from "grammy-guard"; -export function isAdmin() { - return (ids: number[]) => isUserHasId(...ids); +export function isAdmin(ids: number[]) { + return isUserHasId(...ids); } diff --git a/src/bot/grammy-context.ts b/src/bot/grammy-context.ts deleted file mode 100644 index 81d594c..0000000 --- a/src/bot/grammy-context.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { Update, UserFromGetMe } from "@grammyjs/types"; -import { type Api, Context as DefaultContext, type SessionFlavor } from "grammy"; -import type { AutoChatActionFlavor } from "@grammyjs/auto-chat-action"; -import type { HydrateFlavor } from "@grammyjs/hydrate"; -import type { ParseModeFlavor } from "@grammyjs/parse-mode"; -import { Context as UbiquityOsContext } from "../types"; -import { Logger } from "#root/utils/logger.js"; - -export interface SessionData { - field?: string; -} - -interface ExtendedContextFlavor { - logger: Logger; - config: UbiquityOsContext["env"]; -} - -export type Context = ParseModeFlavor & AutoChatActionFlavor>>; - -interface Dependencies { - logger: Logger; - config: UbiquityOsContext["env"]; -} - -export function createContextConstructor({ logger, config }: Dependencies) { - return class extends DefaultContext implements ExtendedContextFlavor { - logger: Logger; - config: UbiquityOsContext["env"]; - - constructor(update: Update, api: Api, me: UserFromGetMe) { - super(update, api, me); - - this.logger = logger; - this.config = config; - } - } as unknown as new (update: Update, api: Api, me: UserFromGetMe) => Context; -} diff --git a/src/bot/helpers/grammy-context.ts b/src/bot/helpers/grammy-context.ts index 0cb51fb..a5bcd1a 100644 --- a/src/bot/helpers/grammy-context.ts +++ b/src/bot/helpers/grammy-context.ts @@ -6,6 +6,8 @@ import type { ParseModeFlavor } from "@grammyjs/parse-mode"; import type { Logger } from "#root/utils/logger.js"; import { Context as UbiquityOsContext } from "../../types"; +export type GrammyTelegramUpdate = Update; + export interface SessionData { field?: string; } @@ -27,11 +29,11 @@ export function createContextConstructor({ logger, config }: Dependencies) { logger: Logger; config: UbiquityOsContext["env"]; - constructor(update: Update, api: Api, me: UserFromGetMe) { + constructor(update: GrammyTelegramUpdate, api: Api, me: UserFromGetMe) { super(update, api, me); this.logger = logger; this.config = config; } - } as unknown as new (update: Update, api: Api, me: UserFromGetMe) => Context; + } as unknown as new (update: GrammyTelegramUpdate, api: Api, me: UserFromGetMe) => Context; } diff --git a/src/bot/helpers/logging.ts b/src/bot/helpers/logging.ts index c688e3c..1dd36fe 100644 --- a/src/bot/helpers/logging.ts +++ b/src/bot/helpers/logging.ts @@ -1,8 +1,7 @@ import type { Middleware } from "grammy"; -import type { Update } from "@grammyjs/types"; -import type { Context } from "#root/bot/helpers/grammy-context.js"; +import type { Context, GrammyTelegramUpdate } from "#root/bot/helpers/grammy-context.js"; -export function getUpdateInfo(ctx: Context): Omit { +export function getUpdateInfo(ctx: Context): Omit { const { update_id, ...update } = ctx.update; return update; diff --git a/src/bot/mtproto-api/workrooms.ts b/src/bot/mtproto-api/workrooms.ts deleted file mode 100644 index 229d071..0000000 --- a/src/bot/mtproto-api/workrooms.ts +++ /dev/null @@ -1,197 +0,0 @@ -import { Context, SupportedEvents } from "#root/types/context"; -import { CallbackResult } from "#root/types/proxy.js"; -import { MtProto } from "./bot/mtproto"; -import { Api } from "telegram"; -import { addCommentToIssue } from "#root/helpers/add-comment-to-issues.js"; - -function isPriceLabelChange(label: string): boolean { - return label.toLowerCase().includes("price"); -} - -export async function createChat(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { - const { payload, config, logger } = context; - const chatName = payload.issue.title; - - const labelName = payload.label?.name; - - if (!labelName || !isPriceLabelChange(labelName)) { - return { status: 200, reason: "skipped" }; - } - - const mtProto = new MtProto(context); - await mtProto.initialize(); - let chatId: number; - logger.info("Creating chat with name: ", { chatName }); - - try { - const botIdString = await mtProto.client.getPeerId(config.botUsername, true); - - const chat = await mtProto.client.invoke( - new mtProto.api.messages.CreateChat({ - title: chatName, - users: [botIdString], - }) - ); - let inviteLink; - - if ("chats" in chat.updates) { - chatId = chat.updates.chats[0].id.toJSNumber(); - } else { - throw new Error("Failed to create chat"); - } - - if (chat.updates.chats[0].className === "Chat") { - inviteLink = await mtProto.client.invoke( - new mtProto.api.messages.ExportChatInvite({ - peer: new mtProto.api.InputPeerChat({ chatId: chat.updates.chats[0].id }), - }) - ); - } - - if (inviteLink) { - const [owner, repo] = payload.repository.full_name.split("/"); - let link; - - if ("link" in inviteLink) { - link = inviteLink.link; - } - - await addCommentToIssue(context, `A new workroom has been created for this task. [Join chat](${link})`, owner, repo, payload.issue.number); - } - - const isPromoted = await mtProto.client.invoke( - new mtProto.api.messages.EditChatAdmin({ - chatId: chat.updates.chats[0].id, - isAdmin: true, - userId: botIdString, - }) - ); - - if (!isPromoted) { - throw new Error("Failed to promote bot to admin"); - } - } catch (er) { - logger.error("Error in creating chat: ", { er }); - return { status: 500, reason: "chat_create_failed", content: { error: er } }; - } - - await context.adapters.supabase.chats.saveChat(chatId, payload.issue.title, payload.issue.node_id); - return { status: 200, reason: "chat_created" }; -} - -export async function closeChat(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { - const { - payload, - adapters: { - supabase: { chats }, - }, - logger, - } = context; - try { - const mtProto = new MtProto(context); - await mtProto.initialize(); - - logger.info("Closing chat with name: ", { chatName: payload.issue.title }); - const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); - - const fetchChat = await mtProto.client.invoke( - new mtProto.api.messages.GetFullChat({ - chatId: chat.chatId, - }) - ); - - if (!fetchChat) { - throw new Error("Failed to fetch chat"); - } - - let chatParticipants; - - if ("participants" in fetchChat.fullChat) { - chatParticipants = fetchChat.fullChat.participants; - } else { - throw new Error("Failed to fetch chat participants"); - } - - if (chatParticipants.className === "ChatParticipants") { - await mtProto.client.invoke( - new mtProto.api.messages.SendMessage({ - message: "This task has been closed and this chat has been archived.", - peer: new mtProto.api.InputPeerChat({ chatId: chat.chatId }), - }) - ); - - const userIds = chatParticipants.participants.map((participant) => { - return participant.userId; - }); - - for (const userId of userIds) { - if (userId.toJSNumber() === context.config.botId) { - continue; - } - await mtProto.client.invoke( - new mtProto.api.messages.DeleteChatUser({ - chatId: chat.chatId, - userId: userId, - }) - ); - } - } - - await chats.updateChatStatus("closed", payload.issue.node_id); - - return { status: 200, reason: "chat_closed" }; - } catch (er) { - logger.error("Failed to close chat", { er }); - return { status: 500, reason: "chat_close_failed", content: { error: er } }; - } -} - -export async function reopenChat(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { - const { - payload, - adapters: { - supabase: { chats }, - }, - logger, - } = context; - try { - const mtProto = new MtProto(context); - await mtProto.initialize(); - - logger.info("Reopening chat with name: ", { chatName: payload.issue.title }); - const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); - - const fetchChat = await mtProto.client.invoke( - new mtProto.api.messages.GetFullChat({ - chatId: chat.chatId, - }) - ); - - if (!fetchChat) { - throw new Error("Failed to fetch chat"); - } - - const chatFull = fetchChat.fullChat as Api.ChatFull; - const participants = chatFull.participants as Api.ChatParticipants; - - console.log("Participants: ", participants); - - for (const participant of participants.participants) { - if (participant instanceof mtProto.api.ChatParticipant) { - await mtProto.client.invoke( - new mtProto.api.messages.AddChatUser({ - chatId: chat.chatId, - userId: participant.userId, - fwdLimit: 50, - }) - ); - } - } - - return { status: 200, reason: "chat_reopened" }; - } catch (er) { - console.log(er); - logger.error("Failed to reopen chat", { er }); - return { status: 500, reason: "chat_reopen_failed", content: { error: er } }; - } -} diff --git a/src/bot/mtproto-api/workrooms/create-chat.ts b/src/bot/mtproto-api/workrooms/create-chat.ts index 0d9e44a..cc78ead 100644 --- a/src/bot/mtproto-api/workrooms/create-chat.ts +++ b/src/bot/mtproto-api/workrooms/create-chat.ts @@ -21,7 +21,7 @@ export async function createChat(context: Context<"issues.labeled", SupportedEve logger.info("Creating chat with name: ", { chatName }); try { - const botIdString = await mtProto.client.getPeerId(config.botUsername, true); + const botIdString = await mtProto.client.getPeerId(config.botId, true); const chat = await mtProto.client.invoke( new mtProto.api.messages.CreateChat({ diff --git a/src/helpers/add-comment-to-issues.ts b/src/helpers/add-comment-to-issues.ts deleted file mode 100644 index b9416ed..0000000 --- a/src/helpers/add-comment-to-issues.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Context } from "#root/types/context.js"; -import { getDeepValue } from "#root/utils/get-deep-value.js"; - -/** - * Ideally pass in owner, repo, and issueNumber, but if not provided, - * attempt to get them from the context. - */ -export async function addCommentToIssue(context: Context, msg: string, owner?: string, repo?: string, issueNumber?: number) { - const { logger, octokit } = context; - logger.info(`Adding comment to ${owner}/${repo}#${issueNumber}`); - - if (!owner || !repo || !issueNumber) { - owner = getDeepValue(context, "payload.repository.owner.login"); - repo = getDeepValue(context, "payload.repository.name"); - issueNumber = getDeepValue(context, "payload.issue.number"); - } - - if (!owner || !repo || !issueNumber) { - throw new Error(logger.error("Missing owner, repo, or issue number", { owner, repo, issueNumber }).logMessage.raw); - } - - try { - await octokit.issues.createComment({ - owner, - repo, - issue_number: issueNumber, - body: msg, - }); - logger.info(`Added comment to issue ${issueNumber}`); - } catch (er) { - logger.error(`Failed to add comment to issue ${issueNumber}`, { er }); - } -} diff --git a/src/types/plugin-inputs.ts b/src/types/plugin-inputs.ts index 1287a49..9702225 100644 --- a/src/types/plugin-inputs.ts +++ b/src/types/plugin-inputs.ts @@ -18,10 +18,6 @@ export const pluginSettingsSchema = T.Object({ botId: T.Transform(T.Unknown()) .Decode((value) => Number(value)) .Encode((value) => value.toString()), - /** - * The bot username, NOT the username of the personal account. - */ - botUsername: T.String(), }); export const pluginSettingsValidator = new StandardValidator(pluginSettingsSchema); diff --git a/src/types/typeguards.ts b/src/types/typeguards.ts index 0f35460..058f7d2 100644 --- a/src/types/typeguards.ts +++ b/src/types/typeguards.ts @@ -1,4 +1,4 @@ -import { Update } from "@grammyjs/types"; +import { GrammyTelegramUpdate } from "#root/bot/helpers/grammy-context.js"; import { Context } from "./context"; import { PluginInputs } from "./plugin-inputs"; @@ -6,22 +6,12 @@ export function isIssueOpenedEvent(context: Context): context is Context<"issues return context.eventName === "issues.opened"; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function isTelegramPayload(payload: any): payload is Update { - try { - return payload.update_id !== undefined; - } catch { - return false; - } +export function isTelegramPayload(payload: object): payload is GrammyTelegramUpdate { + return "update_id" in payload; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function isGithubPayload(inputs: any): inputs is PluginInputs { - try { - return inputs.eventName !== undefined; - } catch { - return false; - } +export function isGithubPayload(inputs: object): inputs is PluginInputs { + return "eventName" in inputs; } export function isIssueLabeledEvent(context: Context): context is Context<"issues.labeled"> { diff --git a/src/utils/smee.ts b/src/utils/smee.ts deleted file mode 100644 index 64993f0..0000000 --- a/src/utils/smee.ts +++ /dev/null @@ -1,13 +0,0 @@ -import dotenv from "dotenv"; -import SmeeClient from "smee-client"; -dotenv.config({ - path: ".dev.vars", -}); - -const smee = new SmeeClient({ - source: process.env.WEBHOOK_PROXY_URL ?? "https://smee.io/new", - target: "http://localhost:8787/events", - logger: console, -}); - -smee.start(); From e7605368c317e0dc69ce94a3d13d2db2a36fa39d Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 12 Sep 2024 19:35:24 +0100 Subject: [PATCH 39/76] chore: fix typeguards --- src/types/typeguards.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/types/typeguards.ts b/src/types/typeguards.ts index 058f7d2..3db2770 100644 --- a/src/types/typeguards.ts +++ b/src/types/typeguards.ts @@ -6,11 +6,13 @@ export function isIssueOpenedEvent(context: Context): context is Context<"issues return context.eventName === "issues.opened"; } -export function isTelegramPayload(payload: object): payload is GrammyTelegramUpdate { +export function isTelegramPayload(payload: unknown): payload is GrammyTelegramUpdate { + if(typeof payload !== "object" || !payload) return false; return "update_id" in payload; } -export function isGithubPayload(inputs: object): inputs is PluginInputs { +export function isGithubPayload(inputs: unknown): inputs is PluginInputs { + if(typeof inputs !== "object" || !inputs) return false; return "eventName" in inputs; } From d785f56611ad414a49373d759178a8f55e8b8709 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 12 Sep 2024 23:03:58 +0100 Subject: [PATCH 40/76] chore: fix getDeepValue generic --- src/utils/add-comment-to-issues.ts | 8 +++++--- src/utils/get-deep-value.ts | 13 ++++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/utils/add-comment-to-issues.ts b/src/utils/add-comment-to-issues.ts index b9416ed..f09e09e 100644 --- a/src/utils/add-comment-to-issues.ts +++ b/src/utils/add-comment-to-issues.ts @@ -9,10 +9,12 @@ export async function addCommentToIssue(context: Context, msg: string, owner?: s const { logger, octokit } = context; logger.info(`Adding comment to ${owner}/${repo}#${issueNumber}`); + let obj; + if (!owner || !repo || !issueNumber) { - owner = getDeepValue(context, "payload.repository.owner.login"); - repo = getDeepValue(context, "payload.repository.name"); - issueNumber = getDeepValue(context, "payload.issue.number"); + owner = getDeepValue(context, "payload.repository.owner.login"); + repo = getDeepValue(context, "payload.repository.name"); + obj = getDeepValue(context, "payload.issue.number"); } if (!owner || !repo || !issueNumber) { diff --git a/src/utils/get-deep-value.ts b/src/utils/get-deep-value.ts index ff99483..003627d 100644 --- a/src/utils/get-deep-value.ts +++ b/src/utils/get-deep-value.ts @@ -1,3 +1,4 @@ +import { Context } from "../types"; /** * This function is a utility that allows us to access deeply nested properties in an object * primarily for use with the context.payload object. It should not be overused and the developer @@ -8,11 +9,13 @@ * - `getDeepValue(context, "payload.repository.owner.login")` will return the owner * - `getDeepValue(context, ["payload", "repository", "owner", "login"])` will return the owner */ -export function getDeepValue(obj: T, path: TK | TK[]) { - if (!obj || !path) return undefined; - +export function getDeepValue(obj: T, path: string | string[]): TK { const pathArray = Array.isArray(path) ? path : path.split("."); + const [head, ...tail] = pathArray; + + if (tail.length === 0) { + return obj[head as keyof T] as TK; + } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - return pathArray.reduce((prev, key) => prev?.[key], obj as any); + return getDeepValue(obj[head as keyof T] as Context, tail) as TK; } From 44aee9f8a91c0f6f62fcb24061e5ea7611071db7 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 12 Sep 2024 23:33:56 +0100 Subject: [PATCH 41/76] chore: comments and tighten typeguards --- src/bot/index.ts | 9 +++++++-- src/bot/mtproto-api/workrooms/close-chat.ts | 12 ++++++++---- src/bot/mtproto-api/workrooms/create-chat.ts | 11 ++++++----- src/bot/mtproto-api/workrooms/reopen-chat.ts | 16 +++++++++++++--- src/handlers/repository-dispatch.ts | 9 +++++++++ src/handlers/workflow-functions.ts | 12 +++--------- src/handlers/workflow-proxy.ts | 3 +-- src/types/typeguards.ts | 8 ++++---- 8 files changed, 51 insertions(+), 29 deletions(-) diff --git a/src/bot/index.ts b/src/bot/index.ts index 0627b2f..3db3ed7 100644 --- a/src/bot/index.ts +++ b/src/bot/index.ts @@ -49,14 +49,19 @@ export function createBot(token: string, dependencies: Dependencies, options: Op protectedBot.use(hydrate()); protectedBot.use(session({ getSessionKey, storage: options.botSessionStorage })); - // Handlers + // the `/start` command for a traditional TG bot, doubt we need this as-is + // but a variation of can be built for various scenarios. protectedBot.use(welcomeFeature); + + // admin commands protectedBot.use(adminFeature); + + // development commands protectedBot.use(userIdFeature); protectedBot.use(chatIdFeature); protectedBot.use(botIdFeature); - // must be the last handler + // unhandled command handler protectedBot.use(unhandledFeature); return bot; diff --git a/src/bot/mtproto-api/workrooms/close-chat.ts b/src/bot/mtproto-api/workrooms/close-chat.ts index b15c74e..3b6c9d4 100644 --- a/src/bot/mtproto-api/workrooms/close-chat.ts +++ b/src/bot/mtproto-api/workrooms/close-chat.ts @@ -18,20 +18,20 @@ export async function closeChat(context: Context<"issues.closed", SupportedEvent logger.info("Closing chat with name: ", { chatName: payload.issue.title }); const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); - const fetchChat = await mtProto.client.invoke( + const fetchedChat = await mtProto.client.invoke( new mtProto.api.messages.GetFullChat({ chatId: chat.chatId, }) ); - if (!fetchChat) { + if (!fetchedChat) { throw new Error("Failed to fetch chat"); } let chatParticipants; - if ("participants" in fetchChat.fullChat) { - chatParticipants = fetchChat.fullChat.participants; + if ("participants" in fetchedChat.fullChat) { + chatParticipants = fetchedChat.fullChat.participants; } else { throw new Error("Failed to fetch chat participants"); } @@ -108,6 +108,7 @@ async function* deleteChatUsers( chatInput: Api.TypeInputPeer ): AsyncGenerator<{ success: boolean; index: number; error?: { errorMessage: string; seconds: number } }> { for (let i = 0; i < userIds.length; i++) { + // don't kick our friendly bot if (userIds[i].toJSNumber() === context.config.botId) { continue; } @@ -127,6 +128,7 @@ async function* deleteChatUsers( } } +// Gives feedback while we wait for the FLOOD error to expire async function intervalLogger(seconds: number, interval: number, logger: Context["logger"], promise: Promise) { let timeLeft = seconds; const intervalId = setInterval(() => { @@ -134,6 +136,8 @@ async function intervalLogger(seconds: number, interval: number, logger: Context logger.info(`Retrying in ${timeLeft} seconds...`); }, interval * 1000); + // by this point the initial promise has resolved, this is a formality + // as without it this function will not be async await promise; clearInterval(intervalId); } diff --git a/src/bot/mtproto-api/workrooms/create-chat.ts b/src/bot/mtproto-api/workrooms/create-chat.ts index cc78ead..0b3f31a 100644 --- a/src/bot/mtproto-api/workrooms/create-chat.ts +++ b/src/bot/mtproto-api/workrooms/create-chat.ts @@ -8,7 +8,7 @@ export async function createChat(context: Context<"issues.labeled", SupportedEve const { payload, config, logger } = context; const chatName = "@" + payload.repository.full_name + "#" + payload.issue.number; - const labelName = payload.label?.name; + const labelName = payload.label?.name.toLowerCase(); if (!labelName?.toLowerCase().includes("price")) { return { status: 200, reason: "skipped" }; @@ -53,12 +53,13 @@ export async function createChat(context: Context<"issues.labeled", SupportedEve if ("link" in inviteLink) { link = inviteLink.link; + await addCommentToIssue(context, `A new workroom has been created for this task. [Join chat](${link})`, owner, repo, payload.issue.number); + } else { + throw new Error(logger.error(`Failed to create chat invite link for the workroom: ${chatName}`).logMessage.raw); } - - await addCommentToIssue(context, `A new workroom has been created for this task. [Join chat](${link})`, owner, repo, payload.issue.number); } - const isPromoted = await mtProto.client.invoke( + const isBotPromotedToAdmin = await mtProto.client.invoke( new mtProto.api.messages.EditChatAdmin({ chatId: chatIdBigInt, isAdmin: true, @@ -66,7 +67,7 @@ export async function createChat(context: Context<"issues.labeled", SupportedEve }) ); - if (!isPromoted) { + if (!isBotPromotedToAdmin) { throw new Error("Failed to promote bot to admin"); } } catch (er) { diff --git a/src/bot/mtproto-api/workrooms/reopen-chat.ts b/src/bot/mtproto-api/workrooms/reopen-chat.ts index 4743002..fa92f6f 100644 --- a/src/bot/mtproto-api/workrooms/reopen-chat.ts +++ b/src/bot/mtproto-api/workrooms/reopen-chat.ts @@ -18,16 +18,17 @@ export async function reopenChat(context: Context<"issues.reopened", SupportedEv logger.info("Reopening chat with name: ", { chatName: payload.issue.title }); const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); - const fetchChat = await mtProto.client.invoke( + const fetchedChat = await mtProto.client.invoke( new mtProto.api.messages.GetFullChat({ chatId: chat.chatId, }) ); - if (!fetchChat) { + if (!fetchedChat) { throw new Error("Failed to fetch chat"); } + // unarchive await mtProto.client.invoke( new mtProto.api.folders.EditPeerFolders({ folderPeers: [ @@ -39,7 +40,7 @@ export async function reopenChat(context: Context<"issues.reopened", SupportedEv }) ); - const chatFull = fetchChat.fullChat as Api.ChatFull; + const chatFull = fetchedChat.fullChat as Api.ChatFull; const participants = chatFull.participants as Api.ChatParticipantsForbidden; const chatCreator = participants.selfParticipant?.userId; @@ -47,6 +48,7 @@ export async function reopenChat(context: Context<"issues.reopened", SupportedEv throw new Error("Failed to get chat creator"); } + // add the creator back to obtain control of the chat await mtProto.client.invoke( new mtProto.api.messages.AddChatUser({ chatId: chat.chatId, @@ -65,8 +67,16 @@ export async function reopenChat(context: Context<"issues.reopened", SupportedEv const chatInput = await mtProto.client.getInputEntity(chat.chatId); for (const userId of userIds) { + /** + * Dialogs are all of the chats, channels, and users that the account has interacted with. + * By obtaining the dialogs, we guarantee our client (that's what we are considered to be by the MTProto API) + * has up to date context otherwise these operations seem to fail. + * + * There is likely a better way to handle this, but this works for now. + */ await mtProto.client.getDialogs(); try { + // don't add the bot or the chat creator, as they are already in the chat if (userId === context.config.botId || userId === chatCreator) { continue; } diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts index c91e6ae..fb47c3a 100644 --- a/src/handlers/repository-dispatch.ts +++ b/src/handlers/repository-dispatch.ts @@ -11,9 +11,18 @@ import { Context } from "../types"; export async function repositoryDispatch(context: Context, workflow: string) { const inputs = PluginContext.getInstance().getInputs(); const { logger } = context; + + /** + * These will remain hardcoded as `context` will have other repositories + * and branches that are not relevant to the worker. + * + * If we release this bot as plugin for partners as opposed to it being just our + * internal bot, we can make these configurable. + */ const repository = "telegram--bot"; const owner = "ubq-testing"; const branch = "workflows"; + const { env: { APP_ID, APP_PRIVATE_KEY }, } = context; diff --git a/src/handlers/workflow-functions.ts b/src/handlers/workflow-functions.ts index 61edd34..fc12de7 100644 --- a/src/handlers/workflow-functions.ts +++ b/src/handlers/workflow-functions.ts @@ -25,20 +25,14 @@ import { repositoryDispatch } from "./repository-dispatch"; */ /** - * NOTICE: - * Please follow the comment pattern below to make it easier to track - * the logic of the workflow functions across the codebase. - */ - -/** - * The logic this function can be found in [../bot/mtproto-api/workrooms/create-chat.ts](../bot/mtproto-api/workrooms/create-chat.ts) + * The logic for this function can be found in [../bot/mtproto-api/workrooms/create-chat.ts](../bot/mtproto-api/workrooms/create-chat.ts) */ export async function createWorkroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { await repositoryDispatch(context, "create-telegram-chat").catch(console.error); return { status: 200, reason: "workflow_dispatched" }; } /** - * The logic this function can be found in [../bot/mtproto-api/workrooms/close-chat.ts](../bot/mtproto-api/workrooms/close-chat.ts) + * The logic for this function can be found in [../bot/mtproto-api/workrooms/close-chat.ts](../bot/mtproto-api/workrooms/close-chat.ts) */ export async function closeWorkroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { await repositoryDispatch(context, "close-telegram-chat").catch(console.error); @@ -46,7 +40,7 @@ export async function closeWorkroom(context: Context<"issues.closed", SupportedE } /** - * The logic this function can be found in [../bot/mtproto-api/workrooms/reopen-chat.ts](../bot/mtproto-api/workrooms/reopen-chat.ts) + * The logic for this function can be found in [../bot/mtproto-api/workrooms/reopen-chat.ts](../bot/mtproto-api/workrooms/reopen-chat.ts) */ export async function reOpenWorkroom(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { await repositoryDispatch(context, "reopen-telegram-chat").catch(console.error); diff --git a/src/handlers/workflow-proxy.ts b/src/handlers/workflow-proxy.ts index 3a7280e..8d0729e 100644 --- a/src/handlers/workflow-proxy.ts +++ b/src/handlers/workflow-proxy.ts @@ -13,8 +13,7 @@ import { handleCallback } from "./worker-proxy"; * * - First event fires, `issues.labeled` and the worker catches it. * - The worker then dispatches a workflow to `compute.yml` with the event name as the input. - * - The workflow receives a `issues.labeled` payload but eventName is now WorkflowFunction (`create-telegram-chat`). - * - The workflow then runs the `createChat` function which needs a node env to run. + * - The workflow receives a `issues.labeled` payload and runs the `createChat` function. * * I.e we're essentially running the first dual action/worker plugin which is * ideal for telegram-bot as it's a bot that needs to be able to be super flexible. diff --git a/src/types/typeguards.ts b/src/types/typeguards.ts index 3db2770..a5aabf2 100644 --- a/src/types/typeguards.ts +++ b/src/types/typeguards.ts @@ -7,13 +7,13 @@ export function isIssueOpenedEvent(context: Context): context is Context<"issues } export function isTelegramPayload(payload: unknown): payload is GrammyTelegramUpdate { - if(typeof payload !== "object" || !payload) return false; - return "update_id" in payload; + if (typeof payload !== "object" || !payload) return false; + return "update_id" in payload && payload.update_id !== undefined; } export function isGithubPayload(inputs: unknown): inputs is PluginInputs { - if(typeof inputs !== "object" || !inputs) return false; - return "eventName" in inputs; + if (typeof inputs !== "object" || !inputs) return false; + return "eventName" in inputs && inputs.eventName !== undefined; } export function isIssueLabeledEvent(context: Context): context is Context<"issues.labeled"> { From a99acb0b0ed39c65c2a0d6aba6ae8022dcf8f690 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 12 Sep 2024 23:50:18 +0100 Subject: [PATCH 42/76] refactor: env configuration --- src/bot/features/admin/admin.ts | 2 +- src/bot/mtproto-api/bot/mtproto.ts | 9 ++- .../bot/scripts/sms-auth/base-mtproto.ts | 11 +--- src/handlers/repository-dispatch.ts | 2 +- src/server/index.ts | 2 +- src/types/env.ts | 60 ++++++++++++++----- src/types/plugin-context-single.ts | 4 +- src/types/telegram-bot-single.ts | 7 ++- 8 files changed, 61 insertions(+), 36 deletions(-) diff --git a/src/bot/features/admin/admin.ts b/src/bot/features/admin/admin.ts index 884eff3..4d75c23 100644 --- a/src/bot/features/admin/admin.ts +++ b/src/bot/features/admin/admin.ts @@ -7,7 +7,7 @@ import { logHandle } from "#root/bot/helpers/logging.js"; const composer = new Composer(); -const feature = composer.chatType("private").filter((ctx) => isAdmin(ctx.config.BOT_ADMINS)(ctx)); +const feature = composer.chatType("private").filter((ctx) => isAdmin(ctx.config.telegramBotSettings.TELEGRAM_BOT_ADMINS)(ctx)); feature.command("setcommands", logHandle("command-setcommands"), chatAction("typing"), setCommandsHandler); diff --git a/src/bot/mtproto-api/bot/mtproto.ts b/src/bot/mtproto-api/bot/mtproto.ts index 063f8aa..660ba05 100644 --- a/src/bot/mtproto-api/bot/mtproto.ts +++ b/src/bot/mtproto-api/bot/mtproto.ts @@ -20,21 +20,20 @@ export class MtProto extends BaseMtProto { constructor(context: Context) { super(); - const key = context.env.SUPABASE_SERVICE_KEY; - const url = context.env.SUPABASE_URL; + const { SUPABASE_URL, SUPABASE_SERVICE_KEY } = context.env.storageSettings; - if (!key || !url) { + if (!SUPABASE_URL || !SUPABASE_SERVICE_KEY) { throw new Error("Missing required environment variables for Supabase"); } - this._supabase = createClient(url, key); + this._supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY); this._context = context; this._session = new SupabaseSession(this._supabase, this._context); } async initialize() { const session = await this._session.getSession(); - await super.initialize(this._context.env, session); + await super.initialize(this._context.env.telegramMtProtoSettings, session); } async saveSession() { diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts index 6771181..a28fd3e 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts @@ -3,14 +3,9 @@ import { Api } from "telegram/tl"; import { TelegramClientParams } from "telegram/client/telegramBaseClient"; import dotenv from "dotenv"; import { StringSession } from "telegram/sessions"; +import { Context } from "#root/types/context.js"; dotenv.config(); -type Env = { - TELEGRAM_API_HASH: string; - TELEGRAM_APP_ID: number; - BOT_TOKEN: string; -}; - /** * @dev Not abstract because we need it to be instantiated for sms-auth * @@ -23,7 +18,7 @@ export class BaseMtProto { _api: typeof Api = Api; _session: StringSession | null = null; - async initialize(env: Env, session: string) { + async initialize(env: Context["env"]["telegramMtProtoSettings"], session: string) { this._api = Api; this._session = new StringSession(session); this._client = await this._mtProtoInit(env, this._session); @@ -41,7 +36,7 @@ export class BaseMtProto { return this._session; } - private async _mtProtoInit(env: Env, session: StringSession) { + private async _mtProtoInit(env: Context["env"]["telegramMtProtoSettings"], session: StringSession) { const { TELEGRAM_API_HASH, TELEGRAM_APP_ID } = env; if (!TELEGRAM_API_HASH || !TELEGRAM_APP_ID) { diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts index fb47c3a..5671d27 100644 --- a/src/handlers/repository-dispatch.ts +++ b/src/handlers/repository-dispatch.ts @@ -24,7 +24,7 @@ export async function repositoryDispatch(context: Context, workflow: string) { const branch = "workflows"; const { - env: { APP_ID, APP_PRIVATE_KEY }, + env: { ubiquityOsSettings: { APP_ID, APP_PRIVATE_KEY } }, } = context; const app = new App({ appId: APP_ID, privateKey: APP_PRIVATE_KEY }); const installation = await app.octokit.rest.apps.getRepoInstallation({ owner, repo: repository }); diff --git a/src/server/index.ts b/src/server/index.ts index 30e89fb..d46c602 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -63,7 +63,7 @@ export function createServer(dependencies: Dependencies) { server.post( "/webhook", webhookCallback(bot, "hono", { - secretToken: config.BOT_WEBHOOK_SECRET, + secretToken: config.telegramBotSettings.TELEGRAM_BOT_WEBHOOK_SECRET, }) ); diff --git a/src/types/env.ts b/src/types/env.ts index 6a44ed8..eb7eb58 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -19,37 +19,33 @@ const allowedUpdates = T.Object({ message_reaction_count: T.String(), }); -export const env = T.Object({ + +const telegramBotSettings = T.Object({ /** - * The token for the bot given by the BotFather. - */ - BOT_TOKEN: T.String(), + * The token for the bot given by the BotFather. + */ + TELEGRAM_BOT_TOKEN: T.String(), /** * The url to forward updates to. */ - BOT_WEBHOOK: T.String(), + TELEGRAM_BOT_WEBHOOK: T.String(), /** * The secret to use when forwarding updates. */ - BOT_WEBHOOK_SECRET: T.String(), + TELEGRAM_BOT_WEBHOOK_SECRET: T.String(), /** * Ids of the users who are allowed to use admin commands. */ - BOT_ADMINS: T.Transform(T.Unknown()) + TELEGRAM_BOT_ADMINS: T.Transform(T.Unknown()) .Decode((str) => (Array.isArray(str) ? str.map(Number) : [Number(str)])) .Encode((arr) => arr.toString()), /** * Which updates the bot should receive, defaults to all. */ ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))), - /** - * The supabase instance url for storing chats, sessions, etc. - */ - SUPABASE_URL: T.String(), - /** - * The supabase service key for storing chats, sessions, etc. - */ - SUPABASE_SERVICE_KEY: T.String(), +}); + +const telegramMtProtoSettings = T.Object({ /** * Obtained from https://my.telegram.org/apps */ @@ -60,6 +56,9 @@ export const env = T.Object({ * Obtained from https://my.telegram.org/apps */ TELEGRAM_API_HASH: T.String(), +}); + +const ubiquityOsSettings = T.Object({ /** * Your UbiquityOS app id */ @@ -74,5 +73,36 @@ export const env = T.Object({ .Encode((str) => str), }); +const storageSettings = T.Object({ + /** + * The supabase instance url for storing chats, sessions, etc. + */ + SUPABASE_URL: T.String(), + /** + * The supabase service key for storing chats, sessions, etc. + */ + SUPABASE_SERVICE_KEY: T.String(), +}); + +export const env = T.Object({ + /** + * BotFather bot settings, worker instance. + */ + telegramBotSettings, + /** + * MtProto bot settings, user instance. + */ + telegramMtProtoSettings, + /** + * UbiquityOS settings. Kernel instance. + */ + ubiquityOsSettings, + /** + * Storage settings. Supbase instance. + * ###### TODO: Move to GitHub JSON based storage. + */ + storageSettings, +}); + export type Env = StaticDecode; export const envValidator = new StandardValidator(env); diff --git a/src/types/plugin-context-single.ts b/src/types/plugin-context-single.ts index e81788e..725dfbb 100644 --- a/src/types/plugin-context-single.ts +++ b/src/types/plugin-context-single.ts @@ -17,7 +17,7 @@ export class PluginContext { private constructor( public readonly inputs: PluginInputs, public _env: Env - ) {} + ) { } get env() { return Value.Decode(envValidator.schema, Value.Default(envValidator.schema, this._env)); @@ -54,7 +54,7 @@ export class PluginContext { adapters: {} as ReturnType, }; - ctx.adapters = createAdapters(createClient(ctx.env.SUPABASE_URL, ctx.env.SUPABASE_SERVICE_KEY), ctx); + ctx.adapters = createAdapters(createClient(ctx.env.storageSettings.SUPABASE_URL, ctx.env.storageSettings.SUPABASE_SERVICE_KEY), ctx); return ctx; } diff --git a/src/types/telegram-bot-single.ts b/src/types/telegram-bot-single.ts index b1dac0d..4733862 100644 --- a/src/types/telegram-bot-single.ts +++ b/src/types/telegram-bot-single.ts @@ -15,15 +15,16 @@ export class TelegramBotSingleton { private static _server: ReturnType; static async initialize(env: Env): Promise { + const { telegramBotSettings: { TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_WEBHOOK, ALLOWED_UPDATES } } = env if (!TelegramBotSingleton._instance) { TelegramBotSingleton._instance = new TelegramBotSingleton(); - TelegramBotSingleton._bot = createBot(env.BOT_TOKEN, { + TelegramBotSingleton._bot = createBot(TELEGRAM_BOT_TOKEN, { config: Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)), logger, }); - await TelegramBotSingleton._bot.api.setWebhook(env.BOT_WEBHOOK, { - allowed_updates: env.ALLOWED_UPDATES, + await TelegramBotSingleton._bot.api.setWebhook(TELEGRAM_BOT_WEBHOOK, { + allowed_updates: ALLOWED_UPDATES, drop_pending_updates: true, }); From 10928688d472bba110a7cbfcfea66dc1e46e57d2 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 17:28:10 +0100 Subject: [PATCH 43/76] chore: update storage adapters --- src/adapters/index.ts | 7 ++--- src/adapters/supabase/helpers/chats.ts | 36 +++++++++++------------ src/adapters/supabase/helpers/supabase.ts | 7 ++--- src/adapters/supabase/helpers/user.ts | 26 ++++++++++++---- 4 files changed, 44 insertions(+), 32 deletions(-) diff --git a/src/adapters/index.ts b/src/adapters/index.ts index 424f9be..4bbc4ea 100644 --- a/src/adapters/index.ts +++ b/src/adapters/index.ts @@ -1,13 +1,12 @@ import { SupabaseClient } from "@supabase/supabase-js"; -import { Context } from "../types/context"; import { User } from "./supabase/helpers/user"; import { Chats } from "./supabase/helpers/chats"; -export function createAdapters(supabaseClient: SupabaseClient, context: Context) { +export function createAdapters(supabaseClient: SupabaseClient) { return { supabase: { - user: new User(supabaseClient, context), - chats: new Chats(supabaseClient, context), + user: new User(supabaseClient), + chats: new Chats(supabaseClient), }, }; } diff --git a/src/adapters/supabase/helpers/chats.ts b/src/adapters/supabase/helpers/chats.ts index 39546fe..68462d6 100644 --- a/src/adapters/supabase/helpers/chats.ts +++ b/src/adapters/supabase/helpers/chats.ts @@ -13,8 +13,8 @@ export type Chat = { * Handles all telegram chat storage and retrieval */ export class Chats extends Super { - constructor(supabase: SupabaseClient, context: Context) { - super(supabase, context); + constructor(supabase: SupabaseClient) { + super(supabase); } /** @@ -25,9 +25,9 @@ export class Chats extends Super { const chat = await this.getChatByChatId(chatId); const { error } = await this.supabase.from("chats").upsert({ ...chat, user_ids: userIds }); if (error) { - this.context.logger.error("Failed to save chat users", { chatId, userIds, er: error }); + this.logger.error("Failed to save chat users", { chatId, userIds, er: error }); } else { - this.context.logger.info("Successfully saved chat users", { chatId, userIds }); + this.logger.info("Successfully saved chat users", { chatId, userIds }); } } @@ -37,9 +37,9 @@ export class Chats extends Super { async getChatUsers(chatId: number) { const { data, error } = await this.supabase.from("chats").select("user_ids").eq("chat_id", chatId).single(); if (error || !data) { - this.context.logger.error("No chat users found", { chatId }); + this.logger.error("No chat users found", { chatId }); } else { - this.context.logger.info("Successfully fetched chat users", { chatId }); + this.logger.info("Successfully fetched chat users", { chatId }); } return data; @@ -47,7 +47,7 @@ export class Chats extends Super { async updateChatStatus(status: "open" | "closed" | "reopened", taskNodeId?: string, chatId?: number) { if (!taskNodeId && !chatId) { - this.context.logger.error("No taskNodeId or chatId provided to update chat status"); + this.logger.error("No taskNodeId or chatId provided to update chat status"); return; } @@ -60,34 +60,34 @@ export class Chats extends Super { } if (!chat) { - this.context.logger.error("No chat found to update chat status"); + this.logger.error("No chat found to update chat status"); return; } const { error } = await this.supabase.from("chats").upsert({ ...chat, status }); if (error) { - this.context.logger.error("Failed to update chat status", { chatId, taskNodeId, er: error }); + this.logger.error("Failed to update chat status", { chatId, taskNodeId, er: error }); } else { - this.context.logger.info("Successfully updated chat status", { chatId, taskNodeId }); + this.logger.info("Successfully updated chat status", { chatId, taskNodeId }); } } async saveChat(chatId: number, chatName: string, taskNodeId: string) { const { error } = await this.supabase.from("chats").insert([{ chat_id: chatId, chat_name: chatName, task_node_id: taskNodeId, status: "open" }]); if (error) { - this.context.logger.error("Failed to save chat", { chatId, chatName, taskNodeId, er: error }); + this.logger.error("Failed to save chat", { chatId, chatName, taskNodeId, er: error }); } else { - this.context.logger.info("Successfully saved chat", { chatId, chatName }); + this.logger.info("Successfully saved chat", { chatId, chatName }); } } async getChatByChatId(chatId: number) { const { data, error } = await this.supabase.from("chats").select("*").eq("chat_id", chatId).single(); if (error || !data) { - this.context.logger.error("No chat found", { chatId }); + this.logger.error("No chat found", { chatId }); } else { - this.context.logger.info("Successfully fetched chat", { chatId }); + this.logger.info("Successfully fetched chat", { chatId }); } return data; @@ -96,9 +96,9 @@ export class Chats extends Super { async getChatByChatName(chatName: string) { const { data, error } = await this.supabase.from("chats").select("*").eq("chat_name", chatName).single(); if (error || !data) { - this.context.logger.error("No chat found", { chatName }); + this.logger.error("No chat found", { chatName }); } else { - this.context.logger.info("Successfully fetched chat", { chatName }); + this.logger.info("Successfully fetched chat", { chatName }); } return data; @@ -108,9 +108,9 @@ export class Chats extends Super { try { const { data, error } = await this.supabase.from("chats").select("*").eq("task_node_id", taskNodeId).single(); if (error || !data) { - this.context.logger.error("No chat found", { taskNodeId }); + this.logger.error("No chat found", { taskNodeId }); } else { - this.context.logger.info("Successfully fetched chat", { taskNodeId }); + this.logger.info("Successfully fetched chat", { taskNodeId }); } return data; diff --git a/src/adapters/supabase/helpers/supabase.ts b/src/adapters/supabase/helpers/supabase.ts index 7a13b85..704511a 100644 --- a/src/adapters/supabase/helpers/supabase.ts +++ b/src/adapters/supabase/helpers/supabase.ts @@ -1,12 +1,11 @@ import { SupabaseClient } from "@supabase/supabase-js"; -import { Context } from "../../../types/context"; +import { logger } from "#root/utils/logger.js"; export class Super { protected supabase: SupabaseClient; - protected context: Context; + protected logger = logger; - constructor(supabase: SupabaseClient, context: Context) { + constructor(supabase: SupabaseClient) { this.supabase = supabase; - this.context = context; } } diff --git a/src/adapters/supabase/helpers/user.ts b/src/adapters/supabase/helpers/user.ts index 8f18cd4..d356aaf 100644 --- a/src/adapters/supabase/helpers/user.ts +++ b/src/adapters/supabase/helpers/user.ts @@ -1,22 +1,36 @@ import { SupabaseClient } from "@supabase/supabase-js"; import { Super } from "./supabase"; -import { Context } from "../../../types/context"; +import { PluginContext } from "#root/types/plugin-context-single.js"; type Wallet = { address: string; }; export class User extends Super { - constructor(supabase: SupabaseClient, context: Context) { - super(supabase, context); + constructor(supabase: SupabaseClient) { + super(supabase); } - async getWalletByUserId(userId: number, issueNumber: number) { + async getWalletByUserId(userId: number) { const { data, error } = (await this.supabase.from("users").select("wallets(*)").eq("id", userId).single()) as { data: { wallets: Wallet }; error: unknown }; if ((error && !data) || !data.wallets?.address) { - this.context.logger.error("No wallet address found", { userId, issueNumber }); + this.logger.error("No wallet address found", { userId }); } else { - this.context.logger.info("Successfully fetched wallet", { userId, address: data.wallets?.address }); + this.logger.info("Successfully fetched wallet", { userId, address: data.wallets?.address }); + } + + return data?.wallets?.address || null; + } + + async getWalletByGitHubUsername(username: string) { + const ctx = PluginContext.getInstance().getContext(); + const { octokit } = ctx + const githubUserID = (await octokit.rest.users.getByUsername({ username })).data.id; + const { data, error } = (await this.supabase.from("users").select("wallets(*)").eq("id", githubUserID).single()) as { data: { wallets: Wallet }; error: unknown }; + if ((error && !data) || !data.wallets?.address) { + this.logger.error("No wallet address found", { githubUserID }); + } else { + this.logger.info("Successfully fetched wallet", { githubUserID, address: data.wallets?.address }); } return data?.wallets?.address || null; From 0ebd2c4835970f03d4a7c37ee4a2e2faeff5c90d Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 17:29:04 +0100 Subject: [PATCH 44/76] chore: organize commands --- src/bot/features/commands/groups/ban.ts | 25 +++++++++++++++++ .../commands/{ => private-chat}/bot-id.ts | 0 .../commands/{ => private-chat}/user-id.ts | 0 .../features/commands/{ => shared}/chat-id.ts | 2 +- src/bot/features/commands/shared/wallet.ts | 28 +++++++++++++++++++ 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/bot/features/commands/groups/ban.ts rename src/bot/features/commands/{ => private-chat}/bot-id.ts (100%) rename src/bot/features/commands/{ => private-chat}/user-id.ts (100%) rename src/bot/features/commands/{ => shared}/chat-id.ts (88%) create mode 100644 src/bot/features/commands/shared/wallet.ts diff --git a/src/bot/features/commands/groups/ban.ts b/src/bot/features/commands/groups/ban.ts new file mode 100644 index 0000000..5a38ebd --- /dev/null +++ b/src/bot/features/commands/groups/ban.ts @@ -0,0 +1,25 @@ +import { chatAction } from "@grammyjs/auto-chat-action"; +import { Composer } from "grammy"; +import type { Context } from "#root/bot/helpers/grammy-context.js"; +import { logHandle } from "#root/bot/helpers/logging.js"; + +const composer = new Composer(); + +const feature = composer.chatType("group"); + +feature.command("ban", logHandle("command-ban"), chatAction("typing"), async (ctx) => { + const { message } = ctx; + if (!message.reply_to_message) { + return ctx.reply("You must reply to a user's message to kick them."); + } + const target = message.reply_to_message.from; + if (!target) { + return ctx.reply("I can't find the user you want to kick."); + } + if (target.id === ctx.me.id) { + return ctx.reply("I can't kick myself."); + } + await ctx.banChatMember(target.id); +}); + +export { composer as banCommand }; diff --git a/src/bot/features/commands/bot-id.ts b/src/bot/features/commands/private-chat/bot-id.ts similarity index 100% rename from src/bot/features/commands/bot-id.ts rename to src/bot/features/commands/private-chat/bot-id.ts diff --git a/src/bot/features/commands/user-id.ts b/src/bot/features/commands/private-chat/user-id.ts similarity index 100% rename from src/bot/features/commands/user-id.ts rename to src/bot/features/commands/private-chat/user-id.ts diff --git a/src/bot/features/commands/chat-id.ts b/src/bot/features/commands/shared/chat-id.ts similarity index 88% rename from src/bot/features/commands/chat-id.ts rename to src/bot/features/commands/shared/chat-id.ts index 87f4e5e..c648559 100644 --- a/src/bot/features/commands/chat-id.ts +++ b/src/bot/features/commands/shared/chat-id.ts @@ -5,7 +5,7 @@ import { logHandle } from "#root/bot/helpers/logging.js"; const composer = new Composer(); -const feature = composer.chatType("group"); +const feature = composer.chatType(["group", "private"]); feature.command("chatid", logHandle("command-chatid"), chatAction("typing"), async (ctx) => { return ctx.reply(`This chat ID is ${ctx.chat.id}`); diff --git a/src/bot/features/commands/shared/wallet.ts b/src/bot/features/commands/shared/wallet.ts new file mode 100644 index 0000000..a537f16 --- /dev/null +++ b/src/bot/features/commands/shared/wallet.ts @@ -0,0 +1,28 @@ +import { chatAction } from "@grammyjs/auto-chat-action"; +import { Composer } from "grammy"; +import type { Context } from "#root/bot/helpers/grammy-context.js"; +import { logHandle } from "#root/bot/helpers/logging.js"; + +const composer = new Composer(); + +const feature = composer.chatType(["group", "private"]); + +feature.command("/wallet", logHandle("command-wallet"), chatAction("typing"), async (ctx) => { + const { message } = ctx; + + // username is after the command + const username = message.text.split(" ")[1]; + if (!username) { + return ctx.reply("You must provide a GitHub username."); + } + + // get wallet by username + const wallet = await ctx.adapters.supabase.user.getWalletByGitHubUsername(username); + if (!wallet) { + return ctx.reply("I can't find a wallet for that GitHub username."); + } + + return ctx.reply(`The wallet for ${username} is ${wallet}`); +}); + +export { composer as userIdFeature }; From c564bca8bda6b05a2438c704997efabad4d9c4d0 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 18:09:06 +0100 Subject: [PATCH 45/76] chore: refactor env schema, replace all console with Logs --- src/adapters/supabase/helpers/chats.ts | 20 ++---- src/adapters/supabase/helpers/user.ts | 13 ++-- src/bot/features/admin/admin.ts | 2 +- src/bot/features/commands/groups/ban.ts | 24 +++---- src/bot/features/commands/shared/wallet.ts | 24 +++---- src/bot/helpers/grammy-context.ts | 6 ++ src/bot/index.ts | 10 ++- src/bot/mtproto-api/bot/mtproto.ts | 4 +- .../bot/scripts/sms-auth/auth-handler.ts | 64 +++++++++++++------ .../bot/scripts/sms-auth/base-mtproto.ts | 4 +- .../bot/scripts/sms-auth/sms-auth.ts | 3 +- src/bot/mtproto-api/workrooms/reopen-chat.ts | 4 +- src/handlers/github-webhook.ts | 11 ++-- src/handlers/repository-dispatch.ts | 8 ++- src/handlers/telegram-webhook.ts | 3 +- src/handlers/workflow-functions.ts | 7 +- src/server/index.ts | 3 +- src/types/env.ts | 48 +++++++------- src/types/plugin-context-single.ts | 6 +- src/types/telegram-bot-single.ts | 14 ++-- src/utils/add-comment-to-issues.ts | 4 +- src/utils/errors.ts | 8 +-- src/worker.ts | 10 ++- src/workflow-entry.ts | 11 ++-- 24 files changed, 178 insertions(+), 133 deletions(-) diff --git a/src/adapters/supabase/helpers/chats.ts b/src/adapters/supabase/helpers/chats.ts index 68462d6..36e39f0 100644 --- a/src/adapters/supabase/helpers/chats.ts +++ b/src/adapters/supabase/helpers/chats.ts @@ -1,6 +1,5 @@ import { SupabaseClient } from "@supabase/supabase-js"; import { Super } from "./supabase"; -import { Context } from "../../../types/context"; export type Chat = { chatId: number; @@ -105,18 +104,13 @@ export class Chats extends Super { } async getChatByTaskNodeId(taskNodeId: string) { - try { - const { data, error } = await this.supabase.from("chats").select("*").eq("task_node_id", taskNodeId).single(); - if (error || !data) { - this.logger.error("No chat found", { taskNodeId }); - } else { - this.logger.info("Successfully fetched chat", { taskNodeId }); - } - - return data; - } catch (e) { - console.error(e); - throw new Error("Failed to fetch chat by task node id"); + const { data, error } = await this.supabase.from("chats").select("*").eq("task_node_id", taskNodeId).single(); + if (error || !data) { + this.logger.error("No chat found", { taskNodeId }); + } else { + this.logger.info("Successfully fetched chat", { taskNodeId }); } + + return data; } } diff --git a/src/adapters/supabase/helpers/user.ts b/src/adapters/supabase/helpers/user.ts index d356aaf..16574c1 100644 --- a/src/adapters/supabase/helpers/user.ts +++ b/src/adapters/supabase/helpers/user.ts @@ -24,13 +24,16 @@ export class User extends Super { async getWalletByGitHubUsername(username: string) { const ctx = PluginContext.getInstance().getContext(); - const { octokit } = ctx - const githubUserID = (await octokit.rest.users.getByUsername({ username })).data.id; - const { data, error } = (await this.supabase.from("users").select("wallets(*)").eq("id", githubUserID).single()) as { data: { wallets: Wallet }; error: unknown }; + const { octokit } = ctx; + const githubUserId = (await octokit.rest.users.getByUsername({ username })).data.id; + const { data, error } = (await this.supabase.from("users").select("wallets(*)").eq("id", githubUserId).single()) as { + data: { wallets: Wallet }; + error: unknown; + }; if ((error && !data) || !data.wallets?.address) { - this.logger.error("No wallet address found", { githubUserID }); + this.logger.error("No wallet address found", { githubUserId }); } else { - this.logger.info("Successfully fetched wallet", { githubUserID, address: data.wallets?.address }); + this.logger.info("Successfully fetched wallet", { githubUserId, address: data.wallets?.address }); } return data?.wallets?.address || null; diff --git a/src/bot/features/admin/admin.ts b/src/bot/features/admin/admin.ts index 4d75c23..6612ad5 100644 --- a/src/bot/features/admin/admin.ts +++ b/src/bot/features/admin/admin.ts @@ -7,7 +7,7 @@ import { logHandle } from "#root/bot/helpers/logging.js"; const composer = new Composer(); -const feature = composer.chatType("private").filter((ctx) => isAdmin(ctx.config.telegramBotSettings.TELEGRAM_BOT_ADMINS)(ctx)); +const feature = composer.chatType("private").filter((ctx) => isAdmin(ctx.config.telegramBotEnv.botSettings.TELEGRAM_BOT_ADMINS)(ctx)); feature.command("setcommands", logHandle("command-setcommands"), chatAction("typing"), setCommandsHandler); diff --git a/src/bot/features/commands/groups/ban.ts b/src/bot/features/commands/groups/ban.ts index 5a38ebd..94dc20d 100644 --- a/src/bot/features/commands/groups/ban.ts +++ b/src/bot/features/commands/groups/ban.ts @@ -8,18 +8,18 @@ const composer = new Composer(); const feature = composer.chatType("group"); feature.command("ban", logHandle("command-ban"), chatAction("typing"), async (ctx) => { - const { message } = ctx; - if (!message.reply_to_message) { - return ctx.reply("You must reply to a user's message to kick them."); - } - const target = message.reply_to_message.from; - if (!target) { - return ctx.reply("I can't find the user you want to kick."); - } - if (target.id === ctx.me.id) { - return ctx.reply("I can't kick myself."); - } - await ctx.banChatMember(target.id); + const { message } = ctx; + if (!message.reply_to_message) { + return ctx.reply("You must reply to a user's message to kick them."); + } + const target = message.reply_to_message.from; + if (!target) { + return ctx.reply("I can't find the user you want to kick."); + } + if (target.id === ctx.me.id) { + return ctx.reply("I can't kick myself."); + } + await ctx.banChatMember(target.id); }); export { composer as banCommand }; diff --git a/src/bot/features/commands/shared/wallet.ts b/src/bot/features/commands/shared/wallet.ts index a537f16..67fe5ba 100644 --- a/src/bot/features/commands/shared/wallet.ts +++ b/src/bot/features/commands/shared/wallet.ts @@ -8,21 +8,21 @@ const composer = new Composer(); const feature = composer.chatType(["group", "private"]); feature.command("/wallet", logHandle("command-wallet"), chatAction("typing"), async (ctx) => { - const { message } = ctx; + const { message } = ctx; - // username is after the command - const username = message.text.split(" ")[1]; - if (!username) { - return ctx.reply("You must provide a GitHub username."); - } + // username is after the command + const username = message.text.split(" ")[1]; + if (!username) { + return ctx.reply("You must provide a GitHub username."); + } - // get wallet by username - const wallet = await ctx.adapters.supabase.user.getWalletByGitHubUsername(username); - if (!wallet) { - return ctx.reply("I can't find a wallet for that GitHub username."); - } + // get wallet by username + const wallet = await ctx.adapters.supabase.user.getWalletByGitHubUsername(username); + if (!wallet) { + return ctx.reply("I can't find a wallet for that GitHub username."); + } - return ctx.reply(`The wallet for ${username} is ${wallet}`); + return ctx.reply(`The wallet for ${username} is ${wallet}`); }); export { composer as userIdFeature }; diff --git a/src/bot/helpers/grammy-context.ts b/src/bot/helpers/grammy-context.ts index a5bcd1a..4fa778c 100644 --- a/src/bot/helpers/grammy-context.ts +++ b/src/bot/helpers/grammy-context.ts @@ -5,6 +5,8 @@ import type { HydrateFlavor } from "@grammyjs/hydrate"; import type { ParseModeFlavor } from "@grammyjs/parse-mode"; import type { Logger } from "#root/utils/logger.js"; import { Context as UbiquityOsContext } from "../../types"; +import { createAdapters } from "#root/adapters/index.js"; +import { createClient } from "@supabase/supabase-js"; export type GrammyTelegramUpdate = Update; @@ -15,6 +17,7 @@ export interface SessionData { interface ExtendedContextFlavor { logger: Logger; config: UbiquityOsContext["env"]; + adapters: ReturnType; } export type Context = ParseModeFlavor & AutoChatActionFlavor>>; @@ -28,12 +31,15 @@ export function createContextConstructor({ logger, config }: Dependencies) { return class extends DefaultContext implements ExtendedContextFlavor { logger: Logger; config: UbiquityOsContext["env"]; + adapters: ReturnType; constructor(update: GrammyTelegramUpdate, api: Api, me: UserFromGetMe) { super(update, api, me); this.logger = logger; this.config = config; + const { SUPABASE_URL, SUPABASE_SERVICE_KEY } = config.telegramBotEnv.storageSettings; + this.adapters = createAdapters(createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY)); } } as unknown as new (update: GrammyTelegramUpdate, api: Api, me: UserFromGetMe) => Context; } diff --git a/src/bot/index.ts b/src/bot/index.ts index 3db3ed7..84e8635 100644 --- a/src/bot/index.ts +++ b/src/bot/index.ts @@ -12,9 +12,10 @@ import { autoChatAction } from "@grammyjs/auto-chat-action"; import { hydrate } from "@grammyjs/hydrate"; import { hydrateReply, parseMode } from "@grammyjs/parse-mode"; import { adminFeature } from "./features/admin/admin"; -import { userIdFeature } from "./features/commands/user-id"; -import { chatIdFeature } from "./features/commands/chat-id"; -import { botIdFeature } from "./features/commands/bot-id"; +import { userIdFeature } from "./features/commands/private-chat/user-id"; +import { chatIdFeature } from "./features/commands/shared/chat-id"; +import { botIdFeature } from "./features/commands/private-chat/bot-id"; +import { banCommand } from "./features/commands/groups/ban"; interface Dependencies { config: UbiquityOsContext["env"]; @@ -61,6 +62,9 @@ export function createBot(token: string, dependencies: Dependencies, options: Op protectedBot.use(chatIdFeature); protectedBot.use(botIdFeature); + // group commands + protectedBot.use(banCommand); + // unhandled command handler protectedBot.use(unhandledFeature); diff --git a/src/bot/mtproto-api/bot/mtproto.ts b/src/bot/mtproto-api/bot/mtproto.ts index 660ba05..2310f03 100644 --- a/src/bot/mtproto-api/bot/mtproto.ts +++ b/src/bot/mtproto-api/bot/mtproto.ts @@ -20,7 +20,7 @@ export class MtProto extends BaseMtProto { constructor(context: Context) { super(); - const { SUPABASE_URL, SUPABASE_SERVICE_KEY } = context.env.storageSettings; + const { SUPABASE_URL, SUPABASE_SERVICE_KEY } = context.env.telegramBotEnv.storageSettings; if (!SUPABASE_URL || !SUPABASE_SERVICE_KEY) { throw new Error("Missing required environment variables for Supabase"); @@ -33,7 +33,7 @@ export class MtProto extends BaseMtProto { async initialize() { const session = await this._session.getSession(); - await super.initialize(this._context.env.telegramMtProtoSettings, session); + await super.initialize(this._context.env.telegramBotEnv.mtProtoSettings, session); } async saveSession() { diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts index 21ae752..05e48a7 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts @@ -3,6 +3,8 @@ import input from "input"; import dotenv from "dotenv"; import { createClient, SupabaseClient } from "@supabase/supabase-js"; import { BaseMtProto } from "./base-mtproto"; +import { Context } from "#root/types/context.js"; +import { logger } from "#root/utils/logger.js"; dotenv.config(); /** @@ -14,29 +16,53 @@ export class AuthHandler { private _env = { TELEGRAM_API_HASH: "", TELEGRAM_APP_ID: 0, - BOT_TOKEN: "", + TELEGRAM_BOT_TOKEN: "", }; constructor() { - const key = process.env.SUPABASE_SERVICE_KEY; - const url = process.env.SUPABASE_URL; - if (!key || !url) { - throw new Error("Missing required environment variables for Supabase"); + const env = process.env.telegramBotEnv; + if (!env) { + throw new Error("Missing required environment variables for Telegram Bot"); } - this._supabase = createClient(url, key); - const hash = process.env.TELEGRAM_API_HASH; - const tgAppId = process.env.TELEGRAM_APP_ID; - const botToken = process.env.BOT_TOKEN; + const parsedEnv: Context["env"]["telegramBotEnv"] = JSON.parse(env); + if (!parsedEnv) { + throw new Error("Failed to parse environment variables for Telegram Bot"); + } + + const { botSettings, mtProtoSettings, ubiquityOsSettings, storageSettings } = parsedEnv; + + if (!botSettings || !mtProtoSettings || !ubiquityOsSettings || !storageSettings) { + throw new Error("Missing required environment variables for Telegram Bot settings"); + } + + const { TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_WEBHOOK } = botSettings; + const { TELEGRAM_APP_ID, TELEGRAM_API_HASH } = mtProtoSettings; + const { SUPABASE_URL, SUPABASE_SERVICE_KEY } = storageSettings; + const { APP_ID, APP_PRIVATE_KEY } = ubiquityOsSettings; + + if (!TELEGRAM_BOT_TOKEN || !TELEGRAM_BOT_WEBHOOK) { + throw new Error("Missing required environment variables for Telegram Bot settings"); + } + + if (!TELEGRAM_APP_ID || !TELEGRAM_API_HASH) { + throw new Error("Missing required environment variables for MtProto settings"); + } - if (!hash || !tgAppId || !botToken) { - throw new Error("Missing required environment variables for Telegram API"); + if (!APP_ID || !APP_PRIVATE_KEY) { + throw new Error("Missing required environment variables for UbiquityOS settings"); } + if (!SUPABASE_URL || !SUPABASE_SERVICE_KEY) { + throw new Error("Missing required environment variables for storage settings"); + } + + this._supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY); + this._env = { - TELEGRAM_API_HASH: hash, - TELEGRAM_APP_ID: Number(tgAppId), - BOT_TOKEN: botToken, + TELEGRAM_API_HASH, + TELEGRAM_APP_ID, + TELEGRAM_BOT_TOKEN, }; } @@ -60,9 +86,9 @@ export class AuthHandler { try { await mtProto.client?.start({ phoneNumber: async () => await input.text("Enter your phone number:"), - password: async () => await input.text("Enter your password if required:"), + password: async () => await input.password("Enter your password if required:"), phoneCode: async () => await input.text("Enter the code you received:"), - onError: (err: unknown) => console.error("Error during login:", err), + onError: (err: unknown) => logger.error("Error during login:", { err }), }); const data = await this._supabase?.from("tg-bot-sessions").insert([{ session_data: mtProto.session?.save() }]); @@ -71,10 +97,10 @@ export class AuthHandler { throw new Error("Failed to save session data to Supabase."); } - console.log("Successfully logged in and saved session data. You can now run the bot."); + logger.ok("Successfully logged in and saved session data. You can now run the bot."); process.exit(0); - } catch (error) { - console.error("Failed to log in:", error); + } catch (err) { + logger.error("Failed to log in:", { err }); } } } diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts index a28fd3e..d665d57 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts @@ -18,7 +18,7 @@ export class BaseMtProto { _api: typeof Api = Api; _session: StringSession | null = null; - async initialize(env: Context["env"]["telegramMtProtoSettings"], session: string) { + async initialize(env: Context["env"]["telegramBotEnv"]["mtProtoSettings"], session: string) { this._api = Api; this._session = new StringSession(session); this._client = await this._mtProtoInit(env, this._session); @@ -36,7 +36,7 @@ export class BaseMtProto { return this._session; } - private async _mtProtoInit(env: Context["env"]["telegramMtProtoSettings"], session: StringSession) { + private async _mtProtoInit(env: Context["env"]["telegramBotEnv"]["mtProtoSettings"], session: StringSession) { const { TELEGRAM_API_HASH, TELEGRAM_APP_ID } = env; if (!TELEGRAM_API_HASH || !TELEGRAM_APP_ID) { diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts index 67ea7a8..d2a4e25 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts @@ -1,3 +1,4 @@ +import { logger } from "#root/utils/logger.js"; import { AuthHandler } from "./auth-handler"; import dotenv from "dotenv"; dotenv.config(); @@ -10,4 +11,4 @@ async function main() { await authHandler.smsLogin(); } -main().catch(console.error); +main().catch(logger.error); diff --git a/src/bot/mtproto-api/workrooms/reopen-chat.ts b/src/bot/mtproto-api/workrooms/reopen-chat.ts index fa92f6f..98c159c 100644 --- a/src/bot/mtproto-api/workrooms/reopen-chat.ts +++ b/src/bot/mtproto-api/workrooms/reopen-chat.ts @@ -70,8 +70,8 @@ export async function reopenChat(context: Context<"issues.reopened", SupportedEv /** * Dialogs are all of the chats, channels, and users that the account has interacted with. * By obtaining the dialogs, we guarantee our client (that's what we are considered to be by the MTProto API) - * has up to date context otherwise these operations seem to fail. - * + * has up to date context otherwise these operations seem to fail. + * * There is likely a better way to handle this, but this works for now. */ await mtProto.client.getDialogs(); diff --git a/src/handlers/github-webhook.ts b/src/handlers/github-webhook.ts index 1fac904..cf7a94d 100644 --- a/src/handlers/github-webhook.ts +++ b/src/handlers/github-webhook.ts @@ -1,6 +1,7 @@ import { Value } from "@sinclair/typebox/value"; import { plugin } from "../plugin"; import { pluginSettingsSchema, pluginSettingsValidator, PluginInputs, Env } from "../types"; +import { logger } from "#root/utils/logger.js"; export async function handleGithubWebhook(request: Request, env: Env): Promise { try { @@ -9,9 +10,9 @@ export async function handleGithubWebhook(request: Request, env: Env): Promise { const isOk = envValidator.test(env); if (!isOk) { const errors = Array.from(envValidator.errors(env)); - console.error(`Invalid bot env: `, errors); + logger.error(`Invalid bot env: `, { errors }); } const settings = Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)); diff --git a/src/handlers/workflow-functions.ts b/src/handlers/workflow-functions.ts index fc12de7..29560f9 100644 --- a/src/handlers/workflow-functions.ts +++ b/src/handlers/workflow-functions.ts @@ -1,4 +1,5 @@ import { CallbackResult } from "#root/types/proxy.js"; +import { logger } from "#root/utils/logger.js"; import { Context, SupportedEvents } from "../types"; import { repositoryDispatch } from "./repository-dispatch"; @@ -28,14 +29,14 @@ import { repositoryDispatch } from "./repository-dispatch"; * The logic for this function can be found in [../bot/mtproto-api/workrooms/create-chat.ts](../bot/mtproto-api/workrooms/create-chat.ts) */ export async function createWorkroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { - await repositoryDispatch(context, "create-telegram-chat").catch(console.error); + await repositoryDispatch(context, "create-telegram-chat").catch(logger.error); return { status: 200, reason: "workflow_dispatched" }; } /** * The logic for this function can be found in [../bot/mtproto-api/workrooms/close-chat.ts](../bot/mtproto-api/workrooms/close-chat.ts) */ export async function closeWorkroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { - await repositoryDispatch(context, "close-telegram-chat").catch(console.error); + await repositoryDispatch(context, "close-telegram-chat").catch(logger.error); return { status: 200, reason: "workflow_dispatched" }; } @@ -43,6 +44,6 @@ export async function closeWorkroom(context: Context<"issues.closed", SupportedE * The logic for this function can be found in [../bot/mtproto-api/workrooms/reopen-chat.ts](../bot/mtproto-api/workrooms/reopen-chat.ts) */ export async function reOpenWorkroom(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { - await repositoryDispatch(context, "reopen-telegram-chat").catch(console.error); + await repositoryDispatch(context, "reopen-telegram-chat").catch(logger.error); return { status: 200, reason: "workflow_dispatched" }; } diff --git a/src/server/index.ts b/src/server/index.ts index d46c602..93325dd 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -32,7 +32,6 @@ export function createServer(dependencies: Dependencies) { server.use(requestLogger()); server.onError(async (error, c) => { - console.error(c); if (error instanceof HTTPException) { if (error.status < 500) c.var.logger.info("Request info failed", { @@ -63,7 +62,7 @@ export function createServer(dependencies: Dependencies) { server.post( "/webhook", webhookCallback(bot, "hono", { - secretToken: config.telegramBotSettings.TELEGRAM_BOT_WEBHOOK_SECRET, + secretToken: config.telegramBotEnv.botSettings.TELEGRAM_BOT_WEBHOOK_SECRET, }) ); diff --git a/src/types/env.ts b/src/types/env.ts index eb7eb58..ce47ec7 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -19,11 +19,10 @@ const allowedUpdates = T.Object({ message_reaction_count: T.String(), }); - -const telegramBotSettings = T.Object({ +const botSettings = T.Object({ /** - * The token for the bot given by the BotFather. - */ + * The token for the bot given by the BotFather. + */ TELEGRAM_BOT_TOKEN: T.String(), /** * The url to forward updates to. @@ -42,14 +41,14 @@ const telegramBotSettings = T.Object({ /** * Which updates the bot should receive, defaults to all. */ - ALLOWED_UPDATES: T.Optional(T.Array(T.KeyOf(allowedUpdates))), + ALLOWED_UPDATES: T.Optional(T.Array(T.Enum(allowedUpdates))), }); -const telegramMtProtoSettings = T.Object({ +const mtProtoSettings = T.Object({ /** * Obtained from https://my.telegram.org/apps */ - TELEGRAM_APP_ID: T.Transform(T.Unknown()) + TELEGRAM_APP_ID: T.Transform(T.Union([T.String(), T.Number()])) .Decode((str) => Number(str)) .Encode((num) => num.toString()), /** @@ -84,25 +83,28 @@ const storageSettings = T.Object({ SUPABASE_SERVICE_KEY: T.String(), }); -export const env = T.Object({ - /** - * BotFather bot settings, worker instance. - */ - telegramBotSettings, - /** - * MtProto bot settings, user instance. - */ - telegramMtProtoSettings, - /** - * UbiquityOS settings. Kernel instance. - */ +const telegramBotEnv = T.Object({ + botSettings, + mtProtoSettings, ubiquityOsSettings, - /** - * Storage settings. Supbase instance. - * ###### TODO: Move to GitHub JSON based storage. - */ storageSettings, }); +export const env = T.Object({ + telegramBotEnv: T.Transform(T.Union([T.String(), telegramBotEnv])) + .Decode((str) => { + if (typeof str === "string") { + const obj = JSON.parse(str) as StaticDecode; + + if (!obj.botSettings || !obj.mtProtoSettings || !obj.ubiquityOsSettings || !obj.storageSettings) { + throw new Error("Missing required environment variables for Telegram Bot settings"); + } + return obj; + } + return str; + }) + .Encode((obj) => JSON.stringify(obj)), +}); + export type Env = StaticDecode; export const envValidator = new StandardValidator(env); diff --git a/src/types/plugin-context-single.ts b/src/types/plugin-context-single.ts index 725dfbb..ad1a955 100644 --- a/src/types/plugin-context-single.ts +++ b/src/types/plugin-context-single.ts @@ -17,7 +17,7 @@ export class PluginContext { private constructor( public readonly inputs: PluginInputs, public _env: Env - ) { } + ) {} get env() { return Value.Decode(envValidator.schema, Value.Default(envValidator.schema, this._env)); @@ -54,7 +54,9 @@ export class PluginContext { adapters: {} as ReturnType, }; - ctx.adapters = createAdapters(createClient(ctx.env.storageSettings.SUPABASE_URL, ctx.env.storageSettings.SUPABASE_SERVICE_KEY), ctx); + const { storageSettings } = ctx.env.telegramBotEnv; + + ctx.adapters = createAdapters(createClient(storageSettings.SUPABASE_URL, storageSettings.SUPABASE_SERVICE_KEY)); return ctx; } diff --git a/src/types/telegram-bot-single.ts b/src/types/telegram-bot-single.ts index 4733862..0cb0ec0 100644 --- a/src/types/telegram-bot-single.ts +++ b/src/types/telegram-bot-single.ts @@ -1,5 +1,4 @@ -import { Value } from "@sinclair/typebox/value"; -import { Env, envValidator } from "."; +import { Env } from "."; import { Bot, createBot } from "../bot"; import { createServer } from "../server"; import { logger } from "../utils/logger"; @@ -15,22 +14,27 @@ export class TelegramBotSingleton { private static _server: ReturnType; static async initialize(env: Env): Promise { - const { telegramBotSettings: { TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_WEBHOOK, ALLOWED_UPDATES } } = env + const { + telegramBotEnv: { + botSettings: { TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_WEBHOOK, ALLOWED_UPDATES }, + }, + } = env; if (!TelegramBotSingleton._instance) { TelegramBotSingleton._instance = new TelegramBotSingleton(); TelegramBotSingleton._bot = createBot(TELEGRAM_BOT_TOKEN, { - config: Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)), + config: env, logger, }); await TelegramBotSingleton._bot.api.setWebhook(TELEGRAM_BOT_WEBHOOK, { allowed_updates: ALLOWED_UPDATES, drop_pending_updates: true, + secret_token: env.telegramBotEnv.botSettings.TELEGRAM_BOT_WEBHOOK_SECRET, }); TelegramBotSingleton._server = createServer({ bot: TelegramBotSingleton._bot, - config: Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)), + config: env, logger, }); } diff --git a/src/utils/add-comment-to-issues.ts b/src/utils/add-comment-to-issues.ts index f09e09e..7ec3f84 100644 --- a/src/utils/add-comment-to-issues.ts +++ b/src/utils/add-comment-to-issues.ts @@ -9,12 +9,10 @@ export async function addCommentToIssue(context: Context, msg: string, owner?: s const { logger, octokit } = context; logger.info(`Adding comment to ${owner}/${repo}#${issueNumber}`); - let obj; - if (!owner || !repo || !issueNumber) { owner = getDeepValue(context, "payload.repository.owner.login"); repo = getDeepValue(context, "payload.repository.name"); - obj = getDeepValue(context, "payload.issue.number"); + issueNumber = getDeepValue(context, "payload.issue.number"); } if (!owner || !repo || !issueNumber) { diff --git a/src/utils/errors.ts b/src/utils/errors.ts index c5c00c8..911a25a 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -1,11 +1,11 @@ import { LogReturn } from "@ubiquity-dao/ubiquibot-logger"; import { Context } from "../types"; import { addCommentToIssue } from "#root/utils/add-comment-to-issues.js"; +import { logger } from "./logger"; -export function handleUncaughtError(error: unknown) { - console.error(error); - const status = 500; - return new Response(JSON.stringify({ error }), { status: status, headers: { "content-type": "application/json" } }); +export function handleUncaughtError(err: unknown) { + logger.error("An uncaught error occurred", { err }); + return new Response(JSON.stringify({ err }), { status: 500, headers: { "content-type": "application/json" } }); } export function sanitizeMetadata(obj: LogReturn["metadata"]): string { return JSON.stringify(obj, null, 2).replace(//g, ">").replace(/--/g, "--"); diff --git a/src/worker.ts b/src/worker.ts index fedd20a..4326e47 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -42,9 +42,7 @@ export default { headers: { "content-type": "application/json" }, }); } - const envSettings = Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)); - if (!envValidator.test(envSettings)) { const errors: string[] = []; for (const error of envValidator.errors(envSettings)) { @@ -58,15 +56,15 @@ export default { } // inits the worker with the telegram bot - await TelegramBotSingleton.initialize(env); + await TelegramBotSingleton.initialize(envSettings); try { if (isGithubPayload(payload)) { // inits the worker with the plugin context for this call - PluginContext.initialize(payload, env); - await handleGithubWebhook(request, env); + PluginContext.initialize(payload, envSettings); + await handleGithubWebhook(request, envSettings); } else if (isTelegramPayload(payload)) { - await handleTelegramWebhook(request, env); + await handleTelegramWebhook(request, envSettings); } else { return new Response(JSON.stringify({ error: "Invalid environment provided" }), { status: 400, diff --git a/src/workflow-entry.ts b/src/workflow-entry.ts index bf77410..7be6307 100644 --- a/src/workflow-entry.ts +++ b/src/workflow-entry.ts @@ -6,6 +6,7 @@ import { PluginContext } from "./types/plugin-context-single"; import { bubbleUpErrorComment } from "./utils/errors"; import dotenv from "dotenv"; import { proxyWorkflowCallbacks } from "./handlers/workflow-proxy"; +import { logger } from "./utils/logger"; dotenv.config(); /** @@ -35,13 +36,13 @@ export async function run() { try { env = Value.Decode(envValidator.schema, payloadEnv); } catch (err) { - console.log("Error decoding env: ", err); + logger.error("Error decoding env: ", { err }); } try { settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, JSON.parse(payload.settings))); } catch (err) { - console.log("Error decoding settings: ", err); + logger.error("Error decoding settings: ", { err }); } if (!(settings && env)) { @@ -90,7 +91,7 @@ run() .then((result) => { core.setOutput("result", result); }) - .catch((error) => { - console.error(error); - core.setFailed(error); + .catch((err) => { + logger.error("Error running workflow: ", { err }); + core.setFailed(err); }); From 414f19cdc8ef297fa29af42fc73703e7147dc7d4 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 19:02:21 +0100 Subject: [PATCH 46/76] chore: env setup helper --- .github/workflows/compute.yml | 28 +- README.md | 51 +++- package.json | 6 +- .../bot/scripts/sms-auth/setup-env.ts | 280 ++++++++++++++++++ 4 files changed, 324 insertions(+), 41 deletions(-) create mode 100644 src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 61df489..2af29be 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -22,19 +22,7 @@ jobs: runs-on: ubuntu-latest permissions: write-all env: - SUPABASE_URL: ${{ secrets.SUPABASE_URL }} - SUPABASE_SERVICE_KEY: ${{ secrets.SUPABASE_SERVICE_KEY }} - - BOT_TOKEN: ${{ secrets.BOT_TOKEN }} - BOT_ADMINS: ${{ secrets.BOT_ADMINS }} - BOT_WEBHOOK: ${{ secrets.BOT_WEBHOOK }} - BOT_WEBHOOK_SECRET: ${{ secrets.BOT_WEBHOOK_SECRET }} - - TELEGRAM_APP_ID: ${{ secrets.TELEGRAM_APP_ID }} - TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }} - - APP_ID: ${{ secrets.APP_ID }} - APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} + telegramBotEnv: ${{ secrets.telegramBotEnv }} steps: - uses: actions/checkout@v4 @@ -51,16 +39,4 @@ jobs: run: npx tsx ./src/workflow-entry.ts id: telegram-bot env: - SUPABASE_URL: ${{ secrets.SUPABASE_URL }} - SUPABASE_SERVICE_KEY: ${{ secrets.SUPABASE_SERVICE_KEY }} - - BOT_TOKEN: ${{ secrets.BOT_TOKEN }} - BOT_ADMINS: ${{ secrets.BOT_ADMINS }} - BOT_WEBHOOK: ${{ secrets.BOT_WEBHOOK }} - BOT_WEBHOOK_SECRET: ${{ secrets.BOT_WEBHOOK_SECRET }} - - TELEGRAM_APP_ID: ${{ secrets.TELEGRAM_APP_ID }} - TELEGRAM_API_HASH: ${{ secrets.TELEGRAM_API_HASH }} - - APP_ID: ${{ secrets.APP_ID }} - APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }} + telegramBotEnv: ${{ secrets.telegramBotEnv }} \ No newline at end of file diff --git a/README.md b/README.md index 117a42a..26d90c2 100644 --- a/README.md +++ b/README.md @@ -65,21 +65,46 @@ This bot operates in two parts: #### Environment Variables -Define these in both `dev.vars` and your GitHub repository secrets: - -```bash -BOT_TOKEN=123:xyz # Telegram Bot Token from BotFather -BOT_WEBHOOK=... # Cloudflare Worker URL -BOT_WEBHOOK_SECRET=... # Cloudflare Worker Secret -BOT_ADMINS=[1234,5678] # Telegram User IDs -SUPABASE_URL=... # Supabase URL -SUPABASE_SERVICE_KEY=... # Supabase Service Key -TELEGRAM_APP_ID=12345678 # Telegram App ID -TELEGRAM_API_HASH=... # Telegram API Hash -APP_PRIVATE_KEY=... # GitHub App Private Key -APP_ID=123456 # GitHub App ID +`telegramBotEnv` is a single JSON object containing all the necessary environment variables for the bot to function. It is made up of four parts: `botSettings`, `mtProtoSettings`, `storageSettings`, and `ubiquityOsSettings`. + +A utility script exists to help you set up your environment variables, run `yarn setup-env` for a guided setup. + +You must define these in three locations: + +- `.env` in order to use the `yarn sms-auth` command +- `.dev.vars` for the Cloudflare Worker instance +- GitHub Secrets for the GitHub Actions workflow + +1. **botSettings**: Contains bot specific settings like `TELEGRAM_BOT_TOKEN`, `TELEGRAM_BOT_WEBHOOK_SECRET`, etc. +2. **mtProtoSettings**: Contains settings for the MTProto API like `TELEGRAM_APP_ID`, `TELEGRAM_API_HASH`, etc. +3. **storageSettings**: Contains settings for the Supabase database like `SUPABASE_URL`, `SUPABASE_SERVICE_KEY`, etc. +4. **ubiquityOsSettings**: Contains settings for the UbiquityOS Kernel like `APP_PRIVATE_KEY`, `APP_ID`, etc. + +```ts +interface TelegramBotEnv { + botSettings: { + TELEGRAM_BOT_TOKEN: string; // Telegram Bot Token from BotFather + TELEGRAM_BOT_WEBHOOK: string; // Cloudflare Worker URL + TELEGRAM_BOT_WEBHOOK_SECRET: string; // Cloudflare Worker Secret + TELEGRAM_BOT_ADMINS: number[]; // Telegram User IDs + }; + mtProtoSettings: { + TELEGRAM_APP_ID: number; // Telegram App ID + TELEGRAM_API_HASH: string; // Telegram API Hash + }; + storageSettings: { + SUPABASE_URL: string; // Supabase URL + SUPABASE_SERVICE_KEY: string; // Supabase Service Key + }; + ubiquityOsSettings: { + APP_PRIVATE_KEY: string; // GitHub App Private Key + APP_ID: number; // GitHub App ID + }; +} ``` + + #### Supabase Configuration 1. Create or use an existing Supabase project. diff --git a/package.json b/package.json index c05add9..768c3b6 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,9 @@ "dev": "tsc-watch --onSuccess \"tsx ./src/main.ts\"", "start": "tsx ./src/main.ts", "deploy": "wrangler deploy --minify src/main.ts", - "sms-auth": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts" + "sms-auth": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts", + "setup-env-guided": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts", + "setup-env-manual": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts --manual" }, "keywords": [ "typescript", @@ -112,4 +114,4 @@ ] }, "packageManager": "yarn@1.22.22" -} +} \ No newline at end of file diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts new file mode 100644 index 0000000..78ae637 --- /dev/null +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts @@ -0,0 +1,280 @@ +// @ts-expect-error no types +import input from "input"; +import { writeFile } from "node:fs/promises"; +import { Context } from "../../../../../types"; +import { logger } from "#root/utils/logger.js"; +import { exit } from "node:process"; +import { Octokit } from "@octokit/rest"; + +/** + * This script is used to help guide the user through setting up the environment variables. + * + * The user will be prompted to enter the required environment variables, they'll be stored + * automatically in the `.env` and `.dev.vars` files. + */ + +class SetUpHandler { + private _env: Context["env"] = { + telegramBotEnv: { + botSettings: { + TELEGRAM_BOT_ADMINS: [], + TELEGRAM_BOT_TOKEN: "", + TELEGRAM_BOT_WEBHOOK: "", + TELEGRAM_BOT_WEBHOOK_SECRET: "", + }, + mtProtoSettings: { + TELEGRAM_API_HASH: "", + TELEGRAM_APP_ID: 0, + }, + storageSettings: { + SUPABASE_SERVICE_KEY: "", + SUPABASE_URL: "", + }, + ubiquityOsSettings: { + APP_ID: 0, + APP_PRIVATE_KEY: "", + }, + }, + }; + + get env() { + return this._env; + } + + set env(env: Context["env"]) { + this._env = env; + } + + steps = [ + { + title: "Bot settings", + questions: [ + { + type: "input", + name: "TELEGRAM_BOT_TOKEN", + message: "Enter your Telegram bot token. This can be obtained from @BotFather", + }, + { + type: "input", + name: "TELEGRAM_BOT_WEBHOOK", + message: "Enter your Telegram bot webhook. Cloudflare for production, ngrok/smee for development", + }, + { + type: "input", + name: "TELEGRAM_BOT_WEBHOOK_SECRET", + message: "Enter your Telegram bot webhook secret. This is used to verify incoming requests from Telegram", + }, + { + type: "input", + name: "TELEGRAM_BOT_ADMINS", + message: "Enter your Telegram bot admin IDs seperated with commas. '123456789,987654321'", + } + ], + }, + { + title: "MTProto settings", + questions: [ + { + type: "input", + name: "TELEGRAM_API_HASH", + message: "Enter your Telegram API hash. This can be obtained from 'https://my.telegram.org'", + }, + { + type: "input", + name: "TELEGRAM_APP_ID", + message: "Enter your Telegram app id. This can be obtained from 'https://my.telegram.org'", + }, + ], + }, + { + title: "Storage settings", + questions: [ + { + type: "input", + name: "SUPABASE_SERVICE_KEY", + message: "Enter your Supabase service key (read/write access)", + }, + { + type: "input", + name: "SUPABASE_URL", + message: "Enter your Supabase URL (https://.supabase.co)", + }, + ], + }, + { + title: "Ubiquity OS settings", + questions: [ + { + type: "input", + name: "APP_ID", + message: "Enter your Ubiquity OS app id. This can be obtained from 'https://github.com/settings/apps'", + }, + { + type: "input", + name: "APP_PRIVATE_KEY", + message: "Enter your Ubiquity OS private key. This can be obtained from 'https://github.com/settings/apps'", + }, + ], + }, + ]; + + async run() { + const answers: Record> = {}; + for (const step of this.steps) { + console.log(step.title); + const questions = step.questions; + + for (const question of questions) { + const answer = await input.text(question.message); + console.log("Answer:", answer); + answers[step.title] ??= {}; + if (question.name === "TELEGRAM_BOT_ADMINS") { + answers[step.title][question.name] = JSON.stringify(answer.split(",").map((id: string) => Number(id))) + continue; + } + answers[step.title][question.name] = answer; + } + } + + console.clear(); + + this.env = { + telegramBotEnv: { + botSettings: { + TELEGRAM_BOT_ADMINS: JSON.parse(answers["Bot settings"]["TELEGRAM_BOT_ADMINS"]), + TELEGRAM_BOT_TOKEN: answers["Bot settings"]["TELEGRAM_BOT_TOKEN"], + TELEGRAM_BOT_WEBHOOK: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK"], + TELEGRAM_BOT_WEBHOOK_SECRET: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK_SECRET"], + }, + mtProtoSettings: { + TELEGRAM_API_HASH: answers["MTProto settings"]["TELEGRAM_API_HASH"], + TELEGRAM_APP_ID: Number(answers["MTProto settings"]["TELEGRAM_APP_ID"]), + }, + storageSettings: { + SUPABASE_SERVICE_KEY: answers["Storage settings"]["SUPABASE_SERVICE_KEY"], + SUPABASE_URL: answers["Storage settings"]["SUPABASE_URL"], + }, + ubiquityOsSettings: { + APP_ID: Number(answers["Ubiquity OS settings"]["APP_ID"]), + APP_PRIVATE_KEY: answers["Ubiquity OS settings"]["APP_PRIVATE_KEY"], + }, + }, + }; + + await this.validateEnv(); + } + + /** + * Manually set the env variables and run `yarn setup-env-manual` + */ + async manual() { + this.env = { + telegramBotEnv: { + botSettings: { + TELEGRAM_BOT_ADMINS: [], + TELEGRAM_BOT_TOKEN: "", + TELEGRAM_BOT_WEBHOOK: "", + TELEGRAM_BOT_WEBHOOK_SECRET: "", + }, + mtProtoSettings: { + TELEGRAM_API_HASH: "", + TELEGRAM_APP_ID: 0, + }, + storageSettings: { + SUPABASE_SERVICE_KEY: "", + SUPABASE_URL: "", + }, + ubiquityOsSettings: { + APP_ID: 0, + APP_PRIVATE_KEY: "", + }, + }, + }; + + await this.saveEnv(); + } + + async validateEnv() { + const env = this.env.telegramBotEnv; + const { botSettings, mtProtoSettings, storageSettings, ubiquityOsSettings } = env + + const merged = { + ...botSettings, + ...mtProtoSettings, + ...storageSettings, + ...ubiquityOsSettings, + } + + const keys = Object.keys(merged); + + const missing = [] + + for (const key_ of keys) { + const key = key_ as keyof typeof merged; + if (!merged[key]) { + missing.push(key); + } + } + + if (missing.length) { + console.log("Missing keys:", missing); + await this.run(); + } + await this.saveEnv(); + + logger.ok("Env saved successfully"); + + exit() + } + + async saveEnv() { + const paths = [ + ".env", + ".dev.vars", + ] + + const envVar = `telegramBotEnv=${JSON.stringify(this.env.telegramBotEnv)}` + + for (const path of paths) { + await writeFile(path, envVar, "utf-8"); + } + + logger.ok("Local env files saved successfully"); + logger.info("Storing secrets in GitHub"); + await this.storeRepoSecrets(); + } + + async storeRepoSecrets() { + const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); + const secret = `${JSON.stringify(this.env.telegramBotEnv)}`; + + try { + await octokit.actions.createOrUpdateRepoSecret({ + owner: "ubq-testing", + repo: "telegram--bot", + secret_name: "telegramBotEnv", + encrypted_value: secret, + }); + logger.ok("Secret stored successfully"); + } catch (err) { + logger.error("Error storing secret", { err }); + } + exit(); + } +} + +async function guided() { + const setup = new SetUpHandler(); + await setup.run(); +} + +async function manual() { + const setup = new SetUpHandler(); + await setup.manual(); +} + +if (process.argv.includes("--manual")) { + manual().catch(logger.error); +} else { + guided().catch(logger.error); +} \ No newline at end of file From 00d9d422fd69aaf3dd605c351643480c589afa9a Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 20:09:04 +0100 Subject: [PATCH 47/76] feat: repo secret saving, guided env setup --- .cspell.json | 5 +- .github/workflows/compute.yml | 4 +- README.md | 52 +- package.json | 3 +- src/bot/features/admin/admin.ts | 2 +- src/bot/helpers/grammy-context.ts | 2 +- src/bot/mtproto-api/bot/mtproto.ts | 4 +- .../bot/scripts/sms-auth/auth-handler.ts | 4 +- .../bot/scripts/sms-auth/base-mtproto.ts | 4 +- .../bot/scripts/sms-auth/setup-env.ts | 478 +++++++++--------- src/handlers/repository-dispatch.ts | 2 +- src/server/index.ts | 2 +- src/types/env.ts | 6 +- src/types/plugin-context-single.ts | 2 +- src/types/telegram-bot-single.ts | 4 +- yarn.lock | 12 + 16 files changed, 317 insertions(+), 269 deletions(-) diff --git a/.cspell.json b/.cspell.json index d95b08b..6e083b4 100644 --- a/.cspell.json +++ b/.cspell.json @@ -31,7 +31,10 @@ "chatid", "myid", "baseclass", - "unarchived" + "unarchived", + "libsodium", + "binkey", + "binsec" ], "dictionaries": ["typescript", "node", "software-terms"], "import": ["@cspell/dict-typescript/cspell-ext.json", "@cspell/dict-node/cspell-ext.json", "@cspell/dict-software-terms"], diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 2af29be..3e886c8 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest permissions: write-all env: - telegramBotEnv: ${{ secrets.telegramBotEnv }} + TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} steps: - uses: actions/checkout@v4 @@ -39,4 +39,4 @@ jobs: run: npx tsx ./src/workflow-entry.ts id: telegram-bot env: - telegramBotEnv: ${{ secrets.telegramBotEnv }} \ No newline at end of file + TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} diff --git a/README.md b/README.md index 26d90c2..c6d236d 100644 --- a/README.md +++ b/README.md @@ -65,46 +65,53 @@ This bot operates in two parts: #### Environment Variables -`telegramBotEnv` is a single JSON object containing all the necessary environment variables for the bot to function. It is made up of four parts: `botSettings`, `mtProtoSettings`, `storageSettings`, and `ubiquityOsSettings`. +The `TELEGRAM_BOT_ENV` is a single JSON object that encapsulates all necessary environment variables for the bot's operation. It consists of four key sections: `botSettings`, `mtProtoSettings`, `storageSettings`, and `ubiquityOsSettings`. -A utility script exists to help you set up your environment variables, run `yarn setup-env` for a guided setup. +You can set up your environment variables in two ways using the provided utility script: -You must define these in three locations: +1. **Guided Setup**: Run `yarn setup-env-guided`, which prompts you to enter each value via the CLI. The values will be serialized and stored both locally and in your repository secrets. +2. **Manual Setup**: Modify the values directly in the script and then run `yarn setup-env-manual` to store them locally and in your repository secrets. -- `.env` in order to use the `yarn sms-auth` command -- `.dev.vars` for the Cloudflare Worker instance -- GitHub Secrets for the GitHub Actions workflow +**Important**: Before running the setup script, ensure that you store your `GITHUB_PAT_TOKEN` in the `.env` file. This token will be used to create repository secrets and will be deleted after the script runs. -1. **botSettings**: Contains bot specific settings like `TELEGRAM_BOT_TOKEN`, `TELEGRAM_BOT_WEBHOOK_SECRET`, etc. +- **GITHUB_PAT_TOKEN**: Create a classic personal access token (PAT) with the `repo` scope. Set the expiry to 24 hours, and save it in your `.env` file. This token will be used to generate repository secrets for the environment variables. + +The environment variables are stored in the following locations: + +- `.env` file: Required to run the `yarn sms-auth` command. +- `.dev.vars` file: For the Cloudflare Worker instance. +- **GitHub Secrets**: Used by the GitHub Actions workflow. + +##### Environment Variable Sections: + +1. **botSettings**: Contains bot-specific settings like `TELEGRAM_BOT_TOKEN`, `TELEGRAM_BOT_WEBHOOK_SECRET`, etc. 2. **mtProtoSettings**: Contains settings for the MTProto API like `TELEGRAM_APP_ID`, `TELEGRAM_API_HASH`, etc. 3. **storageSettings**: Contains settings for the Supabase database like `SUPABASE_URL`, `SUPABASE_SERVICE_KEY`, etc. 4. **ubiquityOsSettings**: Contains settings for the UbiquityOS Kernel like `APP_PRIVATE_KEY`, `APP_ID`, etc. -```ts -interface TelegramBotEnv { +```typescript +interface TELEGRAM_BOT_ENV { botSettings: { - TELEGRAM_BOT_TOKEN: string; // Telegram Bot Token from BotFather - TELEGRAM_BOT_WEBHOOK: string; // Cloudflare Worker URL - TELEGRAM_BOT_WEBHOOK_SECRET: string; // Cloudflare Worker Secret - TELEGRAM_BOT_ADMINS: number[]; // Telegram User IDs + TELEGRAM_BOT_TOKEN: string; // Telegram Bot Token from BotFather + TELEGRAM_BOT_WEBHOOK: string; // Cloudflare Worker URL + TELEGRAM_BOT_WEBHOOK_SECRET: string; // Cloudflare Worker Secret + TELEGRAM_BOT_ADMINS: number[]; // Telegram User IDs }; mtProtoSettings: { - TELEGRAM_APP_ID: number; // Telegram App ID - TELEGRAM_API_HASH: string; // Telegram API Hash + TELEGRAM_APP_ID: number; // Telegram App ID + TELEGRAM_API_HASH: string; // Telegram API Hash }; storageSettings: { - SUPABASE_URL: string; // Supabase URL - SUPABASE_SERVICE_KEY: string; // Supabase Service Key + SUPABASE_URL: string; // Supabase URL + SUPABASE_SERVICE_KEY: string; // Supabase Service Key }; ubiquityOsSettings: { - APP_PRIVATE_KEY: string; // GitHub App Private Key - APP_ID: number; // GitHub App ID + APP_PRIVATE_KEY: string; // GitHub App Private Key + APP_ID: number; // GitHub App ID }; } ``` - - #### Supabase Configuration 1. Create or use an existing Supabase project. @@ -126,12 +133,11 @@ interface TelegramBotEnv { ```yaml - uses: + - skipBotEvents: false - plugin: http://localhost:3000 runsOn: ["issues.opened", "issues.labeled", "issues.reopened", "issues.closed"] - skipBotEvents: false with: botId: 00000000 - botUsername: yourBotName ``` ### Usage diff --git a/package.json b/package.json index 768c3b6..b9755ec 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "jest-junit": "16.0.0", "jest-md-dashboard": "0.8.0", "knip": "5.27.4", + "libsodium-wrappers": "^0.7.15", "lint-staged": "15.2.9", "npm-run-all": "4.1.5", "prettier": "3.3.3", @@ -114,4 +115,4 @@ ] }, "packageManager": "yarn@1.22.22" -} \ No newline at end of file +} diff --git a/src/bot/features/admin/admin.ts b/src/bot/features/admin/admin.ts index 6612ad5..f8dc01b 100644 --- a/src/bot/features/admin/admin.ts +++ b/src/bot/features/admin/admin.ts @@ -7,7 +7,7 @@ import { logHandle } from "#root/bot/helpers/logging.js"; const composer = new Composer(); -const feature = composer.chatType("private").filter((ctx) => isAdmin(ctx.config.telegramBotEnv.botSettings.TELEGRAM_BOT_ADMINS)(ctx)); +const feature = composer.chatType("private").filter((ctx) => isAdmin(ctx.config.TELEGRAM_BOT_ENV.botSettings.TELEGRAM_BOT_ADMINS)(ctx)); feature.command("setcommands", logHandle("command-setcommands"), chatAction("typing"), setCommandsHandler); diff --git a/src/bot/helpers/grammy-context.ts b/src/bot/helpers/grammy-context.ts index 4fa778c..90dd590 100644 --- a/src/bot/helpers/grammy-context.ts +++ b/src/bot/helpers/grammy-context.ts @@ -38,7 +38,7 @@ export function createContextConstructor({ logger, config }: Dependencies) { this.logger = logger; this.config = config; - const { SUPABASE_URL, SUPABASE_SERVICE_KEY } = config.telegramBotEnv.storageSettings; + const { SUPABASE_URL, SUPABASE_SERVICE_KEY } = config.TELEGRAM_BOT_ENV.storageSettings; this.adapters = createAdapters(createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY)); } } as unknown as new (update: GrammyTelegramUpdate, api: Api, me: UserFromGetMe) => Context; diff --git a/src/bot/mtproto-api/bot/mtproto.ts b/src/bot/mtproto-api/bot/mtproto.ts index 2310f03..dcfabf5 100644 --- a/src/bot/mtproto-api/bot/mtproto.ts +++ b/src/bot/mtproto-api/bot/mtproto.ts @@ -20,7 +20,7 @@ export class MtProto extends BaseMtProto { constructor(context: Context) { super(); - const { SUPABASE_URL, SUPABASE_SERVICE_KEY } = context.env.telegramBotEnv.storageSettings; + const { SUPABASE_URL, SUPABASE_SERVICE_KEY } = context.env.TELEGRAM_BOT_ENV.storageSettings; if (!SUPABASE_URL || !SUPABASE_SERVICE_KEY) { throw new Error("Missing required environment variables for Supabase"); @@ -33,7 +33,7 @@ export class MtProto extends BaseMtProto { async initialize() { const session = await this._session.getSession(); - await super.initialize(this._context.env.telegramBotEnv.mtProtoSettings, session); + await super.initialize(this._context.env.TELEGRAM_BOT_ENV.mtProtoSettings, session); } async saveSession() { diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts index 05e48a7..c6bbeff 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts @@ -20,12 +20,12 @@ export class AuthHandler { }; constructor() { - const env = process.env.telegramBotEnv; + const env = process.env.TELEGRAM_BOT_ENV; if (!env) { throw new Error("Missing required environment variables for Telegram Bot"); } - const parsedEnv: Context["env"]["telegramBotEnv"] = JSON.parse(env); + const parsedEnv: Context["env"]["TELEGRAM_BOT_ENV"] = JSON.parse(env); if (!parsedEnv) { throw new Error("Failed to parse environment variables for Telegram Bot"); } diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts index d665d57..4e5e80a 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts @@ -18,7 +18,7 @@ export class BaseMtProto { _api: typeof Api = Api; _session: StringSession | null = null; - async initialize(env: Context["env"]["telegramBotEnv"]["mtProtoSettings"], session: string) { + async initialize(env: Context["env"]["TELEGRAM_BOT_ENV"]["mtProtoSettings"], session: string) { this._api = Api; this._session = new StringSession(session); this._client = await this._mtProtoInit(env, this._session); @@ -36,7 +36,7 @@ export class BaseMtProto { return this._session; } - private async _mtProtoInit(env: Context["env"]["telegramBotEnv"]["mtProtoSettings"], session: StringSession) { + private async _mtProtoInit(env: Context["env"]["TELEGRAM_BOT_ENV"]["mtProtoSettings"], session: StringSession) { const { TELEGRAM_API_HASH, TELEGRAM_APP_ID } = env; if (!TELEGRAM_API_HASH || !TELEGRAM_APP_ID) { diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts index 78ae637..9cf132e 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts @@ -1,280 +1,306 @@ // @ts-expect-error no types import input from "input"; +// @ts-expect-error no types +import sodium from "libsodium-wrappers"; import { writeFile } from "node:fs/promises"; import { Context } from "../../../../../types"; import { logger } from "#root/utils/logger.js"; import { exit } from "node:process"; import { Octokit } from "@octokit/rest"; - +import dotenv from "dotenv"; +dotenv.config(); /** * This script is used to help guide the user through setting up the environment variables. - * - * The user will be prompted to enter the required environment variables, they'll be stored + * + * The user will be prompted to enter the required environment variables, they'll be stored * automatically in the `.env` and `.dev.vars` files. */ class SetUpHandler { - private _env: Context["env"] = { - telegramBotEnv: { - botSettings: { - TELEGRAM_BOT_ADMINS: [], - TELEGRAM_BOT_TOKEN: "", - TELEGRAM_BOT_WEBHOOK: "", - TELEGRAM_BOT_WEBHOOK_SECRET: "", - }, - mtProtoSettings: { - TELEGRAM_API_HASH: "", - TELEGRAM_APP_ID: 0, - }, - storageSettings: { - SUPABASE_SERVICE_KEY: "", - SUPABASE_URL: "", - }, - ubiquityOsSettings: { - APP_ID: 0, - APP_PRIVATE_KEY: "", - }, - }, - }; + private _env: Context["env"] = { + TELEGRAM_BOT_ENV: { + botSettings: { + TELEGRAM_BOT_ADMINS: [], + TELEGRAM_BOT_TOKEN: "", + TELEGRAM_BOT_WEBHOOK: "", + TELEGRAM_BOT_WEBHOOK_SECRET: "", + }, + mtProtoSettings: { + TELEGRAM_API_HASH: "", + TELEGRAM_APP_ID: 0, + }, + storageSettings: { + SUPABASE_SERVICE_KEY: "", + SUPABASE_URL: "", + }, + ubiquityOsSettings: { + APP_ID: 0, + APP_PRIVATE_KEY: "", + }, + }, + }; - get env() { - return this._env; - } + get env() { + return this._env; + } - set env(env: Context["env"]) { - this._env = env; - } + set env(env: Context["env"]) { + this._env = env; + } - steps = [ + steps = [ + { + title: "Bot settings", + questions: [ { - title: "Bot settings", - questions: [ - { - type: "input", - name: "TELEGRAM_BOT_TOKEN", - message: "Enter your Telegram bot token. This can be obtained from @BotFather", - }, - { - type: "input", - name: "TELEGRAM_BOT_WEBHOOK", - message: "Enter your Telegram bot webhook. Cloudflare for production, ngrok/smee for development", - }, - { - type: "input", - name: "TELEGRAM_BOT_WEBHOOK_SECRET", - message: "Enter your Telegram bot webhook secret. This is used to verify incoming requests from Telegram", - }, - { - type: "input", - name: "TELEGRAM_BOT_ADMINS", - message: "Enter your Telegram bot admin IDs seperated with commas. '123456789,987654321'", - } - ], + type: "input", + name: "TELEGRAM_BOT_TOKEN", + message: "Enter your Telegram bot token. This can be obtained from @BotFather", }, { - title: "MTProto settings", - questions: [ - { - type: "input", - name: "TELEGRAM_API_HASH", - message: "Enter your Telegram API hash. This can be obtained from 'https://my.telegram.org'", - }, - { - type: "input", - name: "TELEGRAM_APP_ID", - message: "Enter your Telegram app id. This can be obtained from 'https://my.telegram.org'", - }, - ], + type: "input", + name: "TELEGRAM_BOT_WEBHOOK", + message: "Enter your Telegram bot webhook. Cloudflare for production, ngrok/smee for development", }, { - title: "Storage settings", - questions: [ - { - type: "input", - name: "SUPABASE_SERVICE_KEY", - message: "Enter your Supabase service key (read/write access)", - }, - { - type: "input", - name: "SUPABASE_URL", - message: "Enter your Supabase URL (https://.supabase.co)", - }, - ], + type: "input", + name: "TELEGRAM_BOT_WEBHOOK_SECRET", + message: "Enter your Telegram bot webhook secret. This is used to verify incoming requests from Telegram", }, { - title: "Ubiquity OS settings", - questions: [ - { - type: "input", - name: "APP_ID", - message: "Enter your Ubiquity OS app id. This can be obtained from 'https://github.com/settings/apps'", - }, - { - type: "input", - name: "APP_PRIVATE_KEY", - message: "Enter your Ubiquity OS private key. This can be obtained from 'https://github.com/settings/apps'", - }, - ], + type: "input", + name: "TELEGRAM_BOT_ADMINS", + message: "Enter your Telegram bot admin IDs separated with commas. '123456789,987654321'", }, - ]; - - async run() { - const answers: Record> = {}; - for (const step of this.steps) { - console.log(step.title); - const questions = step.questions; - - for (const question of questions) { - const answer = await input.text(question.message); - console.log("Answer:", answer); - answers[step.title] ??= {}; - if (question.name === "TELEGRAM_BOT_ADMINS") { - answers[step.title][question.name] = JSON.stringify(answer.split(",").map((id: string) => Number(id))) - continue; - } - answers[step.title][question.name] = answer; - } - } + ], + }, + { + title: "MTProto settings", + questions: [ + { + type: "input", + name: "TELEGRAM_API_HASH", + message: "Enter your Telegram API hash. This can be obtained from 'https://my.telegram.org'", + }, + { + type: "input", + name: "TELEGRAM_APP_ID", + message: "Enter your Telegram app id. This can be obtained from 'https://my.telegram.org'", + }, + ], + }, + { + title: "Storage settings", + questions: [ + { + type: "input", + name: "SUPABASE_SERVICE_KEY", + message: "Enter your Supabase service key (read/write access)", + }, + { + type: "input", + name: "SUPABASE_URL", + message: "Enter your Supabase URL (https://.supabase.co)", + }, + ], + }, + { + title: "Ubiquity OS settings", + questions: [ + { + type: "input", + name: "APP_ID", + message: "Enter your Ubiquity OS app id. This can be obtained from 'https://github.com/settings/apps'", + }, + { + type: "input", + name: "APP_PRIVATE_KEY", + message: "Enter your Ubiquity OS private key. This can be obtained from 'https://github.com/settings/apps'", + }, + ], + }, + ]; - console.clear(); - - this.env = { - telegramBotEnv: { - botSettings: { - TELEGRAM_BOT_ADMINS: JSON.parse(answers["Bot settings"]["TELEGRAM_BOT_ADMINS"]), - TELEGRAM_BOT_TOKEN: answers["Bot settings"]["TELEGRAM_BOT_TOKEN"], - TELEGRAM_BOT_WEBHOOK: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK"], - TELEGRAM_BOT_WEBHOOK_SECRET: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK_SECRET"], - }, - mtProtoSettings: { - TELEGRAM_API_HASH: answers["MTProto settings"]["TELEGRAM_API_HASH"], - TELEGRAM_APP_ID: Number(answers["MTProto settings"]["TELEGRAM_APP_ID"]), - }, - storageSettings: { - SUPABASE_SERVICE_KEY: answers["Storage settings"]["SUPABASE_SERVICE_KEY"], - SUPABASE_URL: answers["Storage settings"]["SUPABASE_URL"], - }, - ubiquityOsSettings: { - APP_ID: Number(answers["Ubiquity OS settings"]["APP_ID"]), - APP_PRIVATE_KEY: answers["Ubiquity OS settings"]["APP_PRIVATE_KEY"], - }, - }, - }; - - await this.validateEnv(); + async run() { + if (!process.env.GITHUB_PAT_TOKEN) { + logger.fatal("GITHUB_PAT_TOKEN is not set in the environment variables"); + exit(); } + const answers: Record> = {}; + for (const step of this.steps) { + console.log(step.title); + const questions = step.questions; - /** - * Manually set the env variables and run `yarn setup-env-manual` - */ - async manual() { - this.env = { - telegramBotEnv: { - botSettings: { - TELEGRAM_BOT_ADMINS: [], - TELEGRAM_BOT_TOKEN: "", - TELEGRAM_BOT_WEBHOOK: "", - TELEGRAM_BOT_WEBHOOK_SECRET: "", - }, - mtProtoSettings: { - TELEGRAM_API_HASH: "", - TELEGRAM_APP_ID: 0, - }, - storageSettings: { - SUPABASE_SERVICE_KEY: "", - SUPABASE_URL: "", - }, - ubiquityOsSettings: { - APP_ID: 0, - APP_PRIVATE_KEY: "", - }, - }, - }; - - await this.saveEnv(); + for (const question of questions) { + const answer = await input.text(question.message); + console.log("Answer:", answer); + answers[step.title] ??= {}; + if (question.name === "TELEGRAM_BOT_ADMINS") { + answers[step.title][question.name] = JSON.stringify(answer.split(",").map((id: string) => Number(id))); + continue; + } + answers[step.title][question.name] = answer; + } } - async validateEnv() { - const env = this.env.telegramBotEnv; - const { botSettings, mtProtoSettings, storageSettings, ubiquityOsSettings } = env + console.clear(); - const merged = { - ...botSettings, - ...mtProtoSettings, - ...storageSettings, - ...ubiquityOsSettings, - } + this.env = { + TELEGRAM_BOT_ENV: { + botSettings: { + TELEGRAM_BOT_ADMINS: JSON.parse(answers["Bot settings"]["TELEGRAM_BOT_ADMINS"]), + TELEGRAM_BOT_TOKEN: answers["Bot settings"]["TELEGRAM_BOT_TOKEN"], + TELEGRAM_BOT_WEBHOOK: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK"], + TELEGRAM_BOT_WEBHOOK_SECRET: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK_SECRET"], + }, + mtProtoSettings: { + TELEGRAM_API_HASH: answers["MTProto settings"]["TELEGRAM_API_HASH"], + TELEGRAM_APP_ID: Number(answers["MTProto settings"]["TELEGRAM_APP_ID"]), + }, + storageSettings: { + SUPABASE_SERVICE_KEY: answers["Storage settings"]["SUPABASE_SERVICE_KEY"], + SUPABASE_URL: answers["Storage settings"]["SUPABASE_URL"], + }, + ubiquityOsSettings: { + APP_ID: Number(answers["Ubiquity OS settings"]["APP_ID"]), + APP_PRIVATE_KEY: answers["Ubiquity OS settings"]["APP_PRIVATE_KEY"], + }, + }, + }; + + await this.validateEnv(); + } + + /** + * Manually set the env variables below and run `yarn setup-env-manual` + */ + async manual() { + this.env = { + TELEGRAM_BOT_ENV: { + botSettings: { + TELEGRAM_BOT_ADMINS: [], + TELEGRAM_BOT_TOKEN: "", + TELEGRAM_BOT_WEBHOOK: "", + TELEGRAM_BOT_WEBHOOK_SECRET: "", + }, + mtProtoSettings: { + TELEGRAM_API_HASH: "", + TELEGRAM_APP_ID: 0, + }, + storageSettings: { + SUPABASE_SERVICE_KEY: "", + SUPABASE_URL: "", + }, + ubiquityOsSettings: { + APP_ID: 0, + APP_PRIVATE_KEY: "", + }, + }, + }; - const keys = Object.keys(merged); + await this.saveEnv(); + } - const missing = [] + async validateEnv() { + const env = this.env.TELEGRAM_BOT_ENV; + const { botSettings, mtProtoSettings, storageSettings, ubiquityOsSettings } = env; - for (const key_ of keys) { - const key = key_ as keyof typeof merged; - if (!merged[key]) { - missing.push(key); - } - } + const merged = { + ...botSettings, + ...mtProtoSettings, + ...storageSettings, + ...ubiquityOsSettings, + }; - if (missing.length) { - console.log("Missing keys:", missing); - await this.run(); - } - await this.saveEnv(); + const keys = Object.keys(merged); + + const missing = []; - logger.ok("Env saved successfully"); + for (const key_ of keys) { + const key = key_ as keyof typeof merged; + if (!merged[key]) { + missing.push(key); + } + } - exit() + if (missing.length) { + console.log("Missing keys:", missing); + await this.run(); } + await this.saveEnv(); - async saveEnv() { - const paths = [ - ".env", - ".dev.vars", - ] + logger.ok("Env saved successfully"); - const envVar = `telegramBotEnv=${JSON.stringify(this.env.telegramBotEnv)}` + exit(); + } - for (const path of paths) { - await writeFile(path, envVar, "utf-8"); - } + async saveEnv() { + const paths = [".env", ".dev.vars"]; + + const envVar = `TELEGRAM_BOT_ENV=${JSON.stringify(this.env.TELEGRAM_BOT_ENV)}`; - logger.ok("Local env files saved successfully"); - logger.info("Storing secrets in GitHub"); - await this.storeRepoSecrets(); + for (const path of paths) { + await writeFile(path, envVar, "utf-8"); } - async storeRepoSecrets() { - const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); - const secret = `${JSON.stringify(this.env.telegramBotEnv)}`; - - try { - await octokit.actions.createOrUpdateRepoSecret({ - owner: "ubq-testing", - repo: "telegram--bot", - secret_name: "telegramBotEnv", - encrypted_value: secret, - }); - logger.ok("Secret stored successfully"); - } catch (err) { - logger.error("Error storing secret", { err }); - } - exit(); + logger.ok("Local env files saved successfully"); + logger.info("Storing secrets in GitHub"); + await this.storeRepoSecrets(); + } + + async storeRepoSecrets() { + const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); + const secret = `${JSON.stringify(this.env.TELEGRAM_BOT_ENV)}`; + + try { + const pubKey = await octokit.actions.getRepoPublicKey({ + owner: "ubq-testing", + repo: "telegram--bot", + }); + + const key = pubKey.data.key; + const encryptedSecret = await this.encryptSecret(secret, key); + + await octokit.actions.createOrUpdateRepoSecret({ + owner: "ubq-testing", + repo: "telegram--bot", + secret_name: "TELEGRAM_BOT_ENV", + encrypted_value: encryptedSecret, + key_id: pubKey.data.key_id, + }); + logger.ok("Secret stored successfully"); + } catch (err) { + logger.error("Error storing secret", { err }); } + exit(); + } + + async encryptSecret(secret: string, key: string /* Base64 */) { + await sodium.ready; + // Convert the secret and key to a Uint8Array. + const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL); + const binsec = sodium.from_string(secret); + + // Encrypt the secret using libsodium + const encBytes = sodium.crypto_box_seal(binsec, binkey); + + // Convert the encrypted Uint8Array to Base64 + return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL); + } } async function guided() { - const setup = new SetUpHandler(); - await setup.run(); + const setup = new SetUpHandler(); + await setup.run(); } async function manual() { - const setup = new SetUpHandler(); - await setup.manual(); + const setup = new SetUpHandler(); + await setup.manual(); } if (process.argv.includes("--manual")) { - manual().catch(logger.error); + manual().catch(logger.error); } else { - guided().catch(logger.error); -} \ No newline at end of file + guided().catch(logger.error); +} diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts index 33f8b74..953d23d 100644 --- a/src/handlers/repository-dispatch.ts +++ b/src/handlers/repository-dispatch.ts @@ -25,7 +25,7 @@ export async function repositoryDispatch(context: Context, workflow: string) { const { env: { - telegramBotEnv: { + TELEGRAM_BOT_ENV: { ubiquityOsSettings: { APP_ID, APP_PRIVATE_KEY }, }, }, diff --git a/src/server/index.ts b/src/server/index.ts index 93325dd..b0405e6 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -62,7 +62,7 @@ export function createServer(dependencies: Dependencies) { server.post( "/webhook", webhookCallback(bot, "hono", { - secretToken: config.telegramBotEnv.botSettings.TELEGRAM_BOT_WEBHOOK_SECRET, + secretToken: config.TELEGRAM_BOT_ENV.botSettings.TELEGRAM_BOT_WEBHOOK_SECRET, }) ); diff --git a/src/types/env.ts b/src/types/env.ts index ce47ec7..e2309b9 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -83,7 +83,7 @@ const storageSettings = T.Object({ SUPABASE_SERVICE_KEY: T.String(), }); -const telegramBotEnv = T.Object({ +const TELEGRAM_BOT_ENV = T.Object({ botSettings, mtProtoSettings, ubiquityOsSettings, @@ -91,10 +91,10 @@ const telegramBotEnv = T.Object({ }); export const env = T.Object({ - telegramBotEnv: T.Transform(T.Union([T.String(), telegramBotEnv])) + TELEGRAM_BOT_ENV: T.Transform(T.Union([T.String(), TELEGRAM_BOT_ENV])) .Decode((str) => { if (typeof str === "string") { - const obj = JSON.parse(str) as StaticDecode; + const obj = JSON.parse(str) as StaticDecode; if (!obj.botSettings || !obj.mtProtoSettings || !obj.ubiquityOsSettings || !obj.storageSettings) { throw new Error("Missing required environment variables for Telegram Bot settings"); diff --git a/src/types/plugin-context-single.ts b/src/types/plugin-context-single.ts index ad1a955..040f0fc 100644 --- a/src/types/plugin-context-single.ts +++ b/src/types/plugin-context-single.ts @@ -54,7 +54,7 @@ export class PluginContext { adapters: {} as ReturnType, }; - const { storageSettings } = ctx.env.telegramBotEnv; + const { storageSettings } = ctx.env.TELEGRAM_BOT_ENV; ctx.adapters = createAdapters(createClient(storageSettings.SUPABASE_URL, storageSettings.SUPABASE_SERVICE_KEY)); diff --git a/src/types/telegram-bot-single.ts b/src/types/telegram-bot-single.ts index 0cb0ec0..6de3625 100644 --- a/src/types/telegram-bot-single.ts +++ b/src/types/telegram-bot-single.ts @@ -15,7 +15,7 @@ export class TelegramBotSingleton { static async initialize(env: Env): Promise { const { - telegramBotEnv: { + TELEGRAM_BOT_ENV: { botSettings: { TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_WEBHOOK, ALLOWED_UPDATES }, }, } = env; @@ -29,7 +29,7 @@ export class TelegramBotSingleton { await TelegramBotSingleton._bot.api.setWebhook(TELEGRAM_BOT_WEBHOOK, { allowed_updates: ALLOWED_UPDATES, drop_pending_updates: true, - secret_token: env.telegramBotEnv.botSettings.TELEGRAM_BOT_WEBHOOK_SECRET, + secret_token: env.TELEGRAM_BOT_ENV.botSettings.TELEGRAM_BOT_WEBHOOK_SECRET, }); TelegramBotSingleton._server = createServer({ diff --git a/yarn.lock b/yarn.lock index acd05ee..34e47aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6718,6 +6718,18 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +libsodium-wrappers@^0.7.15: + version "0.7.15" + resolved "https://registry.yarnpkg.com/libsodium-wrappers/-/libsodium-wrappers-0.7.15.tgz#53f13e483820272a3d55b23be2e34402ac988055" + integrity sha512-E4anqJQwcfiC6+Yrl01C1m8p99wEhLmJSs0VQqST66SbQXXBoaJY0pF4BNjRYa/sOQAxx6lXAaAFIlx+15tXJQ== + dependencies: + libsodium "^0.7.15" + +libsodium@^0.7.15: + version "0.7.15" + resolved "https://registry.yarnpkg.com/libsodium/-/libsodium-0.7.15.tgz#ac284e3dcb1c29ae9526c5581cdada6a072f6d20" + integrity sha512-sZwRknt/tUpE2AwzHq3jEyUU5uvIZHtSssktXq7owd++3CSgn8RGrv6UZJJBpP7+iBghBqe7Z06/2M31rI2NKw== + lilconfig@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" From 3eb532eba68ff7210ecdd94c78b0a17f86e788fc Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 20:11:36 +0100 Subject: [PATCH 48/76] chore: mention repo admin requirement --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c6d236d..48fe453 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ You can set up your environment variables in two ways using the provided utility **Important**: Before running the setup script, ensure that you store your `GITHUB_PAT_TOKEN` in the `.env` file. This token will be used to create repository secrets and will be deleted after the script runs. - **GITHUB_PAT_TOKEN**: Create a classic personal access token (PAT) with the `repo` scope. Set the expiry to 24 hours, and save it in your `.env` file. This token will be used to generate repository secrets for the environment variables. +- **Account Permission**: The account in which the PAT is associated with *must* be an `admin` of the repository to be able to save secrets this way. Visit your repository settings `telegram-bot` > `Collaborators & teams` to add the account as an admin first if needed. The environment variables are stored in the following locations: From 45afc7b8c93e07b4c5184703385e00f304fe6deb Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 21:26:01 +0100 Subject: [PATCH 49/76] chore: fixing up the env setup --- .dev.vars.example | 14 +- .env.example | 1 - README.md | 4 +- .../bot/scripts/sms-auth/auth-handler.ts | 2 +- .../bot/scripts/sms-auth/setup-env.ts | 530 ++++++++++-------- .../bot/scripts/sms-auth/sms-auth.ts | 3 +- 6 files changed, 290 insertions(+), 264 deletions(-) delete mode 100644 .env.example diff --git a/.dev.vars.example b/.dev.vars.example index 0a4712f..5477001 100644 --- a/.dev.vars.example +++ b/.dev.vars.example @@ -1,13 +1 @@ -BOT_TOKEN=123:xyz -BOT_WEBHOOK=... -BOT_WEBHOOK_SECRET=... -BOT_ADMINS=[1234,5678] - -SUPABASE_URL=... -SUPABASE_SERVICE_KEY=... - -TELEGRAM_APP_ID=12345678 -TELEGRAM_API_HASH=... - -APP_PRIVATE_KEY=... -APP_ID=123456 \ No newline at end of file +TELEGRAM_BOT_ENV= \ No newline at end of file diff --git a/.env.example b/.env.example deleted file mode 100644 index e49d79a..0000000 --- a/.env.example +++ /dev/null @@ -1 +0,0 @@ -MY_SECRET="MY_SECRET" diff --git a/README.md b/README.md index 48fe453..10696a0 100644 --- a/README.md +++ b/README.md @@ -72,9 +72,7 @@ You can set up your environment variables in two ways using the provided utility 1. **Guided Setup**: Run `yarn setup-env-guided`, which prompts you to enter each value via the CLI. The values will be serialized and stored both locally and in your repository secrets. 2. **Manual Setup**: Modify the values directly in the script and then run `yarn setup-env-manual` to store them locally and in your repository secrets. -**Important**: Before running the setup script, ensure that you store your `GITHUB_PAT_TOKEN` in the `.env` file. This token will be used to create repository secrets and will be deleted after the script runs. - -- **GITHUB_PAT_TOKEN**: Create a classic personal access token (PAT) with the `repo` scope. Set the expiry to 24 hours, and save it in your `.env` file. This token will be used to generate repository secrets for the environment variables. +- **GITHUB_PAT_TOKEN**: Create a classic personal access token (PAT) with the `repo` scope. Set the expiry to 24 hours. This token will be used to generate repository secrets for the environment variables and will be removed from `.env` after the secrets are saved. - **Account Permission**: The account in which the PAT is associated with *must* be an `admin` of the repository to be able to save secrets this way. Visit your repository settings `telegram-bot` > `Collaborators & teams` to add the account as an admin first if needed. The environment variables are stored in the following locations: diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts index c6bbeff..1bbeb72 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts @@ -22,7 +22,7 @@ export class AuthHandler { constructor() { const env = process.env.TELEGRAM_BOT_ENV; if (!env) { - throw new Error("Missing required environment variables for Telegram Bot"); + throw new Error("Have you ran the setup script? Try running 'yarn setup-env-guided' first."); } const parsedEnv: Context["env"]["TELEGRAM_BOT_ENV"] = JSON.parse(env); diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts index 9cf132e..9dd591b 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts @@ -2,12 +2,13 @@ import input from "input"; // @ts-expect-error no types import sodium from "libsodium-wrappers"; -import { writeFile } from "node:fs/promises"; import { Context } from "../../../../../types"; import { logger } from "#root/utils/logger.js"; -import { exit } from "node:process"; +import { exit, kill, nextTick } from "node:process"; import { Octokit } from "@octokit/rest"; import dotenv from "dotenv"; +import { writeFile } from "node:fs/promises"; +import { spawn, spawnSync } from "node:child_process"; dotenv.config(); /** * This script is used to help guide the user through setting up the environment variables. @@ -17,290 +18,331 @@ dotenv.config(); */ class SetUpHandler { - private _env: Context["env"] = { - TELEGRAM_BOT_ENV: { - botSettings: { - TELEGRAM_BOT_ADMINS: [], - TELEGRAM_BOT_TOKEN: "", - TELEGRAM_BOT_WEBHOOK: "", - TELEGRAM_BOT_WEBHOOK_SECRET: "", - }, - mtProtoSettings: { - TELEGRAM_API_HASH: "", - TELEGRAM_APP_ID: 0, - }, - storageSettings: { - SUPABASE_SERVICE_KEY: "", - SUPABASE_URL: "", - }, - ubiquityOsSettings: { - APP_ID: 0, - APP_PRIVATE_KEY: "", - }, - }, - }; - - get env() { - return this._env; - } - - set env(env: Context["env"]) { - this._env = env; - } - - steps = [ - { - title: "Bot settings", - questions: [ - { - type: "input", - name: "TELEGRAM_BOT_TOKEN", - message: "Enter your Telegram bot token. This can be obtained from @BotFather", - }, - { - type: "input", - name: "TELEGRAM_BOT_WEBHOOK", - message: "Enter your Telegram bot webhook. Cloudflare for production, ngrok/smee for development", - }, - { - type: "input", - name: "TELEGRAM_BOT_WEBHOOK_SECRET", - message: "Enter your Telegram bot webhook secret. This is used to verify incoming requests from Telegram", - }, - { - type: "input", - name: "TELEGRAM_BOT_ADMINS", - message: "Enter your Telegram bot admin IDs separated with commas. '123456789,987654321'", - }, - ], - }, - { - title: "MTProto settings", - questions: [ - { - type: "input", - name: "TELEGRAM_API_HASH", - message: "Enter your Telegram API hash. This can be obtained from 'https://my.telegram.org'", + private _env: Context["env"] = { + TELEGRAM_BOT_ENV: { + botSettings: { + TELEGRAM_BOT_ADMINS: [], + TELEGRAM_BOT_TOKEN: "", + TELEGRAM_BOT_WEBHOOK: "", + TELEGRAM_BOT_WEBHOOK_SECRET: "", + }, + mtProtoSettings: { + TELEGRAM_API_HASH: "", + TELEGRAM_APP_ID: 0, + }, + storageSettings: { + SUPABASE_SERVICE_KEY: "", + SUPABASE_URL: "", + }, + ubiquityOsSettings: { + APP_ID: 0, + APP_PRIVATE_KEY: "", + }, }, + }; + + get env() { + return this._env; + } + + set env(env: Context["env"]) { + this._env = env; + } + + steps = [ { - type: "input", - name: "TELEGRAM_APP_ID", - message: "Enter your Telegram app id. This can be obtained from 'https://my.telegram.org'", + title: "Secret upload", + questions: [ + { + type: "input", + name: "GITHUB_PAT_TOKEN", + message: "Enter your GitHub PAT token.\n This is used to store secrets in your repository so it should have the 'repo' scope and be an admin of the repository.", + }, + ], }, - ], - }, - { - title: "Storage settings", - questions: [ { - type: "input", - name: "SUPABASE_SERVICE_KEY", - message: "Enter your Supabase service key (read/write access)", + title: "Bot settings", + questions: [ + { + type: "input", + name: "TELEGRAM_BOT_TOKEN", + message: "Enter your Telegram bot token. This can be obtained from @BotFather", + }, + { + type: "input", + name: "TELEGRAM_BOT_WEBHOOK", + message: "Enter your Telegram bot webhook. Cloudflare for production, ngrok/smee for development", + }, + { + type: "input", + name: "TELEGRAM_BOT_WEBHOOK_SECRET", + message: "Enter your Telegram bot webhook secret. This is used to verify incoming requests from Telegram", + }, + { + type: "input", + name: "TELEGRAM_BOT_ADMINS", + message: "Enter your Telegram bot admin IDs separated with commas. '123456789,987654321'", + }, + ], }, { - type: "input", - name: "SUPABASE_URL", - message: "Enter your Supabase URL (https://.supabase.co)", + title: "MTProto settings", + questions: [ + { + type: "input", + name: "TELEGRAM_API_HASH", + message: "Enter your Telegram API hash. This can be obtained from 'https://my.telegram.org'", + }, + { + type: "input", + name: "TELEGRAM_APP_ID", + message: "Enter your Telegram app id. This can be obtained from 'https://my.telegram.org'", + }, + ], }, - ], - }, - { - title: "Ubiquity OS settings", - questions: [ { - type: "input", - name: "APP_ID", - message: "Enter your Ubiquity OS app id. This can be obtained from 'https://github.com/settings/apps'", + title: "Storage settings", + questions: [ + { + type: "input", + name: "SUPABASE_SERVICE_KEY", + message: "Enter your Supabase service key (read/write access)", + }, + { + type: "input", + name: "SUPABASE_URL", + message: "Enter your Supabase URL (https://.supabase.co)", + }, + ], }, { - type: "input", - name: "APP_PRIVATE_KEY", - message: "Enter your Ubiquity OS private key. This can be obtained from 'https://github.com/settings/apps'", + title: "Ubiquity OS settings", + questions: [ + { + type: "input", + name: "APP_ID", + message: "Enter your Ubiquity OS app id. This can be obtained from your kernel env vars.", + }, + { + type: "input", + name: "APP_PRIVATE_KEY", + message: "Enter your Ubiquity OS private key. This can be obtained from your kernel env vars.", + }, + ], }, - ], - }, - ]; - - async run() { - if (!process.env.GITHUB_PAT_TOKEN) { - logger.fatal("GITHUB_PAT_TOKEN is not set in the environment variables"); - exit(); - } - const answers: Record> = {}; - for (const step of this.steps) { - console.log(step.title); - const questions = step.questions; - - for (const question of questions) { - const answer = await input.text(question.message); - console.log("Answer:", answer); - answers[step.title] ??= {}; - if (question.name === "TELEGRAM_BOT_ADMINS") { - answers[step.title][question.name] = JSON.stringify(answer.split(",").map((id: string) => Number(id))); - continue; + ]; + + async run() { + const answers: Record> = {}; + for (const step of this.steps) { + const questions = step.questions; + + for (const question of questions) { + if (question.name === "GITHUB_PAT_TOKEN" && await this.testAccessToken()) { + continue; + } + console.log(step.title); + const answer = await input.text(` ${question.message}\n> `); + if (question.name === "GITHUB_PAT_TOKEN") { + await writeFile(".env", `GITHUB_PAT_TOKEN=${answer}`, "utf-8"); + logger.ok("GitHub PAT token saved successfully, we must restart the script to continue."); + process.exit(0); + } + + answers[step.title] ??= {}; + + if (question.name === "TELEGRAM_BOT_ADMINS") { + answers[step.title][question.name] = JSON.stringify(answer.split(",").map((id: string) => Number(id))); + continue; + } + answers[step.title][question.name] = answer; + } } - answers[step.title][question.name] = answer; - } + console.clear(); + + this.env = { + TELEGRAM_BOT_ENV: { + botSettings: { + TELEGRAM_BOT_ADMINS: JSON.parse(answers["Bot settings"]["TELEGRAM_BOT_ADMINS"]), + TELEGRAM_BOT_TOKEN: answers["Bot settings"]["TELEGRAM_BOT_TOKEN"], + TELEGRAM_BOT_WEBHOOK: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK"], + TELEGRAM_BOT_WEBHOOK_SECRET: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK_SECRET"], + }, + mtProtoSettings: { + TELEGRAM_API_HASH: answers["MTProto settings"]["TELEGRAM_API_HASH"], + TELEGRAM_APP_ID: Number(answers["MTProto settings"]["TELEGRAM_APP_ID"]), + }, + storageSettings: { + SUPABASE_SERVICE_KEY: answers["Storage settings"]["SUPABASE_SERVICE_KEY"], + SUPABASE_URL: answers["Storage settings"]["SUPABASE_URL"], + }, + ubiquityOsSettings: { + APP_ID: Number(answers["Ubiquity OS settings"]["APP_ID"]), + APP_PRIVATE_KEY: answers["Ubiquity OS settings"]["APP_PRIVATE_KEY"], + }, + }, + }; + + await this.validateEnv(); } - console.clear(); - - this.env = { - TELEGRAM_BOT_ENV: { - botSettings: { - TELEGRAM_BOT_ADMINS: JSON.parse(answers["Bot settings"]["TELEGRAM_BOT_ADMINS"]), - TELEGRAM_BOT_TOKEN: answers["Bot settings"]["TELEGRAM_BOT_TOKEN"], - TELEGRAM_BOT_WEBHOOK: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK"], - TELEGRAM_BOT_WEBHOOK_SECRET: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK_SECRET"], - }, - mtProtoSettings: { - TELEGRAM_API_HASH: answers["MTProto settings"]["TELEGRAM_API_HASH"], - TELEGRAM_APP_ID: Number(answers["MTProto settings"]["TELEGRAM_APP_ID"]), - }, - storageSettings: { - SUPABASE_SERVICE_KEY: answers["Storage settings"]["SUPABASE_SERVICE_KEY"], - SUPABASE_URL: answers["Storage settings"]["SUPABASE_URL"], - }, - ubiquityOsSettings: { - APP_ID: Number(answers["Ubiquity OS settings"]["APP_ID"]), - APP_PRIVATE_KEY: answers["Ubiquity OS settings"]["APP_PRIVATE_KEY"], - }, - }, - }; + /** + * Manually set the env variables below and run `yarn setup-env-manual` + */ + async manual() { + this.env = { + TELEGRAM_BOT_ENV: { + botSettings: { + TELEGRAM_BOT_ADMINS: [], + TELEGRAM_BOT_TOKEN: "", + TELEGRAM_BOT_WEBHOOK: "", + TELEGRAM_BOT_WEBHOOK_SECRET: "", + }, + mtProtoSettings: { + TELEGRAM_API_HASH: "", + TELEGRAM_APP_ID: 0, + }, + storageSettings: { + SUPABASE_SERVICE_KEY: "", + SUPABASE_URL: "", + }, + ubiquityOsSettings: { + APP_ID: 0, + APP_PRIVATE_KEY: "", + }, + }, + }; + + await this.saveEnv(); + } - await this.validateEnv(); - } - - /** - * Manually set the env variables below and run `yarn setup-env-manual` - */ - async manual() { - this.env = { - TELEGRAM_BOT_ENV: { - botSettings: { - TELEGRAM_BOT_ADMINS: [], - TELEGRAM_BOT_TOKEN: "", - TELEGRAM_BOT_WEBHOOK: "", - TELEGRAM_BOT_WEBHOOK_SECRET: "", - }, - mtProtoSettings: { - TELEGRAM_API_HASH: "", - TELEGRAM_APP_ID: 0, - }, - storageSettings: { - SUPABASE_SERVICE_KEY: "", - SUPABASE_URL: "", - }, - ubiquityOsSettings: { - APP_ID: 0, - APP_PRIVATE_KEY: "", - }, - }, - }; + async validateEnv() { + const env = this.env.TELEGRAM_BOT_ENV; + const { botSettings, mtProtoSettings, storageSettings, ubiquityOsSettings } = env; - await this.saveEnv(); - } + const merged = { + ...botSettings, + ...mtProtoSettings, + ...storageSettings, + ...ubiquityOsSettings, + }; - async validateEnv() { - const env = this.env.TELEGRAM_BOT_ENV; - const { botSettings, mtProtoSettings, storageSettings, ubiquityOsSettings } = env; + const keys = Object.keys(merged); - const merged = { - ...botSettings, - ...mtProtoSettings, - ...storageSettings, - ...ubiquityOsSettings, - }; + const missing = []; - const keys = Object.keys(merged); + for (const key_ of keys) { + const key = key_ as keyof typeof merged; + if (!merged[key]) { + missing.push(key); + } + } - const missing = []; + if (missing.length) { + console.log("Missing keys:", missing); + await this.run(); + } + await this.saveEnv(); - for (const key_ of keys) { - const key = key_ as keyof typeof merged; - if (!merged[key]) { - missing.push(key); - } - } + logger.ok("Env saved successfully"); - if (missing.length) { - console.log("Missing keys:", missing); - await this.run(); + exit(); } - await this.saveEnv(); - logger.ok("Env saved successfully"); + async saveEnv() { + const paths = [".env", ".dev.vars"]; - exit(); - } + const envVar = `TELEGRAM_BOT_ENV=${JSON.stringify(this.env.TELEGRAM_BOT_ENV)}`; - async saveEnv() { - const paths = [".env", ".dev.vars"]; + for (const path of paths) { + await writeFile(path, envVar, "utf-8"); + } - const envVar = `TELEGRAM_BOT_ENV=${JSON.stringify(this.env.TELEGRAM_BOT_ENV)}`; + logger.ok("Local env files saved successfully"); + logger.info("Storing secrets in GitHub"); + await this.storeRepoSecrets(); + } - for (const path of paths) { - await writeFile(path, envVar, "utf-8"); + async testAccessToken() { + const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); + const secret = `---`; + + try { + const pubKey = await octokit.actions.getRepoPublicKey({ + owner: "ubq-testing", + repo: "telegram--bot", + }); + + const key = pubKey.data.key; + const encryptedSecret = await this.encryptSecret(secret, key); + + await octokit.actions.createOrUpdateRepoSecret({ + owner: "ubq-testing", + repo: "telegram--bot", + secret_name: "TELEGRAM_BOT_ENV", + encrypted_value: encryptedSecret, + key_id: pubKey.data.key_id, + }); + + return true + } catch (err) { + return false + } } - logger.ok("Local env files saved successfully"); - logger.info("Storing secrets in GitHub"); - await this.storeRepoSecrets(); - } - - async storeRepoSecrets() { - const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); - const secret = `${JSON.stringify(this.env.TELEGRAM_BOT_ENV)}`; - - try { - const pubKey = await octokit.actions.getRepoPublicKey({ - owner: "ubq-testing", - repo: "telegram--bot", - }); - - const key = pubKey.data.key; - const encryptedSecret = await this.encryptSecret(secret, key); - - await octokit.actions.createOrUpdateRepoSecret({ - owner: "ubq-testing", - repo: "telegram--bot", - secret_name: "TELEGRAM_BOT_ENV", - encrypted_value: encryptedSecret, - key_id: pubKey.data.key_id, - }); - logger.ok("Secret stored successfully"); - } catch (err) { - logger.error("Error storing secret", { err }); + async storeRepoSecrets() { + const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); + const secret = `${JSON.stringify(this.env.TELEGRAM_BOT_ENV)}`; + + try { + const pubKey = await octokit.actions.getRepoPublicKey({ + owner: "ubq-testing", + repo: "telegram--bot", + }); + + const key = pubKey.data.key; + const encryptedSecret = await this.encryptSecret(secret, key); + + await octokit.actions.createOrUpdateRepoSecret({ + owner: "ubq-testing", + repo: "telegram--bot", + secret_name: "TELEGRAM_BOT_ENV", + encrypted_value: encryptedSecret, + key_id: pubKey.data.key_id, + }); + logger.ok("Secret stored successfully"); + } catch (err) { + logger.error("Error storing secret", { err }); + } + exit(); } - exit(); - } - async encryptSecret(secret: string, key: string /* Base64 */) { - await sodium.ready; - // Convert the secret and key to a Uint8Array. - const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL); - const binsec = sodium.from_string(secret); + async encryptSecret(secret: string, key: string /* Base64 */) { + await sodium.ready; + // Convert the secret and key to a Uint8Array. + const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL); + const binsec = sodium.from_string(secret); - // Encrypt the secret using libsodium - const encBytes = sodium.crypto_box_seal(binsec, binkey); + // Encrypt the secret using libsodium + const encBytes = sodium.crypto_box_seal(binsec, binkey); - // Convert the encrypted Uint8Array to Base64 - return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL); - } + // Convert the encrypted Uint8Array to Base64 + return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL); + } } async function guided() { - const setup = new SetUpHandler(); - await setup.run(); + const setup = new SetUpHandler(); + await setup.run(); } async function manual() { - const setup = new SetUpHandler(); - await setup.manual(); + const setup = new SetUpHandler(); + await setup.manual(); } if (process.argv.includes("--manual")) { - manual().catch(logger.error); + manual().catch(console.error); } else { - guided().catch(logger.error); + guided().catch(console.error); } diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts index d2a4e25..67ea7a8 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts @@ -1,4 +1,3 @@ -import { logger } from "#root/utils/logger.js"; import { AuthHandler } from "./auth-handler"; import dotenv from "dotenv"; dotenv.config(); @@ -11,4 +10,4 @@ async function main() { await authHandler.smsLogin(); } -main().catch(logger.error); +main().catch(console.error); From f7db10be3ff730a3e9cb8cef8a8dfc7fd1200d76 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 21:45:21 +0100 Subject: [PATCH 50/76] chore: replace logger in sms-auth --- src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts index 1bbeb72..60fb087 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts @@ -88,7 +88,7 @@ export class AuthHandler { phoneNumber: async () => await input.text("Enter your phone number:"), password: async () => await input.password("Enter your password if required:"), phoneCode: async () => await input.text("Enter the code you received:"), - onError: (err: unknown) => logger.error("Error during login:", { err }), + onError: (err: unknown) => console.error("Error during login:", { err }), }); const data = await this._supabase?.from("tg-bot-sessions").insert([{ session_data: mtProto.session?.save() }]); From 7dbf0acc4fb421ecade0e2b6733b4bc42c876e1d Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 21:49:55 +0100 Subject: [PATCH 51/76] chore: update-branch --- src/handlers/repository-dispatch.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts index 953d23d..99c034c 100644 --- a/src/handlers/repository-dispatch.ts +++ b/src/handlers/repository-dispatch.ts @@ -21,7 +21,7 @@ export async function repositoryDispatch(context: Context, workflow: string) { */ const repository = "telegram--bot"; const owner = "ubq-testing"; - const branch = "workflows"; + const branch = "workflows-test"; const { env: { From 590a54a86ee6039f380b18ae0403d52005bf23a8 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 22:04:21 +0100 Subject: [PATCH 52/76] chore: correct workflow payload env --- src/workflow-entry.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/workflow-entry.ts b/src/workflow-entry.ts index 7be6307..28410d4 100644 --- a/src/workflow-entry.ts +++ b/src/workflow-entry.ts @@ -18,19 +18,7 @@ export async function run() { let env, settings; const payloadEnv = { - BOT_TOKEN: process.env.BOT_TOKEN, - BOT_MODE: process.env.BOT_MODE, - LOG_LEVEL: process.env.LOG_LEVEL, - DEBUG: process.env.DEBUG, - BOT_WEBHOOK: process.env.BOT_WEBHOOK, - BOT_WEBHOOK_SECRET: process.env.BOT_WEBHOOK_SECRET, - BOT_ADMINS: process.env.BOT_ADMINS, - TELEGRAM_APP_ID: process.env.TELEGRAM_APP_ID, - TELEGRAM_API_HASH: process.env.TELEGRAM_API_HASH, - SUPABASE_URL: process.env.SUPABASE_URL, - SUPABASE_SERVICE_KEY: process.env.SUPABASE_SERVICE_KEY, - APP_PRIVATE_KEY: process.env.APP_PRIVATE_KEY, - APP_ID: process.env.APP_ID, + TELEGRAM_BOT_ENV: process.env.TELEGRAM_BOT_ENV, }; try { From 99ac8cc4ec0db607c6b673cb0ef0cad69352c3af Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 22:29:25 +0100 Subject: [PATCH 53/76] chore: leftover db refactoring --- src/adapters/supabase/helpers/chats.ts | 4 ++-- src/bot/mtproto-api/bot/mtproto.ts | 1 + .../mtproto-api/bot/scripts/sms-auth/base-mtproto.ts | 2 ++ .../mtproto-api/bot/scripts/sms-auth/setup-env.ts | 1 - src/bot/mtproto-api/workrooms/close-chat.ts | 11 ++++++----- src/bot/mtproto-api/workrooms/create-chat.ts | 2 +- src/bot/mtproto-api/workrooms/reopen-chat.ts | 12 ++++++------ supabase/migrations.sql | 1 + 8 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/adapters/supabase/helpers/chats.ts b/src/adapters/supabase/helpers/chats.ts index 36e39f0..abe3584 100644 --- a/src/adapters/supabase/helpers/chats.ts +++ b/src/adapters/supabase/helpers/chats.ts @@ -22,7 +22,7 @@ export class Chats extends Super { */ async userSnapshot(chatId: number, userIds: number[]) { const chat = await this.getChatByChatId(chatId); - const { error } = await this.supabase.from("chats").upsert({ ...chat, user_ids: userIds }); + const { error } = await this.supabase.from("chats").update({ user_ids: userIds }).eq("chat_id", chat.chat_id); if (error) { this.logger.error("Failed to save chat users", { chatId, userIds, er: error }); } else { @@ -63,7 +63,7 @@ export class Chats extends Super { return; } - const { error } = await this.supabase.from("chats").upsert({ ...chat, status }); + const { error } = await this.supabase.from("chats").update({ status }).eq("chat_id", chat.chat_id); if (error) { this.logger.error("Failed to update chat status", { chatId, taskNodeId, er: error }); diff --git a/src/bot/mtproto-api/bot/mtproto.ts b/src/bot/mtproto-api/bot/mtproto.ts index dcfabf5..f3b4d2e 100644 --- a/src/bot/mtproto-api/bot/mtproto.ts +++ b/src/bot/mtproto-api/bot/mtproto.ts @@ -5,6 +5,7 @@ import { SupabaseSession } from "./session"; import { createClient, SupabaseClient } from "@supabase/supabase-js"; dotenv.config(); + /** * This class MUST ONLY be used in the context of workflow-functions as * it requires a Node.js environment which is not available with Cloudflare Workers. diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts index 4e5e80a..780859f 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts @@ -6,6 +6,8 @@ import { StringSession } from "telegram/sessions"; import { Context } from "#root/types/context.js"; dotenv.config(); + + /** * @dev Not abstract because we need it to be instantiated for sms-auth * diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts index 9dd591b..95af500 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts @@ -8,7 +8,6 @@ import { exit, kill, nextTick } from "node:process"; import { Octokit } from "@octokit/rest"; import dotenv from "dotenv"; import { writeFile } from "node:fs/promises"; -import { spawn, spawnSync } from "node:child_process"; dotenv.config(); /** * This script is used to help guide the user through setting up the environment variables. diff --git a/src/bot/mtproto-api/workrooms/close-chat.ts b/src/bot/mtproto-api/workrooms/close-chat.ts index 3b6c9d4..bbed4fd 100644 --- a/src/bot/mtproto-api/workrooms/close-chat.ts +++ b/src/bot/mtproto-api/workrooms/close-chat.ts @@ -18,9 +18,10 @@ export async function closeChat(context: Context<"issues.closed", SupportedEvent logger.info("Closing chat with name: ", { chatName: payload.issue.title }); const chat = await chats.getChatByTaskNodeId(payload.issue.node_id); + await mtProto.client.getDialogs(); const fetchedChat = await mtProto.client.invoke( new mtProto.api.messages.GetFullChat({ - chatId: chat.chatId, + chatId: chat.chat_id, }) ); @@ -41,7 +42,7 @@ export async function closeChat(context: Context<"issues.closed", SupportedEvent new mtProto.api.folders.EditPeerFolders({ folderPeers: [ new mtProto.api.InputFolderPeer({ - peer: new mtProto.api.InputPeerChat({ chatId: chat.chatId }), + peer: new mtProto.api.InputPeerChat({ chatId: chat.chat_id }), folderId: 1, // 0 is active, 1 is archived }), ], @@ -52,7 +53,7 @@ export async function closeChat(context: Context<"issues.closed", SupportedEvent await mtProto.client.invoke( new mtProto.api.messages.SendMessage({ message: "This task has been closed and this chat has been archived.", - peer: new mtProto.api.InputPeerChat({ chatId: chat.chatId }), + peer: new mtProto.api.InputPeerChat({ chatId: chat.chat_id }), }) ); @@ -74,10 +75,10 @@ export async function closeChat(context: Context<"issues.closed", SupportedEvent } userIds.push(creatorId); - const chatInput = await mtProto.client.getInputEntity(chat.chatId); + const chatInput = await mtProto.client.getInputEntity(chat.chat_id); await chats.userSnapshot( - chat.chatId, + chat.chat_id, userIds.map((id) => id.toJSNumber()) ); diff --git a/src/bot/mtproto-api/workrooms/create-chat.ts b/src/bot/mtproto-api/workrooms/create-chat.ts index 0b3f31a..20761b2 100644 --- a/src/bot/mtproto-api/workrooms/create-chat.ts +++ b/src/bot/mtproto-api/workrooms/create-chat.ts @@ -21,8 +21,8 @@ export async function createChat(context: Context<"issues.labeled", SupportedEve logger.info("Creating chat with name: ", { chatName }); try { + await mtProto.client.getDialogs(); const botIdString = await mtProto.client.getPeerId(config.botId, true); - const chat = await mtProto.client.invoke( new mtProto.api.messages.CreateChat({ title: chatName, diff --git a/src/bot/mtproto-api/workrooms/reopen-chat.ts b/src/bot/mtproto-api/workrooms/reopen-chat.ts index 98c159c..e7c6b98 100644 --- a/src/bot/mtproto-api/workrooms/reopen-chat.ts +++ b/src/bot/mtproto-api/workrooms/reopen-chat.ts @@ -20,7 +20,7 @@ export async function reopenChat(context: Context<"issues.reopened", SupportedEv const fetchedChat = await mtProto.client.invoke( new mtProto.api.messages.GetFullChat({ - chatId: chat.chatId, + chatId: chat.chat_id, }) ); @@ -33,7 +33,7 @@ export async function reopenChat(context: Context<"issues.reopened", SupportedEv new mtProto.api.folders.EditPeerFolders({ folderPeers: [ new mtProto.api.InputFolderPeer({ - peer: new mtProto.api.InputPeerChat({ chatId: chat.chatId }), + peer: new mtProto.api.InputPeerChat({ chatId: chat.chat_id }), folderId: 0, }), ], @@ -51,20 +51,20 @@ export async function reopenChat(context: Context<"issues.reopened", SupportedEv // add the creator back to obtain control of the chat await mtProto.client.invoke( new mtProto.api.messages.AddChatUser({ - chatId: chat.chatId, + chatId: chat.chat_id, userId: chatCreator, fwdLimit: 50, }) ); await chats.updateChatStatus("reopened", payload.issue.node_id); - const users = await chats.getChatUsers(chat.chatId); + const users = await chats.getChatUsers(chat.chat_id); if (!users) { throw new Error("Failed to get chat users"); } const { user_ids: userIds } = users; - const chatInput = await mtProto.client.getInputEntity(chat.chatId); + const chatInput = await mtProto.client.getInputEntity(chat.chat_id); for (const userId of userIds) { /** @@ -96,7 +96,7 @@ export async function reopenChat(context: Context<"issues.reopened", SupportedEv await mtProto.client.invoke( new mtProto.api.messages.SendMessage({ message: "This task has been reopened and this chat has been unarchived.", - peer: new mtProto.api.InputPeerChat({ chatId: chat.chatId }), + peer: new mtProto.api.InputPeerChat({ chatId: chat.chat_id }), }) ); return { status: 200, reason: "chat_reopened" }; diff --git a/supabase/migrations.sql b/supabase/migrations.sql index f8788e8..8da68c5 100644 --- a/supabase/migrations.sql +++ b/supabase/migrations.sql @@ -3,6 +3,7 @@ CREATE TABLE IF NOT EXISTS "chats" ( created_at TIMESTAMPTZ DEFAULT now(), updated_at TIMESTAMPTZ DEFAULT now(), chat_id BIGINT NOT NULL, + chat_name TEXT NOT NULL, task_node_id TEXT UNIQUE NOT NULL, status TEXT NOT NULL CHECK (status IN ('open', 'closed', 'reopened')), user_ids BIGINT[] From 14edbaf4579e22295856bf369be7232f46cb9e4a Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 23:16:48 +0100 Subject: [PATCH 54/76] chore: remove manual, capture repo during setup --- README.md | 7 +- package.json | 3 +- src/adapters/supabase/helpers/user.ts | 18 - src/bot/features/commands/shared/wallet.ts | 28 - src/bot/mtproto-api/bot/mtproto.ts | 1 - .../bot/scripts/sms-auth/base-mtproto.ts | 2 - .../bot/scripts/sms-auth/setup-env.ts | 584 +++++++++--------- src/handlers/repository-dispatch.ts | 20 +- src/types/env.ts | 1 + 9 files changed, 309 insertions(+), 355 deletions(-) delete mode 100644 src/bot/features/commands/shared/wallet.ts diff --git a/README.md b/README.md index 10696a0..74fc7ff 100644 --- a/README.md +++ b/README.md @@ -67,13 +67,12 @@ This bot operates in two parts: The `TELEGRAM_BOT_ENV` is a single JSON object that encapsulates all necessary environment variables for the bot's operation. It consists of four key sections: `botSettings`, `mtProtoSettings`, `storageSettings`, and `ubiquityOsSettings`. -You can set up your environment variables in two ways using the provided utility script: +You can set up your environment variables by using the provided utility script: -1. **Guided Setup**: Run `yarn setup-env-guided`, which prompts you to enter each value via the CLI. The values will be serialized and stored both locally and in your repository secrets. -2. **Manual Setup**: Modify the values directly in the script and then run `yarn setup-env-manual` to store them locally and in your repository secrets. +- Run `yarn setup-env-guided`, which prompts you to enter each value via the CLI. The values will be serialized and stored both locally and in your repository secrets. - **GITHUB_PAT_TOKEN**: Create a classic personal access token (PAT) with the `repo` scope. Set the expiry to 24 hours. This token will be used to generate repository secrets for the environment variables and will be removed from `.env` after the secrets are saved. -- **Account Permission**: The account in which the PAT is associated with *must* be an `admin` of the repository to be able to save secrets this way. Visit your repository settings `telegram-bot` > `Collaborators & teams` to add the account as an admin first if needed. +- **Account Permission**: The account in which the PAT is associated with _must_ be an `admin` of the repository to be able to save secrets this way. Visit your repository settings `telegram-bot` > `Collaborators & teams` to add the account as an admin first if needed. The environment variables are stored in the following locations: diff --git a/package.json b/package.json index b9755ec..1f0b4c2 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,7 @@ "start": "tsx ./src/main.ts", "deploy": "wrangler deploy --minify src/main.ts", "sms-auth": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts", - "setup-env-guided": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts", - "setup-env-manual": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts --manual" + "setup-env-guided": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts" }, "keywords": [ "typescript", diff --git a/src/adapters/supabase/helpers/user.ts b/src/adapters/supabase/helpers/user.ts index 16574c1..e3dae3a 100644 --- a/src/adapters/supabase/helpers/user.ts +++ b/src/adapters/supabase/helpers/user.ts @@ -1,6 +1,5 @@ import { SupabaseClient } from "@supabase/supabase-js"; import { Super } from "./supabase"; -import { PluginContext } from "#root/types/plugin-context-single.js"; type Wallet = { address: string; @@ -21,21 +20,4 @@ export class User extends Super { return data?.wallets?.address || null; } - - async getWalletByGitHubUsername(username: string) { - const ctx = PluginContext.getInstance().getContext(); - const { octokit } = ctx; - const githubUserId = (await octokit.rest.users.getByUsername({ username })).data.id; - const { data, error } = (await this.supabase.from("users").select("wallets(*)").eq("id", githubUserId).single()) as { - data: { wallets: Wallet }; - error: unknown; - }; - if ((error && !data) || !data.wallets?.address) { - this.logger.error("No wallet address found", { githubUserId }); - } else { - this.logger.info("Successfully fetched wallet", { githubUserId, address: data.wallets?.address }); - } - - return data?.wallets?.address || null; - } } diff --git a/src/bot/features/commands/shared/wallet.ts b/src/bot/features/commands/shared/wallet.ts deleted file mode 100644 index 67fe5ba..0000000 --- a/src/bot/features/commands/shared/wallet.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { chatAction } from "@grammyjs/auto-chat-action"; -import { Composer } from "grammy"; -import type { Context } from "#root/bot/helpers/grammy-context.js"; -import { logHandle } from "#root/bot/helpers/logging.js"; - -const composer = new Composer(); - -const feature = composer.chatType(["group", "private"]); - -feature.command("/wallet", logHandle("command-wallet"), chatAction("typing"), async (ctx) => { - const { message } = ctx; - - // username is after the command - const username = message.text.split(" ")[1]; - if (!username) { - return ctx.reply("You must provide a GitHub username."); - } - - // get wallet by username - const wallet = await ctx.adapters.supabase.user.getWalletByGitHubUsername(username); - if (!wallet) { - return ctx.reply("I can't find a wallet for that GitHub username."); - } - - return ctx.reply(`The wallet for ${username} is ${wallet}`); -}); - -export { composer as userIdFeature }; diff --git a/src/bot/mtproto-api/bot/mtproto.ts b/src/bot/mtproto-api/bot/mtproto.ts index f3b4d2e..dcfabf5 100644 --- a/src/bot/mtproto-api/bot/mtproto.ts +++ b/src/bot/mtproto-api/bot/mtproto.ts @@ -5,7 +5,6 @@ import { SupabaseSession } from "./session"; import { createClient, SupabaseClient } from "@supabase/supabase-js"; dotenv.config(); - /** * This class MUST ONLY be used in the context of workflow-functions as * it requires a Node.js environment which is not available with Cloudflare Workers. diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts index 780859f..4e5e80a 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts @@ -6,8 +6,6 @@ import { StringSession } from "telegram/sessions"; import { Context } from "#root/types/context.js"; dotenv.config(); - - /** * @dev Not abstract because we need it to be instantiated for sms-auth * diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts index 95af500..b7a6b2f 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts @@ -4,10 +4,10 @@ import input from "input"; import sodium from "libsodium-wrappers"; import { Context } from "../../../../../types"; import { logger } from "#root/utils/logger.js"; -import { exit, kill, nextTick } from "node:process"; +import { exit } from "node:process"; import { Octokit } from "@octokit/rest"; import dotenv from "dotenv"; -import { writeFile } from "node:fs/promises"; +import { appendFile, writeFile } from "node:fs/promises"; dotenv.config(); /** * This script is used to help guide the user through setting up the environment variables. @@ -17,331 +17,337 @@ dotenv.config(); */ class SetUpHandler { - private _env: Context["env"] = { - TELEGRAM_BOT_ENV: { - botSettings: { - TELEGRAM_BOT_ADMINS: [], - TELEGRAM_BOT_TOKEN: "", - TELEGRAM_BOT_WEBHOOK: "", - TELEGRAM_BOT_WEBHOOK_SECRET: "", - }, - mtProtoSettings: { - TELEGRAM_API_HASH: "", - TELEGRAM_APP_ID: 0, - }, - storageSettings: { - SUPABASE_SERVICE_KEY: "", - SUPABASE_URL: "", - }, - ubiquityOsSettings: { - APP_ID: 0, - APP_PRIVATE_KEY: "", - }, + private _env: Context["env"] = { + TELEGRAM_BOT_ENV: { + botSettings: { + TELEGRAM_BOT_ADMINS: [], + TELEGRAM_BOT_TOKEN: "", + TELEGRAM_BOT_WEBHOOK: "", + TELEGRAM_BOT_WEBHOOK_SECRET: "", + }, + mtProtoSettings: { + TELEGRAM_API_HASH: "", + TELEGRAM_APP_ID: 0, + }, + storageSettings: { + SUPABASE_SERVICE_KEY: "", + SUPABASE_URL: "", + }, + ubiquityOsSettings: { + APP_ID: 0, + APP_PRIVATE_KEY: "", + }, + }, + }; + + get env() { + return this._env; + } + + set env(env: Context["env"]) { + this._env = env; + } + + steps = [ + { + title: "Repository settings", + questions: [ + { + type: "input", + name: "REPOSITORY", + message: "Enter your repository name (owner/repo).", }, - }; - - get env() { - return this._env; - } - - set env(env: Context["env"]) { - this._env = env; - } - - steps = [ + ], + }, + { + title: "Secret upload", + questions: [ { - title: "Secret upload", - questions: [ - { - type: "input", - name: "GITHUB_PAT_TOKEN", - message: "Enter your GitHub PAT token.\n This is used to store secrets in your repository so it should have the 'repo' scope and be an admin of the repository.", - }, - ], + type: "input", + name: "GITHUB_PAT_TOKEN", + message: + "Enter your GitHub PAT token.\n This is used to store secrets in your repository so it should have the 'repo' scope and be an admin of the repository.", }, + ], + }, + { + title: "Bot settings", + questions: [ { - title: "Bot settings", - questions: [ - { - type: "input", - name: "TELEGRAM_BOT_TOKEN", - message: "Enter your Telegram bot token. This can be obtained from @BotFather", - }, - { - type: "input", - name: "TELEGRAM_BOT_WEBHOOK", - message: "Enter your Telegram bot webhook. Cloudflare for production, ngrok/smee for development", - }, - { - type: "input", - name: "TELEGRAM_BOT_WEBHOOK_SECRET", - message: "Enter your Telegram bot webhook secret. This is used to verify incoming requests from Telegram", - }, - { - type: "input", - name: "TELEGRAM_BOT_ADMINS", - message: "Enter your Telegram bot admin IDs separated with commas. '123456789,987654321'", - }, - ], + type: "input", + name: "TELEGRAM_BOT_TOKEN", + message: "Enter your Telegram bot token. This can be obtained from @BotFather", }, { - title: "MTProto settings", - questions: [ - { - type: "input", - name: "TELEGRAM_API_HASH", - message: "Enter your Telegram API hash. This can be obtained from 'https://my.telegram.org'", - }, - { - type: "input", - name: "TELEGRAM_APP_ID", - message: "Enter your Telegram app id. This can be obtained from 'https://my.telegram.org'", - }, - ], + type: "input", + name: "TELEGRAM_BOT_WEBHOOK", + message: "Enter your Telegram bot webhook. Cloudflare for production, ngrok/smee for development", }, { - title: "Storage settings", - questions: [ - { - type: "input", - name: "SUPABASE_SERVICE_KEY", - message: "Enter your Supabase service key (read/write access)", - }, - { - type: "input", - name: "SUPABASE_URL", - message: "Enter your Supabase URL (https://.supabase.co)", - }, - ], + type: "input", + name: "TELEGRAM_BOT_WEBHOOK_SECRET", + message: "Enter your Telegram bot webhook secret. Random 12 char-min e.g '123456123456'", }, { - title: "Ubiquity OS settings", - questions: [ - { - type: "input", - name: "APP_ID", - message: "Enter your Ubiquity OS app id. This can be obtained from your kernel env vars.", - }, - { - type: "input", - name: "APP_PRIVATE_KEY", - message: "Enter your Ubiquity OS private key. This can be obtained from your kernel env vars.", - }, - ], + type: "input", + name: "TELEGRAM_BOT_ADMINS", + message: "Enter your Telegram bot admin IDs separated with commas. '123456789,987654321'", }, - ]; - - async run() { - const answers: Record> = {}; - for (const step of this.steps) { - const questions = step.questions; - - for (const question of questions) { - if (question.name === "GITHUB_PAT_TOKEN" && await this.testAccessToken()) { - continue; - } - console.log(step.title); - const answer = await input.text(` ${question.message}\n> `); - if (question.name === "GITHUB_PAT_TOKEN") { - await writeFile(".env", `GITHUB_PAT_TOKEN=${answer}`, "utf-8"); - logger.ok("GitHub PAT token saved successfully, we must restart the script to continue."); - process.exit(0); - } - - answers[step.title] ??= {}; - - if (question.name === "TELEGRAM_BOT_ADMINS") { - answers[step.title][question.name] = JSON.stringify(answer.split(",").map((id: string) => Number(id))); - continue; - } - answers[step.title][question.name] = answer; - } - } - console.clear(); - - this.env = { - TELEGRAM_BOT_ENV: { - botSettings: { - TELEGRAM_BOT_ADMINS: JSON.parse(answers["Bot settings"]["TELEGRAM_BOT_ADMINS"]), - TELEGRAM_BOT_TOKEN: answers["Bot settings"]["TELEGRAM_BOT_TOKEN"], - TELEGRAM_BOT_WEBHOOK: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK"], - TELEGRAM_BOT_WEBHOOK_SECRET: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK_SECRET"], - }, - mtProtoSettings: { - TELEGRAM_API_HASH: answers["MTProto settings"]["TELEGRAM_API_HASH"], - TELEGRAM_APP_ID: Number(answers["MTProto settings"]["TELEGRAM_APP_ID"]), - }, - storageSettings: { - SUPABASE_SERVICE_KEY: answers["Storage settings"]["SUPABASE_SERVICE_KEY"], - SUPABASE_URL: answers["Storage settings"]["SUPABASE_URL"], - }, - ubiquityOsSettings: { - APP_ID: Number(answers["Ubiquity OS settings"]["APP_ID"]), - APP_PRIVATE_KEY: answers["Ubiquity OS settings"]["APP_PRIVATE_KEY"], - }, - }, - }; - - await this.validateEnv(); + ], + }, + { + title: "MTProto settings", + questions: [ + { + type: "input", + name: "TELEGRAM_API_HASH", + message: "Enter your Telegram API hash. This can be obtained from 'https://my.telegram.org'", + }, + { + type: "input", + name: "TELEGRAM_APP_ID", + message: "Enter your Telegram app id. This can be obtained from 'https://my.telegram.org'", + }, + ], + }, + { + title: "Storage settings", + questions: [ + { + type: "input", + name: "SUPABASE_SERVICE_KEY", + message: "Enter your Supabase service key (read/write access)", + }, + { + type: "input", + name: "SUPABASE_URL", + message: "Enter your Supabase URL (https://.supabase.co)", + }, + ], + }, + { + title: "Ubiquity OS settings", + questions: [ + { + type: "input", + name: "APP_ID", + message: "Enter your Ubiquity OS app id. This can be obtained from your kernel env vars.", + }, + { + type: "input", + name: "APP_PRIVATE_KEY", + message: "Enter your Ubiquity OS private key. This can be obtained from your kernel env vars.", + }, + ], + }, + ]; + + shouldTestToken = !!process.env.GITHUB_PAT_TOKEN; + hasSetRepository = !!process.env.REPOSITORY; + + async handleFirstTwo(question: { name: string; message: string }, answer: string) { + if (question.name === "REPOSITORY") { + if (!answer.includes("/")) { + logger.error("Invalid repository name. Please enter in the format 'owner/repo'"); + process.exit(1); + } + await writeFile(".env", `REPOSITORY=${answer}`, "utf-8"); + logger.ok("Repository name saved successfully"); } - /** - * Manually set the env variables below and run `yarn setup-env-manual` - */ - async manual() { - this.env = { - TELEGRAM_BOT_ENV: { - botSettings: { - TELEGRAM_BOT_ADMINS: [], - TELEGRAM_BOT_TOKEN: "", - TELEGRAM_BOT_WEBHOOK: "", - TELEGRAM_BOT_WEBHOOK_SECRET: "", - }, - mtProtoSettings: { - TELEGRAM_API_HASH: "", - TELEGRAM_APP_ID: 0, - }, - storageSettings: { - SUPABASE_SERVICE_KEY: "", - SUPABASE_URL: "", - }, - ubiquityOsSettings: { - APP_ID: 0, - APP_PRIVATE_KEY: "", - }, - }, - }; - - await this.saveEnv(); + if (question.name === "GITHUB_PAT_TOKEN") { + await appendFile(".env", `\nGITHUB_PAT_TOKEN=${answer}`, "utf-8"); + logger.ok("GitHub PAT token saved successfully, we must restart the script to continue."); + process.exit(0); } + } - async validateEnv() { - const env = this.env.TELEGRAM_BOT_ENV; - const { botSettings, mtProtoSettings, storageSettings, ubiquityOsSettings } = env; + async run() { + const answers: Record> = {}; + for (const step of this.steps) { + const questions = step.questions; - const merged = { - ...botSettings, - ...mtProtoSettings, - ...storageSettings, - ...ubiquityOsSettings, - }; + for (const question of questions) { + if ((question.name === "REPOSITORY" && this.hasSetRepository) || (question.name === "GITHUB_PAT_TOKEN" && (await this.testAccessToken()))) { + continue; + } + console.log(step.title); + const answer = await input.text(` ${question.message}\n> `); - const keys = Object.keys(merged); + await this.handleFirstTwo(question, answer); - const missing = []; + answers[step.title] ??= {}; - for (const key_ of keys) { - const key = key_ as keyof typeof merged; - if (!merged[key]) { - missing.push(key); - } + if (question.name === "TELEGRAM_BOT_ADMINS") { + answers[step.title][question.name] = JSON.stringify(answer.split(",").map((id: string) => Number(id))); + continue; } - if (missing.length) { - console.log("Missing keys:", missing); - await this.run(); - } - await this.saveEnv(); + answers[step.title][question.name] = answer; + } + } + console.clear(); + + this.env = { + TELEGRAM_BOT_ENV: { + botSettings: { + TELEGRAM_BOT_ADMINS: JSON.parse(answers["Bot settings"]["TELEGRAM_BOT_ADMINS"]), + TELEGRAM_BOT_TOKEN: answers["Bot settings"]["TELEGRAM_BOT_TOKEN"], + TELEGRAM_BOT_WEBHOOK: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK"], + TELEGRAM_BOT_WEBHOOK_SECRET: answers["Bot settings"]["TELEGRAM_BOT_WEBHOOK_SECRET"], + }, + mtProtoSettings: { + TELEGRAM_API_HASH: answers["MTProto settings"]["TELEGRAM_API_HASH"], + TELEGRAM_APP_ID: Number(answers["MTProto settings"]["TELEGRAM_APP_ID"]), + }, + storageSettings: { + SUPABASE_SERVICE_KEY: answers["Storage settings"]["SUPABASE_SERVICE_KEY"], + SUPABASE_URL: answers["Storage settings"]["SUPABASE_URL"], + }, + ubiquityOsSettings: { + APP_ID: Number(answers["Ubiquity OS settings"]["APP_ID"]), + APP_PRIVATE_KEY: answers["Ubiquity OS settings"]["APP_PRIVATE_KEY"], + }, + }, + }; - logger.ok("Env saved successfully"); + await this.validateEnv(); + } - exit(); - } + async validateEnv() { + const env = this.env.TELEGRAM_BOT_ENV; + const { botSettings, mtProtoSettings, storageSettings, ubiquityOsSettings } = env; - async saveEnv() { - const paths = [".env", ".dev.vars"]; + const merged = { + ...botSettings, + ...mtProtoSettings, + ...storageSettings, + ...ubiquityOsSettings, + }; - const envVar = `TELEGRAM_BOT_ENV=${JSON.stringify(this.env.TELEGRAM_BOT_ENV)}`; + const keys = Object.keys(merged); - for (const path of paths) { - await writeFile(path, envVar, "utf-8"); - } + const missing = []; - logger.ok("Local env files saved successfully"); - logger.info("Storing secrets in GitHub"); - await this.storeRepoSecrets(); + for (const key_ of keys) { + const key = key_ as keyof typeof merged; + if (!merged[key]) { + missing.push(key); + } } - async testAccessToken() { - const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); - const secret = `---`; - - try { - const pubKey = await octokit.actions.getRepoPublicKey({ - owner: "ubq-testing", - repo: "telegram--bot", - }); - - const key = pubKey.data.key; - const encryptedSecret = await this.encryptSecret(secret, key); - - await octokit.actions.createOrUpdateRepoSecret({ - owner: "ubq-testing", - repo: "telegram--bot", - secret_name: "TELEGRAM_BOT_ENV", - encrypted_value: encryptedSecret, - key_id: pubKey.data.key_id, - }); - - return true - } catch (err) { - return false - } + if (missing.length) { + console.log("Missing keys:", missing); + await this.run(); } + await this.saveEnv(); - async storeRepoSecrets() { - const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); - const secret = `${JSON.stringify(this.env.TELEGRAM_BOT_ENV)}`; - - try { - const pubKey = await octokit.actions.getRepoPublicKey({ - owner: "ubq-testing", - repo: "telegram--bot", - }); - - const key = pubKey.data.key; - const encryptedSecret = await this.encryptSecret(secret, key); - - await octokit.actions.createOrUpdateRepoSecret({ - owner: "ubq-testing", - repo: "telegram--bot", - secret_name: "TELEGRAM_BOT_ENV", - encrypted_value: encryptedSecret, - key_id: pubKey.data.key_id, - }); - logger.ok("Secret stored successfully"); - } catch (err) { - logger.error("Error storing secret", { err }); - } - exit(); + logger.ok("Env saved successfully"); + + exit(); + } + + async saveEnv() { + const paths = [".env", ".dev.vars"]; + + const telegramBotEnv = `TELEGRAM_BOT_ENV=${JSON.stringify(this.env.TELEGRAM_BOT_ENV)}`; + const repositoryEnv = `REPOSITORY=${process.env.REPOSITORY}`; + + for (const path of paths) { + const envVar = `${repositoryEnv}\n${telegramBotEnv}`; + await writeFile(path, envVar, "utf-8"); } - async encryptSecret(secret: string, key: string /* Base64 */) { - await sodium.ready; - // Convert the secret and key to a Uint8Array. - const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL); - const binsec = sodium.from_string(secret); + logger.ok("Local env files saved successfully"); + logger.info("Storing secrets in GitHub"); + await this.storeRepoSecrets(telegramBotEnv, repositoryEnv); + } - // Encrypt the secret using libsodium - const encBytes = sodium.crypto_box_seal(binsec, binkey); + getOwnerRepo() { + if (!process.env.REPOSITORY) { + logger.error("No repository found in environment variables"); + exit(1); + } + const [owner, repo] = process.env.REPOSITORY.split("/"); + return { owner, repo }; + } - // Convert the encrypted Uint8Array to Base64 - return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL); + async testAccessToken() { + if (!this.shouldTestToken) { + return false; } -} + const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); + const secret = `{}`; + + try { + const { owner, repo } = this.getOwnerRepo(); + const pubKey = await octokit.actions.getRepoPublicKey({ + owner, + repo, + }); + + const key = pubKey.data.key; + const encryptedSecret = await this.encryptSecret(secret, key); + + await octokit.actions.createOrUpdateRepoSecret({ + owner, + repo, + secret_name: "TELEGRAM_BOT_ENV", + encrypted_value: encryptedSecret, + key_id: pubKey.data.key_id, + }); + + return true; + } catch { + return false; + } + } -async function guided() { - const setup = new SetUpHandler(); - await setup.run(); -} + async storeRepoSecrets(botEnv: string, repositoryEnv: string) { + const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); + const secrets = { + TELEGRAM_BOT_ENV: botEnv, + REPOSITORY: repositoryEnv, + }; -async function manual() { - const setup = new SetUpHandler(); - await setup.manual(); + try { + for (const [key, value] of Object.entries(secrets)) { + const { owner, repo } = this.getOwnerRepo(); + const pubKey = await octokit.actions.getRepoPublicKey({ + owner, + repo, + }); + + const encryptedSecret = await this.encryptSecret(value, pubKey.data.key); + + await octokit.actions.createOrUpdateRepoSecret({ + owner, + repo, + secret_name: key, + encrypted_value: encryptedSecret, + key_id: pubKey.data.key_id, + }); + + logger.ok(`Secret ${key} stored successfully`); + } + } catch (err) { + logger.error("Error storing secret", { err }); + } + exit(); + } + + async encryptSecret(secret: string, key: string /* Base64 */) { + await sodium.ready; + const binkey = sodium.from_base64(key, sodium.base64_variants.ORIGINAL); + const binsec = sodium.from_string(secret); + const encBytes = sodium.crypto_box_seal(binsec, binkey); + return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL); + } } -if (process.argv.includes("--manual")) { - manual().catch(console.error); -} else { - guided().catch(console.error); +async function guided() { + const setup = new SetUpHandler(); + await setup.run(); } + +guided().catch(console.error); diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts index 99c034c..855ae81 100644 --- a/src/handlers/repository-dispatch.ts +++ b/src/handlers/repository-dispatch.ts @@ -10,18 +10,16 @@ import { Context } from "../types"; */ export async function repositoryDispatch(context: Context, workflow: string) { const inputs = PluginContext.getInstance().getInputs(); - const { logger } = context; + const { + logger, + env: { REPOSITORY }, + } = context; + if (!REPOSITORY) { + throw new Error("REPOSITORY env variable is not set"); + } - /** - * These will remain hardcoded as `context` will have other repositories - * and branches that are not relevant to the worker. - * - * If we release this bot as plugin for partners as opposed to it being just our - * internal bot, we can make these configurable. - */ - const repository = "telegram--bot"; - const owner = "ubq-testing"; - const branch = "workflows-test"; + const [owner, repository] = REPOSITORY.split("/"); + const branch = "development"; const { env: { diff --git a/src/types/env.ts b/src/types/env.ts index e2309b9..b7152f7 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -91,6 +91,7 @@ const TELEGRAM_BOT_ENV = T.Object({ }); export const env = T.Object({ + REPOSITORY: T.Optional(T.String({ examples: ["owner/repo"], default: "ubiquibot/telegram-bot" })), TELEGRAM_BOT_ENV: T.Transform(T.Union([T.String(), TELEGRAM_BOT_ENV])) .Decode((str) => { if (typeof str === "string") { From 0947e076e2365b4f3d31ddade203843d967e0863 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 23:31:09 +0100 Subject: [PATCH 55/76] feat: targetBranch config item --- eslint.config.mjs | 2 +- src/handlers/repository-dispatch.ts | 4 ++-- src/types/plugin-inputs.ts | 4 ++++ tsconfig.json | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index e04c686..d9e2a00 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -9,7 +9,7 @@ export default tsEslint.config({ "@typescript-eslint": tsEslint.plugin, "check-file": checkFile, }, - ignores: [".github/knip.ts", "tests/**/*.ts", "eslint.config.mjs"], + ignores: [".github/knip.ts", "tests/**/*.ts", "eslint.config.mjs", ".wrangler"], extends: [eslint.configs.recommended, ...tsEslint.configs.recommended, sonarjs.configs.recommended], languageOptions: { parser: tsEslint.parser, diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts index 855ae81..153c9f3 100644 --- a/src/handlers/repository-dispatch.ts +++ b/src/handlers/repository-dispatch.ts @@ -19,7 +19,6 @@ export async function repositoryDispatch(context: Context, workflow: string) { } const [owner, repository] = REPOSITORY.split("/"); - const branch = "development"; const { env: { @@ -27,6 +26,7 @@ export async function repositoryDispatch(context: Context, workflow: string) { ubiquityOsSettings: { APP_ID, APP_PRIVATE_KEY }, }, }, + config: { targetBranch }, } = context; const app = new App({ appId: APP_ID, privateKey: APP_PRIVATE_KEY }); const installation = await app.octokit.rest.apps.getRepoInstallation({ owner, repo: repository }); @@ -46,7 +46,7 @@ export async function repositoryDispatch(context: Context, workflow: string) { owner, repo: repository, workflow_id: "compute.yml", - ref: branch, + ref: targetBranch ?? "development", inputs: { ...inputs, eventPayload: JSON.stringify(context.payload), diff --git a/src/types/plugin-inputs.ts b/src/types/plugin-inputs.ts index 9702225..6195362 100644 --- a/src/types/plugin-inputs.ts +++ b/src/types/plugin-inputs.ts @@ -18,6 +18,10 @@ export const pluginSettingsSchema = T.Object({ botId: T.Transform(T.Unknown()) .Decode((value) => Number(value)) .Encode((value) => value.toString()), + /** + * The target branch to run the workflows on. Will default to the default branch. + */ + targetBranch: T.Optional(T.String({ default: "development" })), }); export const pluginSettingsValidator = new StandardValidator(pluginSettingsSchema); diff --git a/tsconfig.json b/tsconfig.json index 1bcbb7d..aaae717 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -23,5 +23,5 @@ "preserveWatchOutput": true }, "include": ["src/**/*"], - "exclude": ["node_modules", "build", "tests", "eslint.config.mjs"] + "exclude": ["node_modules", "build", "tests", "eslint.config.mjs", ".wrangler"] } From 11862fdb3ca801a57bb7deb476b20ea32862d4a8 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 13 Sep 2024 23:47:29 +0100 Subject: [PATCH 56/76] chore: fix setup-env and id comparison --- README.md | 2 +- package.json | 2 +- .../bot/scripts/sms-auth/auth-handler.ts | 2 +- .../bot/scripts/sms-auth/setup-env.ts | 16 +++++++++++----- src/bot/mtproto-api/workrooms/reopen-chat.ts | 2 +- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 74fc7ff..5ca1540 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ The `TELEGRAM_BOT_ENV` is a single JSON object that encapsulates all necessary e You can set up your environment variables by using the provided utility script: -- Run `yarn setup-env-guided`, which prompts you to enter each value via the CLI. The values will be serialized and stored both locally and in your repository secrets. +- Run `yarn setup-env`, which prompts you to enter each value via the CLI. The values will be serialized and stored both locally and in your repository secrets. - **GITHUB_PAT_TOKEN**: Create a classic personal access token (PAT) with the `repo` scope. Set the expiry to 24 hours. This token will be used to generate repository secrets for the environment variables and will be removed from `.env` after the secrets are saved. - **Account Permission**: The account in which the PAT is associated with _must_ be an `admin` of the repository to be able to save secrets this way. Visit your repository settings `telegram-bot` > `Collaborators & teams` to add the account as an admin first if needed. diff --git a/package.json b/package.json index 1f0b4c2..ffd7c52 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "start": "tsx ./src/main.ts", "deploy": "wrangler deploy --minify src/main.ts", "sms-auth": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts", - "setup-env-guided": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts" + "setup-env": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts" }, "keywords": [ "typescript", diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts index 60fb087..05e83bc 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts @@ -22,7 +22,7 @@ export class AuthHandler { constructor() { const env = process.env.TELEGRAM_BOT_ENV; if (!env) { - throw new Error("Have you ran the setup script? Try running 'yarn setup-env-guided' first."); + throw new Error("Have you ran the setup script? Try running 'yarn setup-env' first."); } const parsedEnv: Context["env"]["TELEGRAM_BOT_ENV"] = JSON.parse(env); diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts index b7a6b2f..5242702 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts @@ -260,7 +260,7 @@ class SetUpHandler { logger.ok("Local env files saved successfully"); logger.info("Storing secrets in GitHub"); - await this.storeRepoSecrets(telegramBotEnv, repositoryEnv); + await this.storeRepoSecrets(); } getOwnerRepo() { @@ -303,11 +303,11 @@ class SetUpHandler { } } - async storeRepoSecrets(botEnv: string, repositoryEnv: string) { + async storeRepoSecrets() { const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); const secrets = { - TELEGRAM_BOT_ENV: botEnv, - REPOSITORY: repositoryEnv, + TELEGRAM_BOT_ENV: this.env.TELEGRAM_BOT_ENV, + REPOSITORY: process.env.REPOSITORY, }; try { @@ -318,7 +318,13 @@ class SetUpHandler { repo, }); - const encryptedSecret = await this.encryptSecret(value, pubKey.data.key); + const secret = typeof value === "object" ? JSON.stringify(value) : value; + + if (!secret) { + throw new Error(`No secret found to save for key ${key}`); + } + + const encryptedSecret = await this.encryptSecret(secret, pubKey.data.key); await octokit.actions.createOrUpdateRepoSecret({ owner, diff --git a/src/bot/mtproto-api/workrooms/reopen-chat.ts b/src/bot/mtproto-api/workrooms/reopen-chat.ts index e7c6b98..3beca54 100644 --- a/src/bot/mtproto-api/workrooms/reopen-chat.ts +++ b/src/bot/mtproto-api/workrooms/reopen-chat.ts @@ -77,7 +77,7 @@ export async function reopenChat(context: Context<"issues.reopened", SupportedEv await mtProto.client.getDialogs(); try { // don't add the bot or the chat creator, as they are already in the chat - if (userId === context.config.botId || userId === chatCreator) { + if (userId === context.config.botId || userId === chatCreator.toJSNumber()) { continue; } From d9cdd3773fa69ce7437350579c6cfa2b853f8369 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sat, 14 Sep 2024 00:06:10 +0100 Subject: [PATCH 57/76] chore: some knip fixes --- package.json | 11 +- src/adapters/supabase/helpers/chats.ts | 7 - src/server/index.ts | 2 - src/types/typeguards.ts | 9 - yarn.lock | 258 +------------------------ 5 files changed, 5 insertions(+), 282 deletions(-) diff --git a/package.json b/package.json index ffd7c52..2092f26 100644 --- a/package.json +++ b/package.json @@ -40,27 +40,20 @@ "@actions/github": "6.0.0", "@grammyjs/auto-chat-action": "0.1.1", "@grammyjs/hydrate": "1.4.1", - "@grammyjs/i18n": "1.0.2", "@grammyjs/parse-mode": "1.10.0", - "@grammyjs/runner": "2.0.3", "@grammyjs/types": "3.13.0", "@octokit/rest": "21.0.2", "@octokit/webhooks": "13.3.0", "@sinclair/typebox": "0.33.7", "@supabase/supabase-js": "^2.45.3", "@ubiquity-dao/ubiquibot-logger": "^1.3.1", - "callback-data": "1.1.1", "dotenv": "16.4.5", "grammy": "^1.29.0", "grammy-guard": "0.5.0", "hono": "^4.5.9", - "iso-639-1": "3.1.2", "octokit": "^4.0.2", - "pino": "9.3.2", - "pino-pretty": "11.2.2", "telegram": "^2.24.11", - "typebox-validators": "0.3.5", - "valibot": "0.39.0" + "typebox-validators": "0.3.5" }, "devDependencies": { "@cloudflare/workers-types": "^4.20240529.0", @@ -74,7 +67,6 @@ "@mswjs/data": "0.16.1", "@types/jest": "^29.5.12", "@types/node": "22.5.0", - "@types/tdweb": "^1.4.5", "cspell": "8.14.2", "eslint": "9.9.1", "eslint-config-prettier": "9.1.0", @@ -91,7 +83,6 @@ "lint-staged": "15.2.9", "npm-run-all": "4.1.5", "prettier": "3.3.3", - "smee-client": "^2.0.3", "ts-jest": "29.2.5", "tsc-watch": "^6.2.0", "tsx": "4.18.0", diff --git a/src/adapters/supabase/helpers/chats.ts b/src/adapters/supabase/helpers/chats.ts index abe3584..d67ad88 100644 --- a/src/adapters/supabase/helpers/chats.ts +++ b/src/adapters/supabase/helpers/chats.ts @@ -1,13 +1,6 @@ import { SupabaseClient } from "@supabase/supabase-js"; import { Super } from "./supabase"; -export type Chat = { - chatId: number; - chatName: string; - taskNodeId: string; - status: string; -}; - /** * Handles all telegram chat storage and retrieval */ diff --git a/src/server/index.ts b/src/server/index.ts index b0405e6..4dcd389 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -68,5 +68,3 @@ export function createServer(dependencies: Dependencies) { return server; } - -export type Server = Awaited>; diff --git a/src/types/typeguards.ts b/src/types/typeguards.ts index a5aabf2..136ca30 100644 --- a/src/types/typeguards.ts +++ b/src/types/typeguards.ts @@ -1,11 +1,6 @@ import { GrammyTelegramUpdate } from "#root/bot/helpers/grammy-context.js"; -import { Context } from "./context"; import { PluginInputs } from "./plugin-inputs"; -export function isIssueOpenedEvent(context: Context): context is Context<"issues.opened"> { - return context.eventName === "issues.opened"; -} - export function isTelegramPayload(payload: unknown): payload is GrammyTelegramUpdate { if (typeof payload !== "object" || !payload) return false; return "update_id" in payload && payload.update_id !== undefined; @@ -15,7 +10,3 @@ export function isGithubPayload(inputs: unknown): inputs is PluginInputs { if (typeof inputs !== "object" || !inputs) return false; return "eventName" in inputs && inputs.eventName !== undefined; } - -export function isIssueLabeledEvent(context: Context): context is Context<"issues.labeled"> { - return context.eventName === "issues.labeled"; -} diff --git a/yarn.lock b/yarn.lock index 34e47aa..79f58fd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1688,19 +1688,6 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@deno/shim-deno-test@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@deno/shim-deno-test/-/shim-deno-test-0.5.0.tgz#7d5dd221c736d182e587b8fd9bfca49b4dc0aa79" - integrity sha512-4nMhecpGlPi0cSzT67L+Tm+GOJqvuk8gqHBziqcUQOarnuIax1z96/gJHCSIz2Z0zhxE6Rzwb3IZXPtFh51j+w== - -"@deno/shim-deno@~0.18.0": - version "0.18.2" - resolved "https://registry.yarnpkg.com/@deno/shim-deno/-/shim-deno-0.18.2.tgz#9fe2fe7c91062bf2d127204f3110c09806cbef92" - integrity sha512-oQ0CVmOio63wlhwQF75zA4ioolPvOwAoK0yuzcS5bDC1JUvH3y1GS8xPh8EOpcoDQRU4FTG8OQfxhpR+c6DrzA== - dependencies: - "@deno/shim-deno-test" "^0.5.0" - which "^4.0.0" - "@esbuild-plugins/node-globals-polyfill@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.2.3.tgz#0e4497a2b53c9e9485e149bc92ddb228438d6bcf" @@ -2000,16 +1987,6 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== -"@fluent/bundle@^0.17.1": - version "0.17.1" - resolved "https://registry.yarnpkg.com/@fluent/bundle/-/bundle-0.17.1.tgz#239388f55f115dca593f268d48a5ab8936dc9556" - integrity sha512-CRFNT9QcSFAeFDneTF59eyv3JXFGhIIN4boUO2y22YmsuuKLyDk+N1I/NQUYz9Ab63e6V7T6vItoZIG/2oOOuw== - -"@fluent/langneg@^0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@fluent/langneg/-/langneg-0.6.2.tgz#95e5261c27c7f3cb6237deb62aa1b7006a9bd17d" - integrity sha512-YF4gZ4sLYRQfctpUR2uhb5UyPUYY5n/bi3OaED/Q4awKjPjlaF8tInO3uja7pnLQcmLTURkZL7L9zxv2Z5NDwg== - "@grammyjs/auto-chat-action@0.1.1": version "0.1.1" resolved "https://registry.yarnpkg.com/@grammyjs/auto-chat-action/-/auto-chat-action-0.1.1.tgz#2c70faca0e317ac3e742ea241181cedaa4231081" @@ -2022,27 +1999,11 @@ dependencies: abort-controller "^3.0.0" -"@grammyjs/i18n@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@grammyjs/i18n/-/i18n-1.0.2.tgz#6b2763e78554d3ba19bd4416fd601c5f0abcf855" - integrity sha512-F/6jBB+afp8N3aXLmxTqdlffqD20EZBMFrPiVQNz6YoiKvjAe4Q8rSrU0Y4eQXkUj4e+UNl7yvYvvPSa1h4guw== - dependencies: - "@deno/shim-deno" "~0.18.0" - "@fluent/bundle" "^0.17.1" - "@fluent/langneg" "^0.6.2" - "@grammyjs/parse-mode@1.10.0": version "1.10.0" resolved "https://registry.yarnpkg.com/@grammyjs/parse-mode/-/parse-mode-1.10.0.tgz#41256924b9f4465cc53630a0a9f3d8788da0f1f9" integrity sha512-ZjbY2Ax0b4Nf8lPz3NV0cWDxUC10kOkzgxws+iTdgG+hAiPQVUnP/oJnAKrW1ZQOWULZYQ4GOR/+aCZHyUuLQA== -"@grammyjs/runner@2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@grammyjs/runner/-/runner-2.0.3.tgz#cfb08958fd563ce1e0eda5754a40b3d632c4eaa1" - integrity sha512-nckmTs1dPWfVQteK9cxqxzE+0m1VRvluLWB8UgFzsjg62w3qthPJt0TYtJBEdG7OedvfQq4vnFAyE6iaMkR42A== - dependencies: - abort-controller "^3.0.0" - "@grammyjs/types@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@grammyjs/types/-/types-3.13.0.tgz#3316a809b4faf6cc61cff0c7d7a5a671ec0bd776" @@ -2987,11 +2948,6 @@ resolved "https://registry.yarnpkg.com/@types/statuses/-/statuses-2.0.5.tgz#f61ab46d5352fd73c863a1ea4e1cef3b0b51ae63" integrity sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A== -"@types/tdweb@^1.4.5": - version "1.4.5" - resolved "https://registry.yarnpkg.com/@types/tdweb/-/tdweb-1.4.5.tgz#4a5c3085fdf99de9fae7b87eaad16bc8271c93d5" - integrity sha512-6rFeIo6iofNkNz6Jn2BR9BWtOcjEsDdhJeQ7oYPXg865vOOeI6etPE7x1B2KtU1CE/A04c5jL6CRKhd/ut22xA== - "@types/tough-cookie@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" @@ -3510,11 +3466,6 @@ async@^3.2.3: resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== -atomic-sleep@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" - integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== - available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" @@ -3756,7 +3707,7 @@ call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: get-intrinsic "^1.2.4" set-function-length "^1.2.1" -callback-data@1.1.1, callback-data@^1.0.0: +callback-data@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/callback-data/-/callback-data-1.1.1.tgz#0d4f70995df97ec039cea08985623a7205ac080c" integrity sha512-1XoQQTsTkuU0/Ee2vRS64d+mKmM+zfEWgarI3ETPfYV3R5UvArM7C0sXSGPff+Aztea1Vrom6LDs9HQWSZucXQ== @@ -3972,12 +3923,12 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^2.0.20, colorette@^2.0.7: +colorette@^2.0.20: version "2.0.20" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== -commander@^12.0.0, commander@^12.1.0, commander@~12.1.0: +commander@^12.1.0, commander@~12.1.0: version "12.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== @@ -4306,11 +4257,6 @@ date-fns@^3.6.0: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-3.6.0.tgz#f20ca4fe94f8b754951b24240676e8618c0206bf" integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww== -dateformat@^4.6.3: - version "4.6.3" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" - integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== - debug@^2.2.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -4530,13 +4476,6 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - enhanced-resolve@^5.17.1: version "5.17.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" @@ -5134,16 +5073,6 @@ eventemitter3@^5.0.1: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== -events@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -eventsource@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-2.0.2.tgz#76dfcc02930fb2ff339520b6d290da573a9e8508" - integrity sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA== - execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -5207,11 +5136,6 @@ ext@^1.7.0: dependencies: type "^2.7.2" -fast-copy@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.2.tgz#59c68f59ccbcac82050ba992e0d5c389097c9d35" - integrity sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -5248,16 +5172,6 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== -fast-redact@^3.1.1: - version "3.5.0" - resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" - integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== - -fast-safe-stringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - fast-uri@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.1.tgz#cddd2eecfc83a71c1be2cc2ef2061331be8a7134" @@ -5665,11 +5579,6 @@ headers-polyfill@^4.0.2: resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.3.tgz#922a0155de30ecc1f785bcf04be77844ca95ad07" integrity sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ== -help-me@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" - integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== - hono@^4.5.9: version "4.5.9" resolved "https://registry.yarnpkg.com/hono/-/hono-4.5.9.tgz#2627c55c4c97ae826973dddac857ba4476fde6c6" @@ -6081,16 +5990,6 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -isexe@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d" - integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ== - -iso-639-1@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/iso-639-1/-/iso-639-1-3.1.2.tgz#86a53dcce056e0d856b17c022eb059eb16a35426" - integrity sha512-Le7BRl3Jt9URvaiEHJCDEdvPZCfhiQoXnFgLAWNRhzFMwRFdWO7/5tLRQbiPzE394I9xd7KdRCM7S6qdOhwG5A== - isomorphic-git@^1.25.6: version "1.27.1" resolved "https://registry.yarnpkg.com/isomorphic-git/-/isomorphic-git-1.27.1.tgz#a2752fce23a09f04baa590c41cfaf61e973405b3" @@ -6562,11 +6461,6 @@ jiti@^1.19.1, jiti@^1.21.6: resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== -joycon@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" - integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== - "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -7297,11 +7191,6 @@ octokit@^4.0.2: "@octokit/request-error" "^6.0.0" "@octokit/types" "^13.0.0" -on-exit-leak-free@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" - integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== - once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -7557,56 +7446,6 @@ pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -pino-abstract-transport@^1.0.0, pino-abstract-transport@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz#97f9f2631931e242da531b5c66d3079c12c9d1b5" - integrity sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q== - dependencies: - readable-stream "^4.0.0" - split2 "^4.0.0" - -pino-pretty@11.2.2: - version "11.2.2" - resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-11.2.2.tgz#5e8ec69b31e90eb187715af07b1d29a544e60d39" - integrity sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A== - dependencies: - colorette "^2.0.7" - dateformat "^4.6.3" - fast-copy "^3.0.2" - fast-safe-stringify "^2.1.1" - help-me "^5.0.0" - joycon "^3.1.1" - minimist "^1.2.6" - on-exit-leak-free "^2.1.0" - pino-abstract-transport "^1.0.0" - pump "^3.0.0" - readable-stream "^4.0.0" - secure-json-parse "^2.4.0" - sonic-boom "^4.0.1" - strip-json-comments "^3.1.1" - -pino-std-serializers@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b" - integrity sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA== - -pino@9.3.2: - version "9.3.2" - resolved "https://registry.yarnpkg.com/pino/-/pino-9.3.2.tgz#a530d6d28f1d954b6f54416a218cbb616f52f901" - integrity sha512-WtARBjgZ7LNEkrGWxMBN/jvlFiE17LTbBoH0konmBU684Kd0uIiDwBXlcTCW7iJnA6HfIKwUssS/2AC6cDEanw== - dependencies: - atomic-sleep "^1.0.0" - fast-redact "^3.1.1" - on-exit-leak-free "^2.1.0" - pino-abstract-transport "^1.2.0" - pino-std-serializers "^7.0.0" - process-warning "^4.0.0" - quick-format-unescaped "^4.0.3" - real-require "^0.2.0" - safe-stable-stringify "^2.3.1" - sonic-boom "^4.0.1" - thread-stream "^3.0.0" - pirates@^4.0.4: version "4.0.6" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" @@ -7667,16 +7506,6 @@ printable-characters@^1.0.42: resolved "https://registry.yarnpkg.com/printable-characters/-/printable-characters-1.0.42.tgz#3f18e977a9bd8eb37fcc4ff5659d7be90868b3d8" integrity sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ== -process-warning@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-4.0.0.tgz#581e3a7a1fb456c5f4fd239f76bce75897682d5a" - integrity sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -7706,14 +7535,6 @@ psl@^1.1.33: resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - punycode@^2.1.0, punycode@^2.1.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -7734,11 +7555,6 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -quick-format-unescaped@^4.0.3: - version "4.0.4" - resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" - integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== - react-is@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -7767,17 +7583,6 @@ readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^4.0.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09" - integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g== - dependencies: - abort-controller "^3.0.0" - buffer "^6.0.3" - events "^3.3.0" - process "^0.11.10" - string_decoder "^1.3.0" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -7799,11 +7604,6 @@ real-cancellable-promise@^1.1.1: resolved "https://registry.yarnpkg.com/real-cancellable-promise/-/real-cancellable-promise-1.2.0.tgz#f365e78b29c6a2303584f2c308959b415401056a" integrity sha512-FYhmx1FVSgoPRjneoTjh+EKZcNb8ijl/dyatTzase5eujYhVrLNDOiIY6AgQq7GU1kOoLgEd9jLVbhFg8k8dOQ== -real-require@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" - integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== - refa@^0.12.0, refa@^0.12.1: version "0.12.1" resolved "https://registry.yarnpkg.com/refa/-/refa-0.12.1.tgz#dac13c4782dc22b6bae6cce81a2b863888ea39c6" @@ -8047,11 +7847,6 @@ safe-regex-test@^1.0.3: es-errors "^1.3.0" is-regex "^1.1.4" -safe-stable-stringify@^2.3.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" - integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== - scslre@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/scslre/-/scslre-0.3.0.tgz#c3211e9bfc5547fc86b1eabaa34ed1a657060155" @@ -8061,11 +7856,6 @@ scslre@0.3.0: refa "^0.12.0" regexp-ast-analysis "^0.7.0" -secure-json-parse@^2.4.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" - integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== - selfsigned@^2.0.1: version "2.4.1" resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0" @@ -8225,15 +8015,6 @@ smart-buffer@^4.2.0: resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== -smee-client@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/smee-client/-/smee-client-2.0.3.tgz#de57d90a2531af136e0f0496a88599376ad53fa8" - integrity sha512-W5tQKHzZFe+IMBlaAJ8Ho32Y2wbUbzriHAA2DAFXpITId+0dYHJJbAX36a/HMrGjW7yFjhcKCNPwRBAiIrlZGQ== - dependencies: - commander "^12.0.0" - eventsource "^2.0.2" - validator "^13.11.0" - smol-toml@^1.1.4: version "1.3.0" resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.3.0.tgz#5200e251fffadbb72570c84e9776d2a3eca48143" @@ -8247,13 +8028,6 @@ socks@^2.6.2: ip-address "^9.0.5" smart-buffer "^4.2.0" -sonic-boom@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.0.1.tgz#515b7cef2c9290cb362c4536388ddeece07aed30" - integrity sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ== - dependencies: - atomic-sleep "^1.0.0" - source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -8481,7 +8255,7 @@ string.prototype.trimstart@^1.0.8: define-properties "^1.2.1" es-object-atoms "^1.0.0" -string_decoder@^1.1.1, string_decoder@^1.3.0: +string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -8630,13 +8404,6 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -thread-stream@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1" - integrity sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A== - dependencies: - real-require "^0.2.0" - through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -8977,11 +8744,6 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^2.0.0" -valibot@0.39.0: - version "0.39.0" - resolved "https://registry.yarnpkg.com/valibot/-/valibot-0.39.0.tgz#b6c42566fa362ca406339d8b24e4e3051ae4bc86" - integrity sha512-d+vE8SDRNy9zKg6No5MHz2tdz8H6CW8X3OdqYdmlhnoqQmEoM6Hu0hJUrZv3tPSVrzZkIIMCtdCQtMzcM6NCWw== - validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -8990,11 +8752,6 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validator@^13.11.0: - version "13.12.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-13.12.0.tgz#7d78e76ba85504da3fee4fd1922b385914d4b35f" - integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg== - vscode-languageserver-textdocument@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz#457ee04271ab38998a093c68c2342f53f6e4a631" @@ -9121,13 +8878,6 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -which@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/which/-/which-4.0.0.tgz#cd60b5e74503a3fbcfbf6cd6b4138a8bae644c1a" - integrity sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg== - dependencies: - isexe "^3.1.1" - word-wrap@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" From 423a65882e09fc72d908ddf8378976b0028b1525 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sat, 14 Sep 2024 01:06:34 +0100 Subject: [PATCH 58/76] chore: comment fix and pass secret to workflow although not used --- .github/workflows/compute.yml | 2 ++ README.md | 1 + src/types/plugin-inputs.ts | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 3e886c8..b72cd6d 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -23,6 +23,7 @@ jobs: permissions: write-all env: TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} + REPOSITORY: ${{ secrets.REPOSITORY }} steps: - uses: actions/checkout@v4 @@ -40,3 +41,4 @@ jobs: id: telegram-bot env: TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} + REPOSITORY: ${{ secrets.REPOSITORY }} diff --git a/README.md b/README.md index 5ca1540..0830dc7 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,7 @@ interface TELEGRAM_BOT_ENV { runsOn: ["issues.opened", "issues.labeled", "issues.reopened", "issues.closed"] with: botId: 00000000 + targetBranch: development ``` ### Usage diff --git a/src/types/plugin-inputs.ts b/src/types/plugin-inputs.ts index 6195362..da45c95 100644 --- a/src/types/plugin-inputs.ts +++ b/src/types/plugin-inputs.ts @@ -19,7 +19,7 @@ export const pluginSettingsSchema = T.Object({ .Decode((value) => Number(value)) .Encode((value) => value.toString()), /** - * The target branch to run the workflows on. Will default to the default branch. + * The target branch to run the workflows on. Will default to the `development` branch. */ targetBranch: T.Optional(T.String({ default: "development" })), }); From 4f690b3cdb74673673ed3a81b769c38d8d58e2d8 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Sun, 15 Sep 2024 15:31:32 +0100 Subject: [PATCH 59/76] chore: refactor config item name --- .github/workflows/compute.yml | 4 ++-- README.md | 7 ++++--- .../bot/scripts/sms-auth/setup-env.ts | 21 +++++++++++-------- src/handlers/repository-dispatch.ts | 8 +++---- src/types/env.ts | 2 +- 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index b72cd6d..5d17308 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -23,7 +23,7 @@ jobs: permissions: write-all env: TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} - REPOSITORY: ${{ secrets.REPOSITORY }} + TELEGRAM_BOT_REPOSITORY_FULL_NAME: ${{ secrets.TELEGRAM_BOT_REPOSITORY_FULL_NAME }} steps: - uses: actions/checkout@v4 @@ -41,4 +41,4 @@ jobs: id: telegram-bot env: TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} - REPOSITORY: ${{ secrets.REPOSITORY }} + TELEGRAM_BOT_REPOSITORY_FULL_NAME: ${{ secrets.TELEGRAM_BOT_REPOSITORY_FULL_NAME }} diff --git a/README.md b/README.md index 0830dc7..1dbbc56 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ The environment variables are stored in the following locations: 2. **mtProtoSettings**: Contains settings for the MTProto API like `TELEGRAM_APP_ID`, `TELEGRAM_API_HASH`, etc. 3. **storageSettings**: Contains settings for the Supabase database like `SUPABASE_URL`, `SUPABASE_SERVICE_KEY`, etc. 4. **ubiquityOsSettings**: Contains settings for the UbiquityOS Kernel like `APP_PRIVATE_KEY`, `APP_ID`, etc. +5. **TELEGRAM_BOT_REPOSITORY_FULL_NAME**: A standalone single string value for the full repository name (e.g., `ubiquity-os/telegram-bot`). ```typescript interface TELEGRAM_BOT_ENV { @@ -119,9 +120,9 @@ interface TELEGRAM_BOT_ENV { #### Telegram Configuration 1. Create a new bot using [BotFather](https://t.me/BotFather). -2. Add your `BOT_TOKEN`, `TELEGRAM_APP_ID`, `TELEGRAM_API_HASH`, and `BOT_ADMINS` to the environment variables. -3. Use [Smee.io](https://smee.io/new) to create a webhook and add the URL as `BOT_WEBHOOK`. -4. Generate a secret for `BOT_WEBHOOK_SECRET` to verify webhook requests. +2. Add your `TELEGRAM_BOT_TOKEN`, `TELEGRAM_APP_ID`, `TELEGRAM_API_HASH`, and `TELEGRAM_BOT_ADMINS` to the environment variables. +3. Use [Smee.io](https://smee.io/new) to create a webhook and add the URL as `TELEGRAM_BOT_WEBHOOK`. +4. Generate a secret for `TELEGRAM_BOT_WEBHOOK_SECRET` to verify webhook requests. #### GitHub Configuration diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts index 5242702..ff93dee 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts @@ -54,7 +54,7 @@ class SetUpHandler { questions: [ { type: "input", - name: "REPOSITORY", + name: "TELEGRAM_BOT_REPOSITORY_FULL_NAME", message: "Enter your repository name (owner/repo).", }, ], @@ -143,15 +143,15 @@ class SetUpHandler { ]; shouldTestToken = !!process.env.GITHUB_PAT_TOKEN; - hasSetRepository = !!process.env.REPOSITORY; + hasSetRepository = !!process.env.TELEGRAM_BOT_REPOSITORY_FULL_NAME; async handleFirstTwo(question: { name: string; message: string }, answer: string) { - if (question.name === "REPOSITORY") { + if (question.name === "TELEGRAM_BOT_REPOSITORY_FULL_NAME") { if (!answer.includes("/")) { logger.error("Invalid repository name. Please enter in the format 'owner/repo'"); process.exit(1); } - await writeFile(".env", `REPOSITORY=${answer}`, "utf-8"); + await writeFile(".env", `TELEGRAM_BOT_REPOSITORY_FULL_NAME=${answer}`, "utf-8"); logger.ok("Repository name saved successfully"); } @@ -168,7 +168,10 @@ class SetUpHandler { const questions = step.questions; for (const question of questions) { - if ((question.name === "REPOSITORY" && this.hasSetRepository) || (question.name === "GITHUB_PAT_TOKEN" && (await this.testAccessToken()))) { + if ( + (question.name === "TELEGRAM_BOT_REPOSITORY_FULL_NAME" && this.hasSetRepository) || + (question.name === "GITHUB_PAT_TOKEN" && (await this.testAccessToken())) + ) { continue; } console.log(step.title); @@ -251,7 +254,7 @@ class SetUpHandler { const paths = [".env", ".dev.vars"]; const telegramBotEnv = `TELEGRAM_BOT_ENV=${JSON.stringify(this.env.TELEGRAM_BOT_ENV)}`; - const repositoryEnv = `REPOSITORY=${process.env.REPOSITORY}`; + const repositoryEnv = `TELEGRAM_BOT_REPOSITORY_FULL_NAME=${process.env.TELEGRAM_BOT_REPOSITORY_FULL_NAME}`; for (const path of paths) { const envVar = `${repositoryEnv}\n${telegramBotEnv}`; @@ -264,11 +267,11 @@ class SetUpHandler { } getOwnerRepo() { - if (!process.env.REPOSITORY) { + if (!process.env.TELEGRAM_BOT_REPOSITORY_FULL_NAME) { logger.error("No repository found in environment variables"); exit(1); } - const [owner, repo] = process.env.REPOSITORY.split("/"); + const [owner, repo] = process.env.TELEGRAM_BOT_REPOSITORY_FULL_NAME.split("/"); return { owner, repo }; } @@ -307,7 +310,7 @@ class SetUpHandler { const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); const secrets = { TELEGRAM_BOT_ENV: this.env.TELEGRAM_BOT_ENV, - REPOSITORY: process.env.REPOSITORY, + TELEGRAM_BOT_REPOSITORY_FULL_NAME: process.env.TELEGRAM_BOT_REPOSITORY_FULL_NAME, }; try { diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts index 153c9f3..6ea4948 100644 --- a/src/handlers/repository-dispatch.ts +++ b/src/handlers/repository-dispatch.ts @@ -12,13 +12,13 @@ export async function repositoryDispatch(context: Context, workflow: string) { const inputs = PluginContext.getInstance().getInputs(); const { logger, - env: { REPOSITORY }, + env: { TELEGRAM_BOT_REPOSITORY_FULL_NAME }, } = context; - if (!REPOSITORY) { - throw new Error("REPOSITORY env variable is not set"); + if (!TELEGRAM_BOT_REPOSITORY_FULL_NAME) { + throw new Error("TELEGRAM_BOT_REPOSITORY_FULL_NAME env variable is not set"); } - const [owner, repository] = REPOSITORY.split("/"); + const [owner, repository] = TELEGRAM_BOT_REPOSITORY_FULL_NAME.split("/"); const { env: { diff --git a/src/types/env.ts b/src/types/env.ts index b7152f7..74dd809 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -91,7 +91,7 @@ const TELEGRAM_BOT_ENV = T.Object({ }); export const env = T.Object({ - REPOSITORY: T.Optional(T.String({ examples: ["owner/repo"], default: "ubiquibot/telegram-bot" })), + TELEGRAM_BOT_REPOSITORY_FULL_NAME: T.Optional(T.String({ examples: ["owner/repo"], default: "ubiquibot/telegram-bot" })), TELEGRAM_BOT_ENV: T.Transform(T.Union([T.String(), TELEGRAM_BOT_ENV])) .Decode((str) => { if (typeof str === "string") { From 1a1ba78df23ad2f8f14eb82970b905cd5d665c03 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 26 Sep 2024 05:27:00 +0100 Subject: [PATCH 60/76] chore: /setwebhook chat command --- .../commands/private-chat/set-webhook.ts | 25 +++++++++++++++++++ src/bot/index.ts | 2 ++ 2 files changed, 27 insertions(+) create mode 100644 src/bot/features/commands/private-chat/set-webhook.ts diff --git a/src/bot/features/commands/private-chat/set-webhook.ts b/src/bot/features/commands/private-chat/set-webhook.ts new file mode 100644 index 0000000..f64a2bf --- /dev/null +++ b/src/bot/features/commands/private-chat/set-webhook.ts @@ -0,0 +1,25 @@ +import { chatAction } from "@grammyjs/auto-chat-action"; +import { Composer } from "grammy"; +import type { Context } from "#root/bot/helpers/grammy-context.js"; +import { logHandle } from "#root/bot/helpers/logging.js"; +import { isAdmin } from "#root/bot/filters/is-admin.js"; + +const composer = new Composer(); + +const feature = composer.chatType("private").filter((ctx) => isAdmin(ctx.config.TELEGRAM_BOT_ENV.botSettings.TELEGRAM_BOT_ADMINS)(ctx)); + +feature.command("setwebhook", logHandle("command-setwebhook"), chatAction("typing"), async (ctx) => { + const webhookUrl = ctx.message?.text?.split(" ")[1]; + if (!webhookUrl) { + return ctx.reply("Please provide a webhook URL."); + } + + try { + await ctx.api.setWebhook(webhookUrl); + return ctx.reply("Webhook URL has been set."); + } catch (error) { + return ctx.reply("Failed to set webhook URL."); + } +}); + +export { composer as setWebhookFeature }; diff --git a/src/bot/index.ts b/src/bot/index.ts index 84e8635..52587b1 100644 --- a/src/bot/index.ts +++ b/src/bot/index.ts @@ -16,6 +16,7 @@ import { userIdFeature } from "./features/commands/private-chat/user-id"; import { chatIdFeature } from "./features/commands/shared/chat-id"; import { botIdFeature } from "./features/commands/private-chat/bot-id"; import { banCommand } from "./features/commands/groups/ban"; +import { setWebhookFeature } from "./features/commands/private-chat/set-webhook"; interface Dependencies { config: UbiquityOsContext["env"]; @@ -56,6 +57,7 @@ export function createBot(token: string, dependencies: Dependencies, options: Op // admin commands protectedBot.use(adminFeature); + protectedBot.use(setWebhookFeature); // development commands protectedBot.use(userIdFeature); From c865a9282a2b691522e68b8f58a6f86c2cdf1897 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 26 Sep 2024 05:33:06 +0100 Subject: [PATCH 61/76] chore: minor changes --- package.json | 5 +- .../bot/scripts/sms-auth/setup-env.ts | 2 +- src/handlers/github-webhook.ts | 1 - src/handlers/telegram-webhook.ts | 24 +++--- src/server/index.ts | 2 - src/types/telegram-bot-single.ts | 19 ++--- src/worker.ts | 77 +++++++------------ wrangler.toml | 2 +- yarn.lock | 2 +- 9 files changed, 56 insertions(+), 78 deletions(-) diff --git a/package.json b/package.json index 2092f26..63a2f03 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "worker": "wrangler dev --env dev --port 3000", "dev": "tsc-watch --onSuccess \"tsx ./src/main.ts\"", "start": "tsx ./src/main.ts", - "deploy": "wrangler deploy --minify src/main.ts", + "deploy": "wrangler deploy --env dev", "sms-auth": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/sms-auth.ts", "setup-env": "npx tsx src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts" }, @@ -47,6 +47,7 @@ "@sinclair/typebox": "0.33.7", "@supabase/supabase-js": "^2.45.3", "@ubiquity-dao/ubiquibot-logger": "^1.3.1", + "big-integer": "^1.6.52", "dotenv": "16.4.5", "grammy": "^1.29.0", "grammy-guard": "0.5.0", @@ -105,4 +106,4 @@ ] }, "packageManager": "yarn@1.22.22" -} +} \ No newline at end of file diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts index ff93dee..6cb415e 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts @@ -81,7 +81,7 @@ class SetUpHandler { { type: "input", name: "TELEGRAM_BOT_WEBHOOK", - message: "Enter your Telegram bot webhook. Cloudflare for production, ngrok/smee for development", + message: "Any URL used should end with '/telegram'. e.g 'https://example.com/telegram'", }, { type: "input", diff --git a/src/handlers/github-webhook.ts b/src/handlers/github-webhook.ts index cf7a94d..0ccb4d6 100644 --- a/src/handlers/github-webhook.ts +++ b/src/handlers/github-webhook.ts @@ -6,7 +6,6 @@ import { logger } from "#root/utils/logger.js"; export async function handleGithubWebhook(request: Request, env: Env): Promise { try { const webhookPayload = (await request.json()) as PluginInputs; - const settings = Value.Decode(pluginSettingsSchema, Value.Default(pluginSettingsSchema, webhookPayload.settings)); if (!pluginSettingsValidator.test(settings)) { const errors: string[] = []; diff --git a/src/handlers/telegram-webhook.ts b/src/handlers/telegram-webhook.ts index 0ac9eea..cc87150 100644 --- a/src/handlers/telegram-webhook.ts +++ b/src/handlers/telegram-webhook.ts @@ -1,18 +1,20 @@ -import { Value } from "@sinclair/typebox/value"; -import { envValidator, Env } from "../types"; +import { Env } from "../types"; import { TelegramBotSingleton } from "#root/types/telegram-bot-single.js"; import { logger } from "#root/utils/logger.js"; export async function handleTelegramWebhook(request: Request, env: Env): Promise { - const isOk = envValidator.test(env); - if (!isOk) { - const errors = Array.from(envValidator.errors(env)); - logger.error(`Invalid bot env: `, { errors }); + let server; + try { + server = (await TelegramBotSingleton.initialize(env)).getServer(); + } catch (er) { + logger.error("Error initializing TelegramBotSingleton", { er }); + return new Response("Error initializing TelegramBotSingleton", { status: 500, statusText: "Internal Server Error" }); } - const settings = Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)); - - const server = TelegramBotSingleton.getInstance().getServer(); - - return server.fetch(request, settings); + try { + return server.fetch(request, env); + } catch (er) { + logger.error("Error fetching request from hono server", { er }); + return new Response("Error fetching request from hono server", { status: 500, statusText: "Internal Server Error" }); + } } diff --git a/src/server/index.ts b/src/server/index.ts index 4dcd389..08c86c7 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -58,9 +58,7 @@ export function createServer(dependencies: Dependencies) { ); }); - server.get("/", (c) => c.json({ status: true })); server.post( - "/webhook", webhookCallback(bot, "hono", { secretToken: config.TELEGRAM_BOT_ENV.botSettings.TELEGRAM_BOT_WEBHOOK_SECRET, }) diff --git a/src/types/telegram-bot-single.ts b/src/types/telegram-bot-single.ts index 6de3625..1a7fd44 100644 --- a/src/types/telegram-bot-single.ts +++ b/src/types/telegram-bot-single.ts @@ -19,26 +19,27 @@ export class TelegramBotSingleton { botSettings: { TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_WEBHOOK, ALLOWED_UPDATES }, }, } = env; + if (!TelegramBotSingleton._instance) { TelegramBotSingleton._instance = new TelegramBotSingleton(); TelegramBotSingleton._bot = createBot(TELEGRAM_BOT_TOKEN, { config: env, logger, }); - await TelegramBotSingleton._bot.api.setWebhook(TELEGRAM_BOT_WEBHOOK, { allowed_updates: ALLOWED_UPDATES, - drop_pending_updates: true, secret_token: env.TELEGRAM_BOT_ENV.botSettings.TELEGRAM_BOT_WEBHOOK_SECRET, }); - - TelegramBotSingleton._server = createServer({ - bot: TelegramBotSingleton._bot, - config: env, - logger, - }); + try { + TelegramBotSingleton._server = createServer({ + bot: TelegramBotSingleton._bot, + config: env, + logger, + }); + } catch (er) { + logger.error("Error initializing TelegramBotSingleton", { er }); + } } - return TelegramBotSingleton._instance; } diff --git a/src/worker.ts b/src/worker.ts index 4326e47..fab8a85 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -1,5 +1,4 @@ import { Env, envValidator } from "./types"; -import { isGithubPayload, isTelegramPayload } from "./types/typeguards"; import { handleGithubWebhook } from "./handlers/github-webhook"; import { handleTelegramWebhook } from "./handlers/telegram-webhook"; import manifest from "../manifest.json"; @@ -10,73 +9,51 @@ import { Value } from "@sinclair/typebox/value"; export default { async fetch(request: Request, env: Env): Promise { - if (request.method === "GET") { - const url = new URL(request.url); - if (url.pathname === "/manifest.json") { - return new Response(JSON.stringify(manifest), { - headers: { "content-type": "application/json" }, - }); - } - } + const url = new URL(request.url); + const path = url.pathname; - if (request.method !== "POST") { - return new Response(JSON.stringify({ error: `Only POST requests are supported.` }), { - status: 405, - headers: { "content-type": "application/json", Allow: "POST" }, - }); - } - const contentType = request.headers.get("content-type"); - if (contentType !== "application/json") { - return new Response(JSON.stringify({ error: `Error: ${contentType} is not a valid content type` }), { - status: 400, - headers: { "content-type": "application/json" }, - }); - } - let payload; + let envSettings; try { - payload = await request.clone().json(); + envSettings = Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)); } catch (err) { - return new Response(JSON.stringify({ error: "Invalid JSON payload", err }), { + return new Response(JSON.stringify({ error: "Invalid environment provided" }), { status: 400, headers: { "content-type": "application/json" }, }); } - const envSettings = Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)); - if (!envValidator.test(envSettings)) { - const errors: string[] = []; - for (const error of envValidator.errors(envSettings)) { - console.error(error); - errors.push(`${error.path}: ${error.message}`); + + if (["/telegram", "/telegram/"].includes(path)) { + try { + await TelegramBotSingleton.initialize(envSettings); + PluginContext.initialize(await request.clone().json(), envSettings); + return await handleTelegramWebhook(request, envSettings); + } catch (err) { + console.log("/webhook entry error", err); + return handleUncaughtError(err); } - return new Response(JSON.stringify({ error: `Error: "Invalid environment provided. ${errors.join("; ")}"` }), { - status: 400, - headers: { "content-type": "application/json" }, - }); } - // inits the worker with the telegram bot - await TelegramBotSingleton.initialize(envSettings); - - try { - if (isGithubPayload(payload)) { - // inits the worker with the plugin context for this call - PluginContext.initialize(payload, envSettings); - await handleGithubWebhook(request, envSettings); - } else if (isTelegramPayload(payload)) { - await handleTelegramWebhook(request, envSettings); - } else { - return new Response(JSON.stringify({ error: "Invalid environment provided" }), { - status: 400, + if (request.method === "GET") { + if (path === "/manifest.json") { + return new Response(JSON.stringify(manifest), { headers: { "content-type": "application/json" }, }); } + } - return new Response(JSON.stringify({ success: true }), { - status: 200, + const contentType = request.headers.get("content-type"); + if (contentType !== "application/json") { + return new Response(JSON.stringify({ error: `Error: ${contentType} is not a valid content type` }), { + status: 400, headers: { "content-type": "application/json" }, }); + } + + try { + return await handleGithubWebhook(request, envSettings); } catch (err) { + console.log("github entry error", err); return handleUncaughtError(err); } }, diff --git a/wrangler.toml b/wrangler.toml index e14cbbe..0f0f0db 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,4 +1,4 @@ -name = "your-plugin-name" +name = "ubiquity-os-telegram-bot" main = "src/worker.ts" compatibility_date = "2024-08-26" node_compat = true diff --git a/yarn.lock b/yarn.lock index 79f58fd..ee04ad0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3600,7 +3600,7 @@ before-after-hook@^3.0.2: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-3.0.2.tgz#d5665a5fa8b62294a5aa0a499f933f4a1016195d" integrity sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A== -big-integer@^1.6.48: +big-integer@^1.6.48, big-integer@^1.6.52: version "1.6.52" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== From a2238884d9b7a0a4bd6a2ed3a42340dee438db86 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 26 Sep 2024 05:53:42 +0100 Subject: [PATCH 62/76] chore: delete workflow-function references, getDeepValue, app_id & pkey, repo_dispatch --- src/bot/mtproto-api/bot/mtproto.ts | 2 +- .../bot/scripts/sms-auth/setup-env.ts | 14 +---- src/handlers/repository-dispatch.ts | 56 ------------------- src/handlers/worker-proxy.ts | 7 +-- src/handlers/workflow-functions.ts | 49 ---------------- src/handlers/workflow-proxy.ts | 14 +---- src/types/env.ts | 28 ++-------- src/utils/add-comment-to-issues.ts | 15 +++-- src/utils/get-deep-value.ts | 21 ------- src/workflow-entry.ts | 14 ----- 10 files changed, 24 insertions(+), 196 deletions(-) delete mode 100644 src/handlers/repository-dispatch.ts delete mode 100644 src/handlers/workflow-functions.ts delete mode 100644 src/utils/get-deep-value.ts diff --git a/src/bot/mtproto-api/bot/mtproto.ts b/src/bot/mtproto-api/bot/mtproto.ts index dcfabf5..03e7953 100644 --- a/src/bot/mtproto-api/bot/mtproto.ts +++ b/src/bot/mtproto-api/bot/mtproto.ts @@ -6,7 +6,7 @@ import { createClient, SupabaseClient } from "@supabase/supabase-js"; dotenv.config(); /** - * This class MUST ONLY be used in the context of workflow-functions as + * This class MUST ONLY be used in the context of workflows as * it requires a Node.js environment which is not available with Cloudflare Workers. * * An extension of the BaseMtProto class that integrates with the Supabase based diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts index 6cb415e..305ee3c 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts @@ -33,10 +33,6 @@ class SetUpHandler { SUPABASE_SERVICE_KEY: "", SUPABASE_URL: "", }, - ubiquityOsSettings: { - APP_ID: 0, - APP_PRIVATE_KEY: "", - }, }, }; @@ -55,7 +51,7 @@ class SetUpHandler { { type: "input", name: "TELEGRAM_BOT_REPOSITORY_FULL_NAME", - message: "Enter your repository name (owner/repo).", + message: "Enter your repository name (owner/repo). Need to store your secrets in your repository.", }, ], }, @@ -207,10 +203,6 @@ class SetUpHandler { SUPABASE_SERVICE_KEY: answers["Storage settings"]["SUPABASE_SERVICE_KEY"], SUPABASE_URL: answers["Storage settings"]["SUPABASE_URL"], }, - ubiquityOsSettings: { - APP_ID: Number(answers["Ubiquity OS settings"]["APP_ID"]), - APP_PRIVATE_KEY: answers["Ubiquity OS settings"]["APP_PRIVATE_KEY"], - }, }, }; @@ -219,13 +211,12 @@ class SetUpHandler { async validateEnv() { const env = this.env.TELEGRAM_BOT_ENV; - const { botSettings, mtProtoSettings, storageSettings, ubiquityOsSettings } = env; + const { botSettings, mtProtoSettings, storageSettings } = env; const merged = { ...botSettings, ...mtProtoSettings, ...storageSettings, - ...ubiquityOsSettings, }; const keys = Object.keys(merged); @@ -310,7 +301,6 @@ class SetUpHandler { const octokit = new Octokit({ auth: process.env.GITHUB_PAT_TOKEN }); const secrets = { TELEGRAM_BOT_ENV: this.env.TELEGRAM_BOT_ENV, - TELEGRAM_BOT_REPOSITORY_FULL_NAME: process.env.TELEGRAM_BOT_REPOSITORY_FULL_NAME, }; try { diff --git a/src/handlers/repository-dispatch.ts b/src/handlers/repository-dispatch.ts deleted file mode 100644 index 6ea4948..0000000 --- a/src/handlers/repository-dispatch.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { PluginContext } from "#root/types/plugin-context-single.js"; -import { App } from "octokit"; -import { Context } from "../types"; - -/** - * Used by the worker instance to kick off workflows within it's own repository. - * - * These workflows are extensions of the worker allowing for more complex operations - * to be performed outside of Cloudflare Workers' limitations. - */ -export async function repositoryDispatch(context: Context, workflow: string) { - const inputs = PluginContext.getInstance().getInputs(); - const { - logger, - env: { TELEGRAM_BOT_REPOSITORY_FULL_NAME }, - } = context; - if (!TELEGRAM_BOT_REPOSITORY_FULL_NAME) { - throw new Error("TELEGRAM_BOT_REPOSITORY_FULL_NAME env variable is not set"); - } - - const [owner, repository] = TELEGRAM_BOT_REPOSITORY_FULL_NAME.split("/"); - - const { - env: { - TELEGRAM_BOT_ENV: { - ubiquityOsSettings: { APP_ID, APP_PRIVATE_KEY }, - }, - }, - config: { targetBranch }, - } = context; - const app = new App({ appId: APP_ID, privateKey: APP_PRIVATE_KEY }); - const installation = await app.octokit.rest.apps.getRepoInstallation({ owner, repo: repository }); - - const octokit = await app.getInstallationOctokit(installation.data.id); - - logger.info(`Dispatching workflow function: ${workflow}`); - - /** - * We'll hit the main workflow entry and pass in the same inputs so - * that it essentially runs on the same context as the worker. - */ - - Reflect.deleteProperty(inputs, "signature"); - - return await octokit.rest.actions.createWorkflowDispatch({ - owner, - repo: repository, - workflow_id: "compute.yml", - ref: targetBranch ?? "development", - inputs: { - ...inputs, - eventPayload: JSON.stringify(context.payload), - settings: JSON.stringify(context.config), - }, - }); -} diff --git a/src/handlers/worker-proxy.ts b/src/handlers/worker-proxy.ts index 7ba2701..2f5b800 100644 --- a/src/handlers/worker-proxy.ts +++ b/src/handlers/worker-proxy.ts @@ -1,6 +1,5 @@ import { ProxyCallbacks } from "#root/types/proxy.js"; import { Context, SupportedEventsU } from "../types"; -import { closeWorkroom, createWorkroom, reOpenWorkroom } from "./workflow-functions"; /** * The `callbacks` object defines an array of callback functions for each supported event type. @@ -9,11 +8,7 @@ import { closeWorkroom, createWorkroom, reOpenWorkroom } from "./workflow-functi * callback in an array. This design allows for extensibility and flexibility, enabling * us to add more callbacks for a particular event without modifying the core logic. */ -const callbacks = { - "issues.labeled": [createWorkroom], - "issues.closed": [closeWorkroom], - "issues.reopened": [reOpenWorkroom], -} as ProxyCallbacks; +const callbacks = {} as ProxyCallbacks; /** * The `proxyCallbacks` function returns a Proxy object that intercepts access to the diff --git a/src/handlers/workflow-functions.ts b/src/handlers/workflow-functions.ts deleted file mode 100644 index 29560f9..0000000 --- a/src/handlers/workflow-functions.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { CallbackResult } from "#root/types/proxy.js"; -import { logger } from "#root/utils/logger.js"; -import { Context, SupportedEvents } from "../types"; -import { repositoryDispatch } from "./repository-dispatch"; - -/** - * It is expected that these workflows being dispatched are in the same repository - * as the worker. - * - * Each workflow enters through `compute.yml` like a typical action plugin with - * the worker forwarding the payload to the appropriate workflow event handler. - * - * The workflow instance has access and more privileges than the worker instance - * because it is connected through the MTProto API vs the Bot rest API. - * - * Consider the following: - * - * - The worker is a bot that can only perform actions that are allowed by the - * Telegram Bot API. - * - * - The workflow is a personal user account that can perform any action that is - * allowed by the Telegram API. - * - * - If the worker needs to perform an action that is not allowed by the Bot API, - * it should dispatch a workflow to perform the action instead. - */ - -/** - * The logic for this function can be found in [../bot/mtproto-api/workrooms/create-chat.ts](../bot/mtproto-api/workrooms/create-chat.ts) - */ -export async function createWorkroom(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { - await repositoryDispatch(context, "create-telegram-chat").catch(logger.error); - return { status: 200, reason: "workflow_dispatched" }; -} -/** - * The logic for this function can be found in [../bot/mtproto-api/workrooms/close-chat.ts](../bot/mtproto-api/workrooms/close-chat.ts) - */ -export async function closeWorkroom(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { - await repositoryDispatch(context, "close-telegram-chat").catch(logger.error); - return { status: 200, reason: "workflow_dispatched" }; -} - -/** - * The logic for this function can be found in [../bot/mtproto-api/workrooms/reopen-chat.ts](../bot/mtproto-api/workrooms/reopen-chat.ts) - */ -export async function reOpenWorkroom(context: Context<"issues.reopened", SupportedEvents["issues.reopened"]>): Promise { - await repositoryDispatch(context, "reopen-telegram-chat").catch(logger.error); - return { status: 200, reason: "workflow_dispatched" }; -} diff --git a/src/handlers/workflow-proxy.ts b/src/handlers/workflow-proxy.ts index 8d0729e..4daa56c 100644 --- a/src/handlers/workflow-proxy.ts +++ b/src/handlers/workflow-proxy.ts @@ -6,17 +6,9 @@ import { Context, SupportedEventsU } from "../types"; import { handleCallback } from "./worker-proxy"; /** - * These are function which get dispatched by this worker to fire off workflows - * in the repository. We enter through the main `compute.yml` just like a typical - * action plugin would, we forward the same payload that the worker received to - * the workflow the same way that the kernel does. - * - * - First event fires, `issues.labeled` and the worker catches it. - * - The worker then dispatches a workflow to `compute.yml` with the event name as the input. - * - The workflow receives a `issues.labeled` payload and runs the `createChat` function. - * - * I.e we're essentially running the first dual action/worker plugin which is - * ideal for telegram-bot as it's a bot that needs to be able to be super flexible. + * These functions are run via workflow triggers. They can only run + * if this plugin is defined in `ubiquibot-config.yml` pointing to the workflow URL, + * see the README for more information on how to set this up. */ export const workflowCallbacks = { "issues.labeled": [createChat], diff --git a/src/types/env.ts b/src/types/env.ts index 74dd809..3a76ffb 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -48,30 +48,13 @@ const mtProtoSettings = T.Object({ /** * Obtained from https://my.telegram.org/apps */ - TELEGRAM_APP_ID: T.Transform(T.Union([T.String(), T.Number()])) - .Decode((str) => Number(str)) - .Encode((num) => num.toString()), + TELEGRAM_APP_ID: T.Number(), /** * Obtained from https://my.telegram.org/apps */ TELEGRAM_API_HASH: T.String(), }); -const ubiquityOsSettings = T.Object({ - /** - * Your UbiquityOS app id - */ - APP_ID: T.Transform(T.Unknown()) - .Decode((str) => Number(str)) - .Encode((num) => num.toString()), - /** - * Your UbiquityOS private key - */ - APP_PRIVATE_KEY: T.Transform(T.Unknown()) - .Decode((str) => String(str)) - .Encode((str) => str), -}); - const storageSettings = T.Object({ /** * The supabase instance url for storing chats, sessions, etc. @@ -86,20 +69,21 @@ const storageSettings = T.Object({ const TELEGRAM_BOT_ENV = T.Object({ botSettings, mtProtoSettings, - ubiquityOsSettings, storageSettings, }); +const botEnvValidator = new StandardValidator(TELEGRAM_BOT_ENV); + export const env = T.Object({ - TELEGRAM_BOT_REPOSITORY_FULL_NAME: T.Optional(T.String({ examples: ["owner/repo"], default: "ubiquibot/telegram-bot" })), TELEGRAM_BOT_ENV: T.Transform(T.Union([T.String(), TELEGRAM_BOT_ENV])) .Decode((str) => { if (typeof str === "string") { const obj = JSON.parse(str) as StaticDecode; - if (!obj.botSettings || !obj.mtProtoSettings || !obj.ubiquityOsSettings || !obj.storageSettings) { - throw new Error("Missing required environment variables for Telegram Bot settings"); + if (!botEnvValidator.test(obj)) { + throw new Error('Invalid TELEGRAM_BOT_ENV'); } + return obj; } return str; diff --git a/src/utils/add-comment-to-issues.ts b/src/utils/add-comment-to-issues.ts index 7ec3f84..b00fe3a 100644 --- a/src/utils/add-comment-to-issues.ts +++ b/src/utils/add-comment-to-issues.ts @@ -1,5 +1,4 @@ import { Context } from "#root/types/context.js"; -import { getDeepValue } from "#root/utils/get-deep-value.js"; /** * Ideally pass in owner, repo, and issueNumber, but if not provided, @@ -10,9 +9,17 @@ export async function addCommentToIssue(context: Context, msg: string, owner?: s logger.info(`Adding comment to ${owner}/${repo}#${issueNumber}`); if (!owner || !repo || !issueNumber) { - owner = getDeepValue(context, "payload.repository.owner.login"); - repo = getDeepValue(context, "payload.repository.name"); - issueNumber = getDeepValue(context, "payload.issue.number"); + if ("issue" in context.payload) { + owner = context.payload.repository.owner.login; + repo = context.payload.repository.name; + issueNumber = context.payload.issue.number; + } + + if ("pull_request" in context.payload) { + owner = context.payload.repository.owner.login; + repo = context.payload.repository.name; + issueNumber = context.payload.pull_request.number; + } } if (!owner || !repo || !issueNumber) { diff --git a/src/utils/get-deep-value.ts b/src/utils/get-deep-value.ts deleted file mode 100644 index 003627d..0000000 --- a/src/utils/get-deep-value.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Context } from "../types"; -/** - * This function is a utility that allows us to access deeply nested properties in an object - * primarily for use with the context.payload object. It should not be overused and the developer - * should be aware of the potential performance implications of using this function. - * - * Example usage: - * - * - `getDeepValue(context, "payload.repository.owner.login")` will return the owner - * - `getDeepValue(context, ["payload", "repository", "owner", "login"])` will return the owner - */ -export function getDeepValue(obj: T, path: string | string[]): TK { - const pathArray = Array.isArray(path) ? path : path.split("."); - const [head, ...tail] = pathArray; - - if (tail.length === 0) { - return obj[head as keyof T] as TK; - } - - return getDeepValue(obj[head as keyof T] as Context, tail) as TK; -} diff --git a/src/workflow-entry.ts b/src/workflow-entry.ts index 28410d4..ef94846 100644 --- a/src/workflow-entry.ts +++ b/src/workflow-entry.ts @@ -61,20 +61,6 @@ export async function run() { } } -// Might use this later to receive data back from it's own workflows -// async function returnDataToKernel(repoToken: string, stateId: string, output: object) { -// const octokit = new Octokit({ auth: repoToken }); -// await octokit.repos.createDispatchEvent({ -// owner: github.context.repo.owner, -// repo: github.context.repo.repo, -// event_type: "return_data_to_ubiquibot_kernel", -// client_payload: { -// state_id: stateId, -// output: JSON.stringify(output), -// }, -// }); -// } - run() .then((result) => { core.setOutput("result", result); From 29f6d65025495c364b7d112c5a94c1d87695d011 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 26 Sep 2024 06:19:47 +0100 Subject: [PATCH 63/76] chore: readme --- .github/workflows/compute.yml | 4 +--- README.md | 27 +++++++++------------------ 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 5d17308..69b55ad 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -23,7 +23,6 @@ jobs: permissions: write-all env: TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} - TELEGRAM_BOT_REPOSITORY_FULL_NAME: ${{ secrets.TELEGRAM_BOT_REPOSITORY_FULL_NAME }} steps: - uses: actions/checkout@v4 @@ -40,5 +39,4 @@ jobs: run: npx tsx ./src/workflow-entry.ts id: telegram-bot env: - TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} - TELEGRAM_BOT_REPOSITORY_FULL_NAME: ${{ secrets.TELEGRAM_BOT_REPOSITORY_FULL_NAME }} + TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} \ No newline at end of file diff --git a/README.md b/README.md index 1dbbc56..ab929c1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # `@ubiquity-os/telegram-bot` -A dual-architecture Telegram bot for Ubiquity OS, uniquely combining Cloudflare Workers and GitHub Actions to deliver seamless integration with both Telegram and GitHub. This hybrid plugin is the first of its kind to support both worker and workflow functionality, running across Cloudflare V8 and Node.js environments for enhanced flexibility and performance across multiple runtimes. +A Telegram bot for Ubiquity OS, uniquely combining Cloudflare Workers and GitHub Actions to deliver seamless integration with both Telegram and GitHub. This hybrid plugin is the first of its kind to support both worker and workflow functionality, running across Cloudflare V8 and Node.js environments for enhanced flexibility and performance across multiple runtimes. ## Table of Contents @@ -39,7 +39,7 @@ This bot operates in two parts: #### Ubiquity OS Plugin - **Worker Plugin**: This is a worker plugin with workflow capabilities, allowing it to run on both Cloudflare Workers and GitHub Actions. -- **Actions as a Feature**: By forwarding worker requests to the workflows, we enable collaboration between the two, maximizing functionality. +- **Actions as a Feature**: With a dual-scoped configuration we target both the Worker and Workflow instances, enabling seamless integration with Ubiquity OS. - **Hybrid Architecture**: Combines the best of both worlds, leveraging Cloudflare Workers for speed and GitHub Actions for long-running features or those that require a Node.js environment. - **Bridges the Gap**: Connects our GitHub events to our Telegram bot instantaneously, enabling real-time interactions and seamless integration. @@ -65,7 +65,7 @@ This bot operates in two parts: #### Environment Variables -The `TELEGRAM_BOT_ENV` is a single JSON object that encapsulates all necessary environment variables for the bot's operation. It consists of four key sections: `botSettings`, `mtProtoSettings`, `storageSettings`, and `ubiquityOsSettings`. +The `TELEGRAM_BOT_ENV` is a single JSON object that encapsulates all necessary environment variables for the bot's operation. It consists of three key sections: `botSettings`, `mtProtoSettings`, and `storageSettings`. You can set up your environment variables by using the provided utility script: @@ -85,8 +85,6 @@ The environment variables are stored in the following locations: 1. **botSettings**: Contains bot-specific settings like `TELEGRAM_BOT_TOKEN`, `TELEGRAM_BOT_WEBHOOK_SECRET`, etc. 2. **mtProtoSettings**: Contains settings for the MTProto API like `TELEGRAM_APP_ID`, `TELEGRAM_API_HASH`, etc. 3. **storageSettings**: Contains settings for the Supabase database like `SUPABASE_URL`, `SUPABASE_SERVICE_KEY`, etc. -4. **ubiquityOsSettings**: Contains settings for the UbiquityOS Kernel like `APP_PRIVATE_KEY`, `APP_ID`, etc. -5. **TELEGRAM_BOT_REPOSITORY_FULL_NAME**: A standalone single string value for the full repository name (e.g., `ubiquity-os/telegram-bot`). ```typescript interface TELEGRAM_BOT_ENV { @@ -104,10 +102,6 @@ interface TELEGRAM_BOT_ENV { SUPABASE_URL: string; // Supabase URL SUPABASE_SERVICE_KEY: string; // Supabase Service Key }; - ubiquityOsSettings: { - APP_PRIVATE_KEY: string; // GitHub App Private Key - APP_ID: number; // GitHub App ID - }; } ``` @@ -127,17 +121,14 @@ interface TELEGRAM_BOT_ENV { #### GitHub Configuration 1. Ensure your Ubiquity OS Kernel is set up. -2. Add `APP_PRIVATE_KEY` and `APP_ID` to your environment variables. -3. Configure the plugin in your private organization’s repository: +2. Configure the plugin in your private organization’s repository: ```yaml - uses: - - skipBotEvents: false - - plugin: http://localhost:3000 - runsOn: ["issues.opened", "issues.labeled", "issues.reopened", "issues.closed"] - with: - botId: 00000000 - targetBranch: development + - plugin: http://localhost:3000 + with: + botId: 00000000 + targetBranch: development ``` ### Usage @@ -146,7 +137,7 @@ interface TELEGRAM_BOT_ENV { 2. Start your Ubiquity OS Kernel with the plugin installed in your repository. 3. Run `yarn sms-auth` to authenticate your personal Telegram account with MTProto. 4. Start the worker instance with `yarn worker`. -5. In another terminal, run `smee -u https://smee.io/your-webhook-url -P "/webhook"` to receive Telegram webhook payloads locally. +5. In another terminal, run `smee -u https://smee.io/your-webhook-url -P "/telegram"` to receive Telegram webhook payloads locally. 6. Interact with the bot in Telegram chats or trigger GitHub webhooks as defined in `manifest.json`. ### Commands From ec54f4cdf8fb7d3cb5bb77e6bcebdcab515c0a2f Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 26 Sep 2024 06:39:28 +0100 Subject: [PATCH 64/76] chore: remove last of refs --- .env.example | 3 +++ .../bot/scripts/sms-auth/auth-handler.ts | 8 ++------ .../bot/scripts/sms-auth/setup-env.ts | 17 +---------------- 3 files changed, 6 insertions(+), 22 deletions(-) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..cee17a9 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +# Only `yarn setup-env` requires these variables to be set +TELEGRAM_BOT_REPOSITORY_FULL_NAME= +GITHUB_PAT_TOKEN= \ No newline at end of file diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts index 05e83bc..40f91e4 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts @@ -30,16 +30,15 @@ export class AuthHandler { throw new Error("Failed to parse environment variables for Telegram Bot"); } - const { botSettings, mtProtoSettings, ubiquityOsSettings, storageSettings } = parsedEnv; + const { botSettings, mtProtoSettings, storageSettings } = parsedEnv; - if (!botSettings || !mtProtoSettings || !ubiquityOsSettings || !storageSettings) { + if (!botSettings || !mtProtoSettings || !storageSettings) { throw new Error("Missing required environment variables for Telegram Bot settings"); } const { TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_WEBHOOK } = botSettings; const { TELEGRAM_APP_ID, TELEGRAM_API_HASH } = mtProtoSettings; const { SUPABASE_URL, SUPABASE_SERVICE_KEY } = storageSettings; - const { APP_ID, APP_PRIVATE_KEY } = ubiquityOsSettings; if (!TELEGRAM_BOT_TOKEN || !TELEGRAM_BOT_WEBHOOK) { throw new Error("Missing required environment variables for Telegram Bot settings"); @@ -49,9 +48,6 @@ export class AuthHandler { throw new Error("Missing required environment variables for MtProto settings"); } - if (!APP_ID || !APP_PRIVATE_KEY) { - throw new Error("Missing required environment variables for UbiquityOS settings"); - } if (!SUPABASE_URL || !SUPABASE_SERVICE_KEY) { throw new Error("Missing required environment variables for storage settings"); diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts index 305ee3c..3185dff 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts @@ -77,7 +77,7 @@ class SetUpHandler { { type: "input", name: "TELEGRAM_BOT_WEBHOOK", - message: "Any URL used should end with '/telegram'. e.g 'https://example.com/telegram'", + message: "Any URL (except smee.io) used should end with '/telegram'. e.g 'https://example.com/telegram'", }, { type: "input", @@ -121,21 +121,6 @@ class SetUpHandler { }, ], }, - { - title: "Ubiquity OS settings", - questions: [ - { - type: "input", - name: "APP_ID", - message: "Enter your Ubiquity OS app id. This can be obtained from your kernel env vars.", - }, - { - type: "input", - name: "APP_PRIVATE_KEY", - message: "Enter your Ubiquity OS private key. This can be obtained from your kernel env vars.", - }, - ], - }, ]; shouldTestToken = !!process.env.GITHUB_PAT_TOKEN; From 1e3edc3b23b927c5347b22cab45418c13f92c6fc Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 26 Sep 2024 06:42:01 +0100 Subject: [PATCH 65/76] chore: remove targetBranch --- README.md | 1 - src/types/plugin-inputs.ts | 4 ---- 2 files changed, 5 deletions(-) diff --git a/README.md b/README.md index ab929c1..b0db1f8 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,6 @@ interface TELEGRAM_BOT_ENV { - plugin: http://localhost:3000 with: botId: 00000000 - targetBranch: development ``` ### Usage diff --git a/src/types/plugin-inputs.ts b/src/types/plugin-inputs.ts index da45c95..9702225 100644 --- a/src/types/plugin-inputs.ts +++ b/src/types/plugin-inputs.ts @@ -18,10 +18,6 @@ export const pluginSettingsSchema = T.Object({ botId: T.Transform(T.Unknown()) .Decode((value) => Number(value)) .Encode((value) => value.toString()), - /** - * The target branch to run the workflows on. Will default to the `development` branch. - */ - targetBranch: T.Optional(T.String({ default: "development" })), }); export const pluginSettingsValidator = new StandardValidator(pluginSettingsSchema); From 9a0a5a1bd631d71e8d8e744041e377fa43da762e Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 26 Sep 2024 09:12:45 +0100 Subject: [PATCH 66/76] chore: update readme --- README.md | 80 +++++++++++++++---- .../{migrations.sql => migrations/init.sql} | 0 2 files changed, 66 insertions(+), 14 deletions(-) rename supabase/{migrations.sql => migrations/init.sql} (100%) diff --git a/README.md b/README.md index b0db1f8..ebd7a10 100644 --- a/README.md +++ b/README.md @@ -105,11 +105,7 @@ interface TELEGRAM_BOT_ENV { } ``` -#### Supabase Configuration -1. Create or use an existing Supabase project. -2. Copy and run the SQL migration file from `./supabase/migrations` in the Supabase dashboard. -3. Add your `SUPABASE_URL` and `SUPABASE_SERVICE_KEY` to your environment variables. #### Telegram Configuration @@ -130,18 +126,72 @@ interface TELEGRAM_BOT_ENV { botId: 00000000 ``` -### Usage +#### Supabase Configuration +1. Create or use an existing Supabase project. +2. Run the migration or copypaste the SQL migration file from `./supabase/migrations` in the Supabase dashboard. +3. Add your `SUPABASE_URL` and `SUPABASE_SERVICE_KEY` to your environment variables. + + +##### Running the Migration + +1. Install the Supabase CLI. If you don't have it installed yet, you can install it via npm: + + ```bash + npm install -g supabase + ``` + +2. Make sure your Supabase project is initialized. If not, initialize it: + + ```bash + supabase init + ``` -1. Follow each part of the environment setup to configure your bot. -2. Start your Ubiquity OS Kernel with the plugin installed in your repository. -3. Run `yarn sms-auth` to authenticate your personal Telegram account with MTProto. -4. Start the worker instance with `yarn worker`. -5. In another terminal, run `smee -u https://smee.io/your-webhook-url -P "/telegram"` to receive Telegram webhook payloads locally. -6. Interact with the bot in Telegram chats or trigger GitHub webhooks as defined in `manifest.json`. +3. Set up your `.env` file with your Supabase credentials (or make sure you have already logged in using `supabase login`). + +4. To run the migrations on your local environment, use: + + ```bash + supabase db reset + ``` + + This command will reset your local database and apply all migrations. + +5. To push migrations to your remote database, use: + + ```bash + supabase db push + ``` + + This will apply all migrations to the remote Supabase database. + +For more detailed information, refer to the official [Supabase documentation](https://supabase.com/docs). + + +## Testing Locally + +1. Spin up a Supabase instance and run the migration/copypaste the SQL file into the SQL editor. +2. Run `yarn setup-env` to set up your environment variables. `WEBHOOK_URL` should be set to your local Smee URL initially with no path. +3. Run `yarn sms-auth` to authenticate your personal Telegram account with MTProto. This will store your session in Supabase. +4. Run `yarn worker` to start the Cloudflare Worker instance. +5. Run `smee -u https://smee.io/your-webhook-url -P "/telegram"` to receive Telegram webhook payloads locally. +6. Define the plugin twice in your `ubiquibot-config.yml` file, one pointing at the Cloudflare Worker instance or localhost and the other at the GitHub Actions workflow. +7. Interact with the bot in Telegram chats or trigger GitHub webhooks as defined in `manifest.json`. +8. Run `yarn deploy` to deploy the Cloudflare Worker instance. +9. Paste or push your CF secrets but this time replace the `WEBHOOK_URL` with the Cloudflare Worker URL. +10. Once deployed, use `/setwebhook` to set the bot's webhook URL to the Cloudflare Worker instance. It may take a minute or two to propagate. +11. If you need to revert back to your Smee URL, then simply ping your local worker and it will reset the webhook URL (example below). + + ```bash + curl -X POST http://localhost:3000/telegram -H "Content-Type: application/json" -d '{"message": ""}' + ``` ### Commands -TODO: Commands are not fully implemented yet. A couple of helper commands for obtaining IDs etc are available. +- **/myid**: Get your Telegram User ID. +- **/botid**: Get the bot's Telegram User ID. +- **/chatid**: Get the chat ID. +- **/setwebhook**: Set the bot's webhook url. +- **/setcommands**: Set the bot's commands. ## Repository Structure @@ -173,6 +223,8 @@ TODO: Commands are not fully implemented yet. A couple of helper commands for ob ## Considerations -The bot has two "branches" due to Cloudflare Workers' limitations in handling long-running processes. The **Worker** handles most bot commands and API interactions, while the **Workflow** manages features the bot cannot perform. +- The `WEBHOOK_URL` is set on each call essentially, so the worker should always have it's own URL set as the webhook environment variable. Your local worker preferably retains the Smee URL env var which allows you to switch between the two easily. +- If you have to ping and reset the webhook URL, you will see an `unauthorized` error in the worker logs. This is expected and you can verify a successful reset by using a command like `/myid`. + + -Most functionality is handled by the **Bot API**; the **Client API** is only used for advanced tasks. Due to the nature of the MTProto API, the owner of the personal account must run `yarn sms-auth` to authenticate the bot once, after which it can run uninterrupted. It is not fool-proof and it can be "knocked out" by erroneous auth replacement ceremonies. diff --git a/supabase/migrations.sql b/supabase/migrations/init.sql similarity index 100% rename from supabase/migrations.sql rename to supabase/migrations/init.sql From 1e212f818e66155d6d51c9edff034d020ec45b84 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Thu, 26 Sep 2024 09:16:36 +0100 Subject: [PATCH 67/76] chore: comment about no paths in config --- README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ebd7a10..119de7f 100644 --- a/README.md +++ b/README.md @@ -119,11 +119,18 @@ interface TELEGRAM_BOT_ENV { 1. Ensure your Ubiquity OS Kernel is set up. 2. Configure the plugin in your private organization’s repository: +These URLs **do not** contain url paths, only the domain. This is because as standard, the main entry (`/`) is used for github events and the `/telegram` path is used for Telegram events which is set via the bot's `/setwebhook` command or by worker environment variable. + ```yaml -- uses: - - plugin: http://localhost:3000 - with: - botId: 00000000 +plugins: + - uses: + - plugin: https://cloudflare-worker-url.dev + with: + botId: 00000000 + - uses: + - plugin: http://localhost:3000 + with: + botId: 00000000 ``` #### Supabase Configuration From 14c006f33dcc8ee0e2d4013a95e7c6ad355a8730 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 27 Sep 2024 03:37:08 +0100 Subject: [PATCH 68/76] chore: remove #root, downgrade deps, remove test --- .cspell.json | 1 + .github/workflows/compute.yml | 4 +- README.md | 66 +++---- eslint.config.mjs | 2 +- manifest.json | 2 +- package.json | 15 +- src/adapters/supabase/helpers/supabase.ts | 2 +- src/bot/features/admin/admin.ts | 10 +- src/bot/features/commands/groups/ban.ts | 6 +- .../features/commands/private-chat/bot-id.ts | 6 +- .../commands/private-chat/set-webhook.ts | 28 +-- .../features/commands/private-chat/user-id.ts | 6 +- src/bot/features/commands/shared/chat-id.ts | 6 +- src/bot/features/helpers/unhandled.ts | 6 +- src/bot/features/welcome.ts | 6 +- src/bot/handlers/commands/setcommands.ts | 4 +- src/bot/handlers/error.ts | 6 +- src/bot/helpers/grammy-context.ts | 8 +- src/bot/helpers/logging.ts | 6 +- src/bot/index.ts | 17 +- src/bot/middlewares/session.ts | 6 +- src/bot/mtproto-api/bot/mtproto.ts | 2 +- .../bot/scripts/sms-auth/auth-handler.ts | 5 +- .../bot/scripts/sms-auth/base-mtproto.ts | 2 +- .../bot/scripts/sms-auth/setup-env.ts | 2 +- src/bot/mtproto-api/bot/session.ts | 2 +- src/bot/mtproto-api/workrooms/close-chat.ts | 4 +- src/bot/mtproto-api/workrooms/create-chat.ts | 6 +- src/bot/mtproto-api/workrooms/reopen-chat.ts | 4 +- src/handlers/github-webhook.ts | 2 +- src/handlers/telegram-webhook.ts | 4 +- src/handlers/worker-proxy.ts | 2 +- src/handlers/workflow-proxy.ts | 8 +- src/server/index.ts | 8 +- src/server/middlewares/logger.ts | 2 +- src/types/env.ts | 2 +- src/types/plugin-context-single.ts | 4 +- src/types/typeguards.ts | 2 +- src/utils/add-comment-to-issues.ts | 2 +- src/utils/errors.ts | 2 +- src/worker.ts | 17 +- tests/main.test.ts | 182 +++++++----------- tsconfig.json | 5 +- wrangler.toml | 2 +- yarn.lock | 104 ++++++++-- 45 files changed, 295 insertions(+), 293 deletions(-) diff --git a/.cspell.json b/.cspell.json index 6e083b4..84688c5 100644 --- a/.cspell.json +++ b/.cspell.json @@ -5,6 +5,7 @@ "useGitignore": true, "language": "en", "words": [ + "setwebhook", "Nektos", "dataurl", "devpool", diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index 69b55ad..ab6653e 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -37,6 +37,6 @@ jobs: - name: execute directive run: npx tsx ./src/workflow-entry.ts - id: telegram-bot + id: telegram-bridge env: - TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} \ No newline at end of file + TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} diff --git a/README.md b/README.md index 119de7f..d6bc387 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ -# `@ubiquity-os/telegram-bot` +# `@ubiquity-os/telegram-bridge` -A Telegram bot for Ubiquity OS, uniquely combining Cloudflare Workers and GitHub Actions to deliver seamless integration with both Telegram and GitHub. This hybrid plugin is the first of its kind to support both worker and workflow functionality, running across Cloudflare V8 and Node.js environments for enhanced flexibility and performance across multiple runtimes. +A Telegram bridge for Ubiquity OS, uniquely combining Cloudflare Workers and GitHub Actions to deliver seamless integration with both Telegram and GitHub. This hybrid plugin is the first of its kind to support both worker and workflow functionality, running across Cloudflare V8 and Node.js environments for enhanced flexibility and performance across multiple runtimes. ## Table of Contents - [High-Level Overview](#high-level-overview) - [Architecture Breakdown](#architecture-breakdown) - - [Telegram Bot Components](#telegram-bot-components) + - [Telegram Bridge Components](#telegram-bridge-components) - [Ubiquity OS Plugin](#ubiquity-os-plugin) - [Worker Instance](#worker-instance) - [Workflow Instance](#workflow-instance) @@ -31,7 +31,7 @@ This bot operates in two parts: ### Architecture Breakdown -#### Telegram Bot Components +#### Telegram Bridge Components - **Worker Instance**: Runs Bot API methods on Cloudflare Workers. Handles bot commands, events, and chat interactions using a Telegram Bot created via BotFather. - **Client Instance**: Runs Client API methods on GitHub Actions, responsible for features unavailable to the bot, like creating groups or sending messages as a user. @@ -72,7 +72,7 @@ You can set up your environment variables by using the provided utility script: - Run `yarn setup-env`, which prompts you to enter each value via the CLI. The values will be serialized and stored both locally and in your repository secrets. - **GITHUB_PAT_TOKEN**: Create a classic personal access token (PAT) with the `repo` scope. Set the expiry to 24 hours. This token will be used to generate repository secrets for the environment variables and will be removed from `.env` after the secrets are saved. -- **Account Permission**: The account in which the PAT is associated with _must_ be an `admin` of the repository to be able to save secrets this way. Visit your repository settings `telegram-bot` > `Collaborators & teams` to add the account as an admin first if needed. +- **Account Permission**: The account in which the PAT is associated with _must_ be an `admin` of the repository to be able to save secrets this way. Visit your repository settings `telegram-bridge` > `Collaborators & teams` to add the account as an admin first if needed. The environment variables are stored in the following locations: @@ -105,8 +105,6 @@ interface TELEGRAM_BOT_ENV { } ``` - - #### Telegram Configuration 1. Create a new bot using [BotFather](https://t.me/BotFather). @@ -124,56 +122,55 @@ These URLs **do not** contain url paths, only the domain. This is because as sta ```yaml plugins: - uses: - - plugin: https://cloudflare-worker-url.dev - with: - botId: 00000000 + - plugin: https://cloudflare-worker-url.dev + with: + botId: 00000000 - uses: - - plugin: http://localhost:3000 - with: - botId: 00000000 + - plugin: http://localhost:3000 + with: + botId: 00000000 ``` #### Supabase Configuration + 1. Create or use an existing Supabase project. 2. Run the migration or copypaste the SQL migration file from `./supabase/migrations` in the Supabase dashboard. 3. Add your `SUPABASE_URL` and `SUPABASE_SERVICE_KEY` to your environment variables. - ##### Running the Migration 1. Install the Supabase CLI. If you don't have it installed yet, you can install it via npm: - ```bash - npm install -g supabase - ``` + ```bash + npm install -g supabase + ``` 2. Make sure your Supabase project is initialized. If not, initialize it: - ```bash - supabase init - ``` + ```bash + supabase init + ``` 3. Set up your `.env` file with your Supabase credentials (or make sure you have already logged in using `supabase login`). 4. To run the migrations on your local environment, use: - ```bash - supabase db reset - ``` + ```bash + supabase db reset + ``` - This command will reset your local database and apply all migrations. + This command will reset your local database and apply all migrations. 5. To push migrations to your remote database, use: - ```bash - supabase db push - ``` + ```bash + supabase db push + ``` - This will apply all migrations to the remote Supabase database. + This will apply all migrations to the remote Supabase database. For more detailed information, refer to the official [Supabase documentation](https://supabase.com/docs). - ## Testing Locally 1. Spin up a Supabase instance and run the migration/copypaste the SQL file into the SQL editor. @@ -187,10 +184,10 @@ For more detailed information, refer to the official [Supabase documentation](ht 9. Paste or push your CF secrets but this time replace the `WEBHOOK_URL` with the Cloudflare Worker URL. 10. Once deployed, use `/setwebhook` to set the bot's webhook URL to the Cloudflare Worker instance. It may take a minute or two to propagate. 11. If you need to revert back to your Smee URL, then simply ping your local worker and it will reset the webhook URL (example below). - - ```bash - curl -X POST http://localhost:3000/telegram -H "Content-Type: application/json" -d '{"message": ""}' - ``` + +```bash +curl -X POST http://localhost:3000/telegram -H "Content-Type: application/json" -d '{"message": ""}' +``` ### Commands @@ -232,6 +229,3 @@ For more detailed information, refer to the official [Supabase documentation](ht - The `WEBHOOK_URL` is set on each call essentially, so the worker should always have it's own URL set as the webhook environment variable. Your local worker preferably retains the Smee URL env var which allows you to switch between the two easily. - If you have to ping and reset the webhook URL, you will see an `unauthorized` error in the worker logs. This is expected and you can verify a successful reset by using a command like `/myid`. - - - diff --git a/eslint.config.mjs b/eslint.config.mjs index d9e2a00..ae345aa 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -9,7 +9,7 @@ export default tsEslint.config({ "@typescript-eslint": tsEslint.plugin, "check-file": checkFile, }, - ignores: [".github/knip.ts", "tests/**/*.ts", "eslint.config.mjs", ".wrangler"], + ignores: [".github/knip.ts", "tests/**/*.ts", "eslint.config.mjs", ".wrangler/**/*.{js,ts}", "coverage/**/*.js"], extends: [eslint.configs.recommended, ...tsEslint.configs.recommended, sonarjs.configs.recommended], languageOptions: { parser: tsEslint.parser, diff --git a/manifest.json b/manifest.json index 075f5f1..334c593 100644 --- a/manifest.json +++ b/manifest.json @@ -1,5 +1,5 @@ { - "name": "ubiquity-os/telegram-bot", + "name": "ubiquity-os/telegram-bridge", "description": "Part kernel plugin, part Telegram kernel. This bot is designed to be a bridge between UbiquityOS and Telegram.", "ubiquity:listeners": ["issues.opened", "issues.labeled", "issues.closed", "issues.reopened"] } diff --git a/package.json b/package.json index 63a2f03..294911c 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@ubiquity-os/telegram-bot", + "name": "@ubiquity-os/telegram-bridge", "version": "0.1.0", "description": "Part kernel plugin, part Telegram kernel. This bot is designed to be a bridge between UbiquityOS and Telegram.", "author": "Ubiquity DAO", @@ -9,9 +9,6 @@ "engines": { "node": ">=20.10.0" }, - "imports": { - "#root/*": "./build/src/*" - }, "scripts": { "format": "run-p format:*", "format:lint": "eslint --fix .", @@ -42,9 +39,9 @@ "@grammyjs/hydrate": "1.4.1", "@grammyjs/parse-mode": "1.10.0", "@grammyjs/types": "3.13.0", - "@octokit/rest": "21.0.2", - "@octokit/webhooks": "13.3.0", - "@sinclair/typebox": "0.33.7", + "@octokit/rest": "20.1.1", + "@octokit/webhooks": "13.2.7", + "@sinclair/typebox": "0.32.33", "@supabase/supabase-js": "^2.45.3", "@ubiquity-dao/ubiquibot-logger": "^1.3.1", "big-integer": "^1.6.52", @@ -67,7 +64,7 @@ "@jest/globals": "29.7.0", "@mswjs/data": "0.16.1", "@types/jest": "^29.5.12", - "@types/node": "22.5.0", + "@types/node": "20.14.5", "cspell": "8.14.2", "eslint": "9.9.1", "eslint-config-prettier": "9.1.0", @@ -106,4 +103,4 @@ ] }, "packageManager": "yarn@1.22.22" -} \ No newline at end of file +} diff --git a/src/adapters/supabase/helpers/supabase.ts b/src/adapters/supabase/helpers/supabase.ts index 704511a..3fe0276 100644 --- a/src/adapters/supabase/helpers/supabase.ts +++ b/src/adapters/supabase/helpers/supabase.ts @@ -1,5 +1,5 @@ import { SupabaseClient } from "@supabase/supabase-js"; -import { logger } from "#root/utils/logger.js"; +import { logger } from "../../../utils/logger"; export class Super { protected supabase: SupabaseClient; diff --git a/src/bot/features/admin/admin.ts b/src/bot/features/admin/admin.ts index f8dc01b..fd674b3 100644 --- a/src/bot/features/admin/admin.ts +++ b/src/bot/features/admin/admin.ts @@ -1,11 +1,11 @@ import { chatAction } from "@grammyjs/auto-chat-action"; import { Composer } from "grammy"; -import type { Context } from "#root/bot/helpers/grammy-context.js"; -import { isAdmin } from "#root/bot/filters/is-admin.js"; -import { setCommandsHandler } from "#root/bot/handlers/commands/setcommands.js"; -import { logHandle } from "#root/bot/helpers/logging.js"; +import { GrammyContext } from "../../helpers/grammy-context"; +import { isAdmin } from "../../filters/is-admin"; +import { logHandle } from "../../helpers/logging"; +import { setCommandsHandler } from "../../handlers/commands/setcommands"; -const composer = new Composer(); +const composer = new Composer(); const feature = composer.chatType("private").filter((ctx) => isAdmin(ctx.config.TELEGRAM_BOT_ENV.botSettings.TELEGRAM_BOT_ADMINS)(ctx)); diff --git a/src/bot/features/commands/groups/ban.ts b/src/bot/features/commands/groups/ban.ts index 94dc20d..50c1809 100644 --- a/src/bot/features/commands/groups/ban.ts +++ b/src/bot/features/commands/groups/ban.ts @@ -1,9 +1,9 @@ import { chatAction } from "@grammyjs/auto-chat-action"; import { Composer } from "grammy"; -import type { Context } from "#root/bot/helpers/grammy-context.js"; -import { logHandle } from "#root/bot/helpers/logging.js"; +import { GrammyContext } from "../../../helpers/grammy-context"; +import { logHandle } from "../../../helpers/logging"; -const composer = new Composer(); +const composer = new Composer(); const feature = composer.chatType("group"); diff --git a/src/bot/features/commands/private-chat/bot-id.ts b/src/bot/features/commands/private-chat/bot-id.ts index 3493a64..658562b 100644 --- a/src/bot/features/commands/private-chat/bot-id.ts +++ b/src/bot/features/commands/private-chat/bot-id.ts @@ -1,9 +1,9 @@ import { chatAction } from "@grammyjs/auto-chat-action"; import { Composer } from "grammy"; -import type { Context } from "#root/bot/helpers/grammy-context.js"; -import { logHandle } from "#root/bot/helpers/logging.js"; +import { GrammyContext } from "../../../helpers/grammy-context"; +import { logHandle } from "../../../helpers/logging"; -const composer = new Composer(); +const composer = new Composer(); const feature = composer.chatType("private"); diff --git a/src/bot/features/commands/private-chat/set-webhook.ts b/src/bot/features/commands/private-chat/set-webhook.ts index f64a2bf..d52b4b4 100644 --- a/src/bot/features/commands/private-chat/set-webhook.ts +++ b/src/bot/features/commands/private-chat/set-webhook.ts @@ -1,25 +1,25 @@ import { chatAction } from "@grammyjs/auto-chat-action"; import { Composer } from "grammy"; -import type { Context } from "#root/bot/helpers/grammy-context.js"; -import { logHandle } from "#root/bot/helpers/logging.js"; -import { isAdmin } from "#root/bot/filters/is-admin.js"; +import { GrammyContext } from "../../../helpers/grammy-context"; +import { isAdmin } from "../../../filters/is-admin"; +import { logHandle } from "../../../helpers/logging"; -const composer = new Composer(); +const composer = new Composer(); const feature = composer.chatType("private").filter((ctx) => isAdmin(ctx.config.TELEGRAM_BOT_ENV.botSettings.TELEGRAM_BOT_ADMINS)(ctx)); feature.command("setwebhook", logHandle("command-setwebhook"), chatAction("typing"), async (ctx) => { - const webhookUrl = ctx.message?.text?.split(" ")[1]; - if (!webhookUrl) { - return ctx.reply("Please provide a webhook URL."); - } + const webhookUrl = ctx.message?.text?.split(" ")[1]; + if (!webhookUrl) { + return ctx.reply("Please provide a webhook URL."); + } - try { - await ctx.api.setWebhook(webhookUrl); - return ctx.reply("Webhook URL has been set."); - } catch (error) { - return ctx.reply("Failed to set webhook URL."); - } + try { + await ctx.api.setWebhook(webhookUrl); + return ctx.reply("Webhook URL has been set."); + } catch { + return ctx.reply("Failed to set webhook URL."); + } }); export { composer as setWebhookFeature }; diff --git a/src/bot/features/commands/private-chat/user-id.ts b/src/bot/features/commands/private-chat/user-id.ts index c8a1848..eb2dd51 100644 --- a/src/bot/features/commands/private-chat/user-id.ts +++ b/src/bot/features/commands/private-chat/user-id.ts @@ -1,9 +1,9 @@ import { chatAction } from "@grammyjs/auto-chat-action"; import { Composer } from "grammy"; -import type { Context } from "#root/bot/helpers/grammy-context.js"; -import { logHandle } from "#root/bot/helpers/logging.js"; +import { GrammyContext } from "../../../helpers/grammy-context"; +import { logHandle } from "../../../helpers/logging"; -const composer = new Composer(); +const composer = new Composer(); const feature = composer.chatType("private"); diff --git a/src/bot/features/commands/shared/chat-id.ts b/src/bot/features/commands/shared/chat-id.ts index c648559..91b26da 100644 --- a/src/bot/features/commands/shared/chat-id.ts +++ b/src/bot/features/commands/shared/chat-id.ts @@ -1,9 +1,9 @@ import { chatAction } from "@grammyjs/auto-chat-action"; import { Composer } from "grammy"; -import type { Context } from "#root/bot/helpers/grammy-context.js"; -import { logHandle } from "#root/bot/helpers/logging.js"; +import { GrammyContext } from "../../../helpers/grammy-context"; +import { logHandle } from "../../../helpers/logging"; -const composer = new Composer(); +const composer = new Composer(); const feature = composer.chatType(["group", "private"]); diff --git a/src/bot/features/helpers/unhandled.ts b/src/bot/features/helpers/unhandled.ts index 2bad5f0..c501966 100644 --- a/src/bot/features/helpers/unhandled.ts +++ b/src/bot/features/helpers/unhandled.ts @@ -1,9 +1,9 @@ import { Composer } from "grammy"; -import type { Context } from "#root/bot/helpers/grammy-context.js"; -import { logHandle } from "#root/bot/helpers/logging.js"; import { STRINGS } from "../../strings"; +import { GrammyContext } from "../../helpers/grammy-context"; +import { logHandle } from "../../helpers/logging"; -const composer = new Composer(); +const composer = new Composer(); const feature = composer.chatType("private"); diff --git a/src/bot/features/welcome.ts b/src/bot/features/welcome.ts index cd92a56..4fc79db 100644 --- a/src/bot/features/welcome.ts +++ b/src/bot/features/welcome.ts @@ -1,9 +1,9 @@ import { Composer } from "grammy"; -import type { Context } from "#root/bot/helpers/grammy-context.js"; -import { logHandle } from "#root/bot/helpers/logging.js"; import { STRINGS } from "../strings"; +import { GrammyContext } from "../helpers/grammy-context"; +import { logHandle } from "../helpers/logging"; -const composer = new Composer(); +const composer = new Composer(); const feature = composer.chatType("private"); diff --git a/src/bot/handlers/commands/setcommands.ts b/src/bot/handlers/commands/setcommands.ts index 3b58d3e..7e449cc 100644 --- a/src/bot/handlers/commands/setcommands.ts +++ b/src/bot/handlers/commands/setcommands.ts @@ -1,6 +1,6 @@ import type { BotCommand } from "@grammyjs/types"; import type { CommandContext } from "grammy"; -import type { Context } from "#root/bot/helpers/grammy-context.js"; +import { GrammyContext } from "../../helpers/grammy-context"; function getPrivateChatCommands(): BotCommand[] { return [ @@ -24,7 +24,7 @@ function getGroupChatCommands(): BotCommand[] { return []; } -export async function setCommandsHandler(ctx: CommandContext) { +export async function setCommandsHandler(ctx: CommandContext) { // set private chat commands await ctx.api.setMyCommands([...getPrivateChatCommands()], { scope: { diff --git a/src/bot/handlers/error.ts b/src/bot/handlers/error.ts index e74ae61..c07dd3d 100644 --- a/src/bot/handlers/error.ts +++ b/src/bot/handlers/error.ts @@ -1,8 +1,8 @@ import type { ErrorHandler } from "grammy"; -import type { Context } from "#root/bot/helpers/grammy-context.js"; -import { getUpdateInfo } from "#root/bot/helpers/logging.js"; +import { GrammyContext } from "../helpers/grammy-context"; +import { getUpdateInfo } from "../helpers/logging"; -export function errorHandler(): ErrorHandler { +export function errorHandler(): ErrorHandler { return (error) => { const { ctx } = error; diff --git a/src/bot/helpers/grammy-context.ts b/src/bot/helpers/grammy-context.ts index 90dd590..ca950ac 100644 --- a/src/bot/helpers/grammy-context.ts +++ b/src/bot/helpers/grammy-context.ts @@ -3,10 +3,10 @@ import { type Api, Context as DefaultContext, type SessionFlavor } from "grammy" import type { AutoChatActionFlavor } from "@grammyjs/auto-chat-action"; import type { HydrateFlavor } from "@grammyjs/hydrate"; import type { ParseModeFlavor } from "@grammyjs/parse-mode"; -import type { Logger } from "#root/utils/logger.js"; import { Context as UbiquityOsContext } from "../../types"; -import { createAdapters } from "#root/adapters/index.js"; import { createClient } from "@supabase/supabase-js"; +import { Logger } from "../../utils/logger"; +import { createAdapters } from "../../adapters"; export type GrammyTelegramUpdate = Update; @@ -20,7 +20,7 @@ interface ExtendedContextFlavor { adapters: ReturnType; } -export type Context = ParseModeFlavor & AutoChatActionFlavor>>; +export type GrammyContext = ParseModeFlavor & AutoChatActionFlavor>>; interface Dependencies { logger: Logger; @@ -41,5 +41,5 @@ export function createContextConstructor({ logger, config }: Dependencies) { const { SUPABASE_URL, SUPABASE_SERVICE_KEY } = config.TELEGRAM_BOT_ENV.storageSettings; this.adapters = createAdapters(createClient(SUPABASE_URL, SUPABASE_SERVICE_KEY)); } - } as unknown as new (update: GrammyTelegramUpdate, api: Api, me: UserFromGetMe) => Context; + } as unknown as new (update: GrammyTelegramUpdate, api: Api, me: UserFromGetMe) => GrammyContext; } diff --git a/src/bot/helpers/logging.ts b/src/bot/helpers/logging.ts index 1dd36fe..095e39b 100644 --- a/src/bot/helpers/logging.ts +++ b/src/bot/helpers/logging.ts @@ -1,13 +1,13 @@ import type { Middleware } from "grammy"; -import type { Context, GrammyTelegramUpdate } from "#root/bot/helpers/grammy-context.js"; +import { GrammyContext, GrammyTelegramUpdate } from "./grammy-context"; -export function getUpdateInfo(ctx: Context): Omit { +export function getUpdateInfo(ctx: GrammyContext): Omit { const { update_id, ...update } = ctx.update; return update; } -export function logHandle(id: string): Middleware { +export function logHandle(id: string): Middleware { return (ctx, next) => { ctx.logger.info("Handling update", { msg: `Handle "${id}"`, diff --git a/src/bot/index.ts b/src/bot/index.ts index 52587b1..d0dded1 100644 --- a/src/bot/index.ts +++ b/src/bot/index.ts @@ -1,13 +1,6 @@ import type { BotConfig, StorageAdapter } from "grammy"; import { Bot as TelegramBot } from "grammy"; -import type { Context, SessionData } from "#root/bot/helpers/grammy-context.js"; -import { createContextConstructor } from "#root/bot/helpers/grammy-context.js"; -import type { Logger } from "#root/utils/logger.js"; import { Context as UbiquityOsContext } from "../types"; -import { welcomeFeature } from "#root/bot/features/welcome.js"; -import { unhandledFeature } from "#root/bot/features/helpers/unhandled.js"; -import { errorHandler } from "#root/bot/handlers/error.js"; -import { session } from "#root/bot/middlewares/session.js"; import { autoChatAction } from "@grammyjs/auto-chat-action"; import { hydrate } from "@grammyjs/hydrate"; import { hydrateReply, parseMode } from "@grammyjs/parse-mode"; @@ -17,6 +10,12 @@ import { chatIdFeature } from "./features/commands/shared/chat-id"; import { botIdFeature } from "./features/commands/private-chat/bot-id"; import { banCommand } from "./features/commands/groups/ban"; import { setWebhookFeature } from "./features/commands/private-chat/set-webhook"; +import { Logger } from "../utils/logger"; +import { createContextConstructor, GrammyContext, SessionData } from "./helpers/grammy-context"; +import { errorHandler } from "./handlers/error"; +import { session } from "./middlewares/session"; +import { welcomeFeature } from "./features/welcome"; +import { unhandledFeature } from "./features/helpers/unhandled"; interface Dependencies { config: UbiquityOsContext["env"]; @@ -25,10 +24,10 @@ interface Dependencies { interface Options { botSessionStorage?: StorageAdapter; - botConfig?: Omit, "ContextConstructor">; + botConfig?: Omit, "ContextConstructor">; } -function getSessionKey(ctx: Omit) { +function getSessionKey(ctx: Omit) { return ctx.chat?.id.toString(); } diff --git a/src/bot/middlewares/session.ts b/src/bot/middlewares/session.ts index 53f60fe..632a25c 100644 --- a/src/bot/middlewares/session.ts +++ b/src/bot/middlewares/session.ts @@ -1,9 +1,9 @@ import { type Middleware, type SessionOptions, session as createSession } from "grammy"; -import type { Context, SessionData } from "#root/bot/helpers/grammy-context.js"; +import { GrammyContext, SessionData } from "../helpers/grammy-context"; -type Options = Pick, "getSessionKey" | "storage">; +type Options = Pick, "getSessionKey" | "storage">; -export function session(options: Options): Middleware { +export function session(options: Options): Middleware { return createSession({ getSessionKey: options.getSessionKey, storage: options.storage, diff --git a/src/bot/mtproto-api/bot/mtproto.ts b/src/bot/mtproto-api/bot/mtproto.ts index 03e7953..207b770 100644 --- a/src/bot/mtproto-api/bot/mtproto.ts +++ b/src/bot/mtproto-api/bot/mtproto.ts @@ -1,8 +1,8 @@ -import { Context } from "#root/types/context.js"; import dotenv from "dotenv"; import { BaseMtProto } from "./scripts/sms-auth/base-mtproto"; import { SupabaseSession } from "./session"; import { createClient, SupabaseClient } from "@supabase/supabase-js"; +import { Context } from "../../../types"; dotenv.config(); /** diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts index 40f91e4..7e5f66e 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts @@ -3,8 +3,8 @@ import input from "input"; import dotenv from "dotenv"; import { createClient, SupabaseClient } from "@supabase/supabase-js"; import { BaseMtProto } from "./base-mtproto"; -import { Context } from "#root/types/context.js"; -import { logger } from "#root/utils/logger.js"; +import { Context } from "../../../../../types"; +import { logger } from "../../../../../utils/logger"; dotenv.config(); /** @@ -48,7 +48,6 @@ export class AuthHandler { throw new Error("Missing required environment variables for MtProto settings"); } - if (!SUPABASE_URL || !SUPABASE_SERVICE_KEY) { throw new Error("Missing required environment variables for storage settings"); } diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts index 4e5e80a..484da40 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts @@ -3,7 +3,7 @@ import { Api } from "telegram/tl"; import { TelegramClientParams } from "telegram/client/telegramBaseClient"; import dotenv from "dotenv"; import { StringSession } from "telegram/sessions"; -import { Context } from "#root/types/context.js"; +import { Context } from "../../../../../types"; dotenv.config(); /** diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts index 3185dff..50ebc28 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts @@ -3,11 +3,11 @@ import input from "input"; // @ts-expect-error no types import sodium from "libsodium-wrappers"; import { Context } from "../../../../../types"; -import { logger } from "#root/utils/logger.js"; import { exit } from "node:process"; import { Octokit } from "@octokit/rest"; import dotenv from "dotenv"; import { appendFile, writeFile } from "node:fs/promises"; +import { logger } from "../../../../../utils/logger"; dotenv.config(); /** * This script is used to help guide the user through setting up the environment variables. diff --git a/src/bot/mtproto-api/bot/session.ts b/src/bot/mtproto-api/bot/session.ts index 2a1e466..d7efc61 100644 --- a/src/bot/mtproto-api/bot/session.ts +++ b/src/bot/mtproto-api/bot/session.ts @@ -1,6 +1,6 @@ -import { Context } from "#root/types/context.js"; import { SupabaseClient } from "@supabase/supabase-js"; import { StringSession } from "telegram/sessions"; +import { Context } from "../../../types"; /** * This class extends the StringSession class from the Telegram library. diff --git a/src/bot/mtproto-api/workrooms/close-chat.ts b/src/bot/mtproto-api/workrooms/close-chat.ts index bbed4fd..4d652d5 100644 --- a/src/bot/mtproto-api/workrooms/close-chat.ts +++ b/src/bot/mtproto-api/workrooms/close-chat.ts @@ -1,8 +1,8 @@ -import { Context, SupportedEvents } from "#root/types/context"; -import { CallbackResult } from "#root/types/proxy.js"; import { MtProto } from "../bot/mtproto"; import { Api } from "telegram"; import bigInt from "big-integer"; +import { Context, SupportedEvents } from "../../../types"; +import { CallbackResult } from "../../../types/proxy"; export async function closeChat(context: Context<"issues.closed", SupportedEvents["issues.closed"]>): Promise { const { diff --git a/src/bot/mtproto-api/workrooms/create-chat.ts b/src/bot/mtproto-api/workrooms/create-chat.ts index 20761b2..17b202c 100644 --- a/src/bot/mtproto-api/workrooms/create-chat.ts +++ b/src/bot/mtproto-api/workrooms/create-chat.ts @@ -1,7 +1,7 @@ -import { Context, SupportedEvents } from "#root/types/context"; -import { CallbackResult } from "#root/types/proxy.js"; +import { Context, SupportedEvents } from "../../../types"; +import { CallbackResult } from "../../../types/proxy"; +import { addCommentToIssue } from "../../../utils/add-comment-to-issues"; import { MtProto } from "../bot/mtproto"; -import { addCommentToIssue } from "#root/utils/add-comment-to-issues.js"; import bigInt from "big-integer"; export async function createChat(context: Context<"issues.labeled", SupportedEvents["issues.labeled"]>): Promise { diff --git a/src/bot/mtproto-api/workrooms/reopen-chat.ts b/src/bot/mtproto-api/workrooms/reopen-chat.ts index 3beca54..2fa38fa 100644 --- a/src/bot/mtproto-api/workrooms/reopen-chat.ts +++ b/src/bot/mtproto-api/workrooms/reopen-chat.ts @@ -1,5 +1,5 @@ -import { Context, SupportedEvents } from "#root/types/context"; -import { CallbackResult } from "#root/types/proxy.js"; +import { Context, SupportedEvents } from "../../../types"; +import { CallbackResult } from "../../../types/proxy"; import { MtProto } from "../bot/mtproto"; import { Api } from "telegram"; diff --git a/src/handlers/github-webhook.ts b/src/handlers/github-webhook.ts index 0ccb4d6..f2c9373 100644 --- a/src/handlers/github-webhook.ts +++ b/src/handlers/github-webhook.ts @@ -1,7 +1,7 @@ import { Value } from "@sinclair/typebox/value"; import { plugin } from "../plugin"; import { pluginSettingsSchema, pluginSettingsValidator, PluginInputs, Env } from "../types"; -import { logger } from "#root/utils/logger.js"; +import { logger } from "../utils/logger"; export async function handleGithubWebhook(request: Request, env: Env): Promise { try { diff --git a/src/handlers/telegram-webhook.ts b/src/handlers/telegram-webhook.ts index cc87150..5e2de71 100644 --- a/src/handlers/telegram-webhook.ts +++ b/src/handlers/telegram-webhook.ts @@ -1,6 +1,6 @@ import { Env } from "../types"; -import { TelegramBotSingleton } from "#root/types/telegram-bot-single.js"; -import { logger } from "#root/utils/logger.js"; +import { TelegramBotSingleton } from "../types/telegram-bot-single"; +import { logger } from "../utils/logger"; export async function handleTelegramWebhook(request: Request, env: Env): Promise { let server; diff --git a/src/handlers/worker-proxy.ts b/src/handlers/worker-proxy.ts index 2f5b800..c6e882f 100644 --- a/src/handlers/worker-proxy.ts +++ b/src/handlers/worker-proxy.ts @@ -1,5 +1,5 @@ -import { ProxyCallbacks } from "#root/types/proxy.js"; import { Context, SupportedEventsU } from "../types"; +import { ProxyCallbacks } from "../types/proxy"; /** * The `callbacks` object defines an array of callback functions for each supported event type. diff --git a/src/handlers/workflow-proxy.ts b/src/handlers/workflow-proxy.ts index 4daa56c..389993e 100644 --- a/src/handlers/workflow-proxy.ts +++ b/src/handlers/workflow-proxy.ts @@ -1,8 +1,8 @@ -import { closeChat } from "#root/bot/mtproto-api/workrooms/close-chat.js"; -import { createChat } from "#root/bot/mtproto-api/workrooms/create-chat.js"; -import { reopenChat } from "#root/bot/mtproto-api/workrooms/reopen-chat.js"; -import { ProxyCallbacks } from "#root/types/proxy.js"; +import { closeChat } from "../bot/mtproto-api/workrooms/close-chat"; +import { createChat } from "../bot/mtproto-api/workrooms/create-chat"; +import { reopenChat } from "../bot/mtproto-api/workrooms/reopen-chat"; import { Context, SupportedEventsU } from "../types"; +import { ProxyCallbacks } from "../types/proxy"; import { handleCallback } from "./worker-proxy"; /** diff --git a/src/server/index.ts b/src/server/index.ts index 08c86c7..d3962c1 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -2,11 +2,11 @@ import { Hono } from "hono"; import { HTTPException } from "hono/http-exception"; import { webhookCallback } from "grammy"; import { getPath } from "hono/utils/url"; -import { setLogger } from "#root/server/middlewares/logger.js"; -import type { Bot } from "#root/bot/index.js"; -import { requestLogger } from "#root/server/middlewares/request-logger.js"; -import type { Logger } from "#root/utils/logger.js"; import { Context as UbiquityOsContext } from "../types"; +import { Logger } from "../utils/logger"; +import { Bot } from "../bot"; +import { setLogger } from "./middlewares/logger"; +import { requestLogger } from "./middlewares/request-logger"; interface Dependencies { bot: Bot; diff --git a/src/server/middlewares/logger.ts b/src/server/middlewares/logger.ts index 483c71c..4aa7070 100644 --- a/src/server/middlewares/logger.ts +++ b/src/server/middlewares/logger.ts @@ -1,5 +1,5 @@ import type { MiddlewareHandler } from "hono"; -import type { Logger } from "#root/utils/logger.js"; +import { Logger } from "../../utils/logger"; export function setLogger(logger: Logger): MiddlewareHandler { return async (c, next) => { diff --git a/src/types/env.ts b/src/types/env.ts index 3a76ffb..dd56912 100644 --- a/src/types/env.ts +++ b/src/types/env.ts @@ -81,7 +81,7 @@ export const env = T.Object({ const obj = JSON.parse(str) as StaticDecode; if (!botEnvValidator.test(obj)) { - throw new Error('Invalid TELEGRAM_BOT_ENV'); + throw new Error("Invalid TELEGRAM_BOT_ENV"); } return obj; diff --git a/src/types/plugin-context-single.ts b/src/types/plugin-context-single.ts index 040f0fc..9c2dad2 100644 --- a/src/types/plugin-context-single.ts +++ b/src/types/plugin-context-single.ts @@ -1,9 +1,11 @@ -import { Context, Env, envValidator, PluginInputs } from "#root/types"; import { Octokit } from "@octokit/rest"; import { Value } from "@sinclair/typebox/value"; import { Logs } from "@ubiquity-dao/ubiquibot-logger"; import { createAdapters } from "../adapters"; import { createClient } from "@supabase/supabase-js"; +import { PluginInputs } from "./plugin-inputs"; +import { Env, envValidator } from "./env"; +import { Context } from "./context"; /** * Singleton for the plugin context making accessing it throughout diff --git a/src/types/typeguards.ts b/src/types/typeguards.ts index 136ca30..05d054b 100644 --- a/src/types/typeguards.ts +++ b/src/types/typeguards.ts @@ -1,4 +1,4 @@ -import { GrammyTelegramUpdate } from "#root/bot/helpers/grammy-context.js"; +import { GrammyTelegramUpdate } from "../bot/helpers/grammy-context"; import { PluginInputs } from "./plugin-inputs"; export function isTelegramPayload(payload: unknown): payload is GrammyTelegramUpdate { diff --git a/src/utils/add-comment-to-issues.ts b/src/utils/add-comment-to-issues.ts index b00fe3a..2d661ae 100644 --- a/src/utils/add-comment-to-issues.ts +++ b/src/utils/add-comment-to-issues.ts @@ -1,4 +1,4 @@ -import { Context } from "#root/types/context.js"; +import { Context } from "../types"; /** * Ideally pass in owner, repo, and issueNumber, but if not provided, diff --git a/src/utils/errors.ts b/src/utils/errors.ts index 911a25a..61012d3 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -1,7 +1,7 @@ import { LogReturn } from "@ubiquity-dao/ubiquibot-logger"; import { Context } from "../types"; -import { addCommentToIssue } from "#root/utils/add-comment-to-issues.js"; import { logger } from "./logger"; +import { addCommentToIssue } from "./add-comment-to-issues"; export function handleUncaughtError(err: unknown) { logger.error("An uncaught error occurred", { err }); diff --git a/src/worker.ts b/src/worker.ts index fab8a85..6231db3 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -11,13 +11,20 @@ export default { async fetch(request: Request, env: Env): Promise { const url = new URL(request.url); const path = url.pathname; + if (request.method === "GET") { + if (path === "/manifest.json") { + return new Response(JSON.stringify(manifest), { + headers: { "content-type": "application/json" }, + }); + } + } let envSettings; try { envSettings = Value.Decode(envValidator.schema, Value.Default(envValidator.schema, env)); } catch (err) { - return new Response(JSON.stringify({ error: "Invalid environment provided" }), { + return new Response(JSON.stringify({ err, message: "Invalid environment provided" }), { status: 400, headers: { "content-type": "application/json" }, }); @@ -34,14 +41,6 @@ export default { } } - if (request.method === "GET") { - if (path === "/manifest.json") { - return new Response(JSON.stringify(manifest), { - headers: { "content-type": "application/json" }, - }); - } - } - const contentType = request.headers.get("content-type"); if (contentType !== "application/json") { return new Response(JSON.stringify({ error: `Error: ${contentType} is not a valid content type` }), { diff --git a/tests/main.test.ts b/tests/main.test.ts index 26e170e..c67858c 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -2,19 +2,12 @@ import { drop } from "@mswjs/data"; import { db } from "./__mocks__/db"; import { server } from "./__mocks__/node"; import { expect, describe, beforeAll, beforeEach, afterAll, afterEach, it } from "@jest/globals"; -import { Context } from "../src/types/context"; -import { Octokit } from "@octokit/rest"; -import { STRINGS } from "./__mocks__/strings"; -import { createComment, setupTests } from "./__mocks__/helpers"; +import { setupTests } from "./__mocks__/helpers"; import manifest from "../manifest.json"; import dotenv from "dotenv"; -import { Logs } from "@ubiquity-dao/ubiquibot-logger"; import { Env } from "../src/types"; -import { runPlugin } from "../src/plugin"; dotenv.config(); -jest.requireActual("@octokit/rest"); -const octokit = new Octokit(); beforeAll(() => { server.listen(); @@ -32,56 +25,11 @@ describe("Plugin tests", () => { }); it("Should serve the manifest file", async () => { - const worker = (await import("../src/worker")).default; - const response = await worker.fetch(new Request("http://localhost/manifest.json"), {}); - const content = await response.json(); - expect(content).toEqual(manifest); - }); - - it("Should handle an issue comment event", async () => { - const { context, infoSpy, errorSpy, debugSpy, okSpy, verboseSpy } = createContext(); - - expect(context.eventName).toBe("issue_comment.created"); - expect(context.payload.comment.body).toBe("/Hello"); - - await runPlugin(context); - - expect(errorSpy).not.toHaveBeenCalled(); - expect(debugSpy).toHaveBeenNthCalledWith(1, STRINGS.EXECUTING_HELLO_WORLD, { - caller: STRINGS.CALLER_LOGS_ANON, - sender: STRINGS.USER_1, - repo: STRINGS.TEST_REPO, - issueNumber: 1, - owner: STRINGS.USER_1, - }); - expect(infoSpy).toHaveBeenNthCalledWith(1, STRINGS.HELLO_WORLD); - expect(okSpy).toHaveBeenNthCalledWith(1, STRINGS.SUCCESSFULLY_CREATED_COMMENT); - expect(verboseSpy).toHaveBeenNthCalledWith(1, STRINGS.EXITING_HELLO_WORLD); - }); - - it("Should respond with `Hello, World!` in response to /Hello", async () => { - const { context } = createContext(); - await runPlugin(context); - const comments = db.issueComments.getAll(); - expect(comments.length).toBe(2); - expect(comments[1].body).toBe(STRINGS.HELLO_WORLD); - }); - - it("Should respond with `Hello, Code Reviewers` in response to /Hello", async () => { - const { context } = createContext(STRINGS.CONFIGURABLE_RESPONSE); - await runPlugin(context); - const comments = db.issueComments.getAll(); - expect(comments.length).toBe(2); - expect(comments[1].body).toBe(STRINGS.CONFIGURABLE_RESPONSE); - }); - - it("Should not respond to a comment that doesn't contain /Hello", async () => { - const { context, errorSpy } = createContext(STRINGS.CONFIGURABLE_RESPONSE, STRINGS.INVALID_COMMAND); - await runPlugin(context); - const comments = db.issueComments.getAll(); - - expect(comments.length).toBe(1); - expect(errorSpy).toHaveBeenNthCalledWith(1, STRINGS.INVALID_USE_OF_SLASH_COMMAND, { caller: STRINGS.CALLER_LOGS_ANON, body: STRINGS.INVALID_COMMAND }); + const worker = require("../src/worker").default; + const response = await worker.fetch(new Request("http://localhost/manifest.json"), {} as Env); + const body = await response.json(); + expect(response.status).toBe(200); + expect(body).toEqual(manifest); }); }); @@ -93,68 +41,68 @@ describe("Plugin tests", () => { * * Refactor according to your needs. */ -function createContext( - configurableResponse: string = "Hello, world!", // we pass the plugin configurable items here - commentBody: string = "/Hello", - repoId: number = 1, - payloadSenderId: number = 1, - commentId: number = 1, - issueOne: number = 1 -) { - const repo = db.repo.findFirst({ where: { id: { equals: repoId } } }) as unknown as Context["payload"]["repository"]; - const sender = db.users.findFirst({ where: { id: { equals: payloadSenderId } } }) as unknown as Context["payload"]["sender"]; - const issue1 = db.issue.findFirst({ where: { id: { equals: issueOne } } }) as unknown as Context["payload"]["issue"]; - - createComment(commentBody, commentId); // create it first then pull it from the DB and feed it to _createContext - const comment = db.issueComments.findFirst({ where: { id: { equals: commentId } } }) as unknown as Context["payload"]["comment"]; - - const context = createContextInner(repo, sender, issue1, comment, configurableResponse); - const infoSpy = jest.spyOn(context.logger, "info"); - const errorSpy = jest.spyOn(context.logger, "error"); - const debugSpy = jest.spyOn(context.logger, "debug"); - const okSpy = jest.spyOn(context.logger, "ok"); - const verboseSpy = jest.spyOn(context.logger, "verbose"); - - return { - context, - infoSpy, - errorSpy, - debugSpy, - okSpy, - verboseSpy, - repo, - issue1, - }; -} +// function createContext( +// configurableResponse: string = "Hello, world!", // we pass the plugin configurable items here +// commentBody: string = "/Hello", +// repoId: number = 1, +// payloadSenderId: number = 1, +// commentId: number = 1, +// issueOne: number = 1 +// ) { +// const repo = db.repo.findFirst({ where: { id: { equals: repoId } } }) as unknown as Context["payload"]["repository"]; +// const sender = db.users.findFirst({ where: { id: { equals: payloadSenderId } } }) as unknown as Context["payload"]["sender"]; +// const issue1 = db.issue.findFirst({ where: { id: { equals: issueOne } } }) as unknown as Context["payload"]["issue"]; + +// createComment(commentBody, commentId); // create it first then pull it from the DB and feed it to _createContext +// const comment = db.issueComments.findFirst({ where: { id: { equals: commentId } } }) as unknown as Context["payload"]["comment"]; + +// const context = createContextInner(repo, sender, issue1, comment, configurableResponse); +// const infoSpy = jest.spyOn(context.logger, "info"); +// const errorSpy = jest.spyOn(context.logger, "error"); +// const debugSpy = jest.spyOn(context.logger, "debug"); +// const okSpy = jest.spyOn(context.logger, "ok"); +// const verboseSpy = jest.spyOn(context.logger, "verbose"); + +// return { +// context, +// infoSpy, +// errorSpy, +// debugSpy, +// okSpy, +// verboseSpy, +// repo, +// issue1, +// }; +// } /** * Creates the context object central to the plugin. * * This should represent the active `SupportedEvents` payload for any given event. */ -function createContextInner( - repo: Context["payload"]["repository"], - sender: Context["payload"]["sender"], - issue: Context["payload"]["issue"], - comment: Context["payload"]["comment"], - configurableResponse: string -): Context { - return { - eventName: "issue_comment.created", - payload: { - action: "created", - sender: sender, - repository: repo, - issue: issue, - comment: comment, - installation: { id: 1 } as Context["payload"]["installation"], - organization: { login: STRINGS.USER_1 } as Context["payload"]["organization"], - }, - logger: new Logs("debug"), - config: { - configurableResponse, - }, - env: {} as Env, - octokit: octokit, - }; -} +// function createContextInner( +// repo: Context["payload"]["repository"], +// sender: Context["payload"]["sender"], +// issue: Context["payload"]["issue"], +// comment: Context["payload"]["comment"], +// configurableResponse: string +// ): Context { +// return { +// eventName: "issue_comment.created", +// payload: { +// action: "created", +// sender: sender, +// repository: repo, +// issue: issue, +// comment: comment, +// installation: { id: 1 } as Context["payload"]["installation"], +// organization: { login: STRINGS.USER_1 } as Context["payload"]["organization"], +// }, +// logger: new Logs("debug"), +// config: { +// configurableResponse, +// }, +// env: {} as Env, +// octokit: octokit, +// }; +// } diff --git a/tsconfig.json b/tsconfig.json index aaae717..12579dc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,9 +3,6 @@ "target": "ES2022", "module": "ESNext", "moduleResolution": "Bundler", - "paths": { - "#root/*": ["./src/*"] - }, "types": [ "jest", "node", @@ -23,5 +20,5 @@ "preserveWatchOutput": true }, "include": ["src/**/*"], - "exclude": ["node_modules", "build", "tests", "eslint.config.mjs", ".wrangler"] + "exclude": ["node_modules", "build", "tests", "eslint.config.mjs", ".wrangler", "coverage"] } diff --git a/wrangler.toml b/wrangler.toml index 0f0f0db..0a1fd9d 100644 --- a/wrangler.toml +++ b/wrangler.toml @@ -1,4 +1,4 @@ -name = "ubiquity-os-telegram-bot" +name = "ubiquity-os-telegram-bridge" main = "src/worker.ts" compatibility_date = "2024-08-26" node_compat = true diff --git a/yarn.lock b/yarn.lock index ee04ad0..48a6443 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2444,7 +2444,7 @@ "@octokit/request-error" "^6.0.1" "@octokit/types" "^13.0.0" -"@octokit/core@^5.0.1": +"@octokit/core@^5.0.1", "@octokit/core@^5.0.2": version "5.2.0" resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.2.0.tgz#ddbeaefc6b44a39834e1bb2e58a49a117672a7ea" integrity sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg== @@ -2543,6 +2543,11 @@ resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-22.2.0.tgz#75aa7dcd440821d99def6a60b5f014207ae4968e" integrity sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg== +"@octokit/openapi-webhooks-types@8.2.1": + version "8.2.1" + resolved "https://registry.yarnpkg.com/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-8.2.1.tgz#08b974f1e83a75c4d3ce23f798c7667b433bf4cd" + integrity sha512-msAU1oTSm0ZmvAE0xDemuF4tVs5i0xNnNGtNmr4EuATi+1Rn8cZDetj6NXioSf5LwnxEc209COa/WOSbjuhLUA== + "@octokit/openapi-webhooks-types@8.3.0": version "8.3.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-8.3.0.tgz#a7a4da00c0f27f7f5708eb3fcebefa08f8d51125" @@ -2553,6 +2558,13 @@ resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-5.2.2.tgz#54e2afef55bb204eb945a891b85a169b9ddad1f8" integrity sha512-7znSVvlNAOJisCqAnjN1FtEziweOHSjPGAuc5W58NeGNAr/ZB57yCsjQbXDlWsVryA7hHQaEQPcBbJYFawlkyg== +"@octokit/plugin-paginate-rest@11.3.1": + version "11.3.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.1.tgz#fe92d04b49f134165d6fbb716e765c2f313ad364" + integrity sha512-ryqobs26cLtM1kQxqeZui4v8FeznirUsksiA+RYemMPJ7Micju0WSkv50dBksTuZks9O5cg4wp+t8fZ/cLY56g== + dependencies: + "@octokit/types" "^13.5.0" + "@octokit/plugin-paginate-rest@^11.0.0": version "11.3.3" resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.3.tgz#efc97ba66aae6797e2807a082f99b9cfc0e05aba" @@ -2567,10 +2579,17 @@ dependencies: "@octokit/types" "^12.6.0" -"@octokit/plugin-request-log@^5.3.1": - version "5.3.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz#ccb75d9705de769b2aa82bcd105cc96eb0c00f69" - integrity sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw== +"@octokit/plugin-request-log@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz#98a3ca96e0b107380664708111864cb96551f958" + integrity sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA== + +"@octokit/plugin-rest-endpoint-methods@13.2.2": + version "13.2.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.2.tgz#af8e5dd2cddfea576f92ffaf9cb84659f302a638" + integrity sha512-EI7kXWidkt3Xlok5uN43suK99VWqc8OaIMktY9d9+RNKl69juoTyxmLoWPIZgJYzi41qj/9zU7G/ljnNOJ5AFA== + dependencies: + "@octokit/types" "^13.5.0" "@octokit/plugin-rest-endpoint-methods@^10.0.0": version "10.4.1" @@ -2639,15 +2658,15 @@ "@octokit/types" "^13.1.0" universal-user-agent "^7.0.2" -"@octokit/rest@21.0.2": - version "21.0.2" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-21.0.2.tgz#9b767dbc1098daea8310fd8b76bf7a97215d5972" - integrity sha512-+CiLisCoyWmYicH25y1cDfCrv41kRSvTq6pPWtRroRJzhsCZWZyCqGyI8foJT5LmScADSwRAnr/xo+eewL04wQ== +"@octokit/rest@20.1.1": + version "20.1.1" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-20.1.1.tgz#ec775864f53fb42037a954b9a40d4f5275b3dc95" + integrity sha512-MB4AYDsM5jhIHro/dq4ix1iWTLGToIGk6cWF5L6vanFaMble5jTX/UBQyiv05HsWnwUtY8JrfHy2LWfKwihqMw== dependencies: - "@octokit/core" "^6.1.2" - "@octokit/plugin-paginate-rest" "^11.0.0" - "@octokit/plugin-request-log" "^5.3.1" - "@octokit/plugin-rest-endpoint-methods" "^13.0.0" + "@octokit/core" "^5.0.2" + "@octokit/plugin-paginate-rest" "11.3.1" + "@octokit/plugin-request-log" "^4.0.0" + "@octokit/plugin-rest-endpoint-methods" "13.2.2" "@octokit/types@^12.6.0": version "12.6.0" @@ -2668,7 +2687,17 @@ resolved "https://registry.yarnpkg.com/@octokit/webhooks-methods/-/webhooks-methods-5.1.0.tgz#13b6c08f89902c1ab0ddf31c6eeeec9c2772cfe6" integrity sha512-yFZa3UH11VIxYnnoOYCVoJ3q4ChuSOk2IVBBQ0O3xtKX4x9bmKb/1t+Mxixv2iUhzMdOl1qeWJqEhouXXzB3rQ== -"@octokit/webhooks@13.3.0", "@octokit/webhooks@^13.0.0": +"@octokit/webhooks@13.2.7": + version "13.2.7" + resolved "https://registry.yarnpkg.com/@octokit/webhooks/-/webhooks-13.2.7.tgz#03f89b278cd63f271eba3062f0b75ddd18a82252" + integrity sha512-sPHCyi9uZuCs1gg0yF53FFocM+GsiiBEhQQV/itGzzQ8gjyv2GMJ1YvgdDY4lC0ePZeiV3juEw4GbS6w1VHhRw== + dependencies: + "@octokit/openapi-webhooks-types" "8.2.1" + "@octokit/request-error" "^6.0.1" + "@octokit/webhooks-methods" "^5.0.0" + aggregate-error "^5.0.0" + +"@octokit/webhooks@^13.0.0": version "13.3.0" resolved "https://registry.yarnpkg.com/@octokit/webhooks/-/webhooks-13.3.0.tgz#fd5d54d47c789c75d60a00eb04e982152d7c654a" integrity sha512-TUkJLtI163Bz5+JK0O+zDkQpn4gKwN+BovclUvCj6pI/6RXrFqQvUMRS2M+Rt8Rv0qR3wjoMoOPmpJKeOh0nBg== @@ -2700,10 +2729,10 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== -"@sinclair/typebox@0.33.7": - version "0.33.7" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.33.7.tgz#4356b69f566ef8862848c24dabb5cd64ba025111" - integrity sha512-et38XPs6GMoB6XugH+Spp/HRv5gHYffw7rXC3caen/dIKC7Q6sqs6eEH9Yd9UKziUkOQdrLr9OXUULAc+pRMng== +"@sinclair/typebox@0.32.33": + version "0.32.33" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.32.33.tgz#823af450f6f1571a85c12e2b1f2a0b134f61920f" + integrity sha512-jM50BfkKA0fwfj0uRRO6asfNfbU0oZipJIb/bL2+BUH/THjuEf2BMiqBOvKfBji5Z9t59NboZQGNfKZbdV50Iw== "@sinclair/typebox@^0.27.8": version "0.27.8" @@ -2921,13 +2950,20 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@22.5.0", "@types/node@^22.1.0": +"@types/node@*", "@types/node@^22.1.0": version "22.5.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.0.tgz#10f01fe9465166b4cab72e75f60d8b99d019f958" integrity sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg== dependencies: undici-types "~6.19.2" +"@types/node@20.14.5": + version "20.14.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.5.tgz#fe35e3022ebe58b8f201580eb24e1fcfc0f2487d" + integrity sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA== + dependencies: + undici-types "~5.26.4" + "@types/phoenix@^1.5.4": version "1.6.5" resolved "https://registry.yarnpkg.com/@types/phoenix/-/phoenix-1.6.5.tgz#5654e14ec7ad25334a157a20015996b6d7d2075e" @@ -3223,6 +3259,14 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +aggregate-error@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-5.0.0.tgz#ffe15045d7521c51c9d618e3d7f37c13f29b3fd3" + integrity sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw== + dependencies: + clean-stack "^5.2.0" + indent-string "^5.0.0" + ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -3825,6 +3869,13 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +clean-stack@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-5.2.0.tgz#c7a0c91939c7caace30a3bf254e8a8ac276d1189" + integrity sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ== + dependencies: + escape-string-regexp "5.0.0" + clear-module@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/clear-module/-/clear-module-4.1.2.tgz#5a58a5c9f8dccf363545ad7284cad3c887352a80" @@ -4732,6 +4783,11 @@ escalade@^3.1.1, escalade@^3.1.2: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== +escape-string-regexp@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" + integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== + escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -5660,6 +5716,11 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== +indent-string@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-5.0.0.tgz#4fd2980fccaf8622d14c64d694f4cf33c81951a5" + integrity sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -8623,6 +8684,11 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + undici-types@~6.19.2: version "6.19.8" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" From e5e31e52a69bdaa7f28d6ecbdcf847d235eb62ed Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 27 Sep 2024 03:58:55 +0100 Subject: [PATCH 69/76] chore: remove issues.opened from manifest --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 334c593..1c9e4fc 100644 --- a/manifest.json +++ b/manifest.json @@ -1,5 +1,5 @@ { "name": "ubiquity-os/telegram-bridge", "description": "Part kernel plugin, part Telegram kernel. This bot is designed to be a bridge between UbiquityOS and Telegram.", - "ubiquity:listeners": ["issues.opened", "issues.labeled", "issues.closed", "issues.reopened"] + "ubiquity:listeners": ["issues.labeled", "issues.closed", "issues.reopened"] } From 67e6e55f11771927674ff74c8c5cff1523315ee5 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 27 Sep 2024 04:04:22 +0100 Subject: [PATCH 70/76] chore: skip devpool and knip fix --- package.json | 3 +- src/bot/mtproto-api/workrooms/close-chat.ts | 4 + src/bot/mtproto-api/workrooms/create-chat.ts | 4 + src/bot/mtproto-api/workrooms/reopen-chat.ts | 4 + src/types/typeguards.ts | 12 - yarn.lock | 241 +------------------ 6 files changed, 15 insertions(+), 253 deletions(-) delete mode 100644 src/types/typeguards.ts diff --git a/package.json b/package.json index 294911c..e1a4767 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,6 @@ "grammy": "^1.29.0", "grammy-guard": "0.5.0", "hono": "^4.5.9", - "octokit": "^4.0.2", "telegram": "^2.24.11", "typebox-validators": "0.3.5" }, @@ -103,4 +102,4 @@ ] }, "packageManager": "yarn@1.22.22" -} +} \ No newline at end of file diff --git a/src/bot/mtproto-api/workrooms/close-chat.ts b/src/bot/mtproto-api/workrooms/close-chat.ts index 4d652d5..9207fab 100644 --- a/src/bot/mtproto-api/workrooms/close-chat.ts +++ b/src/bot/mtproto-api/workrooms/close-chat.ts @@ -12,6 +12,10 @@ export async function closeChat(context: Context<"issues.closed", SupportedEvent }, logger, } = context; + if (payload.repository.full_name.includes("devpool-directory")) { + return { status: 200, reason: "skipped" }; + } + const mtProto = new MtProto(context); await mtProto.initialize(); diff --git a/src/bot/mtproto-api/workrooms/create-chat.ts b/src/bot/mtproto-api/workrooms/create-chat.ts index 17b202c..e285958 100644 --- a/src/bot/mtproto-api/workrooms/create-chat.ts +++ b/src/bot/mtproto-api/workrooms/create-chat.ts @@ -8,6 +8,10 @@ export async function createChat(context: Context<"issues.labeled", SupportedEve const { payload, config, logger } = context; const chatName = "@" + payload.repository.full_name + "#" + payload.issue.number; + if (chatName.includes("devpool-directory")) { + return { status: 200, reason: "skipped" }; + } + const labelName = payload.label?.name.toLowerCase(); if (!labelName?.toLowerCase().includes("price")) { diff --git a/src/bot/mtproto-api/workrooms/reopen-chat.ts b/src/bot/mtproto-api/workrooms/reopen-chat.ts index 2fa38fa..626c8ae 100644 --- a/src/bot/mtproto-api/workrooms/reopen-chat.ts +++ b/src/bot/mtproto-api/workrooms/reopen-chat.ts @@ -12,6 +12,10 @@ export async function reopenChat(context: Context<"issues.reopened", SupportedEv logger, } = context; + if (payload.repository.full_name.includes("devpool-directory")) { + return { status: 200, reason: "skipped" }; + } + const mtProto = new MtProto(context); await mtProto.initialize(); diff --git a/src/types/typeguards.ts b/src/types/typeguards.ts deleted file mode 100644 index 05d054b..0000000 --- a/src/types/typeguards.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { GrammyTelegramUpdate } from "../bot/helpers/grammy-context"; -import { PluginInputs } from "./plugin-inputs"; - -export function isTelegramPayload(payload: unknown): payload is GrammyTelegramUpdate { - if (typeof payload !== "object" || !payload) return false; - return "update_id" in payload && payload.update_id !== undefined; -} - -export function isGithubPayload(inputs: unknown): inputs is PluginInputs { - if (typeof inputs !== "object" || !inputs) return false; - return "eventName" in inputs && inputs.eventName !== undefined; -} diff --git a/yarn.lock b/yarn.lock index 48a6443..e87222e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2367,83 +2367,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@octokit/app@^15.0.0": - version "15.1.0" - resolved "https://registry.yarnpkg.com/@octokit/app/-/app-15.1.0.tgz#b330d8826be088ec8d1d43a59dc27ef57d1232b2" - integrity sha512-TkBr7QgOmE6ORxvIAhDbZsqPkF7RSqTY4pLTtUQCvr6dTXqvi2fFo46q3h1lxlk/sGMQjqyZ0kEahkD/NyzOHg== - dependencies: - "@octokit/auth-app" "^7.0.0" - "@octokit/auth-unauthenticated" "^6.0.0" - "@octokit/core" "^6.1.2" - "@octokit/oauth-app" "^7.0.0" - "@octokit/plugin-paginate-rest" "^11.0.0" - "@octokit/types" "^13.0.0" - "@octokit/webhooks" "^13.0.0" - -"@octokit/auth-app@^7.0.0": - version "7.1.1" - resolved "https://registry.yarnpkg.com/@octokit/auth-app/-/auth-app-7.1.1.tgz#d8916ad01e6ffb0a0a50507aa613e91fe7a49b93" - integrity sha512-kRAd6yelV9OgvlEJE88H0VLlQdZcag9UlLr7dV0YYP37X8PPDvhgiTy66QVhDXdyoT0AleFN2w/qXkPdrSzINg== - dependencies: - "@octokit/auth-oauth-app" "^8.1.0" - "@octokit/auth-oauth-user" "^5.1.0" - "@octokit/request" "^9.1.1" - "@octokit/request-error" "^6.1.1" - "@octokit/types" "^13.4.1" - lru-cache "^10.0.0" - universal-github-app-jwt "^2.2.0" - universal-user-agent "^7.0.0" - -"@octokit/auth-oauth-app@^8.0.0", "@octokit/auth-oauth-app@^8.1.0": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-app/-/auth-oauth-app-8.1.1.tgz#6204affa6e86f535016799cadf2af9befe5e893c" - integrity sha512-5UtmxXAvU2wfcHIPPDWzVSAWXVJzG3NWsxb7zCFplCWEmMCArSZV0UQu5jw5goLQXbFyOr5onzEH37UJB3zQQg== - dependencies: - "@octokit/auth-oauth-device" "^7.0.0" - "@octokit/auth-oauth-user" "^5.0.1" - "@octokit/request" "^9.0.0" - "@octokit/types" "^13.0.0" - universal-user-agent "^7.0.0" - -"@octokit/auth-oauth-device@^7.0.0", "@octokit/auth-oauth-device@^7.0.1": - version "7.1.1" - resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-device/-/auth-oauth-device-7.1.1.tgz#7b4f8f97cbcadbe9894d48cde4406dbdef39875a" - integrity sha512-HWl8lYueHonuyjrKKIup/1tiy0xcmQCdq5ikvMO1YwkNNkxb6DXfrPjrMYItNLyCP/o2H87WuijuE+SlBTT8eg== - dependencies: - "@octokit/oauth-methods" "^5.0.0" - "@octokit/request" "^9.0.0" - "@octokit/types" "^13.0.0" - universal-user-agent "^7.0.0" - -"@octokit/auth-oauth-user@^5.0.1", "@octokit/auth-oauth-user@^5.1.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@octokit/auth-oauth-user/-/auth-oauth-user-5.1.1.tgz#4f1570c6ee15bb9ddc3dcca83308dcaa159e3848" - integrity sha512-rRkMz0ErOppdvEfnemHJXgZ9vTPhBuC6yASeFaB7I2yLMd7QpjfrL1mnvRPlyKo+M6eeLxrKanXJ9Qte29SRsw== - dependencies: - "@octokit/auth-oauth-device" "^7.0.1" - "@octokit/oauth-methods" "^5.0.0" - "@octokit/request" "^9.0.1" - "@octokit/types" "^13.0.0" - universal-user-agent "^7.0.0" - "@octokit/auth-token@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-4.0.0.tgz#40d203ea827b9f17f42a29c6afb93b7745ef80c7" integrity sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA== -"@octokit/auth-token@^5.0.0": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-5.1.1.tgz#3bbfe905111332a17f72d80bd0b51a3e2fa2cf07" - integrity sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA== - -"@octokit/auth-unauthenticated@^6.0.0", "@octokit/auth-unauthenticated@^6.0.0-beta.1": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@octokit/auth-unauthenticated/-/auth-unauthenticated-6.1.0.tgz#de0fe923bb06ed93aea526ab99972a98c546d0bf" - integrity sha512-zPSmfrUAcspZH/lOFQnVnvjQZsIvmfApQH6GzJrkIunDooU1Su2qt2FfMTSVPRp7WLTQyC20Kd55lF+mIYaohQ== - dependencies: - "@octokit/request-error" "^6.0.1" - "@octokit/types" "^13.0.0" - "@octokit/core@^5.0.1", "@octokit/core@^5.0.2": version "5.2.0" resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.2.0.tgz#ddbeaefc6b44a39834e1bb2e58a49a117672a7ea" @@ -2457,27 +2385,6 @@ before-after-hook "^2.2.0" universal-user-agent "^6.0.0" -"@octokit/core@^6.0.0", "@octokit/core@^6.1.2": - version "6.1.2" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-6.1.2.tgz#20442d0a97c411612da206411e356014d1d1bd17" - integrity sha512-hEb7Ma4cGJGEUNOAVmyfdB/3WirWMg5hDuNFVejGEDFqupeOysLc2sG6HJxY2etBp5YQu5Wtxwi020jS9xlUwg== - dependencies: - "@octokit/auth-token" "^5.0.0" - "@octokit/graphql" "^8.0.0" - "@octokit/request" "^9.0.0" - "@octokit/request-error" "^6.0.1" - "@octokit/types" "^13.0.0" - before-after-hook "^3.0.2" - universal-user-agent "^7.0.0" - -"@octokit/endpoint@^10.0.0": - version "10.1.1" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-10.1.1.tgz#1a9694e7aef6aa9d854dc78dd062945945869bcc" - integrity sha512-JYjh5rMOwXMJyUpj028cu0Gbp7qe/ihxfJMLc8VZBMMqSwLgOxDI1911gV4Enl1QSavAQNJcwmwBF9M0VvLh6Q== - dependencies: - "@octokit/types" "^13.0.0" - universal-user-agent "^7.0.2" - "@octokit/endpoint@^9.0.1": version "9.0.5" resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-9.0.5.tgz#e6c0ee684e307614c02fc6ac12274c50da465c44" @@ -2495,44 +2402,6 @@ "@octokit/types" "^13.0.0" universal-user-agent "^6.0.0" -"@octokit/graphql@^8.0.0": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-8.1.1.tgz#3cacab5f2e55d91c733e3bf481d3a3f8a5f639c4" - integrity sha512-ukiRmuHTi6ebQx/HFRCXKbDlOh/7xEV6QUXaE7MJEKGNAncGI/STSbOkl12qVXZrfZdpXctx5O9X1AIaebiDBg== - dependencies: - "@octokit/request" "^9.0.0" - "@octokit/types" "^13.0.0" - universal-user-agent "^7.0.0" - -"@octokit/oauth-app@^7.0.0": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@octokit/oauth-app/-/oauth-app-7.1.3.tgz#a0f256dd185e7c00bfbc3e6bc3c5aad66e42c609" - integrity sha512-EHXbOpBkSGVVGF1W+NLMmsnSsJRkcrnVmDKt0TQYRBb6xWfWzoi9sBD4DIqZ8jGhOWO/V8t4fqFyJ4vDQDn9bg== - dependencies: - "@octokit/auth-oauth-app" "^8.0.0" - "@octokit/auth-oauth-user" "^5.0.1" - "@octokit/auth-unauthenticated" "^6.0.0-beta.1" - "@octokit/core" "^6.0.0" - "@octokit/oauth-authorization-url" "^7.0.0" - "@octokit/oauth-methods" "^5.0.0" - "@types/aws-lambda" "^8.10.83" - universal-user-agent "^7.0.0" - -"@octokit/oauth-authorization-url@^7.0.0": - version "7.1.1" - resolved "https://registry.yarnpkg.com/@octokit/oauth-authorization-url/-/oauth-authorization-url-7.1.1.tgz#0e17c2225eb66b58ec902d02b6f1315ffe9ff04b" - integrity sha512-ooXV8GBSabSWyhLUowlMIVd9l1s2nsOGQdlP2SQ4LnkEsGXzeCvbSbCPdZThXhEFzleGPwbapT0Sb+YhXRyjCA== - -"@octokit/oauth-methods@^5.0.0": - version "5.1.2" - resolved "https://registry.yarnpkg.com/@octokit/oauth-methods/-/oauth-methods-5.1.2.tgz#fd31d2a69f4c91d1abc1ed1814dda5252c697e02" - integrity sha512-C5lglRD+sBlbrhCUTxgJAFjWgJlmTx5bQ7Ch0+2uqRjYv7Cfb5xpX4WuSC9UgQna3sqRGBL9EImX9PvTpMaQ7g== - dependencies: - "@octokit/oauth-authorization-url" "^7.0.0" - "@octokit/request" "^9.1.0" - "@octokit/request-error" "^6.1.0" - "@octokit/types" "^13.0.0" - "@octokit/openapi-types@^20.0.0": version "20.0.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-20.0.0.tgz#9ec2daa0090eeb865ee147636e0c00f73790c6e5" @@ -2548,16 +2417,6 @@ resolved "https://registry.yarnpkg.com/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-8.2.1.tgz#08b974f1e83a75c4d3ce23f798c7667b433bf4cd" integrity sha512-msAU1oTSm0ZmvAE0xDemuF4tVs5i0xNnNGtNmr4EuATi+1Rn8cZDetj6NXioSf5LwnxEc209COa/WOSbjuhLUA== -"@octokit/openapi-webhooks-types@8.3.0": - version "8.3.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-8.3.0.tgz#a7a4da00c0f27f7f5708eb3fcebefa08f8d51125" - integrity sha512-vKLsoR4xQxg4Z+6rU/F65ItTUz/EXbD+j/d4mlq2GW8TsA4Tc8Kdma2JTAAJ5hrKWUQzkR/Esn2fjsqiVRYaQg== - -"@octokit/plugin-paginate-graphql@^5.0.0": - version "5.2.2" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-5.2.2.tgz#54e2afef55bb204eb945a891b85a169b9ddad1f8" - integrity sha512-7znSVvlNAOJisCqAnjN1FtEziweOHSjPGAuc5W58NeGNAr/ZB57yCsjQbXDlWsVryA7hHQaEQPcBbJYFawlkyg== - "@octokit/plugin-paginate-rest@11.3.1": version "11.3.1" resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.1.tgz#fe92d04b49f134165d6fbb716e765c2f313ad364" @@ -2565,13 +2424,6 @@ dependencies: "@octokit/types" "^13.5.0" -"@octokit/plugin-paginate-rest@^11.0.0": - version "11.3.3" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.3.tgz#efc97ba66aae6797e2807a082f99b9cfc0e05aba" - integrity sha512-o4WRoOJZlKqEEgj+i9CpcmnByvtzoUYC6I8PD2SA95M+BJ2x8h7oLcVOg9qcowWXBOdcTRsMZiwvM3EyLm9AfA== - dependencies: - "@octokit/types" "^13.5.0" - "@octokit/plugin-paginate-rest@^9.0.0": version "9.2.1" resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz#2e2a2f0f52c9a4b1da1a3aa17dabe3c459b9e401" @@ -2598,30 +2450,6 @@ dependencies: "@octokit/types" "^12.6.0" -"@octokit/plugin-rest-endpoint-methods@^13.0.0": - version "13.2.4" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.2.4.tgz#543add032d3fe3f5d2839bfd619cf66d85469f01" - integrity sha512-gusyAVgTrPiuXOdfqOySMDztQHv6928PQ3E4dqVGEtOvRXAKRbJR4b1zQyniIT9waqaWk/UDaoJ2dyPr7Bk7Iw== - dependencies: - "@octokit/types" "^13.5.0" - -"@octokit/plugin-retry@^7.0.0": - version "7.1.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-retry/-/plugin-retry-7.1.1.tgz#a84483e4afdd068dd71da81abe206a9e442c1288" - integrity sha512-G9Ue+x2odcb8E1XIPhaFBnTTIrrUDfXN05iFXiqhR+SeeeDMMILcAnysOsxUpEWcQp2e5Ft397FCXTcPkiPkLw== - dependencies: - "@octokit/request-error" "^6.0.0" - "@octokit/types" "^13.0.0" - bottleneck "^2.15.3" - -"@octokit/plugin-throttling@^9.0.0": - version "9.3.1" - resolved "https://registry.yarnpkg.com/@octokit/plugin-throttling/-/plugin-throttling-9.3.1.tgz#5648165e1e70e861625f3a16af6c55cafe861061" - integrity sha512-Qd91H4liUBhwLB2h6jZ99bsxoQdhgPk6TdwnClPyTBSDAdviGPceViEgUwj+pcQDmB/rfAXAXK7MTochpHM3yQ== - dependencies: - "@octokit/types" "^13.0.0" - bottleneck "^2.15.3" - "@octokit/request-error@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-5.1.0.tgz#ee4138538d08c81a60be3f320cd71063064a3b30" @@ -2631,7 +2459,7 @@ deprecation "^2.0.0" once "^1.4.0" -"@octokit/request-error@^6.0.0", "@octokit/request-error@^6.0.1", "@octokit/request-error@^6.1.0", "@octokit/request-error@^6.1.1": +"@octokit/request-error@^6.0.1": version "6.1.4" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-6.1.4.tgz#ad96e29148d19edc2ba8009fc2b5a24a36c90f16" integrity sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg== @@ -2648,16 +2476,6 @@ "@octokit/types" "^13.1.0" universal-user-agent "^6.0.0" -"@octokit/request@^9.0.0", "@octokit/request@^9.0.1", "@octokit/request@^9.1.0", "@octokit/request@^9.1.1": - version "9.1.3" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-9.1.3.tgz#42b693bc06238f43af3c037ebfd35621c6457838" - integrity sha512-V+TFhu5fdF3K58rs1pGUJIDH5RZLbZm5BI+MNF+6o/ssFNT4vWlCh/tVpF3NxGtP15HUxTTMUbsG5llAuU2CZA== - dependencies: - "@octokit/endpoint" "^10.0.0" - "@octokit/request-error" "^6.0.1" - "@octokit/types" "^13.1.0" - universal-user-agent "^7.0.2" - "@octokit/rest@20.1.1": version "20.1.1" resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-20.1.1.tgz#ec775864f53fb42037a954b9a40d4f5275b3dc95" @@ -2675,7 +2493,7 @@ dependencies: "@octokit/openapi-types" "^20.0.0" -"@octokit/types@^13.0.0", "@octokit/types@^13.1.0", "@octokit/types@^13.4.1", "@octokit/types@^13.5.0": +"@octokit/types@^13.0.0", "@octokit/types@^13.1.0", "@octokit/types@^13.5.0": version "13.5.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-13.5.0.tgz#4796e56b7b267ebc7c921dcec262b3d5bfb18883" integrity sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ== @@ -2697,15 +2515,6 @@ "@octokit/webhooks-methods" "^5.0.0" aggregate-error "^5.0.0" -"@octokit/webhooks@^13.0.0": - version "13.3.0" - resolved "https://registry.yarnpkg.com/@octokit/webhooks/-/webhooks-13.3.0.tgz#fd5d54d47c789c75d60a00eb04e982152d7c654a" - integrity sha512-TUkJLtI163Bz5+JK0O+zDkQpn4gKwN+BovclUvCj6pI/6RXrFqQvUMRS2M+Rt8Rv0qR3wjoMoOPmpJKeOh0nBg== - dependencies: - "@octokit/openapi-webhooks-types" "8.3.0" - "@octokit/request-error" "^6.0.1" - "@octokit/webhooks-methods" "^5.0.0" - "@open-draft/deferred-promise@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" @@ -2819,11 +2628,6 @@ "@supabase/realtime-js" "2.10.2" "@supabase/storage-js" "2.7.0" -"@types/aws-lambda@^8.10.83": - version "8.10.145" - resolved "https://registry.yarnpkg.com/@types/aws-lambda/-/aws-lambda-8.10.145.tgz#b2d31a987f4888e5553ff1819f57cafa475594d9" - integrity sha512-dtByW6WiFk5W5Jfgz1VM+YPA21xMXTuSFoLYIDY0L44jDLLflVPtZkYuu3/YxpGcvjzKFBZLU+GyKjR0HOYtyw== - "@types/babel__core@^7.1.14": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -3639,11 +3443,6 @@ before-after-hook@^2.2.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== -before-after-hook@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-3.0.2.tgz#d5665a5fa8b62294a5aa0a499f933f4a1016195d" - integrity sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A== - big-integer@^1.6.48, big-integer@^1.6.52: version "1.6.52" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" @@ -3659,11 +3458,6 @@ blake3-wasm@^2.1.5: resolved "https://registry.yarnpkg.com/blake3-wasm/-/blake3-wasm-2.1.5.tgz#b22dbb84bc9419ed0159caa76af4b1b132e6ba52" integrity sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g== -bottleneck@^2.15.3: - version "2.19.5" - resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" - integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -6832,11 +6626,6 @@ loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -lru-cache@^10.0.0: - version "10.4.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" - integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== - lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -7236,22 +7025,6 @@ object.values@^1.1.6, object.values@^1.1.7, object.values@^1.2.0: define-properties "^1.2.1" es-object-atoms "^1.0.0" -octokit@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/octokit/-/octokit-4.0.2.tgz#775d68d363cdaec69d7b73d3dc82ae909d30f59b" - integrity sha512-wbqF4uc1YbcldtiBFfkSnquHtECEIpYD78YUXI6ri1Im5OO2NLo6ZVpRdbJpdnpZ05zMrVPssNiEo6JQtea+Qg== - dependencies: - "@octokit/app" "^15.0.0" - "@octokit/core" "^6.0.0" - "@octokit/oauth-app" "^7.0.0" - "@octokit/plugin-paginate-graphql" "^5.0.0" - "@octokit/plugin-paginate-rest" "^11.0.0" - "@octokit/plugin-rest-endpoint-methods" "^13.0.0" - "@octokit/plugin-retry" "^7.0.0" - "@octokit/plugin-throttling" "^9.0.0" - "@octokit/request-error" "^6.0.0" - "@octokit/types" "^13.0.0" - once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -8741,21 +8514,11 @@ unicorn-magic@^0.1.0: resolved "https://registry.yarnpkg.com/unicorn-magic/-/unicorn-magic-0.1.0.tgz#1bb9a51c823aaf9d73a8bfcd3d1a23dde94b0ce4" integrity sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ== -universal-github-app-jwt@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-2.2.0.tgz#dc6c8929e76f1996a766ba2a08fb420f73365d77" - integrity sha512-G5o6f95b5BggDGuUfKDApKaCgNYy2x7OdHY0zSMF081O0EJobw+1130VONhrA7ezGSV2FNOGyM+KQpQZAr9bIQ== - universal-user-agent@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.1.tgz#15f20f55da3c930c57bddbf1734c6654d5fd35aa" integrity sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ== -universal-user-agent@^7.0.0, universal-user-agent@^7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-7.0.2.tgz#52e7d0e9b3dc4df06cc33cb2b9fd79041a54827e" - integrity sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q== - universalify@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" From 5604ee4c6ad60e4f24c3253ebf3dd4a3da84f3e4 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 27 Sep 2024 10:43:40 +0100 Subject: [PATCH 71/76] chore: add deploy-delete workflows --- .github/workflows/worker-delete.yml | 44 ++++++++++++++++++++++++++ .github/workflows/worker-deploy.yml | 48 +++++++++++++++++++++++++++++ package.json | 2 +- 3 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/worker-delete.yml create mode 100644 .github/workflows/worker-deploy.yml diff --git a/.github/workflows/worker-delete.yml b/.github/workflows/worker-delete.yml new file mode 100644 index 0000000..75b9c91 --- /dev/null +++ b/.github/workflows/worker-delete.yml @@ -0,0 +1,44 @@ +name: Delete Deployment + +on: + delete: + +jobs: + delete: + runs-on: ubuntu-latest + name: Delete Deployment + steps: + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "20.10.0" + + - name: Enable corepack + run: corepack enable + + - uses: actions/checkout@v4 + + - name: Get Deleted Branch Name + id: get_branch + run: | + branch_name=$(echo '${{ github.event.ref }}' | sed 's#refs/heads/##' | sed 's#[^a-zA-Z0-9]#-#g') + echo "branch_name=$branch_name" >> $GITHUB_ENV + - name: Retrieve and Construct Full Worker Name + id: construct_worker_name + run: | + base_name=$(grep '^name = ' wrangler.toml | head -n 1 | sed 's/^name = "\(.*\)"$/\1/') + full_worker_name="${base_name}-${{ env.branch_name }}" + # Make sure that it doesnt exceed 63 characters or it will break RFC 1035 + full_worker_name=$(echo "${full_worker_name}" | cut -c 1-63) + echo "full_worker_name=$full_worker_name" >> $GITHUB_ENV + - name: Delete Deployment with Wrangler + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: delete --name ${{ env.full_worker_name }} + + - name: Output Deletion Result + run: | + echo "### Deployment URL" >> $GITHUB_STEP_SUMMARY + echo 'Deployment `${{ env.full_worker_name }}` has been deleted.' >> $GITHUB_STEP_SUMMARY \ No newline at end of file diff --git a/.github/workflows/worker-deploy.yml b/.github/workflows/worker-deploy.yml new file mode 100644 index 0000000..2c253e7 --- /dev/null +++ b/.github/workflows/worker-deploy.yml @@ -0,0 +1,48 @@ +name: Deploy Worker + +on: + push: + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: "20.10.0" + + - name: Enable corepack + run: corepack enable + + - uses: actions/checkout@v4 + + - name: Update wrangler.toml Name Field + run: | + branch_name=$(echo '${{ github.event.ref }}' | sed 's#refs/heads/##' | sed 's#[^a-zA-Z0-9]#-#g') + # Extract base name from wrangler.toml + base_name=$(grep '^name = ' wrangler.toml | head -n 1 | sed 's/^name = "\(.*\)"$/\1/') + # Concatenate branch name with base name + new_name="${base_name}-${branch_name}" + # Truncate the new name to 63 characters for RFC 1035 + new_name=$(echo "$new_name" | cut -c 1-63) + # Update the wrangler.toml file + sed -i '0,/^name = .*/{s/^name = .*/name = "'"$new_name"'"/}' wrangler.toml + echo "Updated wrangler.toml name to: $new_name" + - name: Deploy with Wrangler + id: wrangler_deploy + uses: cloudflare/wrangler-action@v3 + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + secrets: | + TELEGRAM_BOT_ENV + env: + TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} + + - name: Write Deployment URL to Summary + run: | + echo "### Deployment URL" >> $GITHUB_STEP_SUMMARY + echo "${{ steps.wrangler_deploy.outputs.deployment-url }}" >> $GITHUB_STEP_SUMMARY \ No newline at end of file diff --git a/package.json b/package.json index e1a4767..1d19c11 100644 --- a/package.json +++ b/package.json @@ -102,4 +102,4 @@ ] }, "packageManager": "yarn@1.22.22" -} \ No newline at end of file +} From c8b332551ddd776207421f3c0e0647aecd73c061 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Fri, 27 Sep 2024 10:53:55 +0100 Subject: [PATCH 72/76] chore: rename kernel-telegram --- .github/workflows/compute.yml | 4 ++-- README.md | 2 +- manifest.json | 10 +++++++--- package.json | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index ab6653e..fabc2d9 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -18,7 +18,7 @@ on: jobs: compute: - name: "Telegram-Bot" + name: "Kernel-Telegram" runs-on: ubuntu-latest permissions: write-all env: @@ -37,6 +37,6 @@ jobs: - name: execute directive run: npx tsx ./src/workflow-entry.ts - id: telegram-bridge + id: Kernel-Telegram env: TELEGRAM_BOT_ENV: ${{ secrets.TELEGRAM_BOT_ENV }} diff --git a/README.md b/README.md index d6bc387..291f3ce 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# `@ubiquity-os/telegram-bridge` +# `@ubiquity-os/kernel-telegram` A Telegram bridge for Ubiquity OS, uniquely combining Cloudflare Workers and GitHub Actions to deliver seamless integration with both Telegram and GitHub. This hybrid plugin is the first of its kind to support both worker and workflow functionality, running across Cloudflare V8 and Node.js environments for enhanced flexibility and performance across multiple runtimes. diff --git a/manifest.json b/manifest.json index 1c9e4fc..636b0a9 100644 --- a/manifest.json +++ b/manifest.json @@ -1,5 +1,9 @@ { - "name": "ubiquity-os/telegram-bridge", + "name": "ubiquity-os/kernel-telegram", "description": "Part kernel plugin, part Telegram kernel. This bot is designed to be a bridge between UbiquityOS and Telegram.", - "ubiquity:listeners": ["issues.labeled", "issues.closed", "issues.reopened"] -} + "ubiquity:listeners": [ + "issues.labeled", + "issues.closed", + "issues.reopened" + ] +} \ No newline at end of file diff --git a/package.json b/package.json index 1d19c11..94e3241 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@ubiquity-os/telegram-bridge", + "name": "@ubiquity-os/kernel-telegram", "version": "0.1.0", "description": "Part kernel plugin, part Telegram kernel. This bot is designed to be a bridge between UbiquityOS and Telegram.", "author": "Ubiquity DAO", From 2d030cd7c427ca769709b6b7bd7d6f2f9881ecb7 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:09:51 +0100 Subject: [PATCH 73/76] chore: log pat error, add supabase cli, add smee-client --- .cspell.json | 2 +- .github/workflows/worker-delete.yml | 2 +- .github/workflows/worker-deploy.yml | 2 +- README.md | 41 +- manifest.json | 8 +- package.json | 4 +- .../bot/scripts/sms-auth/setup-env.ts | 3 +- supabase/.gitignore | 4 + supabase/config.toml | 42 ++ .../{init.sql => 20240930115120_init.sql} | 0 supabase/seed.sql | 0 yarn.lock | 446 ++++++++++++++---- 12 files changed, 434 insertions(+), 120 deletions(-) create mode 100644 supabase/.gitignore create mode 100644 supabase/config.toml rename supabase/migrations/{init.sql => 20240930115120_init.sql} (100%) create mode 100644 supabase/seed.sql diff --git a/.cspell.json b/.cspell.json index 84688c5..d4460d2 100644 --- a/.cspell.json +++ b/.cspell.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json", "version": "0.2", - "ignorePaths": ["**/*.json", "**/*.css", "node_modules", "**/*.log", "./src/adapters/supabase/**/**.ts"], + "ignorePaths": ["**/*.json", "**/*.css", "node_modules", "**/*.log", "./src/adapters/supabase/**/**.ts", "supabase/config.toml"], "useGitignore": true, "language": "en", "words": [ diff --git a/.github/workflows/worker-delete.yml b/.github/workflows/worker-delete.yml index 75b9c91..f715a20 100644 --- a/.github/workflows/worker-delete.yml +++ b/.github/workflows/worker-delete.yml @@ -41,4 +41,4 @@ jobs: - name: Output Deletion Result run: | echo "### Deployment URL" >> $GITHUB_STEP_SUMMARY - echo 'Deployment `${{ env.full_worker_name }}` has been deleted.' >> $GITHUB_STEP_SUMMARY \ No newline at end of file + echo 'Deployment `${{ env.full_worker_name }}` has been deleted.' >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/worker-deploy.yml b/.github/workflows/worker-deploy.yml index 2c253e7..468e5bf 100644 --- a/.github/workflows/worker-deploy.yml +++ b/.github/workflows/worker-deploy.yml @@ -45,4 +45,4 @@ jobs: - name: Write Deployment URL to Summary run: | echo "### Deployment URL" >> $GITHUB_STEP_SUMMARY - echo "${{ steps.wrangler_deploy.outputs.deployment-url }}" >> $GITHUB_STEP_SUMMARY \ No newline at end of file + echo "${{ steps.wrangler_deploy.outputs.deployment-url }}" >> $GITHUB_STEP_SUMMARY diff --git a/README.md b/README.md index 291f3ce..83c68ab 100644 --- a/README.md +++ b/README.md @@ -137,37 +137,22 @@ plugins: 2. Run the migration or copypaste the SQL migration file from `./supabase/migrations` in the Supabase dashboard. 3. Add your `SUPABASE_URL` and `SUPABASE_SERVICE_KEY` to your environment variables. -##### Running the Migration +##### Supabase Commands -1. Install the Supabase CLI. If you don't have it installed yet, you can install it via npm: - - ```bash - npm install -g supabase - ``` - -2. Make sure your Supabase project is initialized. If not, initialize it: - - ```bash - supabase init - ``` - -3. Set up your `.env` file with your Supabase credentials (or make sure you have already logged in using `supabase login`). - -4. To run the migrations on your local environment, use: - - ```bash - supabase db reset - ``` - - This command will reset your local database and apply all migrations. - -5. To push migrations to your remote database, use: +- To start the Supabase database locally, run the following command: +```bash +yarn supabase db start +``` - ```bash - supabase db push - ``` +- To reset the Supabase database, run the following command: +```bash +yarn supabase db reset +``` - This will apply all migrations to the remote Supabase database. +- To stop the Supabase database, run the following command: +```bash +yarn supabase stop +``` For more detailed information, refer to the official [Supabase documentation](https://supabase.com/docs). diff --git a/manifest.json b/manifest.json index 636b0a9..20b8a56 100644 --- a/manifest.json +++ b/manifest.json @@ -1,9 +1,5 @@ { "name": "ubiquity-os/kernel-telegram", "description": "Part kernel plugin, part Telegram kernel. This bot is designed to be a bridge between UbiquityOS and Telegram.", - "ubiquity:listeners": [ - "issues.labeled", - "issues.closed", - "issues.reopened" - ] -} \ No newline at end of file + "ubiquity:listeners": ["issues.labeled", "issues.closed", "issues.reopened"] +} diff --git a/package.json b/package.json index 94e3241..9f3c75b 100644 --- a/package.json +++ b/package.json @@ -80,12 +80,14 @@ "lint-staged": "15.2.9", "npm-run-all": "4.1.5", "prettier": "3.3.3", + "smee-client": "2.0.3", + "supabase": "^1.200.3", "ts-jest": "29.2.5", "tsc-watch": "^6.2.0", "tsx": "4.18.0", "typescript": "5.5.4", "typescript-eslint": "8.3.0", - "wrangler": "3.72.2" + "wrangler": "^3.78.12" }, "lint-staged": { "*.ts": [ diff --git a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts index 50ebc28..ccdf6b0 100644 --- a/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts +++ b/src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts @@ -277,7 +277,8 @@ class SetUpHandler { }); return true; - } catch { + } catch (e) { + logger.error("Error testing access token", { e }); return false; } } diff --git a/supabase/.gitignore b/supabase/.gitignore new file mode 100644 index 0000000..a3ad880 --- /dev/null +++ b/supabase/.gitignore @@ -0,0 +1,4 @@ +# Supabase +.branches +.temp +.env diff --git a/supabase/config.toml b/supabase/config.toml new file mode 100644 index 0000000..629b288 --- /dev/null +++ b/supabase/config.toml @@ -0,0 +1,42 @@ +project_id = "supabase" + +[api] +enabled = true +port = 54321 +schemas = ["public", "graphql_public"] +extra_search_path = ["public", "extensions"] +max_rows = 1000 + +[api.tls] +enabled = false + +[db] +port = 54322 +shadow_port = 54320 +major_version = 15 + +[db.pooler] +enabled = false +port = 54329 +pool_mode = "transaction" +default_pool_size = 20 +max_client_conn = 100 + +[realtime] +enabled = true + +[studio] +enabled = true +port = 54323 +api_url = "http://127.0.0.1" +openai_api_key = "env(OPENAI_API_KEY)" + +[edge_runtime] +enabled = true +policy = "oneshot" +inspector_port = 8083 + +[analytics] +enabled = false +port = 54327 +backend = "postgres" \ No newline at end of file diff --git a/supabase/migrations/init.sql b/supabase/migrations/20240930115120_init.sql similarity index 100% rename from supabase/migrations/init.sql rename to supabase/migrations/20240930115120_init.sql diff --git a/supabase/seed.sql b/supabase/seed.sql new file mode 100644 index 0000000..e69de29 diff --git a/yarn.lock b/yarn.lock index e87222e..fb3bbc7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1109,35 +1109,38 @@ dependencies: mime "^3.0.0" -"@cloudflare/workerd-darwin-64@1.20240821.1": - version "1.20240821.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240821.1.tgz#06b8fcd372ab5ceb44c2b30892edccaa8cd97003" - integrity sha512-CDBpfZKrSy4YrIdqS84z67r3Tzal2pOhjCsIb63IuCnvVes59/ft1qhczBzk9EffeOE2iTCrA4YBT7Sbn7USew== - -"@cloudflare/workerd-darwin-arm64@1.20240821.1": - version "1.20240821.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240821.1.tgz#b277d276d016ea41686ba44bf43735f6563bb91f" - integrity sha512-Q+9RedvNbPcEt/dKni1oN94OxbvuNAeJkgHmrLFTGF8zu21wzOhVkQeRNxcYxrMa9mfStc457NAg13OVCj2kHQ== - -"@cloudflare/workerd-linux-64@1.20240821.1": - version "1.20240821.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240821.1.tgz#9e16da0858674d1bb0ece41b482fb161f9da6646" - integrity sha512-j6z3KsPtawrscoLuP985LbqFrmsJL6q1mvSXOXTqXGODAHIzGBipHARdOjms3UQqovzvqB2lQaQsZtLBwCZxtA== - -"@cloudflare/workerd-linux-arm64@1.20240821.1": - version "1.20240821.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240821.1.tgz#c9eec3f830a4bbf1f80b3c828783db8025de69d9" - integrity sha512-I9bHgZOxJQW0CV5gTdilyxzTG7ILzbTirehQWgfPx9X77E/7eIbR9sboOMgyeC69W4he0SKtpx0sYZuTJu4ERw== - -"@cloudflare/workerd-windows-64@1.20240821.1": - version "1.20240821.1" - resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240821.1.tgz#256d61b5dd327f2b86fa4a522fe977f97aa188a2" - integrity sha512-keC97QPArs6LWbPejQM7/Y8Jy8QqyaZow4/ZdsGo+QjlOLiZRDpAenfZx3CBUoWwEeFwQTl2FLO+8hV1SWFFYw== - -"@cloudflare/workers-shared@0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@cloudflare/workers-shared/-/workers-shared-0.3.0.tgz#38e462925a2fbe974cd8108ca0a39756509c8e8f" - integrity sha512-cqtLW1QiBC/ABaZIhAdyGCsnHHY6pAb6hsVUZg82Co2gQtf/faxRYV1FgpCwUYroTdk6A66xUMSTmFqreKCJow== +"@cloudflare/workerd-darwin-64@1.20240925.0": + version "1.20240925.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20240925.0.tgz#f78fe394f73540594609d8e05a2da7feb46c76c0" + integrity sha512-KdLnSXuzB65CbqZPm+qYzk+zkQ1tUNPaaRGYVd/jPYAxwwtfTUQdQ+ahDPwVVs2tmQELKy7ZjQjf2apqSWUfjw== + +"@cloudflare/workerd-darwin-arm64@1.20240925.0": + version "1.20240925.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20240925.0.tgz#f03b17177744ad898bb12610d15cc0a9744abfe6" + integrity sha512-MiQ6uUmCXjsXgWNV+Ock2tp2/tYqNJGzjuaH6jFioeRF+//mz7Tv7J7EczOL4zq+TH8QFOh0/PUsLyazIWVGng== + +"@cloudflare/workerd-linux-64@1.20240925.0": + version "1.20240925.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20240925.0.tgz#fe0366b804b957acf5012d889e94163bab806a57" + integrity sha512-Rjix8jsJMfsInmq3Hm3fmiRQ+rwzuWRPV1pg/OWhMSfNP7Qp2RCU+RGkhgeR9Z5eNAje0Sn2BMrFq4RvF9/yRA== + +"@cloudflare/workerd-linux-arm64@1.20240925.0": + version "1.20240925.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20240925.0.tgz#fcf82de06def420972c661a6021c87683cd8fbdc" + integrity sha512-VYIPeMHQRtbwQoIjUwS/zULlywPxyDvo46XkTpIW5MScEChfqHvAYviQ7TzYGx6Q+gmZmN+DUB2KOMx+MEpCxA== + +"@cloudflare/workerd-windows-64@1.20240925.0": + version "1.20240925.0" + resolved "https://registry.yarnpkg.com/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20240925.0.tgz#0a5c82b95b03a94591cc8a1830f28d2e41ff7685" + integrity sha512-C8peGvaU5R51bIySi1VbyfRgwNSSRknqoFSnSbSBI3uTN3THTB3UnmRKy7GXJDmyjgXuT9Pcs1IgaWNubLtNtw== + +"@cloudflare/workers-shared@0.5.4": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@cloudflare/workers-shared/-/workers-shared-0.5.4.tgz#bbf8f03b79a6bc0169ad66a6015ebe579d36753a" + integrity sha512-PNL/0TjKRdUHa1kwgVdqUNJVZ9ez4kacsi8omz+gv859EvJmsVuGiMAClY2YfJnC9LVKhKCcjqmFgKNXG9/IXA== + dependencies: + mime "^3.0.0" + zod "^3.22.3" "@cloudflare/workers-types@^4.20240529.0": version "4.20240821.1" @@ -2058,6 +2061,25 @@ dependencies: mute-stream "^1.0.0" +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@isaacs/fs-minipass@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" + integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== + dependencies: + minipass "^7.0.4" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -2533,6 +2555,11 @@ resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda" integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@pkgr/core@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" @@ -3055,6 +3082,13 @@ acorn@^8.11.0, acorn@^8.12.0, acorn@^8.8.0, acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== +agent-base@^7.0.2: + version "7.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" + integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== + dependencies: + debug "^4.3.4" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -3149,7 +3183,7 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -ansi-styles@^6.0.0, ansi-styles@^6.2.1: +ansi-styles@^6.0.0, ansi-styles@^6.1.0, ansi-styles@^6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== @@ -3448,6 +3482,16 @@ big-integer@^1.6.48, big-integer@^1.6.52: resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== +bin-links@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-4.0.4.tgz#c3565832b8e287c85f109a02a17027d152a58a63" + integrity sha512-cMtq4W5ZsEwcutJrVId+a/tjt8GSbS+h0oNkdl6+6rBuEv8Ot33Bevj5KPm40t309zuhVic8NjpuL42QCiJWWA== + dependencies: + cmd-shim "^6.0.0" + npm-normalize-package-bin "^3.0.0" + read-cmd-shim "^4.0.0" + write-file-atomic "^5.0.0" + binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" @@ -3643,6 +3687,11 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chownr@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" + integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== + ci-info@^3.2.0: version "3.9.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" @@ -3729,6 +3778,11 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== +cmd-shim@^6.0.0: + version "6.0.3" + resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-6.0.3.tgz#c491e9656594ba17ac83c4bd931590a9d6e26033" + integrity sha512-FMabTRlc5t5zjdenF6mS0MBeFZm0XqHqeOkcskKFb/LYCcRQ5fVgLOHVc4Lq9CqABd9zhjwPjMBCJvMCziSVtA== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -3773,7 +3827,7 @@ colorette@^2.0.20: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== -commander@^12.1.0, commander@~12.1.0: +commander@^12.0.0, commander@^12.1.0, commander@~12.1.0: version "12.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== @@ -3807,11 +3861,6 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -consola@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f" - integrity sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ== - conventional-changelog-angular@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz#5eec8edbff15aa9b1680a8dcfbd53e2d7eb2ba7a" @@ -3909,7 +3958,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -4063,6 +4112,11 @@ data-uri-to-buffer@^2.0.0: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz#d296973d5a4897a5dbe31716d118211921f04770" integrity sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA== +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + data-view-buffer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" @@ -4097,10 +4151,12 @@ date-fns@^2.21.1: dependencies: "@babel/runtime" "^7.21.0" -date-fns@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-3.6.0.tgz#f20ca4fe94f8b754951b24240676e8618c0206bf" - integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww== +debug@4: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" debug@^2.2.0: version "2.6.9" @@ -4280,6 +4336,11 @@ duplexer@~0.1.1: resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + easy-table@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/easy-table/-/easy-table-1.2.0.tgz#ba9225d7138fee307bfd4f0b5bc3c04bdc7c54eb" @@ -4923,6 +4984,11 @@ eventemitter3@^5.0.1: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== +eventsource@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-2.0.2.tgz#76dfcc02930fb2ff339520b6d290da573a9e8508" + integrity sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA== + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -5041,6 +5107,14 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + figures@^1.3.5: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" @@ -5135,6 +5209,21 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" +foreground-child@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" + integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" @@ -5278,6 +5367,18 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== +glob@^10.3.7: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -5454,6 +5555,14 @@ htmlparser2@^6.1.0: domutils "^2.5.2" entities "^2.0.0" +https-proxy-agent@^7.0.2: + version "7.0.5" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" + integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw== + dependencies: + agent-base "^7.0.2" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -5926,6 +6035,15 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + jake@^10.8.5: version "10.9.2" resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f" @@ -6626,6 +6744,11 @@ loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -6733,10 +6856,10 @@ mimic-response@^3.1.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== -miniflare@3.20240821.0: - version "3.20240821.0" - resolved "https://registry.yarnpkg.com/miniflare/-/miniflare-3.20240821.0.tgz#d4fc648ca20c033c4143a8d0ef061dedccad7c2d" - integrity sha512-4BhLGpssQxM/O6TZmJ10GkT3wBJK6emFkZ3V87/HyvQmVt8zMxEBvyw5uv6kdtp+7F54Nw6IKFJjPUL8rFVQrQ== +miniflare@3.20240925.0: + version "3.20240925.0" + resolved "https://registry.yarnpkg.com/miniflare/-/miniflare-3.20240925.0.tgz#a291998dedf90bfb4bcfdad033ba030851ff9171" + integrity sha512-2LmQbKHf0n6ertUKhT+Iltixi53giqDH7P71+wCir3OnGyXIODqYwOECx1mSDNhYThpxM2dav8UdPn6SQiMoXw== dependencies: "@cspotcode/source-map-support" "0.8.1" acorn "^8.8.0" @@ -6746,7 +6869,7 @@ miniflare@3.20240821.0: glob-to-regexp "^0.4.1" stoppable "^1.1.0" undici "^5.28.4" - workerd "1.20240821.1" + workerd "1.20240925.0" ws "^8.17.1" youch "^3.2.2" zod "^3.22.3" @@ -6784,11 +6907,29 @@ minimisted@^2.0.0: dependencies: minimist "^1.2.5" +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4, minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +minizlib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.0.1.tgz#46d5329d1eb3c83924eff1d3b858ca0a31581012" + integrity sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg== + dependencies: + minipass "^7.0.4" + rimraf "^5.0.5" + mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mkdirp@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" + integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -6799,7 +6940,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -6867,10 +7008,10 @@ node-cleanup@^2.1.2: resolved "https://registry.yarnpkg.com/node-cleanup/-/node-cleanup-2.1.2.tgz#7ac19abd297e09a7f72a71545d951b517e4dde2c" integrity sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw== -node-fetch-native@^1.6.4: - version "1.6.4" - resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.4.tgz#679fc8fd8111266d47d7e72c379f1bed9acff06e" - integrity sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ== +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== node-fetch@^2.7.0: version "2.7.0" @@ -6879,6 +7020,15 @@ node-fetch@^2.7.0: dependencies: whatwg-url "^5.0.0" +node-fetch@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + node-forge@^1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -6921,6 +7071,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +npm-normalize-package-bin@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz#25447e32a9a7de1f51362c61a559233b89947832" + integrity sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ== + npm-run-all@4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" @@ -7025,6 +7180,11 @@ object.values@^1.1.6, object.values@^1.1.7, object.values@^1.2.0: define-properties "^1.2.1" es-object-atoms "^1.0.0" +ohash@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/ohash/-/ohash-1.1.4.tgz#ae8d83014ab81157d2c285abf7792e2995fadd72" + integrity sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g== + once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -7129,6 +7289,11 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + pako@^1.0.10: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" @@ -7216,11 +7381,24 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-to-regexp@^6.2.0: version "6.2.2" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz#324377a83e5049cbecadc5554d6a63a9a4866b36" integrity sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw== +path-to-regexp@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" + integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== + path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -7399,6 +7577,11 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== +read-cmd-shim@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-4.0.0.tgz#640a08b473a49043e394ae0c7a34dd822c73b9bb" + integrity sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q== + read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -7615,6 +7798,13 @@ rfdc@^1.4.1: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== +rimraf@^5.0.5: + version "5.0.10" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.10.tgz#23b9843d3dc92db71f96e1a2ce92e39fd2a8221c" + integrity sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ== + dependencies: + glob "^10.3.7" + rollup-plugin-inject@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz#e4233855bfba6c0c12a312fd6649dff9a13ee9f4" @@ -7794,7 +7984,7 @@ signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -signal-exit@^4.1.0: +signal-exit@^4.0.1, signal-exit@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== @@ -7849,6 +8039,15 @@ smart-buffer@^4.2.0: resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== +smee-client@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/smee-client/-/smee-client-2.0.3.tgz#de57d90a2531af136e0f0496a88599376ad53fa8" + integrity sha512-W5tQKHzZFe+IMBlaAJ8Ho32Y2wbUbzriHAA2DAFXpITId+0dYHJJbAX36a/HMrGjW7yFjhcKCNPwRBAiIrlZGQ== + dependencies: + commander "^12.0.0" + eventsource "^2.0.2" + validator "^13.11.0" + smol-toml@^1.1.4: version "1.3.0" resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.3.0.tgz#5200e251fffadbb72570c84e9776d2a3eca48143" @@ -7990,6 +8189,15 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -8008,6 +8216,15 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + string-width@^7.0.0: version "7.2.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" @@ -8096,6 +8313,13 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" @@ -8110,7 +8334,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.1.0: +strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== @@ -8152,6 +8376,16 @@ summary@2.1.0: resolved "https://registry.yarnpkg.com/summary/-/summary-2.1.0.tgz#be8a49a0aa34eb6ceea56042cae88f8add4b0885" integrity sha512-nMIjMrd5Z2nuB2RZCKJfFMjgS3fygbeyGk9PxPPaJR1RIcyN9yn4A63Isovzm3ZtQuEkLBVgMdPup8UeLH7aQw== +supabase@^1.200.3: + version "1.200.3" + resolved "https://registry.yarnpkg.com/supabase/-/supabase-1.200.3.tgz#52cd53fd0bcd46af0748c8ffa61fac05e21a0a23" + integrity sha512-3NdhqBkfPVlm+rAhWQoVcyr54kykuAlHav/GWaAoQEHBDbbYI1lhbDzugk8ryQg92vSLwr3pWz0s4Hjdte8WyQ== + dependencies: + bin-links "^4.0.3" + https-proxy-agent "^7.0.2" + node-fetch "^3.3.2" + tar "7.4.3" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -8196,6 +8430,18 @@ tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== +tar@7.4.3: + version "7.4.3" + resolved "https://registry.yarnpkg.com/tar/-/tar-7.4.3.tgz#88bbe9286a3fcd900e94592cda7a22b192e80571" + integrity sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw== + dependencies: + "@isaacs/fs-minipass" "^4.0.0" + chownr "^3.0.0" + minipass "^7.1.2" + minizlib "^3.0.1" + mkdirp "^3.0.1" + yallist "^5.0.0" + telegram@^2.24.11: version "2.24.11" resolved "https://registry.yarnpkg.com/telegram/-/telegram-2.24.11.tgz#2b0238a2cead8cf63adea23d362de34f85fe4124" @@ -8442,7 +8688,7 @@ typescript@5.5.4: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== -ufo@^1.5.3: +ufo@^1.5.4: version "1.5.4" resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.4.tgz#16d6949674ca0c9e0fbbae1fa20a71d7b1ded754" integrity sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ== @@ -8474,17 +8720,15 @@ undici@^5.25.4, undici@^5.28.4: dependencies: "@fastify/busboy" "^2.0.0" -"unenv@npm:unenv-nightly@1.10.0-1717606461.a117952": - version "1.10.0-1717606461.a117952" - resolved "https://registry.yarnpkg.com/unenv-nightly/-/unenv-nightly-1.10.0-1717606461.a117952.tgz#ff0b97e1e159f84be747271e1d55263b4b3eae7e" - integrity sha512-u3TfBX02WzbHTpaEfWEKwDijDSFAHcgXkayUZ+MVDrjhLFvgAJzFGTSTmwlEhwWi2exyRQey23ah9wELMM6etg== +"unenv@npm:unenv-nightly@2.0.0-20240919-125358-9a64854": + version "2.0.0-20240919-125358-9a64854" + resolved "https://registry.yarnpkg.com/unenv-nightly/-/unenv-nightly-2.0.0-20240919-125358-9a64854.tgz#13f6812c7b12b9521ea05c6d49259d136e093acd" + integrity sha512-XjsgUTrTHR7iw+k/SRTNjh6EQgwpC9voygnoCJo5kh4hKqsSDHUW84MhL9EsHTNfLctvVBHaSw8e2k3R2fKXsQ== dependencies: - consola "^3.2.3" defu "^6.1.4" - mime "^3.0.0" - node-fetch-native "^1.6.4" + ohash "^1.1.4" pathe "^1.1.2" - ufo "^1.5.3" + ufo "^1.5.4" unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" @@ -8581,6 +8825,11 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +validator@^13.11.0: + version "13.12.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.12.0.tgz#7d78e76ba85504da3fee4fd1922b385914d4b35f" + integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg== + vscode-languageserver-textdocument@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz#457ee04271ab38998a093c68c2342f53f6e4a631" @@ -8618,6 +8867,11 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" +web-streams-polyfill@^3.0.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -8712,43 +8966,51 @@ word-wrap@^1.2.5: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -workerd@1.20240821.1: - version "1.20240821.1" - resolved "https://registry.yarnpkg.com/workerd/-/workerd-1.20240821.1.tgz#783115daabb3f5e51e3833117ac83548f6fd79f9" - integrity sha512-y4phjCnEG96u8ZkgkkHB+gSw0i6uMNo23rBmixylWpjxDklB+LWD8dztasvsu7xGaZbLoTxQESdEw956F7VJDA== +workerd@1.20240925.0: + version "1.20240925.0" + resolved "https://registry.yarnpkg.com/workerd/-/workerd-1.20240925.0.tgz#0a2602eabfa7e1d01d89ff2b600ed359be9b515d" + integrity sha512-/Jj6+yLwfieZGEt3Kx4+5MoufuC3g/8iFaIh4MPBNGJOGYmdSKXvgCqz09m2+tVCYnysRfbq2zcbVxJRBfOCqQ== optionalDependencies: - "@cloudflare/workerd-darwin-64" "1.20240821.1" - "@cloudflare/workerd-darwin-arm64" "1.20240821.1" - "@cloudflare/workerd-linux-64" "1.20240821.1" - "@cloudflare/workerd-linux-arm64" "1.20240821.1" - "@cloudflare/workerd-windows-64" "1.20240821.1" + "@cloudflare/workerd-darwin-64" "1.20240925.0" + "@cloudflare/workerd-darwin-arm64" "1.20240925.0" + "@cloudflare/workerd-linux-64" "1.20240925.0" + "@cloudflare/workerd-linux-arm64" "1.20240925.0" + "@cloudflare/workerd-windows-64" "1.20240925.0" -wrangler@3.72.2: - version "3.72.2" - resolved "https://registry.yarnpkg.com/wrangler/-/wrangler-3.72.2.tgz#606224878a25f383422010b3bfac1494aa78c798" - integrity sha512-7nxkJ4md+KtESNJ/0DwTM7bHZP+uNRpJT5gMDT9WllP9UVzYdtXCTF+p4CHtxIReUpe6pOi7tb05hK9/Q6WaiA== +wrangler@^3.78.12: + version "3.78.12" + resolved "https://registry.yarnpkg.com/wrangler/-/wrangler-3.78.12.tgz#c3d7b605856b904ab7cce54afc223286b8454935" + integrity sha512-a/xk/N04IvOGk9J+BLkiFg42GDyPS+0BiJimbrHsbX+CDr8Iqq3HNMEyQld+6zbmq01u/gmc8S7GKVR9vDx4+g== dependencies: "@cloudflare/kv-asset-handler" "0.3.4" - "@cloudflare/workers-shared" "0.3.0" + "@cloudflare/workers-shared" "0.5.4" "@esbuild-plugins/node-globals-polyfill" "^0.2.3" "@esbuild-plugins/node-modules-polyfill" "^0.2.2" blake3-wasm "^2.1.5" chokidar "^3.5.3" - date-fns "^3.6.0" esbuild "0.17.19" - miniflare "3.20240821.0" + miniflare "3.20240925.0" nanoid "^3.3.3" - path-to-regexp "^6.2.0" + path-to-regexp "^6.3.0" resolve "^1.22.8" resolve.exports "^2.0.2" selfsigned "^2.0.1" source-map "^0.6.1" - unenv "npm:unenv-nightly@1.10.0-1717606461.a117952" - workerd "1.20240821.1" + unenv "npm:unenv-nightly@2.0.0-20240919-125358-9a64854" + workerd "1.20240925.0" xxhash-wasm "^1.0.1" optionalDependencies: fsevents "~2.3.2" +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -8767,6 +9029,15 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrap-ansi@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.0.tgz#1a3dc8b70d85eeb8398ddfb1e4a02cd186e58b3e" @@ -8798,6 +9069,14 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" +write-file-atomic@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-5.0.1.tgz#68df4717c55c6fa4281a7860b4c2ba0a6d2b11e7" + integrity sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^4.0.1" + ws@^8.14.2, ws@^8.17.1: version "8.18.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" @@ -8838,6 +9117,11 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yallist@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533" + integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== + yaml@^2.5.0, yaml@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.0.tgz#c6165a721cf8000e91c36490a41d7be25176cf5d" From 3db28f61ef596767ca61026ed25a5419539ecfb3 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:14:21 +0100 Subject: [PATCH 74/76] chore: knip ignore smee and supabase --- .github/knip.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/knip.ts b/.github/knip.ts index 17857ad..928b235 100644 --- a/.github/knip.ts +++ b/.github/knip.ts @@ -6,7 +6,7 @@ const config: KnipConfig = { ignore: ["src/types/config.ts", "**/__mocks__/**", "**/__fixtures__/**"], ignoreExportsUsedInFile: true, // eslint can also be safely ignored as per the docs: https://knip.dev/guides/handling-issues#eslint--jest - ignoreDependencies: ["eslint-config-prettier", "eslint-plugin-prettier", "@mswjs/data"], + ignoreDependencies: ["eslint-config-prettier", "eslint-plugin-prettier", "@mswjs/data", "smee-client", "supabase"], eslint: true, }; From 188cd1d1c750de45ecaf8c096814b1dd0454a75d Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 2 Oct 2024 16:47:25 +0100 Subject: [PATCH 75/76] chore: log wf payload, update readme --- .github/workflows/compute.yml | 3 +++ README.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compute.yml b/.github/workflows/compute.yml index fabc2d9..ad677ce 100644 --- a/.github/workflows/compute.yml +++ b/.github/workflows/compute.yml @@ -35,6 +35,9 @@ jobs: - name: install dependencies run: yarn + - run: ${{ toJSON(inputs) }} + shell: cat {0} + - name: execute directive run: npx tsx ./src/workflow-entry.ts id: Kernel-Telegram diff --git a/README.md b/README.md index 83c68ab..8b67907 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ plugins: - To start the Supabase database locally, run the following command: ```bash -yarn supabase db start +yarn supabase start ``` - To reset the Supabase database, run the following command: From e52735d36b0386801d193d40bac5c391e81b689f Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Wed, 2 Oct 2024 16:48:03 +0100 Subject: [PATCH 76/76] chore: remove packageManager --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 9f3c75b..922b9ee 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,5 @@ "extends": [ "@commitlint/config-conventional" ] - }, - "packageManager": "yarn@1.22.22" -} + } +} \ No newline at end of file