rettiwt-api 1.1.1 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -7
- package/dist/endpoints/Endpoints.d.ts +14 -0
- package/dist/endpoints/Endpoints.js +20 -0
- package/dist/endpoints/Endpoints.js.map +1 -0
- package/dist/endpoints/Url.d.ts +5 -0
- package/dist/endpoints/Url.js +12 -0
- package/dist/endpoints/Url.js.map +1 -0
- package/dist/enums/Endpoints.d.ts +25 -0
- package/dist/enums/Endpoints.js +31 -0
- package/dist/enums/Endpoints.js.map +1 -0
- package/dist/enums/Errors.d.ts +20 -0
- package/dist/enums/Errors.js +28 -0
- package/dist/enums/Errors.js.map +1 -0
- package/dist/enums/HTTP.d.ts +17 -0
- package/dist/enums/HTTP.js +23 -0
- package/dist/enums/HTTP.js.map +1 -0
- package/dist/graphql/enums/Errors.d.ts +20 -0
- package/dist/graphql/enums/Errors.js +28 -0
- package/dist/graphql/enums/Errors.js.map +1 -0
- package/dist/graphql/queries/RootQuery.js +10 -3
- package/dist/graphql/queries/RootQuery.js.map +1 -1
- package/dist/graphql/resolvers/AccountResolver.d.ts +3 -3
- package/dist/graphql/resolvers/AccountResolver.js.map +1 -1
- package/dist/graphql/resolvers/ResolverBase.d.ts +14 -3
- package/dist/graphql/resolvers/ResolverBase.js +13 -1
- package/dist/graphql/resolvers/ResolverBase.js.map +1 -1
- package/dist/graphql/resolvers/TweetResolver.d.ts +3 -3
- package/dist/graphql/resolvers/TweetResolver.js +30 -18
- package/dist/graphql/resolvers/TweetResolver.js.map +1 -1
- package/dist/graphql/resolvers/UserResolver.d.ts +4 -4
- package/dist/graphql/resolvers/UserResolver.js +23 -19
- package/dist/graphql/resolvers/UserResolver.js.map +1 -1
- package/dist/graphql/types/Errors.d.ts +20 -0
- package/dist/graphql/types/Errors.js +28 -0
- package/dist/graphql/types/Errors.js.map +1 -0
- package/dist/graphql/types/TweetTypes.js +2 -2
- package/dist/graphql/types/TweetTypes.js.map +1 -1
- package/dist/index.d.ts +31 -15
- package/dist/index.js +32 -17
- package/dist/index.js.map +1 -1
- package/dist/middlewares/Authentication.d.ts +0 -0
- package/dist/middlewares/Authentication.js +2 -0
- package/dist/middlewares/Authentication.js.map +1 -0
- package/dist/models/args/TweetFilter.d.ts +59 -0
- package/dist/models/args/TweetFilter.js +101 -0
- package/dist/models/args/TweetFilter.js.map +1 -0
- package/dist/models/args/TweetListArgs.d.ts +21 -0
- package/dist/models/args/TweetListArgs.js +54 -0
- package/dist/models/args/TweetListArgs.js.map +1 -0
- package/dist/models/args/UserListArgs.d.ts +21 -0
- package/dist/models/args/UserListArgs.js +54 -0
- package/dist/models/args/UserListArgs.js.map +1 -0
- package/dist/models/auth/AuthCookie.d.ts +21 -0
- package/dist/models/auth/AuthCookie.js +33 -0
- package/dist/models/auth/AuthCookie.js.map +1 -0
- package/dist/models/data/CursoredData.d.ts +34 -0
- package/dist/models/data/CursoredData.js +42 -0
- package/dist/models/data/CursoredData.js.map +1 -0
- package/dist/models/data/DataValidationError.d.ts +18 -0
- package/dist/models/data/DataValidationError.js +21 -0
- package/dist/models/data/DataValidationError.js.map +1 -0
- package/dist/models/data/Errors.d.ts +18 -0
- package/dist/models/data/Errors.js +21 -0
- package/dist/models/data/Errors.js.map +1 -0
- package/dist/models/data/Service.d.ts +33 -0
- package/dist/models/data/Service.js +41 -0
- package/dist/models/data/Service.js.map +1 -0
- package/dist/models/data/Tweet.d.ts +53 -0
- package/dist/models/data/Tweet.js +104 -0
- package/dist/models/data/Tweet.js.map +1 -0
- package/dist/models/data/User.d.ts +41 -0
- package/dist/models/data/User.js +32 -0
- package/dist/models/data/User.js.map +1 -0
- package/dist/models/errors/DataValidationError.d.ts +20 -0
- package/dist/models/errors/DataValidationError.js +23 -0
- package/dist/models/errors/DataValidationError.js.map +1 -0
- package/dist/models/query/Variables.d.ts +2 -0
- package/dist/models/query/Variables.js +10 -0
- package/dist/models/query/Variables.js.map +1 -0
- package/dist/requests/Url.d.ts +5 -0
- package/dist/requests/Url.js +12 -0
- package/dist/requests/Url.js.map +1 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.js +9 -10
- package/dist/server.js.map +1 -1
- package/dist/services/accounts/AccountService.d.ts +6 -0
- package/dist/services/accounts/AccountService.js +20 -0
- package/dist/services/accounts/AccountService.js.map +1 -1
- package/dist/services/auth/AccountService.d.ts +88 -0
- package/dist/services/auth/AccountService.js +392 -0
- package/dist/services/auth/AccountService.js.map +1 -0
- package/dist/services/auth/AuthService.d.ts +31 -0
- package/dist/services/auth/AuthService.js +118 -0
- package/dist/services/auth/AuthService.js.map +1 -0
- package/dist/services/auth/LoginFlows.d.ts +77 -0
- package/dist/services/auth/LoginFlows.js +92 -0
- package/dist/services/auth/LoginFlows.js.map +1 -0
- package/dist/services/data/TweetService.d.ts +46 -16
- package/dist/services/data/TweetService.js +71 -54
- package/dist/services/data/TweetService.js.map +1 -1
- package/dist/services/data/UserService.d.ts +45 -21
- package/dist/services/data/UserService.js +78 -75
- package/dist/services/data/UserService.js.map +1 -1
- package/dist/services/helper/Headers.d.ts +4 -4
- package/dist/services/helper/Headers.js.map +1 -1
- package/dist/services/helper/Parser.d.ts +2 -2
- package/dist/services/helper/Parser.js.map +1 -1
- package/dist/services/helper/extractors/Tweets.d.ts +6 -6
- package/dist/services/helper/extractors/Tweets.js +1 -1
- package/dist/services/helper/extractors/Tweets.js.map +1 -1
- package/dist/services/helper/extractors/Users.d.ts +4 -4
- package/dist/services/helper/extractors/Users.js +1 -1
- package/dist/services/helper/extractors/Users.js.map +1 -1
- package/dist/services/helper/payloads/LoginFlows.d.ts +77 -0
- package/dist/services/helper/payloads/LoginFlows.js +92 -0
- package/dist/services/helper/payloads/LoginFlows.js.map +1 -0
- package/dist/services/util/CacheService.d.ts +33 -0
- package/dist/services/util/CacheService.js +96 -0
- package/dist/services/util/CacheService.js.map +1 -0
- package/dist/services/util/FetcherService.d.ts +65 -0
- package/dist/services/util/FetcherService.js +214 -0
- package/dist/services/util/FetcherService.js.map +1 -0
- package/dist/types/Args.d.ts +38 -0
- package/dist/types/Args.js +5 -0
- package/dist/types/Args.js.map +1 -0
- package/dist/types/Authentication.d.ts +17 -2
- package/dist/types/Authentication.js +1 -0
- package/dist/types/Authentication.js.map +1 -1
- package/dist/types/Resolvers.d.ts +5 -4
- package/dist/types/Rettiwt.d.ts +16 -0
- package/dist/types/Rettiwt.js +3 -0
- package/dist/types/Rettiwt.js.map +1 -0
- package/dist/types/Service.d.ts +15 -23
- package/dist/types/Service.js +2 -16
- package/dist/types/Service.js.map +1 -1
- package/dist/types/Tweet.d.ts +25 -19
- package/dist/types/Tweet.js +0 -2
- package/dist/types/Tweet.js.map +1 -1
- package/dist/types/User.d.ts +35 -0
- package/dist/types/User.js +3 -0
- package/dist/types/User.js.map +1 -0
- package/dist/types/args/TweetFilter.d.ts +54 -0
- package/dist/types/args/TweetFilter.js +96 -0
- package/dist/types/args/TweetFilter.js.map +1 -0
- package/dist/types/args/TweetListArg.d.ts +10 -0
- package/dist/types/args/TweetListArg.js +42 -0
- package/dist/types/args/TweetListArg.js.map +1 -0
- package/dist/types/args/TweetListArgs.d.ts +20 -0
- package/dist/types/args/TweetListArgs.js +52 -0
- package/dist/types/args/TweetListArgs.js.map +1 -0
- package/dist/types/args/UserListArgs.d.ts +16 -0
- package/dist/types/args/UserListArgs.js +48 -0
- package/dist/types/args/UserListArgs.js.map +1 -0
- package/dist/types/data/Errors.d.ts +4 -1
- package/dist/types/data/Errors.js +3 -0
- package/dist/types/data/Errors.js.map +1 -1
- package/dist/types/data/TweetFilter.d.ts +49 -0
- package/dist/types/data/TweetFilter.js +63 -0
- package/dist/types/data/TweetFilter.js.map +1 -0
- package/dist/types/interfaces/Args.d.ts +38 -0
- package/dist/types/interfaces/Args.js +5 -0
- package/dist/types/interfaces/Args.js.map +1 -0
- package/dist/types/interfaces/Authentication.d.ts +40 -0
- package/dist/types/interfaces/Authentication.js +5 -0
- package/dist/types/interfaces/Authentication.js.map +1 -0
- package/dist/types/interfaces/Resolvers.d.ts +14 -0
- package/dist/types/interfaces/Resolvers.js +3 -0
- package/dist/types/interfaces/Resolvers.js.map +1 -0
- package/dist/types/interfaces/Rettiwt.d.ts +16 -0
- package/dist/types/interfaces/Rettiwt.js +3 -0
- package/dist/types/interfaces/Rettiwt.js.map +1 -0
- package/dist/types/interfaces/Service.d.ts +13 -0
- package/dist/types/interfaces/Service.js +3 -0
- package/dist/types/interfaces/Service.js.map +1 -0
- package/dist/types/interfaces/Services.d.ts +13 -0
- package/dist/types/interfaces/Services.js +3 -0
- package/dist/types/interfaces/Services.js.map +1 -0
- package/dist/types/interfaces/Tweet.d.ts +46 -0
- package/dist/types/interfaces/Tweet.js +3 -0
- package/dist/types/interfaces/Tweet.js.map +1 -0
- package/dist/types/interfaces/TweetFilter.d.ts +0 -0
- package/dist/types/interfaces/TweetFilter.js +2 -0
- package/dist/types/interfaces/TweetFilter.js.map +1 -0
- package/{src/types/data/User.ts → dist/types/interfaces/User.d.ts} +35 -51
- package/dist/types/interfaces/User.js +3 -0
- package/dist/types/interfaces/User.js.map +1 -0
- package/dist/types/raw/query/tweet/TweetDetails.d.ts +34 -0
- package/dist/types/raw/query/tweet/TweetDetails.js +5 -0
- package/dist/types/raw/query/tweet/TweetDetails.js.map +1 -0
- package/dist/types/raw/user/User.js.map +1 -1
- package/dist/types/services/args/TweetFilter.d.ts +50 -0
- package/dist/types/services/args/TweetFilter.js +76 -0
- package/dist/types/services/args/TweetFilter.js.map +1 -0
- package/docs/.nojekyll +1 -0
- package/docs/assets/highlight.css +64 -0
- package/docs/assets/main.js +58 -0
- package/docs/assets/search.js +1 -0
- package/docs/assets/style.css +1280 -0
- package/docs/classes/AccountService.html +303 -0
- package/docs/classes/AuthCookie.html +146 -0
- package/docs/classes/AuthService.html +147 -0
- package/docs/classes/CacheService.html +157 -0
- package/docs/classes/Cursor.html +102 -0
- package/docs/classes/CursoredData.html +126 -0
- package/docs/classes/DataValidationError.html +119 -0
- package/docs/classes/FetcherService.html +225 -0
- package/docs/classes/Tweet.html +210 -0
- package/docs/classes/TweetEntities.html +128 -0
- package/docs/classes/TweetFilter.html +204 -0
- package/docs/classes/TweetListArgs.html +118 -0
- package/docs/classes/TweetService.html +313 -0
- package/docs/classes/User.html +230 -0
- package/docs/classes/UserListArgs.html +118 -0
- package/docs/classes/UserService.html +315 -0
- package/docs/enums/HttpMethods.html +74 -0
- package/docs/functions/Rettiwt.html +99 -0
- package/docs/index.html +161 -0
- package/docs/interfaces/IAuthCookie.html +104 -0
- package/docs/interfaces/ICursor.html +77 -0
- package/docs/interfaces/ICursoredData.html +93 -0
- package/docs/interfaces/IDataContext.html +91 -0
- package/docs/interfaces/IListArgs.html +87 -0
- package/docs/interfaces/ITweet.html +176 -0
- package/docs/interfaces/ITweetEntities.html +104 -0
- package/docs/interfaces/ITweetFilter.html +158 -0
- package/docs/interfaces/IUser.html +194 -0
- package/docs/modules.html +109 -0
- package/package.json +5 -2
- package/src/enums/Errors.ts +21 -0
- package/src/graphql/enums/Errors.ts +21 -0
- package/src/graphql/queries/RootQuery.ts +11 -4
- package/src/graphql/resolvers/AccountResolver.ts +3 -3
- package/src/graphql/resolvers/ResolverBase.ts +19 -5
- package/src/graphql/resolvers/TweetResolver.ts +26 -17
- package/src/graphql/resolvers/UserResolver.ts +18 -20
- package/src/graphql/types/TweetTypes.ts +2 -2
- package/src/graphql/types/UserTypes.ts +1 -1
- package/src/index.ts +39 -17
- package/src/models/args/TweetFilter.ts +119 -0
- package/src/models/args/TweetListArgs.ts +47 -0
- package/src/models/args/UserListArgs.ts +47 -0
- package/src/models/auth/AuthCookie.ts +43 -0
- package/src/models/data/CursoredData.ts +45 -0
- package/src/models/data/Tweet.ts +118 -0
- package/src/models/data/User.ts +72 -0
- package/src/models/errors/DataValidationError.ts +29 -0
- package/src/server.ts +9 -10
- package/src/services/{accounts → auth}/AccountService.ts +92 -17
- package/src/services/auth/AuthService.ts +81 -0
- package/src/services/data/TweetService.ts +77 -58
- package/src/services/data/UserService.ts +93 -89
- package/src/services/helper/Headers.ts +4 -4
- package/src/services/helper/Parser.ts +2 -2
- package/src/services/helper/extractors/Tweets.ts +7 -7
- package/src/services/helper/extractors/Users.ts +5 -5
- package/src/services/{CacheService.ts → util/CacheService.ts} +4 -1
- package/src/services/{FetcherService.ts → util/FetcherService.ts} +19 -11
- package/src/types/Args.ts +49 -0
- package/src/types/Authentication.ts +29 -7
- package/src/types/Resolvers.ts +5 -4
- package/src/types/Rettiwt.ts +20 -0
- package/src/types/Service.ts +24 -0
- package/src/types/Tweet.ts +61 -0
- package/src/types/User.ts +48 -0
- package/tsconfig.json +2 -2
- package/src/services/AuthService.ts +0 -68
- package/src/services/helper/deserializers/Tweets.ts +0 -70
- package/src/services/helper/deserializers/Users.ts +0 -26
- package/src/types/data/Errors.ts +0 -34
- package/src/types/data/Service.ts +0 -55
- package/src/types/data/Tweet.ts +0 -123
- package/src/types/raw/auth/Cookie.ts +0 -16
- /package/src/{types → enums}/HTTP.ts +0 -0
- /package/src/services/{accounts → helper/payloads}/LoginFlows.ts +0 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// TYPES
|
|
2
|
+
import { ITweet, ITweetEntities } from '../../types/Tweet';
|
|
3
|
+
import { Result as RawTweet, Entities2 as RawTweetEntities } from '../../types/raw/tweet/Tweet';
|
|
4
|
+
|
|
5
|
+
// PARSERS
|
|
6
|
+
import * as Parsers from '../../services/helper/Parser';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The different types parsed entities like urls, media, mentions, hashtags, etc.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
export class TweetEntities implements ITweetEntities {
|
|
14
|
+
// MEMBER DATA
|
|
15
|
+
/** The list of hashtags mentioned in the tweet. */
|
|
16
|
+
hashtags: string[] = [];
|
|
17
|
+
|
|
18
|
+
/** The list of urls mentioned in the tweet. */
|
|
19
|
+
urls: string[] = [];
|
|
20
|
+
|
|
21
|
+
/** The list of IDs of users mentioned in the tweet. */
|
|
22
|
+
mentionedUsers: string[] = [];
|
|
23
|
+
|
|
24
|
+
/** The list of urls to various media mentioned in the tweet. */
|
|
25
|
+
media: string[] = [];
|
|
26
|
+
|
|
27
|
+
// MEMBER METHODS
|
|
28
|
+
constructor(entities: RawTweetEntities) {
|
|
29
|
+
// Extracting user mentions
|
|
30
|
+
if (entities.user_mentions) {
|
|
31
|
+
for (let user of entities.user_mentions) {
|
|
32
|
+
this.mentionedUsers.push(user.id_str);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Extracting urls
|
|
37
|
+
if (entities.urls) {
|
|
38
|
+
for (let url of entities.urls) {
|
|
39
|
+
this.urls.push(url.expanded_url);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Extracting hashtags
|
|
44
|
+
if (entities.hashtags) {
|
|
45
|
+
for (let hashtag of entities.hashtags) {
|
|
46
|
+
this.hashtags.push(hashtag.text);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Extracting media urls (if any)
|
|
51
|
+
if (entities.media) {
|
|
52
|
+
for (const media of entities.media) {
|
|
53
|
+
this.media.push(media.media_url_https);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The details of a single Tweet.
|
|
61
|
+
*
|
|
62
|
+
* @internal
|
|
63
|
+
*/
|
|
64
|
+
export class Tweet implements ITweet {
|
|
65
|
+
/** The rest id of the tweet. */
|
|
66
|
+
id: string;
|
|
67
|
+
|
|
68
|
+
/** The rest id of the user who made the tweet. */
|
|
69
|
+
tweetBy: string;
|
|
70
|
+
|
|
71
|
+
/** The date and time of creation of the tweet, in UTC string format. */
|
|
72
|
+
createdAt: string;
|
|
73
|
+
|
|
74
|
+
/** Additional tweet entities like urls, mentions, etc. */
|
|
75
|
+
entities: TweetEntities;
|
|
76
|
+
|
|
77
|
+
/** The rest id of the tweet which is quoted in the tweet. */
|
|
78
|
+
quoted: string;
|
|
79
|
+
|
|
80
|
+
/** The full text content of the tweet. */
|
|
81
|
+
fullText: string;
|
|
82
|
+
|
|
83
|
+
/** The rest id of the user to which the tweet is a reply. */
|
|
84
|
+
replyTo: string;
|
|
85
|
+
|
|
86
|
+
/** The language in which the tweet is written. */
|
|
87
|
+
lang: string;
|
|
88
|
+
|
|
89
|
+
/** The number of quotes of the tweet. */
|
|
90
|
+
quoteCount: number;
|
|
91
|
+
|
|
92
|
+
/** The number of replies to the tweet. */
|
|
93
|
+
replyCount: number;
|
|
94
|
+
|
|
95
|
+
/** The number of retweets of the tweet. */
|
|
96
|
+
retweetCount: number;
|
|
97
|
+
|
|
98
|
+
/** The number of likes of the tweet. */
|
|
99
|
+
likeCount: number;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @param tweet The raw tweet data.
|
|
103
|
+
*/
|
|
104
|
+
constructor(tweet: RawTweet) {
|
|
105
|
+
this.id = tweet.rest_id;
|
|
106
|
+
this.createdAt = tweet.legacy.created_at;
|
|
107
|
+
this.tweetBy = tweet.legacy.user_id_str;
|
|
108
|
+
this.entities = new TweetEntities(tweet.legacy.entities);
|
|
109
|
+
this.quoted = tweet.legacy.quoted_status_id_str;
|
|
110
|
+
this.fullText = Parsers.normalizeText(tweet.legacy.full_text);
|
|
111
|
+
this.replyTo = tweet.legacy.in_reply_to_status_id_str;
|
|
112
|
+
this.lang = tweet.legacy.lang;
|
|
113
|
+
this.quoteCount = tweet.legacy.quote_count;
|
|
114
|
+
this.replyCount = tweet.legacy.reply_count;
|
|
115
|
+
this.retweetCount = tweet.legacy.retweet_count;
|
|
116
|
+
this.likeCount = tweet.legacy.favorite_count;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// TYPES
|
|
2
|
+
import { IUser } from '../../types/User';
|
|
3
|
+
import { Result as RawUser } from '../../types/raw/user/User';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The details of a single user.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export class User implements IUser {
|
|
11
|
+
/** The rest id of the user. */
|
|
12
|
+
id: string;
|
|
13
|
+
|
|
14
|
+
/** The username/screenname of the user. */
|
|
15
|
+
userName: string;
|
|
16
|
+
|
|
17
|
+
/** The full name of the user. */
|
|
18
|
+
fullName: string;
|
|
19
|
+
|
|
20
|
+
/** The creation date of user's account. */
|
|
21
|
+
createdAt: string;
|
|
22
|
+
|
|
23
|
+
/** The user's description. */
|
|
24
|
+
description: string;
|
|
25
|
+
|
|
26
|
+
/** Whether the account is verified or not. */
|
|
27
|
+
isVerified: boolean;
|
|
28
|
+
|
|
29
|
+
/** The number of tweets liked by the user. */
|
|
30
|
+
favouritesCount: number;
|
|
31
|
+
|
|
32
|
+
/** The number of followers of the user. */
|
|
33
|
+
followersCount: number;
|
|
34
|
+
|
|
35
|
+
/** The number of following of the user. */
|
|
36
|
+
followingsCount: number;
|
|
37
|
+
|
|
38
|
+
/** The number of tweets made by the user. */
|
|
39
|
+
statusesCount: number;
|
|
40
|
+
|
|
41
|
+
/** The location of user as provided by user. */
|
|
42
|
+
location: string;
|
|
43
|
+
|
|
44
|
+
/** The rest id of the tweet pinned in the user's profile. */
|
|
45
|
+
pinnedTweet: string;
|
|
46
|
+
|
|
47
|
+
/** The url of the profile banner image. */
|
|
48
|
+
profileBanner: string;
|
|
49
|
+
|
|
50
|
+
/** The url of the profile image. */
|
|
51
|
+
profileImage: string;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param user The raw user data.
|
|
55
|
+
*/
|
|
56
|
+
constructor(user: RawUser) {
|
|
57
|
+
this.id = user.rest_id;
|
|
58
|
+
this.userName = user.legacy.screen_name;
|
|
59
|
+
this.fullName = user.legacy.name;
|
|
60
|
+
this.createdAt = user.legacy.created_at;
|
|
61
|
+
this.description = user.legacy.description;
|
|
62
|
+
this.isVerified = user.legacy.verified;
|
|
63
|
+
this.favouritesCount = user.legacy.favourites_count;
|
|
64
|
+
this.followersCount = user.legacy.followers_count;
|
|
65
|
+
this.followingsCount = user.legacy.friends_count;
|
|
66
|
+
this.statusesCount = user.legacy.statuses_count;
|
|
67
|
+
this.location = user.legacy.location;
|
|
68
|
+
this.pinnedTweet = user.legacy.pinned_tweet_ids_str[0];
|
|
69
|
+
this.profileBanner = user.legacy.profile_banner_url;
|
|
70
|
+
this.profileImage = user.legacy.profile_image_url_https;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// PACKAGES
|
|
2
|
+
import { ValidationError } from "class-validator";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Error when any fields of a JSON data fails to validate.
|
|
6
|
+
*
|
|
7
|
+
* @internal
|
|
8
|
+
*
|
|
9
|
+
* @param errorDetails The details of about the specific fields that failed to validate.
|
|
10
|
+
*/
|
|
11
|
+
export class DataValidationError implements Error {
|
|
12
|
+
/** The name of the error. */
|
|
13
|
+
name: string;
|
|
14
|
+
|
|
15
|
+
/** The user-friendly error message. */
|
|
16
|
+
message: string;
|
|
17
|
+
|
|
18
|
+
/** The error data. */
|
|
19
|
+
data: ValidationError[];
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param data The error details.
|
|
23
|
+
*/
|
|
24
|
+
constructor(errorDetails: ValidationError[]) {
|
|
25
|
+
this.name = 'ValidationError';
|
|
26
|
+
this.message = 'One or more validation errors occured. Refer to data for details';
|
|
27
|
+
this.data = errorDetails;
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/server.ts
CHANGED
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
import express from 'express';
|
|
3
3
|
import { graphqlHTTP } from 'express-graphql';
|
|
4
4
|
import { GraphQLSchema } from 'graphql';
|
|
5
|
+
import 'reflect-metadata';
|
|
5
6
|
|
|
6
|
-
//
|
|
7
|
-
import {
|
|
8
|
-
import { TweetService } from './services/data/TweetService';
|
|
9
|
-
import { AccountService } from './services/accounts/AccountService';
|
|
10
|
-
import { AuthService } from './services/AuthService';
|
|
7
|
+
// SERVICES
|
|
8
|
+
import { Rettiwt } from '.';
|
|
11
9
|
|
|
12
10
|
// SCHEMA
|
|
13
11
|
import { rootQuery } from './graphql/queries/RootQuery';
|
|
@@ -23,11 +21,12 @@ app.use('/graphql', graphqlHTTP(req => ({
|
|
|
23
21
|
schema: new GraphQLSchema({
|
|
24
22
|
query: rootQuery
|
|
25
23
|
}),
|
|
26
|
-
context: {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
context: Rettiwt({
|
|
25
|
+
auth_token: req.headers['auth_token'] as string,
|
|
26
|
+
ct0: req.headers['ct0'] as string,
|
|
27
|
+
kdt: req.headers['kdt'] as string,
|
|
28
|
+
twid: req.headers['twid'] as string,
|
|
29
|
+
}),
|
|
31
30
|
// If app is running in development environment, enable graphiql
|
|
32
31
|
graphiql: config.is_development
|
|
33
32
|
})));
|
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
import { curly, CurlyResult } from 'node-libcurl';
|
|
3
3
|
|
|
4
4
|
// SERVICES
|
|
5
|
-
import { AuthService } from '
|
|
5
|
+
import { AuthService } from './AuthService';
|
|
6
6
|
|
|
7
7
|
// TYPES
|
|
8
|
-
import {
|
|
8
|
+
import { IGuestCredentials, IAuthCookie } from '../../types/Authentication';
|
|
9
|
+
|
|
10
|
+
// ENUMS
|
|
11
|
+
import { HttpStatus } from '../../enums/HTTP';
|
|
12
|
+
import { AuthenticationErrors } from '../../enums/Errors';
|
|
9
13
|
|
|
10
14
|
// HELPERS
|
|
11
|
-
import LoginFlows from '
|
|
15
|
+
import LoginFlows from '../helper/payloads/LoginFlows';
|
|
12
16
|
import { loginHeader } from '../helper/Headers';
|
|
13
17
|
import { Cookie, CookieJar } from 'cookiejar';
|
|
14
18
|
|
|
@@ -17,12 +21,11 @@ import { Cookie, CookieJar } from 'cookiejar';
|
|
|
17
21
|
* @public
|
|
18
22
|
*/
|
|
19
23
|
export class AccountService {
|
|
20
|
-
// MEMBER DATA
|
|
21
24
|
/** The AuthService instance to use for authentication. */
|
|
22
25
|
private auth: AuthService;
|
|
23
26
|
|
|
24
27
|
/** The current guest credentials to use. */
|
|
25
|
-
private guestCreds:
|
|
28
|
+
private guestCreds: IGuestCredentials;
|
|
26
29
|
|
|
27
30
|
/** The cookies received from Twitter after logging in. */
|
|
28
31
|
private cookies: Cookie[];
|
|
@@ -30,7 +33,6 @@ export class AccountService {
|
|
|
30
33
|
/** The flow token received after execution of current flow. */
|
|
31
34
|
private flowToken: string;
|
|
32
35
|
|
|
33
|
-
// MEMBER METHODS
|
|
34
36
|
constructor() {
|
|
35
37
|
this.auth = new AuthService();
|
|
36
38
|
this.guestCreds = { authToken: '', guestToken: '' };
|
|
@@ -41,7 +43,7 @@ export class AccountService {
|
|
|
41
43
|
/**
|
|
42
44
|
* @returns The current guest credentials to use. If if does not exists, then a new one is created
|
|
43
45
|
*/
|
|
44
|
-
private async getGuestCredentials(): Promise<
|
|
46
|
+
private async getGuestCredentials(): Promise<IGuestCredentials> {
|
|
45
47
|
// If a guest credential has not been already set, get a new one
|
|
46
48
|
if (!this.guestCreds.guestToken) {
|
|
47
49
|
this.guestCreds = await this.auth.getGuestCredentials();
|
|
@@ -88,6 +90,8 @@ export class AccountService {
|
|
|
88
90
|
/**
|
|
89
91
|
* Step 3: Takes the email for login
|
|
90
92
|
* @internal
|
|
93
|
+
*
|
|
94
|
+
* @throws {@link AuthenticationErrors.InvalidEmail}, if email does not exist.
|
|
91
95
|
*/
|
|
92
96
|
private async enterUserIdentifier(email: string): Promise<void> {
|
|
93
97
|
// Executing the flow
|
|
@@ -97,6 +101,11 @@ export class AccountService {
|
|
|
97
101
|
postFields: JSON.stringify(LoginFlows.EnterUserIdentifier.body(this.flowToken, email))
|
|
98
102
|
});
|
|
99
103
|
|
|
104
|
+
// If no account found with given email
|
|
105
|
+
if (res.statusCode == HttpStatus.BadRequest && res.data.errors[0].code == 399) {
|
|
106
|
+
throw new Error(AuthenticationErrors.InvalidEmail);
|
|
107
|
+
}
|
|
108
|
+
|
|
100
109
|
// Getting the flow token
|
|
101
110
|
this.flowToken = res.data['flow_token'];
|
|
102
111
|
}
|
|
@@ -104,6 +113,8 @@ export class AccountService {
|
|
|
104
113
|
/**
|
|
105
114
|
* Step 4: Takes the username for login
|
|
106
115
|
* @internal
|
|
116
|
+
*
|
|
117
|
+
* @throws {@link AuthenticationErrors.InvalidUsername}, if wrong username entered.
|
|
107
118
|
*/
|
|
108
119
|
private async enterAlternateUserIdentifier(userName: string): Promise<void> {
|
|
109
120
|
// Executing the flow
|
|
@@ -113,6 +124,11 @@ export class AccountService {
|
|
|
113
124
|
postFields: JSON.stringify(LoginFlows.EnterAlternateUserIdentifier.body(this.flowToken, userName))
|
|
114
125
|
});
|
|
115
126
|
|
|
127
|
+
// If invalid username for the given account
|
|
128
|
+
if (res.statusCode == HttpStatus.BadRequest && res.data.errors[0].code == 399) {
|
|
129
|
+
throw new Error(AuthenticationErrors.InvalidUsername);
|
|
130
|
+
}
|
|
131
|
+
|
|
116
132
|
// Getting the flow token
|
|
117
133
|
this.flowToken = res.data['flow_token'];
|
|
118
134
|
}
|
|
@@ -120,6 +136,8 @@ export class AccountService {
|
|
|
120
136
|
/**
|
|
121
137
|
* Step 5: Takes the password for login
|
|
122
138
|
* @internal
|
|
139
|
+
*
|
|
140
|
+
* @throws {@link AuthenticationErrors.InvalidPassword}, incorrect password entered.
|
|
123
141
|
*/
|
|
124
142
|
private async enterPassword(password: string): Promise<void> {
|
|
125
143
|
// Executing the flow
|
|
@@ -129,6 +147,11 @@ export class AccountService {
|
|
|
129
147
|
postFields: JSON.stringify(LoginFlows.EnterPassword.body(this.flowToken, password))
|
|
130
148
|
});
|
|
131
149
|
|
|
150
|
+
// If invalid password for the given account
|
|
151
|
+
if (res.statusCode == HttpStatus.BadRequest && res.data.errors[0].code == 399) {
|
|
152
|
+
throw new Error(AuthenticationErrors.InvalidPassword);
|
|
153
|
+
}
|
|
154
|
+
|
|
132
155
|
// Getting the flow token
|
|
133
156
|
this.flowToken = res.data['flow_token'];
|
|
134
157
|
}
|
|
@@ -153,15 +176,15 @@ export class AccountService {
|
|
|
153
176
|
}
|
|
154
177
|
|
|
155
178
|
/**
|
|
156
|
-
*
|
|
157
|
-
* @public
|
|
179
|
+
* Execute all the flows required to login to Twitter, using the given credentials, then set the response cookies.
|
|
158
180
|
*
|
|
159
|
-
* @
|
|
160
|
-
*
|
|
161
|
-
* @param
|
|
162
|
-
* @
|
|
181
|
+
* @internal
|
|
182
|
+
*
|
|
183
|
+
* @param email The email of the account to be logged into.
|
|
184
|
+
* @param userName The username associated with the given account.
|
|
185
|
+
* @param password The password to the account.
|
|
163
186
|
*/
|
|
164
|
-
|
|
187
|
+
private async executeLoginFlows(email: string, userName: string, password: string): Promise<void> {
|
|
165
188
|
/**
|
|
166
189
|
* This works by sending a chain of request that are required for login to twitter.
|
|
167
190
|
* Each method in the chain returns a flow token that must be provied as payload in the next method in the chain.
|
|
@@ -174,9 +197,61 @@ export class AccountService {
|
|
|
174
197
|
await this.enterUserIdentifier(email);
|
|
175
198
|
await this.enterAlternateUserIdentifier(userName);
|
|
176
199
|
await this.enterPassword(password);
|
|
177
|
-
await this.accountDuplicationCheck();
|
|
200
|
+
await this.accountDuplicationCheck();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Parse the authentication cookies recieved from Twitter into known format.
|
|
205
|
+
*
|
|
206
|
+
* @internal
|
|
207
|
+
*
|
|
208
|
+
* @param cookies The raw cookies received from Twitter.
|
|
209
|
+
*
|
|
210
|
+
* @returns The parsed cookies of type {@link AuthCookie}
|
|
211
|
+
*/
|
|
212
|
+
private parseCookies(cookies: Cookie[]): IAuthCookie {
|
|
213
|
+
/** The tempoorary parsed cookies. */
|
|
214
|
+
let tempCookies: any = {};
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Parsing the cookies into a standard JSON format.
|
|
218
|
+
* The format is 'cookie_name': 'cookie_value'.
|
|
219
|
+
* All other cookie parameters like expiry, etc are dropped.
|
|
220
|
+
*/
|
|
221
|
+
cookies.forEach(cookie => {
|
|
222
|
+
tempCookies[cookie.name] = cookie.value;
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
kdt: tempCookies['kdt'],
|
|
227
|
+
twid: tempCookies['twid'],
|
|
228
|
+
ct0: tempCookies['ct0'],
|
|
229
|
+
auth_token: tempCookies['auth_token']
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Login to Twitter using the given credentials and get back the cookies.
|
|
235
|
+
*
|
|
236
|
+
* @public
|
|
237
|
+
*
|
|
238
|
+
* @param email The email of the account to be logged into.
|
|
239
|
+
* @param userName The username associated with the given account.
|
|
240
|
+
* @param password The password to the account.
|
|
241
|
+
*
|
|
242
|
+
* @returns The cookies for authenticating with the given account.
|
|
243
|
+
*/
|
|
244
|
+
public async login(email: string, userName: string, password: string): Promise<IAuthCookie> {
|
|
245
|
+
/** The parsed cookies that will be returned. */
|
|
246
|
+
let parsedCookies: IAuthCookie;
|
|
247
|
+
|
|
248
|
+
// Executing all login flows
|
|
249
|
+
await this.executeLoginFlows(email, userName, password);
|
|
250
|
+
|
|
251
|
+
// Parsing the cookies
|
|
252
|
+
parsedCookies = this.parseCookies(this.cookies);
|
|
178
253
|
|
|
179
|
-
// Returning the final cookies
|
|
180
|
-
return
|
|
254
|
+
// Returning the final parsed cookies
|
|
255
|
+
return parsedCookies;
|
|
181
256
|
}
|
|
182
257
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// PACKAGE
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
|
|
4
|
+
// URLS
|
|
5
|
+
import { guestTokenUrl } from '../helper/urls/Authentication';
|
|
6
|
+
|
|
7
|
+
// MODELS
|
|
8
|
+
import { AuthCookie } from '../../models/auth/AuthCookie';
|
|
9
|
+
|
|
10
|
+
// TYPES
|
|
11
|
+
import { IGuestCredentials, IAuthCredentials } from '../../types/Authentication';
|
|
12
|
+
|
|
13
|
+
// CONFIGS
|
|
14
|
+
import { config } from '../../config/env';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Handles authentication of http requests and other authentication related tasks.
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export class AuthService {
|
|
22
|
+
/** The common bearer token for authentication. */
|
|
23
|
+
private authToken: string;
|
|
24
|
+
|
|
25
|
+
/** The current authentication credentials. */
|
|
26
|
+
private credentials: IAuthCredentials;
|
|
27
|
+
|
|
28
|
+
/** Whether instance has been authenticated or not. */
|
|
29
|
+
public isAuthenticated: boolean;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param cookie The cookie to be used for authenticating.
|
|
33
|
+
*
|
|
34
|
+
* @remarks
|
|
35
|
+
*
|
|
36
|
+
* If no cookie is supplied, then guest authentication is used.
|
|
37
|
+
*/
|
|
38
|
+
constructor(cookie?: AuthCookie) {
|
|
39
|
+
// Reading the auth token from the config, since it's always the same
|
|
40
|
+
this.authToken = config.twitter_auth_token;
|
|
41
|
+
|
|
42
|
+
// Setting authentication status
|
|
43
|
+
this.isAuthenticated = (cookie?.auth_token && cookie?.ct0 && cookie?.kdt && cookie?.twid) ? true : false;
|
|
44
|
+
|
|
45
|
+
// If a cookies is supplied, initializing authenticated credentials
|
|
46
|
+
if (this.isAuthenticated) {
|
|
47
|
+
// Converting the cookie from JSON to object
|
|
48
|
+
cookie = new AuthCookie(cookie);
|
|
49
|
+
|
|
50
|
+
// Setting up the authenticated credentials
|
|
51
|
+
this.credentials = { authToken: this.authToken, csrfToken: cookie.ct0, cookie: cookie.toString() };
|
|
52
|
+
}
|
|
53
|
+
// If no cookie has been supplied, initializing empty credentials
|
|
54
|
+
else {
|
|
55
|
+
// Setting up the authenticated credentials
|
|
56
|
+
this.credentials = { authToken: this.authToken, csrfToken: '', cookie: '' };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @returns The current authentication credentials. A different credential is returned each time this is invoked
|
|
62
|
+
*/
|
|
63
|
+
async getAuthCredentials(): Promise<IAuthCredentials> {
|
|
64
|
+
return this.credentials;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @returns The guest credentials fetched from twitter.
|
|
69
|
+
*/
|
|
70
|
+
async getGuestCredentials(): Promise<IGuestCredentials> {
|
|
71
|
+
// Getting the guest credentials from twitter
|
|
72
|
+
return await axios.post<{ guest_token: string }>(guestTokenUrl(), null, {
|
|
73
|
+
headers: {
|
|
74
|
+
'Authorization': this.authToken
|
|
75
|
+
}
|
|
76
|
+
}).then(res => ({
|
|
77
|
+
authToken: this.authToken,
|
|
78
|
+
guestToken: res.data.guest_token
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
}
|