refactor: extract download logic and clean up caption handling
This commit is contained in:
parent
1f5b4073e0
commit
8a8a21b155
@ -16,6 +16,12 @@ const composer = new Composer<Context>();
|
|||||||
const feature = composer.chatType('private');
|
const feature = composer.chatType('private');
|
||||||
const redis = getRedisInstance();
|
const redis = getRedisInstance();
|
||||||
|
|
||||||
|
type DownloadResult = {
|
||||||
|
caption?: string;
|
||||||
|
imagesUrls?: string[];
|
||||||
|
videoUrl?: string;
|
||||||
|
};
|
||||||
|
|
||||||
async function checkCacheAndReply(context: Context, url: string) {
|
async function checkCacheAndReply(context: Context, url: string) {
|
||||||
let contentMessageId: number | undefined;
|
let contentMessageId: number | undefined;
|
||||||
|
|
||||||
@ -30,11 +36,13 @@ async function checkCacheAndReply(context: Context, url: string) {
|
|||||||
if (cachedCaption) {
|
if (cachedCaption) {
|
||||||
const { entities, text } = formatCaption(cachedCaption);
|
const { entities, text } = formatCaption(cachedCaption);
|
||||||
|
|
||||||
if (text.trim().length)
|
if (text.trim().length) {
|
||||||
await context.reply(text, {
|
await context.reply(text, {
|
||||||
entities,
|
entities,
|
||||||
reply_parameters: contentMessageId ? { message_id: contentMessageId } : undefined,
|
reply_parameters: { message_id: contentMessageId },
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return { captionSent: true, contentMessageId };
|
return { captionSent: true, contentMessageId };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -47,6 +55,44 @@ function formatCaption(caption: string) {
|
|||||||
return fmt`${expandableBlockquote} ${code} ${cleanCaption} ${code} ${expandableBlockquote}`;
|
return fmt`${expandableBlockquote} ${code} ${cleanCaption} ${code} ${expandableBlockquote}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getDownloadData(
|
||||||
|
url: string,
|
||||||
|
opts: {
|
||||||
|
isInstagram: boolean;
|
||||||
|
isTikTok: boolean;
|
||||||
|
isYoutube: boolean;
|
||||||
|
},
|
||||||
|
): Promise<DownloadResult> {
|
||||||
|
const { isInstagram, isTikTok, isYoutube } = opts;
|
||||||
|
|
||||||
|
if (isTikTok) {
|
||||||
|
const result = await getTiktokDownloadUrl(url);
|
||||||
|
return {
|
||||||
|
caption: result.title,
|
||||||
|
imagesUrls: result.images,
|
||||||
|
videoUrl: result.play,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInstagram) {
|
||||||
|
const result = await getInstagramDownloadUrl(url);
|
||||||
|
return {
|
||||||
|
caption: result.caption,
|
||||||
|
imagesUrls: result.images,
|
||||||
|
videoUrl: result.play,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isYoutube) {
|
||||||
|
const result = await getYoutubeDownloadUrl(url);
|
||||||
|
return {
|
||||||
|
videoUrl: result.play,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
async function sendCaptionAndCache(
|
async function sendCaptionAndCache(
|
||||||
context: Context,
|
context: Context,
|
||||||
caption: string | undefined,
|
caption: string | undefined,
|
||||||
@ -58,11 +104,12 @@ async function sendCaptionAndCache(
|
|||||||
const { entities, text } = formatCaption(caption);
|
const { entities, text } = formatCaption(caption);
|
||||||
await redis.set(`caption:${url}`, caption, 'EX', TTL_URLS);
|
await redis.set(`caption:${url}`, caption, 'EX', TTL_URLS);
|
||||||
|
|
||||||
if (text.trim().length)
|
if (text.trim().length) {
|
||||||
await context.reply(text, {
|
await context.reply(text, {
|
||||||
entities,
|
entities,
|
||||||
reply_parameters: contentMessageId ? { message_id: contentMessageId } : undefined,
|
reply_parameters: contentMessageId ? { message_id: contentMessageId } : undefined,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendImages(
|
async function sendImages(
|
||||||
@ -70,7 +117,7 @@ async function sendImages(
|
|||||||
imagesUrls: string[],
|
imagesUrls: string[],
|
||||||
existingContentMessageId?: number,
|
existingContentMessageId?: number,
|
||||||
) {
|
) {
|
||||||
if (!imagesUrls?.length) return existingContentMessageId;
|
if (!imagesUrls.length) return existingContentMessageId;
|
||||||
|
|
||||||
const chunks = cluster(imagesUrls, 10);
|
const chunks = cluster(imagesUrls, 10);
|
||||||
let contentMessageId = existingContentMessageId;
|
let contentMessageId = existingContentMessageId;
|
||||||
@ -100,8 +147,8 @@ async function sendVideoAndCache(
|
|||||||
const { video, ...videoMessage } = await context.replyWithVideo(
|
const { video, ...videoMessage } = await context.replyWithVideo(
|
||||||
new InputFile({ url: videoUrl }),
|
new InputFile({ url: videoUrl }),
|
||||||
);
|
);
|
||||||
contentMessageId = videoMessage.message_id;
|
|
||||||
|
|
||||||
|
contentMessageId = videoMessage.message_id;
|
||||||
await redis.set(url, video.file_id, 'EX', TTL_URLS);
|
await redis.set(url, video.file_id, 'EX', TTL_URLS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,14 +162,13 @@ feature.on('message:text', logHandle('download-message'), async (context) => {
|
|||||||
const isInstagram = validateInstagramUrl(url);
|
const isInstagram = validateInstagramUrl(url);
|
||||||
const isYoutube = validateYoutubeUrl(url);
|
const isYoutube = validateYoutubeUrl(url);
|
||||||
|
|
||||||
const isSupportedService = isTikTok || isInstagram || isYoutube;
|
if (!isTikTok && !isInstagram && !isYoutube) {
|
||||||
|
|
||||||
if (!isSupportedService) {
|
|
||||||
return context.reply(context.t('err-invalid-url'));
|
return context.reply(context.t('err-invalid-url'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const cacheResult = await checkCacheAndReply(context, url);
|
const cacheResult = await checkCacheAndReply(context, url);
|
||||||
if (cacheResult.captionSent) return;
|
if (cacheResult.captionSent) return;
|
||||||
|
|
||||||
let contentMessageId = cacheResult.contentMessageId;
|
let contentMessageId = cacheResult.contentMessageId;
|
||||||
|
|
||||||
let imagesUrls: string[] | undefined;
|
let imagesUrls: string[] | undefined;
|
||||||
@ -130,20 +176,15 @@ feature.on('message:text', logHandle('download-message'), async (context) => {
|
|||||||
let caption: string | undefined;
|
let caption: string | undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isTikTok) {
|
const result = await getDownloadData(url, {
|
||||||
const result = await getTiktokDownloadUrl(url);
|
isInstagram,
|
||||||
imagesUrls = result.images;
|
isTikTok,
|
||||||
videoUrl = result.play;
|
isYoutube,
|
||||||
caption = result.title;
|
});
|
||||||
} else if (isInstagram) {
|
|
||||||
const result = await getInstagramDownloadUrl(url);
|
imagesUrls = result.imagesUrls;
|
||||||
imagesUrls = result.images;
|
videoUrl = result.videoUrl;
|
||||||
videoUrl = result.play;
|
caption = result.caption;
|
||||||
caption = result.caption;
|
|
||||||
} else if (isYoutube) {
|
|
||||||
const result = await getYoutubeDownloadUrl(url);
|
|
||||||
videoUrl = result.play;
|
|
||||||
}
|
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const message = (error as Error)?.message ?? String(error);
|
const message = (error as Error)?.message ?? String(error);
|
||||||
if (typeof message === 'string' && message.startsWith('err-')) {
|
if (typeof message === 'string' && message.startsWith('err-')) {
|
||||||
@ -158,9 +199,7 @@ feature.on('message:text', logHandle('download-message'), async (context) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contentMessageId = await sendImages(context, imagesUrls ?? [], contentMessageId);
|
contentMessageId = await sendImages(context, imagesUrls ?? [], contentMessageId);
|
||||||
|
|
||||||
contentMessageId = await sendVideoAndCache(context, videoUrl, url, contentMessageId);
|
contentMessageId = await sendVideoAndCache(context, videoUrl, url, contentMessageId);
|
||||||
|
|
||||||
await sendCaptionAndCache(context, caption, url, contentMessageId);
|
await sendCaptionAndCache(context, caption, url, contentMessageId);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user