rettiwt-api 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/README.md +2 -2
  2. package/dist/{queries → graphql/queries}/RootQuery.d.ts +0 -0
  3. package/dist/{queries → graphql/queries}/RootQuery.js +15 -3
  4. package/dist/graphql/queries/RootQuery.js.map +1 -0
  5. package/dist/graphql/resolvers/AccountResolver.d.ts +12 -0
  6. package/dist/graphql/resolvers/AccountResolver.js +84 -0
  7. package/dist/graphql/resolvers/AccountResolver.js.map +1 -0
  8. package/dist/{resolvers → graphql/resolvers}/ResolverBase.d.ts +1 -1
  9. package/dist/{resolvers → graphql/resolvers}/ResolverBase.js +0 -0
  10. package/dist/graphql/resolvers/ResolverBase.js.map +1 -0
  11. package/dist/{resolvers → graphql/resolvers}/TweetResolver.d.ts +10 -9
  12. package/dist/{resolvers → graphql/resolvers}/TweetResolver.js +51 -35
  13. package/dist/graphql/resolvers/TweetResolver.js.map +1 -0
  14. package/dist/{resolvers → graphql/resolvers}/UserResolver.d.ts +5 -4
  15. package/dist/{resolvers → graphql/resolvers}/UserResolver.js +51 -35
  16. package/dist/graphql/resolvers/UserResolver.js.map +1 -0
  17. package/dist/{models/graphql → graphql/types}/Global.d.ts +0 -0
  18. package/dist/{models/graphql → graphql/types}/Global.js +0 -0
  19. package/dist/graphql/types/Global.js.map +1 -0
  20. package/dist/graphql/types/TweetTypes.d.ts +4 -0
  21. package/dist/{models/graphql → graphql/types}/TweetTypes.js +5 -7
  22. package/dist/graphql/types/TweetTypes.js.map +1 -0
  23. package/dist/graphql/types/UserTypes.d.ts +3 -0
  24. package/dist/{models/graphql → graphql/types}/UserTypes.js +9 -11
  25. package/dist/graphql/types/UserTypes.js.map +1 -0
  26. package/dist/index.d.ts +4 -2
  27. package/dist/index.js +5 -3
  28. package/dist/index.js.map +1 -1
  29. package/dist/server.js +6 -4
  30. package/dist/server.js.map +1 -1
  31. package/dist/services/AuthService.js +2 -2
  32. package/dist/services/AuthService.js.map +1 -1
  33. package/dist/services/CacheService.d.ts +3 -3
  34. package/dist/services/CacheService.js +22 -75
  35. package/dist/services/CacheService.js.map +1 -1
  36. package/dist/services/FetcherService.d.ts +14 -4
  37. package/dist/services/FetcherService.js +58 -52
  38. package/dist/services/FetcherService.js.map +1 -1
  39. package/dist/services/accounts/AccountService.d.ts +42 -0
  40. package/dist/services/accounts/AccountService.js +291 -0
  41. package/dist/services/accounts/AccountService.js.map +1 -0
  42. package/dist/services/accounts/LoginFlows.d.ts +77 -0
  43. package/dist/services/accounts/LoginFlows.js +92 -0
  44. package/dist/services/accounts/LoginFlows.js.map +1 -0
  45. package/dist/services/data/TweetService.d.ts +6 -6
  46. package/dist/services/data/TweetService.js +44 -27
  47. package/dist/services/data/TweetService.js.map +1 -1
  48. package/dist/services/data/UserAccountService.d.ts +3 -3
  49. package/dist/services/data/UserAccountService.js +22 -8
  50. package/dist/services/data/UserAccountService.js.map +1 -1
  51. package/dist/services/data/UserService.d.ts +42 -0
  52. package/dist/services/data/UserService.js +255 -0
  53. package/dist/services/data/UserService.js.map +1 -0
  54. package/dist/services/helper/Extractors.js +1 -1
  55. package/dist/services/helper/Extractors.js.map +1 -1
  56. package/dist/services/helper/Headers.d.ts +11 -1
  57. package/dist/services/helper/Headers.js +28 -2
  58. package/dist/services/helper/Headers.js.map +1 -1
  59. package/dist/services/helper/Parser.d.ts +1 -1
  60. package/dist/services/helper/Parser.js +4 -3
  61. package/dist/services/helper/Parser.js.map +1 -1
  62. package/dist/services/helper/Urls.d.ts +2 -2
  63. package/dist/services/helper/Urls.js +19 -3
  64. package/dist/services/helper/Urls.js.map +1 -1
  65. package/dist/services/helper/deserializers/Tweets.d.ts +12 -0
  66. package/dist/services/helper/deserializers/Tweets.js +92 -0
  67. package/dist/services/helper/deserializers/Tweets.js.map +1 -0
  68. package/dist/services/helper/deserializers/User.d.ts +0 -0
  69. package/dist/services/helper/deserializers/User.js +2 -0
  70. package/dist/services/helper/deserializers/User.js.map +1 -0
  71. package/dist/services/helper/deserializers/Users.d.ts +7 -0
  72. package/dist/services/helper/deserializers/Users.js +27 -0
  73. package/dist/services/helper/deserializers/Users.js.map +1 -0
  74. package/dist/services/helper/extractors/TweetExtractors.d.ts +0 -0
  75. package/dist/services/helper/extractors/TweetExtractors.js +2 -0
  76. package/dist/services/helper/extractors/TweetExtractors.js.map +1 -0
  77. package/dist/services/helper/extractors/Tweets.d.ts +32 -0
  78. package/dist/services/helper/extractors/Tweets.js +264 -0
  79. package/dist/services/helper/extractors/Tweets.js.map +1 -0
  80. package/dist/services/helper/extractors/UserExtractors.d.ts +45 -0
  81. package/dist/services/helper/extractors/UserExtractors.js +176 -0
  82. package/dist/services/helper/extractors/UserExtractors.js.map +1 -0
  83. package/dist/services/helper/extractors/Users.d.ts +20 -0
  84. package/dist/services/helper/extractors/Users.js +151 -0
  85. package/dist/services/helper/extractors/Users.js.map +1 -0
  86. package/dist/services/helper/urls/Authentication.d.ts +4 -0
  87. package/dist/services/helper/urls/Authentication.js +11 -0
  88. package/dist/services/helper/urls/Authentication.js.map +1 -0
  89. package/dist/services/helper/urls/Tweets.d.ts +32 -0
  90. package/dist/services/helper/urls/Tweets.js +51 -0
  91. package/dist/services/helper/urls/Tweets.js.map +1 -0
  92. package/dist/services/helper/urls/Urls.d.ts +4 -0
  93. package/dist/services/helper/urls/Urls.js +11 -0
  94. package/dist/services/helper/urls/Urls.js.map +1 -0
  95. package/dist/services/helper/urls/Users.d.ts +31 -0
  96. package/dist/services/helper/urls/Users.js +66 -0
  97. package/dist/services/helper/urls/Users.js.map +1 -0
  98. package/dist/types/{graphql/Errors.d.ts → Errors.d.ts} +0 -0
  99. package/dist/types/{graphql/Errors.js → Errors.js} +0 -0
  100. package/dist/types/Errors.js.map +1 -0
  101. package/dist/types/HTTP.d.ts +0 -7
  102. package/dist/types/HTTP.js +1 -10
  103. package/dist/types/HTTP.js.map +1 -1
  104. package/dist/types/Resolvers.d.ts +9 -0
  105. package/dist/types/Resolvers.js +3 -0
  106. package/dist/types/Resolvers.js.map +1 -0
  107. package/dist/types/Service.d.ts +2 -0
  108. package/dist/types/Service.js.map +1 -1
  109. package/dist/types/Tweet.d.ts +1 -0
  110. package/dist/types/Tweet.js.map +1 -1
  111. package/dist/types/User.d.ts +19 -0
  112. package/dist/types/User.js +4 -0
  113. package/dist/types/User.js.map +1 -0
  114. package/dist/types/data/Errors.d.ts +26 -0
  115. package/dist/types/data/Errors.js +36 -0
  116. package/dist/types/data/Errors.js.map +1 -0
  117. package/dist/types/data/Service.d.ts +29 -0
  118. package/dist/types/data/Service.js +19 -0
  119. package/dist/types/data/Service.js.map +1 -0
  120. package/dist/types/data/Tweet.d.ts +41 -0
  121. package/dist/types/data/Tweet.js +5 -0
  122. package/dist/types/data/Tweet.js.map +1 -0
  123. package/dist/types/data/User.d.ts +19 -0
  124. package/dist/types/data/User.js +4 -0
  125. package/dist/types/data/User.js.map +1 -0
  126. package/dist/types/raw/http/Error.d.ts +34 -0
  127. package/dist/types/raw/{user/Users.js → http/Error.js} +1 -1
  128. package/dist/types/raw/http/Error.js.map +1 -0
  129. package/dist/types/raw/http/Response.d.ts +34 -0
  130. package/dist/types/raw/http/Response.js +3 -0
  131. package/dist/types/raw/http/Response.js.map +1 -0
  132. package/package.json +4 -2
  133. package/src/{queries → graphql/queries}/RootQuery.ts +16 -4
  134. package/src/graphql/resolvers/AccountResolver.ts +22 -0
  135. package/src/{resolvers → graphql/resolvers}/ResolverBase.ts +1 -1
  136. package/src/{resolvers → graphql/resolvers}/TweetResolver.ts +43 -30
  137. package/src/{resolvers → graphql/resolvers}/UserResolver.ts +41 -27
  138. package/src/{models/graphql → graphql/types}/Global.ts +0 -0
  139. package/src/{models/graphql → graphql/types}/TweetTypes.ts +9 -11
  140. package/src/{models/graphql → graphql/types}/UserTypes.ts +13 -15
  141. package/src/index.ts +5 -3
  142. package/src/server.ts +6 -4
  143. package/src/services/AuthService.ts +1 -1
  144. package/src/services/CacheService.ts +6 -8
  145. package/src/services/FetcherService.ts +37 -22
  146. package/src/services/accounts/AccountService.ts +156 -0
  147. package/src/services/accounts/LoginFlows.ts +90 -0
  148. package/src/services/data/TweetService.ts +53 -37
  149. package/src/services/data/UserService.ts +187 -0
  150. package/src/services/helper/Headers.ts +27 -1
  151. package/src/services/helper/Parser.ts +6 -4
  152. package/src/services/helper/{Deserializers.ts → deserializers/Tweets.ts} +3 -28
  153. package/src/services/helper/deserializers/Users.ts +26 -0
  154. package/src/services/helper/extractors/Tweets.ts +252 -0
  155. package/src/services/helper/extractors/Users.ts +137 -0
  156. package/src/services/helper/urls/Authentication.ts +6 -0
  157. package/src/services/helper/urls/Tweets.ts +46 -0
  158. package/src/services/helper/urls/Users.ts +62 -0
  159. package/src/types/HTTP.ts +0 -8
  160. package/src/types/Resolvers.ts +9 -0
  161. package/src/types/data/Errors.ts +28 -0
  162. package/src/types/{Service.ts → data/Service.ts} +6 -5
  163. package/src/types/{Tweet.ts → data/Tweet.ts} +1 -0
  164. package/src/types/{UserAccount.ts → data/User.ts} +0 -0
  165. package/tsconfig.json +2 -2
  166. package/dist/models/graphql/Global.js.map +0 -1
  167. package/dist/models/graphql/TweetTypes.d.ts +0 -6
  168. package/dist/models/graphql/TweetTypes.js.map +0 -1
  169. package/dist/models/graphql/UserTypes.d.ts +0 -3
  170. package/dist/models/graphql/UserTypes.js.map +0 -1
  171. package/dist/queries/RootQuery.js.map +0 -1
  172. package/dist/resolvers/ResolverBase.js.map +0 -1
  173. package/dist/resolvers/TweetResolver.js.map +0 -1
  174. package/dist/resolvers/UserResolver.js.map +0 -1
  175. package/dist/test/Test.js +0 -2
  176. package/dist/test/Test.js.map +0 -1
  177. package/dist/types/graphql/Errors.js.map +0 -1
  178. package/dist/types/raw/user/Users.d.ts +0 -120
  179. package/dist/types/raw/user/Users.js.map +0 -1
  180. package/src/services/data/UserAccountService.ts +0 -176
  181. package/src/services/helper/Extractors.ts +0 -455
  182. package/src/services/helper/Urls.ts +0 -109
  183. package/src/types/graphql/Errors.ts +0 -16
  184. package/src/types/raw/user/Tweets.ts +0 -2847
@@ -12,7 +12,17 @@ import { Result as RawTweet } from '../types/raw/tweet/Tweet';
12
12
 
13
13
  // HELPERS
14
14
  import * as Headers from './helper/Headers'
15
- import * as Deserializers from './helper/Deserializers';
15
+ import * as UserDeserializers from './helper/deserializers/Users';
16
+ import * as TweetDeserializers from './helper/deserializers/Tweets';
17
+ import { CurlyOptions } from 'node-libcurl/dist/curly';
18
+
19
+ /**
20
+ * @summary Stores all the different type of http requests
21
+ */
22
+ export enum HttpMethods {
23
+ POST = "POST",
24
+ GET = "GET"
25
+ };
16
26
 
17
27
  /**
18
28
  * @service The base serivice from which all other data services derive their behaviour
@@ -20,11 +30,13 @@ import * as Deserializers from './helper/Deserializers';
20
30
  export class FetcherService {
21
31
  // MEMBER DATA
22
32
  private auth: AuthService; // To store the auth service instance to use for authentication
33
+ private cache: CacheService; // To stoer the cache service instance to use for caching data
23
34
  protected isAuthenticated: boolean; // To store whether user is authenticated or not
24
35
 
25
36
  // MEMBER METHODS
26
37
  constructor(auth: AuthService) {
27
38
  this.auth = auth;
39
+ this.cache = CacheService.getInstance();
28
40
  this.isAuthenticated = this.auth.isAuthenticated;
29
41
  }
30
42
 
@@ -43,44 +55,47 @@ export class FetcherService {
43
55
  /**
44
56
  * @returns The absolute raw json data from give url
45
57
  * @param url The url to fetch data from
46
- * @param authenticated Whether to authenticate requests or not
58
+ * @param authenticate Whether to authenticate requests or not
59
+ * @param method The HTTP method to use
60
+ * @param data The data to be sent along with the request (works with only POST method)
47
61
  */
48
- protected async request<DataType>(url: string, authenticated: boolean = true): Promise<CurlyResult<DataType>> {
49
- // Fetching the data
50
- let res = await curly.get(url, {
51
- httpHeader: authenticated ? Headers.authorizedHeader(await this.auth.getAuthCredentials()) : Headers.guestHeader(await this.auth.getGuestCredentials()),
52
- sslVerifyPeer: false
53
- }).then(res => this.handleHTTPError(res));
62
+ protected async request<DataType>(url: string, authenticate: boolean = true, method: HttpMethods = HttpMethods.GET, data?: any): Promise<CurlyResult<DataType>> {
63
+ // Creating the configuration for the http request
64
+ let config: CurlyOptions = {
65
+ httpHeader: authenticate ? Headers.authorizedHeader(await this.auth.getAuthCredentials()) : Headers.guestHeader(await this.auth.getGuestCredentials()),
66
+ sslVerifyPeer: false,
67
+ };
54
68
 
55
- return res;
69
+ // If post request is to be made
70
+ if (method == HttpMethods.POST) {
71
+ return await curly.post(url, { ...config, postFields: JSON.stringify(data) }).then(res => this.handleHTTPError(res));
72
+ }
73
+ // If get request is to be made
74
+ else {
75
+ return await curly.get(url, config).then(res => this.handleHTTPError(res));
76
+ }
56
77
  }
57
78
 
58
79
  /**
59
80
  * @summary Caches the extracted data
60
81
  * @param data The extracted data to be cached
61
82
  */
62
- protected async cacheData(data: any): Promise<void> {
63
- // Creating an instance of cache
64
- let cache = await CacheService.getInstance();
65
-
83
+ protected cacheData(data: any): void {
66
84
  // Parsing the extracted data
67
- let users = data.users.map((user: RawUser) => Deserializers.toUser(user));
68
- let tweets = data.tweets.map((tweet: RawTweet) => Deserializers.toTweet(tweet));
85
+ let users = data.users.map((user: RawUser) => UserDeserializers.toUser(user));
86
+ let tweets = data.tweets.map((tweet: RawTweet) => TweetDeserializers.toTweet(tweet));
69
87
 
70
88
  // Caching the data
71
- cache.write(users);
72
- cache.write(tweets);
89
+ this.cache.write(users);
90
+ this.cache.write(tweets);
73
91
  }
74
92
 
75
93
  /**
76
94
  * @returns The data with the given id (if it exists in cache)
77
95
  * @param id The id of the data to be read from cache
78
96
  */
79
- protected async readData(id: string): Promise<any> {
80
- // Creating an instance of cache
81
- let cache = await CacheService.getInstance();
82
-
97
+ protected readData(id: string): any {
83
98
  // Reading data from cache
84
- return cache.read(id);
99
+ return this.cache.read(id);
85
100
  }
86
101
  }
@@ -0,0 +1,156 @@
1
+ // PACKAGES
2
+ import { curly, CurlyResult } from 'node-libcurl';
3
+
4
+ // SERVICES
5
+ import { AuthService } from '../AuthService';
6
+
7
+ // TYPES
8
+ import { GuestCredentials } from '../../types/Authentication';
9
+
10
+ // HELPERS
11
+ import LoginFlows from './LoginFlows';
12
+ import { loginHeader } from '../helper/Headers';
13
+ import { Cookie, CookieJar } from 'cookiejar';
14
+
15
+ export class AccountService {
16
+ // MEMBER DATA
17
+ private auth: AuthService; // To store the auth service instance to use
18
+ private guestCreds: GuestCredentials; // To store the guest credentials to use
19
+ private cookies: Cookie[]; // To store the cookies received from twitter
20
+ private flowToken: string; // To store the flow token received from current flow
21
+
22
+ // MEMBER METHODS
23
+ constructor() {
24
+ this.auth = new AuthService();
25
+ this.guestCreds = { authToken: '', guestToken: '' };
26
+ this.cookies = [];
27
+ this.flowToken = '';
28
+ }
29
+
30
+ /**
31
+ * @returns The current guest credentials to use. If if does not exists, then a new one is created
32
+ */
33
+ private async getGuestCredentials(): Promise<GuestCredentials> {
34
+ // If a guest credential has not been already set, get a new one
35
+ if (!this.guestCreds.guestToken) {
36
+ this.guestCreds = await this.auth.getGuestCredentials();
37
+ }
38
+
39
+ return this.guestCreds;
40
+ }
41
+
42
+ /**
43
+ * @summary Step 1: Initiates login
44
+ */
45
+ private async initiateLogin(): Promise<void> {
46
+ // Initiating the login process
47
+ const res: CurlyResult = await curly.post(LoginFlows.InitiateLogin.url, {
48
+ httpHeader: loginHeader(await this.getGuestCredentials(), this.cookies.toString()),
49
+ sslVerifyPeer: false,
50
+ postFields: ''
51
+ });
52
+
53
+ // Storing cookies received
54
+ this.cookies = new CookieJar().setCookies(res.headers[0]['Set-Cookie'] as string[]);
55
+
56
+ // Getting the flow token
57
+ this.flowToken = res.data['flow_token'];
58
+ }
59
+
60
+ /**
61
+ * @summary Step 2: Does something
62
+ */
63
+ private async jsInstrumentationSubtask(): Promise<void> {
64
+ // Executing the flow
65
+ const res: CurlyResult = await curly.post(LoginFlows.JsInstrumentationSubtask.url, {
66
+ httpHeader: loginHeader(await this.getGuestCredentials(), this.cookies.join(';').toString()),
67
+ sslVerifyPeer: false,
68
+ postFields: JSON.stringify(LoginFlows.JsInstrumentationSubtask.body(this.flowToken))
69
+ });
70
+
71
+ // Getting the flow token
72
+ this.flowToken = res.data['flow_token'];
73
+ }
74
+
75
+ /**
76
+ * @summary Step 3: Takes the email for login
77
+ */
78
+ private async enterUserIdentifier(email: string): Promise<void> {
79
+ // Executing the flow
80
+ const res: CurlyResult = await curly.post(LoginFlows.EnterUserIdentifier.url, {
81
+ httpHeader: loginHeader(await this.getGuestCredentials(), this.cookies.join(';').toString()),
82
+ sslVerifyPeer: false,
83
+ postFields: JSON.stringify(LoginFlows.EnterUserIdentifier.body(this.flowToken, email))
84
+ });
85
+
86
+ // Getting the flow token
87
+ this.flowToken = res.data['flow_token'];
88
+ }
89
+
90
+ /**
91
+ * @summary Step 4: Takes the username for login
92
+ */
93
+ private async enterAlternateUserIdentifier(userName: string): Promise<void> {
94
+ // Executing the flow
95
+ const res: CurlyResult = await curly.post(LoginFlows.EnterAlternateUserIdentifier.url, {
96
+ httpHeader: loginHeader(await this.getGuestCredentials(), this.cookies.join(';').toString()),
97
+ sslVerifyPeer: false,
98
+ postFields: JSON.stringify(LoginFlows.EnterAlternateUserIdentifier.body(this.flowToken, userName))
99
+ });
100
+
101
+ // Getting the flow token
102
+ this.flowToken = res.data['flow_token'];
103
+ }
104
+
105
+ /**
106
+ * @summary Step 5: Takes the password for login
107
+ */
108
+ private async enterPassword(password: string): Promise<void> {
109
+ // Executing the flow
110
+ const res: CurlyResult = await curly.post(LoginFlows.EnterPassword.url, {
111
+ httpHeader: loginHeader(await this.getGuestCredentials(), this.cookies.join(';').toString()),
112
+ sslVerifyPeer: false,
113
+ postFields: JSON.stringify(LoginFlows.EnterPassword.body(this.flowToken, password))
114
+ });
115
+
116
+ // Getting the flow token
117
+ this.flowToken = res.data['flow_token'];
118
+ }
119
+
120
+ /**
121
+ * @summary Step 6: Gets the actual cookies
122
+ */
123
+ private async accountDuplicationCheck(): Promise<void> {
124
+ // Executing the flow
125
+ const res: CurlyResult = await curly.post(LoginFlows.AccountDuplicationCheck.url, {
126
+ httpHeader: loginHeader(await this.getGuestCredentials(), this.cookies.join(';').toString()),
127
+ sslVerifyPeer: false,
128
+ postFields: JSON.stringify(LoginFlows.AccountDuplicationCheck.body(this.flowToken))
129
+ });
130
+
131
+ // Storing cookies received
132
+ this.cookies = new CookieJar().setCookies(res.headers[0]['Set-Cookie'] as string[]);
133
+
134
+ // Getting the flow token
135
+ this.flowToken = res.data['flow_token'];
136
+ }
137
+
138
+ /**
139
+ * @param email The email of the account to be logged into
140
+ * @param userName The username associated with the given account
141
+ * @param password The password to the account
142
+ * @returns The cookies for authenticating with the given account
143
+ */
144
+ public async login(email: string, userName: string, password: string): Promise<string> {
145
+ // Executing each step of login flow
146
+ await this.initiateLogin();
147
+ await this.jsInstrumentationSubtask();
148
+ await this.enterUserIdentifier(email);
149
+ await this.enterAlternateUserIdentifier(userName);
150
+ await this.enterPassword(password);
151
+ await this.accountDuplicationCheck();
152
+
153
+ // Returning the final cookies
154
+ return this.cookies.join(';');
155
+ }
156
+ }
@@ -0,0 +1,90 @@
1
+ const LoginFlows = {
2
+ "InitiateLogin": {
3
+ url: 'https://api.twitter.com/1.1/onboarding/task.json?flow_name=login'
4
+ },
5
+ "JsInstrumentationSubtask": {
6
+ url: 'https://api.twitter.com/1.1/onboarding/task.json',
7
+ body: (flowToken: string) => ({
8
+ "flow_token": flowToken,
9
+ "subtask_inputs": [
10
+ {
11
+ "subtask_id": "LoginJsInstrumentationSubtask",
12
+ "js_instrumentation": {
13
+ "response": "{\"rf\":{\"a09453c7341fb1cbb7d51561f92d478fa0752bc77e7ca6b5703258680b2c51d7\":-4,\"bd26c6694e256b10766447d992deaf92bb220bc05e3b8205ba5c9a4f83302230\":0,\"abfa440376b8dc33ca518e1e2a998b3ac4200a8122ef09781eea2c1408717111\":-1,\"a4e87b66027f638a4634561275fab00f9f7446b81a180b5f03eda69fa32eb8f4\":-224},\"s\":\"yET9nlXrlGRAylCyyBKEsxOpUweMpjRz5RfKzTzQyVADnKE64gmpyILfKBK0-HIHWY8FbJPHGWr6QrCb5A-Z3q2SLRm4DReprZGXykJ111_ynet8kSjFkRjODKKDN2FzT1V6rx9FILnUuRCaMu9ewfPgPBi4wO1g7EUeEsSSHIiCwNc9URJr4c2xVTA3ibIfTbu8p2WhX7RZAk8LWRPpPPB21st8Z1j0LcLlR0bkZoF6LsN-7w75lGB0s4z1JKqus2MVuRcPMay0wWZbn8Qx9In_-tSTvEBLcxjUpDgwu29G0g0iCWoISFzLY4-LLvV7UBGklkByIcPtwYbDbREqRQAAAYYmXAsG\"}",
14
+ "link": "next_link"
15
+ }
16
+ }
17
+ ]
18
+ })
19
+ },
20
+ "EnterUserIdentifier": {
21
+ url: 'https://api.twitter.com/1.1/onboarding/task.json',
22
+ body: (flowToken: string, email: string) => ({
23
+ "flow_token": flowToken,
24
+ "subtask_inputs": [
25
+ {
26
+ "subtask_id": "LoginEnterUserIdentifierSSO",
27
+ "settings_list": {
28
+ "setting_responses": [
29
+ {
30
+ "key": "user_identifier",
31
+ "response_data": {
32
+ "text_data": {
33
+ "result": email
34
+ }
35
+ }
36
+ }
37
+ ],
38
+ "link": "next_link"
39
+ }
40
+ }
41
+ ]
42
+ })
43
+ },
44
+ "EnterAlternateUserIdentifier": {
45
+ url: 'https://api.twitter.com/1.1/onboarding/task.json',
46
+ body: (flowToken: string, userName: string) => ({
47
+ "flow_token": flowToken,
48
+ "subtask_inputs": [
49
+ {
50
+ "subtask_id": "LoginEnterAlternateIdentifierSubtask",
51
+ "enter_text": {
52
+ "text": userName,
53
+ "link": "next_link"
54
+ }
55
+ }
56
+ ]
57
+ })
58
+ },
59
+ "EnterPassword": {
60
+ url: 'https://api.twitter.com/1.1/onboarding/task.json',
61
+ body: (flowToken: string, password: string) => ({
62
+ "flow_token": flowToken,
63
+ "subtask_inputs": [
64
+ {
65
+ "subtask_id": "LoginEnterPassword",
66
+ "enter_password": {
67
+ "password": password,
68
+ "link": "next_link"
69
+ }
70
+ }
71
+ ]
72
+ })
73
+ },
74
+ "AccountDuplicationCheck": {
75
+ url: 'https://api.twitter.com/1.1/onboarding/task.json',
76
+ body: (flowToken: string) => ({
77
+ "flow_token": flowToken,
78
+ "subtask_inputs": [
79
+ {
80
+ "subtask_id": "AccountDuplicationCheck",
81
+ "check_logged_in_account": {
82
+ "link": "AccountDuplicationCheck_false"
83
+ }
84
+ }
85
+ ]
86
+ })
87
+ }
88
+ }
89
+
90
+ export default LoginFlows;
@@ -3,22 +3,25 @@ import { FetcherService } from "../FetcherService";
3
3
  import { AuthService } from "../AuthService";
4
4
 
5
5
  // TYPES
6
- import { TweetFilter, Tweet } from "../../types/Tweet";
7
- import { User } from "../../types/UserAccount";
8
- import { CursoredData } from '../../types/Service';
9
- import RawTweet from '../../types/raw/tweet/Tweet';
6
+ import { TweetFilter, Tweet } from "../../types/data/Tweet";
7
+ import { User } from "../../types/data/User";
8
+ import { CursoredData } from '../../types/data/Service';
9
+ import RawTweet, { Result as TweetData } from '../../types/raw/tweet/Tweet';
10
+ import { Result as UserData } from "../../types/raw/user/User";
10
11
  import RawTweets from '../../types/raw/tweet/Tweets';
11
12
  import RawLikers from '../../types/raw/tweet/Favouriters';
12
13
  import RawRetweeters from '../../types/raw/tweet/Retweeters';
14
+ import * as Errors from '../../types/data/Errors';
13
15
 
14
16
  // URLS
15
- import * as Urls from '../helper/Urls';
17
+ import * as TweetUrls from '../helper/urls/Tweets';
16
18
 
17
19
  // EXTRACTORS
18
- import * as Extractors from "../helper/Extractors";
20
+ import * as TweetExtractors from "../helper/extractors/Tweets";
19
21
 
20
22
  // DESERIALIZERS
21
- import * as Deserializers from '../helper/Deserializers';
23
+ import * as UserDeserializers from '../helper/deserializers/Users';
24
+ import * as TweetDeserializers from '../helper/deserializers/Tweets';
22
25
 
23
26
  // PARSERS
24
27
  import { toQueryString } from '../helper/Parser';
@@ -35,21 +38,26 @@ export class TweetService extends FetcherService {
35
38
  /**
36
39
  * @returns The list of tweets that match the given filter
37
40
  * @param filter The filter be used for searching the tweets
38
- * @param count The number of tweets to fetch
41
+ * @param count The number of tweets to fetch, must be >= 1 and <= 100
39
42
  * @param cursor The cursor to the next batch of tweets. If blank, first batch is fetched
40
43
  */
41
44
  async getTweets(filter: TweetFilter, count: number, cursor: string): Promise<CursoredData<Tweet>> {
45
+ // If invalid count provided
46
+ if (count < 1 && !cursor) {
47
+ throw new Error(Errors.ValidationErrors.InvalidCount);
48
+ }
49
+
42
50
  // Getting the raw data
43
- let res = await this.request<RawTweets>(Urls.tweetsUrl(toQueryString(filter), count, cursor), false).then(res => res.data);
51
+ let res = await this.request<RawTweets>(TweetUrls.tweetsUrl(toQueryString(filter), count, cursor), false).then(res => res.data);
44
52
 
45
53
  // Extracting data
46
- let data = Extractors.extractTweets(res);
54
+ let data = TweetExtractors.extractTweets(res);
47
55
 
48
56
  // Caching data
49
57
  this.cacheData(data);
50
58
 
51
59
  // Parsing data
52
- let tweets = data.required.map(item => Deserializers.toTweet(item));
60
+ let tweets = data.required.map((item: TweetData) => TweetDeserializers.toTweet(item));
53
61
 
54
62
  return {
55
63
  list: tweets,
@@ -69,47 +77,50 @@ export class TweetService extends FetcherService {
69
77
  if (cachedData) {
70
78
  return cachedData;
71
79
  }
72
- // If data does not exist in cache
73
- else {
74
- // Fetching the raw data
75
- let res = await this.request<RawTweet>(Urls.tweetDetailsUrl(tweetId), false).then(res => res.data);
80
+
81
+ // Fetching the raw data
82
+ let res = await this.request<RawTweet>(TweetUrls.tweetDetailsUrl(tweetId), false).then(res => res.data);
76
83
 
77
- // Extracting data
78
- let data = Extractors.extractTweet(res, tweetId);
84
+ // Extracting data
85
+ let data = TweetExtractors.extractTweet(res, tweetId);
79
86
 
80
- // Caching data
81
- this.cacheData(data);
87
+ // Caching data
88
+ this.cacheData(data);
82
89
 
83
- // Parsing data
84
- let tweet = Deserializers.toTweet(data.required[0]);
90
+ // Parsing data
91
+ let tweet = TweetDeserializers.toTweet(data.required[0]);
85
92
 
86
- return tweet;
87
- }
93
+ return tweet;
88
94
  }
89
95
 
90
96
  /**
91
97
  * @returns The list of users who liked the given tweet
92
98
  * @param tweetId The rest id of the target tweet
93
- * @param count The batch size of the list
99
+ * @param count The batch size of the list, must be >= 10 (when no cursor is provided) and <= 100
94
100
  * @param cursor The cursor to the next batch of users. If blank, first batch is fetched
95
101
  */
96
102
  async getTweetLikers(tweetId: string, count: number, cursor: string): Promise<CursoredData<User>> {
97
103
  // If user is not authenticated, abort
98
104
  if(!this.isAuthenticated) {
99
- return { error: new Error('Cannot fetch tweet likes without authentication!') };
105
+ throw new Error(Errors.AuthenticationErrors.NotAuthenticated);
106
+ }
107
+
108
+ // If invalid count provided
109
+ if (count < 10 && !cursor) {
110
+ throw new Error(Errors.ValidationErrors.InvalidCount);
100
111
  }
101
112
 
102
113
  // Fetching the raw data
103
- let res = await this.request<RawLikers>(Urls.tweetLikesUrl(tweetId, count, cursor)).then(res => res.data);
114
+ let res = await this.request<RawLikers>(TweetUrls.tweetLikesUrl(tweetId, count, cursor)).then(res => res.data);
104
115
 
105
116
  // Extracting data
106
- let data = Extractors.extractTweetLikers(res);
117
+ let data = TweetExtractors.extractTweetLikers(res);
107
118
 
108
119
  // Caching data
109
120
  this.cacheData(data);
110
121
 
111
122
  // Parsing data
112
- let users = data.required.map(item => Deserializers.toUser(item));
123
+ let users = data.required.map((item: UserData) => UserDeserializers.toUser(item));
113
124
 
114
125
  return {
115
126
  list: users,
@@ -120,26 +131,31 @@ export class TweetService extends FetcherService {
120
131
  /**
121
132
  * @returns The list of users who retweeted the given tweet
122
133
  * @param tweetId The rest id of the target tweet
123
- * @param count The batch size of the list
134
+ * @param count The batch size of the list, must be >= 10 (when no cursor is provided) and <= 100
124
135
  * @param cursor The cursor to the next batch of users. If blank, first batch is fetched
125
136
  */
126
137
  async getTweetRetweeters(tweetId: string, count: number, cursor: string): Promise<CursoredData<User>> {
127
138
  // If user is not authenticated, abort
128
139
  if(!this.isAuthenticated) {
129
- return { error: new Error('Cannot fetch tweet retweeters without authentication!') };
140
+ throw new Error(Errors.AuthenticationErrors.NotAuthenticated);
141
+ }
142
+
143
+ // If invalid count provided
144
+ if (count < 10 && !cursor) {
145
+ throw new Error(Errors.ValidationErrors.InvalidCount);
130
146
  }
131
147
 
132
148
  // Fetching the raw data
133
- let res = await this.request<RawRetweeters>(Urls.tweetRetweetUrl(tweetId, count, cursor)).then(res => res.data);
149
+ let res = await this.request<RawRetweeters>(TweetUrls.tweetRetweetUrl(tweetId, count, cursor)).then(res => res.data);
134
150
 
135
151
  // Extracting data
136
- let data = Extractors.extractTweetRetweeters(res);
152
+ let data = TweetExtractors.extractTweetRetweeters(res);
137
153
 
138
154
  // Caching data
139
155
  this.cacheData(data);
140
156
 
141
157
  // Parsing data
142
- let users = data.required.map(item => Deserializers.toUser(item));
158
+ let users = data.required.map((item: UserData) => UserDeserializers.toUser(item));
143
159
 
144
160
  return {
145
161
  list: users,
@@ -155,20 +171,20 @@ export class TweetService extends FetcherService {
155
171
  async getTweetReplies(tweetId: string, cursor: string): Promise<CursoredData<Tweet>> {
156
172
  // If user is not authenticated, abort
157
173
  if(!this.isAuthenticated) {
158
- return { error: new Error('Cannot fetch tweet replies without authentication!') };
174
+ throw new Error(Errors.AuthenticationErrors.NotAuthenticated);
159
175
  }
160
176
 
161
177
  // Fetching the raw data
162
- let res = await this.request<RawTweet>(Urls.tweetRepliesUrl(tweetId, cursor)).then(res => res.data);
178
+ let res = await this.request<RawTweet>(TweetUrls.tweetRepliesUrl(tweetId, cursor)).then(res => res.data);
163
179
 
164
180
  // Extracting data
165
- let data = Extractors.extractTweetReplies(res, tweetId);
181
+ let data = TweetExtractors.extractTweetReplies(res, tweetId);
166
182
 
167
183
  // Caching data
168
184
  this.cacheData(data);
169
185
 
170
186
  // Parsing data
171
- let tweets = data.required.map(item => Deserializers.toTweet(item));
187
+ let tweets = data.required.map((item: TweetData) => TweetDeserializers.toTweet(item));
172
188
 
173
189
  return {
174
190
  list: tweets,