diff --git a/src/constants/api.ts b/src/constants/api.ts index e60c844..c24ade0 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -1,10 +1,13 @@ /** Tiktok */ export const _tiktokurl: string = "https://www.tiktok.com" -export const _tiktokapi = (params: any): string => `https://api.tiktokv.com/aweme/v1/feed/?${params}` export const _tiktokSearchUserFull = (params: any): string => `${_tiktokurl}/api/search/user/full/?${params}` export const _tiktokSearchVideoFull = (params: any): string => `${_tiktokurl}/api/search/item/full/?${params}` export const _tiktokGetPosts = (params: any) => `${_tiktokurl}/api/post/item_list/?${params}` +/** Tiktokv */ +export const _tiktokvApi: string = `https://api.tiktokv.com` +export const _tiktokvFeed = (params: any): string => `${_tiktokvApi}/aweme/v1/feed/?${params}` + /** SSSTik */ export const _ssstikurl: string = "https://ssstik.io" export const _ssstikapi: string = `${_ssstikurl}/abc?url=dl` diff --git a/src/utils/downloader/ssstik.ts b/src/utils/downloader/ssstik.ts index ea38e9d..a15fd17 100644 --- a/src/utils/downloader/ssstik.ts +++ b/src/utils/downloader/ssstik.ts @@ -1,4 +1,5 @@ import Axios from "axios" +import asyncRetry from "async-retry" import { load } from "cheerio" import { Author, Statistics, SSSTikFetchTT, SSSTikResponse } from "../../types/downloader/ssstik" import { _ssstikapi, _ssstikurl } from "../../constants/api" @@ -22,9 +23,9 @@ const fetchTT = () => const match = data.match(regex) if (match) { const value = match[1] - resolve({ status: "success", result: value }) + return resolve({ status: "success", result: value }) } else { - resolve({ status: "error", message: "Failed to get the request form!" }) + return resolve({ status: "error", message: "Failed to get the request form!" }) } }) .catch((e) => resolve({ status: "error", message: e.message })) @@ -37,81 +38,101 @@ const fetchTT = () => */ export const SSSTik = (url: string) => - new Promise(async (resolve, reject) => { - if (!TiktokURLregex.test(url)) { - return resolve({ - status: "error", - message: "Invalid Tiktok URL. Make sure your url is correct!" - }) - } - const tt: SSSTikFetchTT = await fetchTT() - if (tt.status !== "success") return resolve({ status: "error", message: tt.message }) - Axios(_ssstikapi, { - method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", - Origin: _ssstikurl, - Referer: _ssstikurl + "/en", - "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0" - }, - data: new URLSearchParams( - Object.entries({ - id: url, - locale: "en", - tt: tt.result + new Promise(async (resolve) => { + try { + if (!TiktokURLregex.test(url)) { + return resolve({ + status: "error", + message: "Invalid Tiktok URL. Make sure your url is correct!" }) + } + const tt: SSSTikFetchTT = await fetchTT() + if (tt.status !== "success") return resolve({ status: "error", message: tt.message }) + + const response = asyncRetry( + async () => { + const res = await Axios(_ssstikapi, { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", + Origin: _ssstikurl, + Referer: _ssstikurl + "/en", + "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0" + }, + data: new URLSearchParams( + Object.entries({ + id: url, + locale: "en", + tt: tt.result + }) + ) + }) + + if (res.status === 200 && res.data !== "") return res.data + + throw new Error("Failed to fetch data from SSSTik!") + }, + { + retries: 20, + minTimeout: 200, + maxTimeout: 1000 + } ) - }) - .then(({ data }) => { - const $ = load(data) - // Result - const desc = $("p.maintext").text().trim() - const author: Author = { - avatar: $("img.result_author").attr("src"), - nickname: $("h2").text().trim() - } - const statistics: Statistics = { - likeCount: $("#trending-actions > .justify-content-start").text().trim(), - commentCount: $("#trending-actions > .justify-content-center").text().trim(), - shareCount: $("#trending-actions > .justify-content-end").text().trim() - } + const $ = load(await response) + // Result + const desc = $("p.maintext").text().trim() + const author: Author = { + avatar: $("img.result_author").attr("src"), + nickname: $("h2").text().trim() + } + const statistics: Statistics = { + likeCount: $("#trending-actions > .justify-content-start").text().trim(), + commentCount: $("#trending-actions > .justify-content-center").text().trim(), + shareCount: $("#trending-actions > .justify-content-end").text().trim() + } + + // Video & Music Result + const video = $("a.without_watermark").attr("href") + const music = $("a.music").attr("href") + + // Images / Slide Result + const images: string[] = [] + $("ul.splide__list > li") + .get() + .map((img) => { + images.push($(img).find("a").attr("href")) + }) + + if (images.length !== 0 && music) { // Images / Slide Result - const images: string[] = [] - $("ul.splide__list > li") - .get() - .map((img) => { - images.push($(img).find("a").attr("href")) - }) - - if (images.length !== 0) { - // Images / Slide Result - resolve({ - status: "success", - result: { - type: "image", - desc, - author, - statistics, - images, - music: $("a.music").attr("href") - } - }) - } else { - // Video Result - resolve({ - status: "success", - result: { - type: "video", - desc, - author, - statistics, - video: $("a.without_watermark").attr("href"), - music: $("a.music").attr("href") - } - }) - } - }) - .catch((e) => resolve({ status: "error", message: e.message })) + resolve({ + status: "success", + result: { + type: "image", + desc, + author, + statistics, + images, + music + } + }) + } else if (video && music) { + // Video Result + resolve({ + status: "success", + result: { + type: "video", + desc, + author, + statistics, + video, + music + } + }) + } + } catch (err) { + resolve({ status: "error", message: err.message }) + } }) diff --git a/src/utils/downloader/tiktokApi.ts b/src/utils/downloader/tiktokApi.ts index e8ac8a1..293f0ff 100644 --- a/src/utils/downloader/tiktokApi.ts +++ b/src/utils/downloader/tiktokApi.ts @@ -1,5 +1,5 @@ import Axios from "axios" -import { _tiktokapi, _tiktokurl } from "../../constants/api" +import { _tiktokvFeed, _tiktokurl } from "../../constants/api" import { _tiktokApiParams } from "../../constants/params" import { Author, TiktokAPIResponse, Statistics, Music, responseParser, Video } from "../../types/downloader/tiktokApi" @@ -94,7 +94,7 @@ export const TiktokAPI = (url: string) => const fetchTiktokData = async (ID: string): Promise | null => { const res = await fetch( - _tiktokapi( + _tiktokvFeed( new URLSearchParams( _tiktokApiParams({ aweme_id: ID @@ -104,6 +104,8 @@ const fetchTiktokData = async (ID: string): Promise | null => { { method: "GET", headers: { + Cookie: + "tt_csrf_token=g1GUApj0-ADAIP9COU6o1m1_NnbwhKGTbiyI; ttwid=1%7CvqigUFT-mdDjU8gnwF3hkh8sPQqokFjCRyD7R1jpM44%7C1720342326%7Cc8c89833ea6bb912642ea1340ef98691ad3382878374ec61a5de85eeb5d79e83; ak_bmsc=C3345397EF8621798FA50BACA05F1AD3~000000000000000000000000000000~YAAQhq0wFzqUPlOQAQAA+ctjjBiYLJJ3WVeqfLXcnxTCKMkcRlAYLT+GxhKgkMdR94wzPi2zqWiZfuEUdBpaJmo01qZY4M4dUO6xiYqbXZev0cFbauilIxyj1WRUHOy9+oAUCAkyWRMubLICOr1g9XUc7eadCgHCEnmwfVYe6mYbkwaqDMn/0mgxdqJCjnLFnEQTLG1FXUYkhk1sjrzg1ubRwJLuAdw4T+FZg2mYeQIdFuo/CUPf8Jw2UYfNd…XkpqwL-3Zzf_VO_mXrptr32f1D4TVmQPhR1FNen76-b7g2Tey2UlUrFD1fhpjJmOySmQtS_eW0p8BVLJthEcysTN98LLGTkAzD7M335V27Rf0zxX8ZsVWE6wa2P7x5X-HNmCwEO_WccrcClQifgb2PCKYDmhpG5BWNwoer5-8ak1SwZjybv_hdspeNhpbylwg4sNLRc_OiunUK0tYW2hiV7xrliwDKsIMVsZcQ0kwvBmp0eyUQJrEJv0fnzoS0o_jKMFtTvUChfEVz0Laj5O4MKf52isC30U3q; last_login_method=google; passport_fe_beating_status=true; msToken=ftn8ICq2_TfkkAyS3f6umBK1FafalSQ_IyzJxq1LmeBmDe2QxefwBfd_weMdvJI3TU5Z8gyFmzJdPSMESb5zUeseZysme5LBC19xouQTYAAMfVV35YliLfxMWhWZ_2ABP_uYMFNDJ5jtYE4Ap6uRyA==", "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" } }