chore: add prettier

Signed-off-by: hansputera <hanifdwyputrasembiring@gmail.com>
This commit is contained in:
hansputera
2022-03-06 13:40:48 +07:00
parent ea4caf5896
commit f8f10b14e3
30 changed files with 927 additions and 779 deletions

View File

@@ -15,7 +15,8 @@
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev --parallel",
"lint": "turbo run lint",
"lint": "turbo run lint --parallel",
"format": "turbo run format --parallel",
"prepare": "husky install"
},
"packageManager": "yarn@3.2.0"

View File

@@ -1,5 +1,5 @@
module.exports = {
extends: ['google'],
extends: ['google', 'prettier'],
settings: {
next: {
rootDir: [

View File

@@ -13,6 +13,9 @@
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0"
"@typescript-eslint/parser": "^5.13.0",
"eslint": "^8.10.0",
"eslint-config-prettier": "^8.5.0",
"prettier": "^2.5.1"
}
}

View File

@@ -0,0 +1,8 @@
module.exports = {
semi: true,
singleQuote: true,
tabWidth: 4,
trailingComma: 'all',
bracketSpacing: false,
// useTabs: true,
};

View File

@@ -0,0 +1 @@
*.json

View File

@@ -0,0 +1 @@
module.exports = require('tiktok-dl-config/prettier');

View File

@@ -1,8 +1,8 @@
import got, {ExtendOptions} from 'got';
export const getFetch = (baseUrl: string, options?: ExtendOptions) =>
got.extend({
prefixUrl: baseUrl,
dnsCache: true,
...options,
});
got.extend({
prefixUrl: baseUrl,
dnsCache: true,
...options,
});

View File

@@ -1,3 +1,3 @@
export * from './src';
export * from './fetch';
export * from './src/utils';
export * from './src/utils';

View File

@@ -9,10 +9,12 @@
"vm2": "^3.9.6"
},
"scripts": {
"lint": "eslint \"+(src)/**/*.ts\" --fix"
"lint": "eslint \"+(src)/**/*.ts\" --fix",
"format": "prettier . --write"
},
"devDependencies": {
"@typescript-eslint/parser": "^5.13.0",
"eslint": "^8.10.0"
"eslint": "^8.10.0",
"prettier": "^2.5.1"
}
}

View File

@@ -5,85 +5,85 @@ import {BaseProvider, ExtractedInfo} from './base';
* @class DLTikProvider
*/
export class DLTikProvider extends BaseProvider {
/**
/**
* @return {string}
*/
public resourceName(): string {
return 'dltik';
}
public resourceName(): string {
return 'dltik';
}
public client = getFetch('https://dltik.com');
public client = getFetch('https://dltik.com');
public maintenance = {
reason: 'My prediction is that DLTik needs an active session to use.',
};
public maintenance = {
reason: 'My prediction is that DLTik needs an active session to use.',
};
/**
/**
* @param {string} url - Video TikTok URL
* @return {Promise<ExtractedInfo>}
*/
public async fetch(url: string): Promise<ExtractedInfo> {
// getting verification token
const response = await this.client('./#url=' + encodeURIComponent(url));
const token = (
public async fetch(url: string): Promise<ExtractedInfo> {
// getting verification token
const response = await this.client('./#url=' + encodeURIComponent(url));
const token = (
response.body.match(/type="hidden" value="([^""]+)"/) as string[]
)[1];
)[1];
const dlResponse = await this.client.post('./', {
form: {
m: 'getlink',
url: `https://m.tiktok.com/v/${
(
const dlResponse = await this.client.post('./', {
form: {
m: 'getlink',
url: `https://m.tiktok.com/v/${
(
/predownload\('([0-9]+)'\)/gi.exec(
response.body,
) as string[]
)[1]
}.html`,
__RequestVerificationToken: token,
},
headers: {
'Origin': this.client.defaults.options.prefixUrl,
'Referer': response.url,
'Cookie': response.headers['set-cookie']?.toString(),
'Content-Type': 'application/x-www-form-urlencoded',
'x-requested-with': 'XMLHttpRequest',
},
});
)[1]
}.html`,
__RequestVerificationToken: token,
},
headers: {
Origin: this.client.defaults.options.prefixUrl,
Referer: response.url,
Cookie: response.headers['set-cookie']?.toString(),
'Content-Type': 'application/x-www-form-urlencoded',
'x-requested-with': 'XMLHttpRequest',
},
});
return this.extract(dlResponse.body);
}
return this.extract(dlResponse.body);
}
/**
/**
*
* @param {string} html - Raw
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const json = JSON.parse(html);
if (!json.status) {
return {
error: json.message,
};
} else {
// if (json.data.videoId === '7013188037203070234') {
// return {
// 'error': 'Invalid url',
// };
// }
return {
video: {
id: json.data.videoId,
urls: [
json.data.watermarkVideoUrl,
json.data.destinationUrl,
],
thumb: json.data.dynamicCover,
},
music: {
url: json.data.musicUrl,
},
caption: json.data.desc,
};
extract(html: string): ExtractedInfo {
const json = JSON.parse(html);
if (!json.status) {
return {
error: json.message,
};
} else {
// if (json.data.videoId === '7013188037203070234') {
// return {
// 'error': 'Invalid url',
// };
// }
return {
video: {
id: json.data.videoId,
urls: [
json.data.watermarkVideoUrl,
json.data.destinationUrl,
],
thumb: json.data.dynamicCover,
},
music: {
url: json.data.musicUrl,
},
caption: json.data.desc,
};
}
}
}
}

View File

@@ -6,47 +6,47 @@ import {matchLink} from './utils';
* @class DDDTikProvider
*/
export class DDDTikProvider extends BaseProvider {
/**
/**
* Get resource name
*
* @return {string}
*/
public resourceName(): string {
return 'dddtik';
}
public resourceName(): string {
return 'dddtik';
}
public client = getFetch('https://dddtik.com');
public client = getFetch('https://dddtik.com');
public maintenance = undefined;
public maintenance = undefined;
/**
/**
* @param {string} url Tiktok video url
* @return {Promise<ExtractedInfo>}
*/
async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client.post('./down.php', {
form: {
url: url,
},
});
async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client.post('./down.php', {
form: {
url: url,
},
});
return this.extract(response.body);
}
return this.extract(response.body);
}
/**
/**
* @param {string} html
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const urls = matchLink(html) as string[];
urls.pop();
extract(html: string): ExtractedInfo {
const urls = matchLink(html) as string[];
urls.pop();
const t = urls[1];
return {
video: {
urls: urls.filter((u) => u !== t),
thumb: t,
},
};
}
const t = urls[1];
return {
video: {
urls: urls.filter((u) => u !== t),
thumb: t,
},
};
}
}

View File

@@ -6,67 +6,67 @@ import {matchCustomDownload} from './utils';
* @class DownTikProvider
*/
export class DownTikProvider extends BaseProvider {
/**
/**
* Get resource name
*
* @return {string}
*/
public resourceName(): string {
return 'downtik';
}
public resourceName(): string {
return 'downtik';
}
public client = getFetch('https://downtik.net');
public client = getFetch('https://downtik.net');
public maintenance = undefined;
public maintenance = undefined;
/**
/**
* @param {string} url
*
* @return {Promise<ExtractedInfo>}
*/
async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client('./');
async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client('./');
const token = (
const token = (
response.body.match(/id="token" value="([^""]+)"/) as string[]
)[1];
)[1];
const responseAction = await this.client.post('./action.php', {
form: {
url: url,
token: token,
},
headers: {
cookie: response.headers['set-cookie']?.toString(),
Referer: 'https://downtik.net/',
Origin: 'https://downtik.net',
},
});
const responseAction = await this.client.post('./action.php', {
form: {
url: url,
token: token,
},
headers: {
cookie: response.headers['set-cookie']?.toString(),
Referer: 'https://downtik.net/',
Origin: 'https://downtik.net',
},
});
if (JSON.parse(responseAction.body).error) {
return {
error: JSON.parse(responseAction.body).message,
};
if (JSON.parse(responseAction.body).error) {
return {
error: JSON.parse(responseAction.body).message,
};
}
return this.extract(JSON.parse(responseAction.body).data);
}
return this.extract(JSON.parse(responseAction.body).data);
}
/**
/**
* @param {string} html
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const urls = matchCustomDownload('downtik', html);
extract(html: string): ExtractedInfo {
const urls = matchCustomDownload('downtik', html);
return {
music: {
url: urls.pop() as string,
},
video: {
thumb: urls?.shift(),
urls: urls as string[],
},
};
}
return {
music: {
url: urls.pop() as string,
},
video: {
thumb: urls?.shift(),
urls: urls as string[],
},
};
}
}

View File

@@ -5,81 +5,81 @@ import {getFetch} from '../fetch';
* @class DownloadOne
*/
export class DownloadOne extends BaseProvider {
/**
/**
* Get provider name
* @return {string}
*/
public resourceName(): string {
return 'ttdownloaderone';
}
public resourceName(): string {
return 'ttdownloaderone';
}
public client = getFetch('http://tiktokdownloader.one');
public client = getFetch('http://tiktokdownloader.one');
public maintenance = undefined;
public maintenance = undefined;
/**
/**
* Fetch ttdownloader.one
* @param {string} url Video TikTok URL
* @return {Promise<ExtractedInfo>}
*/
public async fetch(url: string): Promise<ExtractedInfo> {
// getting the token
const response = await this.client('./');
public async fetch(url: string): Promise<ExtractedInfo> {
// getting the token
const response = await this.client('./');
const token = (
const token = (
/name="_token_" content="(.*)"/gi.exec(response.body) as string[]
)[1];
)[1];
const dlResponse = await this.client('./api/v1/fetch?url=' + url, {
headers: {
TOKEN: token,
Referer: 'http://tiktokdownloader.one/',
Origin: 'http://tiktokdownloader.one',
Accept: 'application/json, text/plain, */*',
},
});
const dlResponse = await this.client('./api/v1/fetch?url=' + url, {
headers: {
TOKEN: token,
Referer: 'http://tiktokdownloader.one/',
Origin: 'http://tiktokdownloader.one',
Accept: 'application/json, text/plain, */*',
},
});
if (dlResponse.statusCode !== 200) {
return {
error: 'Probably the video doesn\'t exist',
};
if (dlResponse.statusCode !== 200) {
return {
error: "Probably the video doesn't exist",
};
}
return this.extract(dlResponse.body);
}
return this.extract(dlResponse.body);
}
/**
/**
* Extract page from ttdownloader.one site
* @param {string} html
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const json = JSON.parse(html);
extract(html: string): ExtractedInfo {
const json = JSON.parse(html);
return {
video: {
urls: [json.url, json.url_nwm],
thumb: json.cover,
id: json.video_id,
},
music: {
url: json.music.url,
title: json.music.title,
cover: json.music.cover,
author: json.music.author,
},
author: {
id: json.user.name,
username: json.user.username,
thumb: json.user.cover,
},
caption: json.caption,
updatedAt: json.updatedAt ?? '-',
uploadedAt: json.uploaded_at,
commentsCount: json.stats.comment,
sharesCount: json.stats.shares,
likesCount: json.stats.likes,
playsCount: json.stats.play,
};
}
return {
video: {
urls: [json.url, json.url_nwm],
thumb: json.cover,
id: json.video_id,
},
music: {
url: json.music.url,
title: json.music.title,
cover: json.music.cover,
author: json.music.author,
},
author: {
id: json.user.name,
username: json.user.username,
thumb: json.user.cover,
},
caption: json.caption,
updatedAt: json.updatedAt ?? '-',
uploadedAt: json.uploaded_at,
commentsCount: json.stats.comment,
sharesCount: json.stats.shares,
likesCount: json.stats.likes,
playsCount: json.stats.play,
};
}
}

View File

@@ -0,0 +1,96 @@
import {BaseProvider, ExtractedInfo} from './base';
import {getFetch} from '../fetch';
import {matchLink} from './utils';
import {random as randomUA} from 'tiktok-dl-config/useragents';
/**
* @class GetVidTikProvider
*/
export class GetVidTikProvider extends BaseProvider {
/**
* Get resource name
*
* @return {string}
*/
public resourceName(): string {
return 'getvidtik';
}
public client = getFetch('https://getvidtik.com');
public maintenance = undefined;
/**
* @param {string} url TikTok Video URL
* @return {Promise<ExtractedInfo>}
*/
async fetch(url: string): Promise<ExtractedInfo> {
// getting the token.
const response = await this.client.get('./', {
headers: {
'User-Agent': randomUA(),
},
});
const matchs = /name="token" type="hidden" value="([^""]+)"/.exec(
response.body,
);
if (!matchs) {
return {
error: "Couldn't get the token.",
};
} else {
// download request
const downloadResponse = await this.client.post('./download', {
headers: {
'User-Agent': randomUA(),
Cookie: response.headers['set-cookie']?.toString(),
Origin: this.client.defaults.options.prefixUrl,
Referer: response.url,
},
followRedirect: false,
});
if (downloadResponse.statusCode === 302) {
return {
error: 'The video is private or removed.',
};
} else {
return this.extract(downloadResponse.body);
}
}
}
/**
* Extract getVidTik Response
* @param {string} html - Raw
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const matchs = matchLink(html);
if (matchs) {
const tiktokMatchs = matchs.filter((url) =>
/http(s)?:\/\/(.*)\.tiktok(cdn)?\.com/gi.test(url),
);
if (tiktokMatchs) {
return {
video: {
thumb: tiktokMatchs[0],
urls: [tiktokMatchs[2], tiktokMatchs[3]], // [0] = no watermark, [1] = watermark
},
music: {
url: tiktokMatchs[tiktokMatchs.length - 1], // soon, i'll use '.at(-1)'
},
};
} else {
return {
error: "Couldn't match tiktok links.",
};
}
} else {
return {
error: "Couldn't match site links.",
};
}
}
}

View File

@@ -17,29 +17,29 @@ import {DownloadOne} from './downloaderOneProvider';
import {NativeProvider} from './nativeProvider';
export const Providers: BaseProvider[] = [
new SnaptikProvider(),
new TikmateProvider(),
new MusicalyDown(),
new TTDownloader(),
new TTSave(), // won't work because we coudn't receive the cookie.
new DLTikProvider(),
new SaveFromProvider(),
new SaveTikProvider(),
new TikDownProvider(),
new DownTikProvider(), // SaveTik Mirror
new LoveTikProvider(),
new DDDTikProvider(),
new TokupProvider(), // ttsave alternative
new DownloadOne(),
new NativeProvider(),
new SnaptikProvider(),
new TikmateProvider(),
new MusicalyDown(),
new TTDownloader(),
new TTSave(), // won't work because we coudn't receive the cookie.
new DLTikProvider(),
new SaveFromProvider(),
new SaveTikProvider(),
new TikDownProvider(),
new DownTikProvider(), // SaveTik Mirror
new LoveTikProvider(),
new DDDTikProvider(),
new TokupProvider(), // ttsave alternative
new DownloadOne(),
new NativeProvider(),
];
export const getRandomProvider = () =>
Providers[Math.floor(Math.random() * Providers.length)];
Providers[Math.floor(Math.random() * Providers.length)];
export const getProvider = (name: string) =>
name.toLowerCase() !== 'random' ?
Providers.find((p) => p.resourceName() === name.toLowerCase()) :
getRandomProvider();
name.toLowerCase() !== 'random'
? Providers.find((p) => p.resourceName() === name.toLowerCase())
: getRandomProvider();
export {BaseProvider, ExtractedInfo};

View File

@@ -5,61 +5,61 @@ import {getFetch} from '../fetch';
* @class LoveTikProvider
*/
export class LoveTikProvider extends BaseProvider {
/**
/**
* Get resource name
*
* @return {string}
*/
public resourceName(): string {
return 'lovetik';
}
public resourceName(): string {
return 'lovetik';
}
public client = getFetch('https://lovetik.com');
public client = getFetch('https://lovetik.com');
public maintenance = undefined;
public maintenance = undefined;
/**
/**
* @param {string} url Video TikTok URL
* @return {Promise<ExtractedInfo>}
*/
async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client.post('./api/ajax/search', {
form: {
query: url,
},
headers: {
Origin: 'https://lovetik.com/',
Referer: 'https://lovetik.com/',
},
});
async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client.post('./api/ajax/search', {
form: {
query: url,
},
headers: {
Origin: 'https://lovetik.com/',
Referer: 'https://lovetik.com/',
},
});
return this.extract(response.body);
}
return this.extract(response.body);
}
/**
/**
* @param {string} jsonString
* @return {ExtractedInfo}
*/
extract(jsonString: string): ExtractedInfo {
const json = JSON.parse(jsonString);
extract(jsonString: string): ExtractedInfo {
const json = JSON.parse(jsonString);
if (json.mess) {
return {
error: json.mess,
};
if (json.mess) {
return {
error: json.mess,
};
}
return {
music: {
url: json.links.pop().a,
},
video: {
thumb: json.cover,
urls: json.links.map((l: Record<string, unknown>) => l.a),
},
author: {
username: json.author.replace(/(<([^>]+)>)/gi, ''),
},
};
}
return {
music: {
url: json.links.pop().a,
},
video: {
thumb: json.cover,
urls: json.links.map((l: Record<string, unknown>) => l.a),
},
author: {
username: json.author.replace(/(<([^>]+)>)/gi, ''),
},
};
}
}

View File

@@ -5,72 +5,72 @@ import {BaseProvider, ExtractedInfo} from './base';
* @class MusicalyDown
*/
export class MusicalyDown extends BaseProvider {
public client = getFetch('https://musicaldown.com/id');
/**
public client = getFetch('https://musicaldown.com/id');
/**
*
* @return {string}
*/
public resourceName(): string {
return 'musicalydown';
}
public resourceName(): string {
return 'musicalydown';
}
public maintenance = undefined;
public maintenance = undefined;
/**
/**
*
* @param {string} url - Video Tiktok URL
* @return {Promise<ExtractedInfo>}
*/
public async fetch(url: string): Promise<ExtractedInfo> {
const res = await this.client('./', {
headers: {
Accept: '*/*',
Referer: this.client.defaults.options.prefixUrl,
Origin: this.client.defaults.options.prefixUrl,
},
});
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: res.headers['set-cookie']?.toString(),
Accept: '*/*',
Referer: this.client.defaults.options.prefixUrl,
Origin: this.client.defaults.options.prefixUrl,
},
});
public async fetch(url: string): Promise<ExtractedInfo> {
const res = await this.client('./', {
headers: {
Accept: '*/*',
Referer: this.client.defaults.options.prefixUrl,
Origin: this.client.defaults.options.prefixUrl,
},
});
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: res.headers['set-cookie']?.toString(),
Accept: '*/*',
Referer: this.client.defaults.options.prefixUrl,
Origin: this.client.defaults.options.prefixUrl,
},
});
return this.extract(response.body);
}
return this.extract(response.body);
}
/**
/**
*
* @param {string} html - Raw HTML
* @return {ExtractedInfo}
*/
public extract(html: string): ExtractedInfo {
const matchUrls = html.match(
/<a.*?target="_blank".*?href="(.*?)".*?<\/a>/gi,
) as string[];
const urls = matchUrls.map(
(url) =>
public extract(html: string): ExtractedInfo {
const matchUrls = html.match(
/<a.*?target="_blank".*?href="(.*?)".*?<\/a>/gi,
) as string[];
const urls = matchUrls.map(
(url) =>
/<a.*?target="_blank".*?href="(.*?)".*?<\/a>/gi.exec(
url,
)?.[1] as string,
);
return {
video: {
urls: urls,
thumb: /img class="responsive-img" src="(.*?)"/gi.exec(
html,
)?.[1],
},
};
}
);
return {
video: {
urls: urls,
thumb: /img class="responsive-img" src="(.*?)"/gi.exec(
html,
)?.[1],
},
};
}
}

View File

@@ -7,85 +7,84 @@ import {matchTikTokData} from './utils';
* @class NativeProvider
*/
export class NativeProvider extends BaseProvider {
/**
/**
* Get resource name.
* @return {string}
*/
public resourceName(): string {
return 'native';
}
public resourceName(): string {
return 'native';
}
public maintenance = undefined;
public client = undefined;
public maintenance = undefined;
public client = undefined;
/**
/**
* @param {string} url Tiktok video url
* @return {Promise<ExtractedInfo>}
*/
async fetch(url: string): Promise<ExtractedInfo> {
const urlInstance = new URL(url);
async fetch(url: string): Promise<ExtractedInfo> {
const urlInstance = new URL(url);
const response = await getFetch(urlInstance.origin).get(
`.${urlInstance.pathname}`,
{
headers: {
Referer: urlInstance.href,
Origin: urlInstance.origin,
'User-Agent': randomUA(),
},
timeout: {
socket: 10000,
},
},
);
const response = await getFetch(urlInstance.origin).get(
urlInstance.pathname,
{
headers: {
'Referer': urlInstance.href,
'Origin': urlInstance.origin,
'User-Agent': randomUA(),
},
timeout: {
socket: 5000,
},
},
);
return this.extract(response.body);
}
return this.extract(response.body);
}
/**
* @param {string} html
/**
* @param {string} html Raw HTML Data
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const matches = matchTikTokData(html);
if (matches.length) {
const json = Object.values(
JSON.parse(matches).ItemModule,
)[0] as any;
extract(html: string): ExtractedInfo {
const matches = matchTikTokData(html);
if (matches.length) {
const json = Object.values(
JSON.parse(matches).ItemModule,
)[0] as any;
return {
video: {
id: json.id,
urls: [json.video.playAddr, json.video.downloadAddr],
thumb: json.video.cover,
duration: json.video.duration,
},
music: {
url: json.music.playUrl,
title: json.music.title,
author: json.music.authorName,
id: json.music.id,
cover: json.music.coverLarge,
album: json.music.album,
duration: json.music.duration,
},
author: {
username: json.author,
id: json.authorId,
thumb: json.avatarThumb,
nick: json.nickname,
},
caption: json.desc,
playsCount: json.stats.playCount,
sharesCount: json.stats.shareCount,
commentsCount: json.stats.commentCount,
likesCount: json.stats.diggCount,
uploadedAt: json.createTime,
};
} else {
return {
error: 'Something was wrong!',
};
return {
video: {
id: json.id,
urls: [json.video.playAddr, json.video.downloadAddr],
thumb: json.video.cover,
duration: json.video.duration,
},
music: {
url: json.music.playUrl,
title: json.music.title,
author: json.music.authorName,
id: json.music.id,
cover: json.music.coverLarge,
album: json.music.album,
duration: json.music.duration,
},
author: {
username: json.author,
id: json.authorId,
thumb: json.avatarThumb,
nick: json.nickname,
},
caption: json.desc,
playsCount: json.stats.playCount,
sharesCount: json.stats.shareCount,
commentsCount: json.stats.commentCount,
likesCount: json.stats.diggCount,
uploadedAt: json.createTime,
};
} else {
return {
error: 'Something was wrong!',
};
}
}
}
}

View File

@@ -6,66 +6,66 @@ import {deObfuscateSaveFromScript} from './utils';
* @class saveFromProvider
*/
export class SaveFromProvider extends BaseProvider {
/**
/**
*
* @return {string}
*/
public resourceName(): string {
return 'savefrom';
}
public resourceName(): string {
return 'savefrom';
}
public client = getFetch('https://worker-as.sf-tools.com');
public client = getFetch('https://worker-as.sf-tools.com');
public maintenance = undefined;
public maintenance = undefined;
/**
/**
*
* @param {string} url - Video TikTok URL
* @return {Promise<ExtractedInfo>}
*/
public async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client.post('./savefrom.php', {
form: {
'sf_url': url,
'sf_submit': '',
'new': '2',
'lang': 'id',
'country': 'id',
'os': 'Ubuntu',
'browser': 'Firefox',
'channel': 'Downloader',
'sf-nomad': '1',
},
headers: {
Origin: 'https://id.savefrom.net',
Referer: 'https://id.savefrom.net',
},
});
public async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client.post('./savefrom.php', {
form: {
sf_url: url,
sf_submit: '',
new: '2',
lang: 'id',
country: 'id',
os: 'Ubuntu',
browser: 'Firefox',
channel: 'Downloader',
'sf-nomad': '1',
},
headers: {
Origin: 'https://id.savefrom.net',
Referer: 'https://id.savefrom.net',
},
});
return this.extract(response.body);
}
return this.extract(response.body);
}
/**
/**
*
* @param {string} html - HTML Raw
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const deobfuscated = deObfuscateSaveFromScript(html);
const json = JSON.parse(
(deobfuscated.match(/\({(.*)}\)/) as string[])[0].replace(
/(\(|\))/g,
'',
),
);
return {
video: {
thumb: json.thumb,
id: json.id,
urls: json.url.map((x: {url: string}) => x.url),
duration: json.meta.duration,
title: json.meta.title,
},
};
}
extract(html: string): ExtractedInfo {
const deobfuscated = deObfuscateSaveFromScript(html);
const json = JSON.parse(
(deobfuscated.match(/\({(.*)}\)/) as string[])[0].replace(
/(\(|\))/g,
'',
),
);
return {
video: {
thumb: json.thumb,
id: json.id,
urls: json.url.map((x: {url: string}) => x.url),
duration: json.meta.duration,
title: json.meta.title,
},
};
}
}

View File

@@ -6,66 +6,66 @@ import {matchCustomDownload} from './utils';
* @class SaveTikProvider
*/
export class SaveTikProvider extends BaseProvider {
/**
/**
* Get resource name
*
* @return {string}
*/
public resourceName(): string {
return 'savetik';
}
public resourceName(): string {
return 'savetik';
}
public client = getFetch('https://savetik.net');
public client = getFetch('https://savetik.net');
public maintenance = undefined;
public maintenance = undefined;
/**
/**
* @param {string} url Video TikTok URL
* @return {Promise<ExtractedInfo>}
*/
async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client('./');
async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client('./');
const token = (
const token = (
response.body.match(/id="token" value="([^""]+)"/) as string[]
)[1];
)[1];
const responseAction = await this.client.post('./action.php', {
form: {
url: url,
token: token,
},
headers: {
cookie: response.headers['set-cookie']?.toString(),
Referer: 'https://savetik.net/',
Origin: 'https://savetik.net',
},
});
const responseAction = await this.client.post('./action.php', {
form: {
url: url,
token: token,
},
headers: {
cookie: response.headers['set-cookie']?.toString(),
Referer: 'https://savetik.net/',
Origin: 'https://savetik.net',
},
});
if (JSON.parse(responseAction.body).error) {
return {
error: JSON.parse(responseAction.body).message,
};
if (JSON.parse(responseAction.body).error) {
return {
error: JSON.parse(responseAction.body).message,
};
}
return this.extract(JSON.parse(responseAction.body).data);
}
return this.extract(JSON.parse(responseAction.body).data);
}
/**
/**
* @param {string} html
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const urls = matchCustomDownload('savetik', html);
extract(html: string): ExtractedInfo {
const urls = matchCustomDownload('savetik', html);
return {
music: {
url: urls?.pop() as string,
},
video: {
thumb: urls?.shift(),
urls: urls as string[],
},
};
}
return {
music: {
url: urls?.pop() as string,
},
video: {
thumb: urls?.shift(),
urls: urls as string[],
},
};
}
}

View File

@@ -6,46 +6,46 @@ import {deObfuscate, matchLink} from './utils';
* @class SnaptikProvider
*/
export class SnaptikProvider extends BaseProvider {
public client = getFetch('https://snaptik.app/en');
/**
public client = getFetch('https://snaptik.app/en');
/**
*
* @return {string}
*/
public resourceName(): string {
return 'snaptik';
}
public resourceName(): string {
return 'snaptik';
}
public maintenance = undefined;
public maintenance = undefined;
/**
/**
*
* @param {string} url - TikTok Video URL
* @return {Promise<ExtractedInfo>}
*/
public async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client('./abc.php', {
searchParams: {
url: url,
},
});
public async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client('./abc.php', {
searchParams: {
url: url,
},
});
return this.extract(response.body);
}
return this.extract(response.body);
}
/**
/**
* Extract information from raw html
* @param {string} html - Raw HTML
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const results = matchLink(deObfuscate(html));
if (!results || !results.length) throw new Error('Broken');
extract(html: string): ExtractedInfo {
const results = matchLink(deObfuscate(html));
if (!results || !results.length) throw new Error('Broken');
return {
video: {
thumb: results?.shift(),
urls: [...new Set(results)],
},
};
}
return {
video: {
thumb: results?.shift(),
urls: [...new Set(results)],
},
};
}
}

View File

@@ -6,61 +6,61 @@ import {matchLink} from './utils';
* @class TikDownProvider
*/
export class TikDownProvider extends BaseProvider {
/**
/**
* Get resource name.
*
* @return {string}
*/
public resourceName(): string {
return 'tikdown';
}
public resourceName(): string {
return 'tikdown';
}
public client = getFetch('https://tikdown.org');
public client = getFetch('https://tikdown.org');
public maintenance = undefined;
public maintenance = undefined;
/**
/**
* @param {string} url
*
* @return {Promise<ExtractedInfo>}
*/
async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client('./');
async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client('./');
const token = (
const token = (
response.body.match(/name="_token" value="([^""]+)"/) as string[]
)[1];
)[1];
const responseAjax = await this.client.post('./getAjax', {
form: {
url: url,
_token: token,
},
headers: {
'x-csrf-token': token,
'cookie': response.headers['set-cookie']?.toString(),
},
});
const responseAjax = await this.client.post('./getAjax', {
form: {
url: url,
_token: token,
},
headers: {
'x-csrf-token': token,
cookie: response.headers['set-cookie']?.toString(),
},
});
if (!JSON.parse(responseAjax.body).status) {
return {
error: 'Something was wrong',
};
if (!JSON.parse(responseAjax.body).status) {
return {
error: 'Something was wrong',
};
}
return this.extract(JSON.parse(responseAjax.body).html);
}
return this.extract(JSON.parse(responseAjax.body).html);
}
/**
/**
* @param {string} html
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const urls = matchLink(html) as string[];
return {
video: {
thumb: urls.shift(),
urls: urls,
},
};
}
extract(html: string): ExtractedInfo {
const urls = matchLink(html) as string[];
return {
video: {
thumb: urls.shift(),
urls: urls,
},
};
}
}

View File

@@ -6,63 +6,63 @@ import {deObfuscate, matchCustomDownload} from './utils';
* @class TikmateProvider
*/
export class TikmateProvider extends BaseProvider {
public client = getFetch('https://tikmate.online');
/**
public client = getFetch('https://tikmate.online');
/**
*
* @return {string}
*/
public resourceName(): string {
return 'tikmate';
}
public resourceName(): string {
return 'tikmate';
}
public maintenance = undefined;
public maintenance = undefined;
/**
/**
*
* @param {string} url - Video TikTok URL
* @return {Promise<ExtractedInfo>}
*/
public async fetch(url: string): Promise<ExtractedInfo> {
// we need to get the token
public async fetch(url: string): Promise<ExtractedInfo> {
// we need to get the token
const response = await this.client('./');
const matchs = response.body.match(
/id="token" value="(.*)?"/,
) as string[];
const response = await this.client('./');
const matchs = response.body.match(
/id="token" value="(.*)?"/,
) as string[];
const cookies = response.headers['cookie'];
const cookies = response.headers['cookie'];
const abcResponse = await this.client.post('./abc.php', {
form: matchs ?
{
url: url,
token: matchs[1],
} :
{
url: url,
},
headers: {
Origin: this.client.defaults.options.prefixUrl,
Referer: this.client.defaults.options.prefixUrl + '/',
Cookie: cookies,
},
});
const abcResponse = await this.client.post('./abc.php', {
form: matchs
? {
url: url,
token: matchs[1],
}
: {
url: url,
},
headers: {
Origin: this.client.defaults.options.prefixUrl,
Referer: this.client.defaults.options.prefixUrl + '/',
Cookie: cookies,
},
});
return this.extract(abcResponse.body);
}
return this.extract(abcResponse.body);
}
/**
/**
* Extract information from raw html
* @param {string} html - Raw HTML
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const matchs = matchCustomDownload('tikmate', deObfuscate(html));
return {
video: {
thumb: matchs.shift(),
urls: matchs,
},
};
}
extract(html: string): ExtractedInfo {
const matchs = matchCustomDownload('tikmate', deObfuscate(html));
return {
video: {
thumb: matchs.shift(),
urls: matchs,
},
};
}
}

View File

@@ -5,87 +5,87 @@ import {getFetch} from '../fetch';
* @class TokupProvider
*/
export class TokupProvider extends BaseProvider {
/**
/**
* Get provider name
* @return {string}
*/
public resourceName(): string {
return 'tokup';
}
public resourceName(): string {
return 'tokup';
}
public client = getFetch('https://tokup.app');
public client = getFetch('https://tokup.app');
public maintenance = {
reason: 'Tokup site returned \'Oops! Something went wrong!\'',
};
public maintenance = {
reason: "Tokup site returned 'Oops! Something went wrong!'",
};
/**
/**
* Fetch tokup
* @param {string} url - TikTok Video URL
* @return {Promise<ExtractedInfo>}
*/
public async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client.post('./', {
form: {
url: url,
},
headers: {
Origin: this.client.defaults.options.prefixUrl,
Referer: this.client.defaults.options.prefixUrl,
},
timeout: 3000,
});
public async fetch(url: string): Promise<ExtractedInfo> {
const response = await this.client.post('./', {
form: {
url: url,
},
headers: {
Origin: this.client.defaults.options.prefixUrl,
Referer: this.client.defaults.options.prefixUrl,
},
timeout: 3000,
});
if (
response.statusCode !== 200 ||
if (
response.statusCode !== 200 ||
/video not found\b/gi.test(response.body)
) {
return {
error: 'Video Not Found',
};
} else if (/oops/gi.test(response.body)) {
return {
error: 'Tokup Error',
};
} else {
return this.extract(response.body);
) {
return {
error: 'Video Not Found',
};
} else if (/oops/gi.test(response.body)) {
return {
error: 'Tokup Error',
};
} else {
return this.extract(response.body);
}
}
}
/**
/**
* Extract tokup html elements
* @param {string} html
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
console.log(html);
const authorProfile = (
extract(html: string): ExtractedInfo {
console.log(html);
const authorProfile = (
/http(s)?(:\/\/(.*)\.tiktokcdn\.com\/(.*))/gi.exec(html) as string[]
)[0];
const nums = (html.match(/<td>[0-9]+<\/td>/g) as string[]).map((n) =>
n.replace(/<(\/)?[a-zA-Z0-9]+>/gi, ''),
);
const url = [
...new Set(
)[0];
const nums = (html.match(/<td>[0-9]+<\/td>/g) as string[]).map((n) =>
n.replace(/<(\/)?[a-zA-Z0-9]+>/gi, ''),
);
const url = [
...new Set(
html.match(
// eslint-disable-next-line max-len
/http(s)?(:\/\/tikmate\.app\/download\/[A-Za-z0-9\-\_]+\/[0-9]+\.mp4+)/gi,
) as string[],
),
][0];
),
][0];
return {
video: {
urls: [url, url + '?hd=1'],
},
author: {
username: (/target="_blank"\>(.*)\</.exec(html) as string[])[1],
thumb: authorProfile.substring(0, authorProfile.length - 1),
},
uploadedAt: (html.match(/<p>(.+)<\/p>/) as string[])[1],
likesCount: nums[0] as unknown as number,
commentsCount: nums[1] as unknown as number,
sharesCount: nums[2] as unknown as number,
};
}
return {
video: {
urls: [url, url + '?hd=1'],
},
author: {
username: (/target="_blank"\>(.*)\</.exec(html) as string[])[1],
thumb: authorProfile.substring(0, authorProfile.length - 1),
},
uploadedAt: (html.match(/<p>(.+)<\/p>/) as string[])[1],
likesCount: nums[0] as unknown as number,
commentsCount: nums[1] as unknown as number,
sharesCount: nums[2] as unknown as number,
};
}
}

View File

@@ -6,56 +6,56 @@ import {matchLink} from './utils';
* @class TTDownloader
*/
export class TTDownloader extends BaseProvider {
/**
/**
* @return {string}
*/
public resourceName(): string {
return 'ttdownloader';
}
public resourceName(): string {
return 'ttdownloader';
}
public client = getFetch('https://ttdownloader.com');
public client = getFetch('https://ttdownloader.com');
public maintenance = undefined;
public maintenance = undefined;
/**
/**
*
* @param {string} url - Video TikTok URL
* @return {Promise<ExtractedInfo>}
*/
public async fetch(url: string): Promise<ExtractedInfo> {
// getting token and cookies
const firstResponse = await this.client('./');
const token = (
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['set-cookie']?.toString(),
},
});
)[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['set-cookie']?.toString(),
},
});
return this.extract(videoResponse.body);
}
return this.extract(videoResponse.body);
}
/**
/**
*
* @param {string} html - HTML Raw
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const urls = matchLink(html);
urls?.pop(); // remove 'https://snaptik.fans'
return {
video: {
urls: urls as string[],
},
};
}
extract(html: string): ExtractedInfo {
const urls = matchLink(html);
urls?.pop(); // remove 'https://snaptik.fans'
return {
video: {
urls: urls as string[],
},
};
}
}

View File

@@ -6,71 +6,71 @@ import {keyGeneratorTTSave, matchLink} from './utils';
* @class TTSave
*/
export class TTSave extends BaseProvider {
/**
/**
* @return {string}
*/
public resourceName(): string {
return 'ttsave';
}
public resourceName(): string {
return 'ttsave';
}
public client = getFetch('https://ttsave.app');
public client = getFetch('https://ttsave.app');
public maintenance = {
reason: 'TTSave doesn\'t returned cookie to manipulate the session',
};
public maintenance = {
reason: "TTSave doesn't returned cookie to manipulate the session",
};
/**
/**
*
* @param {string} url - TikTok Video URL
* @return {Promise<ExtractedInfo>}
*/
public async fetch(url: string): Promise<ExtractedInfo> {
// getting token
const response = await this.client('./');
public async fetch(url: string): Promise<ExtractedInfo> {
// getting token
const response = await this.client('./');
const token = (
const token = (
response.body.match(/(m|doDownload)?\(e,"(.*)"\)}/) as string[]
)
.filter((x) => x.length)
.pop() as string;
const key = await keyGeneratorTTSave(token);
.filter((x) => x.length)
.pop() as string;
const key = await keyGeneratorTTSave(token);
const dlResponse = await this.client.post('./download.php', {
json: {
id: url,
token: token,
key: key,
},
headers: {
Origin: this.client.defaults.options.prefixUrl,
Referer: this.client.defaults.options.prefixUrl,
Cookie: response.headers['set-cookie']?.toString(), // no cookies :(
...response.headers,
},
});
const dlResponse = await this.client.post('./download.php', {
json: {
id: url,
token: token,
key: key,
},
headers: {
Origin: this.client.defaults.options.prefixUrl,
Referer: this.client.defaults.options.prefixUrl,
Cookie: response.headers['set-cookie']?.toString(), // no cookies :(
...response.headers,
},
});
return this.extract(dlResponse.body);
}
return this.extract(dlResponse.body);
}
/**
/**
*
* @param {string} html - HTML Raw
* @return {ExtractedInfo}
*/
extract(html: string): ExtractedInfo {
const tiktokCDNs = (matchLink(html) as string[]).filter((x) =>
/http(s)?:\/\/(.*)?.tiktokcdn.com/gi.test(x),
);
const videoCDNs = tiktokCDNs.filter((x) => !/jpeg/gi.test(x));
extract(html: string): ExtractedInfo {
const tiktokCDNs = (matchLink(html) as string[]).filter((x) =>
/http(s)?:\/\/(.*)?.tiktokcdn.com/gi.test(x),
);
const videoCDNs = tiktokCDNs.filter((x) => !/jpeg/gi.test(x));
return {
video: {
thumb: tiktokCDNs.find((x) => /jpeg/gi.test(x)),
urls: videoCDNs.filter((x) => !/music/gi.test(x)),
},
music: {
url: videoCDNs.find((x) => /music/gi.test(x)) as string,
},
};
}
return {
video: {
thumb: tiktokCDNs.find((x) => /jpeg/gi.test(x)),
urls: videoCDNs.filter((x) => !/music/gi.test(x)),
},
music: {
url: videoCDNs.find((x) => /music/gi.test(x)) as string,
},
};
}
}

View File

@@ -4,79 +4,79 @@ import type {BaseProvider} from '../base';
import {NodeVM} from 'vm2';
export const matchTikTokData = (html: string): string => {
const data = html.match(
// eslint-disable-next-line max-len
/window\['SIGI_STATE'\]=(.*)<\/script><script id="__LOADABLE_REQUIRED_CHUNKS__" type="application\/json">/,
);
const data = html.match(
// eslint-disable-next-line max-len
/window\['SIGI_STATE'\]=(.*)<\/script><script id="__LOADABLE_REQUIRED_CHUNKS__" type="application\/json">/,
);
if (data) {
return data[1].replace(/;window.+/gi, '');
} else {
return '';
}
if (data) {
return data[1].replace(/;window.+/gi, '');
} else {
return '';
}
};
export const deObfuscate = (html: string): string => {
if (/error/gi.test(html)) {
throw new Error(
html.split('\'').find((x) => /(((url)? error)|could)/gi.test(x)),
);
} else {
// only match script tag
const obfuscatedScripts = html.match(
/<script[\s\S]*?>[\s\S]*?<\/script>/gi,
);
if (!obfuscatedScripts?.length) {
throw new Error('Cannot download the video!');
if (/error/gi.test(html)) {
throw new Error(
html.split("'").find((x) => /(((url)? error)|could)/gi.test(x)),
);
} else {
const transformed = obfuscatedScripts[0]
.replace(/<(\/)?script( type=".+")?>/g, '')
.trim()
.replace('eval', '')
.replace(
/\(function(.)?\(h/gi,
'module.exports = (function (h',
);
const deObfuscated = new NodeVM({
compiler: 'javascript',
console: 'inherit',
require: {
external: true,
root: './',
},
}).run(transformed, 'deobfuscate.js');
return deObfuscated;
// only match script tag
const obfuscatedScripts = html.match(
/<script[\s\S]*?>[\s\S]*?<\/script>/gi,
);
if (!obfuscatedScripts?.length) {
throw new Error('Cannot download the video!');
} else {
const transformed = obfuscatedScripts[0]
.replace(/<(\/)?script( type=".+")?>/g, '')
.trim()
.replace('eval', '')
.replace(
/\(function(.)?\(h/gi,
'module.exports = (function (h',
);
const deObfuscated = new NodeVM({
compiler: 'javascript',
console: 'inherit',
require: {
external: true,
root: './',
},
}).run(transformed, 'deobfuscate.js');
return deObfuscated;
}
}
}
};
export const matchLink = (raw: string): string[] | null => {
return raw.match(
// eslint-disable-next-line max-len
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/gi,
);
return raw.match(
// eslint-disable-next-line max-len
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/gi,
);
};
export const matchCustomDownload = (
provider: string,
raw: string,
): string[] => {
const links = matchLink(raw) as string[];
const urls = raw
.match(/\/download.php\?token=(.*?)"/gi)
?.map(
(url) =>
(
const links = matchLink(raw) as string[];
const urls = raw
.match(/\/download.php\?token=(.*?)"/gi)
?.map(
(url) =>
(
getProvider(provider) as BaseProvider
).client!.defaults.options.prefixUrl.slice(0, -1) +
).client!.defaults.options.prefixUrl.slice(0, -1) +
url.slice(0, -3),
);
);
return [links[0]].concat(urls as string[]);
return [links[0]].concat(urls as string[]);
};
export const deObfuscateSaveFromScript = (scriptContent: string): string => {
const safeScript =
const safeScript =
'let result;' +
scriptContent
.replace(/\/\*js\-response\*\//gi, '')
@@ -90,14 +90,14 @@ export const deObfuscateSaveFromScript = (scriptContent: string): string => {
} else []['filter']['constructor'](b).call(a);`,
) +
'module.exports = result;';
const vm = new NodeVM({
compiler: 'javascript',
console: 'inherit',
require: {
external: true,
root: './',
},
});
const result = vm.run(safeScript, 'savefrom.js');
return result;
const vm = new NodeVM({
compiler: 'javascript',
console: 'inherit',
require: {
external: true,
root: './',
},
});
const result = vm.run(safeScript, 'savefrom.js');
return result;
};

View File

@@ -5,7 +5,7 @@
* @return {string | undefined}
*/
export const keyGeneratorTTSave = async (token: string): Promise<string> => {
const expectedLen = token.length / 3;
const expectedLen = token.length / 3;
return token.split('').reverse().join('').slice(-expectedLen);
return token.split('').reverse().join('').slice(-expectedLen);
};

View File

@@ -11,6 +11,7 @@
"lint": {},
"dev": {
"cache": false
}
},
"format": {}
}
}

View File

@@ -574,7 +574,19 @@ __metadata:
languageName: node
linkType: hard
"debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2":
"debug@npm:^4.1.1":
version: 4.3.3
resolution: "debug@npm:4.3.3"
dependencies:
ms: 2.1.2
peerDependenciesMeta:
supports-color:
optional: true
checksum: 14472d56fe4a94dbcfaa6dbed2dd3849f1d72ba78104a1a328047bb564643ca49df0224c3a17fa63533fd11dd3d4c8636cd861191232a2c6735af00cc2d4de16
languageName: node
linkType: hard
"debug@npm:^4.3.1, debug@npm:^4.3.2":
version: 4.3.2
resolution: "debug@npm:4.3.2"
dependencies:
@@ -692,6 +704,17 @@ __metadata:
languageName: node
linkType: hard
"eslint-config-prettier@npm:^8.5.0":
version: 8.5.0
resolution: "eslint-config-prettier@npm:8.5.0"
peerDependencies:
eslint: ">=7.0.0"
bin:
eslint-config-prettier: bin/cli.js
checksum: 0d0f5c32e7a0ad91249467ce71ca92394ccd343178277d318baf32063b79ea90216f4c81d1065d60f96366fdc60f151d4d68ae7811a58bd37228b84c2083f893
languageName: node
linkType: hard
"eslint-scope@npm:^5.1.1":
version: 5.1.1
resolution: "eslint-scope@npm:5.1.1"
@@ -904,9 +927,9 @@ __metadata:
linkType: hard
"flatted@npm:^3.1.0":
version: 3.2.2
resolution: "flatted@npm:3.2.2"
checksum: 9d5e03fd9309b9103f345cf6d0cef4fa46201baa053b0ca3d57fa489449b0bee687b7355407898f630afbb1a1286d2a6658e7e77dea3b85c3cd6c6ce2894a5c3
version: 3.2.5
resolution: "flatted@npm:3.2.5"
checksum: 3c436e9695ccca29620b4be5671dd72e5dd0a7500e0856611b7ca9bd8169f177f408c3b9abfa78dfe1493ee2d873e2c119080a8a9bee4e1a186a9e60ca6c89f1
languageName: node
linkType: hard
@@ -980,11 +1003,11 @@ __metadata:
linkType: hard
"globals@npm:^13.6.0, globals@npm:^13.9.0":
version: 13.12.0
resolution: "globals@npm:13.12.0"
version: 13.12.1
resolution: "globals@npm:13.12.1"
dependencies:
type-fest: ^0.20.2
checksum: 1f959abb11117916468a1afcba527eead152900cad652c8383c4e8976daea7ec55e1ee30c086f48d1b8655719f214e9d92eca083c3a43b5543bc4056e7e5fccf
checksum: cf7877629c8f2a293b0a7d09d1dcce7f2d426ec2528600c481c5b3f3d070b0a120eb2499439ac0404990fb8a5742c0165b1bf1f52603364001ddc89bea3dda24
languageName: node
linkType: hard
@@ -1547,6 +1570,15 @@ __metadata:
languageName: node
linkType: hard
"prettier@npm:^2.5.1":
version: 2.5.1
resolution: "prettier@npm:2.5.1"
bin:
prettier: bin-prettier.js
checksum: 21b9408476ea1c544b0e45d51ceb94a84789ff92095abb710942d780c862d0daebdb29972d47f6b4d0f7ebbfb0ffbf56cc2cfa3e3e9d1cca54864af185b15b66
languageName: node
linkType: hard
"pump@npm:^3.0.0":
version: 3.0.0
resolution: "pump@npm:3.0.0"
@@ -1798,7 +1830,10 @@ __metadata:
dependencies:
"@typescript-eslint/eslint-plugin": ^5.13.0
"@typescript-eslint/parser": ^5.13.0
eslint: ^8.10.0
eslint-config-google: ^0.14.0
eslint-config-prettier: ^8.5.0
prettier: ^2.5.1
languageName: unknown
linkType: soft
@@ -1809,6 +1844,7 @@ __metadata:
"@typescript-eslint/parser": ^5.13.0
eslint: ^8.10.0
got: ^11.8.2
prettier: ^2.5.1
vm2: ^3.9.6
languageName: unknown
linkType: soft