Replace grammy with telegraf for Telegram bot integration; update environment variable for API root and implement message handling for media responses.

This commit is contained in:
vchikalkin 2025-08-14 12:11:06 +03:00
parent a941b7ed36
commit b744686d08
5 changed files with 127 additions and 28 deletions

15
docker-compose.api.yml Normal file
View File

@ -0,0 +1,15 @@
services:
telegram-bot-api:
env_file:
- .env
image: aiogram/telegram-bot-api:latest
# environment:
# TELEGRAM_API_ID: "<api-id>"
# TELEGRAM_API_HASH: "<api-hash>"
volumes:
- telegram-bot-api-data:/var/lib/telegram-bot-api
ports:
- "8081:8081"
volumes:
telegram-bot-api-data:

View File

@ -15,7 +15,7 @@
"dependencies": {
"@tobyg74/tiktok-api-dl": "^1.3.4",
"@types/node": "^24.2.1",
"grammy": "^1.37.0",
"telegraf": "^4.16.3",
"tsup": "^8.5.0",
"zod": "^4.0.17"
},

92
pnpm-lock.yaml generated
View File

@ -14,9 +14,9 @@ importers:
'@types/node':
specifier: ^24.2.1
version: 24.2.1
grammy:
specifier: ^1.37.0
version: 1.37.0
telegraf:
specifier: ^4.16.3
version: 4.16.3
tsup:
specifier: ^8.5.0
version: 8.5.0(jiti@2.5.1)(tsx@4.20.4)(typescript@5.9.2)(yaml@2.8.1)
@ -380,9 +380,6 @@ packages:
'@fastify/busboy@3.1.1':
resolution: {integrity: sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==}
'@grammyjs/types@3.21.0':
resolution: {integrity: sha512-IMj0EpmglPCICuyfGRx4ENKPSuzS2xMSoPgSPzHC6FtnWKDEmJLBP/GbPv/h3TAeb27txqxm/BUld+gbJk6ccQ==}
'@graphql-eslint/eslint-plugin@4.4.0':
resolution: {integrity: sha512-dhW6fpk3Souuaphhc38uMAGCcgKMgtCJWFygIKODw/Kns43wiQqRPVay0aNFY1JBx3aevn4KPT/BCOdm6HNncA==}
engines: {node: '>=18'}
@ -699,6 +696,9 @@ packages:
peerDependencies:
eslint: '>=9.0.0'
'@telegraf/types@7.1.0':
resolution: {integrity: sha512-kGevOIbpMcIlCDeorKGpwZmdH7kHbqlk/Yj6dEpJMKEQw5lk0KVQY0OLXaCswy8GqlIVLd5625OB+rAntP9xVw==}
'@theguild/federation-composition@0.19.1':
resolution: {integrity: sha512-E4kllHSRYh+FsY0VR+fwl0rmWhDV8xUgWawLZTXmy15nCWQwj0BDsoEpdEXjPh7xes+75cRaeJcSbZ4jkBuSdg==}
engines: {node: '>=18'}
@ -1082,6 +1082,15 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
buffer-alloc-unsafe@1.1.0:
resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==}
buffer-alloc@1.2.0:
resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==}
buffer-fill@1.0.0:
resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==}
buffer@5.7.1:
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
@ -1977,10 +1986,6 @@ packages:
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
grammy@1.37.0:
resolution: {integrity: sha512-UBGqGKux+49t1vm7n/m1BaeXIYbWESXjhaFxG+9z33VTLSHdQJwIOmpNKmZSaoBlSWbAJE+IJZ30X7RfWvEolA==}
engines: {node: ^12.20.0 || >=14.13.1}
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
@ -2469,6 +2474,10 @@ packages:
mlly@1.7.4:
resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==}
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@ -2586,6 +2595,10 @@ packages:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
p-timeout@4.1.0:
resolution: {integrity: sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==}
engines: {node: '>=10'}
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
@ -2841,6 +2854,9 @@ packages:
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
safe-compare@1.1.4:
resolution: {integrity: sha512-b9wZ986HHCo/HbKrRpBJb2kqXMK9CEWIE1egeEvZsYn69ay3kdfl9nG3RyOcR+jInTDf7a86WQ1d4VJX7goSSQ==}
safe-push-apply@1.0.0:
resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
engines: {node: '>= 0.4'}
@ -2856,6 +2872,10 @@ packages:
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
sandwich-stream@2.0.2:
resolution: {integrity: sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ==}
engines: {node: '>= 0.10'}
saxes@6.0.0:
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
engines: {node: '>=v12.22.7'}
@ -3069,6 +3089,11 @@ packages:
resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
engines: {node: '>=6'}
telegraf@4.16.3:
resolution: {integrity: sha512-yjEu2NwkHlXu0OARWoNhJlIjX09dRktiMQFsM678BAH/PEPVwctzL67+tvXqLCRQQvm3SDtki2saGO9hLlz68w==}
engines: {node: ^12.20.0 || >=14.13.1}
hasBin: true
thenify-all@1.6.0:
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
engines: {node: '>=0.8'}
@ -3699,8 +3724,6 @@ snapshots:
'@fastify/busboy@3.1.1': {}
'@grammyjs/types@3.21.0': {}
'@graphql-eslint/eslint-plugin@4.4.0(@types/node@24.2.1)(eslint@9.33.0(jiti@2.5.1))(graphql@16.11.0)(typescript@5.9.2)':
dependencies:
'@graphql-tools/code-file-loader': 8.1.22(graphql@16.11.0)
@ -4077,6 +4100,8 @@ snapshots:
- supports-color
- typescript
'@telegraf/types@7.1.0': {}
'@theguild/federation-composition@0.19.1(graphql@16.11.0)':
dependencies:
constant-case: 3.0.4
@ -4517,6 +4542,15 @@ snapshots:
node-releases: 2.0.19
update-browserslist-db: 1.1.3(browserslist@4.25.2)
buffer-alloc-unsafe@1.1.0: {}
buffer-alloc@1.2.0:
dependencies:
buffer-alloc-unsafe: 1.1.0
buffer-fill: 1.0.0
buffer-fill@1.0.0: {}
buffer@5.7.1:
dependencies:
base64-js: 1.5.1
@ -5676,16 +5710,6 @@ snapshots:
graceful-fs@4.2.11: {}
grammy@1.37.0:
dependencies:
'@grammyjs/types': 3.21.0
abort-controller: 3.0.0
debug: 4.4.1
node-fetch: 2.7.0
transitivePeerDependencies:
- encoding
- supports-color
graphemer@1.4.0: {}
graphql-config@5.1.5(@types/node@24.2.1)(graphql@16.11.0)(typescript@5.9.2):
@ -6160,6 +6184,8 @@ snapshots:
pkg-types: 1.3.1
ufo: 1.6.1
mri@1.2.0: {}
ms@2.1.3: {}
mz@2.7.0:
@ -6282,6 +6308,8 @@ snapshots:
dependencies:
p-limit: 3.1.0
p-timeout@4.1.0: {}
package-json-from-dist@1.0.1: {}
parent-module@1.0.1:
@ -6559,6 +6587,10 @@ snapshots:
safe-buffer@5.2.1: {}
safe-compare@1.1.4:
dependencies:
buffer-alloc: 1.2.0
safe-push-apply@1.0.0:
dependencies:
es-errors: 1.3.0
@ -6574,6 +6606,8 @@ snapshots:
safer-buffer@2.1.2: {}
sandwich-stream@2.0.2: {}
saxes@6.0.0:
dependencies:
xmlchars: 2.2.0
@ -6838,6 +6872,20 @@ snapshots:
inherits: 2.0.4
readable-stream: 3.6.2
telegraf@4.16.3:
dependencies:
'@telegraf/types': 7.1.0
abort-controller: 3.0.0
debug: 4.4.1
mri: 1.2.0
node-fetch: 2.7.0
p-timeout: 4.1.0
safe-compare: 1.1.4
sandwich-stream: 2.0.2
transitivePeerDependencies:
- encoding
- supports-color
thenify-all@1.6.0:
dependencies:
thenify: 3.3.1

View File

@ -3,7 +3,7 @@ import { z } from 'zod';
export const envSchema = z.object({
BOT_TOKEN: z.string(),
BOT_URL: z.string(),
TELEGRAM_API_ROOT: z.string(),
});
export const env = envSchema.parse(process.env);

View File

@ -1,5 +1,41 @@
import Tiktok from '@tobyg74/tiktok-api-dl';
import { env } from './config/env';
import { Downloader } from '@tobyg74/tiktok-api-dl';
import { Telegraf as Bot } from 'telegraf';
import { message } from 'telegraf/filters';
Tiktok.Downloader(url_pictures, {
version: 'v3', // "v1" | "v2" | "v3"
}).then((result) => console.log(result));
const bot = new Bot(env.BOT_TOKEN, {
telegram: {
apiRoot: env.TELEGRAM_API_ROOT,
},
});
bot.on(message('text'), async (ctx) => {
try {
const url = ctx.message.text;
const { result, message } = await Downloader(url, {
version: 'v3',
});
if (message) throw new Error(message);
const videoUrl = result?.videoHD || result?.videoSD || result?.videoWatermark;
const imagesUrls = result?.images;
if (result?.type === 'video' && videoUrl) {
return ctx.replyWithVideo({
url: videoUrl,
});
}
if (result?.type === 'image' && imagesUrls) {
return ctx.replyWithMediaGroup(imagesUrls.map((image) => ({ media: image, type: 'photo' })));
}
} catch (error) {
const err_ = error as Error;
return ctx.reply(err_.message);
}
});
bot.launch();