x-relay-mcp 1.1.0 → 1.2.0

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.
@@ -100,7 +100,33 @@ xrelay sync bookmarks|posts|all [--handle <you>] [--repair] [--max N]
100
100
  ```
101
101
  - Pulls ONLY tweets newer than the last sync (snowflake-id watermark + newest-first early-break) — never a
102
102
  full refetch. `--repair` refetches everything and patches records; `--max N` caps a run (good for a first
103
- sync). `posts` needs your `--handle` once (it's remembered). Returns `{ source, added, total, watermark }`.
103
+ sync). `posts` auto-detects your handle from the session (override/remember with `--handle`). Returns
104
+ `{ source, added, total, watermark }`.
105
+
106
+ ### More endpoints
107
+
108
+ ```
109
+ xrelay list <list-id> [--limit N] # tweets from a Twitter List (curated sources)
110
+ xrelay user-media <handle> [--limit N] # a user's images/videos only (visual evidence)
111
+ xrelay followers <handle> [--limit N] # a user's followers (network mapping)
112
+ xrelay following <handle> [--limit N] # who a user follows
113
+ xrelay retweeters <id|url> [--limit N] # who retweeted a tweet (amplification graph)
114
+ xrelay likers <id|url> [--limit N] # who liked a tweet (engagement graph)
115
+ xrelay quoters <id|url> [--limit N] # tweets quoting a tweet (reactions; recency-windowed)
116
+ xrelay trends [--woeid N] [--limit N] # what's hot now (woeid 1 = worldwide, default)
117
+ xrelay article <id|url> # a long-form X Article → Markdown
118
+ xrelay media <id|url> [--out <dir>] # a tweet's image/video URLs; --out downloads the files
119
+ ```
120
+
121
+ - **`retweeters`/`followers`/`following`** return `{ users:[<profile>...], nextCursor }` — the
122
+ amplification/audience graph. Use them to answer "who is paying attention to / amplifying X".
123
+ - **`likers`** also returns `{ users }`, but X made likes private in 2024, so it's usually **empty** for
124
+ tweets you don't own (only the like *count* is public — read that from the tweet's `metrics.likes`).
125
+ - **`quoters`** is search-based (`quoted_tweet_id:`), so it's recency-windowed, not the full historical set.
126
+ - **`trends`** is a cheap zoomed-out entry point before drilling into `search`.
127
+ - **`article`** returns `{ id, title, markdown, url }` — the full long-form read for a finalist.
128
+ - **`media`** returns `{ tweetId, media:[{type,url,...}], files? }`; `--out <dir>` saves the actual
129
+ image/video files (for OCR / transcription / multimodal analysis).
104
130
 
105
131
  ---
106
132
 
@@ -84,6 +84,37 @@ type ThreadResult = {
84
84
  nextCursor?: string;
85
85
  };
86
86
  type SearchProduct$1 = 'Top' | 'Latest' | 'Media' | 'People';
87
+ /** A paginated set of users (followers / following / retweeters / likers). */
88
+ type UserPage = {
89
+ users: UserProfile[];
90
+ nextCursor?: string;
91
+ };
92
+ /** A trending topic. */
93
+ type Trend = {
94
+ name: string;
95
+ rank?: number;
96
+ /** Volume blurb as X reports it, e.g. "42.1K posts". */
97
+ volume?: string;
98
+ url?: string;
99
+ };
100
+ /** A downloadable media asset attached to a tweet. */
101
+ type MediaItem = {
102
+ type: MediaKind;
103
+ url: string;
104
+ thumbnail?: string;
105
+ width?: number;
106
+ height?: number;
107
+ durationMs?: number;
108
+ bitrate?: number;
109
+ };
110
+ /** A long-form X Article rendered to Markdown. */
111
+ type Article = {
112
+ id: string;
113
+ title: string;
114
+ markdown: string;
115
+ url: string;
116
+ author?: Author;
117
+ };
87
118
 
88
119
  /** The two load-bearing cookies, plus any others the jar carries. */
89
120
  type Cookies = {
@@ -150,6 +181,22 @@ declare const OPS: {
150
181
  readonly queryId: "7UuJsFvnWuZo0HmxrzU42Q";
151
182
  readonly operationName: "ListLatestTweetsTimeline";
152
183
  };
184
+ readonly Retweeters: {
185
+ readonly queryId: "TZsWuSj7vGmncVnq7KWDUQ";
186
+ readonly operationName: "Retweeters";
187
+ };
188
+ readonly Favoriters: {
189
+ readonly queryId: "LLkw5EcVutJL6y-2gkz22A";
190
+ readonly operationName: "Favoriters";
191
+ };
192
+ readonly GenericTimelineById: {
193
+ readonly queryId: "_dGVIf1cY6xFanFNPsAzPQ";
194
+ readonly operationName: "GenericTimelineById";
195
+ };
196
+ readonly TweetResultByRestId: {
197
+ readonly queryId: "Xl5pC_lBk_gcO2ItU39DQw";
198
+ readonly operationName: "TweetResultByRestId";
199
+ };
153
200
  };
154
201
  type OpName = keyof typeof OPS;
155
202
  type Vars = Record<string, unknown>;
@@ -204,8 +251,21 @@ interface Engine {
204
251
  search(query: string, opts?: SearchOpts): Promise<SearchResult>;
205
252
  user(handle: string): Promise<UserProfile | null>;
206
253
  userTweets(handle: string, opts?: UserTweetsOpts): Promise<TweetPage>;
254
+ userMedia(handle: string, opts?: PageOpts): Promise<TweetPage>;
207
255
  bookmarks(opts?: PageOpts): Promise<TweetPage>;
208
256
  thread(id: string): Promise<ThreadResult>;
257
+ list(listId: string, opts?: PageOpts): Promise<TweetPage>;
258
+ followers(handle: string, opts?: PageOpts): Promise<UserPage>;
259
+ following(handle: string, opts?: PageOpts): Promise<UserPage>;
260
+ retweeters(tweetId: string, opts?: PageOpts): Promise<UserPage>;
261
+ likers(tweetId: string, opts?: PageOpts): Promise<UserPage>;
262
+ quoters(tweetId: string, opts?: SearchOpts): Promise<SearchResult>;
263
+ trends(opts?: {
264
+ woeid?: number;
265
+ limit?: number;
266
+ }): Promise<Trend[]>;
267
+ article(tweetId: string): Promise<Article | null>;
268
+ media(tweetId: string): Promise<MediaItem[]>;
209
269
  /** The authenticated user's own @handle (from the session), or null. Memoized. */
210
270
  me(): Promise<string | null>;
211
271
  }
@@ -233,4 +293,4 @@ declare function parseArgs(argv: string[]): ParsedArgs;
233
293
  declare function dispatch(parsed: ParsedArgs, engine: Engine): Promise<Envelope<unknown>>;
234
294
  declare function run(argv: string[], engine?: Engine): Promise<number>;
235
295
 
236
- export { type Author as A, type Cookies as C, type Err as E, type MediaKind as M, type Ok as O, type PageOpts as P, type SearchProduct as S, type Tweet as T, type UserProfile as U, type Engine as a, type Envelope as b, type TweetPage as c, type SearchResult as d, type ThreadResult as e, type EngineDeps as f, EngineError as g, type Metrics as h, type SearchOpts as i, type SearchProduct$1 as j, type UserTweetsOpts as k, createEngine as l, dispatch as m, parseCookies as n, type ParsedArgs as o, parseArgs as p, run as r };
296
+ export { type Article as A, type Cookies as C, type Err as E, type MediaItem as M, type Ok as O, type PageOpts as P, type SearchResult as S, type Tweet as T, type UserPage as U, type Engine as a, type Envelope as b, type TweetPage as c, type SearchProduct as d, type ThreadResult as e, type Trend as f, type UserProfile as g, type Author as h, type EngineDeps as i, EngineError as j, type MediaKind as k, type Metrics as l, type SearchOpts as m, type SearchProduct$1 as n, type UserTweetsOpts as o, createEngine as p, dispatch as q, parseArgs as r, parseCookies as s, run as t, type ParsedArgs as u };
package/dist/cli.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export { o as ParsedArgs, m as dispatch, p as parseArgs, r as run } from './cli-DO7p1WNQ.js';
2
+ export { u as ParsedArgs, q as dispatch, r as parseArgs, t as run } from './cli-B4ohNfa7.js';