rettiwt-api 2.0.3 → 2.2.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/.github/workflows/publish.yml +0 -3
- package/README.md +69 -0
- package/dist/Rettiwt.d.ts +3 -2
- package/dist/Rettiwt.js +5 -9
- package/dist/Rettiwt.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/models/CursoredData.d.ts +15 -15
- package/dist/models/CursoredData.js +18 -18
- package/dist/models/CursoredData.js.map +1 -1
- package/dist/models/List.d.ts +29 -0
- package/dist/models/List.js +27 -0
- package/dist/models/List.js.map +1 -0
- package/dist/models/Tweet.d.ts +48 -19
- package/dist/models/Tweet.js +77 -28
- package/dist/models/Tweet.js.map +1 -1
- package/dist/models/User.d.ts +3 -1
- package/dist/models/User.js +2 -0
- package/dist/models/User.js.map +1 -1
- package/dist/services/FetcherService.d.ts +19 -3
- package/dist/services/FetcherService.js +39 -6
- package/dist/services/FetcherService.js.map +1 -1
- package/dist/services/TweetService.d.ts +19 -8
- package/dist/services/TweetService.js +40 -10
- package/dist/services/TweetService.js.map +1 -1
- package/dist/services/UserService.d.ts +16 -3
- package/dist/services/UserService.js +33 -3
- package/dist/services/UserService.js.map +1 -1
- package/dist/types/CursoredData.d.ts +9 -9
- package/dist/types/List.d.ts +21 -0
- package/dist/types/List.js +3 -0
- package/dist/types/List.js.map +1 -0
- package/dist/types/Tweet.d.ts +34 -17
- package/package.json +4 -2
- package/src/Rettiwt.ts +5 -11
- package/src/index.ts +2 -0
- package/src/models/CursoredData.ts +19 -19
- package/src/models/List.ts +48 -0
- package/src/models/Tweet.ts +118 -53
- package/src/models/User.ts +5 -1
- package/src/services/FetcherService.ts +49 -7
- package/src/services/TweetService.ts +35 -11
- package/src/services/UserService.ts +27 -4
- package/src/types/CursoredData.ts +10 -10
- package/src/types/List.ts +27 -0
- package/src/types/Tweet.ts +44 -19
- package/.dockerignore +0 -2
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// PACKAGES
|
|
2
|
+
import { IList as IRawList } from 'rettiwt-core';
|
|
3
|
+
|
|
4
|
+
// TYPES
|
|
5
|
+
import { IList } from '../types/List';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The details of a single Twitter List.
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export class List implements IList {
|
|
13
|
+
/** The rest id of the list. */
|
|
14
|
+
id: string;
|
|
15
|
+
|
|
16
|
+
/** The name of the list. */
|
|
17
|
+
name: string;
|
|
18
|
+
|
|
19
|
+
/** The date and time of creation of the list, int UTC string format. */
|
|
20
|
+
createdAt: string;
|
|
21
|
+
|
|
22
|
+
/** The list description. */
|
|
23
|
+
description: string;
|
|
24
|
+
|
|
25
|
+
/** The number of memeber of the list. */
|
|
26
|
+
memberCount: number;
|
|
27
|
+
|
|
28
|
+
/** The number of subscribers of the list. */
|
|
29
|
+
subscriberCount: number;
|
|
30
|
+
|
|
31
|
+
/** The rest id of the user who created the list. */
|
|
32
|
+
createdBy: string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Initializes a new Tweet List from the given raw list data.
|
|
36
|
+
*
|
|
37
|
+
* @param list - list The raw tweet list data.
|
|
38
|
+
*/
|
|
39
|
+
constructor(list: IRawList) {
|
|
40
|
+
this.id = list.id_str;
|
|
41
|
+
this.name = list.name;
|
|
42
|
+
this.createdAt = new Date(list.created_at).toISOString();
|
|
43
|
+
this.description = list.description;
|
|
44
|
+
this.memberCount = list.member_count;
|
|
45
|
+
this.subscriberCount = list.subscriber_count;
|
|
46
|
+
this.createdBy = list.user_results.result.id;
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/models/Tweet.ts
CHANGED
|
@@ -1,59 +1,20 @@
|
|
|
1
|
+
// PACKAGES
|
|
2
|
+
import {
|
|
3
|
+
ITweet as IRawTweet,
|
|
4
|
+
IEntities as IRawTweetEntities,
|
|
5
|
+
IExtendedMedia as IRawExtendedMedia,
|
|
6
|
+
EMediaType,
|
|
7
|
+
} from 'rettiwt-core';
|
|
8
|
+
|
|
1
9
|
// TYPES
|
|
2
10
|
import { ITweet, ITweetEntities } from '../types/Tweet';
|
|
3
|
-
|
|
11
|
+
|
|
12
|
+
// MODELS
|
|
13
|
+
import { User } from './User';
|
|
4
14
|
|
|
5
15
|
// PARSERS
|
|
6
16
|
import { normalizeText } from '../helper/JsonUtils';
|
|
7
17
|
|
|
8
|
-
/**
|
|
9
|
-
* The different types parsed entities like urls, media, mentions, hashtags, etc.
|
|
10
|
-
*
|
|
11
|
-
* @public
|
|
12
|
-
*/
|
|
13
|
-
export class TweetEntities implements ITweetEntities {
|
|
14
|
-
/** The list of hashtags mentioned in the tweet. */
|
|
15
|
-
hashtags: string[] = [];
|
|
16
|
-
|
|
17
|
-
/** The list of urls mentioned in the tweet. */
|
|
18
|
-
urls: string[] = [];
|
|
19
|
-
|
|
20
|
-
/** The list of IDs of users mentioned in the tweet. */
|
|
21
|
-
mentionedUsers: string[] = [];
|
|
22
|
-
|
|
23
|
-
/** The list of urls to various media mentioned in the tweet. */
|
|
24
|
-
media: string[] = [];
|
|
25
|
-
|
|
26
|
-
constructor(entities: IRawTweetEntities) {
|
|
27
|
-
// Extracting user mentions
|
|
28
|
-
if (entities.user_mentions) {
|
|
29
|
-
for (const user of entities.user_mentions) {
|
|
30
|
-
this.mentionedUsers.push(user.screen_name);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Extracting urls
|
|
35
|
-
if (entities.urls) {
|
|
36
|
-
for (const url of entities.urls) {
|
|
37
|
-
this.urls.push(url.expanded_url);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Extracting hashtags
|
|
42
|
-
if (entities.hashtags) {
|
|
43
|
-
for (const hashtag of entities.hashtags) {
|
|
44
|
-
this.hashtags.push(hashtag.text);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Extracting media urls (if any)
|
|
49
|
-
if (entities.media) {
|
|
50
|
-
for (const media of entities.media) {
|
|
51
|
-
this.media.push(media.media_url_https);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
18
|
/**
|
|
58
19
|
* The details of a single Tweet.
|
|
59
20
|
*
|
|
@@ -63,8 +24,8 @@ export class Tweet implements ITweet {
|
|
|
63
24
|
/** The rest id of the tweet. */
|
|
64
25
|
id: string;
|
|
65
26
|
|
|
66
|
-
/** The
|
|
67
|
-
tweetBy:
|
|
27
|
+
/** The details of the user who made the tweet. */
|
|
28
|
+
tweetBy: User;
|
|
68
29
|
|
|
69
30
|
/** The date and time of creation of the tweet, in UTC string format. */
|
|
70
31
|
createdAt: string;
|
|
@@ -72,6 +33,9 @@ export class Tweet implements ITweet {
|
|
|
72
33
|
/** Additional tweet entities like urls, mentions, etc. */
|
|
73
34
|
entities: TweetEntities;
|
|
74
35
|
|
|
36
|
+
/** The urls of the media contents of the tweet (if any). */
|
|
37
|
+
media: TweetMedia[];
|
|
38
|
+
|
|
75
39
|
/** The rest id of the tweet which is quoted in the tweet. */
|
|
76
40
|
quoted: string;
|
|
77
41
|
|
|
@@ -96,14 +60,23 @@ export class Tweet implements ITweet {
|
|
|
96
60
|
/** The number of likes of the tweet. */
|
|
97
61
|
likeCount: number;
|
|
98
62
|
|
|
63
|
+
/** The number of views of a tweet. */
|
|
64
|
+
viewCount: number;
|
|
65
|
+
|
|
66
|
+
/** The number of bookmarks of a tweet. */
|
|
67
|
+
bookmarkCount: number;
|
|
68
|
+
|
|
99
69
|
/**
|
|
70
|
+
* Initializes a new Tweet from the given raw tweet data.
|
|
71
|
+
*
|
|
100
72
|
* @param tweet - The raw tweet data.
|
|
101
73
|
*/
|
|
102
74
|
constructor(tweet: IRawTweet) {
|
|
103
75
|
this.id = tweet.rest_id;
|
|
104
76
|
this.createdAt = tweet.legacy.created_at;
|
|
105
|
-
this.tweetBy = tweet.
|
|
77
|
+
this.tweetBy = new User(tweet.core.user_results.result);
|
|
106
78
|
this.entities = new TweetEntities(tweet.legacy.entities);
|
|
79
|
+
this.media = tweet.legacy.extended_entities?.media?.map((media) => new TweetMedia(media));
|
|
107
80
|
this.quoted = tweet.legacy.quoted_status_id_str;
|
|
108
81
|
this.fullText = normalizeText(tweet.legacy.full_text);
|
|
109
82
|
this.replyTo = tweet.legacy.in_reply_to_status_id_str;
|
|
@@ -112,5 +85,97 @@ export class Tweet implements ITweet {
|
|
|
112
85
|
this.replyCount = tweet.legacy.reply_count;
|
|
113
86
|
this.retweetCount = tweet.legacy.retweet_count;
|
|
114
87
|
this.likeCount = tweet.legacy.favorite_count;
|
|
88
|
+
this.viewCount = parseInt(tweet.views.count);
|
|
89
|
+
this.bookmarkCount = tweet.legacy.bookmark_count;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The different types parsed entities like urls, media, mentions, hashtags, etc.
|
|
95
|
+
*
|
|
96
|
+
* @public
|
|
97
|
+
*/
|
|
98
|
+
export class TweetEntities implements ITweetEntities {
|
|
99
|
+
/** The list of hashtags mentioned in the tweet. */
|
|
100
|
+
hashtags: string[] = [];
|
|
101
|
+
|
|
102
|
+
/** The list of urls mentioned in the tweet. */
|
|
103
|
+
urls: string[] = [];
|
|
104
|
+
|
|
105
|
+
/** The list of IDs of users mentioned in the tweet. */
|
|
106
|
+
mentionedUsers: string[] = [];
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Initializes the TweetEntities from the raw tweet entities.
|
|
110
|
+
*
|
|
111
|
+
* @param entities - The raw tweet entities.
|
|
112
|
+
*/
|
|
113
|
+
constructor(entities: IRawTweetEntities) {
|
|
114
|
+
// Extracting user mentions
|
|
115
|
+
if (entities.user_mentions) {
|
|
116
|
+
for (const user of entities.user_mentions) {
|
|
117
|
+
this.mentionedUsers.push(user.screen_name);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Extracting urls
|
|
122
|
+
if (entities.urls) {
|
|
123
|
+
for (const url of entities.urls) {
|
|
124
|
+
this.urls.push(url.expanded_url);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Extracting hashtags
|
|
129
|
+
if (entities.hashtags) {
|
|
130
|
+
for (const hashtag of entities.hashtags) {
|
|
131
|
+
this.hashtags.push(hashtag.text);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* A single media content.
|
|
139
|
+
*
|
|
140
|
+
* @public
|
|
141
|
+
*/
|
|
142
|
+
export class TweetMedia {
|
|
143
|
+
/** The type of media. */
|
|
144
|
+
type: EMediaType;
|
|
145
|
+
|
|
146
|
+
/** The direct URL to the media. */
|
|
147
|
+
url: string = '';
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Initializes the TweetMedia from the raw tweet media.
|
|
151
|
+
*
|
|
152
|
+
* @param media - The raw tweet media.
|
|
153
|
+
*/
|
|
154
|
+
constructor(media: IRawExtendedMedia) {
|
|
155
|
+
this.type = media.type;
|
|
156
|
+
|
|
157
|
+
// If the media is a photo
|
|
158
|
+
if (media.type == EMediaType.PHOTO) {
|
|
159
|
+
this.url = media.media_url_https;
|
|
160
|
+
}
|
|
161
|
+
// If the media is a gif
|
|
162
|
+
else if (media.type == EMediaType.GIF) {
|
|
163
|
+
this.url = media.video_info?.variants[0].url as string;
|
|
164
|
+
}
|
|
165
|
+
// If the media is a video
|
|
166
|
+
else {
|
|
167
|
+
/** The highest bitrate of all variants. */
|
|
168
|
+
let highestRate: number = 0;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Selecting the URL of the video variant with the highest bitrate.
|
|
172
|
+
*/
|
|
173
|
+
media.video_info?.variants.forEach((variant) => {
|
|
174
|
+
if (variant.bitrate > highestRate) {
|
|
175
|
+
highestRate = variant.bitrate;
|
|
176
|
+
this.url = variant.url;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
115
180
|
}
|
|
116
181
|
}
|
package/src/models/User.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
// PACKAGES
|
|
2
|
+
import { IUser as IRawUser } from 'rettiwt-core';
|
|
3
|
+
|
|
1
4
|
// TYPES
|
|
2
5
|
import { IUser } from '../types/User';
|
|
3
|
-
import { IUser as IRawUser } from 'rettiwt-core';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* The details of a single user.
|
|
@@ -51,6 +53,8 @@ export class User implements IUser {
|
|
|
51
53
|
profileImage: string;
|
|
52
54
|
|
|
53
55
|
/**
|
|
56
|
+
* Initializes a new User from the given raw user data.
|
|
57
|
+
*
|
|
54
58
|
* @param user - The raw user data.
|
|
55
59
|
*/
|
|
56
60
|
constructor(user: IRawUser) {
|
|
@@ -12,7 +12,9 @@ import {
|
|
|
12
12
|
EErrorCodes,
|
|
13
13
|
} from 'rettiwt-core';
|
|
14
14
|
import axios, { AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse } from 'axios';
|
|
15
|
+
import https, { Agent } from 'https';
|
|
15
16
|
import { AuthCredential } from 'rettiwt-auth';
|
|
17
|
+
import { HttpsProxyAgent } from 'https-proxy-agent';
|
|
16
18
|
|
|
17
19
|
// ENUMS
|
|
18
20
|
import { EHttpStatus } from '../enums/HTTP';
|
|
@@ -35,11 +37,40 @@ export class FetcherService {
|
|
|
35
37
|
/** The credential to use for authenticating against Twitter API. */
|
|
36
38
|
private cred: AuthCredential;
|
|
37
39
|
|
|
40
|
+
/** The HTTPS Agent to use for requests to Twitter API. */
|
|
41
|
+
private readonly httpsAgent: Agent;
|
|
42
|
+
|
|
38
43
|
/**
|
|
39
|
-
* @param
|
|
44
|
+
* @param apiKey - The apiKey (cookie) to use for authenticating Rettiwt against Twitter API.
|
|
45
|
+
* @param proxyUrl - Optional URL with proxy configuration to use for requests to Twitter API.
|
|
40
46
|
*/
|
|
41
|
-
constructor(
|
|
42
|
-
this.cred =
|
|
47
|
+
constructor(apiKey: string, proxyUrl?: URL) {
|
|
48
|
+
this.cred = this.getAuthCredential(apiKey);
|
|
49
|
+
this.httpsAgent = this.getHttpsAgent(proxyUrl);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Returns an AuthCredential generated using the given API key.
|
|
54
|
+
*
|
|
55
|
+
* @param apiKey - The API key to use for authenticating.
|
|
56
|
+
* @returns The generated AuthCredential.
|
|
57
|
+
*/
|
|
58
|
+
private getAuthCredential(apiKey: string): AuthCredential {
|
|
59
|
+
return new AuthCredential(apiKey.split(';'));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Gets the HttpsAgent based on whether a proxy is used or not.
|
|
64
|
+
*
|
|
65
|
+
* @param proxyUrl - Optional URL with proxy configuration to use for requests to Twitter API.
|
|
66
|
+
* @returns The HttpsAgent to use.
|
|
67
|
+
*/
|
|
68
|
+
private getHttpsAgent(proxyUrl?: URL): Agent {
|
|
69
|
+
if (proxyUrl) {
|
|
70
|
+
return new HttpsProxyAgent(proxyUrl);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return new https.Agent();
|
|
43
74
|
}
|
|
44
75
|
|
|
45
76
|
/**
|
|
@@ -98,10 +129,11 @@ export class FetcherService {
|
|
|
98
129
|
method: config.type,
|
|
99
130
|
data: config.payload,
|
|
100
131
|
headers: JSON.parse(JSON.stringify(this.cred.toHeader())) as AxiosRequestHeaders,
|
|
132
|
+
httpsAgent: this.httpsAgent,
|
|
101
133
|
};
|
|
102
134
|
|
|
103
135
|
/**
|
|
104
|
-
* After making the request, the response is then passed to HTTP error handling
|
|
136
|
+
* After making the request, the response is then passed to HTTP error handling middleware for HTTP error handling.
|
|
105
137
|
*/
|
|
106
138
|
return await axios<IResponse<unknown>>(axiosRequest)
|
|
107
139
|
.then((res) => this.handleHttpError(res))
|
|
@@ -124,17 +156,27 @@ export class FetcherService {
|
|
|
124
156
|
/**
|
|
125
157
|
* The required extracted data.
|
|
126
158
|
*/
|
|
127
|
-
let required = [];
|
|
159
|
+
let required: IRawTweet[] | IRawUser[] = [];
|
|
128
160
|
|
|
129
161
|
if (type == EResourceType.TWEET_DETAILS) {
|
|
130
162
|
required = findByFilter<IRawTweet>(data, '__typename', 'Tweet');
|
|
131
163
|
} else if (type == EResourceType.USER_DETAILS || type == EResourceType.USER_DETAILS_BY_ID) {
|
|
132
164
|
required = findByFilter<IRawUser>(data, '__typename', 'User');
|
|
133
|
-
} else if (
|
|
165
|
+
} else if (
|
|
166
|
+
type == EResourceType.TWEET_SEARCH ||
|
|
167
|
+
type == EResourceType.USER_LIKES ||
|
|
168
|
+
type == EResourceType.LIST_TWEETS ||
|
|
169
|
+
type == EResourceType.USER_TWEETS
|
|
170
|
+
) {
|
|
134
171
|
required = findByFilter<ITimelineTweet>(data, '__typename', 'TimelineTweet').map(
|
|
135
172
|
(item) => item.tweet_results.result,
|
|
136
173
|
);
|
|
137
|
-
} else
|
|
174
|
+
} else if (
|
|
175
|
+
type == EResourceType.TWEET_FAVORITERS ||
|
|
176
|
+
type == EResourceType.TWEET_RETWEETERS ||
|
|
177
|
+
type == EResourceType.USER_FOLLOWERS ||
|
|
178
|
+
type == EResourceType.USER_FOLLOWING
|
|
179
|
+
) {
|
|
138
180
|
required = findByFilter<ITimelineUser>(data, '__typename', 'TimelineUser').map(
|
|
139
181
|
(item) => item.user_results.result,
|
|
140
182
|
);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// PACKAGES
|
|
2
2
|
import { EResourceType, TweetFilter } from 'rettiwt-core';
|
|
3
|
-
import { AuthCredential } from 'rettiwt-auth';
|
|
4
3
|
|
|
5
4
|
// SERVICES
|
|
6
5
|
import { FetcherService } from './FetcherService';
|
|
@@ -17,12 +16,28 @@ import { CursoredData } from '../models/CursoredData';
|
|
|
17
16
|
*/
|
|
18
17
|
export class TweetService extends FetcherService {
|
|
19
18
|
/**
|
|
20
|
-
* @param
|
|
19
|
+
* @param apiKey - The apiKey (cookie) to use for authenticating Rettiwt against Twitter API.
|
|
20
|
+
* @param proxyUrl - Optional URL with proxy configuration to use for requests to Twitter API.
|
|
21
21
|
*
|
|
22
22
|
* @internal
|
|
23
23
|
*/
|
|
24
|
-
constructor(
|
|
25
|
-
super(
|
|
24
|
+
constructor(apiKey: string, proxyUrl?: URL) {
|
|
25
|
+
super(apiKey, proxyUrl);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Get the details of a tweet.
|
|
30
|
+
*
|
|
31
|
+
* @param id - The id of the target tweet.
|
|
32
|
+
* @returns The details of a single tweet with the given tweet id.
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
async details(id: string): Promise<Tweet> {
|
|
37
|
+
// Fetching the requested data
|
|
38
|
+
const data = await this.fetch<Tweet>(EResourceType.TWEET_DETAILS, { id: id });
|
|
39
|
+
|
|
40
|
+
return data.list[0];
|
|
26
41
|
}
|
|
27
42
|
|
|
28
43
|
/**
|
|
@@ -50,18 +65,27 @@ export class TweetService extends FetcherService {
|
|
|
50
65
|
}
|
|
51
66
|
|
|
52
67
|
/**
|
|
53
|
-
* Get the
|
|
68
|
+
* Get the tweets from the tweet list with the given id.
|
|
54
69
|
*
|
|
55
|
-
* @param
|
|
56
|
-
* @
|
|
70
|
+
* @param listId - The id of list from where the tweets are to be fetched.
|
|
71
|
+
* @param count - The number of tweets to fetch, must be \<= 100.
|
|
72
|
+
* @param cursor - The cursor to the batch of tweets to fetch.
|
|
73
|
+
* @returns The list tweets present in the given list.
|
|
57
74
|
*
|
|
58
|
-
* @
|
|
75
|
+
* @remarks Due a bug in Twitter API, the count is ignored when no cursor is provided and defaults to 100.
|
|
59
76
|
*/
|
|
60
|
-
async
|
|
77
|
+
async list(listId: string, count?: number, cursor?: string): Promise<CursoredData<Tweet>> {
|
|
61
78
|
// Fetching the requested data
|
|
62
|
-
const data = await this.fetch<Tweet>(EResourceType.
|
|
79
|
+
const data = await this.fetch<Tweet>(EResourceType.LIST_TWEETS, {
|
|
80
|
+
id: listId,
|
|
81
|
+
count: count,
|
|
82
|
+
cursor: cursor,
|
|
83
|
+
});
|
|
63
84
|
|
|
64
|
-
|
|
85
|
+
// Sorting the tweets by date, from recent to oldest
|
|
86
|
+
data.list.sort((a, b) => new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf());
|
|
87
|
+
|
|
88
|
+
return data;
|
|
65
89
|
}
|
|
66
90
|
|
|
67
91
|
/**
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// PACKAGES
|
|
2
2
|
import { EResourceType } from 'rettiwt-core';
|
|
3
|
-
import { AuthCredential } from 'rettiwt-auth';
|
|
4
3
|
|
|
5
4
|
// SERVICES
|
|
6
5
|
import { FetcherService } from './FetcherService';
|
|
@@ -19,12 +18,13 @@ import { CursoredData } from '../models/CursoredData';
|
|
|
19
18
|
*/
|
|
20
19
|
export class UserService extends FetcherService {
|
|
21
20
|
/**
|
|
22
|
-
* @param
|
|
21
|
+
* @param apiKey - The apiKey (cookie) to use for authenticating Rettiwt against Twitter API.
|
|
22
|
+
* @param proxyUrl - Optional URL with proxy configuration to use for requests to Twitter API.
|
|
23
23
|
*
|
|
24
24
|
* @internal
|
|
25
25
|
*/
|
|
26
|
-
constructor(
|
|
27
|
-
super(
|
|
26
|
+
constructor(apiKey: string, proxyUrl?: URL) {
|
|
27
|
+
super(apiKey, proxyUrl);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/**
|
|
@@ -114,4 +114,27 @@ export class UserService extends FetcherService {
|
|
|
114
114
|
|
|
115
115
|
return data;
|
|
116
116
|
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Get the timeline of the given user.
|
|
120
|
+
*
|
|
121
|
+
* @param userId - The rest id of the target user.
|
|
122
|
+
* @param count - The number of timeline items to fetch, must be \<= 20.
|
|
123
|
+
* @param cursor - The cursor to the batch of timeline items to fetch.
|
|
124
|
+
* @returns The timeline of the target user.
|
|
125
|
+
*
|
|
126
|
+
* @remarks If the target user has a pinned tweet, the returned timeline has one item extra and this is always the pinned tweet.
|
|
127
|
+
*
|
|
128
|
+
* @public
|
|
129
|
+
*/
|
|
130
|
+
async timeline(userId: string, count?: number, cursor?: string): Promise<CursoredData<Tweet>> {
|
|
131
|
+
// Fetching the requested data
|
|
132
|
+
const data = await this.fetch<Tweet>(EResourceType.USER_TWEETS, {
|
|
133
|
+
id: userId,
|
|
134
|
+
count: count,
|
|
135
|
+
cursor: cursor,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return data;
|
|
139
|
+
}
|
|
117
140
|
}
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The cursor to the batch of data to be fetched.
|
|
3
|
-
*
|
|
4
|
-
* @public
|
|
5
|
-
*/
|
|
6
|
-
export interface ICursor {
|
|
7
|
-
/** The cursor string. */
|
|
8
|
-
value: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
1
|
/**
|
|
12
2
|
* The data that us fetched batch-wise along with a cursor.
|
|
13
3
|
*
|
|
@@ -22,3 +12,13 @@ export interface ICursoredData<T> {
|
|
|
22
12
|
/** The cursor to the next batch of data. */
|
|
23
13
|
next: ICursor;
|
|
24
14
|
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The cursor to the batch of data to be fetched.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
export interface ICursor {
|
|
22
|
+
/** The cursor string. */
|
|
23
|
+
value: string;
|
|
24
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The details of a single Twitter List.
|
|
3
|
+
*
|
|
4
|
+
* @public
|
|
5
|
+
*/
|
|
6
|
+
export interface IList {
|
|
7
|
+
/** The rest id of the list. */
|
|
8
|
+
id: string;
|
|
9
|
+
|
|
10
|
+
/** The name of the list. */
|
|
11
|
+
name: string;
|
|
12
|
+
|
|
13
|
+
/** The date and time of creation of the list, int UTC string format. */
|
|
14
|
+
createdAt: string;
|
|
15
|
+
|
|
16
|
+
/** The list description. */
|
|
17
|
+
description: string;
|
|
18
|
+
|
|
19
|
+
/** The number of memeber of the list. */
|
|
20
|
+
memberCount: number;
|
|
21
|
+
|
|
22
|
+
/** The number of subscribers of the list. */
|
|
23
|
+
subscriberCount: number;
|
|
24
|
+
|
|
25
|
+
/** The rest id of the user who created the list. */
|
|
26
|
+
createdBy: string;
|
|
27
|
+
}
|
package/src/types/Tweet.ts
CHANGED
|
@@ -1,21 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* @public
|
|
5
|
-
*/
|
|
6
|
-
export interface ITweetEntities {
|
|
7
|
-
/** The list of hashtags mentioned in the tweet. */
|
|
8
|
-
hashtags: string[];
|
|
1
|
+
// PACKAGES
|
|
2
|
+
import { EMediaType } from 'rettiwt-core';
|
|
9
3
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
/** The list of IDs of users mentioned in the tweet. */
|
|
14
|
-
mentionedUsers: string[];
|
|
15
|
-
|
|
16
|
-
/** The list of urls to various media mentioned in the tweet. */
|
|
17
|
-
media: string[];
|
|
18
|
-
}
|
|
4
|
+
// TYPES
|
|
5
|
+
import { IUser } from './User';
|
|
19
6
|
|
|
20
7
|
/**
|
|
21
8
|
* The details of a single Tweet.
|
|
@@ -26,8 +13,8 @@ export interface ITweet {
|
|
|
26
13
|
/** The rest id of the tweet. */
|
|
27
14
|
id: string;
|
|
28
15
|
|
|
29
|
-
/** The
|
|
30
|
-
tweetBy:
|
|
16
|
+
/** The details of the user who made the tweet. */
|
|
17
|
+
tweetBy: IUser;
|
|
31
18
|
|
|
32
19
|
/** The date and time of creation of the tweet, in UTC string format. */
|
|
33
20
|
createdAt: string;
|
|
@@ -35,6 +22,9 @@ export interface ITweet {
|
|
|
35
22
|
/** Additional tweet entities like urls, mentions, etc. */
|
|
36
23
|
entities: ITweetEntities;
|
|
37
24
|
|
|
25
|
+
/** The urls of the media contents of the tweet (if any). */
|
|
26
|
+
media: ITweetMedia[];
|
|
27
|
+
|
|
38
28
|
/** The rest id of the tweet which is quoted in the tweet. */
|
|
39
29
|
quoted: string;
|
|
40
30
|
|
|
@@ -58,4 +48,39 @@ export interface ITweet {
|
|
|
58
48
|
|
|
59
49
|
/** The number of likes of the tweet. */
|
|
60
50
|
likeCount: number;
|
|
51
|
+
|
|
52
|
+
/** The number of views of a tweet. */
|
|
53
|
+
viewCount: number;
|
|
54
|
+
|
|
55
|
+
/** The number of bookmarks of a tweet. */
|
|
56
|
+
bookmarkCount: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The different types parsed entities like urls, media, mentions, hashtags, etc.
|
|
61
|
+
*
|
|
62
|
+
* @public
|
|
63
|
+
*/
|
|
64
|
+
export interface ITweetEntities {
|
|
65
|
+
/** The list of hashtags mentioned in the tweet. */
|
|
66
|
+
hashtags: string[];
|
|
67
|
+
|
|
68
|
+
/** The list of urls mentioned in the tweet. */
|
|
69
|
+
urls: string[];
|
|
70
|
+
|
|
71
|
+
/** The list of IDs of users mentioned in the tweet. */
|
|
72
|
+
mentionedUsers: string[];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* A single media content.
|
|
77
|
+
*
|
|
78
|
+
* @public
|
|
79
|
+
*/
|
|
80
|
+
export interface ITweetMedia {
|
|
81
|
+
/** The type of media. */
|
|
82
|
+
type: EMediaType;
|
|
83
|
+
|
|
84
|
+
/** The direct URL to the media. */
|
|
85
|
+
url: string;
|
|
61
86
|
}
|
package/.dockerignore
DELETED