diff --git a/api/download.ts b/api/download.ts index abd1e5c..1c4394b 100644 --- a/api/download.ts +++ b/api/download.ts @@ -1,7 +1,6 @@ import type {VercelRequest, VercelResponse} from '@vercel/node'; import ow from 'ow'; - -import {snaptik} from '../lib'; +import {getRandomProvider} from '../lib/providers'; export default async (req: VercelRequest, res: VercelResponse) => { try { @@ -9,7 +8,7 @@ export default async (req: VercelRequest, res: VercelResponse) => { 'url': ow.string.url, })); - const result = await snaptik.fetchDownloadPage(req.query.url); + const result = await getRandomProvider().fetch(req.query.url); return res.status(200).json(result); } catch (e) { return res.status(400).json({ diff --git a/lib/decorators/handleException.ts b/lib/decorators/handleException.ts new file mode 100644 index 0000000..8814340 --- /dev/null +++ b/lib/decorators/handleException.ts @@ -0,0 +1,19 @@ +/** + * Decorator to handle exception. + * @return {Function} + */ +export const handleException = (): Function => { + return function( + target: any, + _: string, + descriptor: PropertyDescriptor) { + const oldValue = descriptor.value; + descriptor.value = (...args: any) => { + try { + return oldValue.apply(target, args); + } catch (err) { + return {'error': (err as Error).message}; + } + }; + }; +}; diff --git a/lib/index.ts b/lib/index.ts index de8c844..957e76b 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,5 +1,5 @@ export * from './fetch'; export * from './config'; -export * from './snaptik'; +export * from './providers'; export * from './tiktok'; export * from './transformer'; diff --git a/lib/providers/baseProvider.ts b/lib/providers/baseProvider.ts new file mode 100644 index 0000000..a02c2b1 --- /dev/null +++ b/lib/providers/baseProvider.ts @@ -0,0 +1,16 @@ +export interface ExtractedInfo { + error?: string; + result?: { + thumb?: string; + urls: string[]; + } +}; + +/** + * @class BaseProvider + */ +export abstract class BaseProvider { + abstract resourceName(): string; + abstract fetch(url: string): Promise; + abstract extract(html: string): ExtractedInfo; +}; diff --git a/lib/providers/index.ts b/lib/providers/index.ts new file mode 100644 index 0000000..01b52e8 --- /dev/null +++ b/lib/providers/index.ts @@ -0,0 +1,9 @@ +import {SnaptikProvider} from './snaptikProvider'; + +export const Providers = [ + new SnaptikProvider(), +]; + +export const getRandomProvider = () => Providers[ + Math.floor(Math.random() * Providers.length) +]; diff --git a/lib/snaptik.ts b/lib/providers/snaptikProvider.ts similarity index 57% rename from lib/snaptik.ts rename to lib/providers/snaptikProvider.ts index f2801fb..a91a4c6 100644 --- a/lib/snaptik.ts +++ b/lib/providers/snaptikProvider.ts @@ -1,41 +1,46 @@ -import {snaptikFetch} from '.'; - -interface Extracted { - error?: string; - result?: { - thumb: string; - urls: string[]; - } -} +import {snaptikFetch} from '..'; +import {handleException} from '../decorators/handleException'; +import {BaseProvider, ExtractedInfo} from './baseProvider'; /** - * @class Snaptik + * @class SnaptikProvider */ -class Snaptik { +export class SnaptikProvider extends BaseProvider { + /** + * + * @return {string} + */ + public resourceName(): string { + return 'snaptik'; + } + /** * - * @param {string} url - TikTok URL - * @return {Extracted} + * @param {string} url - TikTok Video URL + * @return {Promise} */ - async fetchDownloadPage(url: string) { + @handleException() + public async fetch(url: string): Promise { const response = await snaptikFetch('./abc.php', { searchParams: { 'url': url, }, }); - return this.extractInfo(response.body); + return this.extract(response.body); } + + /** - * - * @param {string} html - HTML Raw - * @return {Extracted} + * Extract information from raw html + * @param {string} html - Raw HTML + * @return {ExtractedInfo} */ - private extractInfo(html: string): Extracted { + extract(html: string): ExtractedInfo { if (/error/gi.test(html)) { return { 'error': html.split('\'') - .find((x) => /(((url)? error))|could)/gi.test(x)), + .find((x) => /(((url)? error)|could)/gi.test(x)), }; } else { // only match script tag @@ -58,6 +63,4 @@ class Snaptik { } } } -} - -export const snaptik = new Snaptik(); +}; diff --git a/tsconfig.json b/tsconfig.json index ff4fd9b..90072ed 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,8 @@ "skipLibCheck": true, "skipDefaultLibCheck": true, "forceConsistentCasingInFileNames": true, - "noImplicitAny": true + "noImplicitAny": true, + "experimentalDecorators": true }, "exclude": ["node_modules", "dist"] } \ No newline at end of file