diff --git a/packages/core/src/base.ts b/packages/core/src/base.ts index f71fb4c..6d2961d 100644 --- a/packages/core/src/base.ts +++ b/packages/core/src/base.ts @@ -1,5 +1,5 @@ import {Got} from 'got'; -import { ZodObject } from 'zod'; +import {ZodObject} from 'zod'; export interface ExtractedInfo { error?: string; diff --git a/packages/core/src/downTikProvider.ts b/packages/core/src/downTikProvider.ts index 918cd81..7a00d85 100644 --- a/packages/core/src/downTikProvider.ts +++ b/packages/core/src/downTikProvider.ts @@ -1,7 +1,7 @@ import {BaseProvider, ExtractedInfo} from './base'; import {getFetch} from '../fetch'; import {matchCustomDownload, matchLink, runObfuscatedScript} from './utils'; -import { ZodObject } from 'zod'; +import {ZodObject} from 'zod'; /** * @class DownTikProvider diff --git a/packages/core/src/fasttokSaveProvider.ts b/packages/core/src/fasttokSaveProvider.ts new file mode 100644 index 0000000..ab736a8 --- /dev/null +++ b/packages/core/src/fasttokSaveProvider.ts @@ -0,0 +1,95 @@ +import {ZodObject} from 'zod'; +import {getFetch} from '../fetch'; +import {BaseProvider, ExtractedInfo, MaintenanceProvider} from './base'; + +/** + * @class FasttokSaveProvider + */ +export class FasttokSaveProvider extends BaseProvider { + /** + * Get provider resource name + * @return {string} + */ + public resourceName(): string { + return 'fasttoksave'; + } + + public client = getFetch('https://www.fasttoksave.com/'); + public maintenance?: MaintenanceProvider | undefined = undefined; + + /** + * Fetch tiktok video resource + * @param {string} url TikTok URL + * @return {Promise} + */ + async fetch(url: string): Promise { + const response = await this.client + .post('./en/wp-json/tiktok-downloader/v1/fetch', { + json: { + url, + }, + }) + .json<{ + code: number; + msg: string; + data?: { + author: { + nickname: string; + unique_id: string; + }; + comment_count: number; + play_count: number; + cover: string; + play: string; + music_info: { + author: string; + cover: string; + title: string; + }; + wmplay: string; + title: string; + duration: number; + }; + }>(); + + if (response.code === -1 || !response.data) { + return { + error: 'Video not found.', + }; + } + + return { + video: { + urls: [response.data.play, response.data.wmplay], + thumb: response.data.cover, + duration: (response.data.duration * 1000).toString(), + }, + music: { + url: '', + author: response.data.music_info.author, + cover: response.data.music_info.cover, + title: response.data.music_info.title, + }, + commentsCount: response.data.comment_count, + playsCount: response.data.play_count, + caption: response.data.title, + }; + } + + /** + * Extract contents from HTML raw + * @param {string} html HTML Raw + * @return {{}} + */ + public extract(html: string): ExtractedInfo | Promise { + return {}; + } + + /** + * Get params + * @return {undefined} + */ + public getParams(): ZodObject | undefined { + return undefined; + } +} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index a56d4ca..3e00bbe 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -12,6 +12,7 @@ import {DownTikProvider} from './downTikProvider'; // import {DDDTikProvider} from './dddTikProvider'; // import {DownloadOne} from './downloaderOneProvider'; import {NativeProvider} from './nativeProvider'; +import {FasttokSaveProvider} from './fasttokSaveProvider'; // import {GetVidTikProvider} from './getVidTikProvider'; export const Providers: BaseProvider[] = [ @@ -28,12 +29,12 @@ export const Providers: BaseProvider[] = [ // new DownloadOne(), new NativeProvider(), // new GetVidTikProvider(), + new FasttokSaveProvider(), ]; export const getRandomProvider = (): BaseProvider => { - const provider = Providers[Math.floor(Math.random() * Providers.length)] - while(provider.resourceName() === 'native') - { + const provider = Providers[Math.floor(Math.random() * Providers.length)]; + while (provider.resourceName() === 'native') { return getRandomProvider(); } diff --git a/packages/core/src/musicalyDownProvider.ts b/packages/core/src/musicalyDownProvider.ts index 937e7d4..7e999a8 100644 --- a/packages/core/src/musicalyDownProvider.ts +++ b/packages/core/src/musicalyDownProvider.ts @@ -1,7 +1,7 @@ import got from 'got'; import {getFetch} from '../fetch'; import {BaseProvider, ExtractedInfo} from './base'; -import { extractMusicalyDownImages, matchLink } from './utils'; +import {extractMusicalyDownImages, matchLink} from './utils'; /** * @class MusicalyDown @@ -29,7 +29,8 @@ export class MusicalyDown extends BaseProvider { Accept: '*/*', Referer: this.client.defaults.options.prefixUrl.toString(), Origin: this.client.defaults.options.prefixUrl.toString(), - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36' + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', }, }); @@ -48,20 +49,24 @@ export class MusicalyDown extends BaseProvider { Accept: '*/*', Referer: this.client.defaults.options.prefixUrl.toString(), Origin: this.client.defaults.options.prefixUrl.toString(), - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', }, }); - return this.extract(JSON.stringify({ - html: response.body, - headers: { - Cookie: res.headers['set-cookie']?.toString(), - Accept: '*/*', - Referer: this.client.defaults.options.prefixUrl.toString(), - Origin: this.client.defaults.options.prefixUrl.toString(), - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', - }, - })); + return this.extract( + JSON.stringify({ + html: response.body, + headers: { + Cookie: res.headers['set-cookie']?.toString(), + Accept: '*/*', + Referer: this.client.defaults.options.prefixUrl.toString(), + Origin: this.client.defaults.options.prefixUrl.toString(), + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', + }, + }), + ); } /** @@ -70,15 +75,15 @@ export class MusicalyDown extends BaseProvider { * @return {ExtractedInfo} */ public async extract(body: string): Promise { - const { html, headers } = JSON.parse(body); + const {html, headers} = JSON.parse(body); const urls = matchLink(html); - const matchedUrls = urls?.filter(url => /muscdn/gi.test(url)) ?? []; + const matchedUrls = urls?.filter((url) => /muscdn/gi.test(url)) ?? []; const musicalyDownUrls = extractMusicalyDownImages(html); const isSlide = musicalyDownUrls.length > 2; - const nonImages = matchedUrls.filter(u => u.includes('images')); - const image = matchedUrls.find(u => u.includes('images')); + const nonImages = matchedUrls.filter((u) => u.includes('images')); + const image = matchedUrls.find((u) => u.includes('images')); const info: ExtractedInfo = { video: { @@ -86,27 +91,33 @@ export class MusicalyDown extends BaseProvider { thumb: image, }, slides: isSlide ? musicalyDownUrls.slice(1) : undefined, - author: !isSlide ? { - thumb: musicalyDownUrls[0], - } : undefined, - music: !isSlide ? { - url: nonImages[0], - } : undefined, + author: !isSlide + ? { + thumb: musicalyDownUrls[0], + } + : undefined, + music: !isSlide + ? { + url: nonImages[0], + } + : undefined, }; if (isSlide) { const tokenRenderRegex = /data:\s*"([^"]+)"/; const token = tokenRenderRegex.exec(html)?.[1]; - const response = await got.post('https://render.muscdn.app/slider', { - form: { - data: token, - }, - headers, - }).json<{ - success: boolean; - url?: string; - }>(); + const response = await got + .post('https://render.muscdn.app/slider', { + form: { + data: token, + }, + headers, + }) + .json<{ + success: boolean; + url?: string; + }>(); if (response.success && response.url?.length) { info.video = { diff --git a/packages/core/src/nativeProvider.ts b/packages/core/src/nativeProvider.ts index 1023e38..f69f5c2 100644 --- a/packages/core/src/nativeProvider.ts +++ b/packages/core/src/nativeProvider.ts @@ -99,6 +99,6 @@ export class NativeProvider extends BaseProvider { public getParams(): z.ZodObject { return z.object({ 'user-agent': z.string().min(5), - }) + }); } } diff --git a/packages/core/src/saveFromProvider.ts b/packages/core/src/saveFromProvider.ts index c2dacac..0fd4f00 100644 --- a/packages/core/src/saveFromProvider.ts +++ b/packages/core/src/saveFromProvider.ts @@ -47,7 +47,8 @@ export class SaveFromProvider extends BaseProvider { headers: { Origin: 'https://en1.savefrom.net', Referer: 'https://en1.savefrom.net', - 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', + 'User-Agent': + 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', Cookies: responseFirst.headers['set-cookie']?.toString(), }, }); diff --git a/packages/core/src/saveTikProvider.ts b/packages/core/src/saveTikProvider.ts index 7883808..842222a 100644 --- a/packages/core/src/saveTikProvider.ts +++ b/packages/core/src/saveTikProvider.ts @@ -1,6 +1,6 @@ import {BaseProvider, ExtractedInfo} from './base'; import {getFetch} from '../fetch'; -import { ZodObject } from 'zod'; +import {ZodObject} from 'zod'; // import {matchLink, runObfuscatedReplaceEvalScript} from './utils'; /** @@ -32,8 +32,7 @@ export class SaveTikProvider extends BaseProvider { throwHttpErrors: false, }); - if (response.statusCode === 400) - { + if (response.statusCode === 400) { return { error: 'Video not found', }; @@ -72,10 +71,7 @@ export class SaveTikProvider extends BaseProvider { return { video: { - urls: [ - json.downloadUrl, - json.hdDownloadUrl, - ], + urls: [json.downloadUrl, json.hdDownloadUrl], title: json.postinfo.media_title, duration: json.duration.toString(), }, @@ -89,11 +85,11 @@ export class SaveTikProvider extends BaseProvider { sharesCount: json.stats.shareCount, playsCount: json.stats.playCount, commentsCount: json.stats.commentCount, - } + }; } catch { return { error: 'Video not found', - } + }; } } diff --git a/packages/core/src/snaptikProvider.ts b/packages/core/src/snaptikProvider.ts index b36ed6e..d10f9d3 100644 --- a/packages/core/src/snaptikProvider.ts +++ b/packages/core/src/snaptikProvider.ts @@ -1,4 +1,4 @@ -import { ZodObject } from 'zod'; +import {ZodObject} from 'zod'; import {getFetch} from '../fetch'; import {BaseProvider, ExtractedInfo, MaintenanceProvider} from './base'; import {matchLink, runObfuscatedReplaceEvalScript} from './utils'; @@ -16,7 +16,7 @@ export class SnaptikProvider extends BaseProvider { return 'snaptik'; } - public maintenance?: MaintenanceProvider | undefined = undefined + public maintenance?: MaintenanceProvider | undefined = undefined; /** * diff --git a/packages/core/src/tikDownProvider.ts b/packages/core/src/tikDownProvider.ts index 6b03003..fba35ca 100644 --- a/packages/core/src/tikDownProvider.ts +++ b/packages/core/src/tikDownProvider.ts @@ -1,6 +1,6 @@ import {BaseProvider, ExtractedInfo} from './base'; import {getFetch} from '../fetch'; -import { ZodObject } from 'zod'; +import {ZodObject} from 'zod'; /** * @class TikDownProvider @@ -32,8 +32,7 @@ export class TikDownProvider extends BaseProvider { }); const body = response.body; - if (/please double/gi.test(body)) - { + if (/please double/gi.test(body)) { return { error: 'Video not found', }; @@ -50,9 +49,9 @@ export class TikDownProvider extends BaseProvider { if (!responseVideo.body.length) { return { error: 'Couldnt find downloaded URL', - } + }; } - + return this.extract(responseVideo.body); } @@ -63,9 +62,14 @@ export class TikDownProvider extends BaseProvider { extract(html: string): ExtractedInfo { return { video: { - urls: [new URL(`./${html}`, this.client.defaults.options.prefixUrl.toString()).href], - } - } + urls: [ + new URL( + `./${html}`, + this.client.defaults.options.prefixUrl.toString(), + ).href, + ], + }, + }; } /** diff --git a/packages/core/src/tikmateProvider.ts b/packages/core/src/tikmateProvider.ts index 309547a..f6c5ad1 100644 --- a/packages/core/src/tikmateProvider.ts +++ b/packages/core/src/tikmateProvider.ts @@ -1,4 +1,4 @@ -import { ZodObject } from 'zod'; +import {ZodObject} from 'zod'; import {getFetch} from '../fetch'; import {BaseProvider, ExtractedInfo} from './base'; import {deObfuscate, matchLink} from './utils'; @@ -28,8 +28,9 @@ export class TikmateProvider extends BaseProvider { const response = await this.client('./', { headers: { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', - } + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', + }, }); const matchs = response.body.match( @@ -53,7 +54,8 @@ export class TikmateProvider extends BaseProvider { Origin: this.client.defaults.options.prefixUrl.toString(), Referer: this.client.defaults.options.prefixUrl.toString(), Cookie: cookies, - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', + 'User-Agent': + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', }, }); diff --git a/packages/core/src/ttDownloaderProvider.ts b/packages/core/src/ttDownloaderProvider.ts index 474eb40..5f327f1 100644 --- a/packages/core/src/ttDownloaderProvider.ts +++ b/packages/core/src/ttDownloaderProvider.ts @@ -1,4 +1,4 @@ -import { ZodObject } from 'zod'; +import {ZodObject} from 'zod'; import {getFetch} from '../fetch'; import {BaseProvider, ExtractedInfo} from './base'; import {matchLink} from './utils'; @@ -54,14 +54,16 @@ export class TTDownloader extends BaseProvider { const urls = matchLink(html); urls?.pop(); // remove 'https://snaptik.fans' - const musicUrl = urls?.find(u => /mp3/gi.test(u)); + const musicUrl = urls?.find((u) => /mp3/gi.test(u)); return { video: { - urls: urls?.filter(u => u !== musicUrl) ?? [], + urls: urls?.filter((u) => u !== musicUrl) ?? [], }, - music: musicUrl ? { - url: musicUrl, - } : undefined, + music: musicUrl + ? { + url: musicUrl, + } + : undefined, }; } diff --git a/packages/core/src/utils/extractor.ts b/packages/core/src/utils/extractor.ts index bd5cac7..51f24b5 100644 --- a/packages/core/src/utils/extractor.ts +++ b/packages/core/src/utils/extractor.ts @@ -18,11 +18,11 @@ export const matchTikTokData = (html: string): string => { export const runObfuscatedReplaceEvalScript = (jsCode: string): string => { return runObfuscatedScript(jsCode.replace('eval', 'module.exports = ')); -} +}; export const extractMusicalyDownImages = (html: string): string[] => { - const regex = /]+src="(https[^"]+)"/gi; - return [...html.matchAll(regex)].map(m => m[1]); + const regex = /]+src="(https[^"]+)"/gi; + return [...html.matchAll(regex)].map((m) => m[1]); }; export const runObfuscatedScript = (jsCode: string): string => { @@ -92,9 +92,7 @@ export const matchCustomDownload = ( export const deObfuscateSaveFromScript = (scriptContent: string): string => { const safeScript = - 'let result = ' + - scriptContent - .replace(/\/\*js\-response\*\//gi, ''); + 'let result = ' + scriptContent.replace(/\/\*js\-response\*\//gi, ''); const vm = new NodeVM({ compiler: 'javascript',