Add native quote tweet support to TweetData

- Add quoted_status_result to GraphqlTweetResult type
- Add quotedTweet field to TweetData interface
- Extract and map quoted tweets in mapTweetResult()
- Works for getTweet, getBookmarks, search, etc.
- Document JSON output schema in README

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
Alex Hillman
2025-12-31 21:58:48 +00:00
co-authored by Claude Opus 4.5
parent 9c553e46bf
commit c90d3f9ab4
2 changed files with 54 additions and 0 deletions
+18
View File
@@ -121,6 +121,24 @@ Environment shortcuts:
- `read` returns full text for Notes and Articles when present. - `read` returns full text for Notes and Articles when present.
- Use `--plain` for stable, script-friendly output (no emoji, no color). - Use `--plain` for stable, script-friendly output (no emoji, no color).
### JSON Schema
When using `--json`, tweet objects include:
| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Tweet ID |
| `text` | string | Full tweet text (includes Note/Article content when present) |
| `author` | object | `{ username, name }` |
| `authorId` | string | Author's user ID |
| `createdAt` | string | Timestamp |
| `replyCount` | number | Number of replies |
| `retweetCount` | number | Number of retweets |
| `likeCount` | number | Number of likes |
| `conversationId` | string | Thread conversation ID |
| `inReplyToStatusId` | string? | Parent tweet ID (present if this is a reply) |
| `quotedTweet` | object? | Embedded quote tweet with `{ id, text, author, authorId }` (present if this is a quote tweet) |
## Query IDs (GraphQL) ## Query IDs (GraphQL)
X rotates GraphQL “query IDs” frequently. Each GraphQL operation is addressed as: X rotates GraphQL “query IDs” frequently. Each GraphQL operation is addressed as:
+36
View File
@@ -180,6 +180,9 @@ type GraphqlTweetResult = {
}>; }>;
}>; }>;
}; };
quoted_status_result?: {
result?: GraphqlTweetResult;
};
}; };
export type TweetResult = export type TweetResult =
@@ -212,6 +215,15 @@ export interface TweetData {
likeCount?: number; likeCount?: number;
conversationId?: string; conversationId?: string;
inReplyToStatusId?: string; inReplyToStatusId?: string;
quotedTweet?: {
id: string;
text: string;
author: {
username: string;
name: string;
};
authorId?: string;
};
} }
export interface GetTweetResult { export interface GetTweetResult {
@@ -686,6 +698,29 @@ export class TwitterClient {
const text = this.extractTweetText(result); const text = this.extractTweetText(result);
if (!text) return undefined; if (!text) return undefined;
// Extract quoted tweet if present
let quotedTweet: TweetData['quotedTweet'] = undefined;
const quotedResult = result.quoted_status_result?.result;
if (quotedResult?.rest_id) {
const quotedUserResult = quotedResult?.core?.user_results?.result;
const quotedUserLegacy = quotedUserResult?.legacy;
const quotedUserCore = quotedUserResult?.core;
const quotedUsername = quotedUserLegacy?.screen_name ?? quotedUserCore?.screen_name;
const quotedName = quotedUserLegacy?.name ?? quotedUserCore?.name ?? quotedUsername;
const quotedText = this.extractTweetText(quotedResult);
if (quotedUsername && quotedText) {
quotedTweet = {
id: quotedResult.rest_id,
text: quotedText,
author: {
username: quotedUsername,
name: quotedName || quotedUsername,
},
authorId: quotedUserResult?.rest_id,
};
}
}
return { return {
id: result.rest_id, id: result.rest_id,
text, text,
@@ -700,6 +735,7 @@ export class TwitterClient {
name: name || username, name: name || username,
}, },
authorId: userId, authorId: userId,
quotedTweet,
}; };
} }