@granitebps/twitter-mcp 1.0.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.
Files changed (55) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +326 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +35 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/config/env.d.ts +22 -0
  7. package/dist/config/env.js +44 -0
  8. package/dist/config/env.js.map +1 -0
  9. package/dist/domain/requests.d.ts +36 -0
  10. package/dist/domain/requests.js +2 -0
  11. package/dist/domain/requests.js.map +1 -0
  12. package/dist/domain/schemas.d.ts +95 -0
  13. package/dist/domain/schemas.js +53 -0
  14. package/dist/domain/schemas.js.map +1 -0
  15. package/dist/errors/twitter-error.d.ts +20 -0
  16. package/dist/errors/twitter-error.js +35 -0
  17. package/dist/errors/twitter-error.js.map +1 -0
  18. package/dist/index.d.ts +12 -0
  19. package/dist/index.js +6 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/providers/api/mapper.d.ts +34 -0
  22. package/dist/providers/api/mapper.js +45 -0
  23. package/dist/providers/api/mapper.js.map +1 -0
  24. package/dist/providers/api/provider.d.ts +44 -0
  25. package/dist/providers/api/provider.js +150 -0
  26. package/dist/providers/api/provider.js.map +1 -0
  27. package/dist/providers/deadline.d.ts +1 -0
  28. package/dist/providers/deadline.js +15 -0
  29. package/dist/providers/deadline.js.map +1 -0
  30. package/dist/providers/factory.d.ts +7 -0
  31. package/dist/providers/factory.js +17 -0
  32. package/dist/providers/factory.js.map +1 -0
  33. package/dist/providers/provider.d.ts +9 -0
  34. package/dist/providers/provider.js +2 -0
  35. package/dist/providers/provider.js.map +1 -0
  36. package/dist/providers/rettiwt/mapper.d.ts +29 -0
  37. package/dist/providers/rettiwt/mapper.js +42 -0
  38. package/dist/providers/rettiwt/mapper.js.map +1 -0
  39. package/dist/providers/rettiwt/provider.d.ts +30 -0
  40. package/dist/providers/rettiwt/provider.js +161 -0
  41. package/dist/providers/rettiwt/provider.js.map +1 -0
  42. package/dist/server/create-server.d.ts +9 -0
  43. package/dist/server/create-server.js +10 -0
  44. package/dist/server/create-server.js.map +1 -0
  45. package/dist/server/input.d.ts +17 -0
  46. package/dist/server/input.js +34 -0
  47. package/dist/server/input.js.map +1 -0
  48. package/dist/server/output.d.ts +8 -0
  49. package/dist/server/output.js +34 -0
  50. package/dist/server/output.js.map +1 -0
  51. package/dist/server/register-tools.d.ts +9 -0
  52. package/dist/server/register-tools.js +106 -0
  53. package/dist/server/register-tools.js.map +1 -0
  54. package/package.json +83 -0
  55. package/server.json +30 -0
@@ -0,0 +1,35 @@
1
+ export class TwitterError extends Error {
2
+ code;
3
+ safeMessage;
4
+ provider;
5
+ retryable;
6
+ retryAfterSeconds;
7
+ constructor(options) {
8
+ super(options.safeMessage, { cause: options.cause });
9
+ this.name = "TwitterError";
10
+ this.code = options.code;
11
+ this.safeMessage = options.safeMessage;
12
+ this.provider = options.provider;
13
+ this.retryable = options.retryable;
14
+ this.retryAfterSeconds = options.retryAfterSeconds;
15
+ }
16
+ }
17
+ const SECRET_PATTERNS = [
18
+ [/\bAuthorization:\s*(?:Bearer\s+)?[^\s,;]+/gi, "Authorization: [REDACTED]"],
19
+ [/\b(auth_token|ct0|RETTIWT_API_KEY)=([^\s,;]+)/gi, "$1=[REDACTED]"],
20
+ ];
21
+ export function redactSecrets(value) {
22
+ return SECRET_PATTERNS.reduce((redacted, [pattern, replacement]) => redacted.replace(pattern, replacement), value);
23
+ }
24
+ export function toTwitterError(error, provider) {
25
+ if (error instanceof TwitterError)
26
+ return error;
27
+ return new TwitterError({
28
+ code: "INTERNAL_ERROR",
29
+ safeMessage: "The X provider returned an unexpected error",
30
+ provider,
31
+ retryable: false,
32
+ cause: error,
33
+ });
34
+ }
35
+ //# sourceMappingURL=twitter-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"twitter-error.js","sourceRoot":"","sources":["../../src/errors/twitter-error.ts"],"names":[],"mappings":"AAsBA,MAAM,OAAO,YAAa,SAAQ,KAAK;IAC5B,IAAI,CAAmB;IACvB,WAAW,CAAS;IACpB,QAAQ,CAAe;IACvB,SAAS,CAAU;IACnB,iBAAiB,CAAqB;IAE/C,YAAY,OAA4B;QACtC,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IACrD,CAAC;CACF;AAED,MAAM,eAAe,GAA4B;IAC/C,CAAC,6CAA6C,EAAE,2BAA2B,CAAC;IAC5E,CAAC,iDAAiD,EAAE,eAAe,CAAC;CACrE,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,eAAe,CAAC,MAAM,CAC3B,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,EAC5E,KAAK,CACN,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAc,EAAE,QAAsB;IACnE,IAAI,KAAK,YAAY,YAAY;QAAE,OAAO,KAAK,CAAC;IAEhD,OAAO,IAAI,YAAY,CAAC;QACtB,IAAI,EAAE,gBAAgB;QACtB,WAAW,EAAE,6CAA6C;QAC1D,QAAQ;QACR,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,KAAK;KACb,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { loadConfig } from "./config/env.js";
2
+ export type { ApiConfig, ApiCredentials, RettiwtConfig, RuntimeConfig } from "./config/env.js";
3
+ export { ProviderWarningSchema, TweetPageSchema, TweetSchema, UserProfileSchema, } from "./domain/schemas.js";
4
+ export type { ProviderWarning, Tweet, TweetPage, UserProfile } from "./domain/schemas.js";
5
+ export type { GetProfileRequest, GetRepliesRequest, GetTweetRequest, ProviderCapabilities, RequestContext, SearchTweetsRequest, } from "./domain/requests.js";
6
+ export { redactSecrets, toTwitterError, TwitterError } from "./errors/twitter-error.js";
7
+ export type { ProviderName, TwitterErrorCode, TwitterErrorOptions, } from "./errors/twitter-error.js";
8
+ export { createProvider } from "./providers/factory.js";
9
+ export type { ProviderLoaders } from "./providers/factory.js";
10
+ export type { TwitterProvider } from "./providers/provider.js";
11
+ export { createTwitterServer } from "./server/create-server.js";
12
+ export type { CreateServerOptions } from "./server/create-server.js";
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { loadConfig } from "./config/env.js";
2
+ export { ProviderWarningSchema, TweetPageSchema, TweetSchema, UserProfileSchema, } from "./domain/schemas.js";
3
+ export { redactSecrets, toTwitterError, TwitterError } from "./errors/twitter-error.js";
4
+ export { createProvider } from "./providers/factory.js";
5
+ export { createTwitterServer } from "./server/create-server.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,WAAW,EACX,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAU7B,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAMxF,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { Tweet, UserProfile } from "../../domain/schemas.js";
2
+ export interface ApiPublicMetricsLike {
3
+ like_count?: number;
4
+ retweet_count?: number;
5
+ reply_count?: number;
6
+ quote_count?: number;
7
+ bookmark_count?: number;
8
+ impression_count?: number;
9
+ followers_count?: number;
10
+ following_count?: number;
11
+ tweet_count?: number;
12
+ listed_count?: number;
13
+ }
14
+ export interface ApiUserLike {
15
+ id: string;
16
+ name: string;
17
+ username: string;
18
+ description?: string;
19
+ created_at?: string;
20
+ verified?: boolean;
21
+ profile_image_url?: string;
22
+ location?: string;
23
+ url?: string;
24
+ public_metrics?: ApiPublicMetricsLike;
25
+ }
26
+ export interface ApiTweetLike {
27
+ id: string;
28
+ text: string;
29
+ created_at?: string;
30
+ author_id?: string;
31
+ public_metrics?: ApiPublicMetricsLike;
32
+ }
33
+ export declare function mapApiTweet(tweet: ApiTweetLike, users?: ReadonlyMap<string, ApiUserLike>): Tweet;
34
+ export declare function mapApiUser(user: ApiUserLike): UserProfile;
@@ -0,0 +1,45 @@
1
+ export function mapApiTweet(tweet, users = new Map()) {
2
+ const author = tweet.author_id ? users.get(tweet.author_id) : undefined;
3
+ const metrics = tweet.public_metrics;
4
+ return {
5
+ id: tweet.id,
6
+ text: tweet.text,
7
+ ...(tweet.created_at ? { created_at: tweet.created_at } : {}),
8
+ author: author
9
+ ? {
10
+ name: author.name,
11
+ username: author.username,
12
+ verified: author.verified ?? false,
13
+ }
14
+ : null,
15
+ metrics: {
16
+ likes: metrics?.like_count ?? 0,
17
+ retweets: metrics?.retweet_count ?? 0,
18
+ replies: metrics?.reply_count ?? 0,
19
+ quotes: metrics?.quote_count ?? 0,
20
+ bookmarks: metrics?.bookmark_count ?? 0,
21
+ ...(metrics?.impression_count === undefined ? {} : { views: metrics.impression_count }),
22
+ },
23
+ };
24
+ }
25
+ export function mapApiUser(user) {
26
+ const metrics = user.public_metrics;
27
+ return {
28
+ id: user.id,
29
+ name: user.name,
30
+ username: user.username,
31
+ ...(user.description ? { description: user.description } : {}),
32
+ ...(user.created_at ? { created_at: user.created_at } : {}),
33
+ verified: user.verified ?? false,
34
+ ...(user.profile_image_url ? { profile_image_url: user.profile_image_url } : {}),
35
+ ...(user.location ? { location: user.location } : {}),
36
+ ...(user.url ? { url: user.url } : {}),
37
+ metrics: {
38
+ followers_count: metrics?.followers_count ?? 0,
39
+ following_count: metrics?.following_count ?? 0,
40
+ tweet_count: metrics?.tweet_count ?? 0,
41
+ listed_count: metrics?.listed_count ?? 0,
42
+ },
43
+ };
44
+ }
45
+ //# sourceMappingURL=mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.js","sourceRoot":"","sources":["../../../src/providers/api/mapper.ts"],"names":[],"mappings":"AAoCA,MAAM,UAAU,WAAW,CACzB,KAAmB,EACnB,QAA0C,IAAI,GAAG,EAAE;IAEnD,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACxE,MAAM,OAAO,GAAG,KAAK,CAAC,cAAc,CAAC;IAErC,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,MAAM,EAAE,MAAM;YACZ,CAAC,CAAC;gBACE,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,KAAK;aACnC;YACH,CAAC,CAAC,IAAI;QACR,OAAO,EAAE;YACP,KAAK,EAAE,OAAO,EAAE,UAAU,IAAI,CAAC;YAC/B,QAAQ,EAAE,OAAO,EAAE,aAAa,IAAI,CAAC;YACrC,OAAO,EAAE,OAAO,EAAE,WAAW,IAAI,CAAC;YAClC,MAAM,EAAE,OAAO,EAAE,WAAW,IAAI,CAAC;YACjC,SAAS,EAAE,OAAO,EAAE,cAAc,IAAI,CAAC;YACvC,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC;SACxF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAiB;IAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC;IACpC,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK;QAChC,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChF,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE;YACP,eAAe,EAAE,OAAO,EAAE,eAAe,IAAI,CAAC;YAC9C,eAAe,EAAE,OAAO,EAAE,eAAe,IAAI,CAAC;YAC9C,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,CAAC;YACtC,YAAY,EAAE,OAAO,EAAE,YAAY,IAAI,CAAC;SACzC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { ApiConfig } from "../../config/env.js";
2
+ import type { Tweet, TweetPage, UserProfile } from "../../domain/schemas.js";
3
+ import type { GetProfileRequest, GetRepliesRequest, GetTweetRequest, ProviderCapabilities, RequestContext, SearchTweetsRequest } from "../../domain/requests.js";
4
+ import type { TwitterProvider } from "../provider.js";
5
+ import { type ApiTweetLike, type ApiUserLike } from "./mapper.js";
6
+ interface ApiTweetResponse {
7
+ data: ApiTweetLike;
8
+ includes?: {
9
+ users?: ApiUserLike[];
10
+ };
11
+ }
12
+ interface ApiSearchResponse {
13
+ data: {
14
+ data?: ApiTweetLike[];
15
+ meta?: {
16
+ next_token?: string;
17
+ };
18
+ };
19
+ includes?: {
20
+ users?: ApiUserLike[];
21
+ };
22
+ }
23
+ interface ApiUserResponse {
24
+ data?: ApiUserLike;
25
+ }
26
+ export interface OfficialApiClient {
27
+ v2: {
28
+ singleTweet(id: string, options: Record<string, unknown>): Promise<ApiTweetResponse>;
29
+ search(query: string, options: Record<string, unknown>): Promise<ApiSearchResponse>;
30
+ userByUsername(username: string, options: Record<string, unknown>): Promise<ApiUserResponse>;
31
+ };
32
+ }
33
+ export declare class OfficialApiProvider implements TwitterProvider {
34
+ private readonly client;
35
+ readonly capabilities: ProviderCapabilities;
36
+ constructor(client: OfficialApiClient);
37
+ static create(config: ApiConfig): OfficialApiProvider;
38
+ getTweet(request: GetTweetRequest, context: RequestContext): Promise<Tweet>;
39
+ getTweetReplies(request: GetRepliesRequest, context: RequestContext): Promise<TweetPage>;
40
+ getUserProfile(request: GetProfileRequest, context: RequestContext): Promise<UserProfile>;
41
+ searchTweets(request: SearchTweetsRequest, context: RequestContext): Promise<TweetPage>;
42
+ private search;
43
+ }
44
+ export {};
@@ -0,0 +1,150 @@
1
+ import { TwitterApi } from "twitter-api-v2";
2
+ import { TwitterError, toTwitterError } from "../../errors/twitter-error.js";
3
+ import { withDeadline } from "../deadline.js";
4
+ import { mapApiTweet, mapApiUser } from "./mapper.js";
5
+ function timeoutError() {
6
+ return new TwitterError({
7
+ code: "TIMEOUT",
8
+ safeMessage: "The official X API request timed out",
9
+ provider: "api",
10
+ retryable: true,
11
+ });
12
+ }
13
+ function mapApiFailure(error) {
14
+ if (error instanceof TwitterError)
15
+ return error;
16
+ const status = typeof error === "object" && error !== null && "code" in error ? Number(error.code) : undefined;
17
+ const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
18
+ if (status === 401 || status === 403) {
19
+ return new TwitterError({
20
+ code: "AUTH_FAILED",
21
+ safeMessage: "Official X API authentication failed",
22
+ provider: "api",
23
+ retryable: false,
24
+ cause: error,
25
+ });
26
+ }
27
+ if (status === 404) {
28
+ return new TwitterError({
29
+ code: "NOT_FOUND",
30
+ safeMessage: "The requested X resource was not found",
31
+ provider: "api",
32
+ retryable: false,
33
+ cause: error,
34
+ });
35
+ }
36
+ if (status === 429) {
37
+ return new TwitterError({
38
+ code: "RATE_LIMITED",
39
+ safeMessage: "Official X API rate limit reached",
40
+ provider: "api",
41
+ retryable: true,
42
+ cause: error,
43
+ });
44
+ }
45
+ if (message.includes("timeout") || message.includes("econnaborted"))
46
+ return timeoutError();
47
+ return toTwitterError(error, "api");
48
+ }
49
+ function userMap(users) {
50
+ return new Map((users ?? []).map((user) => [user.id, user]));
51
+ }
52
+ const TWEET_FIELDS = ["created_at", "public_metrics", "author_id", "conversation_id", "text"];
53
+ const USER_FIELDS = [
54
+ "name",
55
+ "username",
56
+ "description",
57
+ "created_at",
58
+ "verified",
59
+ "profile_image_url",
60
+ "public_metrics",
61
+ "location",
62
+ "url",
63
+ ];
64
+ export class OfficialApiProvider {
65
+ client;
66
+ capabilities = {
67
+ provider: "api",
68
+ authenticated: true,
69
+ operations: {
70
+ getTweet: true,
71
+ getTweetReplies: true,
72
+ getUserProfile: true,
73
+ searchTweets: true,
74
+ },
75
+ pagination: { replies: true, search: true },
76
+ limits: { replies: 100, search: 100 },
77
+ };
78
+ constructor(client) {
79
+ this.client = client;
80
+ }
81
+ static create(config) {
82
+ const credentials = config.credentials;
83
+ const client = credentials.type === "bearer"
84
+ ? new TwitterApi(credentials.token)
85
+ : new TwitterApi({
86
+ appKey: credentials.appKey,
87
+ appSecret: credentials.appSecret,
88
+ accessToken: credentials.accessToken,
89
+ accessSecret: credentials.accessSecret,
90
+ });
91
+ return new OfficialApiProvider(client);
92
+ }
93
+ async getTweet(request, context) {
94
+ try {
95
+ const response = await withDeadline(this.client.v2.singleTweet(request.tweetId, {
96
+ "tweet.fields": TWEET_FIELDS,
97
+ expansions: ["author_id"],
98
+ "user.fields": USER_FIELDS,
99
+ }), context.signal, context.deadline, timeoutError);
100
+ return mapApiTweet(response.data, userMap(response.includes?.users));
101
+ }
102
+ catch (error) {
103
+ throw mapApiFailure(error);
104
+ }
105
+ }
106
+ getTweetReplies(request, context) {
107
+ return this.search(`conversation_id:${request.tweetId} is:reply`, request.maxResults, context);
108
+ }
109
+ async getUserProfile(request, context) {
110
+ try {
111
+ const response = await withDeadline(this.client.v2.userByUsername(request.username, { "user.fields": USER_FIELDS }), context.signal, context.deadline, timeoutError);
112
+ if (!response.data) {
113
+ throw new TwitterError({
114
+ code: "NOT_FOUND",
115
+ safeMessage: `User @${request.username} was not found`,
116
+ provider: "api",
117
+ retryable: false,
118
+ });
119
+ }
120
+ return mapApiUser(response.data);
121
+ }
122
+ catch (error) {
123
+ throw mapApiFailure(error);
124
+ }
125
+ }
126
+ searchTweets(request, context) {
127
+ return this.search(request.query, request.maxResults, context);
128
+ }
129
+ async search(query, maxResults, context) {
130
+ try {
131
+ const response = await withDeadline(this.client.v2.search(query, {
132
+ max_results: Math.max(10, Math.min(maxResults, 100)),
133
+ "tweet.fields": TWEET_FIELDS,
134
+ expansions: ["author_id"],
135
+ "user.fields": USER_FIELDS,
136
+ }), context.signal, context.deadline, timeoutError);
137
+ const users = userMap(response.includes?.users);
138
+ return {
139
+ items: (response.data.data ?? [])
140
+ .slice(0, maxResults)
141
+ .map((tweet) => mapApiTweet(tweet, users)),
142
+ ...(response.data.meta?.next_token ? { nextCursor: response.data.meta.next_token } : {}),
143
+ };
144
+ }
145
+ catch (error) {
146
+ throw mapApiFailure(error);
147
+ }
148
+ }
149
+ }
150
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/providers/api/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function withDeadline<T>(operation: Promise<T>, signal: AbortSignal, deadline: number, createTimeoutError: () => Error): Promise<T>;
@@ -0,0 +1,15 @@
1
+ export function withDeadline(operation, signal, deadline, createTimeoutError) {
2
+ const remaining = deadline - Date.now();
3
+ if (signal.aborted || remaining <= 0)
4
+ throw createTimeoutError();
5
+ return new Promise((resolve, reject) => {
6
+ const timer = setTimeout(() => reject(createTimeoutError()), remaining);
7
+ const abort = () => reject(createTimeoutError());
8
+ signal.addEventListener("abort", abort, { once: true });
9
+ operation.then(resolve, reject).finally(() => {
10
+ clearTimeout(timer);
11
+ signal.removeEventListener("abort", abort);
12
+ });
13
+ });
14
+ }
15
+ //# sourceMappingURL=deadline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deadline.js","sourceRoot":"","sources":["../../src/providers/deadline.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAC1B,SAAqB,EACrB,MAAmB,EACnB,QAAgB,EAChB,kBAA+B;IAE/B,MAAM,SAAS,GAAG,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACxC,IAAI,MAAM,CAAC,OAAO,IAAI,SAAS,IAAI,CAAC;QAAE,MAAM,kBAAkB,EAAE,CAAC;IAEjE,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QACxE,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAExD,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YAC3C,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ApiConfig, RettiwtConfig, RuntimeConfig } from "../config/env.js";
2
+ import type { TwitterProvider } from "./provider.js";
3
+ export interface ProviderLoaders {
4
+ rettiwt(config: RettiwtConfig): Promise<TwitterProvider>;
5
+ api(config: ApiConfig): Promise<TwitterProvider>;
6
+ }
7
+ export declare function createProvider(config: RuntimeConfig, loaders?: ProviderLoaders): Promise<TwitterProvider>;
@@ -0,0 +1,17 @@
1
+ const defaultLoaders = {
2
+ async rettiwt(config) {
3
+ const { RettiwtProvider } = await import("./rettiwt/provider.js");
4
+ return RettiwtProvider.create(config);
5
+ },
6
+ async api(config) {
7
+ const { OfficialApiProvider } = await import("./api/provider.js");
8
+ return OfficialApiProvider.create(config);
9
+ },
10
+ };
11
+ export async function createProvider(config, loaders = defaultLoaders) {
12
+ if (config.mode === "rettiwt") {
13
+ return loaders.rettiwt(config);
14
+ }
15
+ return loaders.api(config);
16
+ }
17
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/providers/factory.ts"],"names":[],"mappings":"AAQA,MAAM,cAAc,GAAoB;IACtC,KAAK,CAAC,OAAO,CAAC,MAAM;QAClB,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAClE,OAAO,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACxC,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,MAAM;QACd,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAClE,OAAO,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAqB,EACrB,UAA2B,cAAc;IAEzC,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { Tweet, TweetPage, UserProfile } from "../domain/schemas.js";
2
+ import type { GetProfileRequest, GetRepliesRequest, GetTweetRequest, ProviderCapabilities, RequestContext, SearchTweetsRequest } from "../domain/requests.js";
3
+ export interface TwitterProvider {
4
+ readonly capabilities: ProviderCapabilities;
5
+ getTweet(request: GetTweetRequest, context: RequestContext): Promise<Tweet>;
6
+ getTweetReplies(request: GetRepliesRequest, context: RequestContext): Promise<TweetPage>;
7
+ getUserProfile(request: GetProfileRequest, context: RequestContext): Promise<UserProfile>;
8
+ searchTweets(request: SearchTweetsRequest, context: RequestContext): Promise<TweetPage>;
9
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/providers/provider.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ import type { Tweet, UserProfile } from "../../domain/schemas.js";
2
+ export interface RettiwtUserLike {
3
+ id?: string;
4
+ fullName: string;
5
+ userName: string;
6
+ createdAt?: string;
7
+ description?: string;
8
+ isVerified: boolean;
9
+ followersCount?: number;
10
+ followingsCount?: number;
11
+ statusesCount?: number;
12
+ likeCount?: number;
13
+ profileImage?: string;
14
+ location?: string;
15
+ }
16
+ export interface RettiwtTweetLike {
17
+ id: string;
18
+ fullText: string;
19
+ createdAt?: string;
20
+ tweetBy?: Pick<RettiwtUserLike, "fullName" | "userName" | "isVerified"> | undefined;
21
+ likeCount?: number;
22
+ retweetCount?: number;
23
+ replyCount?: number;
24
+ quoteCount?: number;
25
+ bookmarkCount?: number;
26
+ viewCount?: number;
27
+ }
28
+ export declare function mapRettiwtTweet(tweet: RettiwtTweetLike): Tweet;
29
+ export declare function mapRettiwtUser(user: RettiwtUserLike): UserProfile;
@@ -0,0 +1,42 @@
1
+ export function mapRettiwtTweet(tweet) {
2
+ return {
3
+ id: tweet.id,
4
+ text: tweet.fullText,
5
+ ...(tweet.createdAt ? { created_at: tweet.createdAt } : {}),
6
+ author: tweet.tweetBy
7
+ ? {
8
+ name: tweet.tweetBy.fullName,
9
+ username: tweet.tweetBy.userName,
10
+ verified: tweet.tweetBy.isVerified,
11
+ }
12
+ : null,
13
+ metrics: {
14
+ likes: tweet.likeCount ?? 0,
15
+ retweets: tweet.retweetCount ?? 0,
16
+ replies: tweet.replyCount ?? 0,
17
+ quotes: tweet.quoteCount ?? 0,
18
+ bookmarks: tweet.bookmarkCount ?? 0,
19
+ views: tweet.viewCount ?? 0,
20
+ },
21
+ };
22
+ }
23
+ export function mapRettiwtUser(user) {
24
+ return {
25
+ id: user.id ?? "",
26
+ name: user.fullName,
27
+ username: user.userName,
28
+ ...(user.description ? { description: user.description } : {}),
29
+ ...(user.createdAt ? { created_at: user.createdAt } : {}),
30
+ verified: user.isVerified,
31
+ ...(user.profileImage ? { profile_image_url: user.profileImage } : {}),
32
+ ...(user.location ? { location: user.location } : {}),
33
+ metrics: {
34
+ followers_count: user.followersCount ?? 0,
35
+ following_count: user.followingsCount ?? 0,
36
+ tweet_count: user.statusesCount ?? 0,
37
+ listed_count: 0,
38
+ likes_count: user.likeCount ?? 0,
39
+ },
40
+ };
41
+ }
42
+ //# sourceMappingURL=mapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.js","sourceRoot":"","sources":["../../../src/providers/rettiwt/mapper.ts"],"names":[],"mappings":"AA8BA,MAAM,UAAU,eAAe,CAAC,KAAuB;IACrD,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,QAAQ;QACpB,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC3D,MAAM,EAAE,KAAK,CAAC,OAAO;YACnB,CAAC,CAAC;gBACE,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ;gBAC5B,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,QAAQ;gBAChC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,UAAU;aACnC;YACH,CAAC,CAAC,IAAI;QACR,OAAO,EAAE;YACP,KAAK,EAAE,KAAK,CAAC,SAAS,IAAI,CAAC;YAC3B,QAAQ,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC;YACjC,OAAO,EAAE,KAAK,CAAC,UAAU,IAAI,CAAC;YAC9B,MAAM,EAAE,KAAK,CAAC,UAAU,IAAI,CAAC;YAC7B,SAAS,EAAE,KAAK,CAAC,aAAa,IAAI,CAAC;YACnC,KAAK,EAAE,KAAK,CAAC,SAAS,IAAI,CAAC;SAC5B;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAqB;IAClD,OAAO;QACL,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;QACjB,IAAI,EAAE,IAAI,CAAC,QAAQ;QACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,QAAQ,EAAE,IAAI,CAAC,UAAU;QACzB,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,OAAO,EAAE;YACP,eAAe,EAAE,IAAI,CAAC,cAAc,IAAI,CAAC;YACzC,eAAe,EAAE,IAAI,CAAC,eAAe,IAAI,CAAC;YAC1C,WAAW,EAAE,IAAI,CAAC,aAAa,IAAI,CAAC;YACpC,YAAY,EAAE,CAAC;YACf,WAAW,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC;SACjC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { RettiwtConfig } from "../../config/env.js";
2
+ import type { Tweet, TweetPage, UserProfile } from "../../domain/schemas.js";
3
+ import type { GetProfileRequest, GetRepliesRequest, GetTweetRequest, ProviderCapabilities, RequestContext, SearchTweetsRequest } from "../../domain/requests.js";
4
+ import type { TwitterProvider } from "../provider.js";
5
+ import { type RettiwtTweetLike, type RettiwtUserLike } from "./mapper.js";
6
+ interface CursoredTweets {
7
+ list: RettiwtTweetLike[];
8
+ next: string;
9
+ }
10
+ export interface RettiwtClient {
11
+ tweet: {
12
+ details(id: string): Promise<RettiwtTweetLike | undefined>;
13
+ replies(id: string): Promise<CursoredTweets>;
14
+ search(filter: Record<string, unknown>, count?: number): Promise<CursoredTweets>;
15
+ };
16
+ user: {
17
+ details(id: string): Promise<RettiwtUserLike | undefined>;
18
+ };
19
+ }
20
+ export declare class RettiwtProvider implements TwitterProvider {
21
+ private readonly client;
22
+ readonly capabilities: ProviderCapabilities;
23
+ constructor(client: RettiwtClient);
24
+ static create(config: RettiwtConfig): RettiwtProvider;
25
+ getTweet(request: GetTweetRequest, context: RequestContext): Promise<Tweet>;
26
+ getTweetReplies(request: GetRepliesRequest, context: RequestContext): Promise<TweetPage>;
27
+ getUserProfile(request: GetProfileRequest, context: RequestContext): Promise<UserProfile>;
28
+ searchTweets(request: SearchTweetsRequest, context: RequestContext): Promise<TweetPage>;
29
+ }
30
+ export {};