rettiwt-api 6.0.7 → 6.1.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 (220) hide show
  1. package/.github/ISSUE_TEMPLATE/bug-report.yml +57 -0
  2. package/.github/ISSUE_TEMPLATE/feature-request.yml +20 -0
  3. package/.github/ISSUE_TEMPLATE/question.yml +15 -0
  4. package/.github/PULL_REQUEST_TEMPLATE.md +32 -0
  5. package/.github/workflows/ci.yml +33 -0
  6. package/.nvmrc +1 -0
  7. package/README.md +30 -6
  8. package/dist/Rettiwt.d.ts +3 -0
  9. package/dist/Rettiwt.js +4 -0
  10. package/dist/Rettiwt.js.map +1 -1
  11. package/dist/cli.js +2 -0
  12. package/dist/cli.js.map +1 -1
  13. package/dist/collections/Extractors.d.ts +24 -0
  14. package/dist/collections/Extractors.js +14 -0
  15. package/dist/collections/Extractors.js.map +1 -1
  16. package/dist/collections/Groups.js +11 -0
  17. package/dist/collections/Groups.js.map +1 -1
  18. package/dist/collections/Requests.js +12 -0
  19. package/dist/collections/Requests.js.map +1 -1
  20. package/dist/commands/DirectMessage.d.ts +10 -0
  21. package/dist/commands/DirectMessage.js +57 -0
  22. package/dist/commands/DirectMessage.js.map +1 -0
  23. package/dist/commands/List.js +44 -3
  24. package/dist/commands/List.js.map +1 -1
  25. package/dist/commands/Tweet.js +29 -1
  26. package/dist/commands/Tweet.js.map +1 -1
  27. package/dist/commands/User.js +39 -1
  28. package/dist/commands/User.js.map +1 -1
  29. package/dist/enums/Data.d.ts +3 -1
  30. package/dist/enums/Data.js +2 -0
  31. package/dist/enums/Data.js.map +1 -1
  32. package/dist/enums/Resource.d.ts +11 -0
  33. package/dist/enums/Resource.js +12 -0
  34. package/dist/enums/Resource.js.map +1 -1
  35. package/dist/enums/raw/Analytics.d.ts +6 -3
  36. package/dist/enums/raw/Analytics.js +5 -2
  37. package/dist/enums/raw/Analytics.js.map +1 -1
  38. package/dist/index.d.ts +15 -0
  39. package/dist/index.js +8 -0
  40. package/dist/index.js.map +1 -1
  41. package/dist/models/args/FetchArgs.d.ts +9 -0
  42. package/dist/models/args/FetchArgs.js +16 -0
  43. package/dist/models/args/FetchArgs.js.map +1 -1
  44. package/dist/models/args/PostArgs.d.ts +1 -0
  45. package/dist/models/args/PostArgs.js +2 -0
  46. package/dist/models/args/PostArgs.js.map +1 -1
  47. package/dist/models/data/Analytics.d.ts +43 -0
  48. package/dist/models/data/Analytics.js +92 -0
  49. package/dist/models/data/Analytics.js.map +1 -0
  50. package/dist/models/data/Conversation.d.ts +93 -0
  51. package/dist/models/data/Conversation.js +293 -0
  52. package/dist/models/data/Conversation.js.map +1 -0
  53. package/dist/models/data/CursoredData.d.ts +2 -1
  54. package/dist/models/data/CursoredData.js +6 -1
  55. package/dist/models/data/CursoredData.js.map +1 -1
  56. package/dist/models/data/DirectMessage.d.ts +105 -0
  57. package/dist/models/data/DirectMessage.js +284 -0
  58. package/dist/models/data/DirectMessage.js.map +1 -0
  59. package/dist/models/data/Inbox.d.ts +44 -0
  60. package/dist/models/data/Inbox.js +106 -0
  61. package/dist/models/data/Inbox.js.map +1 -0
  62. package/dist/models/data/List.d.ts +20 -0
  63. package/dist/models/data/List.js +50 -1
  64. package/dist/models/data/List.js.map +1 -1
  65. package/dist/models/data/Tweet.d.ts +6 -6
  66. package/dist/models/data/Tweet.js +4 -2
  67. package/dist/models/data/Tweet.js.map +1 -1
  68. package/dist/models/data/User.d.ts +2 -0
  69. package/dist/models/data/User.js +6 -0
  70. package/dist/models/data/User.js.map +1 -1
  71. package/dist/requests/DirectMessage.d.ts +28 -0
  72. package/dist/requests/DirectMessage.js +149 -0
  73. package/dist/requests/DirectMessage.js.map +1 -0
  74. package/dist/requests/List.d.ts +10 -0
  75. package/dist/requests/List.js +52 -0
  76. package/dist/requests/List.js.map +1 -1
  77. package/dist/requests/Tweet.d.ts +8 -0
  78. package/dist/requests/Tweet.js +30 -0
  79. package/dist/requests/Tweet.js.map +1 -1
  80. package/dist/requests/User.d.ts +8 -1
  81. package/dist/requests/User.js +67 -8
  82. package/dist/requests/User.js.map +1 -1
  83. package/dist/services/public/DirectMessageService.d.ts +100 -0
  84. package/dist/services/public/DirectMessageService.js +143 -0
  85. package/dist/services/public/DirectMessageService.js.map +1 -0
  86. package/dist/services/public/FetcherService.d.ts +3 -2
  87. package/dist/services/public/FetcherService.js +64 -3
  88. package/dist/services/public/FetcherService.js.map +1 -1
  89. package/dist/services/public/ListService.d.ts +85 -0
  90. package/dist/services/public/ListService.js +111 -0
  91. package/dist/services/public/ListService.js.map +1 -1
  92. package/dist/services/public/TweetService.d.ts +56 -0
  93. package/dist/services/public/TweetService.js +72 -0
  94. package/dist/services/public/TweetService.js.map +1 -1
  95. package/dist/services/public/UserService.d.ts +61 -2
  96. package/dist/services/public/UserService.js +89 -0
  97. package/dist/services/public/UserService.js.map +1 -1
  98. package/dist/types/args/FetchArgs.d.ts +69 -12
  99. package/dist/types/args/PostArgs.d.ts +29 -11
  100. package/dist/types/data/Analytics.d.ts +42 -0
  101. package/dist/types/data/Analytics.js +3 -0
  102. package/dist/types/data/Analytics.js.map +1 -0
  103. package/dist/types/data/Conversation.d.ts +32 -0
  104. package/dist/types/data/Conversation.js +3 -0
  105. package/dist/types/data/Conversation.js.map +1 -0
  106. package/dist/types/data/CursoredData.d.ts +4 -1
  107. package/dist/types/data/DirectMessage.d.ts +25 -0
  108. package/dist/types/data/DirectMessage.js +3 -0
  109. package/dist/types/data/DirectMessage.js.map +1 -0
  110. package/dist/types/data/Inbox.d.ts +18 -0
  111. package/dist/types/data/Inbox.js +3 -0
  112. package/dist/types/data/Inbox.js.map +1 -0
  113. package/dist/types/data/List.d.ts +5 -1
  114. package/dist/types/data/Tweet.d.ts +6 -6
  115. package/dist/types/data/User.d.ts +4 -0
  116. package/dist/types/raw/base/Analytic.d.ts +6 -1
  117. package/dist/types/raw/base/Message.d.ts +16 -0
  118. package/dist/types/raw/base/Message.js +4 -0
  119. package/dist/types/raw/base/Message.js.map +1 -0
  120. package/dist/types/raw/base/Tweet.d.ts +6 -6
  121. package/dist/types/raw/base/User.d.ts +2 -1
  122. package/dist/types/raw/composite/TimelineList.d.ts +9 -0
  123. package/dist/types/raw/composite/TimelineList.js +3 -0
  124. package/dist/types/raw/composite/TimelineList.js.map +1 -0
  125. package/dist/types/raw/dm/Conversation.d.ts +55 -0
  126. package/dist/types/raw/dm/Conversation.js +4 -0
  127. package/dist/types/raw/dm/Conversation.js.map +1 -0
  128. package/dist/types/raw/dm/InboxInitial.d.ts +137 -0
  129. package/dist/types/raw/dm/InboxInitial.js +4 -0
  130. package/dist/types/raw/dm/InboxInitial.js.map +1 -0
  131. package/dist/types/raw/dm/InboxTimeline.d.ts +287 -0
  132. package/dist/types/raw/dm/InboxTimeline.js +4 -0
  133. package/dist/types/raw/dm/InboxTimeline.js.map +1 -0
  134. package/dist/types/raw/dm/UserUpdates.d.ts +41 -0
  135. package/dist/types/raw/dm/UserUpdates.js +4 -0
  136. package/dist/types/raw/dm/UserUpdates.js.map +1 -0
  137. package/dist/types/raw/list/AddMember.d.ts +151 -0
  138. package/dist/types/raw/list/AddMember.js +4 -0
  139. package/dist/types/raw/list/AddMember.js.map +1 -0
  140. package/dist/types/raw/list/Details.d.ts +44 -13
  141. package/dist/types/raw/list/RemoveMember.d.ts +150 -0
  142. package/dist/types/raw/list/RemoveMember.js +4 -0
  143. package/dist/types/raw/list/RemoveMember.js.map +1 -0
  144. package/dist/types/raw/tweet/Bookmark.d.ts +12 -0
  145. package/dist/types/raw/tweet/Bookmark.js +4 -0
  146. package/dist/types/raw/tweet/Bookmark.js.map +1 -0
  147. package/dist/types/raw/tweet/Unbookmark.d.ts +11 -0
  148. package/dist/types/raw/tweet/Unbookmark.js +4 -0
  149. package/dist/types/raw/tweet/Unbookmark.js.map +1 -0
  150. package/dist/types/raw/user/Analytics.d.ts +6 -18
  151. package/dist/types/raw/user/Analytics.js +0 -1
  152. package/dist/types/raw/user/Analytics.js.map +1 -1
  153. package/dist/types/raw/user/Lists.d.ts +319 -0
  154. package/dist/types/raw/user/Lists.js +4 -0
  155. package/dist/types/raw/user/Lists.js.map +1 -0
  156. package/eslint.config.mjs +1 -1
  157. package/package.json +13 -6
  158. package/playground/.env.example +1 -0
  159. package/playground/README.md +53 -0
  160. package/playground/index.js +15 -0
  161. package/playground/package.json +15 -0
  162. package/src/Rettiwt.ts +5 -0
  163. package/src/cli.ts +2 -0
  164. package/src/collections/Extractors.ts +29 -0
  165. package/src/collections/Groups.ts +11 -0
  166. package/src/collections/Requests.ts +20 -0
  167. package/src/commands/DirectMessage.ts +62 -0
  168. package/src/commands/List.ts +44 -3
  169. package/src/commands/Tweet.ts +29 -1
  170. package/src/commands/User.ts +65 -1
  171. package/src/enums/Data.ts +2 -0
  172. package/src/enums/Resource.ts +13 -0
  173. package/src/enums/raw/Analytics.ts +5 -2
  174. package/src/index.ts +15 -0
  175. package/src/models/args/FetchArgs.ts +17 -0
  176. package/src/models/args/PostArgs.ts +2 -0
  177. package/src/models/data/Analytics.ts +97 -0
  178. package/src/models/data/Conversation.ts +344 -0
  179. package/src/models/data/CursoredData.ts +7 -2
  180. package/src/models/data/DirectMessage.ts +335 -0
  181. package/src/models/data/Inbox.ts +124 -0
  182. package/src/models/data/List.ts +60 -1
  183. package/src/models/data/Tweet.ts +10 -8
  184. package/src/models/data/User.ts +6 -0
  185. package/src/requests/DirectMessage.ts +233 -0
  186. package/src/requests/List.ts +58 -0
  187. package/src/requests/Tweet.ts +32 -0
  188. package/src/requests/User.ts +70 -7
  189. package/src/services/public/DirectMessageService.ts +159 -0
  190. package/src/services/public/FetcherService.ts +86 -4
  191. package/src/services/public/ListService.ts +127 -0
  192. package/src/services/public/TweetService.ts +82 -0
  193. package/src/services/public/UserService.ts +110 -2
  194. package/src/types/args/FetchArgs.ts +77 -12
  195. package/src/types/args/PostArgs.ts +31 -11
  196. package/src/types/data/Analytics.ts +58 -0
  197. package/src/types/data/Conversation.ts +44 -0
  198. package/src/types/data/CursoredData.ts +4 -1
  199. package/src/types/data/DirectMessage.ts +33 -0
  200. package/src/types/data/Inbox.ts +23 -0
  201. package/src/types/data/List.ts +7 -1
  202. package/src/types/data/Tweet.ts +6 -6
  203. package/src/types/data/User.ts +6 -0
  204. package/src/types/raw/base/Analytic.ts +7 -1
  205. package/src/types/raw/base/Message.ts +22 -0
  206. package/src/types/raw/base/Tweet.ts +6 -6
  207. package/src/types/raw/base/User.ts +2 -1
  208. package/src/types/raw/composite/TimelineList.ts +10 -0
  209. package/src/types/raw/dm/Conversation.ts +59 -0
  210. package/src/types/raw/dm/InboxInitial.ts +155 -0
  211. package/src/types/raw/dm/InboxTimeline.ts +301 -0
  212. package/src/types/raw/dm/UserUpdates.ts +46 -0
  213. package/src/types/raw/list/AddMember.ts +175 -0
  214. package/src/types/raw/list/Details.ts +52 -13
  215. package/src/types/raw/list/RemoveMember.ts +174 -0
  216. package/src/types/raw/tweet/Bookmark.ts +14 -0
  217. package/src/types/raw/tweet/Unbookmark.ts +14 -0
  218. package/src/types/raw/user/Analytics.ts +6 -22
  219. package/src/types/raw/user/Lists.ts +378 -0
  220. package/tsconfig.json +1 -1
@@ -5,6 +5,9 @@
5
5
  */
6
6
  export enum ResourceType {
7
7
  // LIST
8
+ LIST_DETAILS = 'LIST_DETAILS',
9
+ LIST_MEMBER_ADD = 'LIST_MEMBER_ADD',
10
+ LIST_MEMBER_REMOVE = 'LIST_MEMBER_REMOVE',
8
11
  LIST_MEMBERS = 'LIST_MEMBERS',
9
12
  LIST_TWEETS = 'LIST_TWEETS',
10
13
 
@@ -13,7 +16,14 @@ export enum ResourceType {
13
16
  MEDIA_UPLOAD_FINALIZE = 'MEDIA_UPLOAD_FINALIZE',
14
17
  MEDIA_UPLOAD_INITIALIZE = 'MEDIA_UPLOAD_INITIALIZE',
15
18
 
19
+ // DM
20
+ DM_CONVERSATION = 'DM_CONVERSATION',
21
+ DM_INBOX_INITIAL_STATE = 'DM_INBOX_INITIAL_STATE',
22
+ DM_INBOX_TIMELINE = 'DM_INBOX_TIMELINE',
23
+ DM_DELETE_CONVERSATION = 'DM_DELETE_CONVERSATION',
24
+
16
25
  // TWEET
26
+ TWEET_BOOKMARK = 'TWEET_BOOKMARK',
17
27
  TWEET_DETAILS = 'TWEET_DETAILS',
18
28
  TWEET_DETAILS_ALT = 'TWEET_DETAILS_ALT',
19
29
  TWEET_DETAILS_BULK = 'TWEET_DETAILS_BULK',
@@ -25,6 +35,7 @@ export enum ResourceType {
25
35
  TWEET_RETWEETERS = 'TWEET_RETWEETERS',
26
36
  TWEET_SCHEDULE = 'TWEET_SCHEDULE',
27
37
  TWEET_SEARCH = 'TWEET_SEARCH',
38
+ TWEET_UNBOOKMARK = 'TWEET_UNBOOKMARK',
28
39
  TWEET_UNLIKE = 'TWEET_UNLIKE',
29
40
  TWEET_UNPOST = 'TWEET_UNPOST',
30
41
  TWEET_UNRETWEET = 'TWEET_UNRETWEET',
@@ -32,6 +43,7 @@ export enum ResourceType {
32
43
 
33
44
  // USER
34
45
  USER_AFFILIATES = 'USER_AFFILIATES',
46
+ USER_ANALYTICS = 'USER_ANALYTICS',
35
47
  USER_BOOKMARKS = 'USER_BOOKMARKS',
36
48
  USER_DETAILS_BY_USERNAME = 'USER_DETAILS_BY_USERNAME',
37
49
  USER_DETAILS_BY_ID = 'USER_DETAILS_BY_ID',
@@ -43,6 +55,7 @@ export enum ResourceType {
43
55
  USER_FOLLOWERS = 'USER_FOLLOWERS',
44
56
  USER_HIGHLIGHTS = 'USER_HIGHLIGHTS',
45
57
  USER_LIKES = 'USER_LIKES',
58
+ USER_LISTS = 'USER_LISTS',
46
59
  USER_MEDIA = 'USER_MEDIA',
47
60
  USER_NOTIFICATIONS = 'USER_NOTIFICATIONS',
48
61
  USER_SUBSCRIPTIONS = 'USER_SUBSCRIPTIONS',
@@ -19,11 +19,14 @@ export enum RawAnalyticsMetric {
19
19
  IMPRESSIONS = 'Impressions',
20
20
  PROFILE_VISITS = 'ProfileVisits',
21
21
  FOLLOWS = 'Follows',
22
- VIDEO_VIEWS = 'VideoViews',
23
22
  REPLIES = 'Replies',
24
23
  LIKES = 'Likes',
25
24
  RETWEETS = 'Retweets',
26
- MEDIA_VIEWS = 'MediaViews',
27
25
  BOOKMARK = 'Bookmark',
28
26
  SHARE = 'Share',
27
+ URL_CLICKS = 'UrlClicks',
28
+ CREATE_TWEET = 'CreateTweet',
29
+ CREATE_QUOTE = 'CreateQuote',
30
+ CREATE_REPLY = 'CreateReply',
31
+ UNFOLLOWS = 'Unfollows',
29
32
  }
package/src/index.ts CHANGED
@@ -18,7 +18,10 @@ export * from './enums/Tweet';
18
18
  // MODELS
19
19
  export * from './models/args/FetchArgs';
20
20
  export * from './models/args/PostArgs';
21
+ export * from './models/data/Conversation';
21
22
  export * from './models/data/CursoredData';
23
+ export * from './models/data/DirectMessage';
24
+ export * from './models/data/Inbox';
22
25
  export * from './models/data/List';
23
26
  export * from './models/data/Notification';
24
27
  export * from './models/data/Tweet';
@@ -26,12 +29,14 @@ export * from './models/data/User';
26
29
  export * from './models/errors/TwitterError';
27
30
 
28
31
  // REQUESTS
32
+ export * from './requests/DirectMessage';
29
33
  export * from './requests/List';
30
34
  export * from './requests/Media';
31
35
  export * from './requests/Tweet';
32
36
  export * from './requests/User';
33
37
 
34
38
  // SERVICES
39
+ export * from './services/public/DirectMessageService';
35
40
  export * from './services/public/FetcherService';
36
41
  export * from './services/public/ListService';
37
42
  export * from './services/public/TweetService';
@@ -40,7 +45,10 @@ export * from './services/public/UserService';
40
45
  // TYPES
41
46
  export * from './types/args/FetchArgs';
42
47
  export * from './types/args/PostArgs';
48
+ export * from './types/data/Conversation';
43
49
  export * from './types/data/CursoredData';
50
+ export * from './types/data/DirectMessage';
51
+ export * from './types/data/Inbox';
44
52
  export * from './types/data/List';
45
53
  export * from './types/data/Notification';
46
54
  export * from './types/data/Tweet';
@@ -53,6 +61,7 @@ export { IErrorData as IRawErrorData, IErrorDetails as IRawErrorDetails } from '
53
61
  export { ILimitedVisibilityTweet as IRawLimitedVisibilityTweet } from './types/raw/base/LimitedVisibilityTweet';
54
62
  export { IList as IRawList } from './types/raw/base/List';
55
63
  export { IMedia as IRawMedia } from './types/raw/base/Media';
64
+ export { IMessage as IRawMessage } from './types/raw/base/Message';
56
65
  export { INotification as IRawNotification } from './types/raw/base/Notification';
57
66
  export { ISpace as IRawSpace } from './types/raw/base/Space';
58
67
  export { ITweet as IRawTweet } from './types/raw/base/Tweet';
@@ -61,6 +70,8 @@ export { IDataResult as IRawDataResult } from './types/raw/composite/DataResult'
61
70
  export { ITimelineTweet as IRawTimelineTweet } from './types/raw/composite/TimelineTweet';
62
71
  export { ITimelineUser as IRawTimelineUser } from './types/raw/composite/TimelineUser';
63
72
  export { IResponse as IRawResponse } from './types/raw/generic/Response';
73
+ export { IListMemberAddResponse as IRawListMemberAddResponse } from './types/raw/list/AddMember';
74
+ export { IListMemberRemoveResponse as IRawListMemberRemoveResponse } from './types/raw/list/RemoveMember';
64
75
  export { IListDetailsResponse as IRawListDetailsResponse } from './types/raw/list/Details';
65
76
  export { IListMembersResponse as IRawListMembersResponse } from './types/raw/list/Members';
66
77
  export { IListTweetsResponse as IRawListTweetsResponse } from './types/raw/list/Tweets';
@@ -102,3 +113,7 @@ export { IUserTweetsAndRepliesResponse as IRawUserTweetsAndRepliesResponse } fro
102
113
  export { IUserUnfollowResponse as IRawUserUnfollowResponse } from './types/raw/user/Unfollow';
103
114
  export * from './types/ErrorHandler';
104
115
  export * from './types/RettiwtConfig';
116
+ export { IConversationTimelineResponse as IRawConversationTimelineResponse } from './types/raw/dm/Conversation';
117
+ export { IInboxInitialResponse as IRawInboxInitialResponse } from './types/raw/dm/InboxInitial';
118
+ export { IInboxTimelineResponse as IRawInboxTimelineResponse } from './types/raw/dm/InboxTimeline';
119
+ export { IUserUpdatesResponse as IRawUserUpdatesResponse } from './types/raw/dm/UserUpdates';
@@ -1,18 +1,27 @@
1
1
  import { TweetRepliesSortType } from '../../enums/Tweet';
2
2
  import { IFetchArgs, ITweetFilter } from '../../types/args/FetchArgs';
3
3
 
4
+ import type { RawAnalyticsGranularity, RawAnalyticsMetric } from '../../enums/raw/Analytics';
4
5
  /**
5
6
  * Options specifying the data that is to be fetched.
6
7
  *
7
8
  * @public
8
9
  */
9
10
  export class FetchArgs implements IFetchArgs {
11
+ public activeConversationId?: string;
12
+ public conversationId?: string;
10
13
  public count?: number;
11
14
  public cursor?: string;
12
15
  public filter?: TweetFilter;
16
+ public fromTime?: Date;
17
+ public granularity?: RawAnalyticsGranularity;
13
18
  public id?: string;
14
19
  public ids?: string[];
20
+ public maxId?: string;
21
+ public metrics?: RawAnalyticsMetric[];
22
+ public showVerifiedFollowers?: boolean;
15
23
  public sortBy?: TweetRepliesSortType;
24
+ public toTime?: Date;
16
25
 
17
26
  /**
18
27
  * @param args - Additional user-defined arguments for fetching the resource.
@@ -24,6 +33,14 @@ export class FetchArgs implements IFetchArgs {
24
33
  this.cursor = args.cursor;
25
34
  this.filter = args.filter ? new TweetFilter(args.filter) : undefined;
26
35
  this.sortBy = args.sortBy;
36
+ this.fromTime = args.fromTime;
37
+ this.toTime = args.toTime;
38
+ this.granularity = args.granularity;
39
+ this.metrics = args.metrics;
40
+ this.showVerifiedFollowers = args.showVerifiedFollowers;
41
+ this.activeConversationId = args.activeConversationId;
42
+ this.conversationId = args.conversationId;
43
+ this.maxId = args.maxId;
27
44
  }
28
45
  }
29
46
 
@@ -9,6 +9,7 @@ export class PostArgs implements IPostArgs {
9
9
  public id?: string;
10
10
  public tweet?: NewTweet;
11
11
  public upload?: UploadArgs;
12
+ public userId?: string;
12
13
 
13
14
  /**
14
15
  * @param resource - The resource to be posted.
@@ -18,6 +19,7 @@ export class PostArgs implements IPostArgs {
18
19
  this.id = args.id;
19
20
  this.tweet = args.tweet ? new NewTweet(args.tweet) : undefined;
20
21
  this.upload = args.upload ? new UploadArgs(args.upload) : undefined;
22
+ this.userId = args.userId;
21
23
  }
22
24
  }
23
25
 
@@ -0,0 +1,97 @@
1
+ import { RawAnalyticsMetric } from '../../enums/raw/Analytics';
2
+ import { IAnalytics as IRawAnalytics } from '../../types/raw/base/Analytic';
3
+
4
+ import type { IAnalytics } from '../../types/data/Analytics';
5
+ import type { IAnalyticsMetric } from '../../types/raw/base/Analytic';
6
+
7
+ /**
8
+ * The details of the analytic result of the connected User.
9
+ *
10
+ * @public
11
+ */
12
+ export class Analytics implements IAnalytics {
13
+ /** The raw analytic details. */
14
+ private readonly _raw: IRawAnalytics;
15
+
16
+ public bookmarks: number;
17
+ public createQuote: number;
18
+ public createReply: number;
19
+ public createTweets: number;
20
+ public createdAt: string;
21
+ public engagements: number;
22
+ public followers: number;
23
+ public follows: number;
24
+ public impressions: number;
25
+ public likes: number;
26
+ public organicMetricsTimeSeries: IAnalyticsMetric[];
27
+ public profileVisits: number;
28
+ public replies: number;
29
+ public retweets: number;
30
+ public shares: number;
31
+ public unfollows: number;
32
+ public verifiedFollowers: number;
33
+
34
+ public constructor(analytics: IRawAnalytics) {
35
+ this._raw = { ...analytics };
36
+ this.organicMetricsTimeSeries = analytics.organic_metrics_time_series;
37
+ this.createdAt = new Date().toISOString();
38
+ this.followers = analytics.relationship_counts.followers;
39
+ this.verifiedFollowers = parseInt(analytics.verified_follower_count, 10);
40
+ this.impressions = this._reduceMetrics(RawAnalyticsMetric.IMPRESSIONS);
41
+ this.profileVisits = this._reduceMetrics(RawAnalyticsMetric.PROFILE_VISITS);
42
+ this.engagements = this._reduceMetrics(RawAnalyticsMetric.ENGAGEMENTS);
43
+ this.follows = this._reduceMetrics(RawAnalyticsMetric.FOLLOWS);
44
+ this.replies = this._reduceMetrics(RawAnalyticsMetric.REPLIES);
45
+ this.likes = this._reduceMetrics(RawAnalyticsMetric.LIKES);
46
+ this.retweets = this._reduceMetrics(RawAnalyticsMetric.RETWEETS);
47
+ this.bookmarks = this._reduceMetrics(RawAnalyticsMetric.BOOKMARK);
48
+ this.shares = this._reduceMetrics(RawAnalyticsMetric.SHARE);
49
+ this.createTweets = this._reduceMetrics(RawAnalyticsMetric.CREATE_TWEET);
50
+ this.createQuote = this._reduceMetrics(RawAnalyticsMetric.CREATE_QUOTE);
51
+ this.createReply = this._reduceMetrics(RawAnalyticsMetric.CREATE_REPLY);
52
+ this.unfollows = this._reduceMetrics(RawAnalyticsMetric.UNFOLLOWS);
53
+ }
54
+
55
+ /** The raw analytic details. */
56
+ public get raw(): IRawAnalytics {
57
+ return { ...this._raw };
58
+ }
59
+
60
+ /**
61
+ * Reduces the organic metrics time series to a total value for a specific metric type.
62
+ *
63
+ * @param metricType - metricType The type of metric to reduce.
64
+ * @returns the total value of the specified metric type across all time series.
65
+ */
66
+ private _reduceMetrics(metricType: RawAnalyticsMetric): number {
67
+ return this.organicMetricsTimeSeries.reduce((acc, metric) => {
68
+ const metricValue = metric.metric_values.find((m) => m.metric_type === (metricType as string));
69
+ return acc + (metricValue ? metricValue.metric_value : 0);
70
+ }, 0);
71
+ }
72
+
73
+ /**
74
+ * @returns A serializable JSON representation of `this` object.
75
+ */
76
+ public toJSON(): IAnalytics {
77
+ return {
78
+ createdAt: this.createdAt,
79
+ followers: this.followers,
80
+ verifiedFollowers: this.verifiedFollowers,
81
+ impressions: this.impressions,
82
+ profileVisits: this.profileVisits,
83
+ engagements: this.engagements,
84
+ follows: this.follows,
85
+ replies: this.replies,
86
+ likes: this.likes,
87
+ retweets: this.retweets,
88
+ bookmarks: this.bookmarks,
89
+ shares: this.shares,
90
+ createTweets: this.createTweets,
91
+ createQuote: this.createQuote,
92
+ unfollows: this.unfollows,
93
+ createReply: this.createReply,
94
+ organicMetricsTimeSeries: this.organicMetricsTimeSeries,
95
+ };
96
+ }
97
+ }
@@ -0,0 +1,344 @@
1
+ import { IConversation } from '../../types/data/Conversation';
2
+ import { IConversationTimelineResponse } from '../../types/raw/dm/Conversation';
3
+ import {
4
+ IInboxInitialResponse,
5
+ Conversation as RawConversation,
6
+ Conversations as RawConversations,
7
+ } from '../../types/raw/dm/InboxInitial';
8
+ import { IInboxTimelineResponse } from '../../types/raw/dm/InboxTimeline';
9
+
10
+ import { DirectMessage } from './DirectMessage';
11
+
12
+ /**
13
+ * Type guard to check if the response is an IConversationTimelineResponse
14
+ */
15
+ function isConversationTimelineResponse(
16
+ response: IConversationTimelineResponse | IInboxInitialResponse | IInboxTimelineResponse,
17
+ ): response is IConversationTimelineResponse {
18
+ return 'conversation_timeline' in response;
19
+ }
20
+
21
+ /**
22
+ * Type guard to check if the response is an IInboxInitialResponse
23
+ */
24
+ function isInboxInitialResponse(
25
+ response: IConversationTimelineResponse | IInboxInitialResponse | IInboxTimelineResponse,
26
+ ): response is IInboxInitialResponse {
27
+ return 'inbox_initial_state' in response;
28
+ }
29
+
30
+ /**
31
+ * Type guard to check if the response is an IInboxTimelineResponse
32
+ */
33
+ function isInboxTimelineResponse(
34
+ response: IConversationTimelineResponse | IInboxInitialResponse | IInboxTimelineResponse,
35
+ ): response is IInboxTimelineResponse {
36
+ return 'inbox_timeline' in response;
37
+ }
38
+
39
+ /**
40
+ * Extract typed conversation data from raw conversations object
41
+ */
42
+ function extractConversationData(rawConversations: RawConversations): Array<[string, RawConversation]> {
43
+ return Object.entries(rawConversations);
44
+ }
45
+
46
+ /**
47
+ * The details of a single conversation.
48
+ *
49
+ * @public
50
+ */
51
+ export class Conversation implements IConversation {
52
+ /** The raw conversation details. */
53
+ private readonly _raw: RawConversation;
54
+
55
+ public avatarUrl?: string;
56
+ public hasMore: boolean;
57
+ public id: string;
58
+ public lastActivityAt: string;
59
+ public lastMessageId?: string;
60
+ public messages: DirectMessage[];
61
+ public muted: boolean;
62
+ public name?: string;
63
+ public notificationsDisabled: boolean;
64
+ public participants: string[];
65
+ public trusted: boolean;
66
+ public type: 'ONE_TO_ONE' | 'GROUP_DM';
67
+
68
+ /**
69
+ * @param conversation - The raw conversation details from the API response.
70
+ * @param messages - Array of messages in this conversation.
71
+ */
72
+ public constructor(conversation: unknown, messages: DirectMessage[] = []) {
73
+ this._raw = conversation as RawConversation;
74
+
75
+ const conv = conversation as Record<string, unknown>;
76
+
77
+ this.id = conv.conversation_id && typeof conv.conversation_id === 'string' ? conv.conversation_id : '';
78
+ this.type = this._parseConversationType(conv.type);
79
+ this.participants = this._parseParticipants(conv.participants);
80
+ this.name = conv.name && typeof conv.name === 'string' ? conv.name : undefined;
81
+ this.avatarUrl = this._parseAvatarUrl(conv);
82
+ this.trusted = Boolean(conv.trusted);
83
+ this.muted = Boolean(conv.muted);
84
+ this.notificationsDisabled = Boolean(conv.notifications_disabled);
85
+ this.lastActivityAt = this._parseTimestamp(conv.sort_timestamp);
86
+ this.lastMessageId =
87
+ conv.sort_event_id && typeof conv.sort_event_id === 'string' ? conv.sort_event_id : undefined;
88
+ this.hasMore = conv.status === 'HAS_MORE';
89
+ this.messages = messages;
90
+ }
91
+
92
+ /** The raw conversation details. */
93
+ public get raw(): RawConversation {
94
+ return this._raw;
95
+ }
96
+
97
+ /**
98
+ * Parse avatar URL from conversation data
99
+ */
100
+ private _parseAvatarUrl(conv: Record<string, unknown>): string | undefined {
101
+ // Try avatar_image_https first
102
+ if (conv.avatar_image_https && typeof conv.avatar_image_https === 'string') {
103
+ return conv.avatar_image_https;
104
+ }
105
+
106
+ // Try nested avatar.image.original_info.url
107
+ const avatar = conv.avatar as Record<string, unknown> | undefined;
108
+ const image = avatar?.image as Record<string, unknown> | undefined;
109
+ const originalInfo = image?.original_info as Record<string, unknown> | undefined;
110
+
111
+ if (originalInfo?.url && typeof originalInfo.url === 'string') {
112
+ return originalInfo.url;
113
+ }
114
+
115
+ return undefined;
116
+ }
117
+
118
+ /**
119
+ * Parse conversation type with proper fallback
120
+ */
121
+ private _parseConversationType(type: unknown): 'ONE_TO_ONE' | 'GROUP_DM' {
122
+ if (type === 'ONE_TO_ONE' || type === 'GROUP_DM') {
123
+ return type;
124
+ }
125
+ return 'ONE_TO_ONE';
126
+ }
127
+
128
+ /**
129
+ * Parse participants array with type safety
130
+ */
131
+ private _parseParticipants(participants: unknown): string[] {
132
+ if (!Array.isArray(participants)) {
133
+ return [];
134
+ }
135
+
136
+ return participants
137
+ .map((p) => {
138
+ if (p && typeof p === 'object' && 'user_id' in p) {
139
+ // eslint-disable-next-line @typescript-eslint/naming-convention
140
+ const participantObj = p as { user_id: unknown };
141
+ if (typeof participantObj.user_id === 'string') {
142
+ return participantObj.user_id;
143
+ }
144
+ }
145
+ return '';
146
+ })
147
+ .filter(Boolean);
148
+ }
149
+
150
+ /**
151
+ * Parse timestamp with proper fallback
152
+ */
153
+ private _parseTimestamp(timestamp: unknown): string {
154
+ if (timestamp && (typeof timestamp === 'string' || typeof timestamp === 'number')) {
155
+ const date = new Date(Number(timestamp));
156
+ if (!isNaN(date.getTime())) {
157
+ return date.toISOString();
158
+ }
159
+ }
160
+ return new Date().toISOString();
161
+ }
162
+
163
+ /**
164
+ * Extracts a single conversation from conversation timeline response.
165
+ *
166
+ * @param response - The raw response data.
167
+ *
168
+ * @returns The deserialized conversation with full message history.
169
+ */
170
+ public static fromConversationTimeline(response: IConversationTimelineResponse): Conversation | undefined {
171
+ if (!response.conversation_timeline?.conversations) {
172
+ return undefined;
173
+ }
174
+
175
+ const rawConversations = response.conversation_timeline.conversations;
176
+ const entries = response.conversation_timeline.entries ?? [];
177
+
178
+ // Extract messages from entries
179
+ const messages: DirectMessage[] = [];
180
+ for (const entry of entries) {
181
+ if ('message' in entry && entry.message) {
182
+ messages.push(new DirectMessage(entry.message));
183
+ }
184
+ }
185
+
186
+ // Get the first (and typically only) conversation
187
+ const conversationEntries = extractConversationData(rawConversations);
188
+ const firstEntry = conversationEntries[0];
189
+
190
+ if (firstEntry) {
191
+ const [, conversationData] = firstEntry;
192
+ return new Conversation(conversationData, messages);
193
+ }
194
+
195
+ return undefined;
196
+ }
197
+
198
+ /**
199
+ * Extracts conversations from inbox initial state response.
200
+ *
201
+ * @param response - The raw response data.
202
+ *
203
+ * @returns The deserialized list of conversations with their preview messages.
204
+ */
205
+ public static listFromInboxInitial(response: IInboxInitialResponse): Conversation[] {
206
+ const conversations: Conversation[] = [];
207
+
208
+ if (!response.inbox_initial_state?.conversations) {
209
+ return conversations;
210
+ }
211
+
212
+ const rawConversations = response.inbox_initial_state.conversations;
213
+ const entries = response.inbox_initial_state.entries ?? [];
214
+
215
+ // Group messages by conversation ID
216
+ const messagesByConversation = new Map<string, DirectMessage[]>();
217
+ for (const entry of entries) {
218
+ if ('message' in entry && entry.message) {
219
+ const message = new DirectMessage(entry.message);
220
+ const convId = message.conversationId;
221
+ if (convId) {
222
+ if (!messagesByConversation.has(convId)) {
223
+ messagesByConversation.set(convId, []);
224
+ }
225
+ messagesByConversation.get(convId)!.push(message);
226
+ }
227
+ }
228
+ }
229
+
230
+ // Create conversations with their messages
231
+ const conversationEntries = extractConversationData(rawConversations);
232
+ for (const [, conversation] of conversationEntries) {
233
+ const convId = (conversation as unknown as Record<string, unknown>).conversation_id as string;
234
+ const messages = messagesByConversation.get(convId) ?? [];
235
+ conversations.push(new Conversation(conversation, messages));
236
+ }
237
+
238
+ return conversations;
239
+ }
240
+
241
+ /**
242
+ * Extracts conversations from inbox timeline response.
243
+ *
244
+ * @param response - The raw response data.
245
+ *
246
+ * @returns The deserialized list of conversations with their messages.
247
+ */
248
+ public static listFromInboxTimeline(response: IInboxTimelineResponse): Conversation[] {
249
+ const conversations: Conversation[] = [];
250
+
251
+ if (!response.inbox_timeline?.conversations) {
252
+ return conversations;
253
+ }
254
+
255
+ const rawConversations = response.inbox_timeline.conversations;
256
+ const entries = response.inbox_timeline.entries ?? [];
257
+
258
+ // Group messages by conversation ID
259
+ const messagesByConversation = new Map<string, DirectMessage[]>();
260
+ for (const entry of entries) {
261
+ if ('message' in entry && entry.message) {
262
+ const message = new DirectMessage(entry.message);
263
+ const convId = message.conversationId;
264
+ if (convId) {
265
+ if (!messagesByConversation.has(convId)) {
266
+ messagesByConversation.set(convId, []);
267
+ }
268
+ messagesByConversation.get(convId)!.push(message);
269
+ }
270
+ }
271
+ }
272
+
273
+ // Create conversations with their messages
274
+ const conversationEntries = extractConversationData(rawConversations);
275
+ for (const [, conversation] of conversationEntries) {
276
+ const convId = (conversation as unknown as Record<string, unknown>).conversation_id as string;
277
+ const messages = messagesByConversation.get(convId) ?? [];
278
+ conversations.push(new Conversation(conversation, messages));
279
+ }
280
+
281
+ return conversations;
282
+ }
283
+
284
+ /**
285
+ * Generic method to extract conversations from any supported response type
286
+ */
287
+ public static listFromResponse(
288
+ response: IConversationTimelineResponse | IInboxInitialResponse | IInboxTimelineResponse,
289
+ ): Conversation[] {
290
+ if (isConversationTimelineResponse(response)) {
291
+ const conversation = Conversation.fromConversationTimeline(response);
292
+ return conversation ? [conversation] : [];
293
+ } else if (isInboxInitialResponse(response)) {
294
+ return Conversation.listFromInboxInitial(response);
295
+ } else if (isInboxTimelineResponse(response)) {
296
+ return Conversation.listFromInboxTimeline(response);
297
+ }
298
+ return [];
299
+ }
300
+
301
+ /**
302
+ * Get the other participant's ID (only for one-to-one conversations)
303
+ */
304
+ public getOtherParticipant(currentUserId: string): string | undefined {
305
+ if (!this.isOneToOne() || this.participants.length !== 2) {
306
+ return undefined;
307
+ }
308
+ return this.participants.find((id) => id !== currentUserId);
309
+ }
310
+
311
+ /**
312
+ * Check if this conversation is a group DM
313
+ */
314
+ public isGroupDM(): boolean {
315
+ return this.type === 'GROUP_DM';
316
+ }
317
+
318
+ /**
319
+ * Check if this conversation is one-to-one
320
+ */
321
+ public isOneToOne(): boolean {
322
+ return this.type === 'ONE_TO_ONE';
323
+ }
324
+
325
+ /**
326
+ * @returns A serializable JSON representation of `this` object.
327
+ */
328
+ public toJSON(): IConversation {
329
+ return {
330
+ avatarUrl: this.avatarUrl,
331
+ hasMore: this.hasMore,
332
+ id: this.id,
333
+ lastActivityAt: this.lastActivityAt,
334
+ lastMessageId: this.lastMessageId,
335
+ messages: this.messages.map((msg) => msg.toJSON()),
336
+ muted: this.muted,
337
+ name: this.name,
338
+ notificationsDisabled: this.notificationsDisabled,
339
+ participants: this.participants,
340
+ trusted: this.trusted,
341
+ type: this.type,
342
+ };
343
+ }
344
+ }
@@ -5,6 +5,8 @@ import { findByFilter } from '../../helper/JsonUtils';
5
5
  import { ICursoredData } from '../../types/data/CursoredData';
6
6
  import { ICursor as IRawCursor } from '../../types/raw/base/Cursor';
7
7
 
8
+ import { List } from './List';
9
+
8
10
  import { Notification } from './Notification';
9
11
  import { Tweet } from './Tweet';
10
12
  import { User } from './User';
@@ -16,7 +18,7 @@ import { User } from './User';
16
18
  *
17
19
  * @public
18
20
  */
19
- export class CursoredData<T extends Notification | Tweet | User> implements ICursoredData<T> {
21
+ export class CursoredData<T extends Notification | Tweet | User | List> implements ICursoredData<T> {
20
22
  public list: T[];
21
23
  public next: string;
22
24
 
@@ -35,9 +37,12 @@ export class CursoredData<T extends Notification | Tweet | User> implements ICur
35
37
  } else if (type == BaseType.USER) {
36
38
  this.list = User.timeline(response) as T[];
37
39
  this.next = findByFilter<IRawCursor>(response, 'cursorType', 'Bottom')[0]?.value ?? '';
40
+ } else if (type == BaseType.LIST) {
41
+ this.list = List.timeline(response) as T[];
42
+ this.next = findByFilter<IRawCursor>(response, 'cursorType', 'Bottom')[0]?.value ?? '';
38
43
  } else if (type == BaseType.NOTIFICATION) {
39
44
  this.list = Notification.list(response) as T[];
40
- this.next = findByFilter<IRawCursor>(response, 'cursorType', 'Top')[0]?.value ?? '';
45
+ this.next = findByFilter<IRawCursor>(response, 'cursorType', 'Bottom')[0]?.value ?? '';
41
46
  }
42
47
  }
43
48