@xpoz/xpoz 0.3.2 → 0.4.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 +202 -2
- package/dist/index.cjs +10 -4
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ The SDK wraps Xpoz's [MCP](https://modelcontextprotocol.io) server, abstracting
|
|
|
30
30
|
|
|
31
31
|
## Features
|
|
32
32
|
|
|
33
|
-
- **
|
|
33
|
+
- **40 data methods** across Twitter, Instagram, Reddit, and TikTok
|
|
34
34
|
- **Fully async** — all methods return `Promise<T>`
|
|
35
35
|
- **Automatic operation polling** — long-running queries are abstracted away
|
|
36
36
|
- **Response types** — choose between fast (immediate), paging (full pagination), or CSV export
|
|
@@ -38,7 +38,7 @@ The SDK wraps Xpoz's [MCP](https://modelcontextprotocol.io) server, abstracting
|
|
|
38
38
|
- **CSV export** — `exportCsv()` on any paginated result
|
|
39
39
|
- **Field selection** — request only the fields you need
|
|
40
40
|
- **TypeScript-first** — fully typed results with autocomplete support
|
|
41
|
-
- **Namespaced API** — `client.twitter.*`, `client.instagram.*`, `client.reddit.*`
|
|
41
|
+
- **Namespaced API** — `client.twitter.*`, `client.instagram.*`, `client.reddit.*`, `client.tiktok.*`, `client.tracking.*`
|
|
42
42
|
|
|
43
43
|
## Quick Start
|
|
44
44
|
|
|
@@ -200,10 +200,12 @@ The following methods accept both `responseType` and `limit`:
|
|
|
200
200
|
- `twitter.getPostsByAuthor()`, `twitter.searchPosts()`, `twitter.getUsersByKeywords()`
|
|
201
201
|
- `instagram.getPostsByUser()`, `instagram.searchPosts()`, `instagram.getUsersByKeywords()`
|
|
202
202
|
- `reddit.searchPosts()`
|
|
203
|
+
- `tiktok.getPostsByUser()`, `tiktok.searchPosts()`, `tiktok.getUsersByKeywords()`
|
|
203
204
|
|
|
204
205
|
These methods accept `limit` only:
|
|
205
206
|
|
|
206
207
|
- `twitter.searchUsers()`, `instagram.searchUsers()`, `reddit.searchUsers()`, `reddit.searchSubreddits()`
|
|
208
|
+
- `tiktok.searchUsers()`
|
|
207
209
|
|
|
208
210
|
## Query Syntax
|
|
209
211
|
|
|
@@ -574,6 +576,122 @@ const subs = await client.reddit.getSubredditsByKeywords("cryptocurrency");
|
|
|
574
576
|
|
|
575
577
|
---
|
|
576
578
|
|
|
579
|
+
### TikTok — `client.tiktok`
|
|
580
|
+
|
|
581
|
+
#### `getUser(identifier, options?) -> Promise<TiktokUser>`
|
|
582
|
+
|
|
583
|
+
```typescript
|
|
584
|
+
const user = await client.tiktok.getUser("charlidamelio");
|
|
585
|
+
console.log(`${user.nickname} — ${user.followerCount?.toLocaleString()} followers`);
|
|
586
|
+
|
|
587
|
+
// By numeric ID
|
|
588
|
+
const user = await client.tiktok.getUser("123456789", { identifierType: "id" });
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
#### `searchUsers(name, options?) -> Promise<TiktokUser[]>`
|
|
592
|
+
|
|
593
|
+
Search users by name. Use `limit` to adjust the number of results.
|
|
594
|
+
|
|
595
|
+
```typescript
|
|
596
|
+
const users = await client.tiktok.searchUsers("charli");
|
|
597
|
+
const topFive = await client.tiktok.searchUsers("charli", { limit: 5 });
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
#### `getUsersByKeywords(query, options?) -> Promise<PaginatedResult<TiktokUser>>`
|
|
601
|
+
|
|
602
|
+
Find users who authored posts matching a keyword query. Supports `responseType` and `limit`.
|
|
603
|
+
|
|
604
|
+
```typescript
|
|
605
|
+
const users = await client.tiktok.getUsersByKeywords('"machine learning"', {
|
|
606
|
+
responseType: ResponseType.Fast,
|
|
607
|
+
limit: 20,
|
|
608
|
+
});
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
#### `getPostsByIds(postIds, options?) -> Promise<TiktokPost[]>`
|
|
612
|
+
|
|
613
|
+
Get 1-100 posts by their IDs.
|
|
614
|
+
|
|
615
|
+
```typescript
|
|
616
|
+
const posts = await client.tiktok.getPostsByIds(["7123456789012345678"]);
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
#### `getPostsByUser(identifier, options?) -> Promise<PaginatedResult<TiktokPost>>`
|
|
620
|
+
|
|
621
|
+
Get all posts by a user. Supports `responseType` and `limit`.
|
|
622
|
+
|
|
623
|
+
```typescript
|
|
624
|
+
const results = await client.tiktok.getPostsByUser("charlidamelio", {
|
|
625
|
+
startDate: "2025-01-01",
|
|
626
|
+
responseType: ResponseType.Fast,
|
|
627
|
+
limit: 50,
|
|
628
|
+
});
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
#### `searchPosts(query, options?) -> Promise<PaginatedResult<TiktokPost>>`
|
|
632
|
+
|
|
633
|
+
Full-text search with filters. Supports `responseType` and `limit`.
|
|
634
|
+
|
|
635
|
+
```typescript
|
|
636
|
+
const results = await client.tiktok.searchPosts("travel vlog", {
|
|
637
|
+
startDate: "2025-01-01",
|
|
638
|
+
responseType: ResponseType.Fast,
|
|
639
|
+
limit: 30,
|
|
640
|
+
});
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
#### `getComments(postId, options?) -> Promise<PaginatedResult<TiktokComment>>`
|
|
644
|
+
|
|
645
|
+
```typescript
|
|
646
|
+
const comments = await client.tiktok.getComments("7123456789012345678");
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
---
|
|
650
|
+
|
|
651
|
+
### Tracking — `client.tracking`
|
|
652
|
+
|
|
653
|
+
Manage tracked items (keywords, users, subreddits) that Xpoz monitors on your behalf. Import the enums to build items:
|
|
654
|
+
|
|
655
|
+
```typescript
|
|
656
|
+
import { XpozClient, TrackedItemType, TrackedItemPlatform } from "@xpoz/xpoz";
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
#### `getTrackedItems() -> Promise<TrackedItem[]>`
|
|
660
|
+
|
|
661
|
+
List all currently tracked items on your account.
|
|
662
|
+
|
|
663
|
+
```typescript
|
|
664
|
+
const items = await client.tracking.getTrackedItems();
|
|
665
|
+
for (const item of items) {
|
|
666
|
+
console.log(`${item.platform} / ${item.type}: ${item.phrase}`);
|
|
667
|
+
}
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
#### `addTrackedItems(items) -> Promise<AddTrackedItemsResult>`
|
|
671
|
+
|
|
672
|
+
Add one or more items to track.
|
|
673
|
+
|
|
674
|
+
```typescript
|
|
675
|
+
const result = await client.tracking.addTrackedItems([
|
|
676
|
+
{ phrase: "bitcoin", type: TrackedItemType.Keyword, platform: TrackedItemPlatform.Twitter },
|
|
677
|
+
{ phrase: "nasa", type: TrackedItemType.User, platform: TrackedItemPlatform.Instagram },
|
|
678
|
+
]);
|
|
679
|
+
console.log(`Added ${result.addedCount} items (${result.currentCount}/${result.maxTrackedItems} used)`);
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
#### `removeTrackedItems(items) -> Promise<RemoveTrackedItemsResult>`
|
|
683
|
+
|
|
684
|
+
Remove one or more tracked items.
|
|
685
|
+
|
|
686
|
+
```typescript
|
|
687
|
+
const result = await client.tracking.removeTrackedItems([
|
|
688
|
+
{ phrase: "bitcoin", type: TrackedItemType.Keyword, platform: TrackedItemPlatform.Twitter },
|
|
689
|
+
]);
|
|
690
|
+
console.log(`Removed ${result.removedCount} items`);
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
---
|
|
694
|
+
|
|
577
695
|
## Type Models
|
|
578
696
|
|
|
579
697
|
All fields are optional and typed as their respective TypeScript types. Unknown fields are preserved on the object.
|
|
@@ -731,6 +849,88 @@ All fields are optional and typed as their respective TypeScript types. Unknown
|
|
|
731
849
|
| `over18` | `boolean` | NSFW flag |
|
|
732
850
|
| `createdAtDate` | `string` | Creation date |
|
|
733
851
|
|
|
852
|
+
### TiktokPost
|
|
853
|
+
|
|
854
|
+
| Field | Type | Description |
|
|
855
|
+
| ---------------------------- | --------- | ---------------------------- |
|
|
856
|
+
| `id` | `string` | Post ID |
|
|
857
|
+
| `description` | `string` | Post caption/description |
|
|
858
|
+
| `descriptionLanguage` | `string` | Language of description |
|
|
859
|
+
| `userId` | `string` | Author user ID |
|
|
860
|
+
| `username` | `string` | Author username |
|
|
861
|
+
| `nickname` | `string` | Author display name |
|
|
862
|
+
| `likeCount` | `number` | Number of likes |
|
|
863
|
+
| `commentCount` | `number` | Number of comments |
|
|
864
|
+
| `playCount` | `number` | Video play count |
|
|
865
|
+
| `collectCount` | `number` | Number of collects/saves |
|
|
866
|
+
| `downloadCount` | `number` | Number of downloads |
|
|
867
|
+
| `forwardCount` | `number` | Number of forwards/shares |
|
|
868
|
+
| `videoThumbnail` | `string` | Thumbnail URL |
|
|
869
|
+
| `postType` | `number` | Post type code |
|
|
870
|
+
| `isPrivate` | `boolean` | Private post flag |
|
|
871
|
+
| `createdAt` | `string` | Creation timestamp |
|
|
872
|
+
| `createdAtDate` | `string` | Creation date (YYYY-MM-DD) |
|
|
873
|
+
|
|
874
|
+
### TiktokUser
|
|
875
|
+
|
|
876
|
+
| Field | Type | Description |
|
|
877
|
+
| ---------------- | --------- | ------------------------ |
|
|
878
|
+
| `id` | `string` | User ID |
|
|
879
|
+
| `username` | `string` | Username |
|
|
880
|
+
| `nickname` | `string` | Display name |
|
|
881
|
+
| `signature` | `string` | Bio text |
|
|
882
|
+
| `secUid` | `string` | Secure user ID |
|
|
883
|
+
| `avatar` | `string` | Profile picture URL |
|
|
884
|
+
| `isPrivate` | `boolean` | Private account |
|
|
885
|
+
| `isVerified` | `boolean` | Verified status |
|
|
886
|
+
| `followerCount` | `number` | Number of followers |
|
|
887
|
+
| `followingCount` | `number` | Number of following |
|
|
888
|
+
| `likeCount` | `number` | Total likes received |
|
|
889
|
+
| `postCount` | `number` | Total posts |
|
|
890
|
+
| `language` | `string` | Profile language |
|
|
891
|
+
| `region` | `string` | Account region |
|
|
892
|
+
| `createdAt` | `string` | Account creation date |
|
|
893
|
+
|
|
894
|
+
### TiktokComment
|
|
895
|
+
|
|
896
|
+
| Field | Type | Description |
|
|
897
|
+
| --------------- | -------- | ------------------------ |
|
|
898
|
+
| `id` | `string` | Comment ID |
|
|
899
|
+
| `postId` | `string` | Parent post ID |
|
|
900
|
+
| `userId` | `string` | Author user ID |
|
|
901
|
+
| `username` | `string` | Author username |
|
|
902
|
+
| `text` | `string` | Comment text |
|
|
903
|
+
| `likeCount` | `number` | Number of likes |
|
|
904
|
+
| `createdAt` | `string` | Creation timestamp |
|
|
905
|
+
| `createdAtDate` | `string` | Creation date (YYYY-MM-DD) |
|
|
906
|
+
|
|
907
|
+
### TrackedItem
|
|
908
|
+
|
|
909
|
+
| Field | Type | Description |
|
|
910
|
+
| ---------- | ---------------------- | -------------------------------------------------------- |
|
|
911
|
+
| `phrase` | `string` | Keyword, username, or subreddit name to track |
|
|
912
|
+
| `type` | `TrackedItemType` | `"keyword"`, `"user"`, or `"subreddit"` |
|
|
913
|
+
| `platform` | `TrackedItemPlatform` | `"twitter"`, `"instagram"`, `"reddit"`, or `"tiktok"` |
|
|
914
|
+
|
|
915
|
+
### AddTrackedItemsResult
|
|
916
|
+
|
|
917
|
+
| Field | Type | Description |
|
|
918
|
+
| ----------------- | --------- | ---------------------------------- |
|
|
919
|
+
| `success` | `boolean` | Whether the operation succeeded |
|
|
920
|
+
| `addedCount` | `number` | Number of items added |
|
|
921
|
+
| `message` | `string` | Status message |
|
|
922
|
+
| `currentCount` | `number` | Total tracked items after addition |
|
|
923
|
+
| `maxTrackedItems` | `number` | Plan limit for tracked items |
|
|
924
|
+
| `planName` | `string` | Current plan name |
|
|
925
|
+
|
|
926
|
+
### RemoveTrackedItemsResult
|
|
927
|
+
|
|
928
|
+
| Field | Type | Description |
|
|
929
|
+
| -------------- | --------- | ------------------------------- |
|
|
930
|
+
| `success` | `boolean` | Whether the operation succeeded |
|
|
931
|
+
| `removedCount` | `number` | Number of items removed |
|
|
932
|
+
| `message` | `string` | Status message |
|
|
933
|
+
|
|
734
934
|
### Composite Types
|
|
735
935
|
|
|
736
936
|
**`RedditPostWithComments`** — returned by `getPostWithComments()`:
|
package/dist/index.cjs
CHANGED
|
@@ -296,7 +296,7 @@ function coerce(value) {
|
|
|
296
296
|
}
|
|
297
297
|
|
|
298
298
|
// src/version.ts
|
|
299
|
-
var VERSION = "0.
|
|
299
|
+
var VERSION = "0.4.0";
|
|
300
300
|
|
|
301
301
|
// src/mcp/transport.ts
|
|
302
302
|
var USER_AGENT = `xpoz-ts-sdk/${VERSION}`;
|
|
@@ -439,14 +439,14 @@ async function waitForResult(callTool, operationId, timeoutMs = DEFAULT_TIMEOUT_
|
|
|
439
439
|
while (true) {
|
|
440
440
|
const result = await callTool("checkOperationStatus", { operationId });
|
|
441
441
|
const status = result["status"];
|
|
442
|
-
if (status === "
|
|
442
|
+
if (status === "error") {
|
|
443
443
|
const error = result["error"] ?? "Unknown error";
|
|
444
444
|
throw new OperationFailedError(operationId, String(error));
|
|
445
445
|
}
|
|
446
446
|
if (status === "cancelled") {
|
|
447
447
|
throw new OperationCancelledError(operationId);
|
|
448
448
|
}
|
|
449
|
-
if (status === "
|
|
449
|
+
if (status === "success" || status === "no_data" || "results" in result || "downloadUrl" in result) {
|
|
450
450
|
return result;
|
|
451
451
|
}
|
|
452
452
|
const elapsed = Date.now() - start;
|
|
@@ -534,7 +534,13 @@ var BaseNamespace = class {
|
|
|
534
534
|
}
|
|
535
535
|
async callAndMaybePoll(toolName, args) {
|
|
536
536
|
const result = await this.callTool(toolName, args);
|
|
537
|
-
if ("
|
|
537
|
+
if (result["status"] === "error") {
|
|
538
|
+
throw new OperationFailedError(
|
|
539
|
+
"",
|
|
540
|
+
String(result["error"] ?? "Unknown error")
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
if (result["status"] === "success" || "results" in result) {
|
|
538
544
|
return result;
|
|
539
545
|
}
|
|
540
546
|
const operationId = result["operationId"];
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -248,7 +248,7 @@ function coerce(value) {
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
// src/version.ts
|
|
251
|
-
var VERSION = "0.
|
|
251
|
+
var VERSION = "0.4.0";
|
|
252
252
|
|
|
253
253
|
// src/mcp/transport.ts
|
|
254
254
|
var USER_AGENT = `xpoz-ts-sdk/${VERSION}`;
|
|
@@ -391,14 +391,14 @@ async function waitForResult(callTool, operationId, timeoutMs = DEFAULT_TIMEOUT_
|
|
|
391
391
|
while (true) {
|
|
392
392
|
const result = await callTool("checkOperationStatus", { operationId });
|
|
393
393
|
const status = result["status"];
|
|
394
|
-
if (status === "
|
|
394
|
+
if (status === "error") {
|
|
395
395
|
const error = result["error"] ?? "Unknown error";
|
|
396
396
|
throw new OperationFailedError(operationId, String(error));
|
|
397
397
|
}
|
|
398
398
|
if (status === "cancelled") {
|
|
399
399
|
throw new OperationCancelledError(operationId);
|
|
400
400
|
}
|
|
401
|
-
if (status === "
|
|
401
|
+
if (status === "success" || status === "no_data" || "results" in result || "downloadUrl" in result) {
|
|
402
402
|
return result;
|
|
403
403
|
}
|
|
404
404
|
const elapsed = Date.now() - start;
|
|
@@ -486,7 +486,13 @@ var BaseNamespace = class {
|
|
|
486
486
|
}
|
|
487
487
|
async callAndMaybePoll(toolName, args) {
|
|
488
488
|
const result = await this.callTool(toolName, args);
|
|
489
|
-
if ("
|
|
489
|
+
if (result["status"] === "error") {
|
|
490
|
+
throw new OperationFailedError(
|
|
491
|
+
"",
|
|
492
|
+
String(result["error"] ?? "Unknown error")
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
if (result["status"] === "success" || "results" in result) {
|
|
490
496
|
return result;
|
|
491
497
|
}
|
|
492
498
|
const operationId = result["operationId"];
|