chore: fix code with applied eslint rules

This commit is contained in:
vchikalkin 2026-01-14 12:23:58 +03:00
parent 05852eff40
commit ce78952fec
7 changed files with 58 additions and 52 deletions

View File

@ -11,6 +11,7 @@ export default [
'@typescript-eslint/naming-convention': 'off', '@typescript-eslint/naming-convention': 'off',
'unicorn/prevent-abbreviations': 'off', 'unicorn/prevent-abbreviations': 'off',
'canonical/id-match': 'off', 'canonical/id-match': 'off',
'id-length': 'off',
}, },
}, },
]; ];

View File

@ -2,13 +2,13 @@
import { type Context } from '../context'; import { type Context } from '../context';
import { logHandle } from '../helpers/logging'; import { logHandle } from '../helpers/logging';
import { TTL_URLS } from '@/config/redis'; import { TTL_URLS } from '@/config/redis';
import { getInstagramDownloadUrl } from '@/utils/instagram';
import { getRedisInstance } from '@/utils/redis'; import { getRedisInstance } from '@/utils/redis';
import { getTiktokDownloadUrl } from '@/utils/tiktok'; import { getTiktokDownloadUrl } from '@/utils/tiktok';
import { getInstagramDownloadUrl } from '@/utils/instagram'; import { validateInstagramUrl, validateTikTokUrl, validateYoutubeUrl } from '@/utils/urls';
import { validateTikTokUrl, validateInstagramUrl, validateYoutubeUrl } from '@/utils/urls'; import { getYoutubeDownloadUrl } from '@/utils/youtube';
import { Composer, InputFile } from 'grammy'; import { Composer, InputFile } from 'grammy';
import { cluster } from 'radashi'; import { cluster } from 'radashi';
import { getYoutubeDownloadUrl } from '@/utils/youtube';
const composer = new Composer<Context>(); const composer = new Composer<Context>();
const feature = composer.chatType('private'); const feature = composer.chatType('private');
@ -22,7 +22,9 @@ 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);
if (!isTikTok && !isInstagram && !isYoutube) { const isSupportedService = isTikTok || isInstagram || isYoutube;
if (!isSupportedService) {
return context.reply(context.t('err-invalid-url')); return context.reply(context.t('err-invalid-url'));
} }
@ -47,8 +49,9 @@ feature.on('message:text', logHandle('download-message'), async (context) => {
const result = await getYoutubeDownloadUrl(url); const result = await getYoutubeDownloadUrl(url);
videoUrl = result.play; videoUrl = result.play;
} }
} catch (err: any) { } catch (error_: unknown) {
const message = err?.message ?? String(err); const error = error_ as Error;
const message = error?.message ?? String(error);
if (typeof message === 'string' && message.startsWith('err-')) { if (typeof message === 'string' && message.startsWith('err-')) {
return context.reply(context.t(message)); return context.reply(context.t(message));
} }

View File

@ -3,6 +3,7 @@ export const TIKTOK_URL_REGEX =
/https:\/\/(?:m|t|www|vm|vt|lite)?\.?tiktok\.com\/(.*\b(?:(?:usr|v|embed|user|video|photo)\/|\?shareId=|&item_id=)(\d+)|\w+)/u; /https:\/\/(?:m|t|www|vm|vt|lite)?\.?tiktok\.com\/(.*\b(?:(?:usr|v|embed|user|video|photo)\/|\?shareId=|&item_id=)(\d+)|\w+)/u;
export const INSTAGRAM_URL_REGEX = export const INSTAGRAM_URL_REGEX =
/https?:\/\/(www\.)?instagram\.com\/(p|reel|tv|stories)\/([a-zA-Z0-9_-]+)(\/)?(\?utm_source=ig_web_copy_link&igshid=[a-z0-9]+)?/u; /https?:\/\/(www\.)?instagram\.com\/(p|reel|tv|stories)\/([\w-]+)(\/)?(\?utm_source=ig_web_copy_link&igshid=[a-z0-9]+)?/u;
export const YOUTUBE_URL_REGEX = /(youtu.*be.*)\/(watch\?v=|embed\/|v|shorts|)(.*?((?=[&#?])|$))/u; export const YOUTUBE_URL_REGEX =
/(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:watch\?v=|embed\/|v\/|shorts\/))([\w-]{11})(?:[?&]\S*)?/u;

View File

@ -1,26 +1,26 @@
import axios from 'axios'; import axios from 'axios';
export interface Root { export type AuthorInfo = {
type: string;
id: number;
url: string;
username: string;
mediaUrls: string[];
carouselItems: CarouselItem[];
authorInfo: AuthorInfo;
}
export interface CarouselItem {
url: string;
type: string;
}
export interface AuthorInfo {
id: number;
username: string;
nickname: string;
avatar: string; avatar: string;
} id: number;
nickname: string;
username: string;
};
export type CarouselItem = {
type: string;
url: string;
};
export type Root = {
authorInfo: AuthorInfo;
carouselItems: CarouselItem[];
id: number;
mediaUrls: string[];
type: string;
url: string;
username: string;
};
export async function getInstagramDownloadUrl(url: string) { export async function getInstagramDownloadUrl(url: string) {
const { data } = await axios.post<Root>('https://thesocialcat.com/api/instagram-download', { const { data } = await axios.post<Root>('https://thesocialcat.com/api/instagram-download', {
@ -33,8 +33,8 @@ export async function getInstagramDownloadUrl(url: string) {
if (isVideo) { if (isVideo) {
return { return {
play: data.mediaUrls.at(0),
images: [], images: [],
play: data.mediaUrls.at(0),
}; };
} }

View File

@ -1,13 +1,13 @@
import { INSTAGRAM_URL_REGEX, TIKTOK_URL_REGEX, YOUTUBE_URL_REGEX } from '@/constants/regex'; import { INSTAGRAM_URL_REGEX, TIKTOK_URL_REGEX, YOUTUBE_URL_REGEX } from '@/constants/regex';
export function validateTikTokUrl(url: string) {
return TIKTOK_URL_REGEX.test(url);
}
export function validateInstagramUrl(url: string) { export function validateInstagramUrl(url: string) {
return INSTAGRAM_URL_REGEX.test(url); return INSTAGRAM_URL_REGEX.test(url);
} }
export function validateTikTokUrl(url: string) {
return TIKTOK_URL_REGEX.test(url);
}
export function validateYoutubeUrl(url: string) { export function validateYoutubeUrl(url: string) {
return YOUTUBE_URL_REGEX.test(url); return YOUTUBE_URL_REGEX.test(url);
} }

View File

@ -24,32 +24,32 @@ const headers = {
const client = wrapper( const client = wrapper(
axios.create({ axios.create({
headers,
jar, jar,
withCredentials: true, withCredentials: true,
headers,
}), }),
); );
export interface Media { export type DownloadRoot = {
type: string;
quality: string;
extension: string;
fileSize: number;
}
export interface InfoRoot {
title: string;
thumbnail: string;
duration: number; duration: number;
medias: Media[]; filename: string;
}
export interface DownloadRoot {
status: string; status: string;
url: string; url: string;
filename: string; };
export type InfoRoot = {
duration: number; duration: number;
} medias: Media[];
thumbnail: string;
title: string;
};
export type Media = {
extension: string;
fileSize: number;
quality: string;
type: string;
};
const qualityOrder = ['144p', '240p', '360p', '480p', '1080p', '720p'].reverse(); const qualityOrder = ['144p', '240p', '360p', '480p', '1080p', '720p'].reverse();
@ -66,7 +66,8 @@ export async function getYoutubeDownloadUrl(url: string) {
); );
if (!infoData?.medias.length) throw new Error('err-invalid-youtube-response'); if (!infoData?.medias.length) throw new Error('err-invalid-youtube-response');
if (infoData.duration > MAX_VIDEO_DURATION_SECONDS) throw new Error('err-youtube-duration-exceeded'); if (infoData.duration > MAX_VIDEO_DURATION_SECONDS)
throw new Error('err-youtube-duration-exceeded');
let quality: string | undefined; let quality: string | undefined;