@irfanshadikrishad/anilist 1.0.0 → 1.0.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.
- package/README.md +47 -22
- package/bin/helpers/auth.d.ts +4 -3
- package/bin/helpers/auth.js +71 -22
- package/bin/helpers/fetcher.d.ts +12 -0
- package/bin/helpers/fetcher.js +54 -0
- package/bin/helpers/lists.d.ts +2 -1
- package/bin/helpers/lists.js +174 -13
- package/bin/helpers/more.d.ts +5 -1
- package/bin/helpers/more.js +227 -10
- package/bin/helpers/mutations.d.ts +4 -0
- package/bin/helpers/mutations.js +20 -0
- package/bin/helpers/queries.d.ts +20 -9
- package/bin/helpers/queries.js +103 -165
- package/bin/helpers/workers.d.ts +11 -1
- package/bin/helpers/workers.js +47 -7
- package/bin/index.js +62 -9
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -39,76 +39,101 @@ here `<client-id>` and `<client-secret>` should be replaced by the ones that you
|
|
|
39
39
|
|
|
40
40
|
#### CLI Commands Overview
|
|
41
41
|
|
|
42
|
-
| **Command**
|
|
43
|
-
|
|
|
44
|
-
| **`login`**
|
|
45
|
-
| **`logout`**
|
|
46
|
-
| **`me`**
|
|
47
|
-
| **`-V, --version`**
|
|
48
|
-
| **`-h, --help`**
|
|
49
|
-
| **`trending`** <br> _(alias: `tr`)_
|
|
50
|
-
| **`popular`** <br> _(alias: `plr`)_
|
|
51
|
-
| **`user`**
|
|
52
|
-
| **`lists`** <br> _(alias: `ls`)_
|
|
53
|
-
| **`delete`** <br> _(alias: `del`)_
|
|
42
|
+
| **Command** | **Options** | **Description** |
|
|
43
|
+
| ----------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------ |
|
|
44
|
+
| **`login`** | `-i, --id` `-s, --secret` | Log in with your AniList credentials |
|
|
45
|
+
| **`logout`** | _None_ | Log out from your AniList account |
|
|
46
|
+
| **`me`** | _None_ | Display information about the logged-in user |
|
|
47
|
+
| **`-V, --version`** | _None_ | Display the current version of the CLI |
|
|
48
|
+
| **`-h, --help`** | _None_ | Display available commands and options |
|
|
49
|
+
| **`trending`** <br> _(alias: `tr`)_ | `-c (default: 10)` | Fetch trending anime (default count is 10) |
|
|
50
|
+
| **`popular`** <br> _(alias: `plr`)_ | `-c (default: 10)` | Fetch popular anime (default count is 10) |
|
|
51
|
+
| **`user`** | `-un (username)` | Get information about a specific AniList user |
|
|
52
|
+
| **`lists`** <br> _(alias: `ls`)_ | `-a, --anime` <br> `-m, --manga` | Fetch anime or manga lists of the logged-in user |
|
|
53
|
+
| **`delete`** <br> _(alias: `del`)_ | `-a, --anime` <br> `-m, --manga` <br> `-ac, --activity` | Delete collections of anime, manga or activities |
|
|
54
|
+
| **`upcoming`** <br> _(alias:`up`)_ | `-c (default: 10)` | Fetch upcoming anime (default count is 10) |
|
|
55
|
+
| **`anime`** | `anime Id` | Get anime details by Anime Id |
|
|
56
|
+
| **`search`** <br> _(alias:`srch`/`find`)_ | `<query>` <br> `-a, --anime` <br> `-m, --manga` <br> `-c (default: 10)` | Get anime/manga search results |
|
|
54
57
|
|
|
55
58
|
#### Command Breakdown:
|
|
56
59
|
|
|
57
|
-
|
|
60
|
+
#### `login`:
|
|
58
61
|
|
|
59
62
|
- **Options**:
|
|
60
63
|
- `-i, --id`: Specify AniList Client ID
|
|
61
64
|
- `-s, --secret`: Provide the AniList Client Secret
|
|
62
65
|
- **Usage**: Authenticate and log in to AniList using your ID and secret credentials.
|
|
63
66
|
|
|
64
|
-
|
|
67
|
+
#### `logout`:
|
|
65
68
|
|
|
66
69
|
- **Description**: End the current session and log out from your AniList account.
|
|
67
70
|
|
|
68
|
-
|
|
71
|
+
#### `me`:
|
|
69
72
|
|
|
70
73
|
- **Description**: Retrieve and display information about the currently logged-in user, including stats and profile details.
|
|
71
74
|
|
|
72
|
-
|
|
75
|
+
#### `-V, --version`:
|
|
73
76
|
|
|
74
77
|
- **Description**: Quickly check which version of the CLI you are running.
|
|
75
78
|
|
|
76
|
-
|
|
79
|
+
#### `-h, --help`:
|
|
77
80
|
|
|
78
81
|
- **Description**: List all available commands and their usage details for quick reference.
|
|
79
82
|
|
|
80
|
-
|
|
83
|
+
#### `trending` _(alias: `tr`)_:
|
|
81
84
|
|
|
82
85
|
- **Options**:
|
|
83
86
|
- `-c (count)`: Specify how many trending anime to fetch (default: 10).
|
|
84
87
|
- **Description**: Fetch the current trending anime series, with the option to customize how many results to display.
|
|
85
88
|
|
|
86
|
-
|
|
89
|
+
#### `popular` _(alias: `plr`)_:
|
|
87
90
|
|
|
88
91
|
- **Options**:
|
|
89
92
|
- `-c (count)`: Specify how many popular anime to fetch (default: 10).
|
|
90
93
|
- **Description**: Fetch the most popular anime series, with the option to customize how many results to display.
|
|
91
94
|
|
|
92
|
-
|
|
95
|
+
#### `upcoming` _(alias: `up`)_:
|
|
96
|
+
|
|
97
|
+
- **Options**:
|
|
98
|
+
- `-c (count)`: Specify how many upcoming anime to fetch (default: 10).
|
|
99
|
+
- **Description**: Fetch the upcoming anime series next season, with the option to customize how many results to display.
|
|
100
|
+
|
|
101
|
+
#### `user`:
|
|
93
102
|
|
|
94
103
|
- **Options**:
|
|
95
104
|
- `-un (username)`: Specify the AniList username to fetch.
|
|
96
105
|
- **Description**: Retrieve profile information about a specific AniList user.
|
|
97
106
|
|
|
98
|
-
|
|
107
|
+
#### `lists` _(alias: `ls`)_:
|
|
99
108
|
|
|
100
109
|
- **Options**:
|
|
101
110
|
- `-a, --anime`: Fetch the authenticated user's anime list.
|
|
102
111
|
- `-m, --manga`: Fetch the authenticated user's manga list.
|
|
103
112
|
- **Description**: Get the anime or manga lists of the logged-in user.
|
|
104
113
|
|
|
105
|
-
|
|
114
|
+
#### `delete` _(alias: `del`)_:
|
|
106
115
|
|
|
107
116
|
- **Options**:
|
|
108
117
|
- `-a, --anime`: Delete your specific anime collection that you want.
|
|
109
118
|
- `-m, --manga`: Delete your specific manga collection that you want.
|
|
119
|
+
- `-ac, --activity`: Delete all or any type of activities you want.
|
|
110
120
|
- **Description**: Delete the entire anime or manga collection from the logged-in user's profile.
|
|
111
121
|
|
|
122
|
+
#### `anime`
|
|
123
|
+
|
|
124
|
+
- **Options**
|
|
125
|
+
- `anime Id` _(eg: 21)_ : Id of the anime you want to get details of.
|
|
126
|
+
- **Description**: Get anime details by anime Id.
|
|
127
|
+
|
|
128
|
+
#### `search` _(alias: `srch`/`find`)_:
|
|
129
|
+
|
|
130
|
+
- **Options**:
|
|
131
|
+
- `<query>` : What you want to search (eg: naruto).
|
|
132
|
+
- `-a, --anime`: To get results of anime search.
|
|
133
|
+
- `-m, --manga`: To get results of manga search.
|
|
134
|
+
- `-c (count)`: Specify how many items to fetch (default: 10).
|
|
135
|
+
- **Description**: Get anime/manga search results
|
|
136
|
+
|
|
112
137
|
#### Security
|
|
113
138
|
|
|
114
139
|
Since you are creating your own API client for login no else else can get your credentials and the generated access token will be stored in your own system. So, As long as you don't share your device (in case you do, just logout) you are safe.
|
package/bin/helpers/auth.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
declare function getAccessTokenFromUser(): Promise<any>;
|
|
2
2
|
declare function storeAccessToken(token: string): Promise<void>;
|
|
3
3
|
declare function retriveAccessToken(): Promise<string>;
|
|
4
|
-
declare function anilistUserLogin(
|
|
5
|
-
declare function currentUserInfo(): Promise<
|
|
4
|
+
declare function anilistUserLogin(clientId: number, clientSecret: string): Promise<void>;
|
|
5
|
+
declare function currentUserInfo(): Promise<any>;
|
|
6
6
|
declare function isLoggedIn(): Promise<Boolean>;
|
|
7
7
|
declare function logoutUser(): Promise<void>;
|
|
8
8
|
declare function currentUsersId(): Promise<any>;
|
|
9
|
-
|
|
9
|
+
declare function currentUsersName(): Promise<any>;
|
|
10
|
+
export { getAccessTokenFromUser, storeAccessToken, retriveAccessToken, anilistUserLogin, currentUserInfo, isLoggedIn, logoutUser, currentUsersId, currentUsersName, };
|
package/bin/helpers/auth.js
CHANGED
|
@@ -13,25 +13,31 @@ import path from "path";
|
|
|
13
13
|
import inquirer from "inquirer";
|
|
14
14
|
import open from "open";
|
|
15
15
|
import fetch from "node-fetch";
|
|
16
|
-
import { currentUserQuery } from "./queries.js";
|
|
17
|
-
import { aniListEndpoint, redirectUri } from "./workers.js";
|
|
16
|
+
import { currentUserQuery, userActivityQuery } from "./queries.js";
|
|
17
|
+
import { aniListEndpoint, getTitle, redirectUri } from "./workers.js";
|
|
18
|
+
import { fetcher } from "./fetcher.js";
|
|
18
19
|
const home_dir = os.homedir();
|
|
19
20
|
const save_path = path.join(home_dir, ".anilist_token");
|
|
20
21
|
function getAccessTokenFromUser() {
|
|
21
22
|
return __awaiter(this, void 0, void 0, function* () {
|
|
22
|
-
const
|
|
23
|
+
const { token } = yield inquirer.prompt([
|
|
23
24
|
{
|
|
24
25
|
type: "password",
|
|
25
26
|
name: "token",
|
|
26
27
|
message: "Please enter your AniList access token:",
|
|
27
28
|
},
|
|
28
29
|
]);
|
|
29
|
-
return
|
|
30
|
+
return token;
|
|
30
31
|
});
|
|
31
32
|
}
|
|
32
33
|
function storeAccessToken(token) {
|
|
33
34
|
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
-
|
|
35
|
+
try {
|
|
36
|
+
fs.writeFileSync(save_path, token, { encoding: "utf8" });
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error(`Error storing acess-token.`);
|
|
40
|
+
}
|
|
35
41
|
});
|
|
36
42
|
}
|
|
37
43
|
function retriveAccessToken() {
|
|
@@ -44,10 +50,10 @@ function retriveAccessToken() {
|
|
|
44
50
|
}
|
|
45
51
|
});
|
|
46
52
|
}
|
|
47
|
-
function anilistUserLogin(
|
|
53
|
+
function anilistUserLogin(clientId, clientSecret) {
|
|
48
54
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49
55
|
console.log("Starting AniList login...");
|
|
50
|
-
const authUrl = `https://anilist.co/api/v2/oauth/authorize?client_id=${
|
|
56
|
+
const authUrl = `https://anilist.co/api/v2/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code`;
|
|
51
57
|
console.log("Opening browser for AniList login...");
|
|
52
58
|
open(authUrl);
|
|
53
59
|
const authCode = yield getAccessTokenFromUser();
|
|
@@ -58,16 +64,22 @@ function anilistUserLogin(cID, cSECRET) {
|
|
|
58
64
|
},
|
|
59
65
|
body: JSON.stringify({
|
|
60
66
|
grant_type: "authorization_code",
|
|
61
|
-
client_id: String(
|
|
62
|
-
client_secret:
|
|
67
|
+
client_id: String(clientId),
|
|
68
|
+
client_secret: clientSecret,
|
|
63
69
|
redirect_uri: redirectUri,
|
|
64
70
|
code: authCode,
|
|
65
71
|
}),
|
|
66
72
|
});
|
|
67
73
|
const token_Data = yield tokenResponse.json();
|
|
68
74
|
if (token_Data === null || token_Data === void 0 ? void 0 : token_Data.access_token) {
|
|
69
|
-
console.log("Login successful!");
|
|
70
75
|
yield storeAccessToken(token_Data === null || token_Data === void 0 ? void 0 : token_Data.access_token);
|
|
76
|
+
const name = yield currentUsersName();
|
|
77
|
+
if (name) {
|
|
78
|
+
console.log(`\nWelcome Back, ${name}!`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.log(`Logged in successfull!`);
|
|
82
|
+
}
|
|
71
83
|
}
|
|
72
84
|
else {
|
|
73
85
|
console.error("Failed to get access token:", token_Data);
|
|
@@ -76,41 +88,58 @@ function anilistUserLogin(cID, cSECRET) {
|
|
|
76
88
|
}
|
|
77
89
|
function currentUserInfo() {
|
|
78
90
|
return __awaiter(this, void 0, void 0, function* () {
|
|
79
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
91
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
80
92
|
const loggedIn = yield isLoggedIn();
|
|
81
93
|
if (loggedIn) {
|
|
82
94
|
const sToken = yield retriveAccessToken();
|
|
95
|
+
const headers = {
|
|
96
|
+
"Content-Type": "application/json",
|
|
97
|
+
Authorization: `Bearer ${sToken}`,
|
|
98
|
+
};
|
|
83
99
|
const request = yield fetch(aniListEndpoint, {
|
|
84
100
|
method: "POST",
|
|
85
|
-
headers:
|
|
86
|
-
"Content-Type": "application/json",
|
|
87
|
-
Authorization: `Bearer ${sToken}`,
|
|
88
|
-
},
|
|
101
|
+
headers: headers,
|
|
89
102
|
body: JSON.stringify({ query: currentUserQuery }),
|
|
90
103
|
});
|
|
91
104
|
const { data, errors } = yield request.json();
|
|
92
105
|
if (request.status === 200) {
|
|
93
106
|
const user = data === null || data === void 0 ? void 0 : data.Viewer;
|
|
107
|
+
const activiResponse = yield fetcher(userActivityQuery, {
|
|
108
|
+
id: user === null || user === void 0 ? void 0 : user.id,
|
|
109
|
+
page: 1,
|
|
110
|
+
perPage: 10,
|
|
111
|
+
});
|
|
112
|
+
const activities = (_b = (_a = activiResponse === null || activiResponse === void 0 ? void 0 : activiResponse.data) === null || _a === void 0 ? void 0 : _a.Page) === null || _b === void 0 ? void 0 : _b.activities;
|
|
94
113
|
console.log(`\nID:\t\t\t${user === null || user === void 0 ? void 0 : user.id}`);
|
|
95
114
|
console.log(`Name:\t\t\t${user === null || user === void 0 ? void 0 : user.name}`);
|
|
96
115
|
console.log(`siteUrl:\t\t${user === null || user === void 0 ? void 0 : user.siteUrl}`);
|
|
97
|
-
console.log(`profileColor:\t\t${(
|
|
98
|
-
console.log(`timeZone:\t\t${(
|
|
99
|
-
console.log(`activityMergeTime:\t${(
|
|
116
|
+
console.log(`profileColor:\t\t${(_c = user === null || user === void 0 ? void 0 : user.options) === null || _c === void 0 ? void 0 : _c.profileColor}`);
|
|
117
|
+
console.log(`timeZone:\t\t${(_d = user === null || user === void 0 ? void 0 : user.options) === null || _d === void 0 ? void 0 : _d.timezone}`);
|
|
118
|
+
console.log(`activityMergeTime:\t${(_e = user === null || user === void 0 ? void 0 : user.options) === null || _e === void 0 ? void 0 : _e.activityMergeTime}`);
|
|
100
119
|
console.log(`donatorTier:\t\t${user === null || user === void 0 ? void 0 : user.donatorTier}`);
|
|
101
120
|
console.log(`donatorBadge:\t\t${user === null || user === void 0 ? void 0 : user.donatorBadge}`);
|
|
102
121
|
console.log(`unreadNotificationCount:${user === null || user === void 0 ? void 0 : user.unreadNotificationCount}`);
|
|
103
122
|
console.log(`Account Created:\t${new Date((user === null || user === void 0 ? void 0 : user.createdAt) * 1000).toUTCString()}`);
|
|
104
123
|
console.log(`Account Updated:\t${new Date((user === null || user === void 0 ? void 0 : user.updatedAt) * 1000).toUTCString()}`);
|
|
105
|
-
console.log(
|
|
106
|
-
console.log(`Statistics (Manga)\nCount: ${(
|
|
124
|
+
console.log(`\nStatistics (Anime)\nCount: ${(_g = (_f = user === null || user === void 0 ? void 0 : user.statistics) === null || _f === void 0 ? void 0 : _f.anime) === null || _g === void 0 ? void 0 : _g.count} meanScore: ${(_j = (_h = user === null || user === void 0 ? void 0 : user.statistics) === null || _h === void 0 ? void 0 : _h.anime) === null || _j === void 0 ? void 0 : _j.meanScore} minutesWatched: ${(_l = (_k = user === null || user === void 0 ? void 0 : user.statistics) === null || _k === void 0 ? void 0 : _k.anime) === null || _l === void 0 ? void 0 : _l.minutesWatched}`);
|
|
125
|
+
console.log(`Statistics (Manga)\nCount: ${(_o = (_m = user === null || user === void 0 ? void 0 : user.statistics) === null || _m === void 0 ? void 0 : _m.manga) === null || _o === void 0 ? void 0 : _o.count} Chapter Read: ${(_q = (_p = user === null || user === void 0 ? void 0 : user.statistics) === null || _p === void 0 ? void 0 : _p.manga) === null || _q === void 0 ? void 0 : _q.chaptersRead} Volumes Read: ${(_s = (_r = user === null || user === void 0 ? void 0 : user.statistics) === null || _r === void 0 ? void 0 : _r.manga) === null || _s === void 0 ? void 0 : _s.volumesRead}`);
|
|
126
|
+
console.log(`\nRecent Activities:`);
|
|
127
|
+
activities.length > 0 &&
|
|
128
|
+
activities.map(({ id, status, progress, createdAt, media }, idx) => {
|
|
129
|
+
progress
|
|
130
|
+
? console.log(`${status} ${progress} of ${getTitle(media === null || media === void 0 ? void 0 : media.title)}`)
|
|
131
|
+
: console.log(`${status} ${getTitle(media === null || media === void 0 ? void 0 : media.title)}`);
|
|
132
|
+
});
|
|
133
|
+
return user;
|
|
107
134
|
}
|
|
108
135
|
else {
|
|
109
136
|
console.log(`Something went wrong. Please log in again. ${errors[0].message}`);
|
|
137
|
+
return null;
|
|
110
138
|
}
|
|
111
139
|
}
|
|
112
140
|
else {
|
|
113
141
|
console.log(`User not logged in. Please login first.`);
|
|
142
|
+
return null;
|
|
114
143
|
}
|
|
115
144
|
});
|
|
116
145
|
}
|
|
@@ -130,7 +159,7 @@ function logoutUser() {
|
|
|
130
159
|
if (fs.existsSync(save_path)) {
|
|
131
160
|
try {
|
|
132
161
|
fs.unlinkSync(save_path);
|
|
133
|
-
console.log("
|
|
162
|
+
console.log("\nLogout successful.");
|
|
134
163
|
}
|
|
135
164
|
catch (error) {
|
|
136
165
|
console.error("Error logging out:", error);
|
|
@@ -161,4 +190,24 @@ function currentUsersId() {
|
|
|
161
190
|
}
|
|
162
191
|
});
|
|
163
192
|
}
|
|
164
|
-
|
|
193
|
+
function currentUsersName() {
|
|
194
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
195
|
+
var _a;
|
|
196
|
+
const request = yield fetch(aniListEndpoint, {
|
|
197
|
+
method: "POST",
|
|
198
|
+
headers: {
|
|
199
|
+
"Content-Type": "application/json",
|
|
200
|
+
Authorization: `Bearer ${yield retriveAccessToken()}`,
|
|
201
|
+
},
|
|
202
|
+
body: JSON.stringify({ query: currentUserQuery }),
|
|
203
|
+
});
|
|
204
|
+
const { data } = yield request.json();
|
|
205
|
+
if (request.status === 200) {
|
|
206
|
+
return (_a = data === null || data === void 0 ? void 0 : data.Viewer) === null || _a === void 0 ? void 0 : _a.name;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
export { getAccessTokenFromUser, storeAccessToken, retriveAccessToken, anilistUserLogin, currentUserInfo, isLoggedIn, logoutUser, currentUsersId, currentUsersName, };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sends a GraphQL request to the AniList API.
|
|
3
|
+
*
|
|
4
|
+
* This function constructs a request with the provided query and variables,
|
|
5
|
+
* handles authorization, and processes the API response.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} query - The AniList GraphQL query to be executed.
|
|
8
|
+
* @param {object} variables - An object containing the variables for the query.
|
|
9
|
+
* @returns {Promise<object|null>} The response from the API as a JSON object if successful; otherwise, null.
|
|
10
|
+
*/
|
|
11
|
+
declare function fetcher(query: string, variables: object): Promise<object | null>;
|
|
12
|
+
export { fetcher };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import fetch from "node-fetch";
|
|
11
|
+
import { aniListEndpoint } from "./workers.js";
|
|
12
|
+
import { isLoggedIn, retriveAccessToken } from "./auth.js";
|
|
13
|
+
/**
|
|
14
|
+
* Sends a GraphQL request to the AniList API.
|
|
15
|
+
*
|
|
16
|
+
* This function constructs a request with the provided query and variables,
|
|
17
|
+
* handles authorization, and processes the API response.
|
|
18
|
+
*
|
|
19
|
+
* @param {string} query - The AniList GraphQL query to be executed.
|
|
20
|
+
* @param {object} variables - An object containing the variables for the query.
|
|
21
|
+
* @returns {Promise<object|null>} The response from the API as a JSON object if successful; otherwise, null.
|
|
22
|
+
*/
|
|
23
|
+
function fetcher(query, variables) {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
var _a;
|
|
26
|
+
try {
|
|
27
|
+
const LOGGEDIN = yield isLoggedIn();
|
|
28
|
+
const headers = {
|
|
29
|
+
"content-type": "application/json",
|
|
30
|
+
};
|
|
31
|
+
if (LOGGEDIN) {
|
|
32
|
+
headers["Authorization"] = `Bearer ${yield retriveAccessToken()}`;
|
|
33
|
+
}
|
|
34
|
+
const request = yield fetch(aniListEndpoint, {
|
|
35
|
+
method: "POST",
|
|
36
|
+
headers: headers,
|
|
37
|
+
body: JSON.stringify({ query, variables }),
|
|
38
|
+
});
|
|
39
|
+
const response = yield request.json();
|
|
40
|
+
if (request.status === 200) {
|
|
41
|
+
return response;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.error(`Error from fetcher. ${(_a = response === null || response === void 0 ? void 0 : response.errors[0]) === null || _a === void 0 ? void 0 : _a.message}.`);
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
console.error(`Something went wrong. ${error.message}.`);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export { fetcher };
|
package/bin/helpers/lists.d.ts
CHANGED
|
@@ -4,4 +4,5 @@ declare function loggedInUsersAnimeLists(): Promise<void>;
|
|
|
4
4
|
declare function loggedInUsersMangaLists(): Promise<void>;
|
|
5
5
|
declare function deleteAnimeCollection(): Promise<void>;
|
|
6
6
|
declare function deleteMangaCollection(): Promise<void>;
|
|
7
|
-
|
|
7
|
+
declare function getUpcomingAnimes(count: number): Promise<void>;
|
|
8
|
+
export { getTrending, getPopular, getUpcomingAnimes, loggedInUsersAnimeLists, loggedInUsersMangaLists, deleteAnimeCollection, deleteMangaCollection, };
|
package/bin/helpers/lists.js
CHANGED
|
@@ -9,13 +9,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import fetch from "node-fetch";
|
|
11
11
|
import inquirer from "inquirer";
|
|
12
|
-
import { aniListEndpoint, getTitle } from "./workers.js";
|
|
13
|
-
import { deleteMangaEntryMutation, deleteMediaEntryMutation, popularQuery, trendingQuery, } from "./queries.js";
|
|
12
|
+
import { aniListEndpoint, getNextSeasonAndYear, getTitle } from "./workers.js";
|
|
13
|
+
import { deleteMangaEntryMutation, deleteMediaEntryMutation, popularQuery, trendingQuery, upcomingAnimesQuery, } from "./queries.js";
|
|
14
14
|
import { currentUserAnimeList, currentUserMangaList } from "./queries.js";
|
|
15
15
|
import { isLoggedIn, currentUsersId, retriveAccessToken } from "./auth.js";
|
|
16
|
+
import { addAnimeToListMutation } from "./mutations.js";
|
|
17
|
+
import { fetcher } from "./fetcher.js";
|
|
16
18
|
function getTrending(count) {
|
|
17
19
|
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
-
var _a, _b, _c;
|
|
20
|
+
var _a, _b, _c, _d;
|
|
19
21
|
try {
|
|
20
22
|
const request = yield fetch(aniListEndpoint, {
|
|
21
23
|
method: "POST",
|
|
@@ -31,13 +33,56 @@ function getTrending(count) {
|
|
|
31
33
|
if (request.status === 200) {
|
|
32
34
|
const media = (_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.Page) === null || _b === void 0 ? void 0 : _b.media;
|
|
33
35
|
if ((media === null || media === void 0 ? void 0 : media.length) > 0) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
const { selectedAnime } = yield inquirer.prompt([
|
|
37
|
+
{
|
|
38
|
+
type: "list",
|
|
39
|
+
name: "selectedAnime",
|
|
40
|
+
message: "Select anime to add to the list:",
|
|
41
|
+
choices: media.map((upx) => ({
|
|
42
|
+
name: getTitle(upx === null || upx === void 0 ? void 0 : upx.title),
|
|
43
|
+
value: upx === null || upx === void 0 ? void 0 : upx.id,
|
|
44
|
+
})),
|
|
45
|
+
},
|
|
46
|
+
]);
|
|
47
|
+
// Where to save
|
|
48
|
+
const { selectedListType } = yield inquirer.prompt([
|
|
49
|
+
{
|
|
50
|
+
type: "list",
|
|
51
|
+
name: "selectedListType",
|
|
52
|
+
message: "Select the list where you want to save this anime:",
|
|
53
|
+
choices: [
|
|
54
|
+
{ name: "Planning", value: "PLANNING" },
|
|
55
|
+
{ name: "Watching", value: "CURRENT" },
|
|
56
|
+
{ name: "Completed", value: "COMPLETED" },
|
|
57
|
+
{ name: "Paused", value: "PAUSED" },
|
|
58
|
+
{ name: "Dropped", value: "DROPPED" },
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
]);
|
|
62
|
+
// Lets save to the list now
|
|
63
|
+
const ISLOGGEDIN = yield isLoggedIn();
|
|
64
|
+
if (ISLOGGEDIN) {
|
|
65
|
+
const query = addAnimeToListMutation;
|
|
66
|
+
const variables = {
|
|
67
|
+
mediaId: selectedAnime,
|
|
68
|
+
status: selectedListType,
|
|
69
|
+
};
|
|
70
|
+
const response = yield fetcher(query, variables);
|
|
71
|
+
if (response) {
|
|
72
|
+
const saved = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
|
|
73
|
+
console.log(`\nEntry ${saved === null || saved === void 0 ? void 0 : saved.id}. Saved as ${saved === null || saved === void 0 ? void 0 : saved.status}.`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
console.error(`Please log in first to use this feature.`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
console.log(`\nNo trending available at the moment.`);
|
|
37
82
|
}
|
|
38
83
|
}
|
|
39
84
|
else {
|
|
40
|
-
console.log(`Something went wrong. ${(
|
|
85
|
+
console.log(`Something went wrong. ${(_d = response === null || response === void 0 ? void 0 : response.errors[0]) === null || _d === void 0 ? void 0 : _d.message}`);
|
|
41
86
|
}
|
|
42
87
|
}
|
|
43
88
|
catch (error) {
|
|
@@ -47,7 +92,7 @@ function getTrending(count) {
|
|
|
47
92
|
}
|
|
48
93
|
function getPopular(count) {
|
|
49
94
|
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
-
var _a, _b, _c;
|
|
95
|
+
var _a, _b, _c, _d;
|
|
51
96
|
try {
|
|
52
97
|
const request = yield fetch(aniListEndpoint, {
|
|
53
98
|
method: "POST",
|
|
@@ -63,13 +108,56 @@ function getPopular(count) {
|
|
|
63
108
|
if (request.status === 200) {
|
|
64
109
|
const media = (_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.Page) === null || _b === void 0 ? void 0 : _b.media;
|
|
65
110
|
if ((media === null || media === void 0 ? void 0 : media.length) > 0) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
111
|
+
const { selectedAnime } = yield inquirer.prompt([
|
|
112
|
+
{
|
|
113
|
+
type: "list",
|
|
114
|
+
name: "selectedAnime",
|
|
115
|
+
message: "Select anime to add to the list:",
|
|
116
|
+
choices: media.map((upx) => ({
|
|
117
|
+
name: getTitle(upx === null || upx === void 0 ? void 0 : upx.title),
|
|
118
|
+
value: upx === null || upx === void 0 ? void 0 : upx.id,
|
|
119
|
+
})),
|
|
120
|
+
},
|
|
121
|
+
]);
|
|
122
|
+
// Where to save
|
|
123
|
+
const { selectedListType } = yield inquirer.prompt([
|
|
124
|
+
{
|
|
125
|
+
type: "list",
|
|
126
|
+
name: "selectedListType",
|
|
127
|
+
message: "Select the list where you want to save this anime:",
|
|
128
|
+
choices: [
|
|
129
|
+
{ name: "Planning", value: "PLANNING" },
|
|
130
|
+
{ name: "Watching", value: "CURRENT" },
|
|
131
|
+
{ name: "Completed", value: "COMPLETED" },
|
|
132
|
+
{ name: "Paused", value: "PAUSED" },
|
|
133
|
+
{ name: "Dropped", value: "DROPPED" },
|
|
134
|
+
],
|
|
135
|
+
},
|
|
136
|
+
]);
|
|
137
|
+
// Lets save to the list now
|
|
138
|
+
const ISLOGGEDIN = yield isLoggedIn();
|
|
139
|
+
if (ISLOGGEDIN) {
|
|
140
|
+
const query = addAnimeToListMutation;
|
|
141
|
+
const variables = {
|
|
142
|
+
mediaId: selectedAnime,
|
|
143
|
+
status: selectedListType,
|
|
144
|
+
};
|
|
145
|
+
const response = yield fetcher(query, variables);
|
|
146
|
+
if (response) {
|
|
147
|
+
const saved = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
|
|
148
|
+
console.log(`\nEntry ${saved === null || saved === void 0 ? void 0 : saved.id}. Saved as ${saved === null || saved === void 0 ? void 0 : saved.status}.`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
console.error(`Please log in first to use this feature.`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
console.log(`No popular available at this moment.`);
|
|
69
157
|
}
|
|
70
158
|
}
|
|
71
159
|
else {
|
|
72
|
-
console.log(`Something went wrong. ${(
|
|
160
|
+
console.log(`Something went wrong. ${(_d = response === null || response === void 0 ? void 0 : response.errors[0]) === null || _d === void 0 ? void 0 : _d.message}`);
|
|
73
161
|
}
|
|
74
162
|
}
|
|
75
163
|
catch (error) {
|
|
@@ -375,4 +463,77 @@ function deleteMangaByMangaId(id, title) {
|
|
|
375
463
|
}
|
|
376
464
|
});
|
|
377
465
|
}
|
|
378
|
-
|
|
466
|
+
function getUpcomingAnimes(count) {
|
|
467
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
468
|
+
var _a, _b, _c, _d, _e;
|
|
469
|
+
try {
|
|
470
|
+
const { nextSeason, nextYear } = getNextSeasonAndYear();
|
|
471
|
+
const loggedIn = yield isLoggedIn();
|
|
472
|
+
let headers = {
|
|
473
|
+
"content-type": "application/json",
|
|
474
|
+
};
|
|
475
|
+
if (loggedIn) {
|
|
476
|
+
headers["Authorization"] = `Bearer ${yield retriveAccessToken()}`;
|
|
477
|
+
}
|
|
478
|
+
const request = yield fetch(aniListEndpoint, {
|
|
479
|
+
method: "POST",
|
|
480
|
+
headers: headers,
|
|
481
|
+
body: JSON.stringify({
|
|
482
|
+
query: upcomingAnimesQuery,
|
|
483
|
+
variables: { nextSeason, nextYear, perPage: count },
|
|
484
|
+
}),
|
|
485
|
+
});
|
|
486
|
+
const response = yield request.json();
|
|
487
|
+
if (request.status === 200) {
|
|
488
|
+
const upcoming = (_c = (_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.Page) === null || _b === void 0 ? void 0 : _b.media) !== null && _c !== void 0 ? _c : [];
|
|
489
|
+
const { selectedAnime } = yield inquirer.prompt([
|
|
490
|
+
{
|
|
491
|
+
type: "list",
|
|
492
|
+
name: "selectedAnime",
|
|
493
|
+
message: "Select anime to add to the list:",
|
|
494
|
+
choices: upcoming.map((upx) => ({
|
|
495
|
+
name: getTitle(upx === null || upx === void 0 ? void 0 : upx.title),
|
|
496
|
+
value: upx === null || upx === void 0 ? void 0 : upx.id,
|
|
497
|
+
})),
|
|
498
|
+
},
|
|
499
|
+
]);
|
|
500
|
+
// Where to save
|
|
501
|
+
const { selectedListType } = yield inquirer.prompt([
|
|
502
|
+
{
|
|
503
|
+
type: "list",
|
|
504
|
+
name: "selectedListType",
|
|
505
|
+
message: "Select the list where you want to save this anime:",
|
|
506
|
+
choices: [
|
|
507
|
+
{ name: "Planning", value: "PLANNING" },
|
|
508
|
+
{ name: "Watching", value: "CURRENT" },
|
|
509
|
+
{ name: "Completed", value: "COMPLETED" },
|
|
510
|
+
{ name: "Paused", value: "PAUSED" },
|
|
511
|
+
{ name: "Dropped", value: "DROPPED" },
|
|
512
|
+
],
|
|
513
|
+
},
|
|
514
|
+
]);
|
|
515
|
+
// Lets save to the list now
|
|
516
|
+
const ISLOGGEDIN = yield isLoggedIn();
|
|
517
|
+
if (ISLOGGEDIN) {
|
|
518
|
+
const query = addAnimeToListMutation;
|
|
519
|
+
const variables = { mediaId: selectedAnime, status: selectedListType };
|
|
520
|
+
const response = yield fetcher(query, variables);
|
|
521
|
+
if (response) {
|
|
522
|
+
const saved = (_d = response === null || response === void 0 ? void 0 : response.data) === null || _d === void 0 ? void 0 : _d.SaveMediaListEntry;
|
|
523
|
+
console.log(`\nEntry ${saved === null || saved === void 0 ? void 0 : saved.id}. Saved as ${saved === null || saved === void 0 ? void 0 : saved.status}.`);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
console.error(`Please log in first to use this feature.`);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
else {
|
|
531
|
+
console.error(`Something went wrong. ${(_e = response === null || response === void 0 ? void 0 : response.errors[0]) === null || _e === void 0 ? void 0 : _e.message}`);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
catch (error) {
|
|
535
|
+
console.error(`Error getting upcoming animes. ${error.message}`);
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
export { getTrending, getPopular, getUpcomingAnimes, loggedInUsersAnimeLists, loggedInUsersMangaLists, deleteAnimeCollection, deleteMangaCollection, };
|
package/bin/helpers/more.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
declare function getUserInfoByUsername(username: string): Promise<void>;
|
|
2
|
-
|
|
2
|
+
declare function getAnimeDetailsByID(anilistID: number): Promise<void>;
|
|
3
|
+
declare function getAnimeSearchResults(search: string, count: number): Promise<void>;
|
|
4
|
+
declare function getMangaSearchResults(search: string, count: number): Promise<void>;
|
|
5
|
+
declare function deleteUserActivities(): Promise<void>;
|
|
6
|
+
export { getUserInfoByUsername, getAnimeDetailsByID, getAnimeSearchResults, getMangaSearchResults, deleteUserActivities, };
|