@xpoz/xpoz 0.6.13 → 0.8.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/dist/index.js CHANGED
@@ -248,7 +248,7 @@ function coerce(value) {
248
248
  }
249
249
 
250
250
  // src/version.ts
251
- var VERSION = "0.6.13";
251
+ var VERSION = "0.8.0";
252
252
 
253
253
  // src/mcp/transport.ts
254
254
  var USER_AGENT = `xpoz-ts-sdk/${VERSION}`;
@@ -401,6 +401,11 @@ var DEFAULT_TIMEOUT_MS = 3e5;
401
401
  var DEFAULT_API_URL = "https://api.xpoz.ai";
402
402
  var ENV_API_URL = "XPOZ_API_URL";
403
403
  var INSTAGRAM_BASE = "/api/data/instagram";
404
+ var TWITTER_BASE = "/api/data/twitter";
405
+ var INSTAGRAM_ROUTES = {
406
+ user: (identifier) => `${INSTAGRAM_BASE}/users/${encodeURIComponent(identifier)}`,
407
+ postsByIds: `${INSTAGRAM_BASE}/posts/ids`
408
+ };
404
409
  var INSTAGRAM_LIVE_ROUTES = {
405
410
  posts: `${INSTAGRAM_BASE}/posts/live`,
406
411
  userPosts: (identifier) => `${INSTAGRAM_BASE}/posts/users/${encodeURIComponent(identifier)}/live`,
@@ -411,6 +416,20 @@ var INSTAGRAM_LIVE_ROUTES = {
411
416
  user: (identifier) => `${INSTAGRAM_BASE}/users/${encodeURIComponent(identifier)}/live`,
412
417
  userConnections: (identifier) => `${INSTAGRAM_BASE}/users/${encodeURIComponent(identifier)}/connections/live`
413
418
  };
419
+ var TWITTER_ROUTES = {
420
+ posts: `${TWITTER_BASE}/posts`
421
+ };
422
+ var TWITTER_LIVE_ROUTES = {
423
+ posts: `${TWITTER_BASE}/posts/live`,
424
+ userPosts: (username) => `${TWITTER_BASE}/posts/users/${encodeURIComponent(username)}/live`,
425
+ post: (postId) => `${TWITTER_BASE}/posts/${encodeURIComponent(postId)}/live`,
426
+ postComments: (postId) => `${TWITTER_BASE}/posts/${encodeURIComponent(postId)}/comments/live`,
427
+ postQuotes: (postId) => `${TWITTER_BASE}/posts/${encodeURIComponent(postId)}/quotes/live`,
428
+ postInteractingUsers: (postId) => `${TWITTER_BASE}/posts/${encodeURIComponent(postId)}/interacting-users/live`,
429
+ users: `${TWITTER_BASE}/users/live`,
430
+ user: (username) => `${TWITTER_BASE}/users/${encodeURIComponent(username)}/live`,
431
+ userConnections: (username) => `${TWITTER_BASE}/users/${encodeURIComponent(username)}/connections/live`
432
+ };
414
433
  var REST_TIMEOUT_MS = 12e4;
415
434
 
416
435
  // src/rest/transport.ts
@@ -523,8 +542,16 @@ var CursorResult = class {
523
542
  }
524
543
  };
525
544
 
526
- // src/namespaces/instagramLive.ts
527
- var STRING_ID_FIELDS = ["id", "userId", "user_id", "postId", "post_id"];
545
+ // src/namespaces/liveBase.ts
546
+ var STRING_ID_FIELDS = [
547
+ "id",
548
+ "userId",
549
+ "user_id",
550
+ "postId",
551
+ "post_id",
552
+ "authorId",
553
+ "author_id"
554
+ ];
528
555
  function coerceStringIds(item) {
529
556
  const record = item;
530
557
  for (const field of STRING_ID_FIELDS) {
@@ -537,7 +564,7 @@ function coerceStringIds(item) {
537
564
  function csvFields(fields) {
538
565
  return fields && fields.length > 0 ? fields.join(",") : void 0;
539
566
  }
540
- var InstagramLiveNamespace = class {
567
+ var LiveNamespace = class {
541
568
  transport;
542
569
  constructor(transport) {
543
570
  this.transport = transport;
@@ -555,6 +582,10 @@ var InstagramLiveNamespace = class {
555
582
  const page = await this.page(path, params);
556
583
  return page.data[0] ?? null;
557
584
  }
585
+ };
586
+
587
+ // src/namespaces/instagramLive.ts
588
+ var InstagramLiveNamespace = class extends LiveNamespace {
558
589
  async searchPosts(query, options = {}) {
559
590
  return this.page(INSTAGRAM_LIVE_ROUTES.posts, {
560
591
  q: query,
@@ -607,6 +638,73 @@ var InstagramLiveNamespace = class {
607
638
  }
608
639
  };
609
640
 
641
+ // src/namespaces/twitterLive.ts
642
+ var TwitterLiveNamespace = class extends LiveNamespace {
643
+ async searchPosts(query, options = {}) {
644
+ return this.page(TWITTER_LIVE_ROUTES.posts, {
645
+ q: query,
646
+ since: options.since,
647
+ until: options.until,
648
+ lang: options.lang,
649
+ countryCode: options.countryCode,
650
+ sortBy: options.sortBy,
651
+ fields: csvFields(options.fields),
652
+ cursor: options.cursor
653
+ });
654
+ }
655
+ async getPostsByUser(username, options = {}) {
656
+ return this.page(TWITTER_LIVE_ROUTES.userPosts(username), {
657
+ since: options.since,
658
+ until: options.until,
659
+ fields: csvFields(options.fields),
660
+ cursor: options.cursor
661
+ });
662
+ }
663
+ async getPost(postId, options = {}) {
664
+ return this.single(TWITTER_LIVE_ROUTES.post(postId), {
665
+ fields: csvFields(options.fields)
666
+ });
667
+ }
668
+ async getComments(postId, options = {}) {
669
+ return this.page(TWITTER_LIVE_ROUTES.postComments(postId), {
670
+ fields: csvFields(options.fields),
671
+ cursor: options.cursor
672
+ });
673
+ }
674
+ async getQuotes(postId, options = {}) {
675
+ return this.page(TWITTER_LIVE_ROUTES.postQuotes(postId), {
676
+ fields: csvFields(options.fields),
677
+ cursor: options.cursor
678
+ });
679
+ }
680
+ async getPostInteractingUsers(postId, interactionType, options = {}) {
681
+ return this.page(TWITTER_LIVE_ROUTES.postInteractingUsers(postId), {
682
+ interactionType,
683
+ fields: csvFields(options.fields),
684
+ cursor: options.cursor
685
+ });
686
+ }
687
+ async searchUsers(query, options = {}) {
688
+ return this.page(TWITTER_LIVE_ROUTES.users, {
689
+ q: query,
690
+ fields: csvFields(options.fields),
691
+ cursor: options.cursor
692
+ });
693
+ }
694
+ async getUser(username, options = {}) {
695
+ return this.single(TWITTER_LIVE_ROUTES.user(username), {
696
+ fields: csvFields(options.fields)
697
+ });
698
+ }
699
+ async getUserConnections(username, connectionType, options = {}) {
700
+ return this.page(TWITTER_LIVE_ROUTES.userConnections(username), {
701
+ connectionType,
702
+ fields: csvFields(options.fields),
703
+ cursor: options.cursor
704
+ });
705
+ }
706
+ };
707
+
610
708
  // src/mcp/polling.ts
611
709
  async function waitForResult(callTool, operationId, timeoutMs = DEFAULT_TIMEOUT_MS) {
612
710
  const start = Date.now();
@@ -768,28 +866,36 @@ var BaseNamespace = class {
768
866
  }
769
867
  };
770
868
 
869
+ // src/concurrency.ts
870
+ var DEFAULT_CONCURRENCY = 10;
871
+ async function parallelMap(items, fn, concurrency = DEFAULT_CONCURRENCY) {
872
+ const results = new Array(items.length);
873
+ let nextIndex = 0;
874
+ async function worker() {
875
+ while (nextIndex < items.length) {
876
+ const index = nextIndex++;
877
+ results[index] = await fn(items[index]);
878
+ }
879
+ }
880
+ const workers = Array.from(
881
+ { length: Math.min(concurrency, items.length) },
882
+ () => worker()
883
+ );
884
+ await Promise.all(workers);
885
+ return results;
886
+ }
887
+
771
888
  // src/config/tools.ts
772
- var GET_TWITTER_POSTS_BY_IDS = "getTwitterPostsByIds";
773
889
  var GET_TWITTER_POSTS_BY_AUTHOR = "getTwitterPostsByAuthor";
774
890
  var SEARCH_TWITTER_POSTS = "getTwitterPostsByKeywords";
775
891
  var GET_TWITTER_RETWEETS = "getTwitterPostRetweets";
776
- var GET_TWITTER_QUOTES = "getTwitterPostQuotes";
777
- var GET_TWITTER_COMMENTS = "getTwitterPostComments";
778
- var GET_TWITTER_POST_INTERACTING_USERS = "getTwitterPostInteractingUsers";
779
892
  var COUNT_TWEETS = "countTweets";
780
893
  var GET_TWITTER_USER = "getTwitterUser";
781
894
  var GET_TWITTER_USERS = "getTwitterUsers";
782
- var SEARCH_TWITTER_USERS = "searchTwitterUsers";
783
895
  var GET_TWITTER_USER_CONNECTIONS = "getTwitterUserConnections";
784
896
  var GET_TWITTER_USERS_BY_KEYWORDS = "getTwitterUsersByKeywords";
785
- var GET_INSTAGRAM_POSTS_BY_IDS = "getInstagramPostsByIds";
786
897
  var GET_INSTAGRAM_POSTS_BY_USER = "getInstagramPostsByUser";
787
898
  var SEARCH_INSTAGRAM_POSTS = "getInstagramPostsByKeywords";
788
- var GET_INSTAGRAM_COMMENTS = "getInstagramCommentsByPostId";
789
- var GET_INSTAGRAM_USER = "getInstagramUser";
790
- var SEARCH_INSTAGRAM_USERS = "searchInstagramUsers";
791
- var GET_INSTAGRAM_USER_CONNECTIONS = "getInstagramUserConnections";
792
- var GET_INSTAGRAM_POST_INTERACTING_USERS = "getInstagramPostInteractingUsers";
793
899
  var GET_INSTAGRAM_USERS_BY_KEYWORDS = "getInstagramUsersByKeywords";
794
900
  var SEARCH_REDDIT_POSTS = "getRedditPostsByKeywords";
795
901
  var GET_REDDIT_POST_WITH_COMMENTS = "getRedditPostWithCommentsById";
@@ -826,33 +932,79 @@ function parseUser(item) {
826
932
  return item;
827
933
  }
828
934
  var TwitterNamespace = class extends BaseNamespace {
935
+ rest;
936
+ constructor(callTool, timeoutMs, restTransport) {
937
+ super(callTool, timeoutMs);
938
+ this.rest = restTransport;
939
+ }
940
+ cursorToPaginatedResult(response, fetchNext, pageNumber = 1) {
941
+ const items = response.results ?? [];
942
+ const hasMore = Boolean(response.has_more);
943
+ const nextCursor = response.next_page_cursor ?? null;
944
+ const pagination = {
945
+ tableName: null,
946
+ totalRows: 0,
947
+ totalPages: hasMore ? pageNumber + 1 : pageNumber,
948
+ pageNumber,
949
+ pageSize: items.length,
950
+ resultsCount: items.length
951
+ };
952
+ const fetchPage = async () => {
953
+ if (!nextCursor) {
954
+ throw new RangeError("No more pages available");
955
+ }
956
+ const nextResponse = await fetchNext(nextCursor);
957
+ return this.cursorToPaginatedResult(nextResponse, fetchNext, pageNumber + 1);
958
+ };
959
+ return new PaginatedResult({
960
+ data: items,
961
+ pagination,
962
+ tableName: null,
963
+ exportOperationId: null,
964
+ fetchPage: () => fetchPage(),
965
+ fetchExport: null
966
+ });
967
+ }
829
968
  async getPostsByIds(postIds, options = {}) {
830
- const args = this.buildArgs({ postIds, ...options });
831
- const result = await this.callAndMaybePoll(
832
- GET_TWITTER_POSTS_BY_IDS,
833
- args
834
- );
835
- return (result["results"] ?? []).map(parseTwitterPost);
969
+ const fieldsCsv = csvFields(options.fields);
970
+ const results = await parallelMap(postIds, async (postId) => {
971
+ const response = await this.rest.get(
972
+ TWITTER_LIVE_ROUTES.post(postId),
973
+ { fields: fieldsCsv }
974
+ );
975
+ return (response.results ?? [])[0] ?? null;
976
+ });
977
+ return results.filter((post) => post !== null);
836
978
  }
837
979
  async getPostsByAuthor(identifier, options = {}) {
838
- const args = this.buildArgs({
839
- username: identifier,
840
- fields: options.fields,
841
- startDate: options.startDate,
842
- endDate: options.endDate,
843
- forceLatest: options.forceLatest,
844
- responseType: options.responseType,
845
- limit: options.limit
846
- });
847
- const result = await this.callAndMaybePoll(
848
- GET_TWITTER_POSTS_BY_AUTHOR,
849
- args
980
+ if (options.responseType === "csv" /* Csv */) {
981
+ const args = this.buildArgs({
982
+ username: identifier,
983
+ fields: options.fields,
984
+ startDate: options.startDate,
985
+ endDate: options.endDate,
986
+ forceLatest: options.forceLatest,
987
+ responseType: options.responseType,
988
+ limit: options.limit
989
+ });
990
+ const result = await this.callAndMaybePoll(GET_TWITTER_POSTS_BY_AUTHOR, args);
991
+ return this.buildPaginatedResult(result, parseTwitterPost, GET_TWITTER_POSTS_BY_AUTHOR, args);
992
+ }
993
+ const params = {
994
+ since: options.startDate,
995
+ until: options.endDate,
996
+ fields: csvFields(options.fields)
997
+ };
998
+ const response = await this.rest.get(
999
+ TWITTER_LIVE_ROUTES.userPosts(identifier),
1000
+ params
850
1001
  );
851
- return this.buildPaginatedResult(
852
- result,
853
- parseTwitterPost,
854
- GET_TWITTER_POSTS_BY_AUTHOR,
855
- args
1002
+ return this.cursorToPaginatedResult(
1003
+ response,
1004
+ (cursor) => this.rest.get(
1005
+ TWITTER_LIVE_ROUTES.userPosts(identifier),
1006
+ { ...params, cursor }
1007
+ )
856
1008
  );
857
1009
  }
858
1010
  async searchPosts(query, options = {}) {
@@ -908,39 +1060,48 @@ var TwitterNamespace = class extends BaseNamespace {
908
1060
  );
909
1061
  }
910
1062
  async getQuotes(postId, options = {}) {
911
- const args = this.buildArgs({ postId, ...options });
912
- const result = await this.callAndMaybePoll(GET_TWITTER_QUOTES, args);
913
- return this.buildPaginatedResult(
914
- result,
915
- parseTwitterPost,
916
- GET_TWITTER_QUOTES,
917
- args
1063
+ const params = { fields: csvFields(options.fields) };
1064
+ const response = await this.rest.get(
1065
+ TWITTER_LIVE_ROUTES.postQuotes(postId),
1066
+ params
1067
+ );
1068
+ return this.cursorToPaginatedResult(
1069
+ response,
1070
+ (cursor) => this.rest.get(
1071
+ TWITTER_LIVE_ROUTES.postQuotes(postId),
1072
+ { ...params, cursor }
1073
+ )
918
1074
  );
919
1075
  }
920
1076
  async getComments(postId, options = {}) {
921
- const args = this.buildArgs({ postId, ...options });
922
- const result = await this.callAndMaybePoll(
923
- GET_TWITTER_COMMENTS,
924
- args
1077
+ const params = { fields: csvFields(options.fields) };
1078
+ const response = await this.rest.get(
1079
+ TWITTER_LIVE_ROUTES.postComments(postId),
1080
+ params
925
1081
  );
926
- return this.buildPaginatedResult(
927
- result,
928
- parseTwitterPost,
929
- GET_TWITTER_COMMENTS,
930
- args
1082
+ return this.cursorToPaginatedResult(
1083
+ response,
1084
+ (cursor) => this.rest.get(
1085
+ TWITTER_LIVE_ROUTES.postComments(postId),
1086
+ { ...params, cursor }
1087
+ )
931
1088
  );
932
1089
  }
933
1090
  async getPostInteractingUsers(postId, interactionType, options = {}) {
934
- const args = this.buildArgs({ postId, interactionType, ...options });
935
- const result = await this.callAndMaybePoll(
936
- GET_TWITTER_POST_INTERACTING_USERS,
937
- args
1091
+ const params = {
1092
+ interactionType,
1093
+ fields: csvFields(options.fields)
1094
+ };
1095
+ const response = await this.rest.get(
1096
+ TWITTER_LIVE_ROUTES.postInteractingUsers(postId),
1097
+ params
938
1098
  );
939
- return this.buildPaginatedResult(
940
- result,
941
- parseUser,
942
- GET_TWITTER_POST_INTERACTING_USERS,
943
- args
1099
+ return this.cursorToPaginatedResult(
1100
+ response,
1101
+ (cursor) => this.rest.get(
1102
+ TWITTER_LIVE_ROUTES.postInteractingUsers(postId),
1103
+ { ...params, cursor }
1104
+ )
944
1105
  );
945
1106
  }
946
1107
  async countPosts(phrase, options = {}) {
@@ -958,48 +1119,81 @@ var TwitterNamespace = class extends BaseNamespace {
958
1119
  return Number(count);
959
1120
  }
960
1121
  async getUsers(identifiers, options = {}) {
961
- const args = this.buildArgs({
962
- identifiers,
963
- identifierType: options.identifierType ?? "username",
964
- fields: options.fields,
965
- forceLatest: options.forceLatest
1122
+ if ((options.identifierType ?? "username") === "id") {
1123
+ const args = this.buildArgs({
1124
+ identifiers,
1125
+ identifierType: "id",
1126
+ fields: options.fields,
1127
+ forceLatest: options.forceLatest
1128
+ });
1129
+ const result = await this.callAndMaybePoll(GET_TWITTER_USERS, args);
1130
+ return (result["results"] ?? []).map(parseUser);
1131
+ }
1132
+ const fieldsCsv = csvFields(options.fields);
1133
+ const results = await parallelMap(identifiers, async (username) => {
1134
+ const response = await this.rest.get(
1135
+ TWITTER_LIVE_ROUTES.user(username),
1136
+ { fields: fieldsCsv }
1137
+ );
1138
+ return (response.results ?? [])[0] ?? null;
966
1139
  });
967
- const result = await this.callAndMaybePoll(GET_TWITTER_USERS, args);
968
- return (result["results"] ?? []).map(parseUser);
1140
+ return results.filter((user) => user !== null);
969
1141
  }
970
1142
  async getUser(identifier, options = {}) {
971
- const args = this.buildArgs({
972
- identifier,
973
- identifierType: options.identifierType ?? "username",
974
- fields: options.fields,
975
- forceLatest: options.forceLatest
976
- });
977
- const result = await this.callAndMaybePoll(GET_TWITTER_USER, args);
978
- const results = result["results"];
979
- if (Array.isArray(results) && results.length > 0) {
980
- return results[0];
1143
+ if ((options.identifierType ?? "username") === "id") {
1144
+ const args = this.buildArgs({
1145
+ identifier,
1146
+ identifierType: "id",
1147
+ fields: options.fields,
1148
+ forceLatest: options.forceLatest
1149
+ });
1150
+ const result = await this.callAndMaybePoll(GET_TWITTER_USER, args);
1151
+ const results = result["results"];
1152
+ if (Array.isArray(results) && results.length > 0) {
1153
+ return results[0];
1154
+ }
1155
+ return result;
981
1156
  }
982
- return result;
1157
+ const response = await this.rest.get(
1158
+ TWITTER_LIVE_ROUTES.user(identifier),
1159
+ { fields: csvFields(options.fields) }
1160
+ );
1161
+ if (response.results && response.results.length > 0) {
1162
+ return response.results[0];
1163
+ }
1164
+ throw new Error(`User not found: ${identifier}`);
983
1165
  }
984
1166
  async searchUsers(name, options = {}) {
985
- const args = this.buildArgs({ name, ...options });
986
- const result = await this.callAndMaybePoll(
987
- SEARCH_TWITTER_USERS,
988
- args
1167
+ const response = await this.rest.get(
1168
+ TWITTER_LIVE_ROUTES.users,
1169
+ { q: name, fields: csvFields(options.fields) }
989
1170
  );
990
- return (result["results"] ?? []).map(parseUser);
1171
+ const users = response.results ?? [];
1172
+ if (options.limit && options.limit > 0) {
1173
+ return users.slice(0, options.limit);
1174
+ }
1175
+ return users;
991
1176
  }
992
1177
  async getUserConnections(username, connectionType, options = {}) {
993
- const args = this.buildArgs({ username, connectionType, ...options });
994
- const result = await this.callAndMaybePoll(
995
- GET_TWITTER_USER_CONNECTIONS,
996
- args
1178
+ if (options.responseType === "csv" /* Csv */) {
1179
+ const args = this.buildArgs({ username, connectionType, ...options });
1180
+ const result = await this.callAndMaybePoll(GET_TWITTER_USER_CONNECTIONS, args);
1181
+ return this.buildPaginatedResult(result, parseUser, GET_TWITTER_USER_CONNECTIONS, args);
1182
+ }
1183
+ const params = {
1184
+ connectionType,
1185
+ fields: csvFields(options.fields)
1186
+ };
1187
+ const response = await this.rest.get(
1188
+ TWITTER_LIVE_ROUTES.userConnections(username),
1189
+ params
997
1190
  );
998
- return this.buildPaginatedResult(
999
- result,
1000
- parseUser,
1001
- GET_TWITTER_USER_CONNECTIONS,
1002
- args
1191
+ return this.cursorToPaginatedResult(
1192
+ response,
1193
+ (cursor) => this.rest.get(
1194
+ TWITTER_LIVE_ROUTES.userConnections(username),
1195
+ { ...params, cursor }
1196
+ )
1003
1197
  );
1004
1198
  }
1005
1199
  async getUsersByKeywords(query, options = {}) {
@@ -1024,92 +1218,187 @@ function parsePost(item) {
1024
1218
  function parseUser2(item) {
1025
1219
  return item;
1026
1220
  }
1027
- function parseComment(item) {
1028
- return item;
1029
- }
1030
1221
  var InstagramNamespace = class extends BaseNamespace {
1222
+ rest;
1223
+ constructor(callTool, timeoutMs, restTransport) {
1224
+ super(callTool, timeoutMs);
1225
+ this.rest = restTransport;
1226
+ }
1227
+ cursorToPaginatedResult(response, fetchNext, pageNumber = 1) {
1228
+ const items = response.results ?? [];
1229
+ const hasMore = Boolean(response.has_more);
1230
+ const nextCursor = response.next_page_cursor ?? null;
1231
+ const pagination = {
1232
+ tableName: null,
1233
+ totalRows: 0,
1234
+ totalPages: hasMore ? pageNumber + 1 : pageNumber,
1235
+ pageNumber,
1236
+ pageSize: items.length,
1237
+ resultsCount: items.length
1238
+ };
1239
+ const fetchPage = async () => {
1240
+ if (!nextCursor) {
1241
+ throw new RangeError("No more pages available");
1242
+ }
1243
+ const nextResponse = await fetchNext(nextCursor);
1244
+ return this.cursorToPaginatedResult(nextResponse, fetchNext, pageNumber + 1);
1245
+ };
1246
+ return new PaginatedResult({
1247
+ data: items,
1248
+ pagination,
1249
+ tableName: null,
1250
+ exportOperationId: null,
1251
+ fetchPage: () => fetchPage(),
1252
+ fetchExport: null
1253
+ });
1254
+ }
1031
1255
  async getPostsByIds(postIds, options = {}) {
1032
- const args = this.buildArgs({ postIds, ...options });
1033
- const result = await this.callAndMaybePoll(GET_INSTAGRAM_POSTS_BY_IDS, args);
1034
- return (result["results"] ?? []).map(parsePost);
1256
+ const fieldsCsv = csvFields(options.fields);
1257
+ const results = await parallelMap(postIds, async (postId) => {
1258
+ const response = await this.rest.get(
1259
+ INSTAGRAM_LIVE_ROUTES.post(postId),
1260
+ { fields: fieldsCsv }
1261
+ );
1262
+ return (response.results ?? [])[0] ?? null;
1263
+ });
1264
+ return results.filter((post) => post !== null);
1035
1265
  }
1036
1266
  async getPostsByUser(identifier, options = {}) {
1037
- const args = this.buildArgs({
1038
- identifier,
1039
- identifierType: options.identifierType ?? "username",
1040
- fields: options.fields,
1041
- startDate: options.startDate,
1042
- endDate: options.endDate,
1043
- forceLatest: options.forceLatest,
1044
- responseType: options.responseType,
1045
- limit: options.limit
1046
- });
1047
- const result = await this.callAndMaybePoll(GET_INSTAGRAM_POSTS_BY_USER, args);
1048
- return this.buildPaginatedResult(
1049
- result,
1050
- parsePost,
1051
- GET_INSTAGRAM_POSTS_BY_USER,
1052
- args
1267
+ if (options.responseType === "csv" /* Csv */) {
1268
+ const args = this.buildArgs({
1269
+ identifier,
1270
+ identifierType: options.identifierType ?? "username",
1271
+ fields: options.fields,
1272
+ startDate: options.startDate,
1273
+ endDate: options.endDate,
1274
+ forceLatest: options.forceLatest,
1275
+ responseType: options.responseType,
1276
+ limit: options.limit
1277
+ });
1278
+ const result = await this.callAndMaybePoll(GET_INSTAGRAM_POSTS_BY_USER, args);
1279
+ return this.buildPaginatedResult(result, parsePost, GET_INSTAGRAM_POSTS_BY_USER, args);
1280
+ }
1281
+ const params = {
1282
+ fields: csvFields(options.fields)
1283
+ };
1284
+ const response = await this.rest.get(
1285
+ INSTAGRAM_LIVE_ROUTES.userPosts(identifier),
1286
+ params
1287
+ );
1288
+ return this.cursorToPaginatedResult(
1289
+ response,
1290
+ (cursor) => this.rest.get(
1291
+ INSTAGRAM_LIVE_ROUTES.userPosts(identifier),
1292
+ { ...params, cursor }
1293
+ )
1053
1294
  );
1054
1295
  }
1055
1296
  async searchPosts(query, options = {}) {
1056
- const args = this.buildArgs({
1057
- query,
1058
- fields: options.fields,
1059
- startDate: options.startDate,
1060
- endDate: options.endDate,
1061
- forceLatest: options.forceLatest,
1062
- responseType: options.responseType,
1063
- limit: options.limit
1064
- });
1065
- const result = await this.callAndMaybePoll(SEARCH_INSTAGRAM_POSTS, args);
1066
- return this.buildPaginatedResult(result, parsePost, SEARCH_INSTAGRAM_POSTS, args);
1297
+ if (options.responseType === "csv" /* Csv */) {
1298
+ const args = this.buildArgs({
1299
+ query,
1300
+ fields: options.fields,
1301
+ startDate: options.startDate,
1302
+ endDate: options.endDate,
1303
+ forceLatest: options.forceLatest,
1304
+ responseType: options.responseType,
1305
+ limit: options.limit
1306
+ });
1307
+ const result = await this.callAndMaybePoll(SEARCH_INSTAGRAM_POSTS, args);
1308
+ return this.buildPaginatedResult(result, parsePost, SEARCH_INSTAGRAM_POSTS, args);
1309
+ }
1310
+ const params = {
1311
+ q: query,
1312
+ fields: csvFields(options.fields)
1313
+ };
1314
+ const response = await this.rest.get(
1315
+ INSTAGRAM_LIVE_ROUTES.posts,
1316
+ params
1317
+ );
1318
+ return this.cursorToPaginatedResult(
1319
+ response,
1320
+ (cursor) => this.rest.get(
1321
+ INSTAGRAM_LIVE_ROUTES.posts,
1322
+ { ...params, cursor }
1323
+ )
1324
+ );
1067
1325
  }
1068
1326
  async getComments(postId, options = {}) {
1069
- const args = this.buildArgs({ postId, ...options });
1070
- const result = await this.callAndMaybePoll(GET_INSTAGRAM_COMMENTS, args);
1071
- return this.buildPaginatedResult(result, parseComment, GET_INSTAGRAM_COMMENTS, args);
1327
+ const params = {
1328
+ fields: csvFields(options.fields)
1329
+ };
1330
+ const response = await this.rest.get(
1331
+ INSTAGRAM_LIVE_ROUTES.postComments(postId),
1332
+ params
1333
+ );
1334
+ return this.cursorToPaginatedResult(
1335
+ response,
1336
+ (cursor) => this.rest.get(
1337
+ INSTAGRAM_LIVE_ROUTES.postComments(postId),
1338
+ { ...params, cursor }
1339
+ )
1340
+ );
1072
1341
  }
1073
1342
  async getUser(identifier, options = {}) {
1074
- const args = this.buildArgs({
1075
- identifier,
1076
- identifierType: options.identifierType ?? "username",
1077
- fields: options.fields,
1078
- forceLatest: options.forceLatest
1079
- });
1080
- const result = await this.callAndMaybePoll(GET_INSTAGRAM_USER, args);
1081
- const results = result["results"];
1082
- if (Array.isArray(results) && results.length > 0) {
1083
- return results[0];
1343
+ const response = await this.rest.get(
1344
+ INSTAGRAM_ROUTES.user(identifier),
1345
+ {
1346
+ identifierType: options.identifierType ?? "username",
1347
+ fields: csvFields(options.fields),
1348
+ forceLatest: true
1349
+ }
1350
+ );
1351
+ if (response.results.length > 0) {
1352
+ return response.results[0];
1084
1353
  }
1085
- return result;
1354
+ throw new Error(`User not found: ${identifier}`);
1086
1355
  }
1087
1356
  async searchUsers(name, options = {}) {
1088
- const args = this.buildArgs({ name, ...options });
1089
- const result = await this.callAndMaybePoll(SEARCH_INSTAGRAM_USERS, args);
1090
- return (result["results"] ?? []).map(parseUser2);
1357
+ const response = await this.rest.get(
1358
+ INSTAGRAM_LIVE_ROUTES.users,
1359
+ {
1360
+ name,
1361
+ fields: csvFields(options.fields)
1362
+ }
1363
+ );
1364
+ const users = response.results ?? [];
1365
+ if (options.limit && options.limit > 0) {
1366
+ return users.slice(0, options.limit);
1367
+ }
1368
+ return users;
1091
1369
  }
1092
1370
  async getUserConnections(username, connectionType, options = {}) {
1093
- const args = this.buildArgs({ username, connectionType, ...options });
1094
- const result = await this.callAndMaybePoll(GET_INSTAGRAM_USER_CONNECTIONS, args);
1095
- return this.buildPaginatedResult(
1096
- result,
1097
- parseUser2,
1098
- GET_INSTAGRAM_USER_CONNECTIONS,
1099
- args
1371
+ const params = {
1372
+ connectionType,
1373
+ fields: csvFields(options.fields)
1374
+ };
1375
+ const response = await this.rest.get(
1376
+ INSTAGRAM_LIVE_ROUTES.userConnections(username),
1377
+ params
1378
+ );
1379
+ return this.cursorToPaginatedResult(
1380
+ response,
1381
+ (cursor) => this.rest.get(
1382
+ INSTAGRAM_LIVE_ROUTES.userConnections(username),
1383
+ { ...params, cursor }
1384
+ )
1100
1385
  );
1101
1386
  }
1102
1387
  async getPostInteractingUsers(postId, interactionType, options = {}) {
1103
- const args = this.buildArgs({ postId, interactionType, ...options });
1104
- const result = await this.callAndMaybePoll(
1105
- GET_INSTAGRAM_POST_INTERACTING_USERS,
1106
- args
1388
+ const params = {
1389
+ interactionType,
1390
+ fields: csvFields(options.fields)
1391
+ };
1392
+ const response = await this.rest.get(
1393
+ INSTAGRAM_LIVE_ROUTES.postInteractingUsers(postId),
1394
+ params
1107
1395
  );
1108
- return this.buildPaginatedResult(
1109
- result,
1110
- parseUser2,
1111
- GET_INSTAGRAM_POST_INTERACTING_USERS,
1112
- args
1396
+ return this.cursorToPaginatedResult(
1397
+ response,
1398
+ (cursor) => this.rest.get(
1399
+ INSTAGRAM_LIVE_ROUTES.postInteractingUsers(postId),
1400
+ { ...params, cursor }
1401
+ )
1113
1402
  );
1114
1403
  }
1115
1404
  async getUsersByKeywords(query, options = {}) {
@@ -1131,7 +1420,7 @@ function parsePost2(item) {
1131
1420
  function parseUser3(item) {
1132
1421
  return item;
1133
1422
  }
1134
- function parseComment2(item) {
1423
+ function parseComment(item) {
1135
1424
  return item;
1136
1425
  }
1137
1426
  function parseSubreddit(item) {
@@ -1151,7 +1440,7 @@ var RedditNamespace = class extends BaseNamespace {
1151
1440
  async searchComments(query, options = {}) {
1152
1441
  const args = this.buildArgs({ query, ...options });
1153
1442
  const result = await this.callAndMaybePoll(SEARCH_REDDIT_COMMENTS, args);
1154
- return this.buildPaginatedResult(result, parseComment2, SEARCH_REDDIT_COMMENTS, args);
1443
+ return this.buildPaginatedResult(result, parseComment, SEARCH_REDDIT_COMMENTS, args);
1155
1444
  }
1156
1445
  async getCommentById(commentId, options = {}) {
1157
1446
  const args = this.buildArgs({ commentId, ...options });
@@ -1216,7 +1505,7 @@ var RedditNamespace = class extends BaseNamespace {
1216
1505
  const pagination = this.extractPagination(raw);
1217
1506
  return {
1218
1507
  post: postData,
1219
- comments: commentsData.map(parseComment2),
1508
+ comments: commentsData.map(parseComment),
1220
1509
  commentsPagination: pagination.totalPages > 0 ? pagination : null,
1221
1510
  commentsTableName: pagination.tableName ?? null
1222
1511
  };
@@ -1245,7 +1534,7 @@ function parsePost3(item) {
1245
1534
  function parseUser4(item) {
1246
1535
  return item;
1247
1536
  }
1248
- function parseComment3(item) {
1537
+ function parseComment2(item) {
1249
1538
  return item;
1250
1539
  }
1251
1540
  function parseSound(item) {
@@ -1292,7 +1581,7 @@ var TiktokNamespace = class extends BaseNamespace {
1292
1581
  async getComments(postId, options = {}) {
1293
1582
  const args = this.buildArgs({ postId, ...options });
1294
1583
  const result = await this.callAndMaybePoll(GET_TIKTOK_COMMENTS, args);
1295
- return this.buildPaginatedResult(result, parseComment3, GET_TIKTOK_COMMENTS, args);
1584
+ return this.buildPaginatedResult(result, parseComment2, GET_TIKTOK_COMMENTS, args);
1296
1585
  }
1297
1586
  async getUser(identifier, options = {}) {
1298
1587
  const args = this.buildArgs({
@@ -1438,6 +1727,7 @@ var XpozClient = class {
1438
1727
  versionCheck;
1439
1728
  restTransport;
1440
1729
  instagramLiveNamespace;
1730
+ twitterLiveNamespace;
1441
1731
  constructor(options = {}) {
1442
1732
  const apiKey = options.apiKey ?? process.env[ENV_API_KEY];
1443
1733
  if (!apiKey) {
@@ -1452,8 +1742,8 @@ var XpozClient = class {
1452
1742
  const apiUrl = options.apiUrl ?? process.env[ENV_API_URL] ?? DEFAULT_API_URL;
1453
1743
  this.restTransport = new RestTransport(apiUrl, apiKey);
1454
1744
  const callTool = this.transport.callTool.bind(this.transport);
1455
- this.twitter = new TwitterNamespace(callTool, timeoutMs);
1456
- this.instagram = new InstagramNamespace(callTool, timeoutMs);
1745
+ this.twitter = new TwitterNamespace(callTool, timeoutMs, this.restTransport);
1746
+ this.instagram = new InstagramNamespace(callTool, timeoutMs, this.restTransport);
1457
1747
  this.reddit = new RedditNamespace(callTool, timeoutMs);
1458
1748
  this.tiktok = new TiktokNamespace(callTool, timeoutMs);
1459
1749
  this.tracking = new TrackingNamespace(callTool, timeoutMs);
@@ -1465,6 +1755,12 @@ var XpozClient = class {
1465
1755
  }
1466
1756
  return this.instagramLiveNamespace;
1467
1757
  }
1758
+ get twitterLive() {
1759
+ if (!this.twitterLiveNamespace) {
1760
+ this.twitterLiveNamespace = new TwitterLiveNamespace(this.restTransport);
1761
+ }
1762
+ return this.twitterLiveNamespace;
1763
+ }
1468
1764
  async connect() {
1469
1765
  await this.transport.connect();
1470
1766
  if (this.versionCheck) {