UNPKG

tiktokapi-src

Version:

Unofficial scraper for downloading media from tiktok

176 lines (175 loc) 7.1 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.StalkUser = void 0; const axios_1 = __importDefault(require("axios")); const cheerio_1 = require("cheerio"); const api_1 = require("../../constants/api"); const params_1 = require("../../constants/params"); const crypto_1 = require("crypto"); const StalkUser = (username, cookie, postLimit) => new Promise(async (resolve, reject) => { username = username.replace("@", ""); axios_1.default.get(`${api_1._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: typeof cookie === "object" ? cookie.map((v) => `${v.name}=${v.value}`).join("; ") : cookie } }) .then(async ({ data }) => { const $ = (0, cheerio_1.load)(data); const result = JSON.parse($("script#__UNIVERSAL_DATA_FOR_REHYDRATION__").text()); if (!result["__DEFAULT_SCOPE__"] && !result["__DEFAULT_SCOPE__"]["webapp.user-detail"]) { return resolve({ status: "error", message: "User not found!" }); } const dataUser = result["__DEFAULT_SCOPE__"]["webapp.user-detail"]["userInfo"]; const posts = await parsePosts(dataUser, postLimit); const { users, stats } = parseDataUser(dataUser, posts); resolve({ status: "success", result: { users, stats, posts } }); }) .catch((e) => resolve({ status: "error", message: e.message })); }); exports.StalkUser = StalkUser; const request = async (secUid, cursor = 0, count = 30) => { const { data } = await axios_1.default.get(`${(0, api_1._tiktokGetPosts)((0, params_1._userPostsParams)())}`, { headers: { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35", "X-tt-params": xttparams((0, params_1._xttParams)(secUid, cursor, count)) } }); return data; }; const parseDataUser = (dataUser, posts) => { const users = { id: dataUser.user.id, username: dataUser.user.uniqueId, nickname: dataUser.user.nickname, avatarLarger: dataUser.user.avatarLarger, avatarThumb: dataUser.user.avatarThumb, avatarMedium: dataUser.user.avatarMedium, signature: dataUser.user.signature, verified: dataUser.user.verified, privateAccount: dataUser.user.privateAccount, region: dataUser.user.region, commerceUser: dataUser.user.commerceUserInfo.commerceUser, usernameModifyTime: dataUser.user.uniqueIdModifyTime, nicknameModifyTime: dataUser.user.nickNameModifyTime }; const stats = { followerCount: dataUser.stats.followerCount, followingCount: dataUser.stats.followingCount, heartCount: dataUser.stats.heartCount, videoCount: dataUser.stats.videoCount, likeCount: dataUser.stats.diggCount, friendCount: dataUser.stats.friendCount, postCount: posts.length }; return { users, stats }; }; const parsePosts = async (dataUser, postLimit) => { let hasMore = true; let cursor = null; const posts = []; while (hasMore) { let result2 = null; let counter = 0; for (let i = 0; i < 30; i++) { result2 = await request(dataUser.user.secUid, cursor, 30); if (result2 !== "") break; } if (result2 === "") hasMore = false; result2?.itemList?.forEach((v) => { const author = { id: v.author.id, username: v.author.uniqueId, nickname: v.author.nickname, avatarLarger: v.author.avatarLarger, avatarThumb: v.author.avatarThumb, avatarMedium: v.author.avatarMedium, signature: v.author.signature, verified: v.author.verified, openFavorite: v.author.openFavorite, privateAccount: v.author.privateAccount, isADVirtual: v.author.isADVirtual, isEmbedBanned: v.author.isEmbedBanned }; if (v.imagePost) { const images = v.imagePost.images.map((img) => img.imageURL.urlList[0]); posts.push({ id: v.id, desc: v.desc, createTime: v.createTime, digged: v.digged, duetEnabled: v.duetEnabled, forFriend: v.forFriend, officalItem: v.officalItem, originalItem: v.originalItem, privateItem: v.privateItem, shareEnabled: v.shareEnabled, stitchEnabled: v.stitchEnabled, stats: v.stats, music: v.music, author, images }); } else { const video = { id: v.video.id, duration: v.video.duration, format: v.video.format, bitrate: v.video.bitrate, ratio: v.video.ratio, playAddr: v.video.playAddr, cover: v.video.cover, originCover: v.video.originCover, dynamicCover: v.video.dynamicCover, downloadAddr: v.video.downloadAddr }; posts.push({ id: v.id, desc: v.desc, createTime: v.createTime, digged: v.digged, duetEnabled: v.duetEnabled, forFriend: v.forFriend, officalItem: v.officalItem, originalItem: v.originalItem, privateItem: v.privateItem, shareEnabled: v.shareEnabled, stitchEnabled: v.stitchEnabled, stats: v.stats, music: v.music, author, video }); } }); if (postLimit !== 0) { let loopCount = Math.floor(postLimit / 30); if (counter >= loopCount) break; } hasMore = result2.hasMore; cursor = hasMore ? result2.cursor : null; counter++; } return postLimit ? posts.slice(0, postLimit) : posts; }; const xttparams = (params) => { const cipher = (0, crypto_1.createCipheriv)("aes-128-cbc", "webapp1.0+202106", "webapp1.0+202106"); return Buffer.concat([cipher.update(params), cipher.final()]).toString("base64"); };