add ci for tg bot
Deploy app frontend / app frontend (push) Failing after 54s
Deploy service couchdb / service couchdb (push) Successful in 38s
Deploy db-migrations / db-migrations (push) Failing after 50s
Deploy service message-delivery-method-web-push / service message-delivery-method-web-push (push) Failing after 1m27s
Deploy service tg-bot / service tg-bot (push) Failing after 44s

This commit is contained in:
2024-12-12 17:45:01 +02:00
parent e07d748e87
commit 7df04c0103
24 changed files with 309 additions and 365 deletions
@@ -0,0 +1,58 @@
name: Deploy service tg-bot
run-name: ${{ github.actor }} deployed to build branch
on:
push:
branches:
- main
paths:
- 'services/tg-bot/**'
- 'packages/couchdb-changes-stream/**'
- '.gitea/workflows/deploy-service-tg-bot.yaml'
- 'docker-compose.yml'
- 'package.json'
- 'pnpm-lock.yaml'
jobs:
service tg-bot:
runs-on: ubuntu-latest
env:
COUCHDB_USER: ${{ secrets.COUCHDB_USER }}
COUCHDB_PASSWORD: ${{ secrets.COUCHDB_PASSWORD }}
VAPID_SUBJECT: ${{ vars.VAPID_SUBJECT }}
GCM_API_KEY: ${{ vars.GCM_API_KEY }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: install dependencies
run: |
corepack enable pnpm && corepack use pnpm@8.15.9
pnpm install --filter ./services/tg-bot
- name: build service
run: |
pnpm run --filter ./services/tg-bot build
pnpm --filter ./services/tg-bot deploy --prod build/service-tg-bot
- name: build docker image
run: MESSAGE_DELIVERY_METHOD_WEB_PUSH_TAG=commit-${{env.GITHUB_SHA}} docker compose -p hereconnect build tg-bot
- name: start container
run: MESSAGE_DELIVERY_METHOD_WEB_PUSH_TAG=commit-${{env.GITHUB_SHA}} docker compose -p hereconnect up -d --pull never --wait tg-bot
- name: rename to latest
run: docker tag hereconnect/service-tg-bot:commit-${{env.GITHUB_SHA}} hereconnect/service-tg-bot:latest
- name: rollback on failure
if: failure()
env:
COUCHDB_TAG: latest
run: docker compose -p hereconnect up -d --pull never --wait tg-bot
- name: cleanup docker image
if: always()
run: docker rmi hereconnect/service-tg-bot:commit-${{env.GITHUB_SHA}}
+22
View File
@@ -60,3 +60,25 @@ services:
options: options:
max-size: "100m" max-size: "100m"
max-file: "10" max-file: "10"
tg-bot:
image: hereconnect/service-tg-bot:${MESSAGE_DELIVERY_METHOD_WEB_PUSH_TAG:-latest}
build:
context: build/service-tg-bot
dockerfile: ../../services/tg-bot/Dockerfile
environment:
- API_URL=http://${COUCHDB_USER}:${COUCHDB_PASSWORD}@couchdb:5984
- BOT_TOKEN=${BOT_TOKEN:-}
- READ_BASE_URL=${READ_BASE_URL:-}
depends_on:
couchdb:
condition: service_healthy
restart: true
db-migrations:
condition: service_completed_successfully
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "10"
+4 -3
View File
@@ -15,10 +15,11 @@
] ]
}, },
"scripts": { "scripts": {
"start": "npm run start --workspace=apps/frontend", "start": "pnpm run --filter ./apps/frontend dev",
"build": "npm run build:deploy:services:message-delivery-method-web-push && npm run build:deploy:services:db-migrations", "build": "npm run build:deploy:services:db-migrations && npm run build:deploy:services:message-delivery-method-web-push && npm run build:deploy:services:tg-bot",
"build:deploy:services:message-delivery-method-web-push": "npm -w ./services/message-delivery-method-web-push run build && pnpm --filter ./services/message-delivery-method-web-push deploy --prod build/service-message-delivery-method-web-push",
"build:deploy:services:db-migrations": "pnpm --filter ./services/db-migrations deploy --prod build/service-db-migrations", "build:deploy:services:db-migrations": "pnpm --filter ./services/db-migrations deploy --prod build/service-db-migrations",
"build:deploy:services:message-delivery-method-web-push": "npm -w ./services/message-delivery-method-web-push run build && pnpm --filter ./services/message-delivery-method-web-push deploy --prod build/service-message-delivery-method-web-push",
"build:deploy:services:tg-bot": "pnpm --filter ./services/tg-bot deploy --prod build/service-tg-bot",
"test": "npm run test --workspaces", "test": "npm run test --workspaces",
"lint": "npm run lint --workspaces" "lint": "npm run lint --workspaces"
}, },
+2 -1
View File
@@ -1,8 +1,9 @@
{ {
"name": "@hereconnect/constants", "name": "@hereconnect/constants",
"version": "1.0.0", "version": "1.0.0",
"type": "module",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.ts", "types": "dist/index.d.ts",
"exports": { "exports": {
".": { ".": {
"import": "./dist/index.js", "import": "./dist/index.js",
@@ -1,18 +1,22 @@
{ {
"name": "@hereconnect/lib-service-health-checkserver", "name": "@hereconnect/lib-service-health-checkserver",
"version": "1.0.0", "version": "1.0.0",
"main": "src/health-server.ts", "type": "module",
"main": "dist/health-server.js",
"types": "dist/health-server.d.ts",
"exports": { "exports": {
".": { ".": {
"import": "./src/health-server.ts", "import": "./dist/health-server.js",
"default": "./src/health-server.ts" "types": "./dist/health-server.d.ts",
"default": "./dist/health-server.js"
} }
}, },
"files": ["src/**/*"], "files": ["dist/**/*"],
"private": true, "private": true,
"scripts": { "scripts": {
"lint": "tsc --noEmit src/health-server.ts", "lint": "tsc --noEmit src/health-server.ts",
"build": "pnpm run lint" "build": "tsc",
"prepare": "npm run build"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20.17.6", "@types/node": "^20.17.6",
@@ -1,10 +1,15 @@
{ {
"compilerOptions": { "compilerOptions": {
"declaration": true, "declaration": true,
"emitDeclarationOnly": true, "target": "ESNext",
"module": "ESNext",
"moduleResolution": "node",
"outDir": "./dist", "outDir": "./dist",
"strict": true, "strict": true,
"types": ["node"] "types": ["node"],
"esModuleInterop": true,
"skipLibCheck": true
}, },
"include": ["index.ts"] "files": ["src/health-server.ts"],
"exclude": ["node_modules", "dist"]
} }
+10 -265
View File
@@ -331,6 +331,9 @@ importers:
services/tg-bot: services/tg-bot:
dependencies: dependencies:
'@grammyjs/conversations':
specifier: ^1.2.0
version: 1.2.0(grammy@1.33.0)
'@hereconnect/constants': '@hereconnect/constants':
specifier: workspace:^ specifier: workspace:^
version: link:../../packages/constants version: link:../../packages/constants
@@ -383,9 +386,6 @@ importers:
specifier: ^3.3.2 specifier: ^3.3.2
version: 3.3.2 version: 3.3.2
devDependencies: devDependencies:
'@grammyjs/conversations':
specifier: ^1.2.0
version: 1.2.0(grammy@1.33.0)
'@grammyjs/types': '@grammyjs/types':
specifier: ^3.17.0 specifier: ^3.17.0
version: 3.17.0 version: 3.17.0
@@ -416,12 +416,6 @@ importers:
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: ^8.18.0 specifier: ^8.18.0
version: 8.18.0(eslint@9.16.0)(typescript@5.7.2) version: 8.18.0(eslint@9.16.0)(typescript@5.7.2)
esbuild:
specifier: ^0.24.0
version: 0.24.0
esbuild-copy-static-files:
specifier: ^0.1.0
version: 0.1.0
eslint: eslint:
specifier: ^9.16.0 specifier: ^9.16.0
version: 9.16.0 version: 9.16.0
@@ -748,14 +742,14 @@ packages:
/@deno/shim-deno-test@0.4.0: /@deno/shim-deno-test@0.4.0:
resolution: {integrity: sha512-oYWcD7CpERZy/TXMTM9Tgh1HD/POHlbY9WpzmAk+5H8DohcxG415Qws8yLGlim3EaKBT2v3lJv01x4G0BosnaQ==} resolution: {integrity: sha512-oYWcD7CpERZy/TXMTM9Tgh1HD/POHlbY9WpzmAk+5H8DohcxG415Qws8yLGlim3EaKBT2v3lJv01x4G0BosnaQ==}
dev: true dev: false
/@deno/shim-deno@0.16.1: /@deno/shim-deno@0.16.1:
resolution: {integrity: sha512-s9v0kzF5bm/o9TgdwvsraHx6QNllYrXXmKzgOG2lh4LFXnVMr2gpjK/c/ve6EflQn1MqImcWmVD8HAv5ahuuZQ==} resolution: {integrity: sha512-s9v0kzF5bm/o9TgdwvsraHx6QNllYrXXmKzgOG2lh4LFXnVMr2gpjK/c/ve6EflQn1MqImcWmVD8HAv5ahuuZQ==}
dependencies: dependencies:
'@deno/shim-deno-test': 0.4.0 '@deno/shim-deno-test': 0.4.0
which: 2.0.2 which: 2.0.2
dev: true dev: false
/@emnapi/runtime@1.3.1: /@emnapi/runtime@1.3.1:
resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==}
@@ -783,15 +777,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/aix-ppc64@0.24.0:
resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-arm64@0.21.5: /@esbuild/android-arm64@0.21.5:
resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -810,15 +795,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/android-arm64@0.24.0:
resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-arm@0.21.5: /@esbuild/android-arm@0.21.5:
resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -837,15 +813,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/android-arm@0.24.0:
resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-x64@0.21.5: /@esbuild/android-x64@0.21.5:
resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -864,15 +831,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/android-x64@0.24.0:
resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/darwin-arm64@0.21.5: /@esbuild/darwin-arm64@0.21.5:
resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -891,15 +849,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/darwin-arm64@0.24.0:
resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@esbuild/darwin-x64@0.21.5: /@esbuild/darwin-x64@0.21.5:
resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -918,15 +867,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/darwin-x64@0.24.0:
resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@esbuild/freebsd-arm64@0.21.5: /@esbuild/freebsd-arm64@0.21.5:
resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -945,15 +885,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/freebsd-arm64@0.24.0:
resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/freebsd-x64@0.21.5: /@esbuild/freebsd-x64@0.21.5:
resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -972,15 +903,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/freebsd-x64@0.24.0:
resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-arm64@0.21.5: /@esbuild/linux-arm64@0.21.5:
resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -999,15 +921,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/linux-arm64@0.24.0:
resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-arm@0.21.5: /@esbuild/linux-arm@0.21.5:
resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1026,15 +939,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/linux-arm@0.24.0:
resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-ia32@0.21.5: /@esbuild/linux-ia32@0.21.5:
resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1053,15 +957,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/linux-ia32@0.24.0:
resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-loong64@0.21.5: /@esbuild/linux-loong64@0.21.5:
resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1080,15 +975,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/linux-loong64@0.24.0:
resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-mips64el@0.21.5: /@esbuild/linux-mips64el@0.21.5:
resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1107,15 +993,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/linux-mips64el@0.24.0:
resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-ppc64@0.21.5: /@esbuild/linux-ppc64@0.21.5:
resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1134,15 +1011,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/linux-ppc64@0.24.0:
resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-riscv64@0.21.5: /@esbuild/linux-riscv64@0.21.5:
resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1161,15 +1029,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/linux-riscv64@0.24.0:
resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-s390x@0.21.5: /@esbuild/linux-s390x@0.21.5:
resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1188,15 +1047,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/linux-s390x@0.24.0:
resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-x64@0.21.5: /@esbuild/linux-x64@0.21.5:
resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1215,15 +1065,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/linux-x64@0.24.0:
resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/netbsd-x64@0.21.5: /@esbuild/netbsd-x64@0.21.5:
resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1242,15 +1083,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/netbsd-x64@0.24.0:
resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/openbsd-arm64@0.23.1: /@esbuild/openbsd-arm64@0.23.1:
resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
@@ -1260,15 +1092,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/openbsd-arm64@0.24.0:
resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/openbsd-x64@0.21.5: /@esbuild/openbsd-x64@0.21.5:
resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1287,15 +1110,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/openbsd-x64@0.24.0:
resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/sunos-x64@0.21.5: /@esbuild/sunos-x64@0.21.5:
resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1314,15 +1128,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/sunos-x64@0.24.0:
resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-arm64@0.21.5: /@esbuild/win32-arm64@0.21.5:
resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1341,15 +1146,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/win32-arm64@0.24.0:
resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-ia32@0.21.5: /@esbuild/win32-ia32@0.21.5:
resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1368,15 +1164,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/win32-ia32@0.24.0:
resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-x64@0.21.5: /@esbuild/win32-x64@0.21.5:
resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -1395,15 +1182,6 @@ packages:
dev: true dev: true
optional: true optional: true
/@esbuild/win32-x64@0.24.0:
resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@eslint-community/eslint-utils@4.4.1(eslint@9.15.0): /@eslint-community/eslint-utils@4.4.1(eslint@9.15.0):
resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -1504,7 +1282,7 @@ packages:
o-son: 1.0.4 o-son: 1.0.4
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: false
/@grammyjs/types@3.17.0: /@grammyjs/types@3.17.0:
resolution: {integrity: sha512-e8AR3xQwRAFX248E7Qw/7mIu1OzvoXloJzOBJVtuPKzzL7tGkn5trZAdZUBgGViVQg5ZwVS/x9N2nRrcyH/DfA==} resolution: {integrity: sha512-e8AR3xQwRAFX248E7Qw/7mIu1OzvoXloJzOBJVtuPKzzL7tGkn5trZAdZUBgGViVQg5ZwVS/x9N2nRrcyH/DfA==}
@@ -3017,6 +2795,7 @@ packages:
engines: {node: '>=6.5'} engines: {node: '>=6.5'}
dependencies: dependencies:
event-target-shim: 5.0.1 event-target-shim: 5.0.1
dev: false
/acorn-jsx@5.3.2(acorn@8.14.0): /acorn-jsx@5.3.2(acorn@8.14.0):
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
@@ -3614,10 +3393,6 @@ packages:
resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==}
dev: true dev: true
/esbuild-copy-static-files@0.1.0:
resolution: {integrity: sha512-KlpmYqANA1t2nZavEdItfcOjJC6wbHA21v35HJWN32DddGTWKNNGDKljUzbCPojmpD+wAw8/DXr5abJ4jFCE0w==}
dev: true
/esbuild@0.21.5: /esbuild@0.21.5:
resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -3681,38 +3456,6 @@ packages:
'@esbuild/win32-x64': 0.23.1 '@esbuild/win32-x64': 0.23.1
dev: true dev: true
/esbuild@0.24.0:
resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==}
engines: {node: '>=18'}
hasBin: true
requiresBuild: true
optionalDependencies:
'@esbuild/aix-ppc64': 0.24.0
'@esbuild/android-arm': 0.24.0
'@esbuild/android-arm64': 0.24.0
'@esbuild/android-x64': 0.24.0
'@esbuild/darwin-arm64': 0.24.0
'@esbuild/darwin-x64': 0.24.0
'@esbuild/freebsd-arm64': 0.24.0
'@esbuild/freebsd-x64': 0.24.0
'@esbuild/linux-arm': 0.24.0
'@esbuild/linux-arm64': 0.24.0
'@esbuild/linux-ia32': 0.24.0
'@esbuild/linux-loong64': 0.24.0
'@esbuild/linux-mips64el': 0.24.0
'@esbuild/linux-ppc64': 0.24.0
'@esbuild/linux-riscv64': 0.24.0
'@esbuild/linux-s390x': 0.24.0
'@esbuild/linux-x64': 0.24.0
'@esbuild/netbsd-x64': 0.24.0
'@esbuild/openbsd-arm64': 0.24.0
'@esbuild/openbsd-x64': 0.24.0
'@esbuild/sunos-x64': 0.24.0
'@esbuild/win32-arm64': 0.24.0
'@esbuild/win32-ia32': 0.24.0
'@esbuild/win32-x64': 0.24.0
dev: true
/escalade@3.2.0: /escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -3998,6 +3741,7 @@ packages:
/event-target-shim@5.0.1: /event-target-shim@5.0.1:
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
dev: false
/events@3.3.0: /events@3.3.0:
resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
@@ -4329,6 +4073,7 @@ packages:
transitivePeerDependencies: transitivePeerDependencies:
- encoding - encoding
- supports-color - supports-color
dev: false
/graphemer@1.4.0: /graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
@@ -5101,7 +4846,7 @@ packages:
resolution: {integrity: sha512-tdGKxZgiTexSv97/igC2m8Y6FljgwvwHW/Zy3ql3Jx6MPKrPKaBDLhV7rz8uuLjcDPw6Pxa2PVsnWwen59MmnQ==} resolution: {integrity: sha512-tdGKxZgiTexSv97/igC2m8Y6FljgwvwHW/Zy3ql3Jx6MPKrPKaBDLhV7rz8uuLjcDPw6Pxa2PVsnWwen59MmnQ==}
dependencies: dependencies:
'@deno/shim-deno': 0.16.1 '@deno/shim-deno': 0.16.1
dev: true dev: false
/object-assign@4.1.1: /object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+2 -2
View File
@@ -1,8 +1,8 @@
FROM oven/bun:1.1.38-alpine FROM node:22-alpine
COPY . ./ COPY . ./
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=1 \ HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=1 \
CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:8000/health || exit 1 CMD wget --no-verbose --tries=1 --spider http://127.0.0.1:8000/health || exit 1
CMD ["bun", "dist/server.js"] CMD ["npm", "start"]
-25
View File
@@ -1,25 +0,0 @@
import esbuild from "esbuild";
import copyStaticFiles from "esbuild-copy-static-files";
esbuild
.build({
entryPoints: ["./src/bot/index.ts"], // Точка входа
outdir: "./dist", // Папка выхода
format: "esm", // Формат (ESM)
bundle: true, // Сборка в один файл
sourcemap: true, // Карты кода
platform: "node", // Платформа (Node.js)
target: ["node20"], // Целевая версия Node.js
external: ["canvas"], // Исключить модуль canvas
plugins: [
copyStaticFiles({
src: "./src/assets", // Папка с вашими статическими файлами
dest: "./dist/assets", // Куда копировать
}),
],
})
.then(() => console.log("Build complete!"))
.catch((err) => {
console.error("Build failed:", err);
process.exit(1);
});
+1 -3
View File
@@ -38,6 +38,7 @@
"start": "node --import=extensionless/register dist/bot/index.js" "start": "node --import=extensionless/register dist/bot/index.js"
}, },
"dependencies": { "dependencies": {
"@grammyjs/conversations": "^1.2.0",
"@hereconnect/constants": "workspace:^", "@hereconnect/constants": "workspace:^",
"@hereconnect/couchdb-changes-stream": "workspace:^", "@hereconnect/couchdb-changes-stream": "workspace:^",
"@hereconnect/lib-service-health-checkserver": "workspace:^", "@hereconnect/lib-service-health-checkserver": "workspace:^",
@@ -57,7 +58,6 @@
"svgo": "^3.3.2" "svgo": "^3.3.2"
}, },
"devDependencies": { "devDependencies": {
"@grammyjs/conversations": "^1.2.0",
"@grammyjs/types": "^3.17.0", "@grammyjs/types": "^3.17.0",
"@hereconnect/types": "workspace:^", "@hereconnect/types": "workspace:^",
"@types/bun": "^1.1.14", "@types/bun": "^1.1.14",
@@ -68,8 +68,6 @@
"@types/pouchdb-upsert": "^2.2.9", "@types/pouchdb-upsert": "^2.2.9",
"@typescript-eslint/eslint-plugin": "^8.18.0", "@typescript-eslint/eslint-plugin": "^8.18.0",
"@typescript-eslint/parser": "^8.18.0", "@typescript-eslint/parser": "^8.18.0",
"esbuild": "^0.24.0",
"esbuild-copy-static-files": "^0.1.0",
"eslint": "^9.16.0", "eslint": "^9.16.0",
"tsx": "^4.19.2", "tsx": "^4.19.2",
"typescript": "^5.7.2" "typescript": "^5.7.2"
+1 -1
View File
@@ -50,7 +50,7 @@ interface CreateQRCodeOptions {
userUuid: string; userUuid: string;
name: string; name: string;
placement: QRCodeDocument["placement"]; placement: QRCodeDocument["placement"];
actions: string[]; actions: QRCodeDocument["actions"];
messageDeliveryMethod?: QRCodeDocument["messageDeliveryMethod"]; messageDeliveryMethod?: QRCodeDocument["messageDeliveryMethod"];
browser_uuid?: string; browser_uuid?: string;
telegram_id?: string; telegram_id?: string;
+3 -3
View File
@@ -1,6 +1,6 @@
import { MyContext } from "@/types/myContext"; import { MyContext } from "../../types/myContext";
import { getQRCodesByUser } from "@/api/qrCodes"; import { getQRCodesByUser } from "../../api/qrCodes";
import { buildManageKeyboard } from "@/bot/utils/keyboards"; import { buildManageKeyboard } from "../../bot/utils/keyboards";
/** /**
* Обработка команды /manage с выводом подменю * Обработка команды /manage с выводом подменю
@@ -1,10 +1,8 @@
import { Bot } from "grammy"; import { Bot } from "grammy";
import { MyContext } from "../../types/myContext"; import { MyContext } from "../../types/myContext"; // Ваш кастомный контекст
import { bot } from "old_bot"; // Ваш кастомный контекст
/** /**
* Устанавливает команды для бота. * Устанавливает команды для бота.
* @param bot - Экземпляр бота.
*/ */
export async function setupCommands(bot: Bot<MyContext>): Promise<void> { export async function setupCommands(bot: Bot<MyContext>): Promise<void> {
// Настройка команд для английского языка (по умолчанию) // Настройка команд для английского языка (по умолчанию)
@@ -32,6 +30,4 @@ export async function setupCommands(bot: Bot<MyContext>): Promise<void> {
], ],
{ language_code: "ru" }, { language_code: "ru" },
); );
console.log("Команды успешно установлены.");
} }
@@ -9,6 +9,7 @@ import {
} from "../utils/keyboards"; } from "../utils/keyboards";
import { createQRCode } from "../../api/qrCodes"; import { createQRCode } from "../../api/qrCodes";
import { generateQRCodeImage } from "../../services/qrGenerator"; import { generateQRCodeImage } from "../../services/qrGenerator";
import { selectMultipleActions } from "./selectMultipleActions";
// Тип разговора (конверсии) // Тип разговора (конверсии)
type MyConversation = Conversation<MyContext>; type MyConversation = Conversation<MyContext>;
@@ -67,34 +68,25 @@ export async function newQRCodeConversation(
return; return;
} }
// 3. Выбор действий, доступных при сканировании // 3. Выбор действий
await ctx.reply( const availableActions = [
"Выберите одно или несколько действий, которые будут доступны при сканировании этого QR-кода:", { action: "sendMessage", label: "📩 Отправить сообщение" },
{ { action: "viewContactInfo", label: "📞 Посмотреть контактные данные" },
reply_markup: { ] as const;
inline_keyboard: buildActionsKeyboard([
{ action: "sendMessage", label: "Отправить сообщение" }, const chosenActions = await selectMultipleActions(
{ action: "viewContactInfo", label: "Посмотреть контактные данные" }, conversation,
]), ctx,
}, availableActions,
},
); );
const actionsMsg = await conversation.waitFor("callback_query:data"); if (chosenActions.length === 0) {
const chosenAction = actionsMsg.update.callback_query?.data; await ctx.reply("Вы не выбрали ни одного действия. Попробуйте снова /new.");
if (!chosenAction) {
await ctx.reply("Вы не выбрали действие. Попробуйте снова /new.");
return; return;
} }
// Подтверждаем выбор
await actionsMsg.answerCallbackQuery({ text: "Действие выбрано!" });
// Пока для MVP можно выбрать только одно действие, в будущем можно расширить
const chosenActions = [chosenAction];
// 4. Создание документа в БД // 4. Создание документа в БД
const { url, uri } = await createQRCode({ const { url } = await createQRCode({
userUuid, userUuid,
name, name,
placement: typedPlacement, placement: typedPlacement,
@@ -0,0 +1,134 @@
import { MyContext } from "../../types/myContext";
import { Conversation } from "@grammyjs/conversations";
// Тип разговора
type MyConversation = Conversation<MyContext>;
interface Action {
readonly action: string;
readonly label: string;
}
/**
* Обработчик выбора нескольких действий
* @param conversation - Инстанс Conversation
* @param ctx - Контекст
* @param availableActions - Список доступных действий
* @returns Список выбранных действий
*/
export async function selectMultipleActions<T extends readonly Action[]>(
conversation: MyConversation,
ctx: MyContext,
availableActions: T,
): Promise<T[number]["action"][]> {
try {
if (!Array.isArray(availableActions) || availableActions.length === 0) {
throw new Error("Список доступных действий пуст или не определён.");
}
const selectedActions = new Set<T[number]["action"]>();
const updateKeyboard = () => {
return availableActions.map(({ action, label }) => [
{
text: `${selectedActions.has(action) ? "✔️ " : ""}${label}`,
callback_data: `action:${action}`,
},
]);
};
// Отправляем начальное сообщение
const replyMessage = await ctx.reply(
"Выберите одно или несколько действий, которые будут доступны при сканировании этого QR-кода. Нажмите 'Готово', когда закончите выбор:",
{
reply_markup: {
inline_keyboard: [
...updateKeyboard(),
[{ text: "Готово", callback_data: "action:done" }],
],
},
},
);
while (true) {
let actionChoice;
try {
actionChoice = await conversation.waitFor("callback_query:data");
} catch (err) {
console.error("Ошибка ожидания callback_query:", err);
await ctx.reply(
"Произошла ошибка при ожидании вашего выбора. Попробуйте снова.",
);
continue;
}
const choice = actionChoice.update.callback_query?.data;
if (!choice || !choice.startsWith("action:")) {
// Игнорируем callback_data, которые не относятся к текущему этапу
console.warn(`Игнорируем callback_data: ${choice}`);
await actionChoice.answerCallbackQuery({
text: "Неизвестное действие.",
});
continue;
}
const action = choice.replace("action:", "");
if (action === "done") {
await actionChoice.answerCallbackQuery({ text: "Выбор завершён!" });
break;
}
// Проверка: является ли выбор валидным
const validChoice = availableActions.find((a) => a.action === action);
if (!validChoice) {
console.error(`Недопустимое действие: ${action}`);
await actionChoice.answerCallbackQuery({
text: "Неверный выбор. Попробуйте снова.",
});
continue;
}
// Добавляем или убираем действие
if (selectedActions.has(action as T[number]["action"])) {
selectedActions.delete(action as T[number]["action"]);
} else {
selectedActions.add(action as T[number]["action"]);
}
await actionChoice.answerCallbackQuery({
text: `Вы ${
selectedActions.has(action as T[number]["action"])
? "добавили"
: "убрали"
} действие.`,
});
// Перерисовываем клавиатуру
try {
await actionChoice.editMessageReplyMarkup({
reply_markup: {
inline_keyboard: [
...updateKeyboard(),
[{ text: "Готово", callback_data: "action:done" }],
],
},
});
} catch (err) {
console.error("Ошибка обновления клавиатуры:", err);
await ctx.reply(
"Произошла ошибка при обновлении выбора. Попробуйте снова.",
);
}
}
return Array.from(selectedActions);
} catch (err) {
console.error("Общая ошибка в selectMultipleActions:", err);
await ctx.reply(
"Произошла непредвиденная ошибка. Попробуйте снова или обратитесь в поддержку.",
);
return [];
}
}
+18 -5
View File
@@ -1,10 +1,11 @@
import { Bot, session } from "grammy"; import { Bot, session } from "grammy";
import { conversations, createConversation } from "@grammyjs/conversations"; import { conversations, createConversation } from "@grammyjs/conversations";
import { MyContext } from "@/types/myContext"; import { startHealthServer } from "@hereconnect/lib-service-health-checkserver";
import { env } from "@/config/env"; import { MyContext } from "../types/myContext";
import { env } from "../config/env";
import { CouchDBStorageAdapter } from "./storageAdapters/CouchDBStorageAdapter"; import { CouchDBStorageAdapter } from "./storageAdapters/CouchDBStorageAdapter";
import { loadUserMiddleware } from "./middleware/loadUser"; import { loadUserMiddleware } from "./middleware/loadUser";
import { tgBotSessionsDb } from "@/dbs"; import { tgBotSessionsDb } from "../dbs";
import { setupCommands } from "./commands/setupCommands"; import { setupCommands } from "./commands/setupCommands";
import { startCommand } from "./commands/start"; import { startCommand } from "./commands/start";
import { helpCommand } from "./commands/help"; import { helpCommand } from "./commands/help";
@@ -13,12 +14,21 @@ import { manageCommand } from "./commands/manage";
import { callbackQueryHandler } from "./callbackHandlers"; import { callbackQueryHandler } from "./callbackHandlers";
import { newQRCodeConversation } from "./conversations/newQRCodeConversation"; import { newQRCodeConversation } from "./conversations/newQRCodeConversation";
const abortController = new AbortController();
const storage = new CouchDBStorageAdapter(tgBotSessionsDb, { const storage = new CouchDBStorageAdapter(tgBotSessionsDb, {
softDelete: true, softDelete: true,
type: "tg_bot_session",
}); });
// Инициализируем бота с нужным типом контекста // Инициализируем бота с нужным типом контекста
const bot = new Bot<MyContext>(env.TELEGRAM_BOT_TOKEN); const bot = new Bot<MyContext>(env.TELEGRAM_BOT_TOKEN, {
client: {
baseFetchConfig: {
signal: abortController.signal,
},
},
});
// Подключаем сессии. По необходимости определите initial state для сессии // Подключаем сессии. По необходимости определите initial state для сессии
bot.use(session({ storage, initial: () => ({}) })); bot.use(session({ storage, initial: () => ({}) }));
@@ -44,7 +54,10 @@ bot.on("callback_query:data", callbackQueryHandler);
await setupCommands(bot); await setupCommands(bot);
// Запуск бота // Запуск бота
bot.start(); await bot.start();
await startHealthServer(abortController);
console.log("Бот запущен!"); console.log("Бот запущен!");
})(); })();
+5
View File
@@ -6,7 +6,12 @@ if (!process.env.READ_BASE_URL) {
throw new Error("Необходимо указать READ_BASE_URL в переменных окружения."); throw new Error("Необходимо указать READ_BASE_URL в переменных окружения.");
} }
if (!process.env.API_URL) {
throw new Error("Environment variable API_URL is not set");
}
export const env = { export const env = {
TELEGRAM_BOT_TOKEN: process.env.BOT_TOKEN, TELEGRAM_BOT_TOKEN: process.env.BOT_TOKEN,
READ_BASE_URL: process.env.READ_BASE_URL, READ_BASE_URL: process.env.READ_BASE_URL,
API_URL: process.env.API_URL,
} as const; } as const;
+14 -16
View File
@@ -12,45 +12,46 @@ import type {
} from "@hereconnect/types"; } from "@hereconnect/types";
import type { TelegramWebhookDesignDocument } from "@hereconnect/tg-bot-webhook-ddoc"; import type { TelegramWebhookDesignDocument } from "@hereconnect/tg-bot-webhook-ddoc";
import { CouchDBSessionDocument } from "@/bot/storageAdapters/CouchDBStorageAdapter"; import { CouchDBSessionDocument } from "./bot/storageAdapters/CouchDBStorageAdapter";
import type { SessionData } from "@/types/myContext"; import type { SessionData } from "./types/myContext";
import { env } from "./config/env";
// import type { TgUpdateDocument } from "./types"; // import type { TgUpdateDocument } from "./types";
if (!process.env.API_URL) { if (!env.API_URL) {
throw new Error("Environment variable API_URL is not set"); throw new Error("Environment variable API_URL is not set");
} }
export const TG_BOT_DB_NAME = "tg_bot"; export const TG_BOT_DB_NAME = "tg_bot";
export const TG_BOT_DB_URL = `${process.env.API_URL}/${TG_BOT_DB_NAME}`; export const TG_BOT_DB_URL = `${env.API_URL}/${TG_BOT_DB_NAME}`;
export const messagesDb = new PouchDB<MessageDocument>( export const messagesDb = new PouchDB<MessageDocument>(
`${process.env.API_URL}/messages`, `${env.API_URL}/messages`,
{ {
skip_setup: true, skip_setup: true,
}, },
); );
export const serverSettingsDb = new PouchDB<MessageDeliveryMethodWebPushVapid>( export const serverSettingsDb = new PouchDB<MessageDeliveryMethodWebPushVapid>(
`${process.env.API_URL}/server_settings`, `${env.API_URL}/server_settings`,
{ {
skip_setup: true, skip_setup: true,
}, },
); );
export const publicSettingsDb = new PouchDB<PublicSettingsDocument>( export const publicSettingsDb = new PouchDB<PublicSettingsDocument>(
`${process.env.API_URL}/public_settings`, `${env.API_URL}/public_settings`,
{ {
skip_setup: true, skip_setup: true,
}, },
); );
export const qrDb = new PouchDB<QRCodeDocument>(`${process.env.API_URL}/qr`, { export const qrDb = new PouchDB<QRCodeDocument>(`${env.API_URL}/qr`, {
skip_setup: true, skip_setup: true,
}); });
export const webPushSubscriptionsDb = new PouchDB< export const webPushSubscriptionsDb = new PouchDB<
WebPushSubscriptionDocument<PushSubscription> WebPushSubscriptionDocument<PushSubscription>
>(`${process.env.API_URL}/web_push_subscriptions`, { >(`${env.API_URL}/web_push_subscriptions`, {
skip_setup: true, skip_setup: true,
}); });
@@ -63,25 +64,22 @@ export const tgBotDesignDocumentsDb =
export const serviceSeqTrackerDb = tgBotDb as ServiceSeqTrackerDatabase; export const serviceSeqTrackerDb = tgBotDb as ServiceSeqTrackerDatabase;
export const tgBotSessionsDb = new PouchDB<CouchDBSessionDocument<SessionData>>( export const tgBotSessionsDb = new PouchDB<CouchDBSessionDocument<SessionData>>(
`${process.env.API_URL}/tg_bot_sessions`, `${env.API_URL}/tg_bot_sessions`,
{ {
skip_setup: true, skip_setup: true,
}, },
); );
export const userChatSettingsDb = new PouchDB<UserChatSettingsDocument>( export const userChatSettingsDb = new PouchDB<UserChatSettingsDocument>(
`${process.env.API_URL}/user_chat_settings`, `${env.API_URL}/user_chat_settings`,
{ {
skip_setup: true, skip_setup: true,
}, },
); );
export const usersDb = new PouchDB<UserDocument>( export const usersDb = new PouchDB<UserDocument>(`${env.API_URL}/_users`, {
`${process.env.API_URL}/_users`,
{
skip_setup: true, skip_setup: true,
}, });
);
export const checkDatabases = async () => { export const checkDatabases = async () => {
const entries = await Promise.all( const entries = await Promise.all(
+1 -1
View File
@@ -1,5 +1,5 @@
import QRCodeStyling from "qr-code-styling"; import QRCodeStyling from "qr-code-styling";
import { SvgProcessor } from "@/utils/images/svg/SvgProcessor"; import { SvgProcessor } from "../utils/images/svg/SvgProcessor";
import fs from "fs/promises"; import fs from "fs/promises";
import path from "path"; import path from "path";
import { fileURLToPath } from "url"; import { fileURLToPath } from "url";
+1 -4
View File
@@ -10,10 +10,7 @@
"skipLibCheck": true, // Пропуск проверки типов в библиотечных файлах "skipLibCheck": true, // Пропуск проверки типов в библиотечных файлах
"declaration": true, // Генерация `.d.ts` файлов "declaration": true, // Генерация `.d.ts` файлов
"sourceMap": true, // Генерация `.map` файлов "sourceMap": true, // Генерация `.map` файлов
"paths": {
"@/*": ["./src/*"] // Настройка алиасов (сопоставление путей)
}
}, },
"include": ["src"], // Указываем папку с исходниками "include": ["src"], // Указываем папку с исходниками
"exclude": ["node_modules", "dist"] // Исключаем ненужные директории "exclude": ["node_modules", "dist", "old"] // Исключаем ненужные директории
} }