feat: typescript support

This commit is contained in:
aqulzz 2023-04-03 23:32:12 +07:00
parent 7594ba06c6
commit 562f063dff
12 changed files with 297 additions and 181 deletions

18
.eslintrc Normal file
View File

@ -0,0 +1,18 @@
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"parserOptions": {
"ecmaVersion": 2020,
"project": ["tsconfig.json"]
},
"rules": {
"no-empty": [2, { "allowEmptyCatch": true }],
"no-inner-declarations": [0, "both"],
"@typescript-eslint/no-unused-vars": 2,
"@typescript-eslint/consistent-type-definitions": [2, "type"]
},
"env": {
"node": true
}
}

4
.gitignore vendored
View File

@ -1,3 +1,5 @@
node_modules node_modules
yarn-lock.json yarn-lock.json
package-lock.json package-lock.json
yarn.lock
lib

View File

@ -1,4 +1,7 @@
node_modules node_modules
yarn-lock.json yarn-lock.json
package-lock.json package-lock.json
.gitignore .gitignore
tsconfig.json
.eslintrc
.prettierrc

16
.prettierrc Normal file
View File

@ -0,0 +1,16 @@
{
"arrowParens": "always",
"endOfLine": "auto",
"printWidth": 333,
"semi": false,
"tabWidth": 2,
"trailingComma": "none",
"overrides": [
{
"files": ["./src/types/*.ts"],
"options": {
"printWidth": 150
}
}
]
}

View File

@ -23,7 +23,7 @@ yarn add @tobyg74/tiktok-api-dl
### Tiktok Downloader ### Tiktok Downloader
``` ```js
const { TiktokDL } = require("@tobyg74/tiktok-api-dl"); const { TiktokDL } = require("@tobyg74/tiktok-api-dl");
const tiktok_url = "https://vt.tiktok.com/ZS84BnrU9" const tiktok_url = "https://vt.tiktok.com/ZS84BnrU9"
@ -36,7 +36,7 @@ TiktokDL(tiktok_url)
### Tiktok Profile ### Tiktok Profile
``` ```js
const { TiktokStalk } = require("@tobyg74/tiktok-api-dl"); const { TiktokStalk } = require("@tobyg74/tiktok-api-dl");
const username = "tobz2k19" const username = "tobz2k19"
@ -51,50 +51,58 @@ TiktokStalk(username)
### Tiktok Downloader ### Tiktok Downloader
``` ```ts
{ {
status: "success", status: "success" | "error"
result: { message?: string
type: "video" // "image", result?: {
id: ..., type: "video" | "image"
create_time: ..., id: string
description: ..., create_time: number
description: string
author: { author: {
... username: string
}, nickname: string
signature: string
birthday: string
region: string
}
statistics: { statistics: {
... play_count: number
}, download_count: number
video // images: [ share_count: number
... comment_count: number
], like_count: number
music: [ favourite_count: number
... }
] video?: string[]
images?: string[]
music: string[]
} }
} }
``` ```
### Tiktok Profile ### Tiktok Profile
``` ```ts
{ {
status: "success", status: "success" | "error"
result: { message?: string
result?: {
users: { users: {
username: ..., username: string
nickname: ..., nickname: string
avatar: ..., avatar: string
signature: ..., signature: string
verified: ..., verified: boolean
region: ... region: string
}, }
stats: { stats: {
followerCount: ..., followerCount: number
followingCount: ..., followingCount: number
heartCount: ..., heartCount: number
videoCount: ..., videoCount: number
likeCount: ... likeCount: number
} }
} }
} }

View File

@ -1,3 +0,0 @@
const { TiktokDL, TiktokStalk } = require("./utils");
module.exports = { TiktokDL, TiktokStalk };

View File

@ -1,10 +1,12 @@
{ {
"name": "@tobyg74/tiktok-api-dl", "name": "@tobyg74/tiktok-api-dl",
"version": "1.0.2-fix", "version": "1.0.3",
"description": "Scrapper for download Video, Image, Music from Tiktok", "description": "Scrapper for download Video, Image, Music from Tiktok",
"main": "index.js", "main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1",
"build": "tsc"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -18,6 +20,7 @@
"tiktok" "tiktok"
], ],
"author": "Tobz", "author": "Tobz",
"contributors": ["aqulzz"],
"license": "ISC", "license": "ISC",
"bugs": { "bugs": {
"url": "https://github.com/TobyG74/tiktok-api-dl/issues" "url": "https://github.com/TobyG74/tiktok-api-dl/issues"
@ -26,5 +29,10 @@
"dependencies": { "dependencies": {
"axios": "^1.3.4", "axios": "^1.3.4",
"cheerio": "^1.0.0-rc.12" "cheerio": "^1.0.0-rc.12"
},
"devDependencies": {
"@types/cheerio": "^0.22.31",
"@types/node": "^18.15.11",
"typescript": "^5.0.3"
} }
} }

1
src/index.ts Normal file
View File

@ -0,0 +1 @@
export * from "./utils"

50
src/types/index.ts Normal file
View File

@ -0,0 +1,50 @@
export type DLResult = {
status: "success" | "error"
message?: string
result?: {
type: "video" | "image"
id: string
create_time: number
description: string
author: {
username: string
nickname: string
signature: string
birthday: string
region: string
}
statistics: {
play_count: number
download_count: number
share_count: number
comment_count: number
like_count: number
favourite_count: number
}
video?: string[]
images?: string[]
music: string[]
}
}
export type StalkResult = {
status: "success" | "error"
message?: string
result?: {
users: {
username: string
nickname: string
avatar: string
signature: string
verified: boolean
region: string
}
stats: {
followerCount: number
followingCount: number
heartCount: number
videoCount: number
likeCount: number
}
}
}

130
src/utils/index.ts Normal file
View File

@ -0,0 +1,130 @@
import axios from "axios"
import { load } from "cheerio"
import { DLResult, StalkResult } from "../types"
const _tiktokurl: string = "https://www.tiktok.com"
const _tiktokapi = (id: string): string =>
`https://api16-va.tiktokv.com/aweme/v1/feed/?aweme_id=${id}&version_name=1.1.9&version_code=119&build_number=1.1.9&manifest_version_code=119&update_version_code=119&openudid=dlcrw3zg28ajm4ml&uuid=3703699664470627&_rticket=1677813932976&ts=1677813932&device_brand=Realme&device_type=RMX1821&device_platform=android&resolution=720*1370&dpi=320&os_version=11&os_api=30&carrier_region=US&sys_region=US%C2%AEion=US&app_name=TK%20Downloader&app_language=en&language=en&timezone_name=Western%20Indonesia%20Time&timezone_offset=25200&channel=googleplay&ac=wifi&mcc_mnc=&is_my_cn=0&aid=1180&ssmix=a&as=a1qwert123`
export const TiktokDL = (url: string): Promise<DLResult> =>
new Promise((resolve, reject) => {
url = url.replace("https://vm", "https://vt")
axios
.head(url)
.then(({ request }) => {
const { responseUrl } = request.res
let ID = responseUrl.match(/\d{17,21}/g)
if (ID === null)
return reject({
status: "error",
message: "Failed to fetch tiktok url. Make sure your tiktok url is correct!"
})
ID = ID[0]
axios
.get(_tiktokapi(ID))
.then(({ data }) => {
const content = data.aweme_list.filter((v) => v.aweme_id === ID)[0]
if (!content)
return resolve({
status: "error",
message: "Failed to find tiktok data. Make sure your tiktok url is correct!"
})
const statistics = {
play_count: content.statistics.play_count,
download_count: content.statistics.download_count,
share_count: content.statistics.share_count,
comment_count: content.statistics.comment_count,
like_count: content.statistics.digg_count,
favourite_count: content.statistics.collect_count
}
const author = {
username: content.author.unique_id,
nickname: content.author.nickname,
signature: content.author.signature,
birthday: content.author.birthday,
region: content.author.region
}
if (content.image_post_info) {
resolve({
status: "success",
result: {
type: "image",
id: content.aweme_id,
create_time: content.create_time,
description: content.desc,
author,
statistics,
images: content.image_post_info.images.map((v) => v.display_image.url_list[0]),
music: content.music.play_url.url_list
}
})
} else {
resolve({
status: "success",
result: {
type: "video",
id: content.aweme_id,
create_time: content.create_time,
description: content.desc,
author,
statistics,
video: content.video.play_addr.url_list,
music: content.music.play_url.url_list
}
})
}
})
.catch(reject)
})
.catch(reject)
})
export const TiktokStalk = (username: string): Promise<StalkResult> =>
new Promise((resolve, reject) => {
axios
.get("https://pastebin.com/raw/ELJjcbZT")
.then(({ data: cookie }) => {
username = username.replace("@", "")
axios
.get(`${_tiktokurl}/@${username}`, {
headers: {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36",
cookie: cookie
}
})
.then(({ data }) => {
const $ = load(data)
const result = JSON.parse($("script#SIGI_STATE").text())
if (!result.UserModule) {
return resolve({
status: "error",
message: "User not found!"
})
}
const user = result.UserModule
const users = {
username: user.users[username].uniqueId,
nickname: user.users[username].nickname,
avatar: user.users[username].avatarLarger,
signature: user.users[username].signature,
verified: user.users[username].verified,
region: user.users[username].region
}
const stats = {
followerCount: user.stats[username].followerCount,
followingCount: user.stats[username].followingCount,
heartCount: user.stats[username].heartCount,
videoCount: user.stats[username].videoCount,
likeCount: user.stats[username].diggCount
}
resolve({
status: "success",
result: {
users,
stats
}
})
})
})
.catch((e) => resolve({ status: "error", message: e.message }))
})

22
tsconfig.json Normal file
View File

@ -0,0 +1,22 @@
{
"compilerOptions": {
"allowJs": false,
"checkJs": false,
"esModuleInterop": true,
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"lib": ["ES2020", "ESNext.Array", "DOM"],
"module": "CommonJS",
"moduleResolution": "node",
"noImplicitThis": true,
"outDir": "lib",
"removeComments": true,
"resolveJsonModule": true,
"rootDir": "src",
"skipLibCheck": true,
"declaration": true,
"target": "ES2020"
},
"exclude": ["node_modules"],
"include": ["./src/**/*.ts"]
}

View File

@ -1,139 +0,0 @@
const Axios = require("axios");
const cheerio = require("cheerio");
const _tiktokurl = "https://www.tiktok.com";
const _tiktokapi = (id) =>
`https://api16-va.tiktokv.com/aweme/v1/feed/?aweme_id=${id}&version_name=1.1.9&version_code=119&build_number=1.1.9&manifest_version_code=119&update_version_code=119&openudid=dlcrw3zg28ajm4ml&uuid=3703699664470627&_rticket=1677813932976&ts=1677813932&device_brand=Realme&device_type=RMX1821&device_platform=android&resolution=720*1370&dpi=320&os_version=11&os_api=30&carrier_region=US&sys_region=US%C2%AEion=US&app_name=TK%20Downloader&app_language=en&language=en&timezone_name=Western%20Indonesia%20Time&timezone_offset=25200&channel=googleplay&ac=wifi&mcc_mnc=&is_my_cn=0&aid=1180&ssmix=a&as=a1qwert123`;
const TiktokDL = (url) => {
return new Promise((resolve, reject) => {
url = url.replace("https://vm", "https://vt");
Axios(url, {
method: "HEAD",
})
.then(({ request }) => {
const { responseUrl } = request.res;
let ID = responseUrl.match(/\d{17,21}/g);
if (ID === null)
return reject({
status: "error",
message:
"Failed to fetch tiktok url. Make sure your tiktok url is correct!",
});
ID = ID[0];
Axios(_tiktokapi(ID), {
method: "GET",
})
.then(({ data }) => {
const content = data.aweme_list.filter((v) => v.aweme_id === ID)[0];
if (!content)
return resolve({
status: "error",
message:
"Failed to find tiktok data. Make sure your tiktok url is correct!",
});
const statistics = {
play_count: content.statistics.play_count,
download_count: content.statistics.download_count,
share_count: content.statistics.share_count,
comment_count: content.statistics.comment_count,
like_count: content.statistics.digg_count,
favourite_count: content.statistics.collect_count,
};
const author = {
username: content.author.unique_id,
nickname: content.author.nickname,
signature: content.author.signature,
birthday: content.author.birthday,
region: content.author.region,
};
if (content.image_post_info) {
resolve({
status: "success",
result: {
type: "image",
id: content.aweme_id,
create_time: content.create_time,
description: content.desc,
author,
statistics,
images: content.image_post_info.images.map(
(v) => v.display_image.url_list[0]
),
music: content.music.play_url.url_list,
},
});
} else {
resolve({
status: "success",
result: {
type: "video",
id: content.aweme_id,
create_time: content.create_time,
description: content.desc,
author,
statistics,
video: content.video.play_addr.url_list,
music: content.music.play_url.url_list,
},
});
}
})
.catch(reject);
})
.catch(reject);
});
};
const TiktokStalk = (username) => {
return new Promise(async (resolve, reject) => {
const { data: cookie } = await Axios.get("https://pastebin.com/raw/ELJjcbZT");
username = username.replace("@", "");
Axios(`${_tiktokurl}/@${username}`, {
method: "GET",
headers: {
"user-agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36",
cookie: cookie,
},
})
.then(({ data }) => {
const $ = cheerio.load(data);
const result = JSON.parse($("script#SIGI_STATE").text());
if (!result.UserModule) {
return resolve({
status: "error",
message: "User not found!",
});
}
const user = result.UserModule;
const users = {
username: user.users[username].uniqueId,
nickname: user.users[username].nickname,
avatar: user.users[username].avatarLarger,
signature: user.users[username].signature,
verified: user.users[username].verified,
region: user.users[username].region,
};
const stats = {
followerCount: user.stats[username].followerCount,
followingCount: user.stats[username].followingCount,
heartCount: user.stats[username].heartCount,
videoCount: user.stats[username].videoCount,
likeCount: user.stats[username].diggCount,
};
resolve({
status: "success",
result: {
users,
stats,
},
});
})
.catch((e) => {
resolve({ status: "error", message: e.message });
});
});
};
module.exports = { TiktokDL, TiktokStalk };