Merge branch 'rainbowcat' of github.com:clansty/Q2TG into rainbowcat

This commit is contained in:
Nofated095 2024-01-24 09:41:28 +08:00
commit c1c3bbae01
27 changed files with 769 additions and 432 deletions

View File

@ -1,9 +1,9 @@
{
"name": "q2tg",
"scripts": {
"dev": "ts-node src/index.ts",
"dev": "tsx src/index.ts",
"build": "tsc",
"start": "prisma db push --accept-data-loss && node build/index.js",
"start": "prisma db push --accept-data-loss --skip-generate && node build/index.js",
"prisma": "prisma",
"import": "ts-node tools/import"
},
@ -17,10 +17,10 @@
"@types/date-and-time": "^3.0.3",
"@types/dockerode": "^3.3.23",
"@types/fluent-ffmpeg": "^2.1.24",
"@types/lodash": "^4.14.201",
"@types/node": "^20.10.8",
"@types/lodash": "^4.14.202",
"@types/node": "^20.11.0",
"@types/prompts": "^2.4.9",
"ts-node": "^10.9.2",
"tsx": "^4.7.0",
"typescript": "^5.3.3"
},
"dependencies": {
@ -29,7 +29,7 @@
"baidu-aip-sdk": "^4.16.15",
"big-integer": "^1.6.52",
"cli-progress": "^3.11.2",
"date-and-time": "^3.1.0",
"date-and-time": "^3.1.1",
"dockerode": "^4.0.2",
"dotenv": "^16.0.1",
"eviltransform": "^0.2.2",
@ -43,12 +43,13 @@
"prisma": "5.8.0",
"prompts": "^2.4.2",
"quote-api": "https://github.com/Clansty/quote-api/archive/37a0e48a434b94bb04c04c7d86d9f0d2295df869.tar.gz",
"sharp": "^0.33.1",
"sharp": "^0.33.2",
"silk-sdk": "^0.2.2",
"telegram": "^2.19.10",
"tmp-promise": "^3.0.3",
"undici": "^6.3.0",
"zincsearch-node": "^2.1.0"
"zincsearch-node": "^2.1.0",
"zod": "^3.22.4"
},
"engines": {
"node": "^14.13.1 || >=16.0.0"

View File

@ -21,8 +21,8 @@ dependencies:
specifier: ^3.11.2
version: 3.12.0
date-and-time:
specifier: ^3.1.0
version: 3.1.0
specifier: ^3.1.1
version: 3.1.1
dockerode:
specifier: ^4.0.2
version: 4.0.2
@ -63,8 +63,8 @@ dependencies:
specifier: https://github.com/Clansty/quote-api/archive/37a0e48a434b94bb04c04c7d86d9f0d2295df869.tar.gz
version: '@github.com/Clansty/quote-api/archive/37a0e48a434b94bb04c04c7d86d9f0d2295df869.tar.gz'
sharp:
specifier: ^0.33.1
version: 0.33.1
specifier: ^0.33.2
version: 0.33.2
silk-sdk:
specifier: ^0.2.2
version: 0.2.2
@ -80,6 +80,9 @@ dependencies:
zincsearch-node:
specifier: ^2.1.0
version: 2.1.1(undici@6.3.0)
zod:
specifier: ^3.22.4
version: 3.22.4
devDependencies:
'@types/cli-progress':
@ -95,17 +98,17 @@ devDependencies:
specifier: ^2.1.24
version: 2.1.24
'@types/lodash':
specifier: ^4.14.201
version: 4.14.201
specifier: ^4.14.202
version: 4.14.202
'@types/node':
specifier: ^20.10.8
version: 20.10.8
specifier: ^20.11.0
version: 20.11.0
'@types/prompts':
specifier: ^2.4.9
version: 2.4.9
ts-node:
specifier: ^10.9.2
version: 10.9.2(@types/node@20.10.8)(typescript@5.3.3)
tsx:
specifier: ^4.7.0
version: 4.7.0
typescript:
specifier: ^5.3.3
version: 5.3.3
@ -120,50 +123,250 @@ packages:
resolution: {integrity: sha512-PcYz4FDGblO6tM2kSC+VzhhK62vml6k6/YAkiWtyPvrgJVfnDRoHGDtKn5UiaRRUrvUTTocBpvc2rRgTCqxjsg==}
dev: false
/@cspotcode/source-map-support@0.8.1:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
dependencies:
'@jridgewell/trace-mapping': 0.3.9
dev: true
/@emnapi/runtime@0.44.0:
resolution: {integrity: sha512-ZX/etZEZw8DR7zAB1eVQT40lNo0jeqpb6dCgOvctB6FIQ5PoXfMuNY8+ayQfu8tNQbAB8gQWSSJupR8NxeiZXw==}
/@emnapi/runtime@0.45.0:
resolution: {integrity: sha512-Txumi3td7J4A/xTTwlssKieHKTGl3j4A1tglBx72auZ49YK7ePY6XZricgIg9mnZT4xPfA+UPCUdnhRuEFDL+w==}
requiresBuild: true
dependencies:
tslib: 2.6.2
dev: false
optional: true
/@esbuild/aix-ppc64@0.19.11:
resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [aix]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-arm64@0.19.11:
resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==}
engines: {node: '>=12'}
cpu: [arm64]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-arm@0.19.11:
resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==}
engines: {node: '>=12'}
cpu: [arm]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/android-x64@0.19.11:
resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==}
engines: {node: '>=12'}
cpu: [x64]
os: [android]
requiresBuild: true
dev: true
optional: true
/@esbuild/darwin-arm64@0.19.11:
resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@esbuild/darwin-x64@0.19.11:
resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==}
engines: {node: '>=12'}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@esbuild/freebsd-arm64@0.19.11:
resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==}
engines: {node: '>=12'}
cpu: [arm64]
os: [freebsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/freebsd-x64@0.19.11:
resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==}
engines: {node: '>=12'}
cpu: [x64]
os: [freebsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-arm64@0.19.11:
resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==}
engines: {node: '>=12'}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-arm@0.19.11:
resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==}
engines: {node: '>=12'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-ia32@0.19.11:
resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==}
engines: {node: '>=12'}
cpu: [ia32]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-loong64@0.19.11:
resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==}
engines: {node: '>=12'}
cpu: [loong64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-mips64el@0.19.11:
resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==}
engines: {node: '>=12'}
cpu: [mips64el]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-ppc64@0.19.11:
resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==}
engines: {node: '>=12'}
cpu: [ppc64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-riscv64@0.19.11:
resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==}
engines: {node: '>=12'}
cpu: [riscv64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-s390x@0.19.11:
resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==}
engines: {node: '>=12'}
cpu: [s390x]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/linux-x64@0.19.11:
resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==}
engines: {node: '>=12'}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@esbuild/netbsd-x64@0.19.11:
resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [netbsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/openbsd-x64@0.19.11:
resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==}
engines: {node: '>=12'}
cpu: [x64]
os: [openbsd]
requiresBuild: true
dev: true
optional: true
/@esbuild/sunos-x64@0.19.11:
resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==}
engines: {node: '>=12'}
cpu: [x64]
os: [sunos]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-arm64@0.19.11:
resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==}
engines: {node: '>=12'}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-ia32@0.19.11:
resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==}
engines: {node: '>=12'}
cpu: [ia32]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@esbuild/win32-x64@0.19.11:
resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==}
engines: {node: '>=12'}
cpu: [x64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@fastify/busboy@2.0.0:
resolution: {integrity: sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==}
engines: {node: '>=14'}
dev: false
/@img/sharp-darwin-arm64@0.33.1:
resolution: {integrity: sha512-esr2BZ1x0bo+wl7Gx2hjssYhjrhUsD88VQulI0FrG8/otRQUOxLWHMBd1Y1qo2Gfg2KUvXNpT0ASnV9BzJCexw==}
/@img/sharp-darwin-arm64@0.33.2:
resolution: {integrity: sha512-itHBs1rPmsmGF9p4qRe++CzCgd+kFYktnsoR1sbIAfsRMrJZau0Tt1AH9KVnufc2/tU02Gf6Ibujx+15qRE03w==}
engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [arm64]
os: [darwin]
requiresBuild: true
optionalDependencies:
'@img/sharp-libvips-darwin-arm64': 1.0.0
'@img/sharp-libvips-darwin-arm64': 1.0.1
dev: false
optional: true
/@img/sharp-darwin-x64@0.33.1:
resolution: {integrity: sha512-YrnuB3bXuWdG+hJlXtq7C73lF8ampkhU3tMxg5Hh+E7ikxbUVOU9nlNtVTloDXz6pRHt2y2oKJq7DY/yt+UXYw==}
/@img/sharp-darwin-x64@0.33.2:
resolution: {integrity: sha512-/rK/69Rrp9x5kaWBjVN07KixZanRr+W1OiyKdXcbjQD6KbW+obaTeBBtLUAtbBsnlTTmWthw99xqoOS7SsySDg==}
engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [x64]
os: [darwin]
requiresBuild: true
optionalDependencies:
'@img/sharp-libvips-darwin-x64': 1.0.0
'@img/sharp-libvips-darwin-x64': 1.0.1
dev: false
optional: true
/@img/sharp-libvips-darwin-arm64@1.0.0:
resolution: {integrity: sha512-VzYd6OwnUR81sInf3alj1wiokY50DjsHz5bvfnsFpxs5tqQxESoHtJO6xyksDs3RIkyhMWq2FufXo6GNSU9BMw==}
/@img/sharp-libvips-darwin-arm64@1.0.1:
resolution: {integrity: sha512-kQyrSNd6lmBV7O0BUiyu/OEw9yeNGFbQhbxswS1i6rMDwBBSX+e+rPzu3S+MwAiGU3HdLze3PanQ4Xkfemgzcw==}
engines: {macos: '>=11', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [arm64]
os: [darwin]
@ -171,8 +374,8 @@ packages:
dev: false
optional: true
/@img/sharp-libvips-darwin-x64@1.0.0:
resolution: {integrity: sha512-dD9OznTlHD6aovRswaPNEy8dKtSAmNo4++tO7uuR4o5VxbVAOoEQ1uSmN4iFAdQneTHws1lkTZeiXPrcCkh6IA==}
/@img/sharp-libvips-darwin-x64@1.0.1:
resolution: {integrity: sha512-eVU/JYLPVjhhrd8Tk6gosl5pVlvsqiFlt50wotCvdkFGf+mDNBJxMh+bvav+Wt3EBnNZWq8Sp2I7XfSjm8siog==}
engines: {macos: '>=10.13', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [x64]
os: [darwin]
@ -180,8 +383,8 @@ packages:
dev: false
optional: true
/@img/sharp-libvips-linux-arm64@1.0.0:
resolution: {integrity: sha512-xTYThiqEZEZc0PRU90yVtM3KE7lw1bKdnDQ9kCTHWbqWyHOe4NpPOtMGy27YnN51q0J5dqRrvicfPbALIOeAZA==}
/@img/sharp-libvips-linux-arm64@1.0.1:
resolution: {integrity: sha512-bnGG+MJjdX70mAQcSLxgeJco11G+MxTz+ebxlz8Y3dxyeb3Nkl7LgLI0mXupoO+u1wRNx/iRj5yHtzA4sde1yA==}
engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [arm64]
os: [linux]
@ -189,8 +392,8 @@ packages:
dev: false
optional: true
/@img/sharp-libvips-linux-arm@1.0.0:
resolution: {integrity: sha512-VwgD2eEikDJUk09Mn9Dzi1OW2OJFRQK+XlBTkUNmAWPrtj8Ly0yq05DFgu1VCMx2/DqCGQVi5A1dM9hTmxf3uw==}
/@img/sharp-libvips-linux-arm@1.0.1:
resolution: {integrity: sha512-FtdMvR4R99FTsD53IA3LxYGghQ82t3yt0ZQ93WMZ2xV3dqrb0E8zq4VHaTOuLEAuA83oDawHV3fd+BsAPadHIQ==}
engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [arm]
os: [linux]
@ -198,8 +401,8 @@ packages:
dev: false
optional: true
/@img/sharp-libvips-linux-s390x@1.0.0:
resolution: {integrity: sha512-o9E46WWBC6JsBlwU4QyU9578G77HBDT1NInd+aERfxeOPbk0qBZHgoDsQmA2v9TbqJRWzoBPx1aLOhprBMgPjw==}
/@img/sharp-libvips-linux-s390x@1.0.1:
resolution: {integrity: sha512-3+rzfAR1YpMOeA2zZNp+aYEzGNWK4zF3+sdMxuCS3ey9HhDbJ66w6hDSHDMoap32DueFwhhs3vwooAB2MaK4XQ==}
engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [s390x]
os: [linux]
@ -207,8 +410,8 @@ packages:
dev: false
optional: true
/@img/sharp-libvips-linux-x64@1.0.0:
resolution: {integrity: sha512-naldaJy4hSVhWBgEjfdBY85CAa4UO+W1nx6a1sWStHZ7EUfNiuBTTN2KUYT5dH1+p/xij1t2QSXfCiFJoC5S/Q==}
/@img/sharp-libvips-linux-x64@1.0.1:
resolution: {integrity: sha512-3NR1mxFsaSgMMzz1bAnnKbSAI+lHXVTqAHgc1bgzjHuXjo4hlscpUxc0vFSAPKI3yuzdzcZOkq7nDPrP2F8Jgw==}
engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [x64]
os: [linux]
@ -216,8 +419,8 @@ packages:
dev: false
optional: true
/@img/sharp-libvips-linuxmusl-arm64@1.0.0:
resolution: {integrity: sha512-OdorplCyvmSAPsoJLldtLh3nLxRrkAAAOHsGWGDYfN0kh730gifK+UZb3dWORRa6EusNqCTjfXV4GxvgJ/nPDQ==}
/@img/sharp-libvips-linuxmusl-arm64@1.0.1:
resolution: {integrity: sha512-5aBRcjHDG/T6jwC3Edl3lP8nl9U2Yo8+oTl5drd1dh9Z1EBfzUKAJFUDTDisDjUwc7N4AjnPGfCA3jl3hY8uDg==}
engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [arm64]
os: [linux]
@ -225,8 +428,8 @@ packages:
dev: false
optional: true
/@img/sharp-libvips-linuxmusl-x64@1.0.0:
resolution: {integrity: sha512-FW8iK6rJrg+X2jKD0Ajhjv6y74lToIBEvkZhl42nZt563FfxkCYacrXZtd+q/sRQDypQLzY5WdLkVTbJoPyqNg==}
/@img/sharp-libvips-linuxmusl-x64@1.0.1:
resolution: {integrity: sha512-dcT7inI9DBFK6ovfeWRe3hG30h51cBAP5JXlZfx6pzc/Mnf9HFCQDLtYf4MCBjxaaTfjCCjkBxcy3XzOAo5txw==}
engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [x64]
os: [linux]
@ -234,84 +437,84 @@ packages:
dev: false
optional: true
/@img/sharp-linux-arm64@0.33.1:
resolution: {integrity: sha512-59B5GRO2d5N3tIfeGHAbJps7cLpuWEQv/8ySd9109ohQ3kzyCACENkFVAnGPX00HwPTQcaBNF7HQYEfZyZUFfw==}
/@img/sharp-linux-arm64@0.33.2:
resolution: {integrity: sha512-pz0NNo882vVfqJ0yNInuG9YH71smP4gRSdeL09ukC2YLE6ZyZePAlWKEHgAzJGTiOh8Qkaov6mMIMlEhmLdKew==}
engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [arm64]
os: [linux]
requiresBuild: true
optionalDependencies:
'@img/sharp-libvips-linux-arm64': 1.0.0
'@img/sharp-libvips-linux-arm64': 1.0.1
dev: false
optional: true
/@img/sharp-linux-arm@0.33.1:
resolution: {integrity: sha512-Ii4X1vnzzI4j0+cucsrYA5ctrzU9ciXERfJR633S2r39CiD8npqH2GMj63uFZRCFt3E687IenAdbwIpQOJ5BNA==}
/@img/sharp-linux-arm@0.33.2:
resolution: {integrity: sha512-Fndk/4Zq3vAc4G/qyfXASbS3HBZbKrlnKZLEJzPLrXoJuipFNNwTes71+Ki1hwYW5lch26niRYoZFAtZVf3EGA==}
engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [arm]
os: [linux]
requiresBuild: true
optionalDependencies:
'@img/sharp-libvips-linux-arm': 1.0.0
'@img/sharp-libvips-linux-arm': 1.0.1
dev: false
optional: true
/@img/sharp-linux-s390x@0.33.1:
resolution: {integrity: sha512-tRGrb2pHnFUXpOAj84orYNxHADBDIr0J7rrjwQrTNMQMWA4zy3StKmMvwsI7u3dEZcgwuMMooIIGWEWOjnmG8A==}
/@img/sharp-linux-s390x@0.33.2:
resolution: {integrity: sha512-MBoInDXDppMfhSzbMmOQtGfloVAflS2rP1qPcUIiITMi36Mm5YR7r0ASND99razjQUpHTzjrU1flO76hKvP5RA==}
engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [s390x]
os: [linux]
requiresBuild: true
optionalDependencies:
'@img/sharp-libvips-linux-s390x': 1.0.0
'@img/sharp-libvips-linux-s390x': 1.0.1
dev: false
optional: true
/@img/sharp-linux-x64@0.33.1:
resolution: {integrity: sha512-4y8osC0cAc1TRpy02yn5omBeloZZwS62fPZ0WUAYQiLhSFSpWJfY/gMrzKzLcHB9ulUV6ExFiu2elMaixKDbeg==}
/@img/sharp-linux-x64@0.33.2:
resolution: {integrity: sha512-xUT82H5IbXewKkeF5aiooajoO1tQV4PnKfS/OZtb5DDdxS/FCI/uXTVZ35GQ97RZXsycojz/AJ0asoz6p2/H/A==}
engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [x64]
os: [linux]
requiresBuild: true
optionalDependencies:
'@img/sharp-libvips-linux-x64': 1.0.0
'@img/sharp-libvips-linux-x64': 1.0.1
dev: false
optional: true
/@img/sharp-linuxmusl-arm64@0.33.1:
resolution: {integrity: sha512-D3lV6clkqIKUizNS8K6pkuCKNGmWoKlBGh5p0sLO2jQERzbakhu4bVX1Gz+RS4vTZBprKlWaf+/Rdp3ni2jLfA==}
/@img/sharp-linuxmusl-arm64@0.33.2:
resolution: {integrity: sha512-F+0z8JCu/UnMzg8IYW1TMeiViIWBVg7IWP6nE0p5S5EPQxlLd76c8jYemG21X99UzFwgkRo5yz2DS+zbrnxZeA==}
engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [arm64]
os: [linux]
requiresBuild: true
optionalDependencies:
'@img/sharp-libvips-linuxmusl-arm64': 1.0.0
'@img/sharp-libvips-linuxmusl-arm64': 1.0.1
dev: false
optional: true
/@img/sharp-linuxmusl-x64@0.33.1:
resolution: {integrity: sha512-LOGKNu5w8uu1evVqUAUKTix2sQu1XDRIYbsi5Q0c/SrXhvJ4QyOx+GaajxmOg5PZSsSnCYPSmhjHHsRBx06/wQ==}
/@img/sharp-linuxmusl-x64@0.33.2:
resolution: {integrity: sha512-+ZLE3SQmSL+Fn1gmSaM8uFusW5Y3J9VOf+wMGNnTtJUMUxFhv+P4UPaYEYT8tqnyYVaOVGgMN/zsOxn9pSsO2A==}
engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [x64]
os: [linux]
requiresBuild: true
optionalDependencies:
'@img/sharp-libvips-linuxmusl-x64': 1.0.0
'@img/sharp-libvips-linuxmusl-x64': 1.0.1
dev: false
optional: true
/@img/sharp-wasm32@0.33.1:
resolution: {integrity: sha512-vWI/sA+0p+92DLkpAMb5T6I8dg4z2vzCUnp8yvxHlwBpzN8CIcO3xlSXrLltSvK6iMsVMNswAv+ub77rsf25lA==}
/@img/sharp-wasm32@0.33.2:
resolution: {integrity: sha512-fLbTaESVKuQcpm8ffgBD7jLb/CQLcATju/jxtTXR1XCLwbOQt+OL5zPHSDMmp2JZIeq82e18yE0Vv7zh6+6BfQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [wasm32]
requiresBuild: true
dependencies:
'@emnapi/runtime': 0.44.0
'@emnapi/runtime': 0.45.0
dev: false
optional: true
/@img/sharp-win32-ia32@0.33.1:
resolution: {integrity: sha512-/xhYkylsKL05R+NXGJc9xr2Tuw6WIVl2lubFJaFYfW4/MQ4J+dgjIo/T4qjNRizrqs/szF/lC9a5+updmY9jaQ==}
/@img/sharp-win32-ia32@0.33.2:
resolution: {integrity: sha512-okBpql96hIGuZ4lN3+nsAjGeggxKm7hIRu9zyec0lnfB8E7Z6p95BuRZzDDXZOl2e8UmR4RhYt631i7mfmKU8g==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [ia32]
os: [win32]
@ -319,8 +522,8 @@ packages:
dev: false
optional: true
/@img/sharp-win32-x64@0.33.1:
resolution: {integrity: sha512-XaM69X0n6kTEsp9tVYYLhXdg7Qj32vYJlAKRutxUsm1UlgQNx6BOhHwZPwukCGXBU2+tH87ip2eV1I/E8MQnZg==}
/@img/sharp-win32-x64@0.33.2:
resolution: {integrity: sha512-E4magOks77DK47FwHUIGH0RYWSgRBfGdK56kIHSVeB9uIS4pPFr4N2kIVsXdQQo4LzOsENKV5KAhRlRL7eMAdg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'}
cpu: [x64]
os: [win32]
@ -674,22 +877,6 @@ packages:
regenerator-runtime: 0.13.11
dev: false
/@jridgewell/resolve-uri@3.1.1:
resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
engines: {node: '>=6.0.0'}
dev: true
/@jridgewell/sourcemap-codec@1.4.15:
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
dev: true
/@jridgewell/trace-mapping@0.3.9:
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
dependencies:
'@jridgewell/resolve-uri': 3.1.1
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
/@mapbox/node-pre-gyp@1.0.11:
resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
hasBin: true
@ -762,39 +949,23 @@ packages:
engines: {node: '>= 6'}
dev: false
/@tsconfig/node10@1.0.9:
resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==}
dev: true
/@tsconfig/node12@1.0.11:
resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==}
dev: true
/@tsconfig/node14@1.0.3:
resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==}
dev: true
/@tsconfig/node16@1.0.4:
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
dev: true
/@types/cli-progress@3.11.5:
resolution: {integrity: sha512-D4PbNRbviKyppS5ivBGyFO29POlySLmA2HyUFE4p5QGazAMM3CwkKWcvTl8gvElSuxRh6FPKL8XmidX873ou4g==}
dependencies:
'@types/node': 20.10.8
'@types/node': 20.11.0
dev: true
/@types/date-and-time@3.0.3:
resolution: {integrity: sha512-5uHEzTnzhS5gO8UOWIwPQitg13mAnixpoWaWuqUfGLvF9GdxBe7Uo56ZRLTQ7CckanqW/oAv/RyQDv4Knf075A==}
deprecated: This is a stub types definition. date-and-time provides its own type definitions, so you do not need this installed.
dependencies:
date-and-time: 2.4.3
date-and-time: 3.1.1
dev: true
/@types/docker-modem@3.0.6:
resolution: {integrity: sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==}
dependencies:
'@types/node': 20.10.8
'@types/node': 20.11.0
'@types/ssh2': 1.11.18
dev: true
@ -802,17 +973,17 @@ packages:
resolution: {integrity: sha512-Lz5J+NFgZS4cEVhquwjIGH4oQwlVn2h7LXD3boitujBnzOE5o7s9H8hchEjoDK2SlRsJTogdKnQeiJgPPKLIEw==}
dependencies:
'@types/docker-modem': 3.0.6
'@types/node': 20.10.8
'@types/node': 20.11.0
dev: true
/@types/fluent-ffmpeg@2.1.24:
resolution: {integrity: sha512-g5oQO8Jgi2kFS3tTub7wLvfLztr1s8tdXmRd8PiL/hLMLzTIAyMR2sANkTggM/rdEDAg3d63nYRRVepwBiCw5A==}
dependencies:
'@types/node': 20.10.8
'@types/node': 20.11.0
dev: true
/@types/lodash@4.14.201:
resolution: {integrity: sha512-y9euML0cim1JrykNxADLfaG0FgD1g/yTHwUs/Jg9ZIU7WKj2/4IW9Lbb1WZbvck78W/lfGXFfe+u2EGfIJXdLQ==}
/@types/lodash@4.14.202:
resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==}
dev: true
/@types/node@16.9.1:
@ -825,8 +996,8 @@ packages:
undici-types: 5.26.5
dev: true
/@types/node@20.10.8:
resolution: {integrity: sha512-f8nQs3cLxbAFc00vEU59yf9UyGUftkPaLGfvbVOIDdx2i1b8epBqj2aNGyP19fiyXWvlmZ7qC1XLjAzw/OKIeA==}
/@types/node@20.11.0:
resolution: {integrity: sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==}
dependencies:
undici-types: 5.26.5
dev: true
@ -834,7 +1005,7 @@ packages:
/@types/prompts@2.4.9:
resolution: {integrity: sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==}
dependencies:
'@types/node': 20.10.8
'@types/node': 20.11.0
kleur: 3.0.3
dev: true
@ -873,11 +1044,6 @@ packages:
engines: {node: '>=0.4.0'}
dev: false
/acorn-walk@8.3.0:
resolution: {integrity: sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==}
engines: {node: '>=0.4.0'}
dev: true
/acorn@7.4.1:
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
engines: {node: '>=0.4.0'}
@ -888,6 +1054,7 @@ packages:
resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==}
engines: {node: '>=0.4.0'}
hasBin: true
dev: false
/agent-base@6.0.2:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
@ -939,10 +1106,6 @@ packages:
readable-stream: 3.6.2
dev: false
/arg@4.1.3:
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
dev: true
/asn1@0.2.6:
resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
dependencies:
@ -1273,10 +1436,6 @@ packages:
dev: false
optional: true
/create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
dev: true
/cssom@0.3.8:
resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==}
dev: false
@ -1315,13 +1474,8 @@ packages:
whatwg-url: 8.7.0
dev: false
/date-and-time@2.4.3:
resolution: {integrity: sha512-xkS/imTmsyEdpp9ie5oV5UWolg3XkYWNySbT2W4ESWr6v4V8YrsHbhpk9fIeQcr0NFTnYbQJLXlgU1zrLItysA==}
dev: true
/date-and-time@3.1.0:
resolution: {integrity: sha512-tWIpW3LK8tyLofyuMYxfOUchstWcyXjM+4rzIzve/VtBLzvS6q1oOxkcwhQ710nhU3M04jpfveDQ18IIw8lm2A==}
dev: false
/date-and-time@3.1.1:
resolution: {integrity: sha512-N9kstidT3P0VUk1iKOFilOZ6251r6iTUNx9M9kvgL2jqOk9mljWZUq5CjAtYwCnppWHbERk5YFQUrSbY7FQOpA==}
/date-format@4.0.14:
resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==}
@ -1436,11 +1590,6 @@ packages:
dev: false
optional: true
/diff@4.0.2:
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
engines: {node: '>=0.3.1'}
dev: true
/docker-modem@5.0.3:
resolution: {integrity: sha512-89zhop5YVhcPEt5FpUFGr3cDyceGhq/F9J+ZndQ4KfqNvfbJpPMfgeixFgUj5OjCYAboElqODxY5Z1EBsSa6sg==}
engines: {node: '>= 8.0'}
@ -1572,6 +1721,37 @@ packages:
ext: 1.7.0
dev: false
/esbuild@0.19.11:
resolution: {integrity: sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==}
engines: {node: '>=12'}
hasBin: true
requiresBuild: true
optionalDependencies:
'@esbuild/aix-ppc64': 0.19.11
'@esbuild/android-arm': 0.19.11
'@esbuild/android-arm64': 0.19.11
'@esbuild/android-x64': 0.19.11
'@esbuild/darwin-arm64': 0.19.11
'@esbuild/darwin-x64': 0.19.11
'@esbuild/freebsd-arm64': 0.19.11
'@esbuild/freebsd-x64': 0.19.11
'@esbuild/linux-arm': 0.19.11
'@esbuild/linux-arm64': 0.19.11
'@esbuild/linux-ia32': 0.19.11
'@esbuild/linux-loong64': 0.19.11
'@esbuild/linux-mips64el': 0.19.11
'@esbuild/linux-ppc64': 0.19.11
'@esbuild/linux-riscv64': 0.19.11
'@esbuild/linux-s390x': 0.19.11
'@esbuild/linux-x64': 0.19.11
'@esbuild/netbsd-x64': 0.19.11
'@esbuild/openbsd-x64': 0.19.11
'@esbuild/sunos-x64': 0.19.11
'@esbuild/win32-arm64': 0.19.11
'@esbuild/win32-ia32': 0.19.11
'@esbuild/win32-x64': 0.19.11
dev: true
/escape-html@1.0.3:
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
dev: false
@ -1744,6 +1924,14 @@ packages:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: false
/fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
requiresBuild: true
dev: true
optional: true
/function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
dev: false
@ -1772,6 +1960,12 @@ packages:
hasown: 2.0.0
dev: false
/get-tsconfig@4.7.2:
resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==}
dependencies:
resolve-pkg-maps: 1.0.0
dev: true
/getpass@0.1.7:
resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==}
dependencies:
@ -2373,10 +2567,6 @@ packages:
semver: 6.3.1
dev: false
/make-error@1.3.6:
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
dev: true
/media-typer@0.3.0:
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
engines: {node: '>= 0.6'}
@ -2861,6 +3051,10 @@ packages:
resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==}
dev: false
/resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
dev: true
/rfdc@1.3.0:
resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==}
dev: false
@ -2932,34 +3126,34 @@ packages:
resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
dev: false
/sharp@0.33.1:
resolution: {integrity: sha512-iAYUnOdTqqZDb3QjMneBKINTllCJDZ3em6WaWy7NPECM4aHncvqHRm0v0bN9nqJxMiwamv5KIdauJ6lUzKDpTQ==}
engines: {libvips: '>=8.15.0', node: ^18.17.0 || ^20.3.0 || >=21.0.0}
/sharp@0.33.2:
resolution: {integrity: sha512-WlYOPyyPDiiM07j/UO+E720ju6gtNtHjEGg5vovUk1Lgxyjm2LFO+37Nt/UI3MMh2l6hxTWQWi7qk3cXJTutcQ==}
engines: {libvips: '>=8.15.1', node: ^18.17.0 || ^20.3.0 || >=21.0.0}
requiresBuild: true
dependencies:
color: 4.2.3
detect-libc: 2.0.2
semver: 7.5.4
optionalDependencies:
'@img/sharp-darwin-arm64': 0.33.1
'@img/sharp-darwin-x64': 0.33.1
'@img/sharp-libvips-darwin-arm64': 1.0.0
'@img/sharp-libvips-darwin-x64': 1.0.0
'@img/sharp-libvips-linux-arm': 1.0.0
'@img/sharp-libvips-linux-arm64': 1.0.0
'@img/sharp-libvips-linux-s390x': 1.0.0
'@img/sharp-libvips-linux-x64': 1.0.0
'@img/sharp-libvips-linuxmusl-arm64': 1.0.0
'@img/sharp-libvips-linuxmusl-x64': 1.0.0
'@img/sharp-linux-arm': 0.33.1
'@img/sharp-linux-arm64': 0.33.1
'@img/sharp-linux-s390x': 0.33.1
'@img/sharp-linux-x64': 0.33.1
'@img/sharp-linuxmusl-arm64': 0.33.1
'@img/sharp-linuxmusl-x64': 0.33.1
'@img/sharp-wasm32': 0.33.1
'@img/sharp-win32-ia32': 0.33.1
'@img/sharp-win32-x64': 0.33.1
'@img/sharp-darwin-arm64': 0.33.2
'@img/sharp-darwin-x64': 0.33.2
'@img/sharp-libvips-darwin-arm64': 1.0.1
'@img/sharp-libvips-darwin-x64': 1.0.1
'@img/sharp-libvips-linux-arm': 1.0.1
'@img/sharp-libvips-linux-arm64': 1.0.1
'@img/sharp-libvips-linux-s390x': 1.0.1
'@img/sharp-libvips-linux-x64': 1.0.1
'@img/sharp-libvips-linuxmusl-arm64': 1.0.1
'@img/sharp-libvips-linuxmusl-x64': 1.0.1
'@img/sharp-linux-arm': 0.33.2
'@img/sharp-linux-arm64': 0.33.2
'@img/sharp-linux-s390x': 0.33.2
'@img/sharp-linux-x64': 0.33.2
'@img/sharp-linuxmusl-arm64': 0.33.2
'@img/sharp-linuxmusl-x64': 0.33.2
'@img/sharp-wasm32': 0.33.2
'@img/sharp-win32-ia32': 0.33.2
'@img/sharp-win32-x64': 0.33.2
dev: false
/should-equal@2.0.0:
@ -3064,12 +3258,12 @@ packages:
engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
dev: false
/smartcrop-sharp@2.0.8(sharp@0.33.1):
/smartcrop-sharp@2.0.8(sharp@0.33.2):
resolution: {integrity: sha512-0rpK/ddGAx7ou6YqqvJRkw/xyR4qgqmJeUQ2EWDnN3hSuJUk4InPGE6Sa45+TYOfGEEQJrchjF1ujBPMhoe9iA==}
peerDependencies:
sharp: ^0.32.5
dependencies:
sharp: 0.33.1
sharp: 0.33.2
smartcrop: 2.0.5
dev: false
@ -3367,37 +3561,6 @@ packages:
engines: {node: '>=14.0.0'}
dev: false
/ts-node@10.9.2(@types/node@20.10.8)(typescript@5.3.3):
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
hasBin: true
peerDependencies:
'@swc/core': '>=1.2.50'
'@swc/wasm': '>=1.2.50'
'@types/node': '*'
typescript: '>=2.7'
peerDependenciesMeta:
'@swc/core':
optional: true
'@swc/wasm':
optional: true
dependencies:
'@cspotcode/source-map-support': 0.8.1
'@tsconfig/node10': 1.0.9
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
'@types/node': 20.10.8
acorn: 8.11.2
acorn-walk: 8.3.0
arg: 4.1.3
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
typescript: 5.3.3
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
dev: true
/tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
dev: false
@ -3407,6 +3570,17 @@ packages:
engines: {node: '>=0.6.x'}
dev: false
/tsx@4.7.0:
resolution: {integrity: sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg==}
engines: {node: '>=18.0.0'}
hasBin: true
dependencies:
esbuild: 0.19.11
get-tsconfig: 4.7.2
optionalDependencies:
fsevents: 2.3.3
dev: true
/tunnel-agent@0.6.0:
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
dependencies:
@ -3526,10 +3700,6 @@ packages:
hasBin: true
dev: false
/v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
dev: true
/vary@1.1.2:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
@ -3712,11 +3882,6 @@ packages:
engines: {node: '>= 4.0.0'}
dev: false
/yn@3.1.1:
resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
engines: {node: '>=6'}
dev: true
/zincsearch-node@2.1.1(undici@6.3.0):
resolution: {integrity: sha512-erRhljqQVK96HE7KWfMFQaFsiere3+DrInZY2g5pHpz5ea/78G1z4Exky2vsLvLZ+D320D2JINcc2BVedY+6aQ==}
peerDependencies:
@ -3726,6 +3891,10 @@ packages:
undici: 6.3.0
dev: false
/zod@3.22.4:
resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
dev: false
'@github.com/Clansty/quote-api/archive/37a0e48a434b94bb04c04c7d86d9f0d2295df869.tar.gz':
resolution: {tarball: https://github.com/Clansty/quote-api/archive/37a0e48a434b94bb04c04c7d86d9f0d2295df869.tar.gz}
name: quote-api
@ -3747,8 +3916,8 @@ packages:
lru-cache: 5.1.1
object-sizeof: 1.6.3
runes: 0.4.3
sharp: 0.33.1
smartcrop-sharp: 2.0.8(sharp@0.33.1)
sharp: 0.33.2
smartcrop-sharp: 2.0.8(sharp@0.33.2)
telegraf: 3.40.0
transitivePeerDependencies:
- bufferutil

View File

@ -45,6 +45,7 @@ model Instance {
qqBotId Int?
qqBot QqBot? @relation(fields: [qqBotId], references: [id], onDelete: Cascade)
reportUrl String?
flags Int @default(0)
}
model QqBot {
@ -87,11 +88,7 @@ model ForwardPair {
avatarCache AvatarCache[]
instanceId Int @default(0)
instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
joinNotice Boolean @default(true)
poke Boolean @default(true)
enable Boolean @default(true)
disableQ2TG Boolean @default(false)
disableTG2Q Boolean @default(false)
flags Int @default(0)
@@unique([qqRoomId, instanceId])
@@unique([tgChatId, instanceId])

View File

@ -20,8 +20,9 @@ import { Converter, Image, rand2uuid } from 'icqq/lib/message';
import { randomBytes } from 'crypto';
import { escapeXml, gzip, timestamp } from 'icqq/lib/common';
import { pb } from 'icqq/lib/core';
import env from '../models/env';
const LOG_LEVEL: LogLevel = process.env.LOG_LEVEL as LogLevel || 'warn';
const LOG_LEVEL: LogLevel = env.OICQ_LOG_LEVEL;
type MessageHandler = (event: PrivateMessageEvent | GroupMessageEvent) => Promise<boolean | void>
@ -123,10 +124,10 @@ export default class OicqClient extends Client {
platform: params.platform,
data_dir: dataPath(params.uin.toString()),
log_level: LOG_LEVEL,
ffmpeg_path: process.env.FFMPEG_PATH,
ffprobe_path: process.env.FFPROBE_PATH,
sign_api_addr: params.signApi || process.env.SIGN_API,
ver: params.signVer || process.env.SIGN_VER,
ffmpeg_path: env.FFMPEG_PATH,
ffprobe_path: env.FFPROBE_PATH,
sign_api_addr: params.signApi || env.SIGN_API,
ver: params.signVer || env.SIGN_VER,
}, params.signDockerId);
client.on('system.login.device', loginDeviceHandler);
client.on('system.login.slider', loginSliderHandler);

View File

@ -15,6 +15,7 @@ import { BigInteger } from 'big-integer';
import { EditMessageParams, IterMessagesParams } from 'telegram/client/messages';
import { PromisedNetSockets, PromisedWebSockets } from 'telegram/extensions';
import { ConnectionTCPFull, ConnectionTCPObfuscated } from 'telegram/network';
import env from '../models/env';
type MessageHandler = (message: Api.Message) => Promise<boolean | void>;
type ServiceMessageHandler = (message: Api.MessageService) => Promise<boolean | void>;
@ -41,24 +42,24 @@ export default class Telegram {
private constructor(appName: string, sessionId?: number) {
this.client = new TelegramClient(
new TelegramSession(sessionId),
parseInt(process.env.TG_API_ID),
process.env.TG_API_HASH,
env.TG_API_ID,
env.TG_API_HASH,
{
connectionRetries: 20,
langCode: 'zh',
deviceModel: `${appName} On ${os.hostname()}`,
appVersion: 'rainbowcat',
useIPV6: !!process.env.IPV6,
proxy: process.env.PROXY_IP ? {
useIPV6: !!env.IPV6,
proxy: env.PROXY_IP ? {
socksType: 5,
ip: process.env.PROXY_IP,
port: parseInt(process.env.PROXY_PORT),
...(process.env.PROXY_USERNAME && { username: process.env.PROXY_USERNAME }),
...(process.env.PROXY_PASSWORD && { password: process.env.PROXY_PASSWORD }),
ip: env.PROXY_IP,
port: env.PROXY_PORT,
username: env.PROXY_USERNAME,
password: env.PROXY_PASSWORD,
} : undefined,
autoReconnect: true,
networkSocket: process.env.TG_CONNECTION === 'websocket' ? PromisedWebSockets : PromisedNetSockets,
connection: process.env.TG_CONNECTION === 'websocket' ? ConnectionTCPObfuscated : ConnectionTCPFull,
networkSocket: env.TG_CONNECTION === 'websocket' ? PromisedWebSockets : PromisedNetSockets,
connection: env.TG_CONNECTION === 'websocket' ? ConnectionTCPObfuscated : ConnectionTCPFull,
},
);
// this.client.logger.setLevel(LogLevel.WARN);

View File

@ -2,7 +2,7 @@ import { BigInteger } from 'big-integer';
import { Api, TelegramClient, utils } from 'telegram';
import { ButtonLike, Entity, EntityLike, MessageIDLike } from 'telegram/define';
import WaitForMessageHelper from '../helpers/WaitForMessageHelper';
import { SendMessageParams } from 'telegram/client/messages';
import { EditMessageParams, SendMessageParams } from 'telegram/client/messages';
import { CustomFile } from 'telegram/client/uploads';
import Telegram from './Telegram';
import createPaginatedInlineSelector from '../utils/paginatedInlineSelector';
@ -186,6 +186,10 @@ export default class TelegramChat {
return await this.client.deleteMessages(this.entity, messageId, { revoke: true });
}
public async editMessages(params: EditMessageParams) {
return await this.client.editMessage(this.entity, params);
}
public async inviteMember(member: EntityLike | EntityLike[]) {
if (!Array.isArray(member)) {
member = [member];

10
src/constants/flags.ts Normal file
View File

@ -0,0 +1,10 @@
enum flags {
DISABLE_Q2TG = 1,
DISABLE_TG2Q = 1 << 1,
DISABLE_JOIN_NOTICE = 1 << 2,
DISABLE_POKE = 1 << 3,
NO_DELETE_MESSAGE = 1 << 4,
NO_AUTO_CREATE_PM = 1 << 5,
}
export default flags;

View File

@ -12,6 +12,8 @@ import {
} from 'icqq';
import Instance from '../models/Instance';
import { getLogger, Logger } from 'log4js';
import { editFlags } from '../utils/flagControl';
import flags from '../constants/flags';
export default class ConfigController {
private readonly configService: ConfigService;
@ -47,6 +49,15 @@ export default class ConfigController {
return false;
}
else if (message.isPrivate) {
switch (messageSplit[0]) {
case '/flag':
case '/flags':
messageSplit.shift();
await message.reply({
message: await editFlags(messageSplit, this.instance),
});
return true;
}
if (this.instance.workMode === 'personal') {
switch (messageSplit[0]) {
case '/addfriend':
@ -105,6 +116,7 @@ export default class ConfigController {
private handleQqMessage = async (message: GroupMessageEvent | PrivateMessageEvent) => {
if (message.message_type !== 'private' || this.instance.workMode === 'group') return false;
if (this.instance.flags & flags.NO_AUTO_CREATE_PM) return false;
const pair = this.instance.forwardPairs.find(message.friend);
if (pair) return false;
// 如果正在创建中,应该阻塞

View File

@ -14,8 +14,9 @@ export default class DeleteMessageController {
this.deleteMessageService = new DeleteMessageService(this.instance, tgBot);
tgBot.addNewMessageEventHandler(this.onTelegramMessage);
tgBot.addEditedMessageEventHandler(this.onTelegramEditMessage);
oicq.on('notice.friend.recall', this.onQqFriendRecall);
oicq.on('notice.group.recall', this.onQqGroupRecall);
// tgUser.addDeletedMessageEventHandler(this.onTgDeletedMessage);
oicq.on('notice.friend.recall', this.onQqRecall);
oicq.on('notice.group.recall', this.onQqRecall);
}
private onTelegramMessage = async (message: Api.Message) => {
@ -39,14 +40,8 @@ export default class DeleteMessageController {
return await this.onTelegramMessage(message);
};
private onQqFriendRecall = async (event: FriendRecallEvent) => {
const pair = this.instance.forwardPairs.find(event.friend);
if (!pair) return;
await this.deleteMessageService.handleQqRecall(event, pair);
};
private onQqGroupRecall = async (event: GroupRecallEvent) => {
const pair = this.instance.forwardPairs.find(event.group);
private onQqRecall = async (event: FriendRecallEvent | GroupRecallEvent) => {
const pair = this.instance.forwardPairs.find('friend' in event ? event.friend : event.group);
if (!pair) return;
await this.deleteMessageService.handleQqRecall(event, pair);
};

View File

@ -18,6 +18,7 @@ import { CustomFile } from 'telegram/client/uploads';
import forwardHelper from '../helpers/forwardHelper';
import helper from '../helpers/forwardHelper';
import ZincSearch from 'zincsearch-node';
import flags from '../constants/flags';
export default class ForwardController {
private readonly forwardService: ForwardService;
@ -44,8 +45,7 @@ export default class ForwardController {
const target = event.message_type === 'private' ? event.friend : event.group;
const pair = this.instance.forwardPairs.find(target);
if (!pair) return;
if (!pair.enable) return;
if (pair.disableQ2TG) return;
if ((pair.flags | this.instance.flags) & flags.DISABLE_Q2TG) return;
// 如果是多张图片的话,是一整条消息,只过一次,所以不受这个判断影响
let existed = event.message_type === 'private' && await db.message.findFirst({
where: {
@ -101,8 +101,7 @@ export default class ForwardController {
if (message.senderId?.eq(this.instance.botMe.id)) return true;
const pair = this.instance.forwardPairs.find(message.chat);
if (!pair) return false;
if (!pair.enable) return;
if (pair.disableTG2Q) return;
if ((pair.flags | this.instance.flags) & flags.DISABLE_TG2Q) return;
const qqMessagesSent = await this.forwardService.forwardFromTelegram(message, pair);
if (qqMessagesSent) {
// 更新数据库
@ -140,7 +139,7 @@ export default class ForwardController {
private onQqGroupMemberIncrease = async (event: MemberIncreaseEvent) => {
try {
const pair = this.instance.forwardPairs.find(event.group);
if (!pair?.joinNotice) return false;
if ((pair?.flags | this.instance.flags) & flags.DISABLE_JOIN_NOTICE) return false;
const avatar = await getAvatar(event.user_id);
await pair.tg.sendMessage({
file: new CustomFile('avatar.png', avatar.length, '', avatar),
@ -156,7 +155,7 @@ export default class ForwardController {
private onTelegramParticipant = async (event: Api.UpdateChannelParticipant) => {
try {
const pair = this.instance.forwardPairs.find(event.channelId);
if (!pair?.joinNotice) return false;
if ((pair?.flags | this.instance.flags) & flags.DISABLE_JOIN_NOTICE) return false;
if (
!(event.newParticipant instanceof Api.ChannelParticipantAdmin) &&
!(event.newParticipant instanceof Api.ChannelParticipantCreator) &&
@ -174,7 +173,7 @@ export default class ForwardController {
private onQqPoke = async (event: FriendPokeEvent | GroupPokeEvent) => {
const target = event.notice_type === 'friend' ? event.friend : event.group;
const pair = this.instance.forwardPairs.find(target);
if (!pair?.poke) return;
if ((pair?.flags | this.instance.flags) & flags.DISABLE_POKE) return;
let operatorName: string, targetName: string;
if (target instanceof Friend) {
if (event.operator_id === target.user_id) {

View File

@ -23,10 +23,11 @@ type ActionSubjectQq = {
type ActionSubject = ActionSubjectTg | ActionSubjectQq;
const COMMAND_REGEX = /^\/([^\w\s$]\S*)|^\/\$(\w\S*)/; // /抱 /$rua
const COMMAND_REGEX = /(^\/([^\w\s$¥]\S*)|^\/[$¥](\w\S*))( (\S*))?/; // /抱 /$rua
export default class {
private readonly log: Logger;
constructor(private readonly instance: Instance,
private readonly tgBot: Telegram,
private readonly oicq: OicqClient) {
@ -47,7 +48,7 @@ export default class {
if (firstElem?.type !== 'text') return;
const exec = COMMAND_REGEX.exec(firstElem.text.trim());
if (!exec) return;
const action = exec[1] || exec[2];
const action = exec[2] || exec[3];
if (!action) return;
const from: ActionSubject = {
from: 'qq',
@ -76,7 +77,7 @@ export default class {
},
});
if (!sourceMessage) {
this.log.error('找不到 sourceMessage')
this.log.error('找不到 sourceMessage');
return true;
}
to = {
@ -100,7 +101,7 @@ export default class {
id: event.sender.user_id,
};
}
await this.sendAction(pair, from, to, action);
await this.sendAction(pair, from, to, action, exec[5]);
return true;
};
@ -109,7 +110,7 @@ export default class {
if (!pair) return;
const exec = COMMAND_REGEX.exec(message.message);
if (!exec) return;
const action = exec[1] || exec[2];
const action = exec[2] || exec[3];
if (!action) return;
const from: ActionSubject = {
from: 'tg',
@ -126,7 +127,7 @@ export default class {
},
});
if (!sourceMessage) {
this.log.error('找不到 sourceMessage')
this.log.error('找不到 sourceMessage');
return true;
}
if (this.tgBot.me.id.eq(sourceMessage.tgSenderId)) {
@ -152,11 +153,11 @@ export default class {
id: (await this.tgBot.getChat(message.senderId)).inputPeer as Api.InputPeerUser,
};
}
await this.sendAction(pair, from, to, action);
await this.sendAction(pair, from, to, action, exec[5]);
return true;
};
private async sendAction(pair: Pair, from: ActionSubject, to: ActionSubject, action: string) {
private async sendAction(pair: Pair, from: ActionSubject, to: ActionSubject, action: string, suffix?: string) {
let tgText = '';
const tgEntities: Api.TypeMessageEntity[] = [];
const qqMessageContent: Sendable = [];
@ -193,6 +194,9 @@ export default class {
}
addText('了 ');
addSubject(to);
if (suffix) {
tgText += ' ' + suffix;
}
addText('');
const tgMessage = await pair.tg.sendMessage({

View File

@ -6,6 +6,8 @@ import OicqClient from '../client/OicqClient';
import { Api } from 'telegram';
import { Group } from 'icqq';
import RecoverMessageHelper from '../helpers/RecoverMessageHelper';
import flags from '../constants/flags';
import { editFlags } from '../utils/flagControl';
export default class InChatCommandsController {
private readonly service: InChatCommandsService;
@ -42,29 +44,39 @@ export default class InChatCommandsController {
await this.service.poke(message, pair);
return true;
case '/forwardoff':
pair.enable = false;
pair.flags |= flags.DISABLE_Q2TG | flags.DISABLE_TG2Q;
await message.reply({ message: '转发已禁用' });
return true;
case '/forwardon':
pair.enable = true;
pair.flags &= ~flags.DISABLE_Q2TG & ~flags.DISABLE_TG2Q;
await message.reply({ message: '转发已启用' });
return true;
case '/disable_qq_forward':
pair.disableQ2TG = true;
pair.flags |= flags.DISABLE_Q2TG;
await message.reply({ message: 'QQ->TG已禁用' });
return true;
case '/enable_qq_forward':
pair.disableQ2TG = false;
pair.flags &= ~flags.DISABLE_Q2TG;
await message.reply({ message: 'QQ->TG已启用' });
return true;
case '/disable_tg_forward':
pair.disableTG2Q = true;
pair.flags |= flags.DISABLE_TG2Q;
await message.reply({ message: 'TG->QQ已禁用' });
return true;
case '/enable_tg_forward':
pair.disableTG2Q = false;
pair.flags &= ~flags.DISABLE_TG2Q;
await message.reply({ message: 'TG->QQ已启用' });
return true;
case '/flags':
case '/flag':
if (!message.senderId.eq(this.instance.owner)) {
await message.reply({ message: '权限不够' });
return true;
}
await message.reply({
message: await editFlags(messageParts, pair),
});
return true;
case '/refresh':
if (this.instance.workMode !== 'personal' || !message.senderId?.eq(this.instance.owner)) return false;
await pair.updateInfo();

View File

@ -0,0 +1,29 @@
import Instance from '../models/Instance';
import Telegram from '../client/Telegram';
import OicqClient from '../client/OicqClient';
import { GroupMessageEvent, MiraiElem, PrivateMessageEvent } from 'icqq';
export default class {
constructor(private readonly instance: Instance,
private readonly tgBot: Telegram,
private readonly tgUser: Telegram,
private readonly qqBot: OicqClient) {
qqBot.addNewMessageEventHandler(this.onQqMessage);
}
// 当 mapInstance 用同服务器其他个人模式账号发送消息后message mirai 会带 q2tgSkip=true
// 防止 bot 重新收到消息再转一圈回来重新转发或者重新响应命令
private onQqMessage = async (event: PrivateMessageEvent | GroupMessageEvent) => {
if ('friend' in event) return;
if (!event.message) return;
const messageMirai = event.message.find(it => it.type === 'mirai') as MiraiElem;
if (messageMirai) {
try {
const miraiData = JSON.parse(messageMirai.data);
if (miraiData.q2tgSkip) return true;
}
catch {
}
}
};
}

View File

@ -12,6 +12,7 @@ import BigInteger from 'big-integer';
import { getAvatarUrl } from '../utils/urls';
import convert from '../helpers/convert';
import { Pair } from '../models/Pair';
import env from '../models/env';
export default class {
private readonly log: Logger;
@ -25,6 +26,7 @@ export default class {
}
private onQqMessage = async (event: PrivateMessageEvent | GroupMessageEvent) => {
if (this.instance.workMode === 'personal') return;
if (event.message_type !== 'group') return;
const pair = this.instance.forwardPairs.find(event.group);
if (!pair) return;
@ -53,13 +55,16 @@ export default class {
this.log.error('找不到 sourceMessage');
return true;
}
try {
await this.sendQuote(pair, sourceMessage);
}
catch (e) {
this.log.error(e);
await event.reply(e.toString(), true);
}
setTimeout(async () => {
// 异步发送,为了让 /q 先到达
try {
await this.sendQuote(pair, sourceMessage);
}
catch (e) {
this.log.error(e);
await event.reply(e.toString(), true);
}
}, 50);
};
private onTelegramMessage = async (message: Api.Message) => {
@ -86,15 +91,20 @@ export default class {
this.log.error('找不到 sourceMessage');
return true;
}
try {
await this.sendQuote(pair, sourceMessage);
}
catch (e) {
this.log.error(e);
await message.reply({
message: e.toString(),
});
}
setTimeout(async () => {
try {
await this.sendQuote(pair, sourceMessage);
}
catch (e) {
this.log.error(e);
await message.reply({
message: e.toString(),
});
}
}, 50);
// 个人模式下,/q 这条消息不转发到 QQ怪话图只有自己可见
if (this.instance.workMode === 'personal') return true;
};
private async genQuote(message: Message) {
@ -153,7 +163,10 @@ export default class {
title: message.nick,
photo: { url: getAvatarUrl(message.qqSenderId) },
};
if (message.tgMessageText.includes('\n')) {
if (message.qqRoomId > 0) {
quoteMessage.text = message.tgMessageText;
}
else if (message.tgMessageText.includes('\n')) {
quoteMessage.text = message.tgMessageText.substring(message.tgMessageText.indexOf('\n')).trim();
}
else {
@ -268,7 +281,7 @@ export default class {
throw new Error('不支持的消息类型');
}
const res = await quotly({
botToken: process.env.TG_BOT_TOKEN,
botToken: env.TG_BOT_TOKEN,
type,
format,
backgroundColor,
@ -287,10 +300,13 @@ export default class {
const tgMessage = await pair.tg.sendMessage({
file: new CustomFile('quote.webp', image.length, undefined, image),
});
if (this.instance.workMode === 'personal') return;
const qqMessage = await pair.qq.sendMsg({
type: 'image',
file: image,
asface: true
asface: true,
});
await db.message.create({
data: {

View File

@ -9,6 +9,7 @@ import { WorkMode } from '../types/definitions';
import OicqClient from '../client/OicqClient';
import { md5Hex } from '../utils/hashing';
import Instance from '../models/Instance';
import env from '../models/env';
export default class SetupController {
private readonly setupService: SetupService;
@ -31,7 +32,7 @@ export default class SetupController {
return false;
}
if (message.text === '/setup' || message.text === '/start setup') {
if (message.message === '/setup' || message.message === '/start setup' || message.message === '/start') {
this.isInProgress = true;
await this.doSetup(Number(message.sender.id));
await this.finishSetup();
@ -105,7 +106,7 @@ export default class SetupController {
let signApi: string;
if (!process.env.SIGN_API) {
if (!env.SIGN_API) {
signApi = await this.setupService.waitForOwnerInput('请输入签名服务器地址', [
[Button.text('不需要签名服务器', true, true)],
]);
@ -114,7 +115,7 @@ export default class SetupController {
let signVer: string;
if (signApi && !process.env.SIGN_VER) {
if (signApi && !env.SIGN_VER) {
signVer = await this.setupService.waitForOwnerInput('请输入签名服务器版本', [
[Button.text('8.9.63', true, true),
Button.text('8.9.68', true, true)],

View File

@ -1,8 +1,9 @@
import { spawn } from 'child_process';
import env from '../models/env';
export default function tgsToGif(tgsPath: string) {
return new Promise(resolve => {
spawn(process.env.TGS_TO_GIF || 'tgs_to_gif', [tgsPath]).on('exit', () => {
spawn(env.TGS_TO_GIF, [tgsPath]).on('exit', () => {
resolve(tgsPath + '.gif');
});
});

View File

@ -19,6 +19,7 @@ import axios from 'axios';
import { CustomFile } from 'telegram/client/uploads';
import fsP from 'fs/promises';
import { file } from 'tmp-promise';
import env from '../models/env';
export default class {
private readonly log: Logger;
@ -196,21 +197,26 @@ export default class {
}
break;
case 'forward':
try {
const messages = await this.pair.qq.getForwardMsg(result.resId);
const hash = md5Hex(result.resId);
text += `转发的消息记录 ${process.env.CRV_API}/?hash=${hash}`;
// 传到 Cloudflare
axios.post(`${process.env.CRV_API}/add`, {
auth: process.env.CRV_KEY,
key: hash,
data: messages,
})
.then(data => this.log.trace('上传消息记录到 Cloudflare', data.data))
.catch(e => this.log.error('上传消息记录到 Cloudflare 失败', e));
if (env.CRV_API) {
try {
const messages = await this.pair.qq.getForwardMsg(result.resId);
const hash = md5Hex(result.resId);
text += `转发的消息记录 ${env.CRV_API}/?hash=${hash}`;
// 传到 Cloudflare
axios.post(`${env.CRV_API}/add`, {
auth: env.CRV_KEY,
key: hash,
data: messages,
})
.then(data => this.log.trace('上传消息记录到 Cloudflare', data.data))
.catch(e => this.log.error('上传消息记录到 Cloudflare 失败', e));
}
catch (e) {
text += '[转发多条消息(无法获取)]';
}
}
catch (e) {
text += '[转发多条消息(无法获取)]';
else {
text += '[转发多条消息]';
}
break;
}
@ -254,11 +260,11 @@ export default class {
ext: 'tgs',
mime: 'application/x-tgsticker',
} : await fileTypeFromFile(filePath);
if(!type){
if (!type) {
type = {
ext: 'bin',
mime: 'application/octet-stream',
}
};
}
let media: Api.TypeInputMedia;
if (['.webp', '.tgs'].includes(path.extname(filePath))) {

View File

@ -1,7 +1,6 @@
import path from 'path';
const DATA_DIR = process.env.DATA_DIR || path.resolve('./data');
import env from '../models/env';
// Wrap of path.join, add base DATA_DIR
export default (...paths: string[]) =>
path.join(DATA_DIR, ...paths);
path.join(env.DATA_DIR, ...paths);

View File

@ -27,7 +27,7 @@ export default class ForwardPairs {
const qq = oicq.getChat(Number(i.qqRoomId));
const tg = await tgBot.getChat(Number(i.tgChatId));
if (qq && tg) {
this.pairs.push(new Pair(qq, tg, i.id, i.joinNotice, i.poke, i.enable, i.disableQ2TG, i.disableTG2Q));
this.pairs.push(new Pair(qq, tg, i.id, i.flags));
}
}
catch (e) {
@ -50,7 +50,7 @@ export default class ForwardPairs {
instanceId: this.instanceId,
},
});
this.pairs.push(new Pair(qq, tg, dbEntry.id, true, true, true, false, false));
this.pairs.push(new Pair(qq, tg, dbEntry.id, dbEntry.flags));
return dbEntry;
}

View File

@ -23,6 +23,8 @@ import { QqBot } from '@prisma/client';
import StatusReportController from '../controllers/StatusReportController';
import HugController from '../controllers/HugController';
import QuotLyController from '../controllers/QuotLyController';
import MiraiSkipFilterController from '../controllers/MiraiSkipFilterController';
import env from './env';
export default class Instance {
private _owner = 0;
@ -32,6 +34,7 @@ export default class Instance {
private _userSessionId = 0;
private _qq: QqBot;
private _reportUrl: string;
private _flags: number;
private readonly log: Logger;
@ -53,6 +56,7 @@ export default class Instance {
private statusReportController: StatusReportController;
private hugController: HugController;
private quotLyController: QuotLyController;
private miraiSkipFilterController: MiraiSkipFilterController;
private constructor(public readonly id: number) {
this.log = getLogger(`Instance - ${this.id}`);
@ -83,6 +87,7 @@ export default class Instance {
this._isSetup = dbEntry.isSetup;
this._workMode = dbEntry.workMode;
this._reportUrl = dbEntry.reportUrl;
this._flags = dbEntry.flags;
}
private async init(botToken?: string) {
@ -91,7 +96,7 @@ export default class Instance {
this.tgBot = await Telegram.connect(this._botSessionId);
}
else {
const token = this.id === 0 ? process.env.TG_BOT_TOKEN : botToken;
const token = this.id === 0 ? env.TG_BOT_TOKEN : botToken;
if (!token) {
throw new Error('botToken 未指定');
}
@ -146,14 +151,12 @@ export default class Instance {
this.requestController = new RequestController(this, this.tgBot, this.oicq);
this.configController = new ConfigController(this, this.tgBot, this.oicq);
this.deleteMessageController = new DeleteMessageController(this, this.tgBot, this.oicq);
this.miraiSkipFilterController = new MiraiSkipFilterController(this, this.tgBot, this.oicq);
this.inChatCommandsController = new InChatCommandsController(this, this.tgBot, this.oicq);
if (this.workMode === 'group') {
this.hugController = new HugController(this, this.tgBot, this.oicq);
}
this.quotLyController = new QuotLyController(this, this.tgBot, this.oicq);
this.forwardController = new ForwardController(this, this.tgBot, this.oicq);
if (this.workMode === 'group') {
// 希望那个 /q 也被转发
this.quotLyController = new QuotLyController(this, this.tgBot, this.oicq);
this.hugController = new HugController(this, this.tgBot, this.oicq);
}
this.fileAndFlashPhotoController = new FileAndFlashPhotoController(this, this.tgBot, this.oicq);
})()
@ -253,6 +256,10 @@ export default class Instance {
return this._reportUrl;
}
get flags() {
return this._flags;
}
set owner(owner: number) {
this._owner = owner;
db.instance.update({
@ -307,10 +314,20 @@ export default class Instance {
}
set reportUrl(reportUrl: string) {
this._reportUrl = reportUrl;
db.instance.update({
data: { reportUrl },
where: { id: this.id },
})
.then(() => this.log.trace(reportUrl));
}
set flags(value) {
this._flags = value;
db.instance.update({
data: { flags: value },
where: { id: this.id },
})
.then(() => this.log.trace(value));
}
}

View File

@ -17,11 +17,7 @@ export class Pair {
public readonly qq: Friend | Group,
private _tg: TelegramChat,
public dbId: number,
private _joinNotice: boolean,
private _poke: boolean,
private _enable: boolean,
private _disableQ2TG: boolean,
private _disableTG2Q: boolean,
private _flags: number,
) {
}
@ -67,72 +63,16 @@ export class Pair {
.then(() => log.info(`出现了到超级群组的转换: ${value.id}`));
}
get joinNotice() {
return this._joinNotice;
get flags() {
return this._flags;
}
set joinNotice(value) {
this._joinNotice = value;
set flags(value) {
this._flags = value;
db.forwardPair
.update({
where: { id: this.dbId },
data: { joinNotice: value },
})
.then(() => 0);
}
get poke() {
return this._poke;
}
set poke(value) {
this._poke = value;
db.forwardPair
.update({
where: { id: this.dbId },
data: { poke: value },
})
.then(() => 0);
}
get enable() {
return this._enable;
}
set enable(value) {
this._enable = value;
db.forwardPair
.update({
where: { id: this.dbId },
data: { enable: value },
})
.then(() => 0);
}
get disableQ2TG() {
return this._disableQ2TG;
}
set disableQ2TG(value) {
this._disableQ2TG = value;
db.forwardPair
.update({
where: { id: this.dbId },
data: { disableQ2TG: value },
})
.then(() => 0);
}
get disableTG2Q() {
return this._disableTG2Q;
}
set disableTG2Q(value) {
this._disableTG2Q = value;
db.forwardPair
.update({
where: { id: this.dbId },
data: { disableTG2Q: value },
data: { flags: value },
})
.then(() => 0);
}

View File

@ -2,6 +2,7 @@ import { MemorySession } from 'telegram/sessions';
import db from './db';
import { AuthKey } from 'telegram/crypto/AuthKey';
import { getLogger, Logger } from 'log4js';
import env from './env';
const PASS = () => 0;
@ -19,19 +20,19 @@ export default class TelegramSession extends MemorySession {
async load() {
this.log.trace('load');
if (process.env.TG_INITIAL_DCID) {
this._dcId = Number(process.env.TG_INITIAL_DCID);
if (env.TG_INITIAL_DCID) {
this._dcId = env.TG_INITIAL_DCID;
}
if (process.env.TG_INITIAL_SERVER) {
this._serverAddress = process.env.TG_INITIAL_SERVER;
if (env.TG_INITIAL_SERVER) {
this._serverAddress = env.TG_INITIAL_SERVER;
}
if (!this._dbId) {
this.log.debug('Session 不存在,创建');
// 创建并返回
const newDbEntry = await db.session.create({
data: {
dcId: process.env.TG_INITIAL_DCID ? Number(process.env.TG_INITIAL_DCID) : null,
serverAddress: process.env.TG_INITIAL_SERVER,
dcId: env.TG_INITIAL_DCID,
serverAddress: env.TG_INITIAL_SERVER,
},
});
this._dbId = newDbEntry.id;

39
src/models/env.ts Normal file
View File

@ -0,0 +1,39 @@
import z from 'zod';
import path from 'path';
const configParsed = z.object({
DATA_DIR: z.string().default(path.resolve('./data')),
OICQ_LOG_LEVEL: z.enum(['trace', 'debug', 'info', 'warn', 'error', 'fatal', 'mark', 'off']).default('warn'),
FFMPEG_PATH: z.string().optional(),
FFPROBE_PATH: z.string().optional(),
SIGN_API: z.string().url().optional(),
SIGN_VER: z.string().optional(),
TG_API_ID: z.string().regex(/^\d+$/).transform(Number),
TG_API_HASH: z.string(),
TG_BOT_TOKEN: z.string(),
TG_CONNECTION: z.enum(['websocket', 'tcp']).default('tcp'),
TG_INITIAL_DCID: z.string().regex(/^\d+$/).transform(Number).optional(),
TG_INITIAL_SERVER: z.string().ip().optional(),
IPV6: z.string().transform((v) => ['true', '1', 'yes'].includes(v.toLowerCase())).default('false'),
PROXY_IP: z.string().ip().optional(),
PROXY_PORT: z.string().regex(/^\d+$/).transform(Number).optional(),
PROXY_USERNAME: z.string().optional(),
PROXY_PASSWORD: z.string().optional(),
TGS_TO_GIF: z.string().default('tgs_to_gif'),
CRV_API: z.string().url().optional(),
CRV_KEY: z.string().optional(),
ZINC_URL: z.string().url().optional(),
ZINC_USERNAME: z.string().optional(),
ZINC_PASSWORD: z.string().optional(),
BAIDU_APP_ID: z.string().optional(),
BAIDU_API_KEY: z.string().optional(),
BAIDU_SECRET_KEY: z.string().optional(),
DISABLE_FILE_UPLOAD_TIP: z.string().transform((v) => ['true', '1', 'yes'].includes(v.toLowerCase())).default('false'),
}).safeParse(process.env);
if (!configParsed.success) {
console.error('环境变量解析错误:', (configParsed as any).error);
process.exit(1);
}
export default configParsed.data;

View File

@ -7,15 +7,26 @@ import Instance from '../models/Instance';
import { Pair } from '../models/Pair';
import { consumer } from '../utils/highLevelFunces';
import forwardHelper from '../helpers/forwardHelper';
import flags from '../constants/flags';
export default class DeleteMessageService {
private readonly log: Logger;
private readonly lockIds = new Set<string>();
constructor(private readonly instance: Instance,
private readonly tgBot: Telegram) {
this.log = getLogger(`DeleteMessageService - ${instance.id}`);
}
private lock(lockId: string) {
if (this.lockIds.has(lockId)) {
this.log.debug('重复执行消息撤回', lockId);
return true;
}
this.lockIds.add(lockId);
setTimeout(() => this.lockIds.delete(lockId), 5000);
}
// 500ms 内只撤回一条消息,防止频繁导致一部分消息没有成功撤回。不过这样的话,会得不到返回的结果
private recallQqMessage = consumer(async (qq: Friend | Group, seq: number, rand: number, timeOrPktnum: number, pair: Pair, isOthersMsg: boolean, noSendError = false) => {
try {
@ -45,6 +56,7 @@ export default class DeleteMessageService {
*/
async telegramDeleteMessage(messageId: number, pair: Pair, isOthersMsg = false) {
// 删除的时候会返回记录
if (this.lock(`tg-${pair.tgId}-${messageId}`)) return;
try {
const messageInfo = await db.message.findFirst({
where: {
@ -55,6 +67,7 @@ export default class DeleteMessageService {
});
if (messageInfo) {
try {
if (this.lock(`qq-${pair.qqRoomId}-${messageInfo.seq}`)) return;
const mapQq = pair.instanceMapForTg[messageInfo.tgSenderId.toString()];
mapQq && this.recallQqMessage(mapQq, messageInfo.seq, Number(messageInfo.rand), messageInfo.pktnum, pair, false, true);
// 假如 mapQQ 是普通成员,机器人是管理员,上面撤回失败了也可以由机器人撤回
@ -134,6 +147,7 @@ export default class DeleteMessageService {
}
public async handleQqRecall(event: FriendRecallEvent | GroupRecallEvent, pair: Pair) {
if (this.lock(`qq-${pair.qqRoomId}-${event.seq}`)) return;
try {
const message = await db.message.findFirst({
where: {
@ -143,11 +157,20 @@ export default class DeleteMessageService {
instanceId: this.instance.id,
},
});
if (message) {
if (!message) return;
if (this.lock(`tg-${pair.tgId}-${message.tgMsgId}`)) return;
if ((pair.flags | this.instance.flags) & flags.NO_DELETE_MESSAGE) {
await pair.tg.editMessages({
message: message.tgMsgId,
text: `<del>${message.tgMessageText}</del>\n<i>此消息已删除</i>`,
parseMode: 'html',
});
}
else {
await pair.tg.deleteMessages(message.tgMsgId);
await db.message.delete({
where: { id: message.id },
});
await pair.tg.deleteMessages(message.tgMsgId);
}
}
catch (e) {

View File

@ -41,6 +41,7 @@ import random from '../utils/random';
import { escapeXml } from 'icqq/lib/common';
import Docker from 'dockerode';
import ReplyKeyboardHide = Api.ReplyKeyboardHide;
import env from '../models/env';
const NOT_CHAINABLE_ELEMENTS = ['flash', 'record', 'video', 'location', 'share', 'json', 'xml', 'poke'];
@ -55,18 +56,18 @@ export default class ForwardService {
private readonly tgBot: Telegram,
private readonly oicq: OicqClient) {
this.log = getLogger(`ForwardService - ${instance.id}`);
if (process.env.ZINC_URL) {
if (env.ZINC_URL) {
this.zincSearch = new ZincSearch({
url: process.env.ZINC_URL,
user: process.env.ZINC_USERNAME,
password: process.env.ZINC_PASSWORD,
url: env.ZINC_URL,
user: env.ZINC_USERNAME,
password: env.ZINC_PASSWORD,
});
}
if (process.env.BAIDU_APP_ID) {
if (env.BAIDU_APP_ID) {
this.speechClient = new AipSpeechClient(
process.env.BAIDU_APP_ID,
process.env.BAIDU_API_KEY,
process.env.BAIDU_SECRET_KEY,
env.BAIDU_APP_ID,
env.BAIDU_API_KEY,
env.BAIDU_SECRET_KEY,
);
}
if (oicq.signDockerId) {
@ -91,16 +92,6 @@ export default class ForwardService {
public async forwardFromQq(event: PrivateMessageEvent | GroupMessageEvent, pair: Pair) {
try {
const messageMirai = event.message.find(it => it.type === 'mirai') as MiraiElem;
if (messageMirai) {
try {
const miraiData = JSON.parse(messageMirai.data);
if (miraiData.q2tgSkip) return;
}
catch {
}
}
const tempFiles: FileResult[] = [];
let message = '', files: FileLike[] = [], buttons: ButtonLike[] = [], replyTo = 0;
let messageHeader = '', sender = '';
@ -120,22 +111,27 @@ export default class ForwardService {
}
};
const useForward = async (resId: string) => {
try {
const messages = await pair.qq.getForwardMsg(resId);
message = helper.generateForwardBrief(messages);
const hash = md5Hex(resId);
buttons.push(Button.url('📃查看', `${process.env.CRV_API}/?hash=${hash}`));
// 传到 Cloudflare
axios.post(`${process.env.CRV_API}/add`, {
auth: process.env.CRV_KEY,
key: hash,
data: messages,
})
.then(data => this.log.trace('上传消息记录到 Cloudflare', data.data))
.catch(e => this.log.error('上传消息记录到 Cloudflare 失败', e));
if(env.CRV_API) {
try {
const messages = await pair.qq.getForwardMsg(resId);
message = helper.generateForwardBrief(messages);
const hash = md5Hex(resId);
buttons.push(Button.url('📃查看', `${env.CRV_API}/?hash=${hash}`));
// 传到 Cloudflare
axios.post(`${env.CRV_API}/add`, {
auth: env.CRV_KEY,
key: hash,
data: messages,
})
.then(data => this.log.trace('上传消息记录到 Cloudflare', data.data))
.catch(e => this.log.error('上传消息记录到 Cloudflare 失败', e));
}
catch (e) {
message = '[<i>转发多条消息(无法获取)</i>]';
}
}
catch (e) {
message = '[<i>转发多条消息(无法获取)</i>]';
else {
message = '[<i>转发多条消息(未配置</i>]';
}
};
for (const elem of event.message) {
@ -350,6 +346,12 @@ export default class ForwardService {
}
}
if (this.instance.workMode === 'personal' && event.message_type === 'group' && event.atme && !replyTo) {
message += `\n<b>@${this.instance.userMe.usernames?.length ?
this.instance.userMe.usernames[0].username :
this.instance.userMe.username}</b>`;
}
// 发送消息
const messageToSend: SendMessageParams = {};
message && (messageToSend.message = message);
@ -389,7 +391,7 @@ export default class ForwardService {
const senderId = Number(message.senderId || message.sender?.id);
// 这条消息在 tg 中被回复的时候显示的
let brief = '', isSpoilerPhoto = false;
const messageHeader = helper.getUserDisplayName(message.sender) +
let messageHeader = helper.getUserDisplayName(message.sender) +
(message.forward ? ' 转发自 ' +
// 要是隐私设置了,应该会有这个,然后下面两个都获取不到
(message.fwdFrom?.fromName ||
@ -545,14 +547,14 @@ export default class ForwardService {
}
}
brief += '[文件]';
if (process.env.DISABLE_FILE_UPLOAD_TIP) {
if (env.DISABLE_FILE_UPLOAD_TIP) {
chain = [];
}
}
if (message.message && !isSpoilerPhoto) {
if (message.entities) {
const emojiEntities = message.entities.filter(it => it instanceof Api.MessageEntityCustomEmoji) as Api.MessageEntityCustomEmoji[];
const emojiEntities = (message.entities || []).filter(it => it instanceof Api.MessageEntityCustomEmoji) as Api.MessageEntityCustomEmoji[];
if (emojiEntities.length) {
const isMessageAllEmojis = _.sum(emojiEntities.map(it => it.length)) === message.message.length;
const newChain = [] as (string | MessageElem)[];
let messageLeft = message.message;
@ -568,11 +570,23 @@ export default class ForwardService {
});
}
chain.push(messageLeft, ...newChain);
brief += message.message;
}
// Q2TG Bot 转发的消息目前不会包含 custom emoji
else if (message.forward?.senderId?.eq?.(this.tgBot.me.id) && /^.*: ?$/.test(message.message.split('\n')[0])) {
// 复读了某一条来自 QQ 的消息 (Repeat as forward)
const originalMessage = message.message.includes('\n') ?
message.message.substring(message.message.indexOf('\n') + 1) : '';
chain.push(originalMessage);
brief += originalMessage;
messageHeader = helper.getUserDisplayName(message.sender) + ' 转发自 ' +
message.message.substring(0, message.message.indexOf(':')) + ': \n';
}
else {
chain.push(message.message);
brief += message.message;
}
brief += message.message;
}
// 处理回复
@ -705,10 +719,10 @@ export default class ForwardService {
nick: string,
}) {
if (!this.zincSearch) return;
const existsReq = await fetch(process.env.ZINC_URL + `/api/index/q2tg-${pairId}`, {
const existsReq = await fetch(env.ZINC_URL + `/api/index/q2tg-${pairId}`, {
method: 'HEAD',
headers: {
Authorization: 'Basic ' + Buffer.from(process.env.ZINC_USERNAME + ':' + process.env.ZINC_PASSWORD).toString('base64'),
Authorization: 'Basic ' + Buffer.from(env.ZINC_USERNAME + ':' + env.ZINC_PASSWORD).toString('base64'),
},
});
if (existsReq.status === 404) {

View File

@ -11,6 +11,7 @@ import db from '../models/db';
import { Friend, Group } from 'icqq';
import { format } from 'date-and-time';
import ZincSearch from 'zincsearch-node';
import env from '../models/env';
export default class InChatCommandsService {
private readonly log: Logger;
@ -20,11 +21,11 @@ export default class InChatCommandsService {
private readonly tgBot: Telegram,
private readonly oicq: OicqClient) {
this.log = getLogger(`InChatCommandsService - ${instance.id}`);
if (process.env.ZINC_URL) {
if (env.ZINC_URL) {
this.zincSearch = new ZincSearch({
url: process.env.ZINC_URL,
user: process.env.ZINC_USERNAME,
password: process.env.ZINC_PASSWORD,
url: env.ZINC_URL,
user: env.ZINC_USERNAME,
password: env.ZINC_PASSWORD,
});
}
}

45
src/utils/flagControl.ts Normal file
View File

@ -0,0 +1,45 @@
import flags from '../constants/flags';
import { Pair } from '../models/Pair';
import Instance from '../models/Instance';
const displayFlag = (flag: number) => {
const enabled = [];
for (const name in flags) {
const value = flags[name] as any as number;
if (flag & value) {
enabled.push(name);
}
}
return ['0b' + flag.toString(2), ...enabled].join('\n');
};
export const editFlags = async (params: string[], target: Pair | Instance) => {
if (!params.length) {
return displayFlag(target.flags);
}
if (params.length !== 2) return '参数格式错误';
let operand = Number(params[1]);
if (isNaN(operand)) {
operand = flags[params[1].toUpperCase()];
}
if (isNaN(operand)) return 'flag 格式错误';
switch (params[0]) {
case 'add':
case 'set':
target.flags |= operand;
break;
case 'rm':
case 'remove':
case 'del':
case 'delete':
target.flags &= ~operand;
break;
case 'put':
target.flags = operand;
break;
}
return displayFlag(target.flags);
};