@apitwitter/sdk 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.
- package/README.md +148 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.js +48 -0
- package/dist/index.d.ts +90 -0
- package/dist/index.js +291 -0
- package/package.json +26 -0
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# ApiTwitter JavaScript/TypeScript SDK
|
|
2
|
+
|
|
3
|
+
Official SDK for the [ApiTwitter](https://apitwitter.com) REST API — access Twitter/X data without the official developer portal.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install apitwitter
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { ApiTwitter } from "apitwitter";
|
|
15
|
+
|
|
16
|
+
const client = new ApiTwitter("your-api-key");
|
|
17
|
+
|
|
18
|
+
// Get user profile (uses server pool — no cookies needed)
|
|
19
|
+
const user = await client.getUser("elonmusk");
|
|
20
|
+
console.log(user.name, user.followers);
|
|
21
|
+
|
|
22
|
+
// Search tweets
|
|
23
|
+
const results = await client.search("javascript", "Top", 10);
|
|
24
|
+
results.tweets.forEach((tweet) => console.log(tweet.text));
|
|
25
|
+
|
|
26
|
+
// Get user tweets
|
|
27
|
+
const tweets = await client.getUserTweets("elonmusk");
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Read Operations (Server Pool)
|
|
31
|
+
|
|
32
|
+
No cookies or proxy needed:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
const client = new ApiTwitter("your-api-key");
|
|
36
|
+
|
|
37
|
+
// Users
|
|
38
|
+
const user = await client.getUser("username");
|
|
39
|
+
const userById = await client.getUserById("12345");
|
|
40
|
+
const users = await client.getUsersBatch(["id1", "id2"]);
|
|
41
|
+
const followers = await client.getFollowers("username", 100);
|
|
42
|
+
const following = await client.getFollowing("username", 100);
|
|
43
|
+
|
|
44
|
+
// Tweets
|
|
45
|
+
const tweets = await client.getUserTweets("username");
|
|
46
|
+
const tweetsById = await client.getTweets(["id1", "id2"]);
|
|
47
|
+
|
|
48
|
+
// Search (product: "Top" | "Latest" | "People" | "Photos" | "Videos")
|
|
49
|
+
const results = await client.search("query", "Top", 20);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Write Operations (Own Credentials)
|
|
53
|
+
|
|
54
|
+
Requires your own Twitter cookies and proxy:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
const creds = {
|
|
58
|
+
cookie: "ct0=...;auth_token=...",
|
|
59
|
+
proxy: "http://user:pass@host:port",
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Tweet
|
|
63
|
+
await client.createTweet("Hello from ApiTwitter!", creds);
|
|
64
|
+
|
|
65
|
+
// Like / unlike
|
|
66
|
+
await client.like("tweet_id", creds);
|
|
67
|
+
await client.unlike("tweet_id", creds);
|
|
68
|
+
|
|
69
|
+
// Retweet
|
|
70
|
+
await client.retweet("tweet_id", creds);
|
|
71
|
+
|
|
72
|
+
// Follow / unfollow
|
|
73
|
+
await client.follow("user_id", creds);
|
|
74
|
+
await client.unfollow("user_id", creds);
|
|
75
|
+
|
|
76
|
+
// DM
|
|
77
|
+
await client.sendDm("user_id", "Hello!", creds);
|
|
78
|
+
|
|
79
|
+
// Bookmarks
|
|
80
|
+
await client.addBookmark("tweet_id", creds);
|
|
81
|
+
const bookmarks = await client.getBookmarks(creds);
|
|
82
|
+
|
|
83
|
+
// Timeline
|
|
84
|
+
const foryou = await client.getTimelineForYou(creds, 20);
|
|
85
|
+
const latest = await client.getTimelineLatest(creds, 20);
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Pagination
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
let result = await client.getFollowers("username", 100);
|
|
92
|
+
let allFollowers = [...result.followers];
|
|
93
|
+
|
|
94
|
+
while (result.next_cursor) {
|
|
95
|
+
result = await client.getFollowers("username", 100, result.next_cursor);
|
|
96
|
+
allFollowers.push(...result.followers);
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Error Handling
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
import {
|
|
104
|
+
ApiTwitter,
|
|
105
|
+
AuthenticationError,
|
|
106
|
+
InsufficientCreditsError,
|
|
107
|
+
RateLimitError,
|
|
108
|
+
NotFoundError,
|
|
109
|
+
} from "apitwitter";
|
|
110
|
+
|
|
111
|
+
const client = new ApiTwitter("your-api-key");
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const user = await client.getUser("username");
|
|
115
|
+
} catch (err) {
|
|
116
|
+
if (err instanceof AuthenticationError) {
|
|
117
|
+
console.log("Invalid API key");
|
|
118
|
+
} else if (err instanceof InsufficientCreditsError) {
|
|
119
|
+
console.log("Top up your balance");
|
|
120
|
+
} else if (err instanceof RateLimitError) {
|
|
121
|
+
console.log(`Rate limited, retry after ${err.retryAfter}s`);
|
|
122
|
+
} else if (err instanceof NotFoundError) {
|
|
123
|
+
console.log("User not found");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Configuration
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// Simple
|
|
132
|
+
const client = new ApiTwitter("your-api-key");
|
|
133
|
+
|
|
134
|
+
// With options
|
|
135
|
+
const client = new ApiTwitter({
|
|
136
|
+
apiKey: "your-api-key",
|
|
137
|
+
baseUrl: "https://api.apitwitter.com", // default
|
|
138
|
+
timeout: 30, // seconds
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Links
|
|
143
|
+
|
|
144
|
+
- [Documentation](https://docs.apitwitter.com)
|
|
145
|
+
- [API Reference](https://docs.apitwitter.com/api-reference)
|
|
146
|
+
- [Website](https://apitwitter.com)
|
|
147
|
+
- [Get API Key](https://apitwitter.com/dashboard)
|
|
148
|
+
- [Telegram Support](https://t.me/ApiTwitter)
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class ApiTwitterError extends Error {
|
|
2
|
+
status: number;
|
|
3
|
+
response: Record<string, unknown>;
|
|
4
|
+
constructor(message: string, status?: number, response?: Record<string, unknown>);
|
|
5
|
+
}
|
|
6
|
+
export declare class AuthenticationError extends ApiTwitterError {
|
|
7
|
+
constructor(message: string, response?: Record<string, unknown>);
|
|
8
|
+
}
|
|
9
|
+
export declare class InsufficientCreditsError extends ApiTwitterError {
|
|
10
|
+
constructor(message: string, response?: Record<string, unknown>);
|
|
11
|
+
}
|
|
12
|
+
export declare class RateLimitError extends ApiTwitterError {
|
|
13
|
+
retryAfter: number;
|
|
14
|
+
constructor(message: string, retryAfter?: number, response?: Record<string, unknown>);
|
|
15
|
+
}
|
|
16
|
+
export declare class NotFoundError extends ApiTwitterError {
|
|
17
|
+
constructor(message: string, response?: Record<string, unknown>);
|
|
18
|
+
}
|
|
19
|
+
export declare class ValidationError extends ApiTwitterError {
|
|
20
|
+
constructor(message: string, response?: Record<string, unknown>);
|
|
21
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ValidationError = exports.NotFoundError = exports.RateLimitError = exports.InsufficientCreditsError = exports.AuthenticationError = exports.ApiTwitterError = void 0;
|
|
4
|
+
class ApiTwitterError extends Error {
|
|
5
|
+
constructor(message, status = 0, response = {}) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "ApiTwitterError";
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.response = response;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.ApiTwitterError = ApiTwitterError;
|
|
13
|
+
class AuthenticationError extends ApiTwitterError {
|
|
14
|
+
constructor(message, response) {
|
|
15
|
+
super(message, 401, response);
|
|
16
|
+
this.name = "AuthenticationError";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.AuthenticationError = AuthenticationError;
|
|
20
|
+
class InsufficientCreditsError extends ApiTwitterError {
|
|
21
|
+
constructor(message, response) {
|
|
22
|
+
super(message, 402, response);
|
|
23
|
+
this.name = "InsufficientCreditsError";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.InsufficientCreditsError = InsufficientCreditsError;
|
|
27
|
+
class RateLimitError extends ApiTwitterError {
|
|
28
|
+
constructor(message, retryAfter = 0, response) {
|
|
29
|
+
super(message, 429, response);
|
|
30
|
+
this.name = "RateLimitError";
|
|
31
|
+
this.retryAfter = retryAfter;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.RateLimitError = RateLimitError;
|
|
35
|
+
class NotFoundError extends ApiTwitterError {
|
|
36
|
+
constructor(message, response) {
|
|
37
|
+
super(message, 404, response);
|
|
38
|
+
this.name = "NotFoundError";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.NotFoundError = NotFoundError;
|
|
42
|
+
class ValidationError extends ApiTwitterError {
|
|
43
|
+
constructor(message, response) {
|
|
44
|
+
super(message, 400, response);
|
|
45
|
+
this.name = "ValidationError";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.ValidationError = ValidationError;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { ApiTwitterError, AuthenticationError, InsufficientCreditsError, RateLimitError, NotFoundError, ValidationError } from "./errors";
|
|
2
|
+
export { ApiTwitterError, AuthenticationError, InsufficientCreditsError, RateLimitError, NotFoundError, ValidationError, };
|
|
3
|
+
interface ClientOptions {
|
|
4
|
+
apiKey: string;
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
timeout?: number;
|
|
7
|
+
}
|
|
8
|
+
interface Credentials {
|
|
9
|
+
cookie: string;
|
|
10
|
+
proxy: string;
|
|
11
|
+
userAgent?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare class ApiTwitter {
|
|
14
|
+
private apiKey;
|
|
15
|
+
private baseUrl;
|
|
16
|
+
private timeout;
|
|
17
|
+
constructor(options: ClientOptions | string);
|
|
18
|
+
private request;
|
|
19
|
+
private get;
|
|
20
|
+
private post;
|
|
21
|
+
private del;
|
|
22
|
+
private patch;
|
|
23
|
+
private creds;
|
|
24
|
+
verifySession(creds: Credentials): Promise<unknown>;
|
|
25
|
+
getUser(username: string): Promise<unknown>;
|
|
26
|
+
getUserById(userId: string): Promise<unknown>;
|
|
27
|
+
getUsersBatch(userIds: string[]): Promise<unknown>;
|
|
28
|
+
getFollowers(username: string, count?: number, cursor?: string): Promise<unknown>;
|
|
29
|
+
getFollowing(username: string, count?: number, cursor?: string): Promise<unknown>;
|
|
30
|
+
getFollowersYouKnow(username: string, count?: number, cursor?: string): Promise<unknown>;
|
|
31
|
+
getUserPost(username: string, creds: Credentials): Promise<unknown>;
|
|
32
|
+
getUserLikes(username: string, creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
33
|
+
getUserMedia(username: string, creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
34
|
+
getUserReplies(username: string, creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
35
|
+
getBlocked(creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
36
|
+
getMuted(creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
37
|
+
removeFollower(userId: string, creds: Credentials): Promise<unknown>;
|
|
38
|
+
getUserTweets(username: string, cursor?: string): Promise<unknown>;
|
|
39
|
+
getTweets(tweetIds: string[]): Promise<unknown>;
|
|
40
|
+
search(query: string, product?: string, count?: number, cursor?: string): Promise<unknown>;
|
|
41
|
+
createTweet(text: string, creds: Credentials, replyTo?: string): Promise<unknown>;
|
|
42
|
+
deleteTweet(tweetId: string, creds: Credentials): Promise<unknown>;
|
|
43
|
+
retweet(tweetId: string, creds: Credentials): Promise<unknown>;
|
|
44
|
+
unretweet(tweetId: string, creds: Credentials): Promise<unknown>;
|
|
45
|
+
pinTweet(tweetId: string, creds: Credentials): Promise<unknown>;
|
|
46
|
+
unpinTweet(tweetId: string, creds: Credentials): Promise<unknown>;
|
|
47
|
+
like(tweetId: string, creds: Credentials): Promise<unknown>;
|
|
48
|
+
unlike(tweetId: string, creds: Credentials): Promise<unknown>;
|
|
49
|
+
follow(userId: string, creds: Credentials): Promise<unknown>;
|
|
50
|
+
unfollow(userId: string, creds: Credentials): Promise<unknown>;
|
|
51
|
+
sendDm(userId: string, text: string, creds: Credentials): Promise<unknown>;
|
|
52
|
+
dmBlock(userId: string, creds: Credentials): Promise<unknown>;
|
|
53
|
+
dmUnblock(userId: string, creds: Credentials): Promise<unknown>;
|
|
54
|
+
addBookmark(tweetId: string, creds: Credentials): Promise<unknown>;
|
|
55
|
+
removeBookmark(tweetId: string, creds: Credentials): Promise<unknown>;
|
|
56
|
+
getBookmarks(creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
57
|
+
getTimelineForYou(creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
58
|
+
getTimelineLatest(creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
59
|
+
searchPost(query: string, creds: Credentials, product?: string, count?: number, cursor?: string): Promise<unknown>;
|
|
60
|
+
createList(name: string, creds: Credentials, options?: {
|
|
61
|
+
description?: string;
|
|
62
|
+
isPrivate?: boolean;
|
|
63
|
+
}): Promise<unknown>;
|
|
64
|
+
deleteList(listId: string, creds: Credentials): Promise<unknown>;
|
|
65
|
+
updateList(listId: string, creds: Credentials, updates: {
|
|
66
|
+
name?: string;
|
|
67
|
+
description?: string;
|
|
68
|
+
isPrivate?: boolean;
|
|
69
|
+
}): Promise<unknown>;
|
|
70
|
+
getListInfo(listId: string, creds: Credentials): Promise<unknown>;
|
|
71
|
+
getListTweets(listId: string, creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
72
|
+
getListMembers(listId: string, creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
73
|
+
addListMember(listId: string, userId: string, creds: Credentials): Promise<unknown>;
|
|
74
|
+
removeListMember(listId: string, userId: string, creds: Credentials): Promise<unknown>;
|
|
75
|
+
getOwnedLists(userId: string, creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
76
|
+
getListMemberships(userId: string, creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
77
|
+
getListSubscribers(listId: string, creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
78
|
+
subscribeToList(listId: string, creds: Credentials): Promise<unknown>;
|
|
79
|
+
unsubscribeFromList(listId: string, creds: Credentials): Promise<unknown>;
|
|
80
|
+
exploreCommunities(creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
81
|
+
getCommunity(communityId: string, creds: Credentials): Promise<unknown>;
|
|
82
|
+
joinCommunity(communityId: string, creds: Credentials): Promise<unknown>;
|
|
83
|
+
leaveCommunity(communityId: string, creds: Credentials): Promise<unknown>;
|
|
84
|
+
getCommunityTweets(communityId: string, creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
85
|
+
getCommunityMedia(communityId: string, creds: Credentials, count?: number, cursor?: string): Promise<unknown>;
|
|
86
|
+
getTopic(topicId: string, creds: Credentials): Promise<unknown>;
|
|
87
|
+
followTopic(topicId: string, creds: Credentials): Promise<unknown>;
|
|
88
|
+
unfollowTopic(topicId: string, creds: Credentials): Promise<unknown>;
|
|
89
|
+
}
|
|
90
|
+
export default ApiTwitter;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiTwitter = exports.ValidationError = exports.NotFoundError = exports.RateLimitError = exports.InsufficientCreditsError = exports.AuthenticationError = exports.ApiTwitterError = void 0;
|
|
4
|
+
const errors_1 = require("./errors");
|
|
5
|
+
Object.defineProperty(exports, "ApiTwitterError", { enumerable: true, get: function () { return errors_1.ApiTwitterError; } });
|
|
6
|
+
Object.defineProperty(exports, "AuthenticationError", { enumerable: true, get: function () { return errors_1.AuthenticationError; } });
|
|
7
|
+
Object.defineProperty(exports, "InsufficientCreditsError", { enumerable: true, get: function () { return errors_1.InsufficientCreditsError; } });
|
|
8
|
+
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return errors_1.RateLimitError; } });
|
|
9
|
+
Object.defineProperty(exports, "NotFoundError", { enumerable: true, get: function () { return errors_1.NotFoundError; } });
|
|
10
|
+
Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return errors_1.ValidationError; } });
|
|
11
|
+
class ApiTwitter {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
if (typeof options === "string") {
|
|
14
|
+
this.apiKey = options;
|
|
15
|
+
this.baseUrl = "https://api.apitwitter.com";
|
|
16
|
+
this.timeout = 30000;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
this.apiKey = options.apiKey;
|
|
20
|
+
this.baseUrl = (options.baseUrl || "https://api.apitwitter.com").replace(/\/$/, "");
|
|
21
|
+
this.timeout = (options.timeout || 30) * 1000;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// -- internal helpers --
|
|
25
|
+
async request(method, path, body, params) {
|
|
26
|
+
const url = new URL(path, this.baseUrl);
|
|
27
|
+
if (params) {
|
|
28
|
+
for (const [k, v] of Object.entries(params)) {
|
|
29
|
+
if (v !== undefined && v !== null)
|
|
30
|
+
url.searchParams.set(k, String(v));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const controller = new AbortController();
|
|
34
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
35
|
+
try {
|
|
36
|
+
const resp = await fetch(url.toString(), {
|
|
37
|
+
method,
|
|
38
|
+
headers: {
|
|
39
|
+
"X-API-Key": this.apiKey,
|
|
40
|
+
"Content-Type": "application/json",
|
|
41
|
+
},
|
|
42
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
43
|
+
signal: controller.signal,
|
|
44
|
+
});
|
|
45
|
+
let data;
|
|
46
|
+
try {
|
|
47
|
+
data = (await resp.json());
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
data = { msg: await resp.text() };
|
|
51
|
+
}
|
|
52
|
+
if (resp.ok)
|
|
53
|
+
return data.data ?? data;
|
|
54
|
+
const msg = String(data.msg || data.message || JSON.stringify(data));
|
|
55
|
+
const status = resp.status;
|
|
56
|
+
if (status === 401)
|
|
57
|
+
throw new errors_1.AuthenticationError(msg, data);
|
|
58
|
+
if (status === 402)
|
|
59
|
+
throw new errors_1.InsufficientCreditsError(msg, data);
|
|
60
|
+
if (status === 404)
|
|
61
|
+
throw new errors_1.NotFoundError(msg, data);
|
|
62
|
+
if (status === 429)
|
|
63
|
+
throw new errors_1.RateLimitError(msg, Number(data.retry_after) || 0, data);
|
|
64
|
+
if (status === 400)
|
|
65
|
+
throw new errors_1.ValidationError(msg, data);
|
|
66
|
+
throw new errors_1.ApiTwitterError(msg, status, data);
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
clearTimeout(timer);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
get(path, params) {
|
|
73
|
+
return this.request("GET", path, undefined, params);
|
|
74
|
+
}
|
|
75
|
+
post(path, body) {
|
|
76
|
+
return this.request("POST", path, body);
|
|
77
|
+
}
|
|
78
|
+
del(path, body) {
|
|
79
|
+
return this.request("DELETE", path, body);
|
|
80
|
+
}
|
|
81
|
+
patch(path, body) {
|
|
82
|
+
return this.request("PATCH", path, body);
|
|
83
|
+
}
|
|
84
|
+
creds(c) {
|
|
85
|
+
const o = { cookie: c.cookie, proxy: c.proxy };
|
|
86
|
+
if (c.userAgent)
|
|
87
|
+
o.user_agent = c.userAgent;
|
|
88
|
+
return o;
|
|
89
|
+
}
|
|
90
|
+
// ── Session ────────────────────────────────────────────
|
|
91
|
+
verifySession(creds) {
|
|
92
|
+
return this.post("/twitter/session/verify", this.creds(creds));
|
|
93
|
+
}
|
|
94
|
+
// ── Users (GET — pool) ─────────────────────────────────
|
|
95
|
+
getUser(username) {
|
|
96
|
+
return this.get(`/twitter/user/${username}`);
|
|
97
|
+
}
|
|
98
|
+
getUserById(userId) {
|
|
99
|
+
return this.get(`/twitter/user/id/${userId}`);
|
|
100
|
+
}
|
|
101
|
+
getUsersBatch(userIds) {
|
|
102
|
+
return this.get("/twitter/users/batch", { userIds: userIds.join(",") });
|
|
103
|
+
}
|
|
104
|
+
getFollowers(username, count = 200, cursor) {
|
|
105
|
+
return this.get(`/twitter/user/${username}/followers`, { count, cursor });
|
|
106
|
+
}
|
|
107
|
+
getFollowing(username, count = 200, cursor) {
|
|
108
|
+
return this.get(`/twitter/user/${username}/following`, { count, cursor });
|
|
109
|
+
}
|
|
110
|
+
getFollowersYouKnow(username, count = 20, cursor) {
|
|
111
|
+
return this.get(`/twitter/user/${username}/followers-you-know`, { count, cursor });
|
|
112
|
+
}
|
|
113
|
+
// ── Users (POST — own credentials) ─────────────────────
|
|
114
|
+
getUserPost(username, creds) {
|
|
115
|
+
return this.post(`/twitter/user/${username}`, this.creds(creds));
|
|
116
|
+
}
|
|
117
|
+
getUserLikes(username, creds, count = 20, cursor) {
|
|
118
|
+
return this.post(`/twitter/user/${username}/likes`, { ...this.creds(creds), count, cursor });
|
|
119
|
+
}
|
|
120
|
+
getUserMedia(username, creds, count = 20, cursor) {
|
|
121
|
+
return this.post(`/twitter/user/${username}/media`, { ...this.creds(creds), count, cursor });
|
|
122
|
+
}
|
|
123
|
+
getUserReplies(username, creds, count = 20, cursor) {
|
|
124
|
+
return this.post(`/twitter/user/${username}/replies`, { ...this.creds(creds), count, cursor });
|
|
125
|
+
}
|
|
126
|
+
getBlocked(creds, count = 200, cursor) {
|
|
127
|
+
return this.post("/twitter/blocked", { ...this.creds(creds), count, cursor });
|
|
128
|
+
}
|
|
129
|
+
getMuted(creds, count = 200, cursor) {
|
|
130
|
+
return this.post("/twitter/muted", { ...this.creds(creds), count, cursor });
|
|
131
|
+
}
|
|
132
|
+
removeFollower(userId, creds) {
|
|
133
|
+
return this.post(`/twitter/user/${userId}/remove-follower`, this.creds(creds));
|
|
134
|
+
}
|
|
135
|
+
// ── Tweets (GET — pool) ────────────────────────────────
|
|
136
|
+
getUserTweets(username, cursor) {
|
|
137
|
+
return this.get(`/twitter/user/${username}/tweets`, { cursor });
|
|
138
|
+
}
|
|
139
|
+
getTweets(tweetIds) {
|
|
140
|
+
return this.get("/twitter/tweets/lookup", { tweet_ids: tweetIds.join(",") });
|
|
141
|
+
}
|
|
142
|
+
search(query, product = "Top", count = 20, cursor) {
|
|
143
|
+
return this.get("/twitter/search", { query, product, count, cursor });
|
|
144
|
+
}
|
|
145
|
+
// ── Tweets (POST — own credentials) ────────────────────
|
|
146
|
+
createTweet(text, creds, replyTo) {
|
|
147
|
+
const body = { tweet_text: text, ...this.creds(creds) };
|
|
148
|
+
if (replyTo)
|
|
149
|
+
body.reply_to_tweet_id = replyTo;
|
|
150
|
+
return this.post("/twitter/tweets", body);
|
|
151
|
+
}
|
|
152
|
+
deleteTweet(tweetId, creds) {
|
|
153
|
+
return this.del(`/twitter/tweets/${tweetId}`, this.creds(creds));
|
|
154
|
+
}
|
|
155
|
+
retweet(tweetId, creds) {
|
|
156
|
+
return this.post(`/twitter/tweets/${tweetId}/retweet`, this.creds(creds));
|
|
157
|
+
}
|
|
158
|
+
unretweet(tweetId, creds) {
|
|
159
|
+
return this.del(`/twitter/tweets/${tweetId}/retweet`, this.creds(creds));
|
|
160
|
+
}
|
|
161
|
+
pinTweet(tweetId, creds) {
|
|
162
|
+
return this.post(`/twitter/tweets/${tweetId}/pin`, this.creds(creds));
|
|
163
|
+
}
|
|
164
|
+
unpinTweet(tweetId, creds) {
|
|
165
|
+
return this.del(`/twitter/tweets/${tweetId}/pin`, this.creds(creds));
|
|
166
|
+
}
|
|
167
|
+
// ── Engagement ─────────────────────────────────────────
|
|
168
|
+
like(tweetId, creds) {
|
|
169
|
+
return this.post(`/twitter/tweets/${tweetId}/like`, this.creds(creds));
|
|
170
|
+
}
|
|
171
|
+
unlike(tweetId, creds) {
|
|
172
|
+
return this.post(`/twitter/tweets/${tweetId}/unlike`, this.creds(creds));
|
|
173
|
+
}
|
|
174
|
+
follow(userId, creds) {
|
|
175
|
+
return this.post(`/twitter/user/${userId}/follow`, this.creds(creds));
|
|
176
|
+
}
|
|
177
|
+
unfollow(userId, creds) {
|
|
178
|
+
return this.post(`/twitter/user/${userId}/unfollow`, this.creds(creds));
|
|
179
|
+
}
|
|
180
|
+
// ── DM ─────────────────────────────────────────────────
|
|
181
|
+
sendDm(userId, text, creds) {
|
|
182
|
+
return this.post(`/twitter/dm/${userId}`, { text, ...this.creds(creds) });
|
|
183
|
+
}
|
|
184
|
+
dmBlock(userId, creds) {
|
|
185
|
+
return this.post(`/twitter/dm/block/${userId}`, this.creds(creds));
|
|
186
|
+
}
|
|
187
|
+
dmUnblock(userId, creds) {
|
|
188
|
+
return this.del(`/twitter/dm/block/${userId}`, this.creds(creds));
|
|
189
|
+
}
|
|
190
|
+
// ── Bookmarks ──────────────────────────────────────────
|
|
191
|
+
addBookmark(tweetId, creds) {
|
|
192
|
+
return this.post(`/twitter/tweets/${tweetId}/bookmark`, this.creds(creds));
|
|
193
|
+
}
|
|
194
|
+
removeBookmark(tweetId, creds) {
|
|
195
|
+
return this.del(`/twitter/tweets/${tweetId}/bookmark`, this.creds(creds));
|
|
196
|
+
}
|
|
197
|
+
getBookmarks(creds, count = 20, cursor) {
|
|
198
|
+
return this.post("/twitter/bookmarks", { ...this.creds(creds), count, cursor });
|
|
199
|
+
}
|
|
200
|
+
// ── Timeline ───────────────────────────────────────────
|
|
201
|
+
getTimelineForYou(creds, count = 20, cursor) {
|
|
202
|
+
return this.post("/twitter/timeline/for-you", { ...this.creds(creds), count, cursor });
|
|
203
|
+
}
|
|
204
|
+
getTimelineLatest(creds, count = 20, cursor) {
|
|
205
|
+
return this.post("/twitter/timeline/latest", { ...this.creds(creds), count, cursor });
|
|
206
|
+
}
|
|
207
|
+
// ── Search (POST) ──────────────────────────────────────
|
|
208
|
+
searchPost(query, creds, product = "Top", count = 20, cursor) {
|
|
209
|
+
return this.post("/twitter/search", { query, ...this.creds(creds), product, count, cursor });
|
|
210
|
+
}
|
|
211
|
+
// ── Lists ──────────────────────────────────────────────
|
|
212
|
+
createList(name, creds, options) {
|
|
213
|
+
return this.post("/twitter/lists", {
|
|
214
|
+
name, ...this.creds(creds),
|
|
215
|
+
description: options?.description,
|
|
216
|
+
is_private: options?.isPrivate ?? false,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
deleteList(listId, creds) {
|
|
220
|
+
return this.del(`/twitter/lists/${listId}`, this.creds(creds));
|
|
221
|
+
}
|
|
222
|
+
updateList(listId, creds, updates) {
|
|
223
|
+
return this.patch(`/twitter/lists/${listId}`, {
|
|
224
|
+
...this.creds(creds),
|
|
225
|
+
name: updates.name,
|
|
226
|
+
description: updates.description,
|
|
227
|
+
is_private: updates.isPrivate,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
getListInfo(listId, creds) {
|
|
231
|
+
return this.post(`/twitter/lists/${listId}/info`, this.creds(creds));
|
|
232
|
+
}
|
|
233
|
+
getListTweets(listId, creds, count = 20, cursor) {
|
|
234
|
+
return this.post(`/twitter/lists/${listId}/tweets`, { ...this.creds(creds), count, cursor });
|
|
235
|
+
}
|
|
236
|
+
getListMembers(listId, creds, count = 20, cursor) {
|
|
237
|
+
return this.post(`/twitter/lists/${listId}/members`, { ...this.creds(creds), count, cursor });
|
|
238
|
+
}
|
|
239
|
+
addListMember(listId, userId, creds) {
|
|
240
|
+
return this.post(`/twitter/lists/${listId}/members/${userId}/add`, this.creds(creds));
|
|
241
|
+
}
|
|
242
|
+
removeListMember(listId, userId, creds) {
|
|
243
|
+
return this.post(`/twitter/lists/${listId}/members/${userId}/remove`, this.creds(creds));
|
|
244
|
+
}
|
|
245
|
+
getOwnedLists(userId, creds, count = 20, cursor) {
|
|
246
|
+
return this.post("/twitter/lists/owned", { ...this.creds(creds), user_id: userId, count, cursor });
|
|
247
|
+
}
|
|
248
|
+
getListMemberships(userId, creds, count = 20, cursor) {
|
|
249
|
+
return this.post("/twitter/lists/memberships", { ...this.creds(creds), user_id: userId, count, cursor });
|
|
250
|
+
}
|
|
251
|
+
getListSubscribers(listId, creds, count = 20, cursor) {
|
|
252
|
+
return this.post(`/twitter/lists/${listId}/subscribers`, { ...this.creds(creds), count, cursor });
|
|
253
|
+
}
|
|
254
|
+
subscribeToList(listId, creds) {
|
|
255
|
+
return this.post(`/twitter/lists/${listId}/subscribe`, this.creds(creds));
|
|
256
|
+
}
|
|
257
|
+
unsubscribeFromList(listId, creds) {
|
|
258
|
+
return this.del(`/twitter/lists/${listId}/subscribe`, this.creds(creds));
|
|
259
|
+
}
|
|
260
|
+
// ── Communities ────────────────────────────────────────
|
|
261
|
+
exploreCommunities(creds, count = 20, cursor) {
|
|
262
|
+
return this.post("/twitter/communities/explore", { ...this.creds(creds), count, cursor });
|
|
263
|
+
}
|
|
264
|
+
getCommunity(communityId, creds) {
|
|
265
|
+
return this.post(`/twitter/communities/${communityId}`, this.creds(creds));
|
|
266
|
+
}
|
|
267
|
+
joinCommunity(communityId, creds) {
|
|
268
|
+
return this.post(`/twitter/communities/${communityId}/join`, this.creds(creds));
|
|
269
|
+
}
|
|
270
|
+
leaveCommunity(communityId, creds) {
|
|
271
|
+
return this.del(`/twitter/communities/${communityId}/join`, this.creds(creds));
|
|
272
|
+
}
|
|
273
|
+
getCommunityTweets(communityId, creds, count = 20, cursor) {
|
|
274
|
+
return this.post(`/twitter/communities/${communityId}/tweets`, { ...this.creds(creds), count, cursor });
|
|
275
|
+
}
|
|
276
|
+
getCommunityMedia(communityId, creds, count = 20, cursor) {
|
|
277
|
+
return this.post(`/twitter/communities/${communityId}/media`, { ...this.creds(creds), count, cursor });
|
|
278
|
+
}
|
|
279
|
+
// ── Topics ─────────────────────────────────────────────
|
|
280
|
+
getTopic(topicId, creds) {
|
|
281
|
+
return this.post(`/twitter/topics/${topicId}`, this.creds(creds));
|
|
282
|
+
}
|
|
283
|
+
followTopic(topicId, creds) {
|
|
284
|
+
return this.post(`/twitter/topics/${topicId}/follow`, this.creds(creds));
|
|
285
|
+
}
|
|
286
|
+
unfollowTopic(topicId, creds) {
|
|
287
|
+
return this.del(`/twitter/topics/${topicId}/follow`, this.creds(creds));
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
exports.ApiTwitter = ApiTwitter;
|
|
291
|
+
exports.default = ApiTwitter;
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@apitwitter/sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "JavaScript/TypeScript SDK for the ApiTwitter REST API — Twitter/X data access",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": ["dist"],
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"prepublishOnly": "npm run build"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["twitter", "api", "sdk", "x", "tweets", "social-media", "typescript"],
|
|
13
|
+
"author": "ApiTwitter <support@apitwitter.com>",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"homepage": "https://apitwitter.com",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/apitwitter/js-sdk"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"typescript": "^5.0.0"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18.0.0"
|
|
25
|
+
}
|
|
26
|
+
}
|