use page instead of cursor
This commit is contained in:
parent
baa8fa2cc8
commit
004e74d338
@ -402,8 +402,8 @@ program
|
||||
"<collectionIdOrUrl>",
|
||||
"Collection ID or URL (e.g. 7507916135931218695 or https://www.tiktok.com/@username/collection/name-id)"
|
||||
)
|
||||
.option("-c, --cursor <cursor>", "Cursor for pagination", "0")
|
||||
.option("-p, --proxy <proxy>", "Proxy URL (http/https/socks)")
|
||||
.option("-p, --page <number>", "Page number", "1")
|
||||
.option("--proxy <proxy>", "Proxy URL (http/https/socks)")
|
||||
.option(
|
||||
"-n, --count <number>",
|
||||
"Number of items to fetch",
|
||||
@ -412,19 +412,18 @@ program
|
||||
)
|
||||
.action(async (collectionIdOrUrl, options) => {
|
||||
try {
|
||||
Logger.info(`Fetching collection... (count: ${options.count})`)
|
||||
Logger.info(`Fetching page ${options.page} with ${options.count} items per page from collection...`)
|
||||
const results = await Tiktok.Collection(collectionIdOrUrl, {
|
||||
cursor: options.cursor,
|
||||
page: options.page,
|
||||
proxy: options.proxy,
|
||||
count: options.count
|
||||
})
|
||||
|
||||
if (results.status === "success" && results.result) {
|
||||
const { itemList, hasMore, cursor } = results.result
|
||||
const { itemList, hasMore } = results.result
|
||||
|
||||
Logger.info(`Found ${itemList.length} videos in collection`)
|
||||
Logger.info(`Has more videos: ${hasMore}`)
|
||||
Logger.info(`Next cursor: ${cursor}\n`)
|
||||
|
||||
for (const [index, video] of itemList.entries()) {
|
||||
Logger.info(`---- VIDEO ${index + 1} ----`)
|
||||
@ -461,9 +460,8 @@ program
|
||||
|
||||
if (video.video) {
|
||||
Logger.info(`---- VIDEO URLs ----`)
|
||||
const videoUrl = `${_tiktokurl}/@${
|
||||
video.author?.uniqueId || "unknown"
|
||||
}/video/${video.id}`
|
||||
const videoUrl = `${_tiktokurl}/@${video.author?.uniqueId || "unknown"
|
||||
}/video/${video.id}`
|
||||
Logger.result(`Video URL: ${videoUrl}`, chalk.blue)
|
||||
}
|
||||
|
||||
@ -479,7 +477,7 @@ program
|
||||
|
||||
if (hasMore) {
|
||||
Logger.info("\nTo fetch more videos, use:")
|
||||
Logger.info(`tiktokdl collection ${collectionIdOrUrl} -c ${cursor}`)
|
||||
Logger.info(`tiktokdl collection ${collectionIdOrUrl} -p ${parseInt(options.page) + 1}`)
|
||||
}
|
||||
} else {
|
||||
Logger.error(`Error: ${results.message}`)
|
||||
|
||||
@ -353,7 +353,12 @@ const generateOdinId = () => {
|
||||
return `${prefix}${random}`
|
||||
}
|
||||
|
||||
export const _getCollectionParams = (collectionId: string, cursor: string = "0", count: number = 5) => {
|
||||
export const _getCollectionParams = (collectionId: string, page: number = 1, count: number = 5) => {
|
||||
let cursor = 0
|
||||
if (page > 0) {
|
||||
cursor = (page - 1) * count
|
||||
}
|
||||
|
||||
return qs.stringify({
|
||||
WebIdLastTime: Date.now(),
|
||||
aid: 1988,
|
||||
@ -368,7 +373,7 @@ export const _getCollectionParams = (collectionId: string, cursor: string = "0",
|
||||
collectionId,
|
||||
cookie_enabled: true,
|
||||
count,
|
||||
cursor,
|
||||
cursor: cursor.toString(),
|
||||
data_collection_enabled: true,
|
||||
device_id: "7002566096994190854",
|
||||
device_platform: "web_pc",
|
||||
|
||||
@ -130,7 +130,7 @@ export = {
|
||||
* @param {string} collectionIdOrUrl - Collection ID or URL (e.g. 7507916135931218695 or https://www.tiktok.com/@username/collection/name-id)
|
||||
* @param {Object} options - The options for collection
|
||||
* @param {string} [options.proxy] - Optional proxy URL
|
||||
* @param {string} [options.cursor] - Optional cursor for pagination
|
||||
* @param {string} [options.page] - Optional page for pagination
|
||||
* @param {number} [options.count] - Optional number of items to fetch
|
||||
* @returns {Promise<TiktokCollectionResponse>}
|
||||
*/
|
||||
@ -138,7 +138,7 @@ export = {
|
||||
collectionIdOrUrl: string,
|
||||
options?: {
|
||||
proxy?: string
|
||||
cursor?: string
|
||||
page?: number
|
||||
count?: number
|
||||
}
|
||||
): Promise<TiktokCollectionResponse> => {
|
||||
@ -149,7 +149,7 @@ export = {
|
||||
message: "Invalid collection ID or URL format"
|
||||
}
|
||||
}
|
||||
return await getCollection(collectionId, options?.proxy, options?.cursor, options?.count)
|
||||
return await getCollection(collectionId, options?.proxy, options?.page, options?.count)
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@ -49,6 +49,5 @@ export type TiktokCollectionResponse = {
|
||||
}>
|
||||
}>
|
||||
hasMore: boolean
|
||||
cursor: string
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,6 @@ export interface TiktokCollectionResponse {
|
||||
status: "success" | "error"
|
||||
message?: string
|
||||
result?: {
|
||||
cursor: string
|
||||
hasMore: boolean
|
||||
itemList: CollectionItem[]
|
||||
extra?: {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import Axios from "axios"
|
||||
import asyncRetry from "async-retry"
|
||||
import { _tiktokvFeed, _tiktokurl } from "../../constants/api"
|
||||
import { _tiktokvFeed, _tiktokurl, _tiktokGetCollection } from "../../constants/api"
|
||||
import { _tiktokApiParams, _getCollectionParams } from "../../constants/params"
|
||||
import {
|
||||
AuthorTiktokAPI,
|
||||
@ -282,8 +282,9 @@ export const TiktokAPI = async (
|
||||
export const Collection = async (
|
||||
collectionIdOrUrl: string,
|
||||
options?: {
|
||||
cursor?: string
|
||||
proxy?: string
|
||||
page?: number,
|
||||
proxy?: string,
|
||||
count?: number
|
||||
}
|
||||
): Promise<TiktokCollectionResponse> => {
|
||||
try {
|
||||
@ -296,55 +297,31 @@ export const Collection = async (
|
||||
}
|
||||
|
||||
const response = await Axios(
|
||||
_tiktokvFeed(_getCollectionParams(collectionId, options?.cursor)),
|
||||
_tiktokGetCollection(
|
||||
_getCollectionParams(collectionId, options.page, options.count)
|
||||
),
|
||||
{
|
||||
method: "OPTIONS",
|
||||
headers: { "User-Agent": USER_AGENT },
|
||||
method: "GET",
|
||||
headers: {
|
||||
"User-Agent":
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
|
||||
Accept: "*/*",
|
||||
"Accept-Language": "en-US,en;q=0.7",
|
||||
Referer: "https://www.tiktok.com/",
|
||||
Origin: "https://www.tiktok.com"
|
||||
},
|
||||
...createProxyAgent(options?.proxy)
|
||||
}
|
||||
)
|
||||
|
||||
if (response.data && response.data.status_code === 0) {
|
||||
const data = response.data
|
||||
const itemList = data.aweme_list.map((item: any) => ({
|
||||
id: item.aweme_id,
|
||||
desc: item.desc,
|
||||
createTime: item.create_time,
|
||||
author: {
|
||||
uid: item.author.uid,
|
||||
username: item.author.unique_id,
|
||||
uniqueId: item.author.unique_id,
|
||||
nickname: item.author.nickname,
|
||||
signature: item.author.signature,
|
||||
region: item.author.region,
|
||||
avatarThumb: item.author?.avatar_thumb?.url_list || [],
|
||||
avatarMedium: item.author?.avatar_medium?.url_list || [],
|
||||
url: `${_tiktokurl}/@${item.author.unique_id}`
|
||||
},
|
||||
statistics: {
|
||||
likeCount: item.statistics.digg_count,
|
||||
commentCount: item.statistics.comment_count,
|
||||
shareCount: item.statistics.share_count,
|
||||
playCount: item.statistics.play_count
|
||||
},
|
||||
video: {
|
||||
ratio: item.video.ratio,
|
||||
duration: item.video.duration,
|
||||
playAddr: item.video?.play_addr?.url_list || [],
|
||||
downloadAddr: item.video?.download_addr?.url_list || [],
|
||||
cover: item.video?.cover?.url_list || [],
|
||||
dynamicCover: item.video?.dynamic_cover?.url_list || [],
|
||||
originCover: item.video?.origin_cover?.url_list || []
|
||||
},
|
||||
textExtra: item.text_extra || []
|
||||
}))
|
||||
|
||||
return {
|
||||
status: "success",
|
||||
result: {
|
||||
itemList,
|
||||
hasMore: data.has_more,
|
||||
cursor: data.cursor
|
||||
itemList: data.itemList || [],
|
||||
hasMore: data.hasMore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,14 +30,14 @@ const createProxyAgent = (proxy?: string): ProxyConfig => {
|
||||
* Get TikTok Collection
|
||||
* @param {string} collectionId - Collection ID
|
||||
* @param {string} proxy - Your Proxy (optional)
|
||||
* @param {string} cursor - Cursor for pagination (optional)
|
||||
* @param {string} page - Page for pagination (optional)
|
||||
* @param {number} count - Number of items to fetch (optional)
|
||||
* @returns {Promise<TiktokCollectionResponse>}
|
||||
*/
|
||||
export const getCollection = async (
|
||||
collectionId: string,
|
||||
proxy?: string,
|
||||
cursor: string = "0",
|
||||
page: number = 1,
|
||||
count: number = 5
|
||||
): Promise<TiktokCollectionResponse> => {
|
||||
try {
|
||||
@ -45,7 +45,7 @@ export const getCollection = async (
|
||||
async () => {
|
||||
const res = await Axios(
|
||||
_tiktokGetCollection(
|
||||
_getCollectionParams(collectionId, cursor, count)
|
||||
_getCollectionParams(collectionId, page, count)
|
||||
),
|
||||
{
|
||||
method: "GET",
|
||||
@ -77,9 +77,8 @@ export const getCollection = async (
|
||||
return {
|
||||
status: "success",
|
||||
result: {
|
||||
cursor: response.cursor,
|
||||
hasMore: response.hasMore,
|
||||
itemList: response.itemList,
|
||||
itemList: response.itemList || [],
|
||||
extra: response.extra
|
||||
}
|
||||
}
|
||||
|
||||
69
test/collection-test.ts
Normal file
69
test/collection-test.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { Collection } from "../src/utils/downloader/tiktokApi"
|
||||
|
||||
async function testCollection() {
|
||||
try {
|
||||
// You can use either a collection ID or URL
|
||||
const collectionIdOrUrl = "https://www.tiktok.com/@getrex.co.nz/collection/big%20back-7507916135931218695"
|
||||
|
||||
console.log("Testing Collection method...")
|
||||
const result = await Collection(collectionIdOrUrl, {
|
||||
page: 2,
|
||||
count: 5, // Optional: Number of items to fetch
|
||||
proxy: undefined // Optional: Add your proxy if needed
|
||||
})
|
||||
|
||||
if (result.status === "success" && result.result) {
|
||||
console.log("\nCollection fetched successfully!")
|
||||
console.log("========================")
|
||||
console.log("Collection Overview:")
|
||||
console.log("========================")
|
||||
console.log(`Collection ID: ${collectionIdOrUrl}`)
|
||||
console.log(`Total items fetched: ${result.result.itemList.length}`)
|
||||
console.log(`Has more items: ${result.result.hasMore}`)
|
||||
|
||||
// Log all items
|
||||
result.result.itemList.forEach((item, index) => {
|
||||
console.log(`\nItem ${index + 1}:`)
|
||||
console.log("-------------------")
|
||||
console.log(`ID: ${item.id}`)
|
||||
console.log(`Description: ${item.desc}`)
|
||||
console.log(`Author: ${item.author.nickname}`)
|
||||
console.log(`Created: ${new Date(item.createTime * 1000).toLocaleString()}`)
|
||||
|
||||
// Log video URL
|
||||
if (item.video?.playAddr?.[0]) {
|
||||
console.log(`Video URL: ${item.video.playAddr[0]}`)
|
||||
} else {
|
||||
console.log("No video URL available")
|
||||
}
|
||||
|
||||
// Log item statistics
|
||||
if (item.statistics) {
|
||||
console.log("\nStatistics:")
|
||||
console.log(`- Likes: ${item.statistics.likeCount || 0}`)
|
||||
console.log(`- Comments: ${item.statistics.commentCount || 0}`)
|
||||
console.log(`- Shares: ${item.statistics.shareCount || 0}`)
|
||||
console.log(`- Plays: ${item.statistics.playCount || 0}`)
|
||||
}
|
||||
|
||||
// Log hashtags if available
|
||||
if (item.textExtra?.length > 0) {
|
||||
console.log("\nHashtags:")
|
||||
item.textExtra.forEach(tag => {
|
||||
if (tag.hashtagName) {
|
||||
console.log(`- #${tag.hashtagName}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log("========================")
|
||||
})
|
||||
} else {
|
||||
console.error("Error:", result.message)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Test failed:", error)
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test
|
||||
testCollection()
|
||||
@ -1,85 +0,0 @@
|
||||
import Tiktok from "../src"
|
||||
|
||||
async function testCollection() {
|
||||
try {
|
||||
// Test collection ID from your example
|
||||
const collectionId = "7507916135931218695"
|
||||
|
||||
console.log("Fetching collection...")
|
||||
const collection = await Tiktok.Collection(collectionId, {
|
||||
cursor: "0" // Optional: For pagination
|
||||
})
|
||||
|
||||
console.log(collection)
|
||||
|
||||
if (collection.status === "success" && collection.result) {
|
||||
const { itemList, hasMore, cursor } = collection.result
|
||||
|
||||
console.log(`\nFound ${itemList.length} videos in collection`)
|
||||
console.log(`Has more videos: ${hasMore}`)
|
||||
console.log(`Next cursor: ${cursor}\n`)
|
||||
|
||||
// Print details of first video
|
||||
if (itemList.length > 0) {
|
||||
const firstVideo = itemList[0]
|
||||
console.log("First video details:")
|
||||
console.log("-------------------")
|
||||
console.log(`Description: ${firstVideo.desc}`)
|
||||
console.log(`Author: ${firstVideo.author?.nickname || 'Unknown'}`)
|
||||
console.log(
|
||||
`Created: ${new Date(firstVideo.createTime * 1000).toLocaleString()}`
|
||||
)
|
||||
|
||||
// Print statistics if available
|
||||
if (firstVideo.statistics) {
|
||||
console.log("\nStatistics:")
|
||||
console.log(`- Likes: ${firstVideo.statistics.likeCount || 0}`)
|
||||
console.log(`- Comments: ${firstVideo.statistics.commentCount || 0}`)
|
||||
console.log(`- Shares: ${firstVideo.statistics.shareCount || 0}`)
|
||||
console.log(`- Plays: ${firstVideo.statistics.playCount || 0}`)
|
||||
}
|
||||
|
||||
// Print video URLs if available
|
||||
if (firstVideo.video) {
|
||||
console.log("\nVideo URLs:")
|
||||
if (firstVideo.video.playAddr?.[0]) {
|
||||
console.log(`- Play URL: ${firstVideo.video.playAddr[0]}`)
|
||||
}
|
||||
if (firstVideo.video.downloadAddr?.[0]) {
|
||||
console.log(`- Download URL: ${firstVideo.video.downloadAddr[0]}`)
|
||||
}
|
||||
}
|
||||
|
||||
// Print hashtags if available
|
||||
if (firstVideo.textExtra?.length > 0) {
|
||||
console.log("\nHashtags:")
|
||||
firstVideo.textExtra.forEach((tag) => {
|
||||
if (tag.hashtagName) {
|
||||
console.log(`- #${tag.hashtagName}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// If there are more videos, you can fetch the next page
|
||||
if (hasMore) {
|
||||
console.log("\nFetching next page...")
|
||||
const nextPage = await Tiktok.Collection(collectionId, {
|
||||
proxy: "http://your-proxy-url", // Optional: Add your proxy if needed
|
||||
cursor: cursor
|
||||
})
|
||||
|
||||
if (nextPage.status === "success" && nextPage.result) {
|
||||
console.log(`Found ${nextPage.result.itemList.length} more videos`)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error("Error:", collection.message)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Test failed:", error)
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test
|
||||
testCollection()
|
||||
Loading…
x
Reference in New Issue
Block a user