rettiwt-api 1.1.0 → 1.1.2

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 (125) hide show
  1. package/.github/workflows/build-docs.yml +27 -0
  2. package/README.md +3 -1
  3. package/dist/Test.d.ts +0 -0
  4. package/dist/Test.js +2 -0
  5. package/dist/Test.js.map +1 -0
  6. package/dist/index.d.ts +16 -5
  7. package/dist/index.js +22 -8
  8. package/dist/index.js.map +1 -1
  9. package/dist/models/graphql/Global.d.ts +4 -0
  10. package/dist/models/graphql/Global.js +13 -0
  11. package/dist/models/graphql/Global.js.map +1 -0
  12. package/dist/models/graphql/TweetTypes.d.ts +6 -0
  13. package/dist/models/graphql/TweetTypes.js +156 -0
  14. package/dist/models/graphql/TweetTypes.js.map +1 -0
  15. package/dist/models/graphql/UserTypes.d.ts +3 -0
  16. package/dist/models/graphql/UserTypes.js +139 -0
  17. package/dist/models/graphql/UserTypes.js.map +1 -0
  18. package/dist/queries/RootQuery.d.ts +4 -0
  19. package/dist/queries/RootQuery.js +70 -0
  20. package/dist/queries/RootQuery.js.map +1 -0
  21. package/dist/resolvers/AccountResolver.d.ts +12 -0
  22. package/dist/resolvers/AccountResolver.js +84 -0
  23. package/dist/resolvers/AccountResolver.js.map +1 -0
  24. package/dist/resolvers/ResolverBase.d.ts +5 -0
  25. package/dist/resolvers/ResolverBase.js +11 -0
  26. package/dist/resolvers/ResolverBase.js.map +1 -0
  27. package/dist/resolvers/TweetResolver.d.ts +54 -0
  28. package/dist/resolvers/TweetResolver.js +332 -0
  29. package/dist/resolvers/TweetResolver.js.map +1 -0
  30. package/dist/resolvers/UserResolver.d.ts +38 -0
  31. package/dist/resolvers/UserResolver.js +253 -0
  32. package/dist/resolvers/UserResolver.js.map +1 -0
  33. package/dist/services/AuthService.d.ts +6 -2
  34. package/dist/services/AuthService.js +4 -3
  35. package/dist/services/AuthService.js.map +1 -1
  36. package/dist/services/CacheService.d.ts +12 -7
  37. package/dist/services/CacheService.js +12 -7
  38. package/dist/services/CacheService.js.map +1 -1
  39. package/dist/services/FetcherService.d.ts +32 -12
  40. package/dist/services/FetcherService.js +45 -14
  41. package/dist/services/FetcherService.js.map +1 -1
  42. package/dist/services/accounts/AccountService.d.ts +23 -6
  43. package/dist/services/accounts/AccountService.js +48 -9
  44. package/dist/services/accounts/AccountService.js.map +1 -1
  45. package/dist/services/data/TrendService.d.ts +17 -0
  46. package/dist/services/data/TrendService.js +116 -0
  47. package/dist/services/data/TrendService.js.map +1 -0
  48. package/dist/services/data/TweetService.d.ts +22 -15
  49. package/dist/services/data/TweetService.js +22 -15
  50. package/dist/services/data/TweetService.js.map +1 -1
  51. package/dist/services/data/UserAccountService.d.ts +42 -0
  52. package/dist/services/data/UserAccountService.js +239 -0
  53. package/dist/services/data/UserAccountService.js.map +1 -0
  54. package/dist/services/data/UserService.d.ts +21 -15
  55. package/dist/services/data/UserService.js +21 -15
  56. package/dist/services/data/UserService.js.map +1 -1
  57. package/dist/services/helper/Deserializers.d.ts +19 -0
  58. package/dist/services/helper/Deserializers.js +115 -0
  59. package/dist/services/helper/Deserializers.js.map +1 -0
  60. package/dist/services/helper/Extractors.d.ts +104 -0
  61. package/dist/services/helper/Extractors.js +432 -0
  62. package/dist/services/helper/Extractors.js.map +1 -0
  63. package/dist/services/helper/Urls.d.ts +85 -0
  64. package/dist/services/helper/Urls.js +130 -0
  65. package/dist/services/helper/Urls.js.map +1 -0
  66. package/dist/services/helper/extractors/Trends.d.ts +3 -0
  67. package/dist/services/helper/extractors/Trends.js +51 -0
  68. package/dist/services/helper/extractors/Trends.js.map +1 -0
  69. package/dist/services/helper/urls/Trends.d.ts +7 -0
  70. package/dist/services/helper/urls/Trends.js +13 -0
  71. package/dist/services/helper/urls/Trends.js.map +1 -0
  72. package/dist/types/Authentication.d.ts +27 -2
  73. package/dist/types/Authentication.js.map +1 -1
  74. package/dist/types/HTTP.d.ts +3 -1
  75. package/dist/types/HTTP.js +3 -1
  76. package/dist/types/HTTP.js.map +1 -1
  77. package/dist/types/Resolvers.d.ts +6 -1
  78. package/dist/types/Service.d.ts +30 -0
  79. package/dist/types/Service.js +19 -0
  80. package/dist/types/Service.js.map +1 -0
  81. package/dist/types/Trends.d.ts +50 -0
  82. package/dist/types/Trends.js +3 -0
  83. package/dist/types/Trends.js.map +1 -0
  84. package/dist/types/Tweet.d.ts +40 -0
  85. package/dist/types/Tweet.js +5 -0
  86. package/dist/types/Tweet.js.map +1 -0
  87. package/dist/types/UserAccount.d.ts +19 -0
  88. package/dist/types/UserAccount.js +4 -0
  89. package/dist/types/UserAccount.js.map +1 -0
  90. package/dist/types/data/Errors.d.ts +13 -4
  91. package/dist/types/data/Errors.js +12 -3
  92. package/dist/types/data/Errors.js.map +1 -1
  93. package/dist/types/data/Service.d.ts +19 -5
  94. package/dist/types/data/Service.js +6 -3
  95. package/dist/types/data/Service.js.map +1 -1
  96. package/dist/types/data/Tweet.d.ts +60 -3
  97. package/dist/types/data/Tweet.js +0 -1
  98. package/dist/types/data/Tweet.js.map +1 -1
  99. package/dist/types/data/User.d.ts +20 -1
  100. package/dist/types/data/User.js +0 -1
  101. package/dist/types/data/User.js.map +1 -1
  102. package/dist/types/graphql/Errors.d.ts +15 -0
  103. package/dist/types/graphql/Errors.js +23 -0
  104. package/dist/types/graphql/Errors.js.map +1 -0
  105. package/dist/types/raw/general/Trends.d.ts +324 -0
  106. package/dist/types/raw/general/Trends.js +3 -0
  107. package/dist/types/raw/general/Trends.js.map +1 -0
  108. package/dist/types/raw/user/Tweets.d.ts +2428 -0
  109. package/dist/types/raw/user/Tweets.js +3 -0
  110. package/dist/types/raw/user/Tweets.js.map +1 -0
  111. package/package.json +5 -4
  112. package/src/index.ts +19 -6
  113. package/src/services/AuthService.ts +13 -7
  114. package/src/services/CacheService.ts +12 -7
  115. package/src/services/FetcherService.ts +62 -21
  116. package/src/services/accounts/AccountService.ts +61 -12
  117. package/src/services/data/TweetService.ts +25 -18
  118. package/src/services/data/UserService.ts +21 -15
  119. package/src/types/Authentication.ts +27 -2
  120. package/src/types/HTTP.ts +4 -2
  121. package/src/types/Resolvers.ts +14 -6
  122. package/src/types/data/Errors.ts +13 -4
  123. package/src/types/data/Service.ts +28 -11
  124. package/src/types/data/Tweet.ts +109 -31
  125. package/src/types/data/User.ts +47 -17
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ exports.__esModule = true;
3
+ //# sourceMappingURL=Tweets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tweets.js","sourceRoot":"","sources":["../../../../src/types/raw/user/Tweets.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rettiwt-api",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "description": "An API for fetching data from TwitterAPI, without any rate limits!",
@@ -21,9 +21,9 @@
21
21
  "bugs": {
22
22
  "url": "https://github.com/Rishikant181/Rettiwt-API/issues"
23
23
  },
24
- "homepage": "https://github.com/Rishikant181/Rettiwt-API#readme",
24
+ "homepage": "https://rishikant181.github.io/Rettiwt-API/",
25
25
  "dependencies": {
26
- "axios": "^1.3.2",
26
+ "axios": "1.3.2",
27
27
  "cookiejar": "2.1.4",
28
28
  "express": "4.18.2",
29
29
  "express-graphql": "0.12.0",
@@ -32,11 +32,12 @@
32
32
  "node-libcurl": "3.0.0"
33
33
  },
34
34
  "devDependencies": {
35
- "@types/cookiejar": "^2.1.2",
35
+ "@types/cookiejar": "2.1.2",
36
36
  "@types/express": "4.17.13",
37
37
  "@types/graphql": "14.5.0",
38
38
  "@types/node": "17.0.24",
39
39
  "nodemon": "2.0.20",
40
+ "typedoc": "0.23.26",
40
41
  "typescript": "4.6.4"
41
42
  }
42
43
  }
package/src/index.ts CHANGED
@@ -5,8 +5,11 @@ import { TweetService } from "./services/data/TweetService";
5
5
  import { AccountService } from "./services/accounts/AccountService";
6
6
 
7
7
  /**
8
- * @param cookie The cookies string to use to fetch data
8
+ * @param cookie The cookie string to use to fetch data
9
9
  * @returns The API for fetching user and tweet data
10
+ * @remarks The cookie can be obtained by using {@link AccountService.login} method.
11
+ * To use the {@link AccountService.login} method, create a {@link Rettiwt} instance without passing any cookie string.
12
+ * Then use the {@link AccountService.login} method of {@link AccountService} to get the cookie.
10
13
  */
11
14
  export const Rettiwt = (cookie: string = '') => {
12
15
  // Creating new auth service instance using the given cookie string
@@ -20,8 +23,18 @@ export const Rettiwt = (cookie: string = '') => {
20
23
  };
21
24
  }
22
25
 
23
- // Exporting additional types
24
- export { User } from './types/data/User';
25
- export { Tweet, TweetEntities, TweetFilter } from './types/data/Tweet';
26
- export { Cursor, CursoredData } from './types/data/Service';
27
- export { AuthenticationErrors, ValidationErrors, DataErrors } from './types/data/Errors';
26
+ // Exporting classes
27
+ export * from './services/AuthService';
28
+ export * from './services/CacheService';
29
+ export * from './services/FetcherService';
30
+ export * from './services/accounts/AccountService';
31
+ export * from './services/data/TweetService';
32
+ export * from './services/data/UserService';
33
+
34
+ // Exporting types
35
+ export * from './types/data/Errors';
36
+ export * from './types/data/Service';
37
+ export * from './types/data/Tweet';
38
+ export * from './types/data/User';
39
+ export * from './types/Authentication';
40
+ export * from './types/HTTP';
@@ -11,13 +11,19 @@ import { GuestCredentials, AuthCredentials } from '../types/Authentication';
11
11
  import { config } from '../config/env';
12
12
 
13
13
  /**
14
- * @summary Handles authentication of http requests and other authentication related tasks
14
+ * Handles authentication of http requests and other authentication related tasks.
15
+ * @internal
15
16
  */
16
17
  export class AuthService {
17
18
  // MEMBER DATA
18
- private authToken: string; // To store the common auth token
19
- private credentials: AuthCredentials; // To store the current authentication credentials
20
- public isAuthenticated: boolean; // To store whether authenticated or not
19
+ /** The common bearer token for authentication. */
20
+ private authToken: string;
21
+
22
+ /** The current authentication credentials. */
23
+ private credentials: AuthCredentials;
24
+
25
+ /** Whether instance has been authenticated or not. */
26
+ public isAuthenticated: boolean;
21
27
 
22
28
  // MEMBER METHODS
23
29
  constructor(cookie: string = '') {
@@ -32,7 +38,7 @@ export class AuthService {
32
38
  * The following regex pattern is used to extract the csrfToken from the cookie string.
33
39
  * This is done by matching any string between the characters 'ct0=' and nearest enclosing ';'.
34
40
  * (?<=pattern) starts matching after the given pattern.
35
- * (?=pattern) stops matching just before the pattern
41
+ * (?=pattern) stops matching just before the pattern.
36
42
  */
37
43
  this.credentials = { authToken: this.authToken, csrfToken: cookie.match(/(?<=ct0=).+?(?=;)/) + '', cookie: cookie};
38
44
 
@@ -46,7 +52,7 @@ export class AuthService {
46
52
  }
47
53
 
48
54
  /**
49
- * @returns The guest credentials fetched from twitter
55
+ * @returns The guest credentials fetched from twitter.
50
56
  */
51
57
  async getGuestCredentials(): Promise<GuestCredentials> {
52
58
  // Getting the guest credentials from twitter
@@ -59,4 +65,4 @@ export class AuthService {
59
65
  guestToken: res.data.guest_token
60
66
  }));
61
67
  }
62
- }
68
+ }
@@ -5,9 +5,12 @@ import NodeCache from 'node-cache';
5
5
  import * as Parsers from './helper/Parser';
6
6
 
7
7
  /**
8
- * @summary Handles reading and writing of data from and to cache.
8
+ * Handles reading and writing of data from and to cache.
9
9
  *
10
- * **Note**: To be able to CacheService, the data to be cached must have a unique "id" field.
10
+ * This services uses a local node-cache instance to cache data, since the data to be cached has no real purpose outside of the server session.
11
+ * This serivce follows a singleton pattern, where at any point, only a single instance of this class exists.
12
+ * This is done so that all the data is cached in a single instance, which makes sharing of cached data between different endpoints possible.
13
+ * @internal
11
14
  */
12
15
  export class CacheService {
13
16
  // MEMBER DATA
@@ -34,9 +37,11 @@ export class CacheService {
34
37
  }
35
38
 
36
39
  /**
37
- * @summary Stores the input data into the cache.
38
- * @returns Whether writing to cache was successful or not
39
- * @param data The input data to store
40
+ * Stores the input data in the cache.
41
+ *
42
+ * @param data The input data to store.
43
+ * @returns Whether writing to cache was successful or not.
44
+ * @remarks In order to cache data, the data to be cached must have a unique 'id' field.
40
45
  */
41
46
  public write(data: any): void {
42
47
  // Converting the data to a list of data
@@ -56,8 +61,8 @@ export class CacheService {
56
61
  }
57
62
 
58
63
  /**
59
- * @returns The data with the given id/rest id from cache
60
- * @param id The id/rest id of the data to be fetched from cache
64
+ * @param id The id id of the data to be fetched from cache.
65
+ * @returns The data with the given id.
61
66
  */
62
67
  public read(id: string): any {
63
68
  // Getting data from cache
@@ -17,7 +17,7 @@ import * as TweetDeserializers from './helper/deserializers/Tweets';
17
17
  import { CurlyOptions } from 'node-libcurl/dist/curly';
18
18
 
19
19
  /**
20
- * @summary Stores all the different type of http requests
20
+ * The different types of http requests.
21
21
  */
22
22
  export enum HttpMethods {
23
23
  POST = "POST",
@@ -25,15 +25,26 @@ export enum HttpMethods {
25
25
  };
26
26
 
27
27
  /**
28
- * @service The base serivice from which all other data services derive their behaviour
28
+ * Handles all HTTP requests.
29
+ * @internal
30
+ *
31
+ * This serves as the base service from which all other data services derive their behaviour.
29
32
  */
30
33
  export class FetcherService {
31
34
  // MEMBER DATA
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
34
- protected isAuthenticated: boolean; // To store whether user is authenticated or not
35
+ /** The authentication service instance. */
36
+ private auth: AuthService;
37
+
38
+ /** The caching service instance. */
39
+ private cache: CacheService;
40
+
41
+ /** Whether instance has been authenticated or not. */
42
+ protected isAuthenticated: boolean;
35
43
 
36
44
  // MEMBER METHODS
45
+ /**
46
+ * @param auth The AuthService instance to use for authentication.
47
+ */
37
48
  constructor(auth: AuthService) {
38
49
  this.auth = auth;
39
50
  this.cache = CacheService.getInstance();
@@ -41,47 +52,75 @@ export class FetcherService {
41
52
  }
42
53
 
43
54
  /**
44
- * @summary Throws the appropriate http error after evaluation of the status code of reponse
45
- * @param res The response object received from http communication
55
+ * The middleware for handling any HTTP error.
56
+ *
57
+ * @param res The response object received.
58
+ * @throws {@link HttpStatus}.
59
+ * @returns The received response, if no HTTP errors are found.
46
60
  */
47
61
  private handleHTTPError(res: CurlyResult): CurlyResult {
62
+ /**
63
+ * If the status code is not 200 => the HTTP request was not successful. hence throwing error
64
+ */
48
65
  if (res.statusCode != 200 && res.statusCode in HttpStatus) {
49
66
  throw new Error(HttpStatus[res.statusCode])
50
67
  }
51
-
68
+
52
69
  return res;
53
70
  }
54
71
 
55
72
  /**
56
- * @returns The absolute raw json data from give url
57
- * @param url The url to fetch data from
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)
73
+ * Creates an HTTP request according to the given parameters.
74
+ *
75
+ * This method internally uses node-libcurl library to make curl requests to the URL, instead of node-fetch.
76
+ * This has been done since that way it better mimics the HTTP requests made from browser.
77
+ *
78
+ * @param url The url to fetch data from.
79
+ * @param authenticate Whether to authenticate requests or not.
80
+ * @param method The HTTP method (from {@link HttpMethods}) to use.
81
+ * @param data The data to be sent along with the request (for POST request).
82
+ * @returns The {@link CurlyResult} received.
61
83
  */
62
84
  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
85
+ /**
86
+ * Creating the request configuration based on the params
87
+ */
64
88
  let config: CurlyOptions = {
89
+ /**
90
+ * If authorization is required, using the authenticated header, using the authentication credentiials.
91
+ * Else, using the guest header, using the guest credentials.
92
+ */
65
93
  httpHeader: authenticate ? Headers.authorizedHeader(await this.auth.getAuthCredentials()) : Headers.guestHeader(await this.auth.getGuestCredentials()),
94
+ /**
95
+ * Disabling SSL peer verification because verification causes Error 404 (only while fetching tweets), likely because peer verification fails.
96
+ */
66
97
  sslVerifyPeer: false,
67
98
  };
68
99
 
69
- // If post request is to be made
100
+ /**
101
+ * While making requests, if data is to be sent, the JSON data first need to be stringified.
102
+ * After making the request, the response is then passed to HTTP error handling middlware for HTTP error handling.
103
+ */
104
+ // If POST request is to be made
70
105
  if (method == HttpMethods.POST) {
71
106
  return await curly.post(url, { ...config, postFields: JSON.stringify(data) }).then(res => this.handleHTTPError(res));
72
107
  }
73
- // If get request is to be made
108
+ // If GET request is to be made
74
109
  else {
75
110
  return await curly.get(url, config).then(res => this.handleHTTPError(res));
76
111
  }
77
112
  }
78
113
 
79
114
  /**
80
- * @summary Caches the extracted data
115
+ * Caches the extracted data into the {@link CacheService} instance.
116
+ *
81
117
  * @param data The extracted data to be cached
82
118
  */
83
119
  protected cacheData(data: any): void {
84
- // Parsing the extracted data
120
+ /**
121
+ * The extracted data is in raw form.
122
+ * This raw data is deserialized into the respective known types.
123
+ */
85
124
  let users = data.users.map((user: RawUser) => UserDeserializers.toUser(user));
86
125
  let tweets = data.tweets.map((tweet: RawTweet) => TweetDeserializers.toTweet(tweet));
87
126
 
@@ -91,11 +130,13 @@ export class FetcherService {
91
130
  }
92
131
 
93
132
  /**
94
- * @returns The data with the given id (if it exists in cache)
95
- * @param id The id of the data to be read from cache
133
+ * Fetches the data with the given id from the cache.
134
+ *
135
+ * @param id The id of the data to be read from cache.
136
+ * @returns The data with the given id. If does not exists, returns undefined.
96
137
  */
97
138
  protected readData(id: string): any {
98
139
  // Reading data from cache
99
140
  return this.cache.read(id);
100
141
  }
101
- }
142
+ }
@@ -6,18 +6,31 @@ import { AuthService } from '../AuthService';
6
6
 
7
7
  // TYPES
8
8
  import { GuestCredentials } from '../../types/Authentication';
9
+ import { HttpStatus } from '../../types/HTTP';
10
+ import { AuthenticationErrors } from '../../types/data/Errors';
9
11
 
10
12
  // HELPERS
11
13
  import LoginFlows from './LoginFlows';
12
14
  import { loginHeader } from '../helper/Headers';
13
15
  import { Cookie, CookieJar } from 'cookiejar';
14
16
 
17
+ /**
18
+ * Handles all operations related to a user's account, such as loggin in, managing account, etc
19
+ * @public
20
+ */
15
21
  export class AccountService {
16
22
  // 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
23
+ /** The AuthService instance to use for authentication. */
24
+ private auth: AuthService;
25
+
26
+ /** The current guest credentials to use. */
27
+ private guestCreds: GuestCredentials;
28
+
29
+ /** The cookies received from Twitter after logging in. */
30
+ private cookies: Cookie[];
31
+
32
+ /** The flow token received after execution of current flow. */
33
+ private flowToken: string;
21
34
 
22
35
  // MEMBER METHODS
23
36
  constructor() {
@@ -40,7 +53,8 @@ export class AccountService {
40
53
  }
41
54
 
42
55
  /**
43
- * @summary Step 1: Initiates login
56
+ * Step 1: Initiates login
57
+ * @internal
44
58
  */
45
59
  private async initiateLogin(): Promise<void> {
46
60
  // Initiating the login process
@@ -58,7 +72,8 @@ export class AccountService {
58
72
  }
59
73
 
60
74
  /**
61
- * @summary Step 2: Does something
75
+ * Step 2: Does something
76
+ * @internal
62
77
  */
63
78
  private async jsInstrumentationSubtask(): Promise<void> {
64
79
  // Executing the flow
@@ -73,7 +88,10 @@ export class AccountService {
73
88
  }
74
89
 
75
90
  /**
76
- * @summary Step 3: Takes the email for login
91
+ * Step 3: Takes the email for login
92
+ * @internal
93
+ *
94
+ * @throws {@link AuthenticationErrors.InvalidEmail}, if email does not exist.
77
95
  */
78
96
  private async enterUserIdentifier(email: string): Promise<void> {
79
97
  // Executing the flow
@@ -83,12 +101,20 @@ export class AccountService {
83
101
  postFields: JSON.stringify(LoginFlows.EnterUserIdentifier.body(this.flowToken, email))
84
102
  });
85
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
+
86
109
  // Getting the flow token
87
110
  this.flowToken = res.data['flow_token'];
88
111
  }
89
112
 
90
113
  /**
91
- * @summary Step 4: Takes the username for login
114
+ * Step 4: Takes the username for login
115
+ * @internal
116
+ *
117
+ * @throws {@link AuthenticationErrors.InvalidUsername}, if wrong username entered.
92
118
  */
93
119
  private async enterAlternateUserIdentifier(userName: string): Promise<void> {
94
120
  // Executing the flow
@@ -98,12 +124,20 @@ export class AccountService {
98
124
  postFields: JSON.stringify(LoginFlows.EnterAlternateUserIdentifier.body(this.flowToken, userName))
99
125
  });
100
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
+
101
132
  // Getting the flow token
102
133
  this.flowToken = res.data['flow_token'];
103
134
  }
104
135
 
105
136
  /**
106
- * @summary Step 5: Takes the password for login
137
+ * Step 5: Takes the password for login
138
+ * @internal
139
+ *
140
+ * @throws {@link AuthenticationErrors.InvalidPassword}, incorrect password entered.
107
141
  */
108
142
  private async enterPassword(password: string): Promise<void> {
109
143
  // Executing the flow
@@ -113,12 +147,18 @@ export class AccountService {
113
147
  postFields: JSON.stringify(LoginFlows.EnterPassword.body(this.flowToken, password))
114
148
  });
115
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
+
116
155
  // Getting the flow token
117
156
  this.flowToken = res.data['flow_token'];
118
157
  }
119
158
 
120
159
  /**
121
- * @summary Step 6: Gets the actual cookies
160
+ * Step 6: Gets the actual cookies
161
+ * @internal
122
162
  */
123
163
  private async accountDuplicationCheck(): Promise<void> {
124
164
  // Executing the flow
@@ -128,7 +168,7 @@ export class AccountService {
128
168
  postFields: JSON.stringify(LoginFlows.AccountDuplicationCheck.body(this.flowToken))
129
169
  });
130
170
 
131
- // Storing cookies received
171
+ // Getting the cookies from the set-cookie header of the reponse.
132
172
  this.cookies = new CookieJar().setCookies(res.headers[0]['Set-Cookie'] as string[]);
133
173
 
134
174
  // Getting the flow token
@@ -136,13 +176,22 @@ export class AccountService {
136
176
  }
137
177
 
138
178
  /**
179
+ * Login to Twitter using the given credentials and get back the cookies.
180
+ * @public
181
+ *
139
182
  * @param email The email of the account to be logged into
140
183
  * @param userName The username associated with the given account
141
184
  * @param password The password to the account
142
185
  * @returns The cookies for authenticating with the given account
143
186
  */
144
187
  public async login(email: string, userName: string, password: string): Promise<string> {
145
- // Executing each step of login flow
188
+ /**
189
+ * This works by sending a chain of request that are required for login to twitter.
190
+ * Each method in the chain returns a flow token that must be provied as payload in the next method in the chain.
191
+ * Each such method is called a subtask.
192
+ * Each subtask sets the {@link flowToken} property of the class which is then given in the payload of the next subtask.
193
+ * The final subtask returns the headers which actually contains the cookie in the 'set-cookie' field.
194
+ */
146
195
  await this.initiateLogin();
147
196
  await this.jsInstrumentationSubtask();
148
197
  await this.enterUserIdentifier(email);
@@ -27,19 +27,24 @@ import * as TweetDeserializers from '../helper/deserializers/Tweets';
27
27
  import { toQueryString } from '../helper/Parser';
28
28
 
29
29
  /**
30
- * A service that deals with fetching of data related to tweets
30
+ * Handles fetching of data related to tweets.
31
+ * @public
31
32
  */
32
33
  export class TweetService extends FetcherService {
33
34
  // MEMBER METHODS
35
+ /**
36
+ * @param auth The AuthService instance to use for authentication.
37
+ */
34
38
  constructor(auth: AuthService) {
35
39
  super(auth);
36
40
  }
37
41
 
38
42
  /**
39
- * @returns The list of tweets that match the given filter
40
- * @param filter The filter be used for searching the tweets
41
- * @param count The number of tweets to fetch, must be >= 1 and <= 100
42
- * @param cursor The cursor to the next batch of tweets. If blank, first batch is fetched
43
+ * @param filter The filter be used for searching the tweets.
44
+ * @param count The number of tweets to fetch.
45
+ * @param cursor The cursor to the next batch of tweets. If blank, first batch is fetched.
46
+ * @returns The list of tweets that match the given filter.
47
+ * @remarks count must be >= 1 and <= 100.
43
48
  */
44
49
  async getTweets(filter: TweetFilter, count: number, cursor: string): Promise<CursoredData<Tweet>> {
45
50
  // If invalid count provided
@@ -66,8 +71,8 @@ export class TweetService extends FetcherService {
66
71
  }
67
72
 
68
73
  /**
69
- * @returns The details of a single tweet with the given tweet id
70
- * @param tweetId The rest id of the target tweet
74
+ * @param tweetId The rest id of the target tweet.
75
+ * @returns The details of a single tweet with the given tweet id.
71
76
  */
72
77
  async getTweetById(tweetId: string): Promise<Tweet> {
73
78
  // Getting data from cache
@@ -94,10 +99,11 @@ export class TweetService extends FetcherService {
94
99
  }
95
100
 
96
101
  /**
97
- * @returns The list of users who liked the given tweet
98
- * @param tweetId The rest id of the target tweet
99
- * @param count The batch size of the list, must be >= 10 (when no cursor is provided) and <= 100
100
- * @param cursor The cursor to the next batch of users. If blank, first batch is fetched
102
+ * @param tweetId The rest id of the target tweet.
103
+ * @param count The batch size of the list.
104
+ * @param cursor The cursor to the next batch of users. If blank, first batch is fetched.
105
+ * @returns The list of users who liked the given tweet.
106
+ * @remarks count must be >= 10 (when no cursor is provided) and <= 100.
101
107
  */
102
108
  async getTweetLikers(tweetId: string, count: number, cursor: string): Promise<CursoredData<User>> {
103
109
  // If user is not authenticated, abort
@@ -129,10 +135,11 @@ export class TweetService extends FetcherService {
129
135
  }
130
136
 
131
137
  /**
132
- * @returns The list of users who retweeted the given tweet
133
- * @param tweetId The rest id of the target tweet
134
- * @param count The batch size of the list, must be >= 10 (when no cursor is provided) and <= 100
135
- * @param cursor The cursor to the next batch of users. If blank, first batch is fetched
138
+ * @param tweetId The rest id of the target tweet.
139
+ * @param count The batch size of the list.
140
+ * @param cursor The cursor to the next batch of users. If blank, first batch is fetched.
141
+ * @returns The list of users who retweeted the given tweet.
142
+ * @remarks count must be >= 10 (when no cursor is provided) and <= 100.
136
143
  */
137
144
  async getTweetRetweeters(tweetId: string, count: number, cursor: string): Promise<CursoredData<User>> {
138
145
  // If user is not authenticated, abort
@@ -167,9 +174,9 @@ export class TweetService extends FetcherService {
167
174
  * THIS IS DISABLED FOR USE FOR NOW BECAUSE TWITTER DOESN'T HAVE ANY ENDPOINT FOR FETCHING REPLIES.
168
175
  * THE DATA THIS RETURNS IS INCONSISTENT!
169
176
  *
170
- * @returns The list of replies to the given tweet
171
- * @param tweetId The rest id of the target tweet
172
- * @param cursor The cursor to the next batch of replies. If blank, first batch is fetched
177
+ * @param tweetId The rest id of the target tweet.
178
+ * @param cursor The cursor to the next batch of replies. If blank, first batch is fetched.
179
+ * @returns The list of replies to the given tweet.
173
180
  */
174
181
  /*
175
182
  async getTweetReplies(tweetId: string, cursor: string): Promise<CursoredData<Tweet>> {
@@ -24,17 +24,20 @@ import * as UserDeserializers from '../helper/deserializers/Users';
24
24
  import * as TweetDeserializers from '../helper/deserializers/Tweets';
25
25
 
26
26
  /**
27
- * A service that deals with fetching of data related to user account
27
+ * Handles fetching of data related to user account
28
28
  */
29
29
  export class UserService extends FetcherService {
30
30
  // MEMBER METHODS
31
+ /**
32
+ * @param auth The AuthService instance to use for authentication.
33
+ */
31
34
  constructor(auth: AuthService) {
32
35
  super(auth);
33
36
  }
34
37
 
35
38
  /**
36
- * @returns The details of the given user
37
39
  * @param screenName The screen name of the target user.
40
+ * @returns The details of the given user.
38
41
  */
39
42
  async getUserDetails(screenName: string): Promise<User> {
40
43
  // Fetching the raw data
@@ -53,8 +56,8 @@ export class UserService extends FetcherService {
53
56
  }
54
57
 
55
58
  /**
56
- * @returns The details of the user with given rest id
57
59
  * @param restId The screen name of the target user.
60
+ * @returns The details of the user with given rest id.
58
61
  */
59
62
  async getUserDetailsById(restId: string): Promise<User> {
60
63
  // Getting data from cache
@@ -81,10 +84,11 @@ export class UserService extends FetcherService {
81
84
  }
82
85
 
83
86
  /**
84
- * @returns The list of users followed by the target user
85
- * @param userId The rest id of the target user
86
- * @param count The number of following to fetch, should be >= 40 (when no cursor is provided) and <=100
87
- * @param cursor The cursor to next batch. If blank, first batch is fetched
87
+ * @param userId The rest id of the target user.
88
+ * @param count The number of following to fetch.
89
+ * @param cursor The cursor to next batch. If blank, first batch is fetched.
90
+ * @returns The list of users followed by the target user.
91
+ * @remarks count must be >= 40 (when no cursor is provided) and <=100.
88
92
  */
89
93
  async getUserFollowing(userId: string, count: number, cursor: string): Promise<CursoredData<User>> {
90
94
  // If user is not authenticated, abort
@@ -116,10 +120,11 @@ export class UserService extends FetcherService {
116
120
  }
117
121
 
118
122
  /**
119
- * @returns The list of users following the target user
120
- * @param userId The rest id of the target user
121
- * @param count The number of followers to fetch, should be >= 40 (when no cursor is provided) and <=100
122
- * @param cursor The cursor to next batch. If blank, first batch is fetched
123
+ * @param userId The rest id of the target user.
124
+ * @param count The number of followers to fetch.
125
+ * @param cursor The cursor to next batch. If blank, first batch is fetched.
126
+ * @returns The list of users following the target user.
127
+ * @remarks count must be >= 40 (when no cursor is provided) and <=100.
123
128
  */
124
129
  async getUserFollowers(userId: string, count: number, cursor: string): Promise<CursoredData<User>> {
125
130
  // If user is not authenticated, abort
@@ -151,10 +156,11 @@ export class UserService extends FetcherService {
151
156
  }
152
157
 
153
158
  /**
154
- * @returns The list of tweets liked by the target user
155
- * @param userId The rest id of the target user
156
- * @param count The number of likes to fetch, must be >= 40 (when no cursor is provided) and <= 100
157
- * @param cursor The cursor to next batch. If blank, first batch is fetched
159
+ * @param userId The rest id of the target user.
160
+ * @param count The number of likes to fetch.
161
+ * @param cursor The cursor to next batch. If blank, first batch is fetched.
162
+ * @returns The list of tweets liked by the target user.
163
+ * @remarks count must be >= 40 (when no cursor is provided) and <= 100.
158
164
  */
159
165
  async getUserLikes(userId: string, count: number, cursor: string): Promise<CursoredData<Tweet>> {
160
166
  // If user is not authenticated, abort