rettiwt-api 1.4.0 → 2.0.1
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/.eslintignore +3 -0
- package/.eslintrc.js +54 -0
- package/.github/workflows/documentation.yml +29 -9
- package/.github/workflows/publish.yml +8 -3
- package/.prettierignore +3 -0
- package/.prettierrc +13 -0
- package/README.md +59 -61
- package/dist/Rettiwt.d.ts +19 -0
- package/dist/Rettiwt.js +30 -0
- package/dist/Rettiwt.js.map +1 -0
- package/dist/enums/ApiErrors.d.ts +30 -0
- package/dist/enums/ApiErrors.js +35 -0
- package/dist/enums/ApiErrors.js.map +1 -0
- package/dist/enums/HTTP.d.ts +11 -11
- package/dist/enums/HTTP.js +15 -16
- package/dist/enums/HTTP.js.map +1 -1
- package/dist/helper/JsonUtils.d.ts +26 -0
- package/dist/helper/JsonUtils.js +88 -0
- package/dist/helper/JsonUtils.js.map +1 -0
- package/dist/index.d.ts +10 -43
- package/dist/index.js +16 -55
- package/dist/index.js.map +1 -1
- package/dist/models/CursoredData.d.ts +37 -0
- package/dist/models/CursoredData.js +59 -0
- package/dist/models/CursoredData.js.map +1 -0
- package/dist/models/{data/Tweet.d.ts → Tweet.d.ts} +4 -4
- package/dist/models/{data/Tweet.js → Tweet.js} +7 -32
- package/dist/models/Tweet.js.map +1 -0
- package/dist/models/{data/User.d.ts → User.d.ts} +3 -3
- package/dist/models/{data/User.js → User.js} +3 -3
- package/dist/models/User.js.map +1 -0
- package/dist/services/FetcherService.d.ts +66 -0
- package/dist/services/FetcherService.js +209 -0
- package/dist/services/FetcherService.js.map +1 -0
- package/dist/services/TweetService.d.ts +88 -0
- package/dist/services/TweetService.js +244 -0
- package/dist/services/TweetService.js.map +1 -0
- package/dist/services/UserService.d.ts +60 -0
- package/dist/services/UserService.js +188 -0
- package/dist/services/UserService.js.map +1 -0
- package/dist/types/{Service.d.ts → CursoredData.d.ts} +3 -3
- package/dist/types/CursoredData.js +3 -0
- package/dist/types/CursoredData.js.map +1 -0
- package/dist/types/Tweet.js +1 -1
- package/dist/types/User.js +1 -1
- package/package.json +15 -19
- package/src/Rettiwt.ts +33 -0
- package/src/enums/ApiErrors.ts +30 -0
- package/src/enums/HTTP.ts +12 -12
- package/src/helper/JsonUtils.ts +86 -0
- package/src/index.ts +14 -57
- package/src/models/CursoredData.ts +64 -0
- package/src/models/Tweet.ts +116 -0
- package/src/models/User.ts +72 -0
- package/src/services/FetcherService.ts +186 -0
- package/src/services/TweetService.ts +153 -0
- package/src/services/UserService.ts +117 -0
- package/src/types/CursoredData.ts +24 -0
- package/src/types/Tweet.ts +35 -35
- package/src/types/User.ts +30 -30
- package/tsconfig.json +9 -9
- package/dist/config/env.d.ts +0 -5
- package/dist/config/env.js +0 -9
- package/dist/config/env.js.map +0 -1
- package/dist/enums/Errors.d.ts +0 -21
- package/dist/enums/Errors.js +0 -29
- package/dist/enums/Errors.js.map +0 -1
- package/dist/graphql/enums/Errors.d.ts +0 -21
- package/dist/graphql/enums/Errors.js +0 -29
- package/dist/graphql/enums/Errors.js.map +0 -1
- package/dist/graphql/queries/RootQuery.d.ts +0 -4
- package/dist/graphql/queries/RootQuery.js +0 -83
- package/dist/graphql/queries/RootQuery.js.map +0 -1
- package/dist/graphql/resolvers/AccountResolver.d.ts +0 -12
- package/dist/graphql/resolvers/AccountResolver.js +0 -84
- package/dist/graphql/resolvers/AccountResolver.js.map +0 -1
- package/dist/graphql/resolvers/ResolverBase.d.ts +0 -16
- package/dist/graphql/resolvers/ResolverBase.js +0 -23
- package/dist/graphql/resolvers/ResolverBase.js.map +0 -1
- package/dist/graphql/resolvers/TweetResolver.d.ts +0 -46
- package/dist/graphql/resolvers/TweetResolver.js +0 -302
- package/dist/graphql/resolvers/TweetResolver.js.map +0 -1
- package/dist/graphql/resolvers/UserResolver.d.ts +0 -48
- package/dist/graphql/resolvers/UserResolver.js +0 -334
- package/dist/graphql/resolvers/UserResolver.js.map +0 -1
- package/dist/graphql/types/Global.d.ts +0 -4
- package/dist/graphql/types/Global.js +0 -13
- package/dist/graphql/types/Global.js.map +0 -1
- package/dist/graphql/types/TweetTypes.d.ts +0 -4
- package/dist/graphql/types/TweetTypes.js +0 -160
- package/dist/graphql/types/TweetTypes.js.map +0 -1
- package/dist/graphql/types/UserTypes.d.ts +0 -3
- package/dist/graphql/types/UserTypes.js +0 -137
- package/dist/graphql/types/UserTypes.js.map +0 -1
- package/dist/models/args/TweetListArgs.d.ts +0 -21
- package/dist/models/args/TweetListArgs.js +0 -54
- package/dist/models/args/TweetListArgs.js.map +0 -1
- package/dist/models/args/UserListArgs.d.ts +0 -21
- package/dist/models/args/UserListArgs.js +0 -54
- package/dist/models/args/UserListArgs.js.map +0 -1
- package/dist/models/auth/AuthCookie.d.ts +0 -21
- package/dist/models/auth/AuthCookie.js +0 -33
- package/dist/models/auth/AuthCookie.js.map +0 -1
- package/dist/models/data/CursoredData.d.ts +0 -34
- package/dist/models/data/CursoredData.js +0 -42
- package/dist/models/data/CursoredData.js.map +0 -1
- package/dist/models/data/Tweet.js.map +0 -1
- package/dist/models/data/User.js.map +0 -1
- package/dist/server.d.ts +0 -1
- package/dist/server.js +0 -76
- package/dist/server.js.map +0 -1
- package/dist/services/auth/AccountService.d.ts +0 -83
- package/dist/services/auth/AccountService.js +0 -412
- package/dist/services/auth/AccountService.js.map +0 -1
- package/dist/services/auth/AuthService.d.ts +0 -31
- package/dist/services/auth/AuthService.js +0 -118
- package/dist/services/auth/AuthService.js.map +0 -1
- package/dist/services/data/TweetService.d.ts +0 -60
- package/dist/services/data/TweetService.js +0 -250
- package/dist/services/data/TweetService.js.map +0 -1
- package/dist/services/data/UserService.d.ts +0 -71
- package/dist/services/data/UserService.js +0 -278
- package/dist/services/data/UserService.js.map +0 -1
- package/dist/services/helper/Headers.d.ts +0 -19
- package/dist/services/helper/Headers.js +0 -62
- package/dist/services/helper/Headers.js.map +0 -1
- package/dist/services/helper/Parser.d.ts +0 -22
- package/dist/services/helper/Parser.js +0 -84
- package/dist/services/helper/Parser.js.map +0 -1
- package/dist/services/helper/extractors/Tweets.d.ts +0 -23
- package/dist/services/helper/extractors/Tweets.js +0 -200
- package/dist/services/helper/extractors/Tweets.js.map +0 -1
- package/dist/services/helper/extractors/Users.d.ts +0 -17
- package/dist/services/helper/extractors/Users.js +0 -151
- package/dist/services/helper/extractors/Users.js.map +0 -1
- package/dist/services/helper/payloads/LoginFlows.d.ts +0 -77
- package/dist/services/helper/payloads/LoginFlows.js +0 -92
- package/dist/services/helper/payloads/LoginFlows.js.map +0 -1
- package/dist/services/helper/urls/Authentication.d.ts +0 -4
- package/dist/services/helper/urls/Authentication.js +0 -11
- package/dist/services/helper/urls/Authentication.js.map +0 -1
- package/dist/services/util/CacheService.d.ts +0 -33
- package/dist/services/util/CacheService.js +0 -96
- package/dist/services/util/CacheService.js.map +0 -1
- package/dist/services/util/FetcherService.d.ts +0 -65
- package/dist/services/util/FetcherService.js +0 -202
- package/dist/services/util/FetcherService.js.map +0 -1
- package/dist/types/Args.d.ts +0 -11
- package/dist/types/Args.js +0 -4
- package/dist/types/Args.js.map +0 -1
- package/dist/types/Authentication.d.ts +0 -55
- package/dist/types/Authentication.js +0 -6
- package/dist/types/Authentication.js.map +0 -1
- package/dist/types/Resolvers.d.ts +0 -15
- package/dist/types/Resolvers.js +0 -3
- package/dist/types/Resolvers.js.map +0 -1
- package/dist/types/Rettiwt.d.ts +0 -16
- package/dist/types/Rettiwt.js +0 -3
- package/dist/types/Rettiwt.js.map +0 -1
- package/dist/types/Service.js +0 -5
- package/dist/types/Service.js.map +0 -1
- package/docs/.nojekyll +0 -1
- package/docs/assets/highlight.css +0 -64
- package/docs/assets/main.js +0 -58
- package/docs/assets/search.js +0 -1
- package/docs/assets/style.css +0 -1280
- package/docs/classes/AccountService.html +0 -286
- package/docs/classes/AuthCookie.html +0 -146
- package/docs/classes/AuthService.html +0 -147
- package/docs/classes/CacheService.html +0 -157
- package/docs/classes/Cursor.html +0 -102
- package/docs/classes/CursoredData.html +0 -126
- package/docs/classes/DataValidationError.html +0 -120
- package/docs/classes/FetcherService.html +0 -225
- package/docs/classes/Tweet.html +0 -210
- package/docs/classes/TweetEntities.html +0 -128
- package/docs/classes/TweetFilter.html +0 -233
- package/docs/classes/TweetListArgs.html +0 -118
- package/docs/classes/TweetService.html +0 -319
- package/docs/classes/User.html +0 -230
- package/docs/classes/UserListArgs.html +0 -118
- package/docs/classes/UserService.html +0 -355
- package/docs/enums/HttpMethods.html +0 -74
- package/docs/functions/Rettiwt.html +0 -100
- package/docs/index.html +0 -159
- package/docs/interfaces/IAuthCookie.html +0 -104
- package/docs/interfaces/ICursor.html +0 -77
- package/docs/interfaces/ICursoredData.html +0 -93
- package/docs/interfaces/IDataContext.html +0 -91
- package/docs/interfaces/IDataValidationError.html +0 -109
- package/docs/interfaces/IListArgs.html +0 -87
- package/docs/interfaces/ITweet.html +0 -176
- package/docs/interfaces/ITweetEntities.html +0 -104
- package/docs/interfaces/ITweetFilter.html +0 -158
- package/docs/interfaces/IUser.html +0 -194
- package/docs/modules.html +0 -111
- package/environment.d.ts +0 -11
- package/src/config/env.ts +0 -5
- package/src/enums/Errors.ts +0 -22
- package/src/graphql/enums/Errors.ts +0 -22
- package/src/graphql/queries/RootQuery.ts +0 -81
- package/src/graphql/resolvers/AccountResolver.ts +0 -22
- package/src/graphql/resolvers/ResolverBase.ts +0 -26
- package/src/graphql/resolvers/TweetResolver.ts +0 -225
- package/src/graphql/resolvers/UserResolver.ts +0 -257
- package/src/graphql/types/Global.ts +0 -10
- package/src/graphql/types/TweetTypes.ts +0 -158
- package/src/graphql/types/UserTypes.ts +0 -134
- package/src/models/args/TweetListArgs.ts +0 -47
- package/src/models/args/UserListArgs.ts +0 -47
- package/src/models/auth/AuthCookie.ts +0 -43
- package/src/models/data/CursoredData.ts +0 -45
- package/src/models/data/Tweet.ts +0 -118
- package/src/models/data/User.ts +0 -72
- package/src/server.ts +0 -37
- package/src/services/auth/AccountService.ts +0 -283
- package/src/services/auth/AuthService.ts +0 -81
- package/src/services/data/TweetService.ts +0 -197
- package/src/services/data/UserService.ts +0 -221
- package/src/services/helper/Headers.ts +0 -60
- package/src/services/helper/Parser.ts +0 -89
- package/src/services/helper/extractors/Tweets.ts +0 -190
- package/src/services/helper/extractors/Users.ts +0 -141
- package/src/services/helper/payloads/LoginFlows.ts +0 -90
- package/src/services/helper/urls/Authentication.ts +0 -6
- package/src/services/util/CacheService.ts +0 -76
- package/src/services/util/FetcherService.ts +0 -143
- package/src/types/Args.ts +0 -12
- package/src/types/Authentication.ts +0 -63
- package/src/types/Resolvers.ts +0 -18
- package/src/types/Rettiwt.ts +0 -20
- package/src/types/Service.ts +0 -24
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
// PACKAGES
|
|
2
|
-
import { curly, CurlyResult } from 'node-libcurl';
|
|
3
|
-
|
|
4
|
-
// SERVICES
|
|
5
|
-
import { AuthService } from './AuthService';
|
|
6
|
-
|
|
7
|
-
// TYPES
|
|
8
|
-
import { IGuestCredentials, IAuthCookie } from '../../types/Authentication';
|
|
9
|
-
|
|
10
|
-
// ENUMS
|
|
11
|
-
import { HttpStatus } from '../../enums/HTTP';
|
|
12
|
-
import { AuthenticationErrors } from '../../enums/Errors';
|
|
13
|
-
|
|
14
|
-
// HELPERS
|
|
15
|
-
import LoginFlows from '../helper/payloads/LoginFlows';
|
|
16
|
-
import { loginHeader } from '../helper/Headers';
|
|
17
|
-
import { Cookie, CookieJar } from 'cookiejar';
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Handles all operations related to a user's account, such as loggin in, managing account, etc
|
|
21
|
-
* @public
|
|
22
|
-
*/
|
|
23
|
-
export class AccountService {
|
|
24
|
-
/** The AuthService instance to use for authentication. */
|
|
25
|
-
private auth: AuthService = new AuthService();
|
|
26
|
-
|
|
27
|
-
/** The current guest credentials to use. */
|
|
28
|
-
private guestCreds: IGuestCredentials = { authToken: '', guestToken: '' };
|
|
29
|
-
|
|
30
|
-
/** The email id of Twitter account to be logged into. */
|
|
31
|
-
private email: string = '';
|
|
32
|
-
|
|
33
|
-
/** The user name of the Twitter account ot be logged into */
|
|
34
|
-
private userName: string = '';
|
|
35
|
-
|
|
36
|
-
/** The password to the Twitter account to be logged into. */
|
|
37
|
-
private password: string = '';
|
|
38
|
-
|
|
39
|
-
/** The cookies received from Twitter after logging in. */
|
|
40
|
-
private cookies: Cookie[] = [];
|
|
41
|
-
|
|
42
|
-
/** The flow token received after execution of current flow. */
|
|
43
|
-
private flowToken: string = '';
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* @returns The current guest credentials to use. If if does not exists, then a new one is created
|
|
47
|
-
*/
|
|
48
|
-
private async getGuestCredentials(): Promise<IGuestCredentials> {
|
|
49
|
-
// If a guest credential has not been already set, get a new one
|
|
50
|
-
if (!this.guestCreds.guestToken) {
|
|
51
|
-
this.guestCreds = await this.auth.getGuestCredentials();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return this.guestCreds;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Step 1: Initiates login
|
|
59
|
-
* @internal
|
|
60
|
-
*/
|
|
61
|
-
private async initiateLogin(): Promise<void> {
|
|
62
|
-
// Initiating the login process
|
|
63
|
-
const res: CurlyResult = await curly.post(LoginFlows.InitiateLogin.url, {
|
|
64
|
-
httpHeader: loginHeader(await this.getGuestCredentials(), this.cookies.toString()),
|
|
65
|
-
sslVerifyPeer: false,
|
|
66
|
-
postFields: ''
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// Storing cookies received
|
|
70
|
-
this.cookies = new CookieJar().setCookies(res.headers[0]['Set-Cookie'] as string[]);
|
|
71
|
-
|
|
72
|
-
// Getting the flow token
|
|
73
|
-
this.flowToken = res.data['flow_token'];
|
|
74
|
-
|
|
75
|
-
// Executing next subtask
|
|
76
|
-
await this.jsInstrumentationSubtask();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Step 2: Does something
|
|
81
|
-
* @internal
|
|
82
|
-
*/
|
|
83
|
-
private async jsInstrumentationSubtask(): Promise<void> {
|
|
84
|
-
// Executing the subtask
|
|
85
|
-
const res: CurlyResult = await curly.post(LoginFlows.JsInstrumentationSubtask.url, {
|
|
86
|
-
httpHeader: loginHeader(await this.getGuestCredentials(), this.cookies.join(';').toString()),
|
|
87
|
-
sslVerifyPeer: false,
|
|
88
|
-
postFields: JSON.stringify(LoginFlows.JsInstrumentationSubtask.body(this.flowToken))
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
// Getting the flow token
|
|
92
|
-
this.flowToken = res.data['flow_token'];
|
|
93
|
-
|
|
94
|
-
// Executing next subtask
|
|
95
|
-
await this.enterUserIdentifier();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Step 3: Takes the email for login
|
|
100
|
-
* @internal
|
|
101
|
-
*
|
|
102
|
-
* @throws {@link AuthenticationErrors.InvalidEmail}, if email does not exist.
|
|
103
|
-
*/
|
|
104
|
-
private async enterUserIdentifier(): Promise<void> {
|
|
105
|
-
// Executing the subtask
|
|
106
|
-
const res: CurlyResult = await curly.post(LoginFlows.EnterUserIdentifier.url, {
|
|
107
|
-
httpHeader: loginHeader(await this.getGuestCredentials(), this.cookies.join(';').toString()),
|
|
108
|
-
sslVerifyPeer: false,
|
|
109
|
-
postFields: JSON.stringify(LoginFlows.EnterUserIdentifier.body(this.flowToken, this.email))
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
// If no account found with given email
|
|
113
|
-
if (res.statusCode == HttpStatus.BadRequest && res.data.errors[0].code == 399) {
|
|
114
|
-
throw new Error(AuthenticationErrors.InvalidEmail);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Getting the flow token
|
|
118
|
-
this.flowToken = res.data['flow_token'];
|
|
119
|
-
|
|
120
|
-
// Checking the next available subtasks
|
|
121
|
-
/**
|
|
122
|
-
* This subtask has two possible outcomes.
|
|
123
|
-
* 1. The server asks for a username next.
|
|
124
|
-
* 2. The server directly asks for password, skipping username check.
|
|
125
|
-
*
|
|
126
|
-
* So, checking which is the subtask required by server, and executing that particular subtask.
|
|
127
|
-
*/
|
|
128
|
-
for (let task of res.data.subtasks) {
|
|
129
|
-
// If next subtask is to enter username
|
|
130
|
-
if (task['subtask_id'] == 'LoginEnterAlternateIdentifierSubtask') {
|
|
131
|
-
// Executing next subtask
|
|
132
|
-
await this.enterAlternateUserIdentifier();
|
|
133
|
-
|
|
134
|
-
break;
|
|
135
|
-
}
|
|
136
|
-
// If next subtask is to enter password
|
|
137
|
-
else if (task['subtask_id'] == 'LoginEnterPassword') {
|
|
138
|
-
// Executing next subtask
|
|
139
|
-
await this.enterPassword();
|
|
140
|
-
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Step 4: Takes the username for login
|
|
148
|
-
* @internal
|
|
149
|
-
*
|
|
150
|
-
* @throws {@link AuthenticationErrors.InvalidUsername}, if wrong username entered.
|
|
151
|
-
*/
|
|
152
|
-
private async enterAlternateUserIdentifier(): Promise<void> {
|
|
153
|
-
// Executing the subtask
|
|
154
|
-
const res: CurlyResult = await curly.post(LoginFlows.EnterAlternateUserIdentifier.url, {
|
|
155
|
-
httpHeader: loginHeader(await this.getGuestCredentials(), this.cookies.join(';').toString()),
|
|
156
|
-
sslVerifyPeer: false,
|
|
157
|
-
postFields: JSON.stringify(LoginFlows.EnterAlternateUserIdentifier.body(this.flowToken, this.userName))
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
// If invalid username for the given account
|
|
161
|
-
if (res.statusCode == HttpStatus.BadRequest && res.data.errors[0].code == 399) {
|
|
162
|
-
throw new Error(AuthenticationErrors.InvalidUsername);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Getting the flow token
|
|
166
|
-
this.flowToken = res.data['flow_token'];
|
|
167
|
-
|
|
168
|
-
// Executing next subtask
|
|
169
|
-
await this.enterPassword();
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Step 5: Takes the password for login
|
|
174
|
-
* @internal
|
|
175
|
-
*
|
|
176
|
-
* @throws {@link AuthenticationErrors.InvalidPassword}, incorrect password entered.
|
|
177
|
-
*/
|
|
178
|
-
private async enterPassword(): Promise<void> {
|
|
179
|
-
// Executing the subtask
|
|
180
|
-
const res: CurlyResult = await curly.post(LoginFlows.EnterPassword.url, {
|
|
181
|
-
httpHeader: loginHeader(await this.getGuestCredentials(), this.cookies.join(';').toString()),
|
|
182
|
-
sslVerifyPeer: false,
|
|
183
|
-
postFields: JSON.stringify(LoginFlows.EnterPassword.body(this.flowToken, this.password))
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
// If invalid password for the given account
|
|
187
|
-
if (res.statusCode == HttpStatus.BadRequest && res.data.errors[0].code == 399) {
|
|
188
|
-
throw new Error(AuthenticationErrors.InvalidPassword);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Getting the flow token
|
|
192
|
-
this.flowToken = res.data['flow_token'];
|
|
193
|
-
|
|
194
|
-
// Executing next subtask
|
|
195
|
-
await this.accountDuplicationCheck();
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Step 6: Gets the actual cookies
|
|
200
|
-
* @internal
|
|
201
|
-
*/
|
|
202
|
-
private async accountDuplicationCheck(): Promise<void> {
|
|
203
|
-
// Executing the subtask
|
|
204
|
-
const res: CurlyResult = await curly.post(LoginFlows.AccountDuplicationCheck.url, {
|
|
205
|
-
httpHeader: loginHeader(await this.getGuestCredentials(), this.cookies.join(';').toString()),
|
|
206
|
-
sslVerifyPeer: false,
|
|
207
|
-
postFields: JSON.stringify(LoginFlows.AccountDuplicationCheck.body(this.flowToken))
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
// Getting the cookies from the set-cookie header of the reponse.
|
|
211
|
-
this.cookies = new CookieJar().setCookies(res.headers[0]['Set-Cookie'] as string[]);
|
|
212
|
-
|
|
213
|
-
// Getting the flow token
|
|
214
|
-
this.flowToken = res.data['flow_token'];
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Parse the authentication cookies recieved from Twitter into known format.
|
|
219
|
-
*
|
|
220
|
-
* @internal
|
|
221
|
-
*
|
|
222
|
-
* @param cookies The raw cookies received from Twitter.
|
|
223
|
-
*
|
|
224
|
-
* @returns The parsed cookies of type {@link AuthCookie}
|
|
225
|
-
*/
|
|
226
|
-
private parseCookies(cookies: Cookie[]): IAuthCookie {
|
|
227
|
-
/** The tempoorary parsed cookies. */
|
|
228
|
-
let tempCookies: any = {};
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Parsing the cookies into a standard JSON format.
|
|
232
|
-
* The format is 'cookie_name': 'cookie_value'.
|
|
233
|
-
* All other cookie parameters like expiry, etc are dropped.
|
|
234
|
-
*/
|
|
235
|
-
cookies.forEach(cookie => {
|
|
236
|
-
tempCookies[cookie.name] = cookie.value;
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
return {
|
|
240
|
-
kdt: tempCookies['kdt'],
|
|
241
|
-
twid: tempCookies['twid'],
|
|
242
|
-
ct0: tempCookies['ct0'],
|
|
243
|
-
auth_token: tempCookies['auth_token']
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Login to Twitter using the given credentials and get back the cookies.
|
|
249
|
-
*
|
|
250
|
-
* @public
|
|
251
|
-
*
|
|
252
|
-
* @param email The email of the account to be logged into.
|
|
253
|
-
* @param userName The username associated with the given account.
|
|
254
|
-
* @param password The password to the account.
|
|
255
|
-
*
|
|
256
|
-
* @returns The cookies for authenticating with the given account.
|
|
257
|
-
*/
|
|
258
|
-
public async login(email: string, userName: string, password: string): Promise<IAuthCookie> {
|
|
259
|
-
/** The parsed cookies that will be returned. */
|
|
260
|
-
let parsedCookies: IAuthCookie;
|
|
261
|
-
|
|
262
|
-
// Setting user credentials
|
|
263
|
-
this.email = email;
|
|
264
|
-
this.userName = userName;
|
|
265
|
-
this.password = password;
|
|
266
|
-
|
|
267
|
-
// Initiating login
|
|
268
|
-
/**
|
|
269
|
-
* This works by sending a chain of request that are required for login to twitter.
|
|
270
|
-
* Each method in the chain returns a flow token that must be provied as payload in the next method in the chain.
|
|
271
|
-
* Each such method is called a subtask.
|
|
272
|
-
* Each subtask sets the {@link flowToken} property of the class which is used in the payload of the next subtask.
|
|
273
|
-
* The final subtask returns the headers which actually contains the cookie in the 'set-cookie' field.
|
|
274
|
-
*/
|
|
275
|
-
await this.initiateLogin();
|
|
276
|
-
|
|
277
|
-
// Parsing the cookies
|
|
278
|
-
parsedCookies = this.parseCookies(this.cookies);
|
|
279
|
-
|
|
280
|
-
// Returning the final parsed cookies
|
|
281
|
-
return parsedCookies;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
// PACKAGES
|
|
2
|
-
import {
|
|
3
|
-
Url,
|
|
4
|
-
EResourceType,
|
|
5
|
-
ITweetSearchResponse,
|
|
6
|
-
ITweetDetailsResponse,
|
|
7
|
-
ITweetFavoritersResponse,
|
|
8
|
-
ITweetRetweetersResponse,
|
|
9
|
-
ITweet as IRawTweet,
|
|
10
|
-
IUser as IRawUser,
|
|
11
|
-
TweetFilter
|
|
12
|
-
} from 'rettiwt-core';
|
|
13
|
-
|
|
14
|
-
// SERVICES
|
|
15
|
-
import { FetcherService } from "../util/FetcherService";
|
|
16
|
-
import { AuthService } from "../auth/AuthService";
|
|
17
|
-
|
|
18
|
-
// MODELS
|
|
19
|
-
import { Tweet } from "../../models/data/Tweet";
|
|
20
|
-
import { User } from "../../models/data/User";
|
|
21
|
-
import { TweetListArgs } from "../../models/args/TweetListArgs";
|
|
22
|
-
import { CursoredData } from '../../models/data/CursoredData';
|
|
23
|
-
|
|
24
|
-
// ENUMS
|
|
25
|
-
import { AuthenticationErrors } from '../../enums/Errors';
|
|
26
|
-
|
|
27
|
-
// EXTRACTORS
|
|
28
|
-
import * as TweetExtractors from "../helper/extractors/Tweets";
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Handles fetching of data related to tweets.
|
|
32
|
-
* @public
|
|
33
|
-
*/
|
|
34
|
-
export class TweetService extends FetcherService {
|
|
35
|
-
/**
|
|
36
|
-
* @param auth The AuthService instance to use for authentication.
|
|
37
|
-
*/
|
|
38
|
-
constructor(auth: AuthService) {
|
|
39
|
-
super(auth);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* @param filter The filter be used for searching the tweets.
|
|
44
|
-
* @param count The number of tweets to fetch, must be >= 10 (when no cursor is provided) and <= 20
|
|
45
|
-
* @param cursor The cursor to the next batch of tweets. If blank, first batch is fetched.
|
|
46
|
-
*
|
|
47
|
-
* @returns The list of tweets that match the given filter.
|
|
48
|
-
*
|
|
49
|
-
* @throws {@link Errors.AuthenticationErrors.NotAuthenticated} error, if no cookies have been provided.
|
|
50
|
-
* @throws {@link Errors.ValidationErrors.InvalidCount} error, if an invalid count has been provided.
|
|
51
|
-
*/
|
|
52
|
-
async getTweets(query: TweetFilter, count?: number, cursor?: string): Promise<CursoredData<Tweet>> {
|
|
53
|
-
// If user is not authenticated, abort
|
|
54
|
-
if (!this.isAuthenticated) {
|
|
55
|
-
throw new Error(AuthenticationErrors.NotAuthenticated);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Objectifying parameters
|
|
59
|
-
let args: TweetListArgs = new TweetListArgs(count, cursor);
|
|
60
|
-
|
|
61
|
-
// Preparing the URL
|
|
62
|
-
const url: string = new Url(EResourceType.TWEET_SEARCH, { filter: query, count: args.count, cursor: args.cursor }).toString();
|
|
63
|
-
|
|
64
|
-
// Getting the raw data
|
|
65
|
-
let res = await this.request<ITweetSearchResponse>(url).then(res => res.data);
|
|
66
|
-
|
|
67
|
-
// Extracting data
|
|
68
|
-
let data = TweetExtractors.extractTweets(res);
|
|
69
|
-
|
|
70
|
-
// Caching data
|
|
71
|
-
this.cacheData(data);
|
|
72
|
-
|
|
73
|
-
// Parsing data
|
|
74
|
-
let tweets = data.required.map((item: IRawTweet) => new Tweet(item));
|
|
75
|
-
|
|
76
|
-
// Sorting the tweets by date, from recent to oldest
|
|
77
|
-
tweets.sort((a, b) => new Date(b.createdAt).valueOf() - new Date(a.createdAt).valueOf());
|
|
78
|
-
|
|
79
|
-
return new CursoredData<Tweet>(tweets, data.cursor);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* @param id The id of the target tweet.
|
|
84
|
-
*
|
|
85
|
-
* @returns The details of a single tweet with the given tweet id.
|
|
86
|
-
*
|
|
87
|
-
* @throws {@link Errors.AuthenticationErrors.NotAuthenticated} error, if no cookies have been provided.
|
|
88
|
-
* @throws {@link Errors.DataErrors.TweetNotFound} error, if no tweet with the given id was found.
|
|
89
|
-
*/
|
|
90
|
-
async getTweetDetails(id: string): Promise<Tweet> {
|
|
91
|
-
// If user is not authenticated, abort
|
|
92
|
-
if (!this.isAuthenticated) {
|
|
93
|
-
throw new Error(AuthenticationErrors.NotAuthenticated);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Getting data from cache
|
|
97
|
-
let cachedData = await this.readData(id);
|
|
98
|
-
|
|
99
|
-
// If data exists in cache
|
|
100
|
-
if (cachedData) {
|
|
101
|
-
return cachedData;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Preparing the URL
|
|
105
|
-
const url: string = new Url(EResourceType.TWEET_DETAILS, { id: id }).toString();
|
|
106
|
-
|
|
107
|
-
// Fetching the raw data
|
|
108
|
-
let res = await this.request<ITweetDetailsResponse>(url).then(res => res.data);
|
|
109
|
-
|
|
110
|
-
// Extracting data
|
|
111
|
-
let data = TweetExtractors.extractTweet(res, id);
|
|
112
|
-
|
|
113
|
-
// Caching data
|
|
114
|
-
this.cacheData(data);
|
|
115
|
-
|
|
116
|
-
// Parsing data
|
|
117
|
-
let tweet = new Tweet(data.required[0]);
|
|
118
|
-
|
|
119
|
-
return tweet;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* @param tweetId The rest id of the target tweet.
|
|
124
|
-
* @param count The batch size of the list, must be >= 10 (when no cursor is provided) and <= 20.
|
|
125
|
-
* @param cursor The cursor to the next batch of users. If blank, first batch is fetched.
|
|
126
|
-
*
|
|
127
|
-
* @returns The list of users who liked the given tweet.
|
|
128
|
-
*
|
|
129
|
-
* @throws {@link Errors.AuthenticationErrors.NotAuthenticated} error, if no cookies have been provided.
|
|
130
|
-
* @throws {@link Errors.ValidationErrors.InvalidCount} error, if invalid count is provided.
|
|
131
|
-
* @throws {@link Errors.DataErrors.TweetNotFound} error, if no tweet with the given id was found.
|
|
132
|
-
*/
|
|
133
|
-
async getTweetLikers(tweetId: string, count?: number, cursor?: string): Promise<CursoredData<User>> {
|
|
134
|
-
// If user is not authenticated, abort
|
|
135
|
-
if (!this.isAuthenticated) {
|
|
136
|
-
throw new Error(AuthenticationErrors.NotAuthenticated);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Objectifying parameters
|
|
140
|
-
let args: TweetListArgs = new TweetListArgs(count, cursor);
|
|
141
|
-
|
|
142
|
-
// Preparing the URL
|
|
143
|
-
const url: string = new Url(EResourceType.TWEET_FAVORITERS, { id: tweetId, count: args.count, cursor: args.cursor }).toString();
|
|
144
|
-
|
|
145
|
-
// Fetching the raw data
|
|
146
|
-
let res = await this.request<ITweetFavoritersResponse>(url).then(res => res.data);
|
|
147
|
-
|
|
148
|
-
// Extracting data
|
|
149
|
-
let data = TweetExtractors.extractTweetLikers(res);
|
|
150
|
-
|
|
151
|
-
// Caching data
|
|
152
|
-
this.cacheData(data);
|
|
153
|
-
|
|
154
|
-
// Parsing data
|
|
155
|
-
let users = data.required.map((item: IRawUser) => new User(item));
|
|
156
|
-
|
|
157
|
-
return new CursoredData<User>(users, data.cursor);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* @param tweetId The rest id of the target tweet.
|
|
162
|
-
* @param count The batch size of the list, must be >= 10 (when no cursor is provided) and <= 100.
|
|
163
|
-
* @param cursor The cursor to the next batch of users. If blank, first batch is fetched.
|
|
164
|
-
*
|
|
165
|
-
* @returns The list of users who retweeted the given tweet.
|
|
166
|
-
*
|
|
167
|
-
* @throws {@link Errors.AuthenticationErrors.NotAuthenticated} error, if no cookies have been provided.
|
|
168
|
-
* @throws {@link Errors.ValidationErrors.InvalidCount} error, if invalid count is provided.
|
|
169
|
-
* @throws {@link Errors.DataErrors.TweetNotFound} error, if no tweet with the given id was found.
|
|
170
|
-
*/
|
|
171
|
-
async getTweetRetweeters(tweetId: string, count?: number, cursor?: string): Promise<CursoredData<User>> {
|
|
172
|
-
// If user is not authenticated, abort
|
|
173
|
-
if (!this.isAuthenticated) {
|
|
174
|
-
throw new Error(AuthenticationErrors.NotAuthenticated);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Objectifying parameters
|
|
178
|
-
let args: TweetListArgs = new TweetListArgs(count, cursor);
|
|
179
|
-
|
|
180
|
-
// Preparing the URL
|
|
181
|
-
const url: string = new Url(EResourceType.TWEET_RETWEETERS, { id: tweetId, count: args.count, cursor: args.cursor }).toString();
|
|
182
|
-
|
|
183
|
-
// Fetching the raw data
|
|
184
|
-
let res = await this.request<ITweetRetweetersResponse>(url).then(res => res.data);
|
|
185
|
-
|
|
186
|
-
// Extracting data
|
|
187
|
-
let data = TweetExtractors.extractTweetRetweeters(res);
|
|
188
|
-
|
|
189
|
-
// Caching data
|
|
190
|
-
this.cacheData(data);
|
|
191
|
-
|
|
192
|
-
// Parsing data
|
|
193
|
-
let users = data.required.map((item: IRawUser) => new User(item));
|
|
194
|
-
|
|
195
|
-
return new CursoredData<User>(users, data.cursor);
|
|
196
|
-
}
|
|
197
|
-
}
|