@glagan/rettiwt-api 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/.eslintrc.js +166 -0
  2. package/.gitattributes +3 -0
  3. package/.github/FUNDING.yml +4 -0
  4. package/.github/ISSUE_TEMPLATE/bug-report.yml +57 -0
  5. package/.github/ISSUE_TEMPLATE/feature-request.yml +20 -0
  6. package/.github/ISSUE_TEMPLATE/question.yml +15 -0
  7. package/.github/PULL_REQUEST_TEMPLATE.md +32 -0
  8. package/.github/workflows/ci.yml +32 -0
  9. package/.github/workflows/publish.yml +23 -0
  10. package/.nvmrc +1 -0
  11. package/.prettierignore +3 -0
  12. package/.prettierrc +13 -0
  13. package/LICENSE +21 -0
  14. package/README.md +566 -0
  15. package/dist/cli.js +43 -0
  16. package/eslint.config.mjs +17 -0
  17. package/package.json +50 -0
  18. package/src/Rettiwt.ts +97 -0
  19. package/src/cli.ts +48 -0
  20. package/src/collections/Extractors.ts +155 -0
  21. package/src/collections/Groups.ts +81 -0
  22. package/src/collections/Requests.ts +89 -0
  23. package/src/collections/Tweet.ts +17 -0
  24. package/src/commands/DirectMessage.ts +62 -0
  25. package/src/commands/List.ts +90 -0
  26. package/src/commands/Tweet.ts +437 -0
  27. package/src/commands/User.ts +367 -0
  28. package/src/enums/Api.ts +10 -0
  29. package/src/enums/Authentication.ts +10 -0
  30. package/src/enums/Data.ts +13 -0
  31. package/src/enums/Logging.ts +14 -0
  32. package/src/enums/Media.ts +10 -0
  33. package/src/enums/Notification.ts +12 -0
  34. package/src/enums/Resource.ts +69 -0
  35. package/src/enums/Tweet.ts +8 -0
  36. package/src/enums/raw/Analytics.ts +32 -0
  37. package/src/enums/raw/Media.ts +10 -0
  38. package/src/enums/raw/Notification.ts +11 -0
  39. package/src/enums/raw/Tweet.ts +20 -0
  40. package/src/helper/CliUtils.ts +17 -0
  41. package/src/helper/JsonUtils.ts +70 -0
  42. package/src/index.ts +128 -0
  43. package/src/models/RettiwtConfig.ts +101 -0
  44. package/src/models/args/FetchArgs.ts +169 -0
  45. package/src/models/args/PostArgs.ts +93 -0
  46. package/src/models/args/ProfileArgs.ts +68 -0
  47. package/src/models/auth/AuthCookie.ts +58 -0
  48. package/src/models/auth/AuthCredential.ts +83 -0
  49. package/src/models/data/Analytics.ts +97 -0
  50. package/src/models/data/BookmarkFolder.ts +73 -0
  51. package/src/models/data/Conversation.ts +344 -0
  52. package/src/models/data/CursoredData.ts +64 -0
  53. package/src/models/data/DirectMessage.ts +335 -0
  54. package/src/models/data/Inbox.ts +124 -0
  55. package/src/models/data/List.ts +113 -0
  56. package/src/models/data/Notification.ts +84 -0
  57. package/src/models/data/Tweet.ts +388 -0
  58. package/src/models/data/User.ts +187 -0
  59. package/src/models/errors/TwitterError.ts +65 -0
  60. package/src/models/params/Variables.ts +62 -0
  61. package/src/requests/DirectMessage.ts +229 -0
  62. package/src/requests/List.ts +203 -0
  63. package/src/requests/Media.ts +67 -0
  64. package/src/requests/Tweet.ts +607 -0
  65. package/src/requests/User.ts +1191 -0
  66. package/src/services/internal/AuthService.ts +115 -0
  67. package/src/services/internal/ErrorService.ts +41 -0
  68. package/src/services/internal/LogService.ts +34 -0
  69. package/src/services/public/DirectMessageService.ts +159 -0
  70. package/src/services/public/FetcherService.ts +366 -0
  71. package/src/services/public/ListService.ts +241 -0
  72. package/src/services/public/TweetService.ts +886 -0
  73. package/src/services/public/UserService.ts +1154 -0
  74. package/src/types/ErrorHandler.ts +13 -0
  75. package/src/types/Fetch.ts +3 -0
  76. package/src/types/RettiwtConfig.ts +48 -0
  77. package/src/types/args/FetchArgs.ts +233 -0
  78. package/src/types/args/PostArgs.ts +142 -0
  79. package/src/types/args/ProfileArgs.ts +33 -0
  80. package/src/types/auth/AuthCookie.ts +22 -0
  81. package/src/types/auth/AuthCredential.ts +28 -0
  82. package/src/types/auth/TransactionHeader.ts +8 -0
  83. package/src/types/data/Analytics.ts +58 -0
  84. package/src/types/data/BookmarkFolder.ts +12 -0
  85. package/src/types/data/Conversation.ts +44 -0
  86. package/src/types/data/CursoredData.ts +24 -0
  87. package/src/types/data/DirectMessage.ts +33 -0
  88. package/src/types/data/Inbox.ts +23 -0
  89. package/src/types/data/List.ts +33 -0
  90. package/src/types/data/Notification.ts +26 -0
  91. package/src/types/data/Tweet.ts +99 -0
  92. package/src/types/data/User.ts +54 -0
  93. package/src/types/errors/TwitterError.ts +37 -0
  94. package/src/types/params/Variables.ts +41 -0
  95. package/src/types/raw/base/Analytic.ts +32 -0
  96. package/src/types/raw/base/BookmarkFolder.ts +12 -0
  97. package/src/types/raw/base/Cursor.ts +13 -0
  98. package/src/types/raw/base/Error.ts +38 -0
  99. package/src/types/raw/base/LimitedVisibilityTweet.ts +40 -0
  100. package/src/types/raw/base/List.ts +50 -0
  101. package/src/types/raw/base/Media.ts +53 -0
  102. package/src/types/raw/base/Message.ts +22 -0
  103. package/src/types/raw/base/Notification.ts +66 -0
  104. package/src/types/raw/base/Space.ts +35 -0
  105. package/src/types/raw/base/Tweet.ts +139 -0
  106. package/src/types/raw/base/User.ts +182 -0
  107. package/src/types/raw/composite/DataResult.ts +8 -0
  108. package/src/types/raw/composite/TimelineList.ts +10 -0
  109. package/src/types/raw/composite/TimelineTweet.ts +14 -0
  110. package/src/types/raw/composite/TimelineUser.ts +13 -0
  111. package/src/types/raw/dm/Conversation.ts +59 -0
  112. package/src/types/raw/dm/InboxInitial.ts +155 -0
  113. package/src/types/raw/dm/InboxTimeline.ts +301 -0
  114. package/src/types/raw/dm/UserUpdates.ts +46 -0
  115. package/src/types/raw/generic/Response.ts +10 -0
  116. package/src/types/raw/list/AddMember.ts +175 -0
  117. package/src/types/raw/list/Details.ts +176 -0
  118. package/src/types/raw/list/Members.ts +154 -0
  119. package/src/types/raw/list/RemoveMember.ts +174 -0
  120. package/src/types/raw/list/Tweets.ts +2296 -0
  121. package/src/types/raw/media/FinalizeUpload.ts +20 -0
  122. package/src/types/raw/media/InitalizeUpload.ts +12 -0
  123. package/src/types/raw/media/LiveVideoStream.ts +21 -0
  124. package/src/types/raw/space/Details.ts +359 -0
  125. package/src/types/raw/tweet/Bookmark.ts +14 -0
  126. package/src/types/raw/tweet/Details.ts +210 -0
  127. package/src/types/raw/tweet/DetailsBulk.ts +338 -0
  128. package/src/types/raw/tweet/Like.ts +14 -0
  129. package/src/types/raw/tweet/Likers.ts +200 -0
  130. package/src/types/raw/tweet/Post.ts +150 -0
  131. package/src/types/raw/tweet/Replies.ts +539 -0
  132. package/src/types/raw/tweet/Retweet.ts +31 -0
  133. package/src/types/raw/tweet/Retweeters.ts +208 -0
  134. package/src/types/raw/tweet/Schedule.ts +18 -0
  135. package/src/types/raw/tweet/Search.ts +597 -0
  136. package/src/types/raw/tweet/Unbookmark.ts +14 -0
  137. package/src/types/raw/tweet/Unlike.ts +14 -0
  138. package/src/types/raw/tweet/Unpost.ts +20 -0
  139. package/src/types/raw/tweet/Unretweet.ts +31 -0
  140. package/src/types/raw/tweet/Unschedule.ts +14 -0
  141. package/src/types/raw/user/Affiliates.ts +179 -0
  142. package/src/types/raw/user/Analytics.ts +23 -0
  143. package/src/types/raw/user/BookmarkFolderTweets.ts +53 -0
  144. package/src/types/raw/user/BookmarkFolders.ts +41 -0
  145. package/src/types/raw/user/Bookmarks.ts +637 -0
  146. package/src/types/raw/user/Details.ts +185 -0
  147. package/src/types/raw/user/DetailsBulk.ts +104 -0
  148. package/src/types/raw/user/Follow.ts +280 -0
  149. package/src/types/raw/user/Followed.ts +1942 -0
  150. package/src/types/raw/user/Followers.ts +215 -0
  151. package/src/types/raw/user/Following.ts +215 -0
  152. package/src/types/raw/user/Highlights.ts +1287 -0
  153. package/src/types/raw/user/Likes.ts +1254 -0
  154. package/src/types/raw/user/Lists.ts +378 -0
  155. package/src/types/raw/user/Media.ts +1738 -0
  156. package/src/types/raw/user/Notifications.ts +499 -0
  157. package/src/types/raw/user/ProfileUpdate.ts +80 -0
  158. package/src/types/raw/user/Recommended.ts +2319 -0
  159. package/src/types/raw/user/Scheduled.ts +37 -0
  160. package/src/types/raw/user/Search.ts +230 -0
  161. package/src/types/raw/user/Subscriptions.ts +176 -0
  162. package/src/types/raw/user/Tweets.ts +1254 -0
  163. package/src/types/raw/user/TweetsAndReplies.ts +1254 -0
  164. package/src/types/raw/user/Unfollow.ts +280 -0
  165. package/tsconfig.json +97 -0
@@ -0,0 +1,1154 @@
1
+ import { Extractors } from '../../collections/Extractors';
2
+ import { RawAnalyticsGranularity, RawAnalyticsMetric } from '../../enums/raw/Analytics';
3
+ import { ResourceType } from '../../enums/Resource';
4
+ import { ProfileUpdateOptions } from '../../models/args/ProfileArgs';
5
+ import { Analytics } from '../../models/data/Analytics';
6
+ import { BookmarkFolder } from '../../models/data/BookmarkFolder';
7
+ import { CursoredData } from '../../models/data/CursoredData';
8
+ import { List } from '../../models/data/List';
9
+ import { Notification } from '../../models/data/Notification';
10
+ import { Tweet } from '../../models/data/Tweet';
11
+ import { User } from '../../models/data/User';
12
+ import { RettiwtConfig } from '../../models/RettiwtConfig';
13
+ import { IProfileUpdateOptions } from '../../types/args/ProfileArgs';
14
+ import { IUserAffiliatesResponse } from '../../types/raw/user/Affiliates';
15
+ import { IUserAnalyticsResponse } from '../../types/raw/user/Analytics';
16
+ import { IUserBookmarkFoldersResponse } from '../../types/raw/user/BookmarkFolders';
17
+ import { IUserBookmarkFolderTweetsResponse } from '../../types/raw/user/BookmarkFolderTweets';
18
+ import { IUserBookmarksResponse } from '../../types/raw/user/Bookmarks';
19
+ import { IUserDetailsResponse } from '../../types/raw/user/Details';
20
+ import { IUserDetailsBulkResponse } from '../../types/raw/user/DetailsBulk';
21
+ import { IUserFollowResponse } from '../../types/raw/user/Follow';
22
+ import { IUserFollowedResponse } from '../../types/raw/user/Followed';
23
+ import { IUserFollowersResponse } from '../../types/raw/user/Followers';
24
+ import { IUserFollowingResponse } from '../../types/raw/user/Following';
25
+ import { IUserHighlightsResponse } from '../../types/raw/user/Highlights';
26
+ import { IUserLikesResponse } from '../../types/raw/user/Likes';
27
+ import { IUserListsResponse } from '../../types/raw/user/Lists';
28
+ import { IUserMediaResponse } from '../../types/raw/user/Media';
29
+ import { IUserNotificationsResponse } from '../../types/raw/user/Notifications';
30
+ import { IUserProfileUpdateResponse } from '../../types/raw/user/ProfileUpdate';
31
+ import { IUserRecommendedResponse } from '../../types/raw/user/Recommended';
32
+ import { IUserSearchResponse } from '../../types/raw/user/Search';
33
+ import { IUserSubscriptionsResponse } from '../../types/raw/user/Subscriptions';
34
+ import { IUserTweetsResponse } from '../../types/raw/user/Tweets';
35
+ import { IUserTweetsAndRepliesResponse } from '../../types/raw/user/TweetsAndReplies';
36
+ import { IUserUnfollowResponse } from '../../types/raw/user/Unfollow';
37
+
38
+ import { FetcherService } from './FetcherService';
39
+
40
+ /**
41
+ * Handles interacting with resources related to user account
42
+ *
43
+ * @public
44
+ */
45
+ export class UserService extends FetcherService {
46
+ /**
47
+ * @param config - The config object for configuring the Rettiwt instance.
48
+ *
49
+ * @internal
50
+ */
51
+ public constructor(config: RettiwtConfig) {
52
+ super(config);
53
+ }
54
+
55
+ /**
56
+ * Get the list affiliates of a user.
57
+ *
58
+ * @param id - The ID of the target user. If no id is provided, the logged-in user's id is used.
59
+ * @param count - The number of affiliates to fetch, must be \<= 100.
60
+ * @param cursor - The cursor to the batch of affiliates to fetch.
61
+ *
62
+ * @returns The list of users affiliated to the target user.
63
+ *
64
+ * @example
65
+ *
66
+ * ```ts
67
+ * import { Rettiwt } from 'rettiwt-api';
68
+ *
69
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
70
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
71
+ *
72
+ * // Fetching the first 100 affiliates of the User with id '1234567890'
73
+ * rettiwt.user.affiliates('1234567890')
74
+ * .then(res => {
75
+ * console.log(res);
76
+ * })
77
+ * .catch(err => {
78
+ * console.log(err);
79
+ * });
80
+ * ```
81
+ */
82
+ public async affiliates(id?: string, count?: number, cursor?: string): Promise<CursoredData<User>> {
83
+ const resource = ResourceType.USER_AFFILIATES;
84
+
85
+ // Fetching raw list of affiliates
86
+ const response = await this.request<IUserAffiliatesResponse>(resource, {
87
+ id: id ?? this.config.userId,
88
+ count: count,
89
+ cursor: cursor,
90
+ });
91
+
92
+ // Deserializing response
93
+ const data = Extractors[resource](response);
94
+
95
+ return data;
96
+ }
97
+
98
+ /**
99
+ * Get the analytics overview of the logged in user.
100
+ *
101
+ * @param fromTime - The start time of the analytics period. Defaults to 7 days ago.
102
+ * @param toTime - The end time of the analytics period. Defaults to now.
103
+ * @param granularity - The granularity of the analytics data. Defaults to daily.
104
+ * @param metrics - The metrics to include in the analytics data. Defaults to all available metrics available.
105
+ * @param showVerifiedFollowers - Whether to include verified follower count and relationship counts in the response. Defaults to true.
106
+ *
107
+ * @returns The raw analytics data of the user.
108
+ *
109
+ * @example
110
+ *
111
+ * ```ts
112
+ * import { Rettiwt } from 'rettiwt-api';
113
+ *
114
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
115
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
116
+ *
117
+ * // Fetching the analytics overview of the logged in user
118
+ * rettiwt.user.analytics().then(res => {
119
+ * console.log(res);
120
+ * })
121
+ * .catch(err => {
122
+ * console.log(err);
123
+ * });
124
+ * ```
125
+ */
126
+ public async analytics(
127
+ fromTime?: Date,
128
+ toTime?: Date,
129
+ granularity?: RawAnalyticsGranularity,
130
+ metrics?: RawAnalyticsMetric[],
131
+ showVerifiedFollowers?: boolean,
132
+ ): Promise<Analytics> {
133
+ const resource = ResourceType.USER_ANALYTICS;
134
+
135
+ // Define default values if not provided
136
+ fromTime = fromTime ?? new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
137
+ toTime = toTime ?? new Date();
138
+ granularity = granularity ?? RawAnalyticsGranularity.DAILY;
139
+ metrics = metrics ?? Object.values(RawAnalyticsMetric);
140
+ showVerifiedFollowers = showVerifiedFollowers ?? true;
141
+
142
+ // Fetching raw analytics
143
+ const response = await this.request<IUserAnalyticsResponse>(resource, {
144
+ fromTime,
145
+ toTime,
146
+ granularity,
147
+ metrics,
148
+ showVerifiedFollowers,
149
+ });
150
+
151
+ const data = Extractors[resource](response);
152
+
153
+ return data;
154
+ }
155
+
156
+ /**
157
+ * Get the list of tweets in a specific bookmark folder of the logged in user.
158
+ *
159
+ * @param folderId - The ID of the bookmark folder.
160
+ * @param count - The number of tweets to fetch, must be \<= 100.
161
+ * @param cursor - The cursor to the batch of tweets to fetch.
162
+ *
163
+ * @returns The list of tweets in the bookmark folder.
164
+ *
165
+ * @example
166
+ *
167
+ * ```ts
168
+ * import { Rettiwt } from 'rettiwt-api';
169
+ *
170
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
171
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
172
+ *
173
+ * // Fetching the first 100 tweets from bookmark folder with ID '2001752149647049173'
174
+ * rettiwt.user.bookmarkFolderTweets('2001752149647049173')
175
+ * .then(res => {
176
+ * console.log(res);
177
+ * })
178
+ * .catch(err => {
179
+ * console.log(err);
180
+ * });
181
+ * ```
182
+ */
183
+ public async bookmarkFolderTweets(folderId: string, count?: number, cursor?: string): Promise<CursoredData<Tweet>> {
184
+ const resource = ResourceType.USER_BOOKMARK_FOLDER_TWEETS;
185
+
186
+ // Fetching raw list of tweets from folder
187
+ const response = await this.request<IUserBookmarkFolderTweetsResponse>(resource, {
188
+ id: folderId,
189
+ count: count,
190
+ cursor: cursor,
191
+ });
192
+
193
+ // Deserializing response
194
+ const data = Extractors[resource](response);
195
+
196
+ return data;
197
+ }
198
+
199
+ /**
200
+ * Get the list of bookmark folders of the logged in user.
201
+ *
202
+ * @param cursor - The cursor to the batch of bookmark folders to fetch.
203
+ *
204
+ * @returns The list of bookmark folders.
205
+ *
206
+ * @example
207
+ *
208
+ * ```ts
209
+ * import { Rettiwt } from 'rettiwt-api';
210
+ *
211
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
212
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
213
+ *
214
+ * // Fetching all bookmark folders of the logged in user
215
+ * rettiwt.user.bookmarkFolders()
216
+ * .then(res => {
217
+ * console.log(res);
218
+ * })
219
+ * .catch(err => {
220
+ * console.log(err);
221
+ * });
222
+ * ```
223
+ */
224
+ public async bookmarkFolders(cursor?: string): Promise<CursoredData<BookmarkFolder>> {
225
+ const resource = ResourceType.USER_BOOKMARK_FOLDERS;
226
+
227
+ // Fetching raw list of bookmark folders
228
+ const response = await this.request<IUserBookmarkFoldersResponse>(resource, {
229
+ cursor: cursor,
230
+ });
231
+
232
+ // Deserializing response
233
+ const data = Extractors[resource](response);
234
+
235
+ return data;
236
+ }
237
+
238
+ /**
239
+ * Get the list of bookmarks of the logged in user.
240
+ *
241
+ * @param count - The number of bookmakrs to fetch, must be \<= 100.
242
+ * @param cursor - The cursor to the batch of bookmarks to fetch.
243
+ *
244
+ * @returns The list of tweets bookmarked by the target user.
245
+ *
246
+ * @example
247
+ *
248
+ * ```ts
249
+ * import { Rettiwt } from 'rettiwt-api';
250
+ *
251
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
252
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
253
+ *
254
+ * // Fetching the most recent 100 liked Tweets of the logged in User
255
+ * rettiwt.user.bookmarks()
256
+ * .then(res => {
257
+ * console.log(res);
258
+ * })
259
+ * .catch(err => {
260
+ * console.log(err);
261
+ * });
262
+ * ```
263
+ */
264
+ public async bookmarks(count?: number, cursor?: string): Promise<CursoredData<Tweet>> {
265
+ const resource = ResourceType.USER_BOOKMARKS;
266
+
267
+ // Fetching raw list of likes
268
+ const response = await this.request<IUserBookmarksResponse>(resource, {
269
+ count: count,
270
+ cursor: cursor,
271
+ });
272
+
273
+ // Deserializing response
274
+ const data = Extractors[resource](response);
275
+
276
+ return data;
277
+ }
278
+
279
+ /**
280
+ * Get the details of the logged in user.
281
+ *
282
+ * @returns The details of the user.
283
+ *
284
+ * @example
285
+ *
286
+ * ```ts
287
+ * import { Rettiwt } from 'rettiwt-api';
288
+ *
289
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
290
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
291
+ *
292
+ * // Fetching the details of the User
293
+ * rettiwt.user.details()
294
+ * .then(res => {
295
+ * console.log(res);
296
+ * })
297
+ * .catch(err => {
298
+ * console.log(err);
299
+ * });
300
+ * ```
301
+ */
302
+ public async details(): Promise<User | undefined>;
303
+
304
+ /**
305
+ * Get the details of a user.
306
+ *
307
+ * @param id - The ID/username of the target user.
308
+ *
309
+ * @returns The details of the user.
310
+ *
311
+ * @example
312
+ *
313
+ * #### Fetching the details of a single user using username
314
+ * ```ts
315
+ * import { Rettiwt } from 'rettiwt-api';
316
+ *
317
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
318
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
319
+ *
320
+ * // Fetching the details of the User with username 'user1' or '@user1'
321
+ * rettiwt.user.details('user1') // or @user1
322
+ * .then(res => {
323
+ * console.log(res);
324
+ * })
325
+ * .catch(err => {
326
+ * console.log(err);
327
+ * });
328
+ * ```
329
+ *
330
+ * @example
331
+ *
332
+ * #### Fetching the details of a single user using ID
333
+ * ```ts
334
+ * import { Rettiwt } from 'rettiwt-api';
335
+ *
336
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
337
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
338
+ *
339
+ * // Fetching the details of the User with id '1234567890'
340
+ * rettiwt.user.details('1234567890')
341
+ * .then(res => {
342
+ * console.log(res); # 'res' is a single tweet
343
+ * })
344
+ * .catch(err => {
345
+ * console.log(err);
346
+ * });
347
+ * ```
348
+ */
349
+ public async details(id: string): Promise<User | undefined>;
350
+
351
+ /**
352
+ * Get the details of multiple users in bulk.
353
+ *
354
+ * @param id - The list of IDs of the target users.
355
+ *
356
+ * @returns The details of the users.
357
+ *
358
+ * @example
359
+ *
360
+ * ```ts
361
+ * import { Rettiwt } from 'rettiwt-api';
362
+ *
363
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
364
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
365
+ *
366
+ * // Fetching the details of the users with IDs '123', '456', '789'
367
+ * rettiwt.user.details(['123', '456', '789'])
368
+ * .then(res => {
369
+ * console.log(res); # 'res' is an array of users
370
+ * })
371
+ * .catch(err => {
372
+ * console.log(err);
373
+ * });
374
+ * ```
375
+ */
376
+ public async details(id: string[]): Promise<User[]>;
377
+
378
+ public async details(id?: string | string[]): Promise<User | User[] | undefined> {
379
+ let resource: ResourceType;
380
+
381
+ // If details of multiple users required
382
+ if (Array.isArray(id)) {
383
+ resource = ResourceType.USER_DETAILS_BY_IDS_BULK;
384
+
385
+ // Fetching raw details
386
+ const response = await this.request<IUserDetailsBulkResponse>(resource, { ids: id });
387
+
388
+ // Deserializing response
389
+ const data = Extractors[resource](response, id);
390
+
391
+ return data;
392
+ }
393
+ // If details of single user required
394
+ else {
395
+ // If username is given
396
+ if (id && isNaN(Number(id))) {
397
+ resource = ResourceType.USER_DETAILS_BY_USERNAME;
398
+ if (id?.startsWith('@')) {
399
+ id = id.slice(1);
400
+ }
401
+ }
402
+ // If id is given (or not, for self details)
403
+ else {
404
+ resource = ResourceType.USER_DETAILS_BY_ID;
405
+ }
406
+
407
+ // If no ID is given, and not authenticated, skip
408
+ if (!id && !this.config.userId) {
409
+ return undefined;
410
+ }
411
+
412
+ // Fetching raw details
413
+ const response = await this.request<IUserDetailsResponse>(resource, { id: id ?? this.config.userId });
414
+
415
+ // Deserializing response
416
+ const data = Extractors[resource](response);
417
+
418
+ return data;
419
+ }
420
+ }
421
+
422
+ /**
423
+ * Follow a user.
424
+ *
425
+ * @param id - The ID the user to be followed.
426
+ *
427
+ * @returns Whether following was successful or not.
428
+ *
429
+ * @throws Code 108 if given user id is invalid.
430
+ *
431
+ * @example
432
+ *
433
+ * ```ts
434
+ * import { Rettiwt } from 'rettiwt-api';
435
+ *
436
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
437
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
438
+ *
439
+ * // Following the User with id '1234567890'
440
+ * rettiwt.user.follow('1234567890')
441
+ * .then(res => {
442
+ * console.log(res);
443
+ * })
444
+ * .catch(err => {
445
+ * console.log(err);
446
+ * });
447
+ * ```
448
+ */
449
+ public async follow(id: string): Promise<boolean> {
450
+ const resource = ResourceType.USER_FOLLOW;
451
+
452
+ // Following the user
453
+ const response = await this.request<IUserFollowResponse>(ResourceType.USER_FOLLOW, { id: id });
454
+
455
+ // Deserializing the response
456
+ const data = Extractors[resource](response) ?? false;
457
+
458
+ return data;
459
+ }
460
+
461
+ /**
462
+ * Get the followed feed of the logged in user.
463
+ *
464
+ * @param cursor - The cursor to the batch of feed items to fetch.
465
+ *
466
+ * @returns - The followed feed of the logged-in user.
467
+ *
468
+ * @example
469
+ *
470
+ * ```ts
471
+ * import { Rettiwt } from 'rettiwt-api';
472
+ *
473
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
474
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
475
+ *
476
+ * // Fetching the first 35 followed feed items of the logged-in user
477
+ * rettiwt.user.followed()
478
+ * .then(res => {
479
+ * console.log(res);
480
+ * })
481
+ * .catch(err => {
482
+ * console.log(err);
483
+ * });
484
+ * ```
485
+ *
486
+ * @remarks Always returns 35 feed items, with no way to customize the count.
487
+ */
488
+ public async followed(cursor?: string): Promise<CursoredData<Tweet>> {
489
+ const resource = ResourceType.USER_FEED_FOLLOWED;
490
+
491
+ // Fetching raw list of tweets
492
+ const response = await this.request<IUserFollowedResponse>(resource, {
493
+ cursor: cursor,
494
+ });
495
+
496
+ // Deserializing response
497
+ const data = Extractors[resource](response);
498
+
499
+ return data;
500
+ }
501
+
502
+ /**
503
+ * Get the list followers of a user.
504
+ *
505
+ * @param id - The ID of the target user. If no ID is provided, the logged-in user's ID is used.
506
+ * @param count - The number of followers to fetch, must be \<= 100.
507
+ * @param cursor - The cursor to the batch of followers to fetch.
508
+ *
509
+ * @returns The list of users following the target user.
510
+ *
511
+ * @example
512
+ *
513
+ * ```ts
514
+ * import { Rettiwt } from 'rettiwt-api';
515
+ *
516
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
517
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
518
+ *
519
+ * // Fetching the first 100 followers of the User with id '1234567890'
520
+ * rettiwt.user.followers('1234567890')
521
+ * .then(res => {
522
+ * console.log(res);
523
+ * })
524
+ * .catch(err => {
525
+ * console.log(err);
526
+ * });
527
+ * ```
528
+ */
529
+ public async followers(id?: string, count?: number, cursor?: string): Promise<CursoredData<User>> {
530
+ const resource = ResourceType.USER_FOLLOWERS;
531
+
532
+ // Fetching raw list of followers
533
+ const response = await this.request<IUserFollowersResponse>(resource, {
534
+ id: id ?? this.config.userId,
535
+ count: count,
536
+ cursor: cursor,
537
+ });
538
+
539
+ // Deserializing response
540
+ const data = Extractors[resource](response);
541
+
542
+ return data;
543
+ }
544
+
545
+ /**
546
+ * Get the list of users who are followed by a user.
547
+ *
548
+ * @param id - The ID of the target user. If no ID is provided, the logged-in user's ID is used.
549
+ * @param count - The number of following to fetch, must be \<= 100.
550
+ * @param cursor - The cursor to the batch of following to fetch.
551
+ *
552
+ * @returns The list of users followed by the target user.
553
+ *
554
+ * @example
555
+ *
556
+ * ```ts
557
+ * import { Rettiwt } from 'rettiwt-api';
558
+ *
559
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
560
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
561
+ *
562
+ * // Fetching the first 100 following of the User with id '1234567890'
563
+ * rettiwt.user.following('1234567890')
564
+ * .then(res => {
565
+ * console.log(res);
566
+ * })
567
+ * .catch(err => {
568
+ * console.log(err);
569
+ * });
570
+ * ```
571
+ */
572
+ public async following(id?: string, count?: number, cursor?: string): Promise<CursoredData<User>> {
573
+ const resource = ResourceType.USER_FOLLOWING;
574
+
575
+ // Fetching raw list of following
576
+ const response = await this.request<IUserFollowingResponse>(resource, {
577
+ id: id ?? this.config.userId,
578
+ count: count,
579
+ cursor: cursor,
580
+ });
581
+
582
+ // Deserializing response
583
+ const data = Extractors[resource](response);
584
+
585
+ return data;
586
+ }
587
+
588
+ /**
589
+ * Get the highlighted tweets of a user.
590
+ *
591
+ * @param id - The ID of the target user. If no ID is provided, the logged-in user's ID is used.
592
+ * @param count - The number of followers to fetch, must be \<= 100.
593
+ * @param cursor - The cursor to the batch of followers to fetch.
594
+ *
595
+ * @returns The list of highlighted tweets of the target user.
596
+ *
597
+ * @example
598
+ *
599
+ * ```ts
600
+ * import { Rettiwt } from 'rettiwt-api';
601
+ *
602
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
603
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
604
+ *
605
+ * // Fetching the top 100 highlights of the User with id '1234567890'
606
+ * rettiwt.user.highlights('1234567890')
607
+ * .then(res => {
608
+ * console.log(res);
609
+ * })
610
+ * .catch(err => {
611
+ * console.log(err);
612
+ * });
613
+ * ```
614
+ */
615
+ public async highlights(id?: string, count?: number, cursor?: string): Promise<CursoredData<Tweet>> {
616
+ const resource = ResourceType.USER_HIGHLIGHTS;
617
+
618
+ // Fetching raw list of highlights
619
+ const response = await this.request<IUserHighlightsResponse>(resource, {
620
+ id: id ?? this.config.userId,
621
+ count: count,
622
+ cursor: cursor,
623
+ });
624
+
625
+ // Deserializing response
626
+ const data = Extractors[resource](response);
627
+
628
+ return data;
629
+ }
630
+
631
+ /**
632
+ * Get the list of tweets liked by the logged in user.
633
+ *
634
+ * @param count - The number of likes to fetch, must be \<= 100.
635
+ * @param cursor - The cursor to the batch of likes to fetch.
636
+ *
637
+ * @returns The list of tweets liked by the target user.
638
+ *
639
+ * @example
640
+ *
641
+ * ```ts
642
+ * import { Rettiwt } from 'rettiwt-api';
643
+ *
644
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
645
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
646
+ *
647
+ * // Fetching the most recent 100 liked Tweets of the logged in User
648
+ * rettiwt.user.likes()
649
+ * .then(res => {
650
+ * console.log(res);
651
+ * })
652
+ * .catch(err => {
653
+ * console.log(err);
654
+ * });
655
+ * ```
656
+ */
657
+ public async likes(count?: number, cursor?: string): Promise<CursoredData<Tweet>> {
658
+ const resource = ResourceType.USER_LIKES;
659
+
660
+ // Fetching raw list of likes
661
+ const response = await this.request<IUserLikesResponse>(resource, {
662
+ id: this.config.userId,
663
+ count: count,
664
+ cursor: cursor,
665
+ });
666
+
667
+ // Deserializing response
668
+ const data = Extractors[resource](response);
669
+
670
+ return data;
671
+ }
672
+
673
+ /**
674
+ * Get the list of of the the logged in user. Includes both followed and owned.
675
+ *
676
+ * @param count - The number of lists to fetch, must be \<= 100.
677
+ * @param cursor - The cursor to the batch of likes to fetch.
678
+ *
679
+ * @returns The list of tweets liked by the target user.
680
+ *
681
+ * @example
682
+ *
683
+ * ```ts
684
+ * import { Rettiwt } from 'rettiwt-api';
685
+ *
686
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
687
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
688
+ *
689
+ * // Fetching the first 100 Lists of the logged in User
690
+ * rettiwt.user.lists()
691
+ * .then(res => {
692
+ * console.log(res);
693
+ * })
694
+ * .catch(err => {
695
+ * console.log(err);
696
+ * });
697
+ * ```
698
+ */
699
+ public async lists(count?: number, cursor?: string): Promise<CursoredData<List>> {
700
+ const resource = ResourceType.USER_LISTS;
701
+
702
+ // Fetching raw list of lists
703
+ const response = await this.request<IUserListsResponse>(resource, {
704
+ id: this.config.userId,
705
+ count: count,
706
+ cursor: cursor,
707
+ });
708
+
709
+ // Deserializing response
710
+ const data = Extractors[resource](response);
711
+
712
+ return data;
713
+ }
714
+
715
+ /**
716
+ * Get the media timeline of a user.
717
+ *
718
+ * @param id - The ID of the target user. If no ID is provided, the logged-in user's ID is used.
719
+ * @param count - The number of media to fetch, must be \<= 100.
720
+ * @param cursor - The cursor to the batch of media to fetch
721
+ *
722
+ * @returns The media timeline of the target user.
723
+ *
724
+ * @example
725
+ *
726
+ * ```ts
727
+ * import { Rettiwt } from 'rettiwt-api';
728
+ *
729
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
730
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
731
+ *
732
+ * // Fetching the first 100 timeline media tweets of the User with id '1234567890'
733
+ * rettiwt.user.timeline('1234567890')
734
+ * .then(res => {
735
+ * console.log(res);
736
+ * })
737
+ * .catch(err => {
738
+ * console.log(err);
739
+ * });
740
+ * ```
741
+ */
742
+ public async media(id?: string, count?: number, cursor?: string): Promise<CursoredData<Tweet>> {
743
+ const resource = ResourceType.USER_MEDIA;
744
+
745
+ // Fetching raw list of media
746
+ const response = await this.request<IUserMediaResponse>(resource, {
747
+ id: id ?? this.config.userId,
748
+ count: count,
749
+ cursor: cursor,
750
+ });
751
+
752
+ // Deserializing response
753
+ const data = Extractors[resource](response);
754
+
755
+ return data;
756
+ }
757
+
758
+ /**
759
+ * Stream notifications of the logged in user in pseudo real-time.
760
+ *
761
+ * @param pollingInterval - The interval in milliseconds to poll for new tweets. Default interval is 60000 ms.
762
+ *
763
+ * @returns An async generator that yields new notifications as they are received.
764
+ *
765
+ * @example
766
+ *
767
+ * ```ts
768
+ * import { Rettiwt } from 'rettiwt-api';
769
+ *
770
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
771
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
772
+ *
773
+ * // Creating a function that streams all new notifications
774
+ * async function streamNotifications() {
775
+ * try {
776
+ * // Awaiting for the notifications returned by the AsyncGenerator returned by the method
777
+ * for await (const notification of rettiwt.user.notifications(5000)) {
778
+ * console.log(notification.message);
779
+ * }
780
+ * }
781
+ * catch (err) {
782
+ * console.log(err);
783
+ * }
784
+ * }
785
+ *
786
+ * // Calling the function
787
+ * streamNotifications();
788
+ * ```
789
+ */
790
+ public async *notifications(pollingInterval = 60000): AsyncGenerator<Notification> {
791
+ const resource = ResourceType.USER_NOTIFICATIONS;
792
+
793
+ /** Whether it's the first batch of notifications or not. */
794
+ let first = true;
795
+
796
+ /** The cursor to the last notification received. */
797
+ let cursor: string | undefined = undefined;
798
+
799
+ while (true) {
800
+ // Pause execution for the specified polling interval before proceeding to the next iteration
801
+ await new Promise((resolve) => setTimeout(resolve, pollingInterval));
802
+
803
+ // Get the batch of notifications after the given cursor
804
+ const response = await this.request<IUserNotificationsResponse>(resource, {
805
+ count: 40,
806
+ cursor: cursor,
807
+ });
808
+
809
+ // Deserializing response
810
+ const notifications = Extractors[resource](response);
811
+
812
+ // Sorting the notifications by time, from oldest to recent
813
+ notifications.list.sort((a, b) => new Date(a.receivedAt).valueOf() - new Date(b.receivedAt).valueOf());
814
+
815
+ // If not first batch, return new notifications
816
+ if (!first) {
817
+ // Yield the notifications
818
+ for (const notification of notifications.list) {
819
+ yield notification;
820
+ }
821
+ }
822
+ // Else do nothing, do nothing since first batch is notifications that have already been received
823
+ else {
824
+ first = false;
825
+ }
826
+
827
+ cursor = notifications.next;
828
+ }
829
+ }
830
+
831
+ /**
832
+ * Get the recommended feed of the logged in user.
833
+ *
834
+ * @param cursor - The cursor to the batch of feed items to fetch.
835
+ *
836
+ * @returns - The recommended feed of the logged-in user.
837
+ *
838
+ * @example
839
+ *
840
+ * ```ts
841
+ * import { Rettiwt } from 'rettiwt-api';
842
+ *
843
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
844
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
845
+ *
846
+ * // Fetching the first 35 recommended feed items of the logged-in user
847
+ * rettiwt.user.recommended()
848
+ * .then(res => {
849
+ * console.log(res);
850
+ * })
851
+ * .catch(err => {
852
+ * console.log(err);
853
+ * });
854
+ * ```
855
+ *
856
+ * @remarks Always returns 35 feed items, with no way to customize the count.
857
+ */
858
+ public async recommended(cursor?: string): Promise<CursoredData<Tweet>> {
859
+ const resource = ResourceType.USER_FEED_RECOMMENDED;
860
+
861
+ // Fetching raw list of tweets
862
+ const response = await this.request<IUserRecommendedResponse>(resource, {
863
+ cursor: cursor,
864
+ });
865
+
866
+ // Deserializing response
867
+ const data = Extractors[resource](response);
868
+
869
+ return data;
870
+ }
871
+
872
+ /**
873
+ * Get the reply timeline of a user.
874
+ *
875
+ * @param id - The ID of the target user. If no ID is provided, the logged-in user's ID is used.
876
+ * @param count - The number of replies to fetch, must be \<= 20.
877
+ * @param cursor - The cursor to the batch of replies to fetch.
878
+ *
879
+ * @returns The reply timeline of the target user.
880
+ *
881
+ * @example
882
+ *
883
+ * ```ts
884
+ * import { Rettiwt } from 'rettiwt-api';
885
+ *
886
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
887
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
888
+ *
889
+ * // Fetching the first 100 timeline replies of the User with id '1234567890'
890
+ * rettiwt.user.replies('1234567890')
891
+ * .then(res => {
892
+ * console.log(res);
893
+ * })
894
+ * .catch(err => {
895
+ * console.log(err);
896
+ * });
897
+ * ```
898
+ *
899
+ * @remarks
900
+ *
901
+ * If the target user has a pinned tweet, the returned reply timeline has one item extra and this is always the pinned tweet.
902
+ */
903
+ public async replies(id?: string, count?: number, cursor?: string): Promise<CursoredData<Tweet>> {
904
+ const resource = ResourceType.USER_TIMELINE_AND_REPLIES;
905
+
906
+ // Fetching raw list of replies
907
+ const response = await this.request<IUserTweetsAndRepliesResponse>(resource, {
908
+ id: id ?? this.config.userId,
909
+ count: count,
910
+ cursor: cursor,
911
+ });
912
+
913
+ // Deserializing response
914
+ const data = Extractors[resource](response);
915
+
916
+ return data;
917
+ }
918
+
919
+ /**
920
+ * Search for a username.
921
+ *
922
+ * @param userName - The username to search for.
923
+ * @param count - The number of results to fetch, must be \<= 20.
924
+ * @param cursor - The cursor to the batch of results to fetch.
925
+ *
926
+ * @returns The list of users that match the given username.
927
+ *
928
+ * @example
929
+ *
930
+ * ```ts
931
+ * import { Rettiwt } from 'rettiwt-api';
932
+ *
933
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
934
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
935
+ *
936
+ * // Fetching the top 5 matching users for the username 'user1'
937
+ * rettiwt.user.search('user1')
938
+ * .then(res => {
939
+ * console.log(res);
940
+ * })
941
+ * .catch(err => {
942
+ * console.log(err);
943
+ * });
944
+ * ```
945
+ */
946
+ public async search(userName: string, count?: number, cursor?: string): Promise<CursoredData<User>> {
947
+ const resource = ResourceType.USER_SEARCH;
948
+
949
+ // Fetching raw list of filtered tweets
950
+ const response = await this.request<IUserSearchResponse>(resource, {
951
+ id: userName,
952
+ count: count,
953
+ cursor: cursor,
954
+ });
955
+
956
+ // Deserializing response
957
+ const data = Extractors[resource](response);
958
+
959
+ return data;
960
+ }
961
+
962
+ /**
963
+ * Get the list of subscriptions of a user.
964
+ *
965
+ * @param id - The ID of the target user. If no ID is provided, the logged-in user's ID is used.
966
+ * @param count - The number of subscriptions to fetch, must be \<= 100.
967
+ * @param cursor - The cursor to the batch of subscriptions to fetch.
968
+ *
969
+ * @returns The list of subscriptions by the target user.
970
+ *
971
+ * @example
972
+ *
973
+ * ```ts
974
+ * import { Rettiwt } from 'rettiwt-api';
975
+ *
976
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
977
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
978
+ *
979
+ * // Fetching the first 100 subscriptions of the User with id '1234567890'
980
+ * rettiwt.user.subscriptions('1234567890')
981
+ * .then(res => {
982
+ * console.log(res);
983
+ * })
984
+ * .catch(err => {
985
+ * console.log(err);
986
+ * });
987
+ * ```
988
+ */
989
+ public async subscriptions(id?: string, count?: number, cursor?: string): Promise<CursoredData<User>> {
990
+ const resource = ResourceType.USER_SUBSCRIPTIONS;
991
+
992
+ // Fetching raw list of subscriptions
993
+ const response = await this.request<IUserSubscriptionsResponse>(resource, {
994
+ id: id ?? this.config.userId,
995
+ count: count,
996
+ cursor: cursor,
997
+ });
998
+
999
+ // Deserializing response
1000
+ const data = Extractors[resource](response);
1001
+
1002
+ return data;
1003
+ }
1004
+
1005
+ /**
1006
+ * Get the tweet timeline of a user.
1007
+ *
1008
+ * @param id - The ID of the target user. If no ID is provided, the logged-in user's ID is used.
1009
+ * @param count - The number of timeline items to fetch, must be \<= 20.
1010
+ * @param cursor - The cursor to the batch of timeline items to fetch.
1011
+ *
1012
+ * @returns The timeline of the target user.
1013
+ *
1014
+ * @example
1015
+ *
1016
+ * ```ts
1017
+ * import { Rettiwt } from 'rettiwt-api';
1018
+ *
1019
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
1020
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
1021
+ *
1022
+ * // Fetching the first 20 timeline tweets of the User with id '1234567890'
1023
+ * rettiwt.user.timeline('1234567890')
1024
+ * .then(res => {
1025
+ * console.log(res);
1026
+ * })
1027
+ * .catch(err => {
1028
+ * console.log(err);
1029
+ * });
1030
+ * ```
1031
+ *
1032
+ * @remarks
1033
+ *
1034
+ * - If the target user has a pinned tweet, the returned timeline has one item extra and this is always the pinned tweet.
1035
+ * - If timeline is fetched without authenticating, then the most popular tweets of the target user are returned instead.
1036
+ */
1037
+ public async timeline(id?: string, count?: number, cursor?: string): Promise<CursoredData<Tweet>> {
1038
+ const resource = ResourceType.USER_TIMELINE;
1039
+
1040
+ // Fetching raw list of tweets
1041
+ const response = await this.request<IUserTweetsResponse>(resource, {
1042
+ id: id ?? this.config.userId,
1043
+ count: count,
1044
+ cursor: cursor,
1045
+ });
1046
+
1047
+ // Deserializing response
1048
+ const data = Extractors[resource](response);
1049
+
1050
+ return data;
1051
+ }
1052
+
1053
+ /**
1054
+ * Unfollow a user.
1055
+ *
1056
+ * @param id - The ID the user to be unfollowed.
1057
+ *
1058
+ * @returns Whether unfollowing was successful or not.
1059
+ *
1060
+ * @example
1061
+ *
1062
+ * ```ts
1063
+ * import { Rettiwt } from 'rettiwt-api';
1064
+ *
1065
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
1066
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
1067
+ *
1068
+ * // Unfollowing the User with id '12345678'
1069
+ * rettiwt.user.unfollow('12345678')
1070
+ * .then(res => {
1071
+ * console.log(res);
1072
+ * })
1073
+ * .catch(err => {
1074
+ * console.log(err);
1075
+ * });
1076
+ * ```
1077
+ */
1078
+ public async unfollow(id: string): Promise<boolean> {
1079
+ const resource = ResourceType.USER_UNFOLLOW;
1080
+
1081
+ // Unfollowing the user
1082
+ const response = await this.request<IUserUnfollowResponse>(ResourceType.USER_UNFOLLOW, { id: id });
1083
+
1084
+ // Deserializing the response
1085
+ const data = Extractors[resource](response) ?? false;
1086
+
1087
+ return data;
1088
+ }
1089
+
1090
+ /**
1091
+ * Update the logged in user's profile.
1092
+ *
1093
+ * @param options - The profile update options.
1094
+ *
1095
+ * @returns Whether the profile update was successful or not.
1096
+ *
1097
+ * @example
1098
+ *
1099
+ * #### Updating only the display name
1100
+ * ```ts
1101
+ * import { Rettiwt } from 'rettiwt-api';
1102
+ *
1103
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
1104
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
1105
+ *
1106
+ * // Updating the display name of the logged in user
1107
+ * rettiwt.user.updateProfile({ name: 'New Display Name' })
1108
+ * .then(res => {
1109
+ * console.log(res);
1110
+ * })
1111
+ * .catch(err => {
1112
+ * console.log(err);
1113
+ * });
1114
+ * ```
1115
+ *
1116
+ * @example
1117
+ *
1118
+ * #### Updating multiple profile fields
1119
+ * ```ts
1120
+ * import { Rettiwt } from 'rettiwt-api';
1121
+ *
1122
+ * // Creating a new Rettiwt instance using the given 'API_KEY'
1123
+ * const rettiwt = new Rettiwt({ apiKey: API_KEY });
1124
+ *
1125
+ * // Updating multiple profile fields
1126
+ * rettiwt.user.updateProfile({
1127
+ * name: 'New Display Name',
1128
+ * location: 'Istanbul',
1129
+ * description: 'Hello world!',
1130
+ * url: 'https://example.com'
1131
+ * })
1132
+ * .then(res => {
1133
+ * console.log(res);
1134
+ * })
1135
+ * .catch(err => {
1136
+ * console.log(err);
1137
+ * });
1138
+ * ```
1139
+ */
1140
+ public async updateProfile(options: IProfileUpdateOptions): Promise<boolean> {
1141
+ const resource = ResourceType.USER_PROFILE_UPDATE;
1142
+
1143
+ // Validating the options
1144
+ const validatedOptions = new ProfileUpdateOptions(options);
1145
+
1146
+ // Updating the profile
1147
+ const response = await this.request<IUserProfileUpdateResponse>(resource, { profileOptions: validatedOptions });
1148
+
1149
+ // Deserializing the response
1150
+ const data = Extractors[resource](response) ?? false;
1151
+
1152
+ return data;
1153
+ }
1154
+ }