feat: added asyncRetry to prevent empty data
This commit is contained in:
parent
92d2e7ad94
commit
585158817c
@ -1,13 +1,14 @@
|
|||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
|
import asyncRetry from "async-retry"
|
||||||
import { _tiktokapi, _tiktokurl } from "../../api"
|
import { _tiktokapi, _tiktokurl } from "../../api"
|
||||||
import { Author, TiktokAPIResponse, Statistics, Music } from "../../types/tiktokApi"
|
import { Author, TiktokAPIResponse, Statistics, Music, responseParser } from "../../types/tiktokApi"
|
||||||
|
|
||||||
export const TiktokAPI = (url: string) =>
|
export const TiktokAPI = (url: string) =>
|
||||||
new Promise<TiktokAPIResponse>((resolve, reject) => {
|
new Promise<TiktokAPIResponse>((resolve, reject) => {
|
||||||
url = url.replace("https://vm", "https://vt")
|
url = url.replace("https://vm", "https://vt")
|
||||||
axios
|
axios
|
||||||
.head(url)
|
.head(url)
|
||||||
.then(({ request }) => {
|
.then(async ({ request }) => {
|
||||||
const { responseUrl } = request.res
|
const { responseUrl } = request.res
|
||||||
let ID = responseUrl.match(/\d{17,21}/g)
|
let ID = responseUrl.match(/\d{17,21}/g)
|
||||||
if (ID === null)
|
if (ID === null)
|
||||||
@ -16,107 +17,146 @@ export const TiktokAPI = (url: string) =>
|
|||||||
message: "Failed to fetch tiktok url. Make sure your tiktok url is correct!"
|
message: "Failed to fetch tiktok url. Make sure your tiktok url is correct!"
|
||||||
})
|
})
|
||||||
ID = ID[0]
|
ID = ID[0]
|
||||||
axios
|
|
||||||
.get(
|
|
||||||
_tiktokapi(
|
|
||||||
new URLSearchParams(
|
|
||||||
withParams({
|
|
||||||
aweme_id: ID
|
|
||||||
})
|
|
||||||
).toString()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.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
|
let data2 = await fetchTiktokData(ID)
|
||||||
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
|
if (!data2.content) {
|
||||||
const author: Author = {
|
return resolve({
|
||||||
uid: content.author.uid,
|
status: "error",
|
||||||
username: content.author.unique_id,
|
message: "Failed to fetch tiktok data. Make sure your tiktok url is correct!"
|
||||||
nickname: content.author.nickname,
|
})
|
||||||
signature: content.author.signature,
|
}
|
||||||
region: content.author.region,
|
|
||||||
avatarThumb: content.author.avatar_thumb.url_list,
|
|
||||||
avatarMedium: content.author.avatar_medium.url_list,
|
|
||||||
url: `${_tiktokurl}/@${content.author.unique_id}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Music Result
|
const { content, author, statistics, music } = data2
|
||||||
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
|
// Download Result
|
||||||
if (content.image_post_info) {
|
if (content.image_post_info) {
|
||||||
// Images or Slide Result
|
// Images or Slide Result
|
||||||
resolve({
|
resolve({
|
||||||
status: "success",
|
status: "success",
|
||||||
result: {
|
result: {
|
||||||
type: "image",
|
type: "image",
|
||||||
id: content.aweme_id,
|
id: content.aweme_id,
|
||||||
createTime: content.create_time,
|
createTime: content.create_time,
|
||||||
description: content.desc,
|
description: content.desc,
|
||||||
hashtag: content.text_extra.filter((x) => x.hashtag_name !== undefined).map((v) => v.hashtag_name),
|
hashtag: content.text_extra.filter((x) => x.hashtag_name !== undefined).map((v) => v.hashtag_name),
|
||||||
author,
|
author,
|
||||||
statistics,
|
statistics,
|
||||||
images: content.image_post_info.images.map((v) => v.display_image.url_list[0]),
|
images: content.image_post_info.images.map((v) => v.display_image.url_list[0]),
|
||||||
music
|
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 }))
|
} 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 }))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const fetchTiktokData = async (ID: string) => {
|
||||||
|
let data2: responseParser
|
||||||
|
await asyncRetry(
|
||||||
|
async () => {
|
||||||
|
const res = await fetch(
|
||||||
|
_tiktokapi(
|
||||||
|
new URLSearchParams(
|
||||||
|
withParams({
|
||||||
|
aweme_id: ID
|
||||||
|
})
|
||||||
|
).toString()
|
||||||
|
),
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"User-Agent": "com.ss.android.ugc.trill/494+Mozilla/5.0+(Linux;+Android+12;+2112123G+Build/SKQ1.211006.001;+wv)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Version/4.0+Chrome/107.0.5304.105+Mobile+Safari/537.36"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (res.headers.get("content-length") !== "0") {
|
||||||
|
const data = await res.json()
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
data2 = parseTiktokData(data)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error("Data is empty!")
|
||||||
|
},
|
||||||
|
{ forever: true, minTimeout: 0, maxTimeout: 0 }
|
||||||
|
)
|
||||||
|
|
||||||
|
return data2
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseTiktokData = (data: any): responseParser => {
|
||||||
|
let content = data?.aweme_list
|
||||||
|
|
||||||
|
if (!content) return { content: null }
|
||||||
|
|
||||||
|
content = content[0]
|
||||||
|
|
||||||
|
// Statistics 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,
|
||||||
|
avatarThumb: content.author.avatar_thumb.url_list,
|
||||||
|
avatarMedium: content.author.avatar_medium.url_list,
|
||||||
|
url: `${_tiktokurl}/@${content.author.unique_id}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
return { content, statistics, author, music }
|
||||||
|
}
|
||||||
|
|
||||||
const withParams = (args) => {
|
const withParams = (args) => {
|
||||||
return {
|
return {
|
||||||
...args,
|
...args,
|
||||||
@ -155,7 +195,7 @@ const withParams = (args) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const toMinute = (duration) => {
|
const toMinute = (duration: number) => {
|
||||||
const mins = ~~((duration % 3600) / 60)
|
const mins = ~~((duration % 3600) / 60)
|
||||||
const secs = ~~duration % 60
|
const secs = ~~duration % 60
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user