feat: splitting multiple files for easy reading
This commit is contained in:
parent
3bedf837c2
commit
300530a161
2
src/api/index.ts
Normal file
2
src/api/index.ts
Normal 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
57
src/types/downloader.ts
Normal 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
|
||||
}
|
||||
@ -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
31
src/types/stalker.ts
Normal 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
123
src/utils/downloader.ts
Normal 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 }))
|
||||
})
|
||||
@ -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
66
src/utils/stalker.ts
Normal 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 }))
|
||||
})
|
||||
Loading…
x
Reference in New Issue
Block a user