From 436d4dfb89c09259b03bb3effd03ca649261a7ee Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 12 Jan 2026 02:09:47 +0000 Subject: [PATCH] refactor: centralize paged tweet printing --- src/cli/shared.ts | 24 ++++++++++++++++++++++++ src/commands/bookmarks.ts | 6 +----- src/commands/lists.ts | 10 +++++----- src/commands/user-tweets.ts | 14 +++++--------- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/cli/shared.ts b/src/cli/shared.ts index 3f6bc3d..0e2cd56 100644 --- a/src/cli/shared.ts +++ b/src/cli/shared.ts @@ -51,6 +51,17 @@ export type CliContext = { resolveCredentialsFromOptions: (opts: CredentialsOptions) => ReturnType; loadMedia: (opts: { media: string[]; alts: string[] }) => MediaSpec[]; printTweets: (tweets: TweetData[], opts?: { json?: boolean; emptyMessage?: string; showSeparator?: boolean }) => void; + printTweetsResult: ( + result: { + tweets?: TweetData[]; + nextCursor?: string; + }, + opts: { + json: boolean; + usePagination: boolean; + emptyMessage: string; + }, + ) => void; extractTweetId: (tweetIdOrUrl: string) => string; }; @@ -389,6 +400,18 @@ export function createCliContext(normalizedArgs: string[], env: NodeJS.ProcessEn } } + function printTweetsResult( + result: { tweets?: TweetData[]; nextCursor?: string }, + opts: { json: boolean; usePagination: boolean; emptyMessage: string }, + ) { + const tweets = result.tweets ?? []; + if (opts.json && opts.usePagination) { + console.log(JSON.stringify({ tweets, nextCursor: result.nextCursor ?? null }, null, 2)); + return; + } + printTweets(tweets, { json: opts.json, emptyMessage: opts.emptyMessage }); + } + return { isTty, getOutput: () => output, @@ -402,6 +425,7 @@ export function createCliContext(normalizedArgs: string[], env: NodeJS.ProcessEn resolveCredentialsFromOptions, loadMedia, printTweets, + printTweetsResult, extractTweetId, }; } diff --git a/src/commands/bookmarks.ts b/src/commands/bookmarks.ts index ab55e27..89a8ed3 100644 --- a/src/commands/bookmarks.ts +++ b/src/commands/bookmarks.ts @@ -74,11 +74,7 @@ export function registerBookmarksCommand(program: Command, ctx: CliContext): voi if (result.success && result.tweets) { const emptyMessage = folderId ? 'No bookmarks found in folder.' : 'No bookmarks found.'; 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 }); - } + ctx.printTweetsResult(result, { json: isJson, usePagination, emptyMessage }); } else { console.error(`${ctx.p('err')}Failed to fetch bookmarks: ${result.error}`); process.exit(1); diff --git a/src/commands/lists.ts b/src/commands/lists.ts index 3fe7d45..8aef7d9 100644 --- a/src/commands/lists.ts +++ b/src/commands/lists.ts @@ -139,11 +139,11 @@ export function registerListsCommand(program: Command, ctx: CliContext): void { 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 tweets found in this list.' }); - } + ctx.printTweetsResult(result, { + json: isJson, + usePagination, + emptyMessage: 'No tweets found in this list.', + }); } else { console.error(`${ctx.p('err')}Failed to fetch list timeline: ${result.error}`); process.exit(1); diff --git a/src/commands/user-tweets.ts b/src/commands/user-tweets.ts index 72906f8..52aa6d7 100644 --- a/src/commands/user-tweets.ts +++ b/src/commands/user-tweets.ts @@ -115,15 +115,11 @@ export function registerUserTweetsCommand(program: Command, ctx: CliContext): vo if (result.success && result.tweets) { const isJson = cmdOpts.json || cmdOpts.jsonFull; - if (isJson && wantsPaginationOutput) { - // Include nextCursor for pagination consumers - console.log(JSON.stringify({ tweets: result.tweets, nextCursor: result.nextCursor ?? null }, null, 2)); - } else { - ctx.printTweets(result.tweets, { - json: isJson, - emptyMessage: `No tweets found for @${username}.`, - }); - } + ctx.printTweetsResult(result, { + json: isJson, + usePagination: wantsPaginationOutput, + emptyMessage: `No tweets found for @${username}.`, + }); // Show pagination hint if there's more if (result.nextCursor && !cmdOpts.json && !cmdOpts.jsonFull) {