fix(provider): fixed musically down token match

This commit is contained in:
hansputera
2021-11-08 10:33:52 +07:00
parent 5def3ade4d
commit 7296cc2385
13 changed files with 138 additions and 79 deletions

View File

@@ -11,7 +11,8 @@ export default async (req: VercelRequest, res: VercelResponse) => {
'type': ow.optional.string.validate((v) => ({
'validator': typeof v === 'string' &&
providersType.includes(v.toLowerCase()),
'message': 'Invalid Provider',
'message': 'Invalid Provider, available provider is: ' +
Providers.map((x) => x.resourceName()).join(', '),
})),
}));

View File

@@ -1,22 +1,30 @@
/**
* Decorator to handle exception.
* @return {Function}
* @param {any} target
* @param {string} _
* @param {PropertyDescriptor} descriptor
* @return {void}
*/
export const handleException = (): Function => {
return function(
target: any,
_: string,
descriptor: PropertyDescriptor) {
const oldValue = descriptor.value;
descriptor.value = (...args: any) => {
export const handleException = <T extends Function>
(target: object, _: string, descriptor: TypedPropertyDescriptor<T>):
TypedPropertyDescriptor<T> | void => {
return {
configurable: true,
get(this: T): T {
try {
return oldValue.apply(target, args);
const bound: T = descriptor.value?.bind(this);
Object.defineProperty(this, _, {
value: bound,
configurable: true,
writable: true,
});
return bound;
} catch (err) {
return {
'error': (err as Error).message,
'error.stack': (err as Error).stack as string,
};
} as unknown as T;
}
};
},
};
};

View File

@@ -1,4 +1,4 @@
import got from 'got';
import got, {ExtendOptions} from 'got';
import {tiktokBase, tiktokTBase} from './config';
export const TFetch = got.extend({
@@ -11,17 +11,10 @@ export const fetch = got.extend({
dnsCache: true,
});
export const snaptikFetch = got.extend({
prefixUrl: 'https://snaptik.app/en',
dnsCache: true,
});
export const tikmateFetch = got.extend({
prefixUrl: 'https://tikmate.online',
dnsCache: true,
});
export const musicalyFetch = got.extend({
prefixUrl: 'https://musicaldown.com/id',
dnsCache: true,
});
export const getFetch = (baseUrl: string, options?: ExtendOptions) =>
got.extend({
prefixUrl: baseUrl,
dnsCache: true,
...options,
});

View File

@@ -1,3 +1,5 @@
import {Got} from 'got';
export interface ExtractedInfo {
error?: string;
result?: {
@@ -10,8 +12,8 @@ export interface ExtractedInfo {
* @class BaseProvider
*/
export abstract class BaseProvider {
abstract client: Got;
abstract resourceName(): string;
abstract fetch(url: string): Promise<ExtractedInfo>;
abstract extract(html: string): ExtractedInfo;
abstract getURI(): string;
};

View File

@@ -3,11 +3,13 @@ import {MusicalyDown} from './musicalyDown';
import {SnaptikProvider} from './snaptikProvider';
import {TikmateProvider} from './tikmateProvider';
import {TTDownloader} from './ttDownloader';
export const Providers: BaseProvider[] = [
new SnaptikProvider(),
new TikmateProvider(),
new MusicalyDown(),
new TTDownloader(),
];
export const getRandomProvider = () => Providers[

View File

@@ -1,4 +1,4 @@
import {musicalyFetch} from '..';
import {getFetch} from '..';
import {handleException} from '../decorators';
import {BaseProvider, ExtractedInfo} from './baseProvider';
@@ -6,6 +6,7 @@ import {BaseProvider, ExtractedInfo} from './baseProvider';
* @class MusicalyDown
*/
export class MusicalyDown extends BaseProvider {
public client = getFetch('https://musicaldown.com/id');
/**
*
* @return {string}
@@ -14,47 +15,40 @@ export class MusicalyDown extends BaseProvider {
return 'musicalydown';
}
/**
* @return {string}
*/
public getURI(): string {
return musicalyFetch.defaults.options.prefixUrl;
}
/**
*
* @param {string} url - Video Tiktok URL
* @return {string}
*/
@handleException()
@handleException
public async fetch(url: string): Promise<ExtractedInfo> {
const headers = {
'Accept': '*/*',
'Referer': this.client.defaults.options.prefixUrl,
'Origin': this.client.defaults.options.prefixUrl,
};
const res = await musicalyFetch('./', {
const res = await this.client('./', {
headers,
});
const form = {} as Record<string, string>;
const tokens = (res.body.match(/input name="([^"]+)/gi) as string[])
.map((x) => x.split('"').pop() as string);
const token = (
res.body.match(/type="hidden" value="(.*?)"/gi) as string[])[0]
.split(/=/g).pop()?.replace(/\"/g, '');
const value = [url, token as string, '1'];
// eslint-disable-next-line guard-for-in
for (const tok in tokens) {
form[tokens[tok]] = value[tok];
}
const cookie = res.headers['set-cookie']?.toString();
const response = await musicalyFetch.post('./download', {
form,
const tokens = (
res.body.match(
/input name="([^""]+)" type="hidden" value="([^""]+)"/) as string[]
);
const response = await this.client.post('./download', {
form: {
[(
res.body.match(/input name="([^"]+)/) as string[]
)[1]]: url,
[tokens[1]]: tokens[2],
'verify': 1,
},
headers: {
cookie,
'Cookie': res.headers['set-cookie']?.toString(),
...headers,
},
method: 'POST',
}).text();
return this.extract(response);
});
return this.extract(response.body);
}
/**

View File

@@ -1,4 +1,4 @@
import {snaptikFetch} from '..';
import {getFetch} from '..';
import {handleException} from '../decorators';
import {BaseProvider, ExtractedInfo} from './baseProvider';
import {deObfuscate, matchLink} from './util';
@@ -7,6 +7,7 @@ import {deObfuscate, matchLink} from './util';
* @class SnaptikProvider
*/
export class SnaptikProvider extends BaseProvider {
public client = getFetch('https://snaptik.app/en');
/**
*
* @return {string}
@@ -15,22 +16,14 @@ export class SnaptikProvider extends BaseProvider {
return 'snaptik';
}
/**
*
* @return {string}
*/
public getURI(): string {
return snaptikFetch.defaults.options.prefixUrl;
}
/**
*
* @param {string} url - TikTok Video URL
* @return {Promise<ExtractedInfo>}
*/
@handleException()
@handleException
public async fetch(url: string): Promise<ExtractedInfo> {
const response = await snaptikFetch('./abc.php', {
const response = await this.client('./abc.php', {
searchParams: {
'url': url,
},
@@ -45,7 +38,7 @@ export class SnaptikProvider extends BaseProvider {
* @param {string} html - Raw HTML
* @return {ExtractedInfo}
*/
@handleException()
@handleException
extract(html: string): ExtractedInfo {
const results = matchLink(deObfuscate(html));
if (!results || !results.length) throw new Error('Broken');

View File

@@ -1,4 +1,4 @@
import {tikmateFetch} from '..';
import {getFetch} from '..';
import {handleException} from '../decorators';
import {BaseProvider, ExtractedInfo} from './baseProvider';
import {deObfuscate, matchTikmateDownload} from './util';
@@ -7,6 +7,7 @@ import {deObfuscate, matchTikmateDownload} from './util';
* @class TikmateProvider
*/
export class TikmateProvider extends BaseProvider {
public client = getFetch('https://tikmate.online');
/**
*
* @return {string}
@@ -20,7 +21,7 @@ export class TikmateProvider extends BaseProvider {
* @return {string}
*/
public getURI(): string {
return tikmateFetch.defaults.options.prefixUrl;
return this.client.defaults.options.prefixUrl;
}
@@ -28,23 +29,23 @@ export class TikmateProvider extends BaseProvider {
*
* @param {string} url - Video TikTok URL
*/
@handleException()
@handleException
public async fetch(url: string): Promise<ExtractedInfo> {
// we need to get the token
const response = await tikmateFetch('./');
const response = await this.client('./');
const token =
(response.body.match(/id="token" value="(.*)?"/) as string[])[1];
const cookies = response.headers['cookie'];
const abcResponse = await tikmateFetch.post('./abc.php', {
const abcResponse = await this.client.post('./abc.php', {
form: {
'url': url,
'token': token,
},
headers: {
'Origin': tikmateFetch.defaults.options.prefixUrl,
'Referer': tikmateFetch.defaults.options.prefixUrl + '/',
'Origin': this.client.defaults.options.prefixUrl,
'Referer': this.client.defaults.options.prefixUrl + '/',
'Cookie': cookies,
},
});

View File

@@ -0,0 +1,58 @@
import {getFetch} from '..';
import {handleException} from '../decorators';
import {BaseProvider, ExtractedInfo} from './baseProvider';
import bind from 'bind-decorator';
/**
* @class TTDownloader
*/
export class TTDownloader extends BaseProvider {
/**
* @return {string}
*/
public resourceName(): string {
return 'tt';
}
public client = getFetch('https://ttdownloader.com');
/**
*
* @param {string} url - Video TikTok URL
* @return {Promise<ExtractedInfo>}
*/
@handleException
@bind
public async fetch(url: string): Promise<ExtractedInfo> {
// getting token and cookies
const firstResponse = await this.client('./');
const token = (firstResponse.body
.match(/name="token" value="(.*)?"/) as string[])[1];
const videoResponse = await this.client.post('./req', {
form: {
'token': token,
'format': '',
'url': url,
},
headers: {
'Origin': 'https://ttdownloader.com',
'Referer': 'https://ttdownloader.com',
'Cookie': firstResponse.headers['cookie'],
},
});
return this.extract(videoResponse.body);
}
/**
*
* @param {string} html - HTML Raw
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
console.log(html);
return {
'error': '',
};
}
};

View File

@@ -1,4 +1,5 @@
import {tikmateFetch} from '../..';
import {getProvider} from '..';
import type {BaseProvider} from '../baseProvider';
export const deObfuscate = (html: string): string => {
if (/error/gi.test(html)) {
@@ -30,7 +31,8 @@ export const matchLink = (raw: string): string[] | null => {
export const matchTikmateDownload = (raw: string): string[] => {
const links = matchLink(raw) as string[];
const urls = raw.match(/\/download.php\?token=(.*?)"/gi)
?.map((url) => tikmateFetch.defaults.options.prefixUrl.slice(0, -1)+
?.map((url) => (getProvider('tikmate') as BaseProvider).client.
defaults.options.prefixUrl.slice(0, -1)+
url.slice(0, -3));
return [links[0]].concat(urls as string[]);

View File

@@ -11,12 +11,13 @@
"@typescript-eslint/eslint-plugin": "^5.3.0",
"@typescript-eslint/parser": "^5.3.0",
"@vercel/node": "^1.12.1",
"bind-decorator": "^1.0.11",
"eslint": "^8.2.0",
"eslint-config-google": "^0.14.0",
"typescript": "^4.4.4"
},
"scripts": {
"build": "npm run lint && echo build",
"build": "echo build",
"lint": "eslint \"./lib/**/*.ts\" \"./types/*.ts\" \"./api/**/*.ts\" --fix"
}
}

View File

@@ -14,7 +14,6 @@
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"forceConsistentCasingInFileNames": true,
"noImplicitAny": true,
"experimentalDecorators": true
},
"exclude": ["node_modules", "dist"]

View File

@@ -239,6 +239,11 @@ balanced-match@^1.0.0:
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
bind-decorator@^1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/bind-decorator/-/bind-decorator-1.0.11.tgz#e41bc06a1f65dd9cec476c91c5daf3978488252f"
integrity sha1-5BvAah9l3ZzsR2yRxdrzl4SIJS8=
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"