@nxgiang/tiktok-api 1.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +492 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +95 -0
- package/LICENSE +201 -0
- package/README.md +1663 -0
- package/bun.lock +367 -0
- package/helper/signature.js +390 -0
- package/helper/webmssdk.js +4586 -0
- package/helper/xbogus.js +563 -0
- package/install.sh +51 -0
- package/lib/cli/index.d.ts +2 -0
- package/lib/cli/index.js +809 -0
- package/lib/constants/api.d.ts +22 -0
- package/lib/constants/api.js +39 -0
- package/lib/constants/headers.d.ts +2 -0
- package/lib/constants/headers.js +5 -0
- package/lib/constants/index.d.ts +23 -0
- package/lib/constants/index.js +26 -0
- package/lib/constants/params.d.ts +19 -0
- package/lib/constants/params.js +531 -0
- package/lib/index.d.ts +93 -0
- package/lib/index.js +137 -0
- package/lib/lib/logger.d.ts +8 -0
- package/lib/lib/logger.js +25 -0
- package/lib/services/cookieManager.d.ts +10 -0
- package/lib/services/cookieManager.js +51 -0
- package/lib/services/downloadManager.d.ts +5 -0
- package/lib/services/downloadManager.js +188 -0
- package/lib/services/tiktokService.d.ts +14 -0
- package/lib/services/tiktokService.js +78 -0
- package/lib/types/common.d.ts +65 -0
- package/lib/types/common.js +2 -0
- package/lib/types/cookieManager.d.ts +13 -0
- package/lib/types/cookieManager.js +2 -0
- package/lib/types/downloader/musicaldownDownloader.d.ts +27 -0
- package/lib/types/downloader/musicaldownDownloader.js +2 -0
- package/lib/types/downloader/ssstikDownloader.d.ts +30 -0
- package/lib/types/downloader/ssstikDownloader.js +2 -0
- package/lib/types/downloader/tiktokApiDownloader.d.ts +38 -0
- package/lib/types/downloader/tiktokApiDownloader.js +2 -0
- package/lib/types/get/getCollection.d.ts +53 -0
- package/lib/types/get/getCollection.js +2 -0
- package/lib/types/get/getComments.d.ts +26 -0
- package/lib/types/get/getComments.js +2 -0
- package/lib/types/get/getMusicDetail.d.ts +49 -0
- package/lib/types/get/getMusicDetail.js +2 -0
- package/lib/types/get/getMusicVideos.d.ts +93 -0
- package/lib/types/get/getMusicVideos.js +2 -0
- package/lib/types/get/getPlaylist.d.ts +65 -0
- package/lib/types/get/getPlaylist.js +2 -0
- package/lib/types/get/getProfile.d.ts +71 -0
- package/lib/types/get/getProfile.js +2 -0
- package/lib/types/get/getTrendings.d.ts +61 -0
- package/lib/types/get/getTrendings.js +2 -0
- package/lib/types/get/getUserLiked.d.ts +90 -0
- package/lib/types/get/getUserLiked.js +2 -0
- package/lib/types/get/getUserPosts.d.ts +68 -0
- package/lib/types/get/getUserPosts.js +2 -0
- package/lib/types/get/getUserReposts.d.ts +104 -0
- package/lib/types/get/getUserReposts.js +2 -0
- package/lib/types/search/index.d.ts +15 -0
- package/lib/types/search/index.js +2 -0
- package/lib/types/search/liveSearch.d.ts +48 -0
- package/lib/types/search/liveSearch.js +2 -0
- package/lib/types/search/userSearch.d.ts +32 -0
- package/lib/types/search/userSearch.js +2 -0
- package/lib/types/search/videoSearch.d.ts +62 -0
- package/lib/types/search/videoSearch.js +2 -0
- package/lib/utils/downloader/musicaldownDownloader.d.ts +2 -0
- package/lib/utils/downloader/musicaldownDownloader.js +193 -0
- package/lib/utils/downloader/ssstikDownloader.d.ts +2 -0
- package/lib/utils/downloader/ssstikDownloader.js +177 -0
- package/lib/utils/downloader/tiktokAPIDownloader.d.ts +3 -0
- package/lib/utils/downloader/tiktokAPIDownloader.js +221 -0
- package/lib/utils/get/getCollection.d.ts +7 -0
- package/lib/utils/get/getCollection.js +113 -0
- package/lib/utils/get/getComments.d.ts +2 -0
- package/lib/utils/get/getComments.js +139 -0
- package/lib/utils/get/getMusicDetail.d.ts +2 -0
- package/lib/utils/get/getMusicDetail.js +68 -0
- package/lib/utils/get/getMusicVideos.d.ts +2 -0
- package/lib/utils/get/getMusicVideos.js +249 -0
- package/lib/utils/get/getPlaylist.d.ts +7 -0
- package/lib/utils/get/getPlaylist.js +115 -0
- package/lib/utils/get/getProfile.d.ts +2 -0
- package/lib/utils/get/getProfile.js +92 -0
- package/lib/utils/get/getTrendings.d.ts +7 -0
- package/lib/utils/get/getTrendings.js +120 -0
- package/lib/utils/get/getUserLiked.d.ts +2 -0
- package/lib/utils/get/getUserLiked.js +204 -0
- package/lib/utils/get/getUserPosts.d.ts +2 -0
- package/lib/utils/get/getUserPosts.js +199 -0
- package/lib/utils/get/getUserRepost.d.ts +2 -0
- package/lib/utils/get/getUserRepost.js +239 -0
- package/lib/utils/search/liveSearch.d.ts +2 -0
- package/lib/utils/search/liveSearch.js +99 -0
- package/lib/utils/search/userSearch.d.ts +2 -0
- package/lib/utils/search/userSearch.js +76 -0
- package/lib/utils/search/videoSearch.d.ts +2 -0
- package/lib/utils/search/videoSearch.js +140 -0
- package/lib/utils/urlExtractors.d.ts +3 -0
- package/lib/utils/urlExtractors.js +37 -0
- package/lib/utils/validator.d.ts +1 -0
- package/lib/utils/validator.js +13 -0
- package/package.json +60 -0
- package/test/collection-test.ts +73 -0
- package/test/comments-test.ts +54 -0
- package/test/downloader-v1-test.ts +49 -0
- package/test/downloader-v2-test.ts +47 -0
- package/test/downloader-v3-test.ts +35 -0
- package/test/music-detail-test.ts +97 -0
- package/test/music-videos-test.ts +86 -0
- package/test/playlist-test.ts +48 -0
- package/test/profile-test.ts +49 -0
- package/test/search-live-test.ts +42 -0
- package/test/search-user-test.ts +46 -0
- package/test/search-video-test.ts +53 -0
- package/test/trending-test.ts +128 -0
- package/test/userliked-test.ts +65 -0
- package/test/userposts-test.ts +56 -0
- package/test/userreposts-test.ts +57 -0
- package/tobyg74-tiktok-api-1.3.7.tgz +0 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SearchLive = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const api_1 = require("../../constants/api");
|
|
9
|
+
const params_1 = require("../../constants/params");
|
|
10
|
+
const socks_proxy_agent_1 = require("socks-proxy-agent");
|
|
11
|
+
const https_proxy_agent_1 = require("https-proxy-agent");
|
|
12
|
+
const SearchLive = async (keyword, cookie, page = 1, proxy) => new Promise(async (resolve) => {
|
|
13
|
+
if (!cookie) {
|
|
14
|
+
return resolve({
|
|
15
|
+
status: "error",
|
|
16
|
+
message: "Cookie is required!"
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
(0, axios_1.default)((0, api_1._tiktokSearchLiveFull)((0, params_1._liveSearchParams)(keyword, page)), {
|
|
20
|
+
method: "GET",
|
|
21
|
+
headers: {
|
|
22
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0",
|
|
23
|
+
cookie: typeof cookie === "object"
|
|
24
|
+
? cookie.map((v) => `${v.name}=${v.value}`).join("; ")
|
|
25
|
+
: cookie
|
|
26
|
+
},
|
|
27
|
+
httpsAgent: (proxy &&
|
|
28
|
+
(proxy.startsWith("http") || proxy.startsWith("https")
|
|
29
|
+
? new https_proxy_agent_1.HttpsProxyAgent(proxy)
|
|
30
|
+
: proxy.startsWith("socks")
|
|
31
|
+
? new socks_proxy_agent_1.SocksProxyAgent(proxy)
|
|
32
|
+
: undefined)) ||
|
|
33
|
+
undefined
|
|
34
|
+
})
|
|
35
|
+
.then(({ data }) => {
|
|
36
|
+
if (data.status_code === 2483)
|
|
37
|
+
return resolve({ status: "error", message: "Invalid cookie!" });
|
|
38
|
+
if (data.status_code !== 0)
|
|
39
|
+
return resolve({
|
|
40
|
+
status: "error",
|
|
41
|
+
message: data.status_msg ||
|
|
42
|
+
"An error occurred! Please report this issue to the developer."
|
|
43
|
+
});
|
|
44
|
+
if (!data.data)
|
|
45
|
+
return resolve({ status: "error", message: "Live not found!" });
|
|
46
|
+
const result = [];
|
|
47
|
+
data.data.forEach((v) => {
|
|
48
|
+
const content = JSON.parse(v.live_info.raw_data);
|
|
49
|
+
const liveInfo = {
|
|
50
|
+
id: content.id,
|
|
51
|
+
title: content.title,
|
|
52
|
+
cover: content.cover?.url_list || [],
|
|
53
|
+
squareCover: content.square_cover_img?.url_list || [],
|
|
54
|
+
rectangleCover: content.rectangle_cover_img?.url_list || [],
|
|
55
|
+
liveTypeThirdParty: content.live_type_third_party,
|
|
56
|
+
hashtag: content.hashtag?.title || "",
|
|
57
|
+
startTime: content.start_time,
|
|
58
|
+
stats: {
|
|
59
|
+
totalUser: content.stats.total_user,
|
|
60
|
+
viewerCount: content.user_count,
|
|
61
|
+
likeCount: content.like_count
|
|
62
|
+
},
|
|
63
|
+
owner: {
|
|
64
|
+
uid: content.owner.id,
|
|
65
|
+
nickname: content.owner.nickname,
|
|
66
|
+
username: content.owner.display_id,
|
|
67
|
+
signature: content.owner.bio_description,
|
|
68
|
+
avatarThumb: content.owner.avatar_thumb?.url_list || [],
|
|
69
|
+
avatarMedium: content.owner.avatar_medium?.url_list || [],
|
|
70
|
+
avatarLarge: content.owner.avatar_large?.url_list || [],
|
|
71
|
+
modifyTime: content.owner.modify_time,
|
|
72
|
+
stats: {
|
|
73
|
+
followingCount: content.owner.follow_info.following_count,
|
|
74
|
+
followerCount: content.owner.follow_info.follower_count
|
|
75
|
+
},
|
|
76
|
+
isVerified: content.owner?.authentication_info?.custom_verify ===
|
|
77
|
+
"verified account" || false
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const roomInfo = {
|
|
81
|
+
hasCommerceGoods: v.live_info.room_info.has_commerce_goods,
|
|
82
|
+
isBattle: v.live_info.room_info.is_battle
|
|
83
|
+
};
|
|
84
|
+
result.push({ roomInfo, liveInfo });
|
|
85
|
+
});
|
|
86
|
+
if (!result.length)
|
|
87
|
+
return resolve({ status: "error", message: "Live not found!" });
|
|
88
|
+
resolve({
|
|
89
|
+
status: "success",
|
|
90
|
+
result,
|
|
91
|
+
page,
|
|
92
|
+
totalResults: result.length
|
|
93
|
+
});
|
|
94
|
+
})
|
|
95
|
+
.catch((e) => {
|
|
96
|
+
resolve({ status: "error", message: e.message });
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
exports.SearchLive = SearchLive;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SearchUser = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const api_1 = require("../../constants/api");
|
|
9
|
+
const https_proxy_agent_1 = require("https-proxy-agent");
|
|
10
|
+
const socks_proxy_agent_1 = require("socks-proxy-agent");
|
|
11
|
+
const tiktokService_1 = require("../../services/tiktokService");
|
|
12
|
+
const headers_1 = require("../../constants/headers");
|
|
13
|
+
const SearchUser = (username, cookie, page = 1, proxy) => new Promise(async (resolve) => {
|
|
14
|
+
if (!cookie) {
|
|
15
|
+
return resolve({
|
|
16
|
+
status: "error",
|
|
17
|
+
message: "Cookie is required!"
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
const Tiktok = new tiktokService_1.TiktokService();
|
|
21
|
+
(0, axios_1.default)(Tiktok.generateURLXbogus(username, page), {
|
|
22
|
+
method: "GET",
|
|
23
|
+
headers: {
|
|
24
|
+
"User-Agent": headers_1.webUserAgent,
|
|
25
|
+
cookie: typeof cookie === "object"
|
|
26
|
+
? cookie.map((v) => `${v.name}=${v.value}`).join("; ")
|
|
27
|
+
: cookie
|
|
28
|
+
},
|
|
29
|
+
httpsAgent: (proxy &&
|
|
30
|
+
(proxy.startsWith("http") || proxy.startsWith("https")
|
|
31
|
+
? new https_proxy_agent_1.HttpsProxyAgent(proxy)
|
|
32
|
+
: proxy.startsWith("socks")
|
|
33
|
+
? new socks_proxy_agent_1.SocksProxyAgent(proxy)
|
|
34
|
+
: undefined)) ||
|
|
35
|
+
undefined
|
|
36
|
+
})
|
|
37
|
+
.then(({ data }) => {
|
|
38
|
+
if (data.status_code === 2483)
|
|
39
|
+
return resolve({ status: "error", message: "Invalid cookie!" });
|
|
40
|
+
if (data.status_code !== 0)
|
|
41
|
+
return resolve({
|
|
42
|
+
status: "error",
|
|
43
|
+
message: data.status_msg ||
|
|
44
|
+
"An error occurred! Please report this issue to the developer."
|
|
45
|
+
});
|
|
46
|
+
if (!data.user_list)
|
|
47
|
+
return resolve({ status: "error", message: "User not found!" });
|
|
48
|
+
const result = [];
|
|
49
|
+
for (let i = 0; i < data.user_list.length; i++) {
|
|
50
|
+
const user = data.user_list[i];
|
|
51
|
+
result.push({
|
|
52
|
+
uid: user.user_info.uid,
|
|
53
|
+
username: user.user_info.unique_id,
|
|
54
|
+
nickname: user.user_info.nickname,
|
|
55
|
+
signature: user.user_info.signature,
|
|
56
|
+
followerCount: user.user_info.follower_count,
|
|
57
|
+
avatarThumb: user.user_info.avatar_thumb,
|
|
58
|
+
isVerified: user.custom_verify !== "",
|
|
59
|
+
secUid: user.user_info.sec_uid,
|
|
60
|
+
url: `${api_1._tiktokDesktopUrl}/@${user.user_info.unique_id}`
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (!result.length)
|
|
64
|
+
return resolve({ status: "error", message: "User not found!" });
|
|
65
|
+
resolve({
|
|
66
|
+
status: "success",
|
|
67
|
+
result,
|
|
68
|
+
page,
|
|
69
|
+
totalResults: result.length
|
|
70
|
+
});
|
|
71
|
+
})
|
|
72
|
+
.catch((e) => {
|
|
73
|
+
resolve({ status: "error", message: e.message });
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
exports.SearchUser = SearchUser;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SearchVideo = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const api_1 = require("../../constants/api");
|
|
9
|
+
const params_1 = require("../../constants/params");
|
|
10
|
+
const socks_proxy_agent_1 = require("socks-proxy-agent");
|
|
11
|
+
const https_proxy_agent_1 = require("https-proxy-agent");
|
|
12
|
+
const async_retry_1 = __importDefault(require("async-retry"));
|
|
13
|
+
const SearchVideo = async (keyword, cookie, page = 1, proxy) => new Promise(async (resolve) => {
|
|
14
|
+
if (!cookie) {
|
|
15
|
+
return resolve({
|
|
16
|
+
status: "error",
|
|
17
|
+
message: "Cookie is required!"
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const data = await requestVideoSearch(keyword, page, cookie, proxy);
|
|
22
|
+
if (data.status_code === 2483)
|
|
23
|
+
return resolve({ status: "error", message: "Invalid cookie!" });
|
|
24
|
+
if (data.status_code !== 0)
|
|
25
|
+
return resolve({
|
|
26
|
+
status: "error",
|
|
27
|
+
message: data.status_msg ||
|
|
28
|
+
"An error occurred! Please report this issue to the developer."
|
|
29
|
+
});
|
|
30
|
+
if (!data.item_list)
|
|
31
|
+
return resolve({ status: "error", message: "Video not found!" });
|
|
32
|
+
const result = [];
|
|
33
|
+
data.item_list.forEach((v) => {
|
|
34
|
+
const video = {
|
|
35
|
+
id: v.video.id,
|
|
36
|
+
ratio: v.video.ratio,
|
|
37
|
+
cover: v.video.cover,
|
|
38
|
+
originCover: v.video.originCover,
|
|
39
|
+
dynamicCover: v.video.dynamicCover,
|
|
40
|
+
playAddr: v.video.playAddr,
|
|
41
|
+
downloadAddr: v.video.downloadAddr,
|
|
42
|
+
format: v.video.format
|
|
43
|
+
};
|
|
44
|
+
const stats = {
|
|
45
|
+
likeCount: v.stats.diggCount,
|
|
46
|
+
shareCount: v.stats.shareCount,
|
|
47
|
+
commentCount: v.stats.commentCount,
|
|
48
|
+
playCount: v.stats.playCount,
|
|
49
|
+
collectCount: v.stats.collectCount
|
|
50
|
+
};
|
|
51
|
+
const author = {
|
|
52
|
+
id: v.author.id,
|
|
53
|
+
uniqueId: v.author.uniqueId,
|
|
54
|
+
nickname: v.author.nickname,
|
|
55
|
+
avatarThumb: v.author.avatarThumb,
|
|
56
|
+
avatarMedium: v.author.avatarMedium,
|
|
57
|
+
avatarLarger: v.author.avatarLarger,
|
|
58
|
+
signature: v.author.signature,
|
|
59
|
+
verified: v.author.verified,
|
|
60
|
+
secUid: v.author.secUid,
|
|
61
|
+
openFavorite: v.author.openFavorite,
|
|
62
|
+
privateAccount: v.author.privateAccount,
|
|
63
|
+
isADVirtual: v.author.isADVirtual,
|
|
64
|
+
tiktokSeller: v.author.ttSeller,
|
|
65
|
+
isEmbedBanned: v.author.isEmbedBanned
|
|
66
|
+
};
|
|
67
|
+
const music = {
|
|
68
|
+
id: v.music.id,
|
|
69
|
+
title: v.music.title,
|
|
70
|
+
playUrl: v.music.playUrl,
|
|
71
|
+
coverThumb: v.music.coverThumb,
|
|
72
|
+
coverMedium: v.music.coverMedium,
|
|
73
|
+
coverLarge: v.music.coverLarge,
|
|
74
|
+
authorName: v.music.authorName,
|
|
75
|
+
original: v.music.original,
|
|
76
|
+
album: v.music.album,
|
|
77
|
+
duration: v.music.duration,
|
|
78
|
+
isCopyrighted: v.music.isCopyrighted
|
|
79
|
+
};
|
|
80
|
+
result.push({
|
|
81
|
+
id: v.id,
|
|
82
|
+
desc: v.desc,
|
|
83
|
+
createTime: v.createTime,
|
|
84
|
+
author,
|
|
85
|
+
stats,
|
|
86
|
+
video,
|
|
87
|
+
music
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
if (!result.length)
|
|
91
|
+
return resolve({ status: "error", message: "Video not found!" });
|
|
92
|
+
resolve({
|
|
93
|
+
status: "success",
|
|
94
|
+
result,
|
|
95
|
+
page,
|
|
96
|
+
totalResults: result.length
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
resolve({ status: "error", message: e.message });
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
exports.SearchVideo = SearchVideo;
|
|
104
|
+
const requestVideoSearch = async (keyword, page, cookie, proxy) => {
|
|
105
|
+
return (0, async_retry_1.default)(async (bail, attempt) => {
|
|
106
|
+
try {
|
|
107
|
+
const { data } = await (0, axios_1.default)((0, api_1._tiktokSearchVideoFull)((0, params_1._videoSearchParams)(keyword, page)), {
|
|
108
|
+
method: "GET",
|
|
109
|
+
headers: {
|
|
110
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0",
|
|
111
|
+
cookie: typeof cookie === "object"
|
|
112
|
+
? cookie.map((v) => `${v.name}=${v.value}`).join("; ")
|
|
113
|
+
: cookie
|
|
114
|
+
},
|
|
115
|
+
httpsAgent: (proxy &&
|
|
116
|
+
(proxy.startsWith("http") || proxy.startsWith("https")
|
|
117
|
+
? new https_proxy_agent_1.HttpsProxyAgent(proxy)
|
|
118
|
+
: proxy.startsWith("socks")
|
|
119
|
+
? new socks_proxy_agent_1.SocksProxyAgent(proxy)
|
|
120
|
+
: undefined)) ||
|
|
121
|
+
undefined
|
|
122
|
+
});
|
|
123
|
+
if (data === "") {
|
|
124
|
+
throw new Error("Empty response");
|
|
125
|
+
}
|
|
126
|
+
return data;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
throw error;
|
|
130
|
+
}
|
|
131
|
+
}, {
|
|
132
|
+
retries: 10,
|
|
133
|
+
minTimeout: 1000,
|
|
134
|
+
maxTimeout: 5000,
|
|
135
|
+
factor: 2,
|
|
136
|
+
onRetry: (error, attempt) => {
|
|
137
|
+
console.log(`Retry attempt ${attempt} due to: ${error}`);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractPlaylistId = exports.extractCollectionId = exports.extractMusicId = void 0;
|
|
4
|
+
const extractMusicId = (musicIdOrUrl) => {
|
|
5
|
+
if (!musicIdOrUrl || typeof musicIdOrUrl !== "string") {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
const trimmed = musicIdOrUrl.trim();
|
|
9
|
+
if (/^\d+$/.test(trimmed)) {
|
|
10
|
+
return trimmed;
|
|
11
|
+
}
|
|
12
|
+
const urlPattern = /tiktok\.com\/music\/[^\/\-]*-?(\d+)/i;
|
|
13
|
+
const match = trimmed.match(urlPattern);
|
|
14
|
+
if (match && match[1]) {
|
|
15
|
+
return match[1];
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
};
|
|
19
|
+
exports.extractMusicId = extractMusicId;
|
|
20
|
+
const extractCollectionId = (input) => {
|
|
21
|
+
if (/^\d+$/.test(input)) {
|
|
22
|
+
return input;
|
|
23
|
+
}
|
|
24
|
+
const urlPattern = /collection\/[^\/\-]*-?(\d+)/i;
|
|
25
|
+
const match = input.match(urlPattern);
|
|
26
|
+
return match ? match[1] : null;
|
|
27
|
+
};
|
|
28
|
+
exports.extractCollectionId = extractCollectionId;
|
|
29
|
+
const extractPlaylistId = (input) => {
|
|
30
|
+
if (/^\d+$/.test(input)) {
|
|
31
|
+
return input;
|
|
32
|
+
}
|
|
33
|
+
const urlPattern = /playlist\/[^\/\-]*-?(\d+)/i;
|
|
34
|
+
const match = input.match(urlPattern);
|
|
35
|
+
return match ? match[1] : null;
|
|
36
|
+
};
|
|
37
|
+
exports.extractPlaylistId = extractPlaylistId;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const validateCookie: (cookie: string | any[]) => boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateCookie = void 0;
|
|
4
|
+
const validateCookie = (cookie) => {
|
|
5
|
+
if (!cookie)
|
|
6
|
+
return false;
|
|
7
|
+
if (typeof cookie === "string")
|
|
8
|
+
return cookie.length > 0;
|
|
9
|
+
if (Array.isArray(cookie))
|
|
10
|
+
return cookie.length > 0;
|
|
11
|
+
return false;
|
|
12
|
+
};
|
|
13
|
+
exports.validateCookie = validateCookie;
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nxgiang/tiktok-api",
|
|
3
|
+
"version": "1.3.7",
|
|
4
|
+
"description": "Scraper for downloading media in the form of videos, images and audio from Tiktok. Also for stalking Tiktok Users, getting user posts, likes, comments, followers and following.",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"cli": "[ -d ./lib ] || npm run build && ts-node lib/cli/index.js"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"tiktokdl": "./lib/cli/index.js"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/TobyG74/tiktok-api-dl.git"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"tiktok-api",
|
|
20
|
+
"tiktok-downloader",
|
|
21
|
+
"tiktok-dl",
|
|
22
|
+
"tiktok-nowatermark",
|
|
23
|
+
"tiktok",
|
|
24
|
+
"musically",
|
|
25
|
+
"tiktokv",
|
|
26
|
+
"tiktok-user",
|
|
27
|
+
"tiktok-stalk"
|
|
28
|
+
],
|
|
29
|
+
"author": "Tobz",
|
|
30
|
+
"license": "ISC",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/TobyG74/tiktok-api-dl/issues"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/TobyG74/tiktok-api-dl#readme",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"async-retry": "^1.3.3",
|
|
37
|
+
"axios": "^1.3.4",
|
|
38
|
+
"chalk": "^4.1.2",
|
|
39
|
+
"cheerio": "^1.0.0-rc.12",
|
|
40
|
+
"commander": "^11.0.0",
|
|
41
|
+
"crypto-js": "^4.2.0",
|
|
42
|
+
"https-proxy-agent": "^7.0.5",
|
|
43
|
+
"jsdom": "^26.0.0",
|
|
44
|
+
"node-fetch": "^2.7.0",
|
|
45
|
+
"qs": "^6.12.0",
|
|
46
|
+
"socks-proxy-agent": "^8.0.4",
|
|
47
|
+
"ts-node": "^10.9.2",
|
|
48
|
+
"uuid": "^10.0.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/async-retry": "^1.4.9",
|
|
52
|
+
"@types/cheerio": "^0.22.31",
|
|
53
|
+
"@types/node": "^18.15.11",
|
|
54
|
+
"@types/qs": "^6.9.17",
|
|
55
|
+
"typescript": "^5.0.3"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"canvas": "^3.1.2"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import Tiktok from "../src/index"
|
|
2
|
+
|
|
3
|
+
async function testCollection() {
|
|
4
|
+
try {
|
|
5
|
+
// You can use either a collection ID or URL
|
|
6
|
+
const collectionId = "7507916135931218695"
|
|
7
|
+
const collectionUrl =
|
|
8
|
+
"https://www.tiktok.com/@getrex.co.nz/collection/big%20back-7507916135931218695"
|
|
9
|
+
const collectionShareableLink = "https://vt.tiktok.com/ZShvmqNjQ/"
|
|
10
|
+
|
|
11
|
+
console.log("Testing Collection method...")
|
|
12
|
+
const result = await Tiktok.Collection(collectionId, {
|
|
13
|
+
page: 1,
|
|
14
|
+
count: 5, // Optional: Number of items to fetch
|
|
15
|
+
proxy: undefined // Optional: Add your proxy if needed
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
if (result.status === "success" && result.result) {
|
|
19
|
+
console.log("\nCollection fetched successfully!")
|
|
20
|
+
console.log("========================")
|
|
21
|
+
console.log("Collection Overview:")
|
|
22
|
+
console.log("========================")
|
|
23
|
+
console.log(`Total items fetched: ${result.result.itemList.length}`)
|
|
24
|
+
console.log(`Has more items: ${result.result.hasMore}`)
|
|
25
|
+
|
|
26
|
+
// Log all items
|
|
27
|
+
result.result.itemList.forEach((item, index) => {
|
|
28
|
+
console.log(`\nItem ${index + 1}:`)
|
|
29
|
+
console.log("-------------------")
|
|
30
|
+
console.log(`ID: ${item.id}`)
|
|
31
|
+
console.log(`Description: ${item.desc}`)
|
|
32
|
+
console.log(`Author: ${item.author.nickname}`)
|
|
33
|
+
console.log(
|
|
34
|
+
`Created: ${new Date(item.createTime * 1000).toLocaleString()}`
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
// Log video URL
|
|
38
|
+
if (item.video?.playAddr?.[0]) {
|
|
39
|
+
console.log(`Video URL: ${item.video.playAddr[0]}`)
|
|
40
|
+
} else {
|
|
41
|
+
console.log("No video URL available")
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Log item statistics
|
|
45
|
+
if (item.statistics) {
|
|
46
|
+
console.log("\nStatistics:")
|
|
47
|
+
console.log(`- Likes: ${item.statistics.likeCount || 0}`)
|
|
48
|
+
console.log(`- Comments: ${item.statistics.commentCount || 0}`)
|
|
49
|
+
console.log(`- Shares: ${item.statistics.shareCount || 0}`)
|
|
50
|
+
console.log(`- Plays: ${item.statistics.playCount || 0}`)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Log hashtags if available
|
|
54
|
+
if (item.textExtra?.length > 0) {
|
|
55
|
+
console.log("\nHashtags:")
|
|
56
|
+
item.textExtra.forEach((tag) => {
|
|
57
|
+
if (tag.hashtagName) {
|
|
58
|
+
console.log(`- #${tag.hashtagName}`)
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
console.log("========================")
|
|
63
|
+
})
|
|
64
|
+
} else {
|
|
65
|
+
console.error("Error:", result.message)
|
|
66
|
+
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error("Test failed:", error)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Run the test
|
|
73
|
+
testCollection()
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Test for Tiktok Video Comments
|
|
2
|
+
import Tiktok from "../src/index"
|
|
3
|
+
|
|
4
|
+
async function testComments() {
|
|
5
|
+
try {
|
|
6
|
+
const url = "https://www.tiktok.com/@letuankhang2002/video/7578120269450071304?is_from_webapp=1&sender_device=pc" // Change to a valid TikTok video URL
|
|
7
|
+
const result = await Tiktok.GetVideoComments(url, {
|
|
8
|
+
commentLimit: 1000,
|
|
9
|
+
proxy: undefined
|
|
10
|
+
})
|
|
11
|
+
if (result.status === "success" && result.result) {
|
|
12
|
+
console.log("\nComments fetched successfully!")
|
|
13
|
+
console.log("========================")
|
|
14
|
+
console.log("Comments Overview:")
|
|
15
|
+
console.log("========================")
|
|
16
|
+
console.log(`Total comments fetched: ${result.result.length}`)
|
|
17
|
+
// Log all comments
|
|
18
|
+
result.result.forEach((comment, index) => {
|
|
19
|
+
console.log(`\nComment ${index + 1}:`)
|
|
20
|
+
console.log("-------------------")
|
|
21
|
+
console.log(`ID: ${comment.cid}`)
|
|
22
|
+
if (comment.user) {
|
|
23
|
+
console.log(
|
|
24
|
+
`Author: ${comment.user.nickname} (@${comment.user.username})`
|
|
25
|
+
)
|
|
26
|
+
console.log(`Verified: ${comment.user.isVerified ? "Yes" : "No"}`)
|
|
27
|
+
}
|
|
28
|
+
console.log(`Text: ${comment.text}`)
|
|
29
|
+
if (comment.createTime) {
|
|
30
|
+
console.log(
|
|
31
|
+
`Created: ${new Date(comment.createTime * 1000).toLocaleString()}`
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
// Log comment statistics
|
|
35
|
+
if (typeof comment.likeCount !== "undefined") {
|
|
36
|
+
console.log("\nStatistics:")
|
|
37
|
+
console.log(`- Likes: ${comment.likeCount}`)
|
|
38
|
+
}
|
|
39
|
+
if (typeof comment.replyCommentTotal !== "undefined") {
|
|
40
|
+
console.log(`- Replies: ${comment.replyCommentTotal}`)
|
|
41
|
+
}
|
|
42
|
+
if (comment.isAuthorLiked) console.log("👍 Liked by author")
|
|
43
|
+
if (comment.isCommentTranslatable) console.log("🌐 Translatable")
|
|
44
|
+
console.log("========================")
|
|
45
|
+
})
|
|
46
|
+
} else {
|
|
47
|
+
console.error("Error:", result.message)
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error("Test failed:", error)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
testComments()
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Test for Tiktok Downloader v1
|
|
2
|
+
import Tiktok from "../src/index"
|
|
3
|
+
|
|
4
|
+
async function testDownloaderV1() {
|
|
5
|
+
try {
|
|
6
|
+
const url = "https://www.tiktok.com/@tobz2k19/video/7451777267107187986" // Change to a valid TikTok video URL
|
|
7
|
+
console.log(`\nTesting Downloader version: v1`)
|
|
8
|
+
const result = await Tiktok.Downloader(url, {
|
|
9
|
+
version: "v1",
|
|
10
|
+
proxy: undefined
|
|
11
|
+
})
|
|
12
|
+
if (result.status === "success" && result.result) {
|
|
13
|
+
const r = result.result
|
|
14
|
+
console.log(`Type: ${r.type}`)
|
|
15
|
+
console.log(`ID: ${r.id}`)
|
|
16
|
+
console.log(`Description: ${r.desc}`)
|
|
17
|
+
if (r.author) {
|
|
18
|
+
console.log(`Author: ${r.author.nickname}`)
|
|
19
|
+
}
|
|
20
|
+
if (r.statistics) {
|
|
21
|
+
console.log("Statistics:")
|
|
22
|
+
console.log(`- Likes: ${r.statistics.likeCount}`)
|
|
23
|
+
console.log(`- Comments: ${r.statistics.commentCount}`)
|
|
24
|
+
console.log(`- Shares: ${r.statistics.shareCount}`)
|
|
25
|
+
console.log(`- Plays: ${r.statistics.playCount}`)
|
|
26
|
+
}
|
|
27
|
+
if (r.video?.playAddr?.length) {
|
|
28
|
+
console.log(`Video URL: ${r.video.playAddr[0]}`)
|
|
29
|
+
}
|
|
30
|
+
if (r.images?.length) {
|
|
31
|
+
console.log(`Images: ${r.images.join(", ")}`)
|
|
32
|
+
}
|
|
33
|
+
if (r.music) {
|
|
34
|
+
console.log(`Music:`)
|
|
35
|
+
console.log(`- Title: ${r.music.title}`)
|
|
36
|
+
if (r.music.playUrl?.length) {
|
|
37
|
+
console.log(`- Music URL: ${r.music.playUrl[0]}`)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
console.log("========================")
|
|
41
|
+
} else {
|
|
42
|
+
console.error("Error:", result.message)
|
|
43
|
+
}
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error("Test failed:", error)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
testDownloaderV1()
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Test for Tiktok Downloader v2
|
|
2
|
+
import Tiktok from "../src/index"
|
|
3
|
+
|
|
4
|
+
async function testDownloaderV2() {
|
|
5
|
+
try {
|
|
6
|
+
const url = "https://www.tiktok.com/@tobz2k19/video/7451777267107187986" // Change to a valid TikTok video URL
|
|
7
|
+
console.log(`\nTesting Downloader version: v2`)
|
|
8
|
+
const result = await Tiktok.Downloader(url, {
|
|
9
|
+
version: "v2",
|
|
10
|
+
proxy: undefined
|
|
11
|
+
})
|
|
12
|
+
if (result.status === "success" && result.result) {
|
|
13
|
+
const r = result.result
|
|
14
|
+
console.log(`Type: ${r.type}`)
|
|
15
|
+
if (r.desc) console.log(`Description: ${r.desc}`)
|
|
16
|
+
if (r.author && r.author.nickname) {
|
|
17
|
+
console.log(`Author: ${r.author.nickname}`)
|
|
18
|
+
} else if (r.author && r.author.avatar) {
|
|
19
|
+
// fallback for v2 author structure
|
|
20
|
+
console.log(`Author Avatar: ${r.author.avatar}`)
|
|
21
|
+
}
|
|
22
|
+
if (r.statistics) {
|
|
23
|
+
console.log("Statistics:")
|
|
24
|
+
if (r.statistics.likeCount !== undefined)
|
|
25
|
+
console.log(`- Likes: ${r.statistics.likeCount}`)
|
|
26
|
+
if (r.statistics.commentCount !== undefined)
|
|
27
|
+
console.log(`- Comments: ${r.statistics.commentCount}`)
|
|
28
|
+
if (r.statistics.shareCount !== undefined)
|
|
29
|
+
console.log(`- Shares: ${r.statistics.shareCount}`)
|
|
30
|
+
}
|
|
31
|
+
if (r.video?.playAddr?.length) {
|
|
32
|
+
console.log(`Video URL: ${r.video.playAddr[0]}`)
|
|
33
|
+
}
|
|
34
|
+
if (r.music?.playUrl?.length) {
|
|
35
|
+
console.log(`Music URL: ${r.music.playUrl[0]}`)
|
|
36
|
+
}
|
|
37
|
+
if (r.images?.length) console.log(`Images: ${r.images.join(", ")}`)
|
|
38
|
+
console.log("========================")
|
|
39
|
+
} else {
|
|
40
|
+
console.error("Error:", result.message)
|
|
41
|
+
}
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error("Test failed:", error)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
testDownloaderV2()
|