gj-boomlings-api 2.0.2 → 2.1.0

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 (48) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +4 -4
  3. package/functions/acceptFriendRequest.js +39 -0
  4. package/functions/blockUser.js +12 -13
  5. package/functions/deleteAccountPost.js +12 -11
  6. package/functions/deleteComment.js +11 -12
  7. package/functions/deleteFriendRequest.js +43 -0
  8. package/functions/deleteLevel.js +10 -13
  9. package/functions/deleteMessage.js +37 -0
  10. package/functions/{dlLevel.js → downloadLevel.js} +46 -38
  11. package/functions/{dlMessage.js → downloadMessage.js} +9 -8
  12. package/functions/getAccountPosts.js +3 -4
  13. package/functions/getBlockedList.js +31 -12
  14. package/functions/getCommentHistory.js +8 -6
  15. package/functions/getComments.js +11 -7
  16. package/functions/getCreatorScores.js +13 -4
  17. package/functions/getDailyLevel.js +3 -3
  18. package/functions/getFriendRequests.js +87 -0
  19. package/functions/getFriendsList.js +25 -11
  20. package/functions/getGauntlets.js +5 -3
  21. package/functions/getLevelByID.js +2 -2
  22. package/functions/getLevelScores.js +22 -21
  23. package/functions/getMapPacks.js +1 -1
  24. package/functions/getMessages.js +10 -10
  25. package/functions/getProfile.js +139 -41
  26. package/functions/getSongInfo.js +3 -3
  27. package/functions/getTab.js +2 -2
  28. package/functions/getTop100.js +1 -1
  29. package/functions/getTopLists.js +1 -1
  30. package/functions/getUserLevels.js +3 -3
  31. package/functions/getWeeklyDemon.js +3 -3
  32. package/functions/removeFriend.js +40 -0
  33. package/functions/reportLevel.js +2 -2
  34. package/functions/searchLevels.js +1 -1
  35. package/functions/searchLists.js +2 -2
  36. package/functions/unblockUser.js +13 -14
  37. package/functions/updateLevelDesc.js +9 -10
  38. package/functions/uploadAccountPost.js +10 -11
  39. package/functions/uploadComment.js +15 -15
  40. package/functions/uploadFriendRequest.js +42 -0
  41. package/functions/uploadMessage.js +15 -15
  42. package/index.js +29 -3
  43. package/misc/GJDecode.js +12 -9
  44. package/misc/gauntlets.json +13 -1
  45. package/misc/gjp2.js +5 -0
  46. package/package.json +1 -1
  47. /package/{gjReq.js → misc/gjReq.js} +0 -0
  48. /package/{xor.js → misc/xor.js} +0 -0
package/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2025 shikoshib
1
+ Copyright 2026 shikoshib
2
2
 
3
3
  Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
4
4
 
package/README.md CHANGED
@@ -18,7 +18,7 @@ yarn add gj-boomlings-api
18
18
  ## Download a level
19
19
  ```js
20
20
  const gd = require("gj-boomlings-api");
21
- gd.dlLevel("95540029").then(console.log);
21
+ gd.downloadLevel("117041578").then(console.log);
22
22
  ```
23
23
  ## View a profile
24
24
  ```js
@@ -37,9 +37,9 @@ gd.uploadAccountPost("I love gj-boomlings-api!", "shikoshib", "your password her
37
37
  ```
38
38
  ## Send a message
39
39
  ```js
40
- // This code sends a message from shikoshib to Mipper6
40
+ // This code makes shikoshib send a message to RobTop
41
41
  const gd = require("gj-boomlings-api");
42
- gd.uploadMessage("Mipper6", "message subject", "message content", "shikoshib", "your password here");
42
+ gd.uploadMessage("RobTop", "message subject", "message content", "shikoshib", "your password here");
43
43
  ```
44
44
  # License
45
- [ISC](https://github.com/shikoshib/gj-boomlings-api/blob/main/LICENSE)
45
+ [ISC](https://github.com/shikoshib/gj-boomlings-api/blob/main/LICENSE)
@@ -0,0 +1,39 @@
1
+ module.exports = {
2
+ /**
3
+ * Accepts a friend request.
4
+ * @param {string} from - The player the friend request was sent from.
5
+ * @param {string} username - The target's username or player ID.
6
+ * @param {string} password - The target's password.
7
+ * @returns {number} Returns 1 if everything's OK, or -1 if something went wrong.
8
+ */
9
+ acceptFriendRequest: async function (from, username, password) {
10
+ if (!from) throw new Error("Please specify the player the friend request was sent from!");
11
+ if (!username) throw new Error("Please provide the username or the player ID!");
12
+ if (!password) throw new Error("Please provide the password!");
13
+
14
+ const { gjReq } = require("../misc/gjReq");
15
+ const { gjp2 } = require("../misc/gjp2");
16
+
17
+ let userSearch = await gjReq("getGJUsers20", {
18
+ str: username,
19
+ secret: "Wmfd2893gb7"
20
+ });
21
+ if (userSearch.data == -1) throw new Error(`-1: Player with the ID or player username "${username}" not found`);
22
+ let userAccID = userSearch.data.split(":")[23];
23
+
24
+ let recSearch = await gjReq("getGJUsers20", {
25
+ str: from,
26
+ secret: "Wmfd2893gb7"
27
+ });
28
+ if (recSearch.data == -1) throw new Error(`-1: Player with the ID or player username "${from}" not found`);
29
+ let recAccID = recSearch.data.split(":")[23];
30
+
31
+ let res = await gjReq("acceptGJFriendRequest20", {
32
+ accountID: userAccID,
33
+ targetAccountID: recAccID,
34
+ gjp2: gjp2(password),
35
+ secret: "Wmfd2893gb7",
36
+ });
37
+ return Number(res.data);
38
+ }
39
+ }
@@ -1,39 +1,38 @@
1
1
  module.exports = {
2
2
  /**
3
3
  * Blocks a specified user.
4
- * @param {string} target - The player that needs to be blocked.
4
+ * @param {string} target - The player to be blocked.
5
5
  * @param {string} username - The blocking person's username or player ID.
6
6
  * @param {string} password - The blocking person's password.
7
- * @returns {number} Returns 1 if everything's OK, and -1 if something went wrong.
7
+ * @returns {number} Returns 1 if everything's OK, or -1 if something went wrong.
8
8
  */
9
9
  blockUser: async function (target, username, password) {
10
- if (!target) throw new Error("Please provide a target's player ID or username!");
11
- if (!username) throw new Error("Please provide a player ID or username!");
12
- if (!password) throw new Error("Please provide a password!");
10
+ if (!target) throw new Error("Please provide the target's player ID or username!");
11
+ if (!username) throw new Error("Please provide the player ID or username!");
12
+ if (!password) throw new Error("Please provide the password!");
13
13
 
14
- const { gjReq } = require("../gjReq");
15
- const XOR = require("../xor");
16
- const xor = new XOR;
14
+ const { gjReq } = require("../misc/gjReq");
15
+ const { gjp2 } = require("../misc/gjp2");
17
16
 
18
17
  let userSearch = await gjReq("getGJUsers20", {
19
18
  str: username,
20
19
  secret: "Wmfd2893gb7"
21
20
  });
22
- if (userSearch.data == -1) throw new Error(-1);
23
- let userAccID = userSearch.data.split(":")[21];
21
+ if (userSearch.data == -1) throw new Error(`-1: Player with the ID or player username "${username}" not found`);
22
+ let userAccID = userSearch.data.split(":")[23];
24
23
 
25
24
  let recSearch = await gjReq("getGJUsers20", {
26
25
  str: target,
27
26
  secret: "Wmfd2893gb7"
28
27
  });
29
- if (recSearch.data == -1) throw new Error(-1);
30
- let targetAccID = recSearch.data.split(":")[21];
28
+ if (recSearch.data == -1) throw new Error(`-1: Player with the ID or player username "${target}" not found`);
29
+ let targetAccID = recSearch.data.split(":")[23];
31
30
 
32
31
  const data = {
33
32
  secret: "Wmfd2893gb7",
34
33
  targetAccountID: targetAccID,
35
34
  accountID: userAccID,
36
- gjp: xor.encrypt(password, 37526)
35
+ gjp2: gjp2(password)
37
36
  }
38
37
 
39
38
  let res = await gjReq("blockGJUser20", data);
@@ -4,29 +4,30 @@ module.exports = {
4
4
  * @param {number} id - The post's ID.
5
5
  * @param {string} username - The poster's username or player ID.
6
6
  * @param {string} password - The poster's password.
7
- * @returns {number} Returns 1 if everything's OK, and -1 if something went wrong.
7
+ * @returns {number} Returns 1 if everything's OK, or -1 if something went wrong.
8
8
  */
9
9
  deleteAccountPost: async function (id, username, password) {
10
- if (!id) throw new Error("Please provide an account post ID!");
11
- if (!username) throw new Error("Please provide a player ID or username!");
12
- if (!password) throw new Error("Please provide a password!");
10
+ if (!id) throw new Error("Please provide the account post ID!");
11
+ if (!username) throw new Error("Please provide the player ID or username!");
12
+ if (!password) throw new Error("Please provide the password!");
13
13
 
14
- const { gjReq } = require("../gjReq");
15
- const XOR = require("../xor");
16
- const xor = new XOR;
14
+ const { gjReq } = require("../misc/gjReq");
15
+ const { gjp2 } = require("../misc/gjp2");
17
16
 
18
17
  let search = await gjReq("getGJUsers20", {
19
18
  str: username,
20
19
  secret: "Wmfd2893gb7"
21
20
  });
22
- if (search.data == -1) throw new Error(-1);
23
- let accID = search.data.split(":")[21];
21
+ if (search.data == -1) throw new Error(`-1: Player with the ID or player username "${username}" not found`);
22
+ let accID = search.data.split(":")[23];
24
23
 
25
24
  let res = await gjReq("deleteGJAccComment20", {
26
25
  accountID: accID,
27
26
  secret: "Wmfd2893gb7",
28
- gjp: xor.encrypt(password, 37526),
29
- commentID: id
27
+ gjp2: gjp2(password),
28
+ commentID: id,
29
+ cType: 1,
30
+ targetAccountID: accID
30
31
  });
31
32
 
32
33
  return Number(res.data);
@@ -5,31 +5,30 @@ module.exports = {
5
5
  * @param {number} level - The ID of the level which has the comment.
6
6
  * @param {string} username - The commenter's username.
7
7
  * @param {string} password - The commenter's password.
8
- * @returns {number} Returns 1 if everything's OK, and -1 if something went wrong.
8
+ * @returns {number} Returns 1 if everything's OK, or -1 if something went wrong.
9
9
  */
10
10
  deleteComment:
11
11
  async function (id, level, username, password) {
12
- if (!id) throw new Error("Please provide a comment ID!");
13
- if (!level) throw new Error("Please provide a level ID!");
14
- if (!username) throw new Error("Please provide a user ID or name!");
15
- if (!password) throw new Error("Please provide a password!");
12
+ if (!id) throw new Error("Please provide the comment ID!");
13
+ if (!level) throw new Error("Please provide the level ID!");
14
+ if (!username) throw new Error("Please provide the username or the player ID!");
15
+ if (!password) throw new Error("Please provide the password!");
16
+
17
+ const { gjReq } = require("../misc/gjReq");
18
+ const { gjp2 } = require("../misc/gjp2");
16
19
 
17
- const { gjReq } = require("../gjReq.js");
18
20
  let search = await gjReq("getGJUsers20", {
19
21
  str: username,
20
22
  secret: "Wmfd2893gb7"
21
23
  });
22
- if (search.data == -1) throw new Error(-1);
23
- let accID = search.data.split(":")[21];
24
-
25
- const XOR = require("../xor.js");
26
- const xor = new XOR;
24
+ if (search.data == -1) throw new Error(`-1: Player with the ID or player username "${username}" not found`);
25
+ let accID = search.data.split(":")[23];
27
26
 
28
27
  const res = await gjReq("deleteGJComment20", {
29
28
  accountID: accID,
30
29
  secret: "Wmfd2893gb7",
31
30
  levelID: level,
32
- gjp: xor.encrypt(password, 37526),
31
+ gjp2: gjp2(password),
33
32
  commentID: id
34
33
  });
35
34
 
@@ -0,0 +1,43 @@
1
+ module.exports = {
2
+ /**
3
+ * Deletes a friend request.
4
+ * @param {string} target - The player the friend request was sent to.
5
+ * @param {string} username - The sender's username or player ID.
6
+ * @param {string} password - The sender's password.
7
+ * @param {boolean} isSender - Whether the person specified in `username` was the one sending the friend request. Defaults to false (the person is the one receiving friend requests).
8
+ * @returns {number} Returns 1 if everything's OK, or -1 if something went wrong.
9
+ */
10
+ deleteFriendRequest: async function (target, username, password, isSender = false) {
11
+ if (!target) throw new Error("Please specify the target!");
12
+ if (!username) throw new Error("Please provide the username or the player ID!");
13
+ if (!password) throw new Error("Please provide the password!");
14
+ if (isSender && isNaN(isSender)) throw new Error("Please provide either false or true for isSender!");
15
+
16
+ const { gjReq } = require("../misc/gjReq");
17
+ const { gjp2 } = require("../misc/gjp2");
18
+
19
+ let userSearch = await gjReq("getGJUsers20", {
20
+ str: username,
21
+ secret: "Wmfd2893gb7"
22
+ });
23
+ if (userSearch.data == -1) throw new Error(`-1: Player with the ID or player username "${username}" not found`);
24
+ let userAccID = userSearch.data.split(":")[23];
25
+
26
+ let recSearch = await gjReq("getGJUsers20", {
27
+ str: target,
28
+ secret: "Wmfd2893gb7"
29
+ });
30
+ if (recSearch.data == -1) throw new Error(`-1: Player with the ID or player username "${target}" not found`);
31
+ let recAccID = recSearch.data.split(":")[23];
32
+
33
+ let res = await gjReq("deleteGJFriendRequests20", {
34
+ accountID: userAccID,
35
+ targetAccountID: recAccID,
36
+ gjp2: gjp2(password),
37
+ secret: "Wmfd2893gb7",
38
+ isSender: Number(isSender)
39
+ });
40
+
41
+ return Number(res.data);
42
+ }
43
+ }
@@ -4,32 +4,29 @@ module.exports = {
4
4
  * @param {number} level - The ID of the level that needs to be deleted.
5
5
  * @param {string} username - The uploader's username or player ID.
6
6
  * @param {string} password - The uploader's password.
7
- * @returns {number} Returns 1 if everything's OK, and -1 if something went wrong.
7
+ * @returns {number} Returns 1 if everything's OK, or -1 if something went wrong.
8
8
  */
9
9
  deleteLevel: async function (level, username, password) {
10
10
  if (isNaN(level)) throw new Error("Please provide a valid level ID!");
11
- if (!username) throw new Error("Please provide a user ID or name!");
12
- if (!password) throw new Error("Please provide a password!");
11
+ if (!username) throw new Error("Please provide the username or the player ID!");
12
+ if (!password) throw new Error("Please provide the password!");
13
13
 
14
- const { gjReq } = require("../gjReq");
15
- const XOR = require("../xor");
16
- const xor = new XOR;
14
+ const { gjReq } = require("../misc/gjReq");
15
+ const { gjp2 } = require("../misc/gjp2");
17
16
 
18
17
  let search = await gjReq("getGJUsers20", {
19
18
  str: username,
20
19
  secret: "Wmfd2893gb7"
21
20
  });
22
- if (search.data == -1) throw new Error(-1);
23
- let accID = search.data.split(":")[21];
21
+ if (search.data == -1) throw new Error(`-1: Player with the ID or player username "${username}" not found`);
22
+ let accID = search.data.split(":")[23];
24
23
 
25
- let data = {
24
+ let res = await gjReq("deleteGJLevelUser20", {
26
25
  accountID: accID,
27
26
  secret: "Wmfv2898gc9",
28
27
  levelID: level,
29
- gjp: xor.encrypt(password, 37526),
30
- };
31
-
32
- let res = await gjReq("deleteGJLevelUser20", data);
28
+ gjp2: gjp2(password),
29
+ });
33
30
 
34
31
  return Number(res.data);
35
32
  }
@@ -0,0 +1,37 @@
1
+ module.exports = {
2
+ /**
3
+ * Deletes a message.
4
+ * @param {number} id - The message ID.
5
+ * @param {string} username - The deleting person's username or player ID.
6
+ * @param {string} password - The deleting person's password.
7
+ * @param {boolean} isSender - Whether the person specified in `username` was the one sending the message. Defaults to false (the person is the one receiving the message).
8
+ * @returns {Number} Returns 1 regardless of whether the message was deleted or not, or -1 if the credentials are incorrect.
9
+ */
10
+ deleteMessage: async function (id, username, password, isSender = false) {
11
+ if (!id) throw new Error("Please provide a valid message ID!");
12
+ if (!username) throw new Error("Please provide the player ID or username!");
13
+ if (!password) throw new Error("Please provide the password!");
14
+ if (isSender && isNaN(isSender)) throw new Error("Please provide either false or true for isSender!");
15
+
16
+ const { gjReq } = require("../misc/gjReq");
17
+ const { gjp2 } = require("../misc/gjp2");
18
+
19
+ let search = await gjReq("getGJUsers20", {
20
+ str: username,
21
+ secret: "Wmfd2893gb7"
22
+ });
23
+ if (search.data == -1) throw new Error(`-1: Player with the ID or player username "${username}" not found`);
24
+ let accID = search.data.split(":")[23];
25
+
26
+ let data = {
27
+ accountID: accID,
28
+ gjp2: gjp2(password),
29
+ secret: "Wmfd2893gb7",
30
+ messageID: id
31
+ };
32
+ if (isSender) data.isSender = 1;
33
+
34
+ let res = await gjReq("deleteGJMessages20", data);
35
+ return Number(res.data);
36
+ }
37
+ }
@@ -29,7 +29,9 @@
29
29
  * @property {string|boolean} rating - Primarily used for new 2.2 ratings. Returns either "epic", "legendary", "mythic", or `false` if the level's rating is lower than epic.
30
30
  * @property {number} objects - The amount of objects the level has, based on the level data.
31
31
  * @property {string} uploaded - How long ago the level was uploaded.
32
+ * @property {number} uploadedTimestamp - The Unix timestamp of the level's upload date (GMT timezone).
32
33
  * @property {string} updated - How long ago the level was last updated.
34
+ * @property {number} updatedTimestamp - The Unix timestamp of the level's last update date (GMT timezone).
33
35
  * @property {number} starsRequested - The amount of stars the uploader requested for this level.
34
36
  * @property {string} gameVersion - The version of the game used to upload the current version of the level. Returns "Pre-1.7" if the level was last updated in 1.6 or earlier.
35
37
  * @property {boolean} ldm - Whether the level has a "Low Detail Mode" option.
@@ -39,8 +41,8 @@
39
41
  * @property {number} coins - The amount of coins the level has.
40
42
  * @property {boolean} verifiedCoins - Whether the coins are verified.
41
43
  * @property {Song} song - The main song used in the level.
42
- * @property {Array} additionalSongs - The array containing additional songs' IDs.
43
- * @property {Array} sfx - The array containing sound effects' IDs.
44
+ * @property {Array<number>} additionalSongs - The array containing additional songs' IDs.
45
+ * @property {Array<number>} sfx - The array containing sound effects' IDs.
44
46
  */
45
47
 
46
48
  module.exports = {
@@ -49,12 +51,12 @@ module.exports = {
49
51
  * @param {number} level - The level ID.
50
52
  * @returns {Level}
51
53
  */
52
- dlLevel: async function (level) {
54
+ downloadLevel: async function (level) {
53
55
  const zlib = require("zlib");
54
56
  if (!level) throw new Error("Please provide a level ID.");
55
57
  if (isNaN(level)) throw new Error("The level parameter should be a number.");
56
58
 
57
- const { gjReq } = require("../gjReq");
59
+ const { gjReq } = require("../misc/gjReq");
58
60
 
59
61
  const data = {
60
62
  levelID: level.toString().trim(),
@@ -63,39 +65,41 @@ module.exports = {
63
65
 
64
66
  let res = await gjReq("downloadGJLevel22", data);
65
67
  if (res.data == -1) return {};
66
- const XOR = require("../xor");
68
+ const XOR = require("../misc/xor");
67
69
  let xor = new XOR;
68
70
 
69
71
  let s = res.data.split("#")[0].split(":");
70
72
 
71
- let id = Number(s[1]);
72
- let name = s[3];
73
- let description = Buffer.from(s[5], "base64url").toString();
74
- let levelString = s[7];
75
- let version = Number(s[9]);
76
- let playerID = Number(s[11]);
77
- let difficulty = s[15];
78
- let downloads = Number(s[17]);
79
- let officialSongID = Number(s[19]);
80
- let gameVersion = Number(s[21]);
81
- let likes = Number(s[23]);
82
- let isDemon = s[25];
83
- let stars = Number(s[31]);
84
- let isFeatured = s[33];
85
- let isEpic = s[35];
86
- let objStats = Number(s[37]);
87
- let length = Number(s[39]);
88
- let copiedID = Number(s[41]);
89
- let is2P = s[43];
90
- let uploaded = s[45];
91
- let updated = s[47];
92
- let NGSongID = Number(s[49]);
93
- let coins = Number(s[53]);
94
- let coinsVerified = s[55];
95
- let starReq = Number(s[57]);
96
- let isLDM = s[63];
97
- let password = xor.decrypt(s[67].split("#")[0], 26364);
98
- if (password.length == 7) password = password.replace("1", "");
73
+ let id = Number(s[1]); // 1:
74
+ let name = s[3]; // 2:
75
+ let description = Buffer.from(s[5], "base64url").toString(); // 3: in base64
76
+ let levelString = s[7]; // 4:
77
+ let version = Number(s[9]); // 5:
78
+ let playerID = Number(s[11]); // 6:
79
+ let difficulty = s[15]; // 9:
80
+ let downloads = Number(s[17]); // 10:
81
+ let officialSongID = Number(s[19]); // 12:
82
+ let gameVersion = Number(s[21]); // 13:
83
+ let likes = Number(s[23]); // 14:
84
+ let isDemon = s[25]; // 17:
85
+ let stars = Number(s[31]); // 18:
86
+ let isFeatured = s[33]; // 19:
87
+ let isEpic = s[35]; // 42:
88
+ let objStats = Number(s[37]); // 45:
89
+ let length = Number(s[39]); // 15:
90
+ let copiedID = Number(s[41]); // 30:
91
+ let is2P = s[43]; // 31:
92
+ let uploaded = s[45]; // 28:
93
+ let updated = s[47]; // 29:
94
+ let uploadedUnix = Number(s[49]); // 62:
95
+ let updatedUnix = Number(s[51]); // 63:
96
+ let NGSongID = Number(s[53]); // 35:
97
+ let coins = Number(s[57]); // 37:
98
+ let coinsVerified = s[59]; // 38:
99
+ let starReq = Number(s[61]); // 39:
100
+ let isLDM = s[67]; // 40:
101
+ let password = xor.decrypt(s[71].split("#")[0], 26364);
102
+ if (password.length == 5 || password.length == 7) password = password.replace("1", "");
99
103
 
100
104
  let diffObj = {
101
105
  "-10": "Auto",
@@ -186,12 +190,14 @@ module.exports = {
186
190
  rating: epicObj[Number(isEpic)],
187
191
  objects: objs.length - 1,
188
192
  uploaded: uploaded,
193
+ uploadedTimestamp: uploadedUnix,
189
194
  updated: updated,
195
+ updatedTimestamp: updatedUnix,
190
196
  starsRequested: starReq,
191
197
  gameVersion: versionObj[gameVersion] ? versionObj[gameVersion] : "Pre-1.7",
192
198
  ldm: Boolean(Number(isLDM)),
193
199
  copiedFrom: copiedID,
194
- large: objStats > 4e4 ? true : false,
200
+ large: objStats > 40000 ? true : false,
195
201
  twoPlayer: Boolean(Number(is2P)),
196
202
  coins: coins,
197
203
  verifiedCoins: Boolean(Number(coinsVerified)),
@@ -200,15 +206,17 @@ module.exports = {
200
206
  sfx: []
201
207
  }
202
208
 
203
- if (s[69] && s[68] != "41") {
209
+ if (s[73] && s[72] != "41") {
204
210
  let songsIDArray = [];
205
211
  let sfxIDArray = [];
206
- for (let songID of s[69].split(",")) {
212
+ for (let songID of s[73].split(",")) { // 52:
207
213
  if (songID == NGSongID) continue;
208
214
  songsIDArray.push(Number(songID));
209
215
  }
210
- for (let sfx of s[71].split("#")[0].split(",")) {
211
- sfxIDArray.push(Number(sfx));
216
+ if (s[74] == "53") {
217
+ for (let sfx of s[75].split("#")[0].split(",")) { // 53:
218
+ sfxIDArray.push(Number(sfx));
219
+ }
212
220
  }
213
221
  result.additionalSongs = songsIDArray;
214
222
  result.sfx = sfxIDArray;
@@ -17,25 +17,26 @@ module.exports = {
17
17
  * @param {string} password - The message recipient's password.
18
18
  * @returns {Message}
19
19
  */
20
- dlMessage: async function (id, username, password) {
20
+ downloadMessage: async function (id, username, password) {
21
21
  if (!id) throw new Error("Please provide a valid message ID!");
22
- if (!username) throw new Error("Please provide a player ID or username!");
23
- if (!password) throw new Error("Please provide a password!");
22
+ if (!username) throw new Error("Please provide the player ID or username!");
23
+ if (!password) throw new Error("Please provide the password!");
24
24
 
25
- const { gjReq } = require("../gjReq");
26
- const XOR = require("../xor");
25
+ const { gjReq } = require("../misc/gjReq");
26
+ const { gjp2 } = require("../misc/gjp2");
27
+ const XOR = require("../misc/xor");
27
28
  const xor = new XOR;
28
29
 
29
30
  let search = await gjReq("getGJUsers20", {
30
31
  str: username,
31
32
  secret: "Wmfd2893gb7"
32
33
  });
33
- if (search.data == -1) return {};
34
- let accID = search.data.split(":")[21];
34
+ if (search.data == -1) throw new Error(`-1: Player with the ID or player username "${username}" not found`);
35
+ let accID = search.data.split(":")[23];
35
36
 
36
37
  let res = await gjReq("downloadGJMessage20", {
37
38
  accountID: accID,
38
- gjp: xor.encrypt(password, 37526),
39
+ gjp2: gjp2(password),
39
40
  secret: "Wmfd2893gb7",
40
41
  messageID: id
41
42
  });
@@ -15,21 +15,20 @@ module.exports = {
15
15
  */
16
16
  getAccountPosts: async function (target, page = 1) {
17
17
  if (!target) throw new Error("Please provide a player ID or username!");
18
- const { gjReq } = require("../gjReq");
18
+ const { gjReq } = require("../misc/gjReq");
19
19
 
20
20
  let search = await gjReq("getGJUsers20", {
21
21
  str: target,
22
22
  secret: "Wmfd2893gb7"
23
23
  });
24
- if (search.data == -1) return [];
25
- let targetAccID = search.data.split(":")[21];
24
+ if (search.data == -1) throw new Error(`-1: Player with the ID or player username "${target}" not found`);
25
+ let targetAccID = search.data.split(":")[23];
26
26
 
27
27
  let res = await gjReq("getGJAccountComments20", {
28
28
  accountID: targetAccID,
29
29
  secret: "Wmfd2893gb7",
30
30
  page: page - 1
31
31
  })
32
- if (res.data == -1) throw new Error("-1 Not found.");
33
32
  if (res.data.startsWith("#")) return [];
34
33
 
35
34
  let accPosts = res.data.split("#")[0].split("|");
@@ -3,8 +3,10 @@
3
3
  * @property {string} username - The blocked person's username.
4
4
  * @property {number} playerID - The blocked person's player ID.
5
5
  * @property {number} accountID - The blocked person's account ID.
6
+ * @property {string} iconID - The blocked person's icon ID.
6
7
  * @property {string} color1 - The HEX code of the blocked person's primary color.
7
8
  * @property {string} color2 - The HEX code of the blocked person's secondary color.
9
+ * @property {("cube"|"ship"|"ball"|"ufo"|"wave"|"robot"|"spider"|"swing"|"jetpack")} iconType - The blocked person's selected game mode to be displayed as an icon.
8
10
  */
9
11
 
10
12
  module.exports = {
@@ -15,23 +17,22 @@ module.exports = {
15
17
  * @returns {BlockedUser[]}
16
18
  */
17
19
  getBlockedList: async function (username, password) {
18
- if (!username) throw new Error("Please provide a player ID or username!");
19
- if (!password) throw new Error("Please provide a password!");
20
+ if (!username) throw new Error("Please provide the player ID or username!");
21
+ if (!password) throw new Error("Please provide the password!");
20
22
 
21
- const { gjReq } = require("../gjReq");
22
- const XOR = require("../xor");
23
- const xor = new XOR;
23
+ const { gjReq } = require("../misc/gjReq");
24
+ const { gjp2 } = require("../misc/gjp2");
24
25
 
25
26
  let search = await gjReq("getGJUsers20", {
26
27
  str: username,
27
28
  secret: "Wmfd2893gb7"
28
29
  });
29
- if (search.data == -1) return [];
30
- let accID = search.data.split(":")[21];
30
+ if (search.data == -1) throw new Error(`-1: Player with the ID or player username "${username}" not found`);
31
+ let accID = search.data.split(":")[23];
31
32
 
32
33
  const data = {
33
34
  accountID: accID,
34
- gjp: xor.encrypt(password, 37526),
35
+ gjp2: gjp2(password),
35
36
  secret: "Wmfd2893gb7",
36
37
  type: 1
37
38
  }
@@ -44,20 +45,38 @@ module.exports = {
44
45
  let colors = require("../misc/colors.json");
45
46
  const { rgbToHEX } = require("../misc/rgbToHEX");
46
47
 
47
- players.forEach(p => {
48
- let s=p.split(":");
48
+ let iconObj = {
49
+ 0: "cube",
50
+ 1: "ship",
51
+ 2: "ball",
52
+ 3: "ufo",
53
+ 4: "wave",
54
+ 5: "robot",
55
+ 6: "spider",
56
+ 7: "swing",
57
+ 8: "jetpack"
58
+ };
59
+
60
+ res.data.split("|").forEach(p => {
61
+ let s = p.split(":");
49
62
  let username = s[1];
50
63
  let playerID = s[3];
64
+ let iconID = s[5];
51
65
  let p1 = s[7];
52
66
  let p2 = s[9];
53
- let accID = s[15];
67
+ let glowColor = s[11];
68
+ let iconType = s[13];
69
+ let accID = s[17];
54
70
 
55
71
  result.push({
56
72
  username: username,
57
73
  playerID: Number(playerID),
58
74
  accountID: Number(accID),
75
+ iconID: Number(iconID),
59
76
  color1: rgbToHEX(colors[p1]),
60
- color2: rgbToHEX(colors[p2])
77
+ color2: rgbToHEX(colors[p2]),
78
+ glowColor: glowColor != "0" ? rgbToHEX(colors[glowColor]) : null,
79
+ iconType: iconObj[Number(iconType)]
61
80
  })
62
81
  })
63
82