fix download from tiktok

This commit is contained in:
vchikalkin 2025-09-12 14:31:53 +03:00
parent 9a3b3d6bad
commit 048779cfeb
4 changed files with 100 additions and 788 deletions

View File

@ -28,12 +28,13 @@
"@grammyjs/storage-redis": "^2.5.1",
"@grammyjs/types": "^3.21.0",
"@repo/typescript-config": "workspace:*",
"@tobyg74/tiktok-api-dl": "^1.3.4",
"@types/node": "catalog:",
"axios": "^1.12.0",
"grammy": "^1.37.0",
"ioredis": "^5.7.0",
"pino": "^9.9.0",
"pino-pretty": "^13.1.1",
"radashi": "^12.6.2",
"tsup": "^8.5.0",
"typescript": "catalog:",
"zod": "catalog:"

View File

@ -3,9 +3,10 @@ import { type Context } from '../context';
import { logHandle } from '../helpers/logging';
import { TTL_URLS } from '@/config/redis';
import { getRedisInstance } from '@/utils/redis';
import { getTiktokDownloadUrl } from '@/utils/tiktok';
import { validateTikTokUrl } from '@/utils/urls';
import { Downloader } from '@tobyg74/tiktok-api-dl';
import { Composer, InputFile } from 'grammy';
import { cluster } from 'radashi';
const composer = new Composer<Context>();
const feature = composer.chatType('private');
@ -24,27 +25,26 @@ feature.on('message:text', logHandle('download-message'), async (context) => {
return context.replyWithVideo(cachedFileId);
}
const { message, result } = await Downloader(url, { version: 'v3' });
if (message) {
throw new Error(message);
}
const videoUrl = result?.videoSD || result?.videoWatermark;
const imagesUrls = result?.images;
const { images: imagesUrls, play: videoUrl } = await getTiktokDownloadUrl(url);
if (!videoUrl && !imagesUrls?.length) {
return context.reply(context.t('err-invalid-download-urls'));
}
if (result?.type === 'video' && videoUrl) {
const { video } = await context.replyWithVideo(new InputFile({ url: videoUrl }));
return redis.set(url, video.file_id, 'EX', TTL_URLS);
if (imagesUrls?.length) {
const chunks = cluster(imagesUrls, 10);
for (const chunk of chunks) {
await context.replyWithMediaGroup(
chunk.map((imageUrl) => ({ media: imageUrl, type: 'photo' })),
);
}
return;
}
if (result?.type === 'image' && imagesUrls) {
return context.replyWithMediaGroup(
imagesUrls.map((image) => ({ media: image, type: 'photo' })),
);
if (videoUrl) {
const { video } = await context.replyWithVideo(new InputFile({ url: videoUrl }));
await redis.set(url, video.file_id, 'EX', TTL_URLS);
}
});

View File

@ -0,0 +1,45 @@
import axios from 'axios';
export type Data = {
ai_dynamic_cover: string;
anchors_extras: string;
collect_count: number;
comment_count: number;
commercial_video_info: string;
cover: string;
create_time: number;
digg_count: number;
download_count: number;
duration: number;
id: string;
images: string[];
is_ad: boolean;
item_comment_settings: number;
mentioned_users: string;
music: string;
origin_cover: string;
play: string;
play_count: number;
region: string;
share_count: number;
size: number;
title: string;
wm_size: number;
wmplay: string;
};
export type Root = {
code: number;
data: Data;
msg: string;
processed_time: number;
};
export async function getTiktokDownloadUrl(url: string) {
const res = await axios.get(`https://tikwm.com/api/?url=${encodeURIComponent(url)}`);
const { data } = res.data as Root;
if (!data) throw new Error('Invalid TikTok response');
return data;
}

810
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff