refactor: align replies/thread pagination (#35) (thanks @crcatala)
This commit is contained in:
+24
-33
@@ -50,8 +50,8 @@ export function registerReadCommands(program: Command, ctx: CliContext): void {
|
||||
.description('List replies to a tweet (by ID or URL)')
|
||||
.argument('<tweet-id-or-url>', 'Tweet ID or URL')
|
||||
.option('--all', 'Fetch all replies (paged)')
|
||||
.option('--max-pages <number>', 'Stop after N pages when using --all')
|
||||
.option('--delay <ms>', 'Delay in ms between page fetches (default: 1000)')
|
||||
.option('--max-pages <number>', 'Fetch N pages (implies pagination)')
|
||||
.option('--delay <ms>', 'Delay in ms between page fetches', '1000')
|
||||
.option('--cursor <string>', 'Resume pagination from a cursor')
|
||||
.option('--json', 'Output as JSON')
|
||||
.option('--json-full', 'Output as JSON with full raw API response in _raw field')
|
||||
@@ -72,13 +72,9 @@ export function registerReadCommands(program: Command, ctx: CliContext): void {
|
||||
const quoteDepth = ctx.resolveQuoteDepthFromOptions(opts);
|
||||
const tweetId = ctx.extractTweetId(tweetIdOrUrl);
|
||||
const maxPages = cmdOpts.maxPages ? Number.parseInt(cmdOpts.maxPages, 10) : undefined;
|
||||
const pageDelayMs = cmdOpts.delay ? Number.parseInt(cmdOpts.delay, 10) : 1000;
|
||||
const pageDelayMs = Number.parseInt(cmdOpts.delay || '1000', 10);
|
||||
|
||||
const usePagination = cmdOpts.all || cmdOpts.cursor;
|
||||
if (maxPages !== undefined && !usePagination) {
|
||||
console.error(`${ctx.p('err')}--max-pages requires --all or --cursor.`);
|
||||
process.exit(1);
|
||||
}
|
||||
const usePagination = Boolean(cmdOpts.all || cmdOpts.cursor || maxPages !== undefined);
|
||||
if (maxPages !== undefined && (!Number.isFinite(maxPages) || maxPages <= 0)) {
|
||||
console.error(`${ctx.p('err')}Invalid --max-pages. Expected a positive integer.`);
|
||||
process.exit(1);
|
||||
@@ -111,18 +107,19 @@ export function registerReadCommands(program: Command, ctx: CliContext): void {
|
||||
})
|
||||
: await client.getReplies(tweetId, { includeRaw });
|
||||
|
||||
if (result.success && result.tweets) {
|
||||
const isJson = cmdOpts.json || cmdOpts.jsonFull;
|
||||
if (isJson && usePagination) {
|
||||
console.log(JSON.stringify({ tweets: result.tweets, nextCursor: result.nextCursor ?? null }, null, 2));
|
||||
} else {
|
||||
ctx.printTweets(result.tweets, { json: isJson, emptyMessage: 'No replies found.' });
|
||||
}
|
||||
if (result.tweets) {
|
||||
const isJson = Boolean(cmdOpts.json || cmdOpts.jsonFull);
|
||||
ctx.printTweetsResult(result, { json: isJson, usePagination, emptyMessage: 'No replies found.' });
|
||||
|
||||
// Show pagination hint if there's more
|
||||
if (result.nextCursor && !isJson) {
|
||||
console.error(`${ctx.p('info')}More replies available. Use --cursor "${result.nextCursor}" to continue.`);
|
||||
}
|
||||
|
||||
if (!result.success) {
|
||||
console.error(`${ctx.p('err')}Failed to fetch replies: ${result.error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
console.error(`${ctx.p('err')}Failed to fetch replies: ${result.error}`);
|
||||
process.exit(1);
|
||||
@@ -135,8 +132,8 @@ export function registerReadCommands(program: Command, ctx: CliContext): void {
|
||||
.description('Show the full conversation thread containing the tweet')
|
||||
.argument('<tweet-id-or-url>', 'Tweet ID or URL')
|
||||
.option('--all', 'Fetch all thread tweets (paged)')
|
||||
.option('--max-pages <number>', 'Stop after N pages when using --all')
|
||||
.option('--delay <ms>', 'Delay in ms between page fetches (default: 1000)')
|
||||
.option('--max-pages <number>', 'Fetch N pages (implies pagination)')
|
||||
.option('--delay <ms>', 'Delay in ms between page fetches', '1000')
|
||||
.option('--cursor <string>', 'Resume pagination from a cursor')
|
||||
.option('--json', 'Output as JSON')
|
||||
.option('--json-full', 'Output as JSON with full raw API response in _raw field')
|
||||
@@ -157,13 +154,9 @@ export function registerReadCommands(program: Command, ctx: CliContext): void {
|
||||
const quoteDepth = ctx.resolveQuoteDepthFromOptions(opts);
|
||||
const tweetId = ctx.extractTweetId(tweetIdOrUrl);
|
||||
const maxPages = cmdOpts.maxPages ? Number.parseInt(cmdOpts.maxPages, 10) : undefined;
|
||||
const pageDelayMs = cmdOpts.delay ? Number.parseInt(cmdOpts.delay, 10) : 1000;
|
||||
const pageDelayMs = Number.parseInt(cmdOpts.delay || '1000', 10);
|
||||
|
||||
const usePagination = cmdOpts.all || cmdOpts.cursor;
|
||||
if (maxPages !== undefined && !usePagination) {
|
||||
console.error(`${ctx.p('err')}--max-pages requires --all or --cursor.`);
|
||||
process.exit(1);
|
||||
}
|
||||
const usePagination = Boolean(cmdOpts.all || cmdOpts.cursor || maxPages !== undefined);
|
||||
if (maxPages !== undefined && (!Number.isFinite(maxPages) || maxPages <= 0)) {
|
||||
console.error(`${ctx.p('err')}Invalid --max-pages. Expected a positive integer.`);
|
||||
process.exit(1);
|
||||
@@ -196,16 +189,9 @@ export function registerReadCommands(program: Command, ctx: CliContext): void {
|
||||
})
|
||||
: await client.getThread(tweetId, { includeRaw });
|
||||
|
||||
if (result.success && result.tweets) {
|
||||
const isJson = cmdOpts.json || cmdOpts.jsonFull;
|
||||
if (isJson && usePagination) {
|
||||
console.log(JSON.stringify({ tweets: result.tweets, nextCursor: result.nextCursor ?? null }, null, 2));
|
||||
} else {
|
||||
ctx.printTweets(result.tweets, {
|
||||
json: isJson,
|
||||
emptyMessage: 'No thread tweets found.',
|
||||
});
|
||||
}
|
||||
if (result.tweets) {
|
||||
const isJson = Boolean(cmdOpts.json || cmdOpts.jsonFull);
|
||||
ctx.printTweetsResult(result, { json: isJson, usePagination, emptyMessage: 'No thread tweets found.' });
|
||||
|
||||
// Show pagination hint if there's more
|
||||
if (result.nextCursor && !isJson) {
|
||||
@@ -213,6 +199,11 @@ export function registerReadCommands(program: Command, ctx: CliContext): void {
|
||||
`${ctx.p('info')}More thread tweets available. Use --cursor "${result.nextCursor}" to continue.`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!result.success) {
|
||||
console.error(`${ctx.p('err')}Failed to fetch thread: ${result.error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
console.error(`${ctx.p('err')}Failed to fetch thread: ${result.error}`);
|
||||
process.exit(1);
|
||||
|
||||
@@ -383,7 +383,7 @@ export function withTweetDetails<TBase extends AbstractConstructor<TwitterClient
|
||||
if (!response.success) {
|
||||
// If we have some replies already, return them with the error
|
||||
if (allReplies.length > 0) {
|
||||
return { success: true, tweets: allReplies, nextCursor: cursor, error: response.error };
|
||||
return { success: false, tweets: allReplies, nextCursor: cursor, error: response.error };
|
||||
}
|
||||
return response;
|
||||
}
|
||||
@@ -402,7 +402,7 @@ export function withTweetDetails<TBase extends AbstractConstructor<TwitterClient
|
||||
}
|
||||
|
||||
const pageCursor = extractCursorFromInstructions(instructions);
|
||||
if (!pageCursor || pageCursor === cursor || replies.length === 0) {
|
||||
if (!pageCursor || pageCursor === cursor) {
|
||||
nextCursor = undefined;
|
||||
break;
|
||||
}
|
||||
@@ -441,7 +441,7 @@ export function withTweetDetails<TBase extends AbstractConstructor<TwitterClient
|
||||
if (!response.success) {
|
||||
// If we have some tweets already, return them with the error
|
||||
if (allTweets.length > 0) {
|
||||
return { success: true, tweets: allTweets, nextCursor: cursor, error: response.error };
|
||||
return { success: false, tweets: allTweets, nextCursor: cursor, error: response.error };
|
||||
}
|
||||
return response;
|
||||
}
|
||||
@@ -467,7 +467,7 @@ export function withTweetDetails<TBase extends AbstractConstructor<TwitterClient
|
||||
}
|
||||
|
||||
const pageCursor = extractCursorFromInstructions(instructions);
|
||||
if (!pageCursor || pageCursor === cursor || threadTweets.length === 0) {
|
||||
if (!pageCursor || pageCursor === cursor) {
|
||||
nextCursor = undefined;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user