@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
package/lib/cli/index.js
ADDED
|
@@ -0,0 +1,809 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const __1 = __importDefault(require(".."));
|
|
9
|
+
const cookieManager_1 = require("../services/cookieManager");
|
|
10
|
+
const logger_1 = require("../lib/logger");
|
|
11
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
12
|
+
const downloadManager_1 = require("../services/downloadManager");
|
|
13
|
+
const api_1 = require("../constants/api");
|
|
14
|
+
const urlExtractors_1 = require("../utils/urlExtractors");
|
|
15
|
+
const TIKTOK_URL_REGEX = {
|
|
16
|
+
playlist: /https:\/\/(?:www|m)\.tiktok\.com\/@[\w.-]+\/playlist\/[\w-]+-(\d+)/,
|
|
17
|
+
collection: /https:\/\/(?:www|m)\.tiktok\.com\/@[\w.-]+\/collection\/[\w-]+-(\d+)/,
|
|
18
|
+
video: /https:\/\/(?:www|m)\.tiktok\.com\/@[\w.-]+\/video\/(\d+)/,
|
|
19
|
+
photo: /https:\/\/(?:www|m)\.tiktok\.com\/@[\w.-]+\/photo\/(\d+)/,
|
|
20
|
+
shortLink: /https:\/\/(vm|vt|lite)\.tiktok\.com\/[\w\d]+\/?/,
|
|
21
|
+
music: /https:\/\/(?:www|m)\.tiktok\.com\/music\/[\w%-]+-(\d+)/
|
|
22
|
+
};
|
|
23
|
+
const cookieManager = new cookieManager_1.CookieManager();
|
|
24
|
+
commander_1.program
|
|
25
|
+
.name("tiktokdl")
|
|
26
|
+
.description("TikTok downloader and search CLI tool")
|
|
27
|
+
.version("1.0.0");
|
|
28
|
+
commander_1.program
|
|
29
|
+
.command("download")
|
|
30
|
+
.description("Download TikTok Video / Slide / Music / Playlist / Collection")
|
|
31
|
+
.argument("<urls...>", "TikTok URLs (Video / Slide / Music / Playlist / Collection)")
|
|
32
|
+
.option("-o, --output <path>", "Output directory path")
|
|
33
|
+
.option("-v, --version <version>", "Downloader version (v1/v2/v3)", "v1")
|
|
34
|
+
.option("-p, --proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
35
|
+
.option("-c, --count <number>", "Number of items to fetch for playlist/collection (default: 20)", (val) => parseInt(val), 20)
|
|
36
|
+
.action(async (urls, options) => {
|
|
37
|
+
const outputPath = options.output || (0, downloadManager_1.getDefaultDownloadPath)();
|
|
38
|
+
const version = options.version.toLowerCase();
|
|
39
|
+
const count = options.count || 20;
|
|
40
|
+
if (!Array.isArray(urls))
|
|
41
|
+
urls = [urls];
|
|
42
|
+
for (const url of urls) {
|
|
43
|
+
try {
|
|
44
|
+
if (!["v1", "v2", "v3"].includes(version)) {
|
|
45
|
+
throw new Error("Invalid version. Use v1, v2 or v3");
|
|
46
|
+
}
|
|
47
|
+
if (TIKTOK_URL_REGEX.playlist.test(url)) {
|
|
48
|
+
logger_1.Logger.info(`Fetching playlist items from: ${url}`);
|
|
49
|
+
const match = url.match(TIKTOK_URL_REGEX.playlist);
|
|
50
|
+
const results = await __1.default.Playlist(match[1], {
|
|
51
|
+
page: 1,
|
|
52
|
+
proxy: options.proxy,
|
|
53
|
+
count: count
|
|
54
|
+
});
|
|
55
|
+
if (results.status === "success" && results.result) {
|
|
56
|
+
const { itemList } = results.result;
|
|
57
|
+
logger_1.Logger.info(`Found ${itemList.length} items in playlist. Starting download...`);
|
|
58
|
+
for (const [index, item] of itemList.entries()) {
|
|
59
|
+
logger_1.Logger.info(`Downloading [${index + 1}/${itemList.length}]: ${item.id}`);
|
|
60
|
+
const videoUrl = `https://www.tiktok.com/@${item.author?.uniqueId || "unknown"}/video/${item.id}`;
|
|
61
|
+
try {
|
|
62
|
+
const data = await __1.default.Downloader(videoUrl, {
|
|
63
|
+
version: version,
|
|
64
|
+
proxy: options.proxy
|
|
65
|
+
});
|
|
66
|
+
await (0, downloadManager_1.handleMediaDownload)(data, outputPath, version);
|
|
67
|
+
logger_1.Logger.success(`Downloaded: ${videoUrl}`);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
logger_1.Logger.error(`Failed to download ${videoUrl}: ${err.message}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
logger_1.Logger.info("All downloads finished.");
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else if (TIKTOK_URL_REGEX.collection.test(url)) {
|
|
80
|
+
logger_1.Logger.info(`Fetching collection items from: ${url}`);
|
|
81
|
+
const match = url.match(TIKTOK_URL_REGEX.collection);
|
|
82
|
+
const results = await __1.default.Collection(match[1], {
|
|
83
|
+
page: 1,
|
|
84
|
+
proxy: options.proxy,
|
|
85
|
+
count: count
|
|
86
|
+
});
|
|
87
|
+
if (results.status === "success" && results.result) {
|
|
88
|
+
const { itemList } = results.result;
|
|
89
|
+
logger_1.Logger.info(`Found ${itemList.length} items in collection. Starting download...`);
|
|
90
|
+
for (const [index, item] of itemList.entries()) {
|
|
91
|
+
logger_1.Logger.info(`Downloading [${index + 1}/${itemList.length}]: ${item.id}`);
|
|
92
|
+
const videoUrl = `https://www.tiktok.com/@${item.author?.uniqueId || "unknown"}/video/${item.id}`;
|
|
93
|
+
try {
|
|
94
|
+
const data = await __1.default.Downloader(videoUrl, {
|
|
95
|
+
version: version,
|
|
96
|
+
proxy: options.proxy
|
|
97
|
+
});
|
|
98
|
+
await (0, downloadManager_1.handleMediaDownload)(data, outputPath, version);
|
|
99
|
+
logger_1.Logger.success(`Downloaded: ${videoUrl}`);
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
logger_1.Logger.error(`Failed to download ${videoUrl}: ${err.message}`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
logger_1.Logger.info("All downloads finished.");
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else if (TIKTOK_URL_REGEX.video.test(url) ||
|
|
112
|
+
TIKTOK_URL_REGEX.shortLink.test(url) ||
|
|
113
|
+
TIKTOK_URL_REGEX.photo.test(url)) {
|
|
114
|
+
logger_1.Logger.info("Fetching media information...");
|
|
115
|
+
const data = await __1.default.Downloader(url, {
|
|
116
|
+
version: version,
|
|
117
|
+
proxy: options.proxy
|
|
118
|
+
});
|
|
119
|
+
await (0, downloadManager_1.handleMediaDownload)(data, outputPath, version);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
logger_1.Logger.error("URL tidak valid atau tidak dikenali: " + url);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
const cookieCommand = commander_1.program.command("cookie").description("Cookie Manager");
|
|
131
|
+
cookieCommand
|
|
132
|
+
.command("set <value>")
|
|
133
|
+
.description("Set a cookie")
|
|
134
|
+
.action((value) => {
|
|
135
|
+
cookieManager.setCookie(value);
|
|
136
|
+
logger_1.Logger.success("Cookie set successfully.");
|
|
137
|
+
});
|
|
138
|
+
cookieCommand
|
|
139
|
+
.command("get")
|
|
140
|
+
.description("Get cookie value")
|
|
141
|
+
.action(() => {
|
|
142
|
+
const cookie = cookieManager.getCookie();
|
|
143
|
+
if (cookie) {
|
|
144
|
+
logger_1.Logger.info(`Cookie: ${cookie}`);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
logger_1.Logger.warning("No cookie found.");
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
cookieCommand
|
|
151
|
+
.command("delete")
|
|
152
|
+
.description("Delete cookie")
|
|
153
|
+
.action(() => {
|
|
154
|
+
cookieManager.deleteCookie();
|
|
155
|
+
logger_1.Logger.success("Cookie deleted successfully.");
|
|
156
|
+
});
|
|
157
|
+
const searchCommand = commander_1.program
|
|
158
|
+
.command("search")
|
|
159
|
+
.description("Search TikTok users or live streams or videos");
|
|
160
|
+
searchCommand
|
|
161
|
+
.command("user")
|
|
162
|
+
.description("Search TikTok users")
|
|
163
|
+
.argument("<keyword>", "Search keyword")
|
|
164
|
+
.option("-p, --page <number>", "Page number", "1")
|
|
165
|
+
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
166
|
+
.action(async (keyword, options) => {
|
|
167
|
+
try {
|
|
168
|
+
const page = parseInt(options.page);
|
|
169
|
+
const results = await __1.default.Search(keyword, {
|
|
170
|
+
type: "user",
|
|
171
|
+
cookie: cookieManager.getCookie(),
|
|
172
|
+
page: page,
|
|
173
|
+
proxy: options.proxy
|
|
174
|
+
});
|
|
175
|
+
if (results.status === "success") {
|
|
176
|
+
const data = results.result;
|
|
177
|
+
for (const [index, item] of data.entries()) {
|
|
178
|
+
if (item.type === "user") {
|
|
179
|
+
logger_1.Logger.info(`---- USER ${index + 1} ----`);
|
|
180
|
+
logger_1.Logger.result(`Username: ${item.username}`, chalk_1.default.green);
|
|
181
|
+
logger_1.Logger.result(`Nickname: ${item.nickname}`, chalk_1.default.green);
|
|
182
|
+
logger_1.Logger.result(`Bio: ${item.signature}`, chalk_1.default.green);
|
|
183
|
+
logger_1.Logger.result(`Followers: ${item.followerCount}`, chalk_1.default.yellow);
|
|
184
|
+
logger_1.Logger.result(`Verified: ${item.isVerified ? "Yes" : "No"}`, chalk_1.default.yellow);
|
|
185
|
+
logger_1.Logger.result(`Profile URL: ${item.url}`, chalk_1.default.yellow);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
logger_1.Logger.info(`Total users: ${data.length}`);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
searchCommand
|
|
199
|
+
.command("live")
|
|
200
|
+
.description("Search TikTok live streams")
|
|
201
|
+
.argument("<keyword>", "Search keyword")
|
|
202
|
+
.option("-p, --page <number>", "Page number", "1")
|
|
203
|
+
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
204
|
+
.action(async (keyword, options) => {
|
|
205
|
+
try {
|
|
206
|
+
const page = parseInt(options.page);
|
|
207
|
+
const results = await __1.default.Search(keyword, {
|
|
208
|
+
type: "live",
|
|
209
|
+
cookie: cookieManager.getCookie(),
|
|
210
|
+
page: page,
|
|
211
|
+
proxy: options.proxy
|
|
212
|
+
});
|
|
213
|
+
if (results.status === "success") {
|
|
214
|
+
const data = results.result;
|
|
215
|
+
for (const [index, item] of data.entries()) {
|
|
216
|
+
if (item.type === "live") {
|
|
217
|
+
logger_1.Logger.info(`---- LIVE ${index + 1} ----`);
|
|
218
|
+
logger_1.Logger.result(`Title: ${item.liveInfo.title}`, chalk_1.default.green);
|
|
219
|
+
logger_1.Logger.result(`Nickname: ${item.liveInfo.owner.nickname}`, chalk_1.default.green);
|
|
220
|
+
logger_1.Logger.result(`Username: ${item.liveInfo.owner.username}`, chalk_1.default.green);
|
|
221
|
+
logger_1.Logger.result(`Verified: ${item.liveInfo.owner.isVerified ? "Yes" : "No"}`, chalk_1.default.green);
|
|
222
|
+
logger_1.Logger.result(`Type Third Party: ${item.liveInfo.liveTypeThirdParty ? "Yes" : "No"}`, chalk_1.default.green);
|
|
223
|
+
logger_1.Logger.result(`Hashtag: ${item.liveInfo.hashtag}`, chalk_1.default.green);
|
|
224
|
+
logger_1.Logger.info(`---- STATISTICS ----`);
|
|
225
|
+
logger_1.Logger.result(`Likes: ${item.liveInfo.stats.likeCount}`, chalk_1.default.yellow);
|
|
226
|
+
logger_1.Logger.result(`Views: ${item.liveInfo.stats.viewerCount}`, chalk_1.default.yellow);
|
|
227
|
+
logger_1.Logger.result(`Users: ${item.liveInfo.stats.totalUser}`, chalk_1.default.yellow);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
logger_1.Logger.info(`Total live streams: ${data.length}`);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
searchCommand
|
|
241
|
+
.command("video")
|
|
242
|
+
.description("Search TikTok videos")
|
|
243
|
+
.argument("<keyword>", "Search keyword")
|
|
244
|
+
.option("-p, --page <number>", "Page number", "1")
|
|
245
|
+
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
246
|
+
.action(async (keyword, options) => {
|
|
247
|
+
try {
|
|
248
|
+
const page = parseInt(options.page);
|
|
249
|
+
const results = await __1.default.Search(keyword, {
|
|
250
|
+
type: "video",
|
|
251
|
+
cookie: cookieManager.getCookie(),
|
|
252
|
+
page: page,
|
|
253
|
+
proxy: options.proxy
|
|
254
|
+
});
|
|
255
|
+
if (results.status === "success") {
|
|
256
|
+
const data = results.result;
|
|
257
|
+
for (const [index, item] of data.entries()) {
|
|
258
|
+
if (item.type === "video") {
|
|
259
|
+
logger_1.Logger.info(`---- VIDEO ${index + 1} ----`);
|
|
260
|
+
logger_1.Logger.result(`Video ID: ${item.id}`, chalk_1.default.green);
|
|
261
|
+
logger_1.Logger.result(`Description: ${item.desc}`, chalk_1.default.yellow);
|
|
262
|
+
logger_1.Logger.result(`Author: ${item.author.nickname}`, chalk_1.default.yellow);
|
|
263
|
+
logger_1.Logger.result(`Video URL: ${api_1._tiktokDesktopUrl}/@${item.author.uniqueId}/video/${item.id}`, chalk_1.default.yellow);
|
|
264
|
+
logger_1.Logger.info(`---- STATISTICS ----`);
|
|
265
|
+
logger_1.Logger.result(`Likes: ${item.stats.likeCount}`, chalk_1.default.yellow);
|
|
266
|
+
logger_1.Logger.result(`Favorites: ${item.stats.collectCount}`, chalk_1.default.yellow);
|
|
267
|
+
logger_1.Logger.result(`Views: ${item.stats.playCount}`, chalk_1.default.yellow);
|
|
268
|
+
logger_1.Logger.result(`Shares: ${item.stats.shareCount}`, chalk_1.default.yellow);
|
|
269
|
+
logger_1.Logger.result(`Comments: ${item.stats.commentCount}`, chalk_1.default.yellow);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
logger_1.Logger.info(`Total videos: ${data.length}`);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
commander_1.program
|
|
283
|
+
.command("getvideocomments")
|
|
284
|
+
.description("Get comments from a TikTok video")
|
|
285
|
+
.argument("<url>", "TikTok video URL")
|
|
286
|
+
.option("-l, --limit <number>", "Limit of comments", "10")
|
|
287
|
+
.option("-p, --proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
288
|
+
.action(async (url, options) => {
|
|
289
|
+
try {
|
|
290
|
+
const limit = parseInt(options.limit);
|
|
291
|
+
const comments = await __1.default.GetVideoComments(url, {
|
|
292
|
+
commentLimit: limit,
|
|
293
|
+
proxy: options.proxy
|
|
294
|
+
});
|
|
295
|
+
if (comments.status === "success") {
|
|
296
|
+
const data = comments.result;
|
|
297
|
+
for (const [index, comment] of data.entries()) {
|
|
298
|
+
logger_1.Logger.info(`---- COMMENT ${index + 1} ----`);
|
|
299
|
+
logger_1.Logger.result(`Username: ${comment.user.username}`, chalk_1.default.green);
|
|
300
|
+
logger_1.Logger.result(`Text: ${comment.text}`, chalk_1.default.green);
|
|
301
|
+
logger_1.Logger.result(`Likes: ${comment.likeCount}`, chalk_1.default.yellow);
|
|
302
|
+
}
|
|
303
|
+
logger_1.Logger.info(`Total comments: ${data.length}`);
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
306
|
+
logger_1.Logger.error(`Error: ${comments.message}`);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
commander_1.program
|
|
314
|
+
.command("getuserposts")
|
|
315
|
+
.description("Get posts from a TikTok user")
|
|
316
|
+
.argument("<username>", "TikTok username")
|
|
317
|
+
.option("-l, --limit <number>", "Limit of posts", "5")
|
|
318
|
+
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
319
|
+
.action(async (username, options) => {
|
|
320
|
+
try {
|
|
321
|
+
const postLimit = parseInt(options.limit);
|
|
322
|
+
const results = await __1.default.GetUserPosts(username, {
|
|
323
|
+
postLimit: postLimit,
|
|
324
|
+
proxy: options.proxy
|
|
325
|
+
});
|
|
326
|
+
if (results.status === "success") {
|
|
327
|
+
const data = results.result;
|
|
328
|
+
for (const [index, post] of data.entries()) {
|
|
329
|
+
logger_1.Logger.info(`---- POST ${index + 1} ----`);
|
|
330
|
+
logger_1.Logger.result(`Video ID: ${post.id}`, chalk_1.default.green);
|
|
331
|
+
logger_1.Logger.result(`Description: ${post.desc}`, chalk_1.default.yellow);
|
|
332
|
+
logger_1.Logger.info(`---- STATISTICS ----`);
|
|
333
|
+
logger_1.Logger.result(`Likes: ${post.stats.likeCount}`, chalk_1.default.yellow);
|
|
334
|
+
logger_1.Logger.result(`Favorites: ${post.stats.collectCount}`, chalk_1.default.yellow);
|
|
335
|
+
logger_1.Logger.result(`Views: ${post.stats.playCount}`, chalk_1.default.yellow);
|
|
336
|
+
logger_1.Logger.result(`Shares: ${post.stats.shareCount}`, chalk_1.default.yellow);
|
|
337
|
+
logger_1.Logger.result(`Comments: ${post.stats.commentCount}`, chalk_1.default.yellow);
|
|
338
|
+
}
|
|
339
|
+
logger_1.Logger.info(`Total posts: ${data.length}`);
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
342
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
commander_1.program
|
|
350
|
+
.command("getuserreposts")
|
|
351
|
+
.description("Get reposts from a TikTok user")
|
|
352
|
+
.argument("<username>", "TikTok username")
|
|
353
|
+
.option("-l, --limit <number>", "Limit of reposts", "5")
|
|
354
|
+
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
355
|
+
.action(async (username, options) => {
|
|
356
|
+
try {
|
|
357
|
+
const postLimit = parseInt(options.limit);
|
|
358
|
+
const results = await __1.default.GetUserReposts(username, {
|
|
359
|
+
postLimit: postLimit,
|
|
360
|
+
proxy: options.proxy
|
|
361
|
+
});
|
|
362
|
+
if (results.status === "success") {
|
|
363
|
+
const data = results.result;
|
|
364
|
+
for (const [index, repost] of data.entries()) {
|
|
365
|
+
logger_1.Logger.info(`---- REPOST ${index + 1} ----`);
|
|
366
|
+
logger_1.Logger.result(`Video ID: ${repost.id}`, chalk_1.default.green);
|
|
367
|
+
logger_1.Logger.result(`Description: ${repost.desc}`, chalk_1.default.yellow);
|
|
368
|
+
logger_1.Logger.info(`---- STATISTICS ----`);
|
|
369
|
+
logger_1.Logger.result(`Shares: ${repost.stats.shareCount}`, chalk_1.default.yellow);
|
|
370
|
+
if (repost.stats.likeCount) {
|
|
371
|
+
logger_1.Logger.result(`Likes: ${repost.stats.likeCount}`, chalk_1.default.yellow);
|
|
372
|
+
}
|
|
373
|
+
if (repost.stats.collectCount) {
|
|
374
|
+
logger_1.Logger.result(`Favorites: ${repost.stats.collectCount}`, chalk_1.default.yellow);
|
|
375
|
+
}
|
|
376
|
+
if (repost.stats.playCount) {
|
|
377
|
+
logger_1.Logger.result(`Views: ${repost.stats.playCount}`, chalk_1.default.yellow);
|
|
378
|
+
}
|
|
379
|
+
if (repost.stats.commentCount) {
|
|
380
|
+
logger_1.Logger.result(`Comments: ${repost.stats.commentCount}`, chalk_1.default.yellow);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
logger_1.Logger.info(`Total reposts: ${data.length}`);
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
catch (error) {
|
|
390
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
commander_1.program
|
|
394
|
+
.command("stalk")
|
|
395
|
+
.description("Stalk a TikTok user")
|
|
396
|
+
.argument("<username>", "TikTok username")
|
|
397
|
+
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
398
|
+
.action(async (username, options) => {
|
|
399
|
+
try {
|
|
400
|
+
const results = await __1.default.StalkUser(username, {
|
|
401
|
+
proxy: options.proxy
|
|
402
|
+
});
|
|
403
|
+
if (results.status === "success") {
|
|
404
|
+
const data = results.result;
|
|
405
|
+
logger_1.Logger.info("---- TIKTOK STALKER ----");
|
|
406
|
+
logger_1.Logger.result(`Username:${data.user.username}`, chalk_1.default.green);
|
|
407
|
+
logger_1.Logger.result(`Nickname:${data.user.nickname}`, chalk_1.default.green);
|
|
408
|
+
logger_1.Logger.result(`Bio:${data.user.signature}`, chalk_1.default.green);
|
|
409
|
+
logger_1.Logger.result(`Verified:${data.user.verified ? "Yes" : "No"}`, chalk_1.default.green);
|
|
410
|
+
logger_1.Logger.result(`Commerce User:${data.user.commerceUser ? "Yes" : "No"}`, chalk_1.default.green);
|
|
411
|
+
logger_1.Logger.result(`Private Account:${data.user.privateAccount ? "Yes" : "No"}`, chalk_1.default.green);
|
|
412
|
+
logger_1.Logger.result(`Region:${data.user.region}`, chalk_1.default.green);
|
|
413
|
+
logger_1.Logger.info("---- STATISTICS ----");
|
|
414
|
+
logger_1.Logger.result(`Followers:${data.stats.followerCount}`, chalk_1.default.yellow);
|
|
415
|
+
logger_1.Logger.result(`Following:${data.stats.followingCount}`, chalk_1.default.yellow);
|
|
416
|
+
logger_1.Logger.result(`Hearts:${data.stats.heartCount}`, chalk_1.default.yellow);
|
|
417
|
+
logger_1.Logger.result(`Videos:${data.stats.videoCount}`, chalk_1.default.yellow);
|
|
418
|
+
logger_1.Logger.result(`Likes:${data.stats.likeCount}`, chalk_1.default.yellow);
|
|
419
|
+
logger_1.Logger.result(`Friends:${data.stats.friendCount}`, chalk_1.default.yellow);
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
commander_1.program
|
|
430
|
+
.command("collection")
|
|
431
|
+
.description("Get videos from a TikTok collection (supports collection ID or URL)")
|
|
432
|
+
.argument("<collectionIdOrUrl>", "Collection ID or URL (e.g. 7507916135931218695 or https://www.tiktok.com/@username/collection/name-id)")
|
|
433
|
+
.option("-p, --page <number>", "Page number", "1")
|
|
434
|
+
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
435
|
+
.option("-n, --count <number>", "Number of items to fetch", (val) => parseInt(val), 5)
|
|
436
|
+
.action(async (collectionIdOrUrl, options) => {
|
|
437
|
+
try {
|
|
438
|
+
logger_1.Logger.info(`Fetching page ${options.page} with ${options.count} items per page from collection...`);
|
|
439
|
+
const results = await __1.default.Collection(collectionIdOrUrl, {
|
|
440
|
+
page: options.page,
|
|
441
|
+
proxy: options.proxy,
|
|
442
|
+
count: options.count
|
|
443
|
+
});
|
|
444
|
+
if (results.status === "success" && results.result) {
|
|
445
|
+
const { itemList, hasMore } = results.result;
|
|
446
|
+
logger_1.Logger.info(`Found ${itemList.length} videos in collection`);
|
|
447
|
+
logger_1.Logger.info(`Has more videos: ${hasMore}`);
|
|
448
|
+
for (const [index, video] of itemList.entries()) {
|
|
449
|
+
logger_1.Logger.info(`---- VIDEO ${index + 1} ----`);
|
|
450
|
+
logger_1.Logger.result(`Video ID: ${video.id}`, chalk_1.default.green);
|
|
451
|
+
logger_1.Logger.result(`Description: ${video.desc}`, chalk_1.default.yellow);
|
|
452
|
+
logger_1.Logger.result(`Author: ${video.author?.nickname || "Unknown"}`, chalk_1.default.yellow);
|
|
453
|
+
logger_1.Logger.result(`Created: ${new Date(video.createTime * 1000).toLocaleString()}`, chalk_1.default.yellow);
|
|
454
|
+
if (video.statistics) {
|
|
455
|
+
logger_1.Logger.info(`---- STATISTICS ----`);
|
|
456
|
+
logger_1.Logger.result(`Likes: ${video.statistics.likeCount || 0}`, chalk_1.default.yellow);
|
|
457
|
+
logger_1.Logger.result(`Comments: ${video.statistics.commentCount || 0}`, chalk_1.default.yellow);
|
|
458
|
+
logger_1.Logger.result(`Shares: ${video.statistics.shareCount || 0}`, chalk_1.default.yellow);
|
|
459
|
+
logger_1.Logger.result(`Plays: ${video.statistics.playCount || 0}`, chalk_1.default.yellow);
|
|
460
|
+
}
|
|
461
|
+
if (video.video) {
|
|
462
|
+
logger_1.Logger.info(`---- VIDEO URLs ----`);
|
|
463
|
+
const videoUrl = `${api_1._tiktokDesktopUrl}/@${video.author?.uniqueId || "unknown"}/video/${video.id}`;
|
|
464
|
+
logger_1.Logger.result(`Video URL: ${videoUrl}`, chalk_1.default.blue);
|
|
465
|
+
}
|
|
466
|
+
if (video.textExtra?.length > 0) {
|
|
467
|
+
logger_1.Logger.info(`---- HASHTAGS ----`);
|
|
468
|
+
video.textExtra.forEach((tag) => {
|
|
469
|
+
if (tag.hashtagName) {
|
|
470
|
+
logger_1.Logger.result(`#${tag.hashtagName}`, chalk_1.default.cyan);
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
if (hasMore) {
|
|
476
|
+
logger_1.Logger.info("\nTo fetch more videos, use:");
|
|
477
|
+
logger_1.Logger.info(`tiktokdl collection ${collectionIdOrUrl} -p ${parseInt(options.page) + 1}`);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
else {
|
|
481
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
catch (error) {
|
|
485
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
486
|
+
}
|
|
487
|
+
});
|
|
488
|
+
commander_1.program
|
|
489
|
+
.command("playlist")
|
|
490
|
+
.description("Get videos from a TikTok playlist")
|
|
491
|
+
.argument("<PlaylistIdOrUrl>", "Collection URL (e.g. https://www.tiktok.com/@username/playlist/name-id)")
|
|
492
|
+
.option("-p, --page <number>", "Page number", "1")
|
|
493
|
+
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
494
|
+
.option("-c, --count <number>", "Number of items to fetch (max: 20)", (val) => parseInt(val), 5)
|
|
495
|
+
.option("-r, --raw", "Show raw response", false)
|
|
496
|
+
.action(async (url, options) => {
|
|
497
|
+
try {
|
|
498
|
+
logger_1.Logger.info(`Fetching page ${options.page} with ${options.count} items per page from playlist...`);
|
|
499
|
+
const results = await __1.default.Playlist(url, {
|
|
500
|
+
page: options.page,
|
|
501
|
+
proxy: options.proxy,
|
|
502
|
+
count: options.count
|
|
503
|
+
});
|
|
504
|
+
const contentType = (content) => {
|
|
505
|
+
if (content?.imagePost) {
|
|
506
|
+
return "photo";
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
return "video";
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
if (results.status === "success" && results.result) {
|
|
513
|
+
if (options.raw) {
|
|
514
|
+
console.log(JSON.stringify(results.result, null, 2));
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
517
|
+
const { itemList, hasMore } = results.result;
|
|
518
|
+
logger_1.Logger.info(`Found ${itemList.length} items in playlist`);
|
|
519
|
+
logger_1.Logger.info(`Has more items: ${hasMore}`);
|
|
520
|
+
for (const [index, item] of itemList.entries()) {
|
|
521
|
+
logger_1.Logger.info(`---- ITEM ${index + 1} ----`);
|
|
522
|
+
logger_1.Logger.result(`Item ID: ${item.id}`, chalk_1.default.green);
|
|
523
|
+
logger_1.Logger.result(`Description: ${item.desc}`, chalk_1.default.yellow);
|
|
524
|
+
logger_1.Logger.result(`Author: ${item.author?.nickname || "Unknown"}`, chalk_1.default.yellow);
|
|
525
|
+
logger_1.Logger.result(`Created: ${new Date(item.createTime * 1000).toLocaleString()}`, chalk_1.default.yellow);
|
|
526
|
+
if (item.stats) {
|
|
527
|
+
logger_1.Logger.info(`---- STATISTICS ----`);
|
|
528
|
+
logger_1.Logger.result(`Comments: ${item.stats.commentCount || 0}`, chalk_1.default.yellow);
|
|
529
|
+
logger_1.Logger.result(`Shares: ${item.stats.shareCount || 0}`, chalk_1.default.yellow);
|
|
530
|
+
logger_1.Logger.result(`Plays: ${item.stats.playCount || 0}`, chalk_1.default.yellow);
|
|
531
|
+
}
|
|
532
|
+
if (item.video) {
|
|
533
|
+
logger_1.Logger.info(`---- VIDEO URLs ----`);
|
|
534
|
+
const videoUrl = `${api_1._tiktokDesktopUrl}/@${item.author?.uniqueId || "unknown"}/${contentType(item)}/${item.id}`;
|
|
535
|
+
logger_1.Logger.result(`Video URL: ${videoUrl}`, chalk_1.default.blue);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
if (hasMore) {
|
|
539
|
+
logger_1.Logger.info("\nTo fetch more videos, use:");
|
|
540
|
+
logger_1.Logger.info(`tiktokdl playlist ${url} -p ${parseInt(options.page) + 1}`);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
catch (error) {
|
|
548
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
commander_1.program
|
|
552
|
+
.command("trending")
|
|
553
|
+
.description("Get TikTok trending content and creators")
|
|
554
|
+
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
555
|
+
.option("-c, --creators", "Show only trending creators", false)
|
|
556
|
+
.option("-r, --raw", "Show raw response", false)
|
|
557
|
+
.action(async (options) => {
|
|
558
|
+
try {
|
|
559
|
+
if (options.creators) {
|
|
560
|
+
logger_1.Logger.info("Fetching trending creators...");
|
|
561
|
+
const results = await __1.default.TrendingCreators({
|
|
562
|
+
proxy: options.proxy
|
|
563
|
+
});
|
|
564
|
+
if (results.status === "success" && results.result) {
|
|
565
|
+
if (options.raw) {
|
|
566
|
+
console.log(JSON.stringify(results.result, null, 2));
|
|
567
|
+
return;
|
|
568
|
+
}
|
|
569
|
+
logger_1.Logger.info(`Found ${results.result.length} trending creators`);
|
|
570
|
+
results.result.slice(0, 20).forEach((creator, index) => {
|
|
571
|
+
logger_1.Logger.info(`---- CREATOR ${index + 1} ----`);
|
|
572
|
+
logger_1.Logger.result(`Username: @${creator.username}`, chalk_1.default.green);
|
|
573
|
+
logger_1.Logger.result(`Nickname: ${creator.nickname}`, chalk_1.default.green);
|
|
574
|
+
logger_1.Logger.result(`Verified: ${creator.verified ? "Yes" : "No"}`, chalk_1.default.green);
|
|
575
|
+
logger_1.Logger.result(`Followers: ${creator.followerCount.toLocaleString()}`, chalk_1.default.yellow);
|
|
576
|
+
logger_1.Logger.result(`Total Likes: ${creator.likeCount.toLocaleString()}`, chalk_1.default.yellow);
|
|
577
|
+
logger_1.Logger.result(`Videos: ${creator.videoCount.toLocaleString()}`, chalk_1.default.yellow);
|
|
578
|
+
logger_1.Logger.result(`Following: ${creator.followingCount.toLocaleString()}`, chalk_1.default.yellow);
|
|
579
|
+
logger_1.Logger.result(`Description: ${creator.description.substring(0, 100)}${creator.description.length > 100 ? "..." : ""}`, chalk_1.default.blue);
|
|
580
|
+
logger_1.Logger.result(`Profile: https://www.tiktok.com${creator.link}`, chalk_1.default.blue);
|
|
581
|
+
});
|
|
582
|
+
if (results.result.length > 20) {
|
|
583
|
+
logger_1.Logger.info(`\nShowing first 20 of ${results.result.length} trending creators`);
|
|
584
|
+
}
|
|
585
|
+
const verifiedCount = results.result.filter((c) => c.verified).length;
|
|
586
|
+
const totalFollowers = results.result.reduce((sum, c) => sum + c.followerCount, 0);
|
|
587
|
+
const avgFollowers = Math.round(totalFollowers / results.result.length);
|
|
588
|
+
logger_1.Logger.info(`\n---- STATISTICS ----`);
|
|
589
|
+
logger_1.Logger.result(`Verified creators: ${verifiedCount}/${results.result.length}`, chalk_1.default.cyan);
|
|
590
|
+
logger_1.Logger.result(`Average followers: ${avgFollowers.toLocaleString()}`, chalk_1.default.cyan);
|
|
591
|
+
logger_1.Logger.result(`Total combined followers: ${totalFollowers.toLocaleString()}`, chalk_1.default.cyan);
|
|
592
|
+
}
|
|
593
|
+
else {
|
|
594
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
else {
|
|
598
|
+
logger_1.Logger.info("Fetching trending content...");
|
|
599
|
+
const results = await __1.default.Trending({
|
|
600
|
+
proxy: options.proxy
|
|
601
|
+
});
|
|
602
|
+
if (results.status === "success" && results.result) {
|
|
603
|
+
if (options.raw) {
|
|
604
|
+
console.log(JSON.stringify(results.result, null, 2));
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
logger_1.Logger.info(`Found ${results.result.length} trending sections`);
|
|
608
|
+
results.result.forEach((section, sectionIndex) => {
|
|
609
|
+
logger_1.Logger.info(`\n---- SECTION ${sectionIndex + 1} ----`);
|
|
610
|
+
logger_1.Logger.result(`Items in section: ${section.exploreList.length}`, chalk_1.default.green);
|
|
611
|
+
if (section.pageState) {
|
|
612
|
+
logger_1.Logger.result(`Region: ${section.pageState.region}`, chalk_1.default.yellow);
|
|
613
|
+
logger_1.Logger.result(`OS: ${section.pageState.os}`, chalk_1.default.yellow);
|
|
614
|
+
}
|
|
615
|
+
section.exploreList.slice(0, 5).forEach((item, index) => {
|
|
616
|
+
const cardItem = item.cardItem;
|
|
617
|
+
logger_1.Logger.info(`\n Item ${index + 1}:`);
|
|
618
|
+
logger_1.Logger.result(` Title: ${cardItem.title}`, chalk_1.default.green);
|
|
619
|
+
logger_1.Logger.result(` Subtitle: ${cardItem.subTitle}`, chalk_1.default.green);
|
|
620
|
+
logger_1.Logger.result(` Type: ${cardItem.type}`, chalk_1.default.yellow);
|
|
621
|
+
logger_1.Logger.result(` Description: ${cardItem.description.substring(0, 80)}${cardItem.description.length > 80 ? "..." : ""}`, chalk_1.default.blue);
|
|
622
|
+
if (cardItem.extraInfo) {
|
|
623
|
+
logger_1.Logger.result(` Verified: ${cardItem.extraInfo.verified ? "Yes" : "No"}`, chalk_1.default.cyan);
|
|
624
|
+
logger_1.Logger.result(` Fans: ${cardItem.extraInfo.fans?.toLocaleString() || "N/A"}`, chalk_1.default.cyan);
|
|
625
|
+
logger_1.Logger.result(` Likes: ${cardItem.extraInfo.likes?.toLocaleString() || "N/A"}`, chalk_1.default.cyan);
|
|
626
|
+
logger_1.Logger.result(` Videos: ${cardItem.extraInfo.video || "N/A"}`, chalk_1.default.cyan);
|
|
627
|
+
}
|
|
628
|
+
logger_1.Logger.result(` Profile: https://www.tiktok.com${cardItem.link}`, chalk_1.default.blue);
|
|
629
|
+
});
|
|
630
|
+
if (section.exploreList.length > 5) {
|
|
631
|
+
logger_1.Logger.info(` ... and ${section.exploreList.length - 5} more items`);
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
logger_1.Logger.info("\nTip: Use --creators flag to see only trending creators");
|
|
635
|
+
logger_1.Logger.info("Tip: Use --raw flag to see the complete JSON response");
|
|
636
|
+
}
|
|
637
|
+
else {
|
|
638
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
catch (error) {
|
|
643
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
commander_1.program
|
|
647
|
+
.command("getmusicvideos")
|
|
648
|
+
.description("Get videos by music ID or URL")
|
|
649
|
+
.argument("<musicIdOrUrl>", "Music ID or URL (e.g., 6771810675950880769 or https://www.tiktok.com/music/QKThr-6771810675950880769)")
|
|
650
|
+
.option("-p, --page <number>", "Page number", "1")
|
|
651
|
+
.option("-c, --count <number>", "Number of videos per page", "30")
|
|
652
|
+
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
653
|
+
.option("-r, --raw", "Show raw response", false)
|
|
654
|
+
.action(async (musicIdOrUrl, options) => {
|
|
655
|
+
try {
|
|
656
|
+
const page = parseInt(options.page);
|
|
657
|
+
const count = parseInt(options.count);
|
|
658
|
+
logger_1.Logger.info(`Fetching videos for music: ${musicIdOrUrl} (page ${page}, ${count} per page)...`);
|
|
659
|
+
const results = await __1.default.GetVideosByMusicId(musicIdOrUrl, {
|
|
660
|
+
page,
|
|
661
|
+
count,
|
|
662
|
+
proxy: options.proxy
|
|
663
|
+
});
|
|
664
|
+
if (results.status === "success" && results.result) {
|
|
665
|
+
if (options.raw) {
|
|
666
|
+
console.log(JSON.stringify(results.result, null, 2));
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
const { music, videos, totalVideos } = results.result;
|
|
670
|
+
if (music) {
|
|
671
|
+
logger_1.Logger.info("\n---- MUSIC INFO ----");
|
|
672
|
+
logger_1.Logger.result(`Music ID: ${music.id}`, chalk_1.default.green);
|
|
673
|
+
logger_1.Logger.result(`Title: ${music.title}`, chalk_1.default.green);
|
|
674
|
+
logger_1.Logger.result(`Author: ${music.authorName}`, chalk_1.default.green);
|
|
675
|
+
logger_1.Logger.result(`Duration: ${music.duration || "N/A"} seconds`, chalk_1.default.yellow);
|
|
676
|
+
logger_1.Logger.result(`Original: ${music.original ? "Yes" : "No"}`, chalk_1.default.yellow);
|
|
677
|
+
}
|
|
678
|
+
if (videos && videos.length > 0) {
|
|
679
|
+
logger_1.Logger.info(`\nFound ${videos.length} videos`);
|
|
680
|
+
if (totalVideos) {
|
|
681
|
+
logger_1.Logger.info(`Total videos using this music: ${totalVideos}`);
|
|
682
|
+
}
|
|
683
|
+
videos.slice(0, 10).forEach((video, index) => {
|
|
684
|
+
logger_1.Logger.info(`\n---- VIDEO ${index + 1} ----`);
|
|
685
|
+
logger_1.Logger.result(`Video ID: ${video.id}`, chalk_1.default.green);
|
|
686
|
+
logger_1.Logger.result(`Description: ${video.desc || "N/A"}`, chalk_1.default.yellow);
|
|
687
|
+
logger_1.Logger.result(`Author: ${video.author?.nickname || "Unknown"}`, chalk_1.default.yellow);
|
|
688
|
+
logger_1.Logger.result(`Username: @${video.author?.uniqueId || "unknown"}`, chalk_1.default.yellow);
|
|
689
|
+
if (video.stats) {
|
|
690
|
+
logger_1.Logger.info("---- STATISTICS ----");
|
|
691
|
+
logger_1.Logger.result(`Likes: ${video.stats.diggCount?.toLocaleString() || 0}`, chalk_1.default.yellow);
|
|
692
|
+
logger_1.Logger.result(`Comments: ${video.stats.commentCount?.toLocaleString() || 0}`, chalk_1.default.yellow);
|
|
693
|
+
logger_1.Logger.result(`Shares: ${video.stats.shareCount?.toLocaleString() || 0}`, chalk_1.default.yellow);
|
|
694
|
+
logger_1.Logger.result(`Plays: ${video.stats.playCount?.toLocaleString() || 0}`, chalk_1.default.yellow);
|
|
695
|
+
}
|
|
696
|
+
const videoUrl = `${api_1._tiktokDesktopUrl}/@${video.author?.uniqueId || "unknown"}/video/${video.id}`;
|
|
697
|
+
logger_1.Logger.result(`Video URL: ${videoUrl}`, chalk_1.default.blue);
|
|
698
|
+
});
|
|
699
|
+
if (videos.length > 10) {
|
|
700
|
+
logger_1.Logger.info(`\n... and ${videos.length - 10} more videos`);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
else {
|
|
704
|
+
logger_1.Logger.warning("No videos found for this music");
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
else {
|
|
708
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
catch (error) {
|
|
712
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
commander_1.program
|
|
716
|
+
.command("getmusicdetail")
|
|
717
|
+
.description("Get detailed information about a music/audio track by music ID or URL")
|
|
718
|
+
.argument("<musicIdOrUrl>", "Music ID or URL (e.g., 6771810675950880769 or https://www.tiktok.com/music/QKThr-6771810675950880769)")
|
|
719
|
+
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
720
|
+
.option("-r, --raw", "Show raw response", false)
|
|
721
|
+
.action(async (musicIdOrUrl, options) => {
|
|
722
|
+
try {
|
|
723
|
+
const cookie = cookieManager.getCookie();
|
|
724
|
+
if (!cookie) {
|
|
725
|
+
logger_1.Logger.error("Cookie is required for this command. Set cookie using: tiktokdl cookie set <value>");
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
logger_1.Logger.info(`Fetching music detail for: ${musicIdOrUrl}...`);
|
|
729
|
+
const results = await __1.default.GetMusicDetail(musicIdOrUrl, {
|
|
730
|
+
cookie,
|
|
731
|
+
proxy: options.proxy
|
|
732
|
+
});
|
|
733
|
+
if (results.status === "success" && results.result) {
|
|
734
|
+
if (options.raw) {
|
|
735
|
+
console.log(JSON.stringify(results.result, null, 2));
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
const { musicInfo, shareMeta } = results.result;
|
|
739
|
+
logger_1.Logger.info("\n==== MUSIC INFORMATION ====");
|
|
740
|
+
logger_1.Logger.result(`Music ID: ${musicInfo.music.id}`, chalk_1.default.green);
|
|
741
|
+
logger_1.Logger.result(`Title: ${musicInfo.music.title}`, chalk_1.default.green);
|
|
742
|
+
logger_1.Logger.result(`Author: ${musicInfo.music.authorName}`, chalk_1.default.green);
|
|
743
|
+
logger_1.Logger.result(`Duration: ${musicInfo.music.duration} seconds`, chalk_1.default.yellow);
|
|
744
|
+
logger_1.Logger.result(`Original: ${musicInfo.music.original ? "Yes" : "No"}`, chalk_1.default.yellow);
|
|
745
|
+
logger_1.Logger.result(`Copyrighted: ${musicInfo.music.isCopyrighted ? "Yes" : "No"}`, chalk_1.default.yellow);
|
|
746
|
+
logger_1.Logger.result(`Private: ${musicInfo.music.private ? "Yes" : "No"}`, chalk_1.default.yellow);
|
|
747
|
+
logger_1.Logger.info("\n==== AUTHOR INFORMATION ====");
|
|
748
|
+
logger_1.Logger.result(`Author ID: ${musicInfo.author.id}`, chalk_1.default.green);
|
|
749
|
+
logger_1.Logger.result(`Nickname: ${musicInfo.author.nickname}`, chalk_1.default.green);
|
|
750
|
+
logger_1.Logger.result(`Username: @${musicInfo.author.uniqueId}`, chalk_1.default.green);
|
|
751
|
+
logger_1.Logger.result(`Signature: ${musicInfo.author.signature || "N/A"}`, chalk_1.default.yellow);
|
|
752
|
+
logger_1.Logger.result(`Verified: ${musicInfo.author.ftc ? "Yes" : "No"}`, chalk_1.default.yellow);
|
|
753
|
+
logger_1.Logger.result(`Private Account: ${musicInfo.author.privateAccount ? "Yes" : "No"}`, chalk_1.default.yellow);
|
|
754
|
+
logger_1.Logger.info("\n==== STATISTICS ====");
|
|
755
|
+
logger_1.Logger.result(`Videos using this music: ${musicInfo.stats.videoCount.toLocaleString()}`, chalk_1.default.cyan);
|
|
756
|
+
logger_1.Logger.info("\n==== URLs ====");
|
|
757
|
+
logger_1.Logger.result(`Play URL: ${musicInfo.music.playUrl}`, chalk_1.default.blue);
|
|
758
|
+
logger_1.Logger.result(`Cover Thumbnail: ${musicInfo.music.coverThumb}`, chalk_1.default.blue);
|
|
759
|
+
logger_1.Logger.result(`Cover Medium: ${musicInfo.music.coverMedium}`, chalk_1.default.blue);
|
|
760
|
+
logger_1.Logger.result(`Cover Large: ${musicInfo.music.coverLarge}`, chalk_1.default.blue);
|
|
761
|
+
if (shareMeta) {
|
|
762
|
+
logger_1.Logger.info("\n==== SHARE META ====");
|
|
763
|
+
logger_1.Logger.result(`Title: ${shareMeta.title}`, chalk_1.default.magenta);
|
|
764
|
+
logger_1.Logger.result(`Description: ${shareMeta.desc}`, chalk_1.default.magenta);
|
|
765
|
+
}
|
|
766
|
+
logger_1.Logger.info("\n✨ Tip: Use the music ID with 'getmusicvideos' command to see videos using this music");
|
|
767
|
+
}
|
|
768
|
+
else {
|
|
769
|
+
logger_1.Logger.error(`Error: ${results.message}`);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
catch (error) {
|
|
773
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
774
|
+
}
|
|
775
|
+
});
|
|
776
|
+
commander_1.program
|
|
777
|
+
.command("downloadmusic")
|
|
778
|
+
.description("Download music/audio from TikTok by music ID or URL (requires cookie)")
|
|
779
|
+
.argument("<musicIdOrUrl>", "Music ID or TikTok music URL (e.g. 7562597337407785760 or https://www.tiktok.com/music/QKThr-6771810675950880769)")
|
|
780
|
+
.option("-o, --output <path>", "Output directory path")
|
|
781
|
+
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
|
782
|
+
.action(async (musicIdOrUrl, options) => {
|
|
783
|
+
try {
|
|
784
|
+
const cookie = cookieManager.getCookie();
|
|
785
|
+
if (!cookie) {
|
|
786
|
+
logger_1.Logger.error("Cookie is required for downloading music. Set cookie using: tiktokdl cookie set <value>");
|
|
787
|
+
logger_1.Logger.info("\n💡 How to get cookie: Open TikTok in your browser, login, open DevTools (F12), go to Application/Storage > Cookies, and copy the cookie value");
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
const outputPath = options.output || (0, downloadManager_1.getDefaultDownloadPath)();
|
|
791
|
+
const musicId = (0, urlExtractors_1.extractMusicId)(musicIdOrUrl);
|
|
792
|
+
if (!musicId) {
|
|
793
|
+
logger_1.Logger.error("Invalid input. Please provide either a music ID (numbers only) or a valid TikTok music URL");
|
|
794
|
+
logger_1.Logger.info("Example URL: https://www.tiktok.com/music/QKThr-6771810675950880769");
|
|
795
|
+
logger_1.Logger.info("Example ID: 7562597337407785760");
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
logger_1.Logger.info(`Starting music download for music ID: ${musicId}`);
|
|
799
|
+
logger_1.Logger.info(`Output directory: ${outputPath}`);
|
|
800
|
+
await (0, downloadManager_1.downloadMusicFromDetail)(musicIdOrUrl, cookie, outputPath, options.proxy);
|
|
801
|
+
logger_1.Logger.success("\n✅ Music download completed!");
|
|
802
|
+
logger_1.Logger.info("\n💡 Tip: Use 'tiktokdl getmusicdetail' to view detailed information about this music");
|
|
803
|
+
}
|
|
804
|
+
catch (error) {
|
|
805
|
+
logger_1.Logger.error(`Error: ${error.message}`);
|
|
806
|
+
logger_1.Logger.info("\nPossible issues:\n- Invalid or expired cookie\n- Invalid music ID\n- Network/connection problem\n- Music might be region-restricted");
|
|
807
|
+
}
|
|
808
|
+
});
|
|
809
|
+
commander_1.program.parse();
|