@tobyg74/tiktok-api-dl
Version:
Scraper for downloading media in the form of videos, images and audio from Tiktok. Also for stalking Tiktok Users
194 lines (193 loc) • 6.37 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.MusicalDown = void 0;
const axios_1 = __importDefault(require("axios"));
const cheerio_1 = require("cheerio");
const api_1 = require("../../constants/api");
const https_proxy_agent_1 = require("https-proxy-agent");
const socks_proxy_agent_1 = require("socks-proxy-agent");
const constants_1 = require("../../constants");
const TIKTOK_URL_REGEX = /https:\/\/(?:m|www|vm|vt|lite)?\.?tiktok\.com\/((?:.*\b(?:(?:usr|v|embed|user|video|photo)\/|\?shareId=|\&item_id=)(\d+))|\w+)/;
const USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0";
const createProxyAgent = (proxy) => {
if (!proxy)
return {};
const isHttpProxy = proxy.startsWith("http") || proxy.startsWith("https");
const isSocksProxy = proxy.startsWith("socks");
if (!isHttpProxy && !isSocksProxy)
return {};
return {
httpsAgent: isHttpProxy
? new https_proxy_agent_1.HttpsProxyAgent(proxy)
: new socks_proxy_agent_1.SocksProxyAgent(proxy)
};
};
const validateTikTokUrl = (url) => {
return TIKTOK_URL_REGEX.test(url);
};
const isValidUrl = (url) => {
try {
new URL(url);
return true;
}
catch {
return false;
}
};
const extractRequestForm = ($) => {
const input = $("div > input").map((_, el) => $(el));
return {
[input.get(0).attr("name") || ""]: input.get(0).attr("value") || "",
[input.get(1).attr("name") || ""]: input.get(1).attr("value") || "",
[input.get(2).attr("name") || ""]: input.get(2).attr("value") || ""
};
};
const parseImages = ($) => {
const images = [];
$("div.row > div[class='col s12 m3']").each((_, v) => {
const src = $(v).find("img").attr("src");
if (src)
images.push(src);
});
return images;
};
const parseVideos = ($) => {
const videos = {};
const videoContainer = $("div.row > div")
.map((_, el) => $(el))
.get(1);
if (!videoContainer)
return videos;
$(videoContainer)
.find("a")
.each((_, v) => {
const href = $(v).attr("href");
if (!href || href === "#modal2")
return;
if (!isValidUrl(href))
return;
const dataEvent = $(v).attr("data-event") || "";
const onclick = $(v).attr("onclick") || "";
const downloadUrl = href !== undefined ? href : /downloadX\('([^']+)'\)/.exec(onclick)?.[1];
if (!downloadUrl)
return;
if (dataEvent.includes("hd")) {
videos.videoHD = downloadUrl;
}
else if (dataEvent.includes("mp4")) {
videos.videoSD = downloadUrl;
}
else if (dataEvent.includes("watermark")) {
videos.videoWatermark = downloadUrl;
}
else if (href.includes("type=mp3")) {
videos.music = downloadUrl;
}
});
return videos;
};
const createImageResponse = (images) => ({
status: "success",
result: {
type: "image",
images
}
});
const createVideoResponse = ($, videos) => ({
status: "success",
result: {
type: "video",
author: {
avatar: $("div.img-area > img").attr("src") || "",
nickname: $("h2.video-author > b").text()
},
desc: $("p.video-desc").text(),
...videos
}
});
const getRequest = async (url, proxy) => {
try {
if (!validateTikTokUrl(url)) {
return {
status: "error",
message: constants_1.ERROR_MESSAGES.INVALID_URL
};
}
const { data, headers } = await (0, axios_1.default)(api_1._musicaldownurl, {
method: "GET",
headers: {
Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Update-Insecure-Requests": "1",
"User-Agent": USER_AGENT
},
...createProxyAgent(proxy)
});
const cookie = headers["set-cookie"]?.[0]?.split(";")[0];
if (!cookie) {
return {
status: "error",
message: constants_1.ERROR_MESSAGES.NETWORK_ERROR
};
}
const $ = (0, cheerio_1.load)(data);
const request = extractRequestForm($);
return {
status: "success",
request,
cookie
};
}
catch (error) {
return {
status: "error",
message: error instanceof Error ? error.message : constants_1.ERROR_MESSAGES.NETWORK_ERROR
};
}
};
const MusicalDown = async (url, proxy) => {
try {
const request = await getRequest(url, proxy);
if (request.status !== "success") {
return {
status: "error",
message: request.message
};
}
const { data } = await (0, axios_1.default)(api_1._musicaldownapi, {
method: "POST",
headers: {
cookie: request.cookie,
"Content-Type": "application/x-www-form-urlencoded",
Origin: "https://musicaldown.com",
Referer: "https://musicaldown.com/en",
"Upgrade-Insecure-Requests": "1",
"User-Agent": USER_AGENT
},
data: new URLSearchParams(Object.entries(request.request)),
...createProxyAgent(proxy)
});
const $ = (0, cheerio_1.load)(data);
const images = parseImages($);
if (images.length > 0) {
return createImageResponse(images);
}
const videos = parseVideos($);
if (Object.keys(videos).length === 0) {
return {
status: "error",
message: "There is an error. Can't find download link"
};
}
return createVideoResponse($, videos);
}
catch (error) {
return {
status: "error",
message: error instanceof Error ? error.message : constants_1.ERROR_MESSAGES.NETWORK_ERROR
};
}
};
exports.MusicalDown = MusicalDown;