feat: splitting multiple files for easy reading

This commit is contained in:
TobyG74 2023-10-07 21:33:23 +07:00
parent 3bedf837c2
commit 300530a161
7 changed files with 283 additions and 194 deletions

2
src/api/index.ts Normal file
View File

@ -0,0 +1,2 @@
export const _tiktokurl: string = "https://www.tiktok.com"
export const _tiktokapi = (id: string): string => `https://api16-core.tiktokv.com/aweme/v1/feed/?aweme_id=${id}`

57
src/types/downloader.ts Normal file
View File

@ -0,0 +1,57 @@
export interface DLResult {
status: "success" | "error"
message?: string
result?: {
type: "video" | "image"
id: string
createTime: number
description: string
duration?: string
author: Author
statistics: Statistics
hashtag: string[]
cover?: string[]
dynamicCover?: string[]
originCover?: string[]
video?: string[]
images?: string[]
music: Music
}
}
export interface Author {
uid: number
username: string
nickname: string
signature: string
region: string
avatarLarger: string[]
avatarThumb: string[]
avatarMedium: string[]
url: string
}
export interface Statistics {
playCount: number
downloadCount: number
shareCount: number
commentCount: number
likeCount: number
favoriteCount: number
forwardCount: number
whatsappShareCount: number
loseCount: number
loseCommentCount: number
}
export interface Music {
id: number
title: string
author: string
album: string
playUrl: string[]
coverLarge: string[]
coverMedium: string[]
coverThumb: string[]
duration: number
}

View File

@ -1,61 +1,2 @@
export interface DLResult {
status: "success" | "error"
message?: string
result?: {
type: "video" | "image"
id: string
createTime: number
description: string
author: Author
statistics: Statistics
video?: string[]
cover?: string[]
dynamic_cover?: string[]
images?: string[]
music: string[]
}
}
export interface Author {
uid: number
username: string
nickname: string
signature: string
birthday: string
region: string
}
export interface Statistics {
playCount: number
downloadCount: number
shareCount: number
commentCount: number
likeCount: number
favoriteCount: number
}
export interface StalkResult {
status: "success" | "error"
message?: string
result?: {
users: Users
stats: Stats
}
}
export interface Users {
username: string
nickname: string
avatar: string
signature: string
verified: boolean
region: string
}
export interface Stats {
followerCount: number
followingCount: number
heartCount: number
videoCount: number
likeCount: number
}
export * from "./downloader"
export * from "./stalker"

31
src/types/stalker.ts Normal file
View File

@ -0,0 +1,31 @@
export interface StalkResult {
status: "success" | "error"
message?: string
result?: {
users: Users
stats: Stats
}
}
export interface Users {
username: string
nickname: string
avatarLarger: string
avatarThumb: string
avatarMedium: string
signature: string
verified: boolean
region: string
commerceUser: boolean
usernameModifyTime: number
nicknameModifyTime: number
}
export interface Stats {
followerCount: number
followingCount: number
heartCount: number
videoCount: number
likeCount: number
friendCount: number
}

123
src/utils/downloader.ts Normal file
View File

@ -0,0 +1,123 @@
import axios from "axios"
import { _tiktokapi, _tiktokurl } from "../api"
import { Author, DLResult, Statistics, Music } from "../types"
const toMinute = (duration) => {
const mins = ~~((duration % 3600) / 60)
const secs = ~~duration % 60
let ret = ""
ret += "" + mins + ":" + (secs < 10 ? "0" : "")
ret += "" + secs
return ret
}
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 resolve({
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!"
})
// Statictics Result
const statistics: Statistics = {
playCount: content.statistics.play_count,
downloadCount: content.statistics.download_count,
shareCount: content.statistics.share_count,
commentCount: content.statistics.comment_count,
likeCount: content.statistics.digg_count,
favoriteCount: content.statistics.collect_count,
forwardCount: content.statistics.forward_count,
whatsappShareCount: content.statistics.whatsapp_share_count,
loseCount: content.statistics.lose_count,
loseCommentCount: content.statistics.lose_comment_count
}
// Author Result
const author: Author = {
uid: content.author.uid,
username: content.author.unique_id,
nickname: content.author.nickname,
signature: content.author.signature,
region: content.author.region,
avatarLarger: content.author.avatar_larger.url_list,
avatarThumb: content.author.avatar_thumb.url_list,
avatarMedium: content.author.avatar_medium.url_list,
url: `${_tiktokurl}/@${content.username}`
}
// Music Result
const music: Music = {
id: content.music.id,
title: content.music.title,
author: content.music.author,
album: content.music.album,
playUrl: content.music.play_url.url_list,
coverLarge: content.music.cover_large.url_list,
coverMedium: content.music.cover_medium.url_list,
coverThumb: content.music.cover_thumb.url_list,
duration: content.music.duration
}
// Download Result
if (content.image_post_info) {
// Images or Slide Result
resolve({
status: "success",
result: {
type: "image",
id: content.aweme_id,
createTime: content.create_time,
description: content.desc,
hashtag: content.text_extra.filter((x) => x.hashtag_name !== undefined).map((v) => v.hashtag_name),
author,
statistics,
images: content.image_post_info.images.map((v) => v.display_image.url_list[0]),
music
}
})
} else {
// Video Result
resolve({
status: "success",
result: {
type: "video",
id: content.aweme_id,
createTime: content.create_time,
description: content.desc,
hashtag: content.text_extra.filter((x) => x.hashtag_name !== undefined).map((v) => v.hashtag_name),
duration: toMinute(content.duration),
author,
statistics,
video: content.video.play_addr.url_list,
cover: content.video.cover.url_list,
dynamicCover: content.video.dynamic_cover.url_list,
originCover: content.video.origin_cover.url_list,
music
}
})
}
})
.catch((e) => resolve({ status: "error", message: e.message }))
})
.catch((e) => resolve({ status: "error", message: e.message }))
})

View File

@ -1,133 +1,2 @@
import axios from "axios"
import { load } from "cheerio"
import { Author, DLResult, StalkResult, Statistics, Stats, Users } from "../types"
const _tiktokurl: string = "https://www.tiktok.com"
const _tiktokapi = (id: string): string => `https://api16-core.tiktokv.com/aweme/v1/feed/?aweme_id=${id}&openudid=vi8vz5c5aec5wllw&uuid=7661132520610792&_rticket=1694319262046&ts=1694319262&device_platform=android&channel=googleplay&ac=wifi`
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 resolve({
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: Statistics = {
playCount: content.statistics.play_count,
downloadCount: content.statistics.download_count,
shareCount: content.statistics.share_count,
commentCount: content.statistics.comment_count,
likeCount: content.statistics.digg_count,
favoriteCount: content.statistics.collect_count
}
const author: Author = {
uid: content.author.uid,
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,
createTime: 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,
createTime: content.create_time,
description: content.desc,
author,
statistics,
video: content.video.play_addr.url_list,
cover: content.video.cover.url_list,
dynamic_cover: content.video.dynamic_cover.url_list,
music: content.music.play_url.url_list
}
})
}
})
.catch((e) => resolve({ status: "error", message: e.message }))
})
.catch((e) => reject(e))
})
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: 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: 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 }))
})
.catch((e) => reject(e))
})
export * from "./downloader"
export * from "./stalker"

66
src/utils/stalker.ts Normal file
View File

@ -0,0 +1,66 @@
import axios from "axios"
import { load } from "cheerio"
import { _tiktokurl } from "../api"
import { StalkResult, Stats, Users } from "../types"
const getCookie = () =>
new Promise((resolve, reject) => {
axios
.get("https://pastebin.com/raw/ELJjcbZT")
.then(({ data: cookie }) => {
resolve(cookie)
})
.catch((e) => resolve({ status: "error", message: "Failed to fetch cookie." }))
})
export const TiktokStalk = (username: string, options: { cookie: string }): Promise<StalkResult> =>
new Promise(async (resolve, reject) => {
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: (options?.cookie ? options.cookie : await getCookie()) as string
}
})
.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: Users = {
username: user.users[username].uniqueId,
nickname: user.users[username].nickname,
avatarLarger: user.users[username].avatarLarger,
avatarThumb: user.users[username].avatarThumb,
avatarMedium: user.users[username].avatarMedium,
signature: user.users[username].signature,
verified: user.users[username].verified,
region: user.users[username].region,
commerceUser: user.users[username].commerceUserInfo.commerceUser,
usernameModifyTime: user.users[username].uniqueIdModifyTime,
nicknameModifyTime: user.users[username].nickNameModifyTime
}
const stats: 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,
friendCount: user.stats[username].friendCount
}
resolve({
status: "success",
result: {
users,
stats
}
})
})
.catch((e) => resolve({ status: "error", message: e.message }))
})