feat: added tiktok downloader v3

This commit is contained in:
TobyG74 2023-10-14 19:09:31 +07:00
parent 6f18c5112e
commit f5849a600f
5 changed files with 176 additions and 9 deletions

View File

@ -2,3 +2,6 @@ export const _tiktokurl: string = "https://www.tiktok.com"
export const _tiktokapi = (id: string): string => `https://api.tiktokv.com/aweme/v1/feed/?aweme_id=${id}`
export const _ssstikapi: string = "https://ssstik.io/abc?url=dl"
export const _ssstikurl: string = "https://ssstik.io"
export const _musicaldownapi: string = "https://musicaldown.com/download"
export const _musicaldownurl: string = "https://musicaldown.com"
export const _musicaldownmusicapi: string = "https://musicaldown.com/mp3/download"

32
src/types/musicaldown.ts Normal file
View File

@ -0,0 +1,32 @@
export interface getRequest {
status: "success" | "error"
request?: {
[key: string]: string
}
message?: string
cookie?: string
}
export interface MusicalDownResponse {
status: "success" | "error"
message?: string
result?: {
type: "video" | "image"
desc?: string
author: {
avatar?: string
nickname: string
}
music?: string
images?: string[]
video1?: string
video2?: string
video_hd?: string
video_watermark?: string
}
}
export interface getMusic {
status: "success" | "error"
result?: string
}

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

@ -0,0 +1,123 @@
import Axios from "axios"
import { load } from "cheerio"
import { MusicalDownResponse, getMusic, getRequest } from "../types/musicaldown"
import { _musicaldownapi, _musicaldownmusicapi, _musicaldownurl } from "../api"
/**
* Using API from Website:
* BASE URL : https://ssstik.io
*/
const getRequest = (url: string) =>
new Promise<getRequest>((resolve, reject) => {
Axios.get(_musicaldownurl, {
headers: {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0"
}
})
.then((data) => {
const cookie = data.headers["set-cookie"][0].split(";")[0] + "; " + "lang=en"
const $ = load(data.data)
const input = $("div > input").map((_, el) => $(el))
const request = {
[input.get(0).attr("name")]: url,
[input.get(1).attr("name")]: input.get(1).attr("value"),
[input.get(2).attr("name")]: input.get(2).attr("value")
}
resolve({ status: "success", request, cookie })
})
.catch((e) => resolve({ status: "error", message: "Failed to get the request form!" }))
})
const getMusic = (cookie: string) =>
new Promise<getMusic>((resolve, reject) => {
Axios.get(_musicaldownmusicapi, {
headers: {
cookie: cookie,
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0"
}
})
.then(({ data }) => {
const $ = load(data)
const music = $("audio > source").attr("src")
resolve({ status: "success", result: music })
})
.catch((e) => resolve({ status: "error" }))
})
export const MusicalDown = (url: string) =>
new Promise<MusicalDownResponse>(async (resolve, reject) => {
const request: getRequest = await getRequest(url)
if (request.status !== "success") return resolve({ status: "error", message: request.message })
Axios(_musicaldownapi, {
method: "POST",
headers: {
cookie: request.cookie,
"Upgrade-Insecure-Requests": "1",
"Content-Type": "application/x-www-form-urlencoded",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0"
},
data: new URLSearchParams(Object.entries(request.request))
})
.then(async ({ data }) => {
const $ = load(data)
// Get Image Video
const images = []
$("div.row > div[class='col s12 m3']")
.get()
.map((v) => {
images.push($(v).find("img").attr("src"))
})
// Get Result Video
let i = 1
let videos = {}
$("div[class='col s12 l8'] > a")
.get()
.map((v) => {
if ($(v).attr("href") !== "#modal2") {
let text = $(v).text().trim().replace(/\s/, " ").replace("arrow_downward", "").toLowerCase()
videos[text.includes("hd") ? "video_hd" : text.includes("watermark") ? "video_watermark" : `video${i}`] = $(v).attr("href")
i++
}
})
// Result
if (images.length !== 0) {
// Images or Slide Result
resolve({
status: "success",
result: {
type: "image",
author: {
nickname: $("h2.white-text").text().trim().replace("Download Now: Check out ", "").replace("s video! #TikTok >If MusicallyDown has helped you, you can help us too", "").replace("Download Now: ", "").replace("If MusicallyDown has helped you, you can help us too", "")
},
images,
music: $("a.download").attr("href")
}
})
} else {
// Video Result
const music = await getMusic(request.cookie)
resolve({
status: "success",
result: {
type: "video",
author: {
avatar: $("div.img-area > img").attr("src"),
nickname: $("div.row > div > div > h2")
.map((_, el) => $(el).text())
.get(0)
},
desc: $("div.row > div > div > h2")
.map((_, el) => $(el).text())
.get(1),
music: music.result,
...videos
}
})
}
})
.catch((e) => resolve({ status: "error", message: e.message }))
})

View File

@ -3,6 +3,11 @@ import { load } from "cheerio"
import { Author, Statistics, SSSTikFetchTT, SSSTikResult } from "../types/ssstik"
import { _ssstikapi, _ssstikurl } from "../api"
/**
* Using API from Website:
* BASE URL : https://ssstik.io
*/
const fetchTT = () =>
new Promise<SSSTikFetchTT>(async (resolve, reject) => {
Axios.get(_ssstikurl, {
@ -14,10 +19,10 @@ const fetchTT = () =>
const regex = /form\.setAttribute\("include-vals",\s*"([^"]+)"\)/
const match = data.match(regex)
if (match) {
const includeValsValue = match[1]
resolve({ status: "success", result: includeValsValue })
const value = match[1]
resolve({ status: "success", result: value })
} else {
resolve({ status: "error", message: "Not found" })
resolve({ status: "error", message: "Failed to get the request form!" })
}
})
.catch((e) => resolve({ status: "error", message: e.message }))
@ -39,7 +44,7 @@ export const SSSTik = (url: string) =>
Object.entries({
id: url,
locale: "en",
tt: tt.result as string
tt: tt.result
})
)
})
@ -49,7 +54,7 @@ export const SSSTik = (url: string) =>
// Result
const desc = $("p.maintext").text().trim()
const author: Author = {
avatar: $("img.result_author").attr("src") as string,
avatar: $("img.result_author").attr("src"),
nickname: $("h2").text().trim()
}
const statistics: Statistics = {
@ -63,7 +68,7 @@ export const SSSTik = (url: string) =>
$("ul.splide__list > li")
.get()
.map((img) => {
images.push($(img).find("img").attr("src") as string)
images.push($(img).find("img").attr("src"))
})
if (images.length !== 0) {
@ -76,7 +81,7 @@ export const SSSTik = (url: string) =>
author,
statistics,
images,
music: $("a.music").attr("href") as string
music: $("a.music").attr("href")
}
})
} else {
@ -89,7 +94,7 @@ export const SSSTik = (url: string) =>
author,
statistics,
video: $("a.without_watermark").attr("href"),
music: $("a.music").attr("href") as string
music: $("a.music").attr("href")
}
})
}

View File

@ -1,7 +1,8 @@
import { MusicalDown } from "./musicaldown"
import { SSSTik } from "./ssstik"
import { TiktokAPI } from "./tiktokapi"
export const TiktokDL = (url: string, options: { version: "v1" | "v2" }) =>
export const TiktokDL = (url: string, options: { version: "v1" | "v2" | "v3" }) =>
new Promise(async (resolve, reject) => {
switch (options.version) {
case "v1": {
@ -10,6 +11,9 @@ export const TiktokDL = (url: string, options: { version: "v1" | "v2" }) =>
case "v2": {
await SSSTik(url).then(resolve).catch(reject)
}
case "v3": {
await MusicalDown(url).then(resolve).catch(reject)
}
default: {
await TiktokAPI(url).then(resolve).catch(reject)
}