gj-boomlings-api 2.0.3 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +5 -5
  3. package/functions/acceptFriendRequest.js +32 -0
  4. package/functions/blockUser.js +14 -22
  5. package/functions/deleteAccountPost.js +13 -16
  6. package/functions/deleteComment.js +11 -16
  7. package/functions/deleteFriendRequest.js +36 -0
  8. package/functions/deleteLevel.js +11 -17
  9. package/functions/deleteMessage.js +33 -0
  10. package/functions/{dlLevel.js → downloadLevel.js} +47 -43
  11. package/functions/{dlMessage.js → downloadMessage.js} +10 -13
  12. package/functions/getAccountPosts.js +4 -9
  13. package/functions/getBlockedList.js +32 -17
  14. package/functions/getCommentHistory.js +8 -7
  15. package/functions/getComments.js +12 -9
  16. package/functions/getCreatorScores.js +13 -5
  17. package/functions/getDailyLevel.js +3 -3
  18. package/functions/getFriendRequests.js +83 -0
  19. package/functions/getFriendsList.js +26 -16
  20. package/functions/getGauntlets.js +5 -3
  21. package/functions/getLevelByID.js +2 -3
  22. package/functions/getLevelScores.js +23 -26
  23. package/functions/getMapPacks.js +2 -6
  24. package/functions/getMessages.js +11 -15
  25. package/functions/getProfile.js +146 -57
  26. package/functions/getSongInfo.js +4 -9
  27. package/functions/getSongsLibrary.js +14 -3
  28. package/functions/getTab.js +3 -4
  29. package/functions/getTop100.js +3 -6
  30. package/functions/getTopLists.js +1 -2
  31. package/functions/getUserLevels.js +4 -8
  32. package/functions/getWeeklyDemon.js +3 -3
  33. package/functions/removeFriend.js +33 -0
  34. package/functions/reportLevel.js +3 -6
  35. package/functions/searchLevels.js +2 -3
  36. package/functions/searchLists.js +2 -3
  37. package/functions/unblockUser.js +17 -27
  38. package/functions/updateAccountSettings.js +75 -0
  39. package/functions/updateLevelDesc.js +11 -16
  40. package/functions/uploadAccountPost.js +11 -16
  41. package/functions/uploadComment.js +15 -19
  42. package/functions/uploadFriendRequest.js +35 -0
  43. package/functions/uploadMessage.js +18 -25
  44. package/index.js +30 -3
  45. package/misc/GJDecode.js +12 -9
  46. package/misc/gauntlets.json +14 -1
  47. package/misc/gjReq.js +33 -0
  48. package/misc/gjp2.js +5 -0
  49. package/package.json +2 -5
  50. package/gjReq.js +0 -18
  51. /package/{xor.js → misc/xor.js} +0 -0
@@ -1,3 +1,45 @@
1
+ /**
2
+ * @typedef {Object} completedClassicLevels
3
+ * @property {number} auto - The amount of classic levels rated auto (1*) the player has completed.
4
+ * @property {number} easy - The amount of classic levels rated easy (2*) the player has completed.
5
+ * @property {number} normal - The amount of classic levels rated normal (3*) the player has completed.
6
+ * @property {number} hard - The amount of classic levels rated hard (4-5*) the player has completed.
7
+ * @property {number} harder - The amount of classic levels rated harder (6-7*) the player has completed.
8
+ * @property {number} insane - The amount of classic levels rated insane (8-9*) the player has completed.
9
+ * @property {number} daily - The amount of daily levels the player has completed.
10
+ * @property {number} gauntlet - The amount of levels the player has completed in gauntlets.
11
+ */
12
+
13
+ /**
14
+ * @typedef {Object} completedPlatformers
15
+ * @property {number} auto - The amount of platformers rated auto (1 moon) the player has completed.
16
+ * @property {number} easy - The amount of platformers rated easy (2 moons) the player has completed.
17
+ * @property {number} normal - The amount of platformers rated normal (3 moons) the player has completed.
18
+ * @property {number} hard - The amount of platformers rated hard (4-5 moons) the player has completed.
19
+ * @property {number} harder - The amount of platformers rated harder (6-7 moons) the player has completed.
20
+ * @property {number} insane - The amount of platformers rated insane (8-9 moons) the player has completed.
21
+ */
22
+
23
+ /**
24
+ * @typedef {Object} completedClassicDemons
25
+ * @property {number} easy - The amount of classic easy demons the player has completed.
26
+ * @property {number} medium - The amount of classic medium demons the player has completed.
27
+ * @property {number} hard - The amount of classic hard demons the player has completed.
28
+ * @property {number} insane - The amount of classic insane demons the player has completed.
29
+ * @property {number} extreme - The amount of classic extreme demons the player has completed.
30
+ * @property {number} weekly - The amount of weekly demons the player has completed.
31
+ * @property {number} gauntlet - The amount of demons the player has completed in gauntlets.
32
+ */
33
+
34
+ /**
35
+ * @typedef {Object} completedPlatformerDemons
36
+ * @property {number} easy - The amount of platformer easy demons the player has completed.
37
+ * @property {number} medium - The amount of platformer medium demons the player has completed.
38
+ * @property {number} hard - The amount of platformer hard demons the player has completed.
39
+ * @property {number} insane - The amount of platformer insane demons the player has completed.
40
+ * @property {number} extreme - The amount of platformer extreme demons the player has completed.
41
+ */
42
+
1
43
  /**
2
44
  * @typedef {Object} Player
3
45
  * @property {string} username - The player's username.
@@ -24,61 +66,78 @@
24
66
  * @property {number} jetpackID - The ID of the currently selected jetpack icon.
25
67
  * @property {number} explosionID - The ID of the currently selected explosion animation.
26
68
  * @property {boolean} glow - Whether the player's icon has the "glow" feature enabled.
27
- * @property {string} messages - The current state of messaging the player. Returns "all" if anyone can message the person, "friends" if it's limited to friends, and "none" if no one can.
69
+ * @property {string} glowColor - The HEX code of the player's glow color.
70
+ * @property {("all"|"friends"|"none")} messages - The current state of messaging the player. Returns "all" if anyone can message the person, "friends" if it's limited to friends, or "none" if no one can.
28
71
  * @property {boolean} friendRequests - Whether the player has allowed to receive friend requests.
29
- * @property {string} commentHistory - The current state of viewing the player's comment history. Returns "all" if anyone can do it, "friends" if it's limited to friends, and "none" if only the player can.
30
- * @property {string|null} mod - Whether the player is a moderator. Returns `null` if not, "mod" if the user is a regular moderator and "elder" if the user is an elder moderator.
31
- * @property {string} youtube - The player's YouTube channel ID, used in this template: `https://youtube.com/channel/((youtube))`.
72
+ * @property {("all"|"friends"|"none")} commentHistory - The current state of viewing the player's comment history. Returns "all" if anyone can do it, "friends" if it's limited to friends, or "none" if only the player can.
73
+ * @property {string|null} mod - Whether the player is a moderator. Returns `null` if not, "mod" if the user is a regular moderator or "elder" if the user is an elder moderator.
74
+ * @property {string} youtube - The player's YouTube channel ID/handle, used in this template: `https://youtube.com/@((youtube))` or `https://youtube.com/channel/((youtube))` (only if the provided value starts with UC).
32
75
  * @property {string} twitter - The player's X (formerly Twitter) username, used in this template: `https://x.com/((twitter))`.
33
76
  * @property {string} twitch - The player's Twitch username, used in this template: `https://twitch.tv/((twitch))`.
77
+ * @property {string} instagram - The player's Instagram username, used in this template: `https://instagram.com/@((instagram))`.
78
+ * @property {string} tiktok - The player's TikTok username, used in this template: `https://tiktok.com/@((tiktok))`.
79
+ * @property {string} discord - The player's Discord username.
80
+ * @property {string} custom - The custom string provided by the player.
81
+ * @property {completedClassicLevels} completedClassicLevels - An object breaking down what classic levels the player has completed by difficulties, as well as daily levels and gauntlet levels.
82
+ * @property {completedPlatformers} completedPlatformers - An object breaking down what platformer levels (non-demons) the player has completed by difficulties.
83
+ * @property {completedClassicDemons} completedClassicDemons - An object breaking down what classic demons the player has completed by difficulties, as well as weekly demons and gauntlet demons.
84
+ * @property {completedPlatformerDemons} completedPlatformerDemons - An object breaking down what platformer demons the player has completed by difficulties.
34
85
  */
35
86
 
36
87
  module.exports = {
37
88
  /**
38
89
  * Fetches the profile of a specified user.
39
- * @param {string} name - The search query (user, account ID or player ID).
40
- * @param {("name"|"accountid"|"playerid")} mode - The search mode, defaults to "auto". If "auto" is selected, the search is first attempted by matching the matching the username, then account ID and then player ID.
90
+ * @param {string} name - The search query (username, account ID or player ID).
91
+ * @param {("name"|"accountid"|"playerid"|"auto")} mode - The search mode, defaults to "auto". If "auto" is selected, the search is first attempted by looking up the username, then account ID and then player ID.
41
92
  * @returns {Player}
42
93
  */
43
94
  getProfile: async function (name, mode = "auto") {
44
- const { gjReq } = require("../gjReq");
95
+ const { gjReq } = require("../misc/gjReq");
45
96
  const { rgbToHEX } = require("../misc/rgbToHEX");
46
97
  const colors = require("../misc/colors.json");
47
- if (!name) throw new Error("Please provide an account name, player ID or account ID!")
48
- if (!["name", "accountid", "playerid", "auto"].includes(mode)) throw new Error("Please provide a valid search mode! It's either \"name\", \"accountid\", \"playerid\", or \"auto\"")
98
+ if (!name) throw new Error("Please provide the account name, player ID or account ID!")
99
+ if (!["name", "accountid", "playerid", "auto"].includes(mode)) throw new Error("Please provide a valid search mode! It's either \"name\", \"accountid\", \"playerid\", or \"auto\".")
49
100
 
50
101
  function decodeUser(array) {
51
- let accName = array[1];
52
- let playerID = Number(array[3]);
53
- let secretCoins = Number(array[5]);
54
- let userCoins = Number(array[7]);
55
- let c1 = array[9];
56
- let c2 = array[11];
57
- let stars = Number(array[15]);
58
- let moons = Number(array[17]);
59
- let diamonds = Number(array[19]);
60
- let demons = Number(array[21]);
61
- let cp = Number(array[23]);
62
- let msg = array[25];
63
- let friendReqs = array[27];
64
- let commentHistory = array[29];
65
- let yt = array[31];
66
- let cube = Number(array[33]);
67
- let ship = Number(array[35]);
68
- let ball = Number(array[37]);
69
- let ufo = Number(array[39]);
70
- let wave = Number(array[41]);
71
- let robot = Number(array[43]);
72
- let spider = Number(array[47]);
73
- let swing = Number(array[51]);
74
- let jetpack = Number(array[53]);
75
- let glow = Boolean(Number(array[45]));
76
- let explosion = Number(array[49]);
77
- let rank = Number(array[55]);
78
- let accID = Number(array[57]);
79
- let twitter = array[61];
80
- let twitch = array[63];
81
- let mod = array[65];
102
+ let accName = array[1]; // 1:
103
+ let playerID = Number(array[3]); // 2:
104
+ let secretCoins = Number(array[5]); // 13:
105
+ let userCoins = Number(array[7]); // 17:
106
+ let c1 = array[9]; // 10:
107
+ let c2 = array[11]; // 11:
108
+ let stars = Number(array[15]); // 3:
109
+ let moons = Number(array[17]); // 52:
110
+ let diamonds = Number(array[19]); // 46:
111
+ let demons = Number(array[21]); // 4:
112
+ let cp = Number(array[23]); // 8:
113
+ let msg = array[25]; // 18:
114
+ let friendReqs = array[27]; // 19:
115
+ let commentHistory = array[29]; // 50:
116
+ let yt = array[31]; // 20:
117
+ let cube = Number(array[33]); // 21:
118
+ let ship = Number(array[35]); // 22:
119
+ let ball = Number(array[37]); // 23:
120
+ let ufo = Number(array[39]); // 24:
121
+ let wave = Number(array[41]); // 25:
122
+ let robot = Number(array[43]); // 26:
123
+ let spider = Number(array[47]); // 43:
124
+ let swing = Number(array[51]); // 53:
125
+ let jetpack = Number(array[53]); // 54:
126
+ let glowColor = Number(array[13]); // 51:
127
+ let glow = Boolean(Number(array[45])); // 28:
128
+ let explosion = Number(array[49]); // 48:
129
+ let rank = Number(array[81]); // 30:
130
+ let accID = Number(array[55]); // 16:
131
+ let twitter = array[59]; // 44:
132
+ let twitch = array[61]; // 45:
133
+ let instagram = array[63]; // 59:
134
+ let tiktok = array[65]; // 60:
135
+ let discord = array[67]; // 58:
136
+ let custom = array[69]; // 61:
137
+ let mod = array[71]; // 49:
138
+ let completedDemons = array[73].split(","); // 55:
139
+ let completedClassicLevels = array[75].split(","); // 56:
140
+ let completedPlatformers = array[77].split(","); // 57:
82
141
 
83
142
  let msgObj = {
84
143
  0: "all",
@@ -122,39 +181,69 @@ module.exports = {
122
181
  jetpackID: jetpack,
123
182
  explosionID: explosion,
124
183
  glow: glow,
184
+ glowColor: rgbToHEX(colors[glowColor]),
125
185
  messages: msgObj[msg],
126
186
  friendRequests: friendReqsObj[friendReqs],
127
187
  commentHistory: msgObj[commentHistory],
128
188
  mod: modObj[mod],
129
189
  youtube: yt,
130
190
  twitter: twitter,
131
- twitch: twitch
191
+ twitch: twitch,
192
+ instagram: instagram,
193
+ tiktok: tiktok,
194
+ discord: discord,
195
+ custom: custom,
196
+ completedClassicLevels: {
197
+ auto: Number(completedClassicLevels[0]),
198
+ easy: Number(completedClassicLevels[1]),
199
+ normal: Number(completedClassicLevels[2]),
200
+ hard: Number(completedClassicLevels[3]),
201
+ harder: Number(completedClassicLevels[4]),
202
+ insane: Number(completedClassicLevels[5]),
203
+ daily: Number(completedClassicLevels[6]),
204
+ gauntlet: Number(completedClassicLevels[7])
205
+ },
206
+ completedPlatformers: {
207
+ auto: Number(completedPlatformers[0]),
208
+ easy: Number(completedPlatformers[1]),
209
+ normal: Number(completedPlatformers[2]),
210
+ hard: Number(completedPlatformers[3]),
211
+ harder: Number(completedPlatformers[4]),
212
+ insane: Number(completedPlatformers[5])
213
+ },
214
+ completedClassicDemons: {
215
+ easy: Number(completedDemons[0]),
216
+ medium: Number(completedDemons[1]),
217
+ hard: Number(completedDemons[2]),
218
+ insane: Number(completedDemons[3]),
219
+ extreme: Number(completedDemons[4]),
220
+ weekly: Number(completedDemons[10]),
221
+ gauntlet: Number(completedDemons[11])
222
+ },
223
+ completedPlatformerDemons: {
224
+ easy: Number(completedDemons[5]),
225
+ medium: Number(completedDemons[6]),
226
+ hard: Number(completedDemons[7]),
227
+ insane: Number(completedDemons[8]),
228
+ extreme: Number(completedDemons[9])
229
+ }
132
230
  }
133
231
  }
134
232
 
135
233
  async function accIDSearch() {
136
- let res = await gjReq("getGJUserInfo20", {
137
- targetAccountID: name,
138
- secret: "Wmfd2893gb7"
139
- });
140
- if (res.data == -1) return {};
234
+ let res = await gjReq("getGJUserInfo20", { targetAccountID: name });
235
+ if (res.data == -1) throw new Error(`-1: Player not found`);
141
236
  let accArray = res.data.split(":");
142
237
 
143
238
  return decodeUser(accArray);
144
239
  }
145
240
 
146
241
  async function nonAccIDSearch() {
147
- let search = await gjReq("getGJUsers20", {
148
- str: name,
149
- secret: "Wmfd2893gb7"
150
- });
151
- if (search.data == -1) return {};
152
- let targetAccID = search.data.split(":")[21];
153
-
154
- let res = await gjReq("getGJUserInfo20", {
155
- targetAccountID: targetAccID,
156
- secret: "Wmfd2893gb7"
157
- });
242
+ let search = await gjReq("getGJUsers20", { str: name });
243
+ if (search.data == -1) throw new Error(`-1: Player not found`);
244
+ let targetAccID = search.data.split(":")[23];
245
+
246
+ let res = await gjReq("getGJUserInfo20", { targetAccountID: targetAccID });
158
247
  let accArray = res.data.split(":");
159
248
 
160
249
  return decodeUser(accArray);
@@ -12,19 +12,14 @@ module.exports = {
12
12
  /**
13
13
  * Searches for a song on Newgrounds or in the internal Geometry Dash song library.
14
14
  * @param {number} song - The song ID.
15
- * @returns {Song}
15
+ * @returns {Song} Returns the song object, or an empty object containing only the song ID if the song hasn't been found.
16
16
  */
17
17
  getSongInfo: async function (song) {
18
18
  if (isNaN(song)) throw new Error("Please provide a valid song ID.");
19
- const { gjReq } = require("../gjReq");
19
+ const { gjReq } = require("../misc/gjReq");
20
20
 
21
- const data = {
22
- songID: song,
23
- secret: "Wmfd2893gb7"
24
- }
25
-
26
- let res = await gjReq('getGJSongInfo', data);
27
- if (res.data == -2) throw new Error(`-2. Couldn't find a song with ID ${song}.`)
21
+ let res = await gjReq('getGJSongInfo', { songID: song });
22
+ if (res.data == -2 || res.data == -1) return { id: Number(song) };
28
23
  let rawSong = res.data.split("~|~");
29
24
 
30
25
  let link = decodeURIComponent(rawSong[13]);
@@ -29,10 +29,21 @@ module.exports = {
29
29
  */
30
30
  getSongsLibrary: async function () {
31
31
  const zlib = require("zlib");
32
- const fetch = require("node-fetch");
32
+ const https = require("https");
33
33
 
34
- let req = await fetch("https://geometrydashfiles.b-cdn.net/music/musiclibrary.dat");
35
- let res = await req.text();
34
+ const res = await new Promise((resolve, reject) => {
35
+ https.get("https://geometrydashfiles.b-cdn.net/music/musiclibrary.dat", (res) => {
36
+ let data = "";
37
+
38
+ res.on("data", chunk => {
39
+ data += chunk;
40
+ });
41
+
42
+ res.on("end", () => {
43
+ resolve(data);
44
+ });
45
+ }).on("error", reject);
46
+ });
36
47
 
37
48
  let libArray;
38
49
  const buffer = await new Promise((resolve, reject) => {
@@ -9,16 +9,15 @@ module.exports = {
9
9
  let tabs = { trending: 3, recent: 4, featured: 6, magic: 7, awarded: 11, sent: 27 }
10
10
  if (!tabs[tab.toLowerCase()]) throw new Error('Please provide a valid tab! Possible tabs: "trending", "recent", "featured", "magic", "awarded", "sent".');
11
11
 
12
- const { gjReq } = require("../gjReq");
12
+ const { gjReq } = require("../misc/gjReq");
13
13
  let GJDecode = require("../misc/GJDecode");
14
14
  const { decodeSearchResults } = new GJDecode;
15
15
  const res = await gjReq("getGJLevels21", {
16
16
  type: tabs[tab.toLowerCase()],
17
- page: Number(page) - 1,
18
- secret: "Wmfd2893gb7"
17
+ page: Number(page) - 1
19
18
  });
20
19
  if (res.data == -1) return [];
21
-
20
+
22
21
  return decodeSearchResults(res.data);
23
22
  }
24
23
  }
@@ -6,15 +6,12 @@ module.exports = {
6
6
  getTop100: async function () {
7
7
  let GJDecode = require("../misc/GJDecode");
8
8
  const { decodeScoresUser } = new GJDecode;
9
- const { gjReq } = require("../gjReq");
9
+ const { gjReq } = require("../misc/gjReq");
10
10
 
11
- const data = {
12
- secret: "Wmfd2893gb7",
11
+ let res = await gjReq("getGJScores20", {
13
12
  type: "top",
14
13
  count: 100
15
- }
16
-
17
- let res = await gjReq("getGJScores20", data);
14
+ });
18
15
 
19
16
  let players = res.data.split("|");
20
17
  players.pop();
@@ -5,12 +5,11 @@ module.exports = {
5
5
  * @returns {import("./searchLists").List[]}
6
6
  */
7
7
  getTopLists: async function (page = 1) {
8
- const { gjReq } = require("../gjReq");
8
+ const { gjReq } = require("../misc/gjReq");
9
9
  const GJDecode = require("../misc/GJDecode");
10
10
  const { decodeLists } = new GJDecode;
11
11
  const res = await gjReq("getGJLevelLists", {
12
12
  type: 6,
13
- secret: "Wmfd2893gb7",
14
13
  page: Number(page) - 1
15
14
  })
16
15
  if (res.data == -1) return [];
@@ -8,23 +8,19 @@ module.exports = {
8
8
  getUserLevels: async function (username, page = 1) {
9
9
  if (!username) throw new Error("Please provide a username or player ID!");
10
10
 
11
- const { gjReq } = require("../gjReq.js");
11
+ const { gjReq } = require("../misc/gjReq");
12
12
  let GJDecode = require("../misc/GJDecode.js");
13
13
  const { decodeSearchResults } = new GJDecode;
14
- let playerID=username;
14
+ let playerID = username;
15
15
  if (isNaN(username)) {
16
- let search = await gjReq("getGJUsers20", {
17
- str: username,
18
- secret: "Wmfd2893gb7"
19
- });
20
- if (search.data == -1) return [];
16
+ let search = await gjReq("getGJUsers20", { str: username });
17
+ if (search.data == -1) throw new Error(`-1: Player "${username}" not found`);
21
18
  playerID = search.data.split(":")[3];
22
19
  }
23
20
 
24
21
  const res = await gjReq("getGJLevels21", {
25
22
  type: 5,
26
23
  str: playerID,
27
- secret: "Wmfd2893gb7",
28
24
  page: Number(page) - 1
29
25
  });
30
26
  if (res.data == -1) return [];
@@ -1,11 +1,11 @@
1
1
  module.exports = {
2
2
  /**
3
3
  * Gets the current weekly demon.
4
- * @returns {import("./dlLevel").Level}
4
+ * @returns {import("./downloadLevel").Level}
5
5
  */
6
6
  getWeeklyDemon: async function () {
7
- const { dlLevel } = require("./dlLevel");
8
- let res = await dlLevel(-2);
7
+ const { downloadLevel } = require("./downloadLevel");
8
+ let res = await downloadLevel(-2);
9
9
  return res;
10
10
  }
11
11
  }
@@ -0,0 +1,33 @@
1
+ module.exports = {
2
+ /**
3
+ * Removes a friend.
4
+ * @param {string} target - The friend to be removed.
5
+ * @param {string} username - The removing person's username or player ID.
6
+ * @param {string} password - The removing person's password.
7
+ * @returns {number} Returns 1 if everything's OK, or -1 if something went wrong.
8
+ */
9
+ removeFriend: async function (target, username, 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
+
14
+ const { gjReq } = require("../misc/gjReq");
15
+ const { gjp2 } = require("../misc/gjp2");
16
+
17
+ let userSearch = await gjReq("getGJUsers20", { str: username });
18
+ if (userSearch.data == -1) throw new Error(`-1: Player with the ID or player username "${username}" not found`);
19
+ let userAccID = userSearch.data.split(":")[23];
20
+
21
+ let recSearch = await gjReq("getGJUsers20", { str: target });
22
+ if (recSearch.data == -1) throw new Error(`-1: Player with the ID or player username "${target}" not found`);
23
+ let targetAccID = recSearch.data.split(":")[23];
24
+
25
+ let res = await gjReq("removeGJFriend20", {
26
+ targetAccountID: targetAccID,
27
+ accountID: userAccID,
28
+ gjp2: gjp2(password)
29
+ });
30
+
31
+ return Number(res.data);
32
+ }
33
+ }
@@ -2,16 +2,13 @@ module.exports = {
2
2
  /**
3
3
  * Reports a level.
4
4
  * @param {number} level - The level ID.
5
- * @returns {1} - Always returns 1, regardless of whether the level was reported or not.
5
+ * @returns {1} Always returns 1, regardless of whether the level was reported or not.
6
6
  */
7
7
  reportLevel: async function (level) {
8
8
  if (isNaN(level)) throw new Error("Please provide a valid level ID.");
9
- const { gjReq } = require("../gjReq");
9
+ const { gjReq } = require("../misc/gjReq");
10
10
 
11
- let res = await gjReq("reportGJLevel", {
12
- levelID: level,
13
- secret: "Wmfd2893gb7"
14
- });
11
+ let res = await gjReq("reportGJLevel", { levelID: level });
15
12
 
16
13
  return res.data;
17
14
  }
@@ -6,15 +6,14 @@ module.exports = {
6
6
  * @returns {import("./getLevelByID").Level[]}
7
7
  */
8
8
  searchLevels: async function (query, page = 1) {
9
- const { gjReq } = require("../gjReq");
9
+ const { gjReq } = require("../misc/gjReq");
10
10
  let GJDecode = require("../misc/GJDecode");
11
11
  const { decodeSearchResults } = new GJDecode;
12
12
 
13
13
  let res = await gjReq("getGJLevels21", {
14
14
  type: 0,
15
15
  str: query,
16
- page: Number(page) - 1,
17
- secret: "Wmfd2893gb7"
16
+ page: Number(page) - 1
18
17
  });
19
18
  if (res.data == -1) return [];
20
19
 
@@ -13,7 +13,7 @@
13
13
  * @property {boolean} disliked - Whether the list is disliked (i.e. if the likes count is less than 0).
14
14
  * @property {Array<Number>} levels - The array of level IDs in the list.
15
15
  * @property {number} required - The amount of completed levels required to get the reward.
16
- * @property {number} uploadedUnix - The UNIX timestamp of the list's upload date.
16
+ * @property {number} uploadedUnix - The Unix timestamp of the list's upload date (GMT timezone).
17
17
  */
18
18
 
19
19
  module.exports = {
@@ -24,13 +24,12 @@ module.exports = {
24
24
  * @returns {List[]}
25
25
  */
26
26
  searchLists: async function (query, page = 1) {
27
- const { gjReq } = require("../gjReq");
27
+ const { gjReq } = require("../misc/gjReq");
28
28
  const GJDecode = require("../misc/GJDecode");
29
29
  const { decodeLists } = new GJDecode;
30
30
  const res = await gjReq("getGJLevelLists", {
31
31
  type: 0,
32
32
  str: query,
33
- secret: "Wmfd2893gb7",
34
33
  page: Number(page) - 1
35
34
  })
36
35
  if (res.data == -1) return [];
@@ -1,43 +1,33 @@
1
1
  module.exports = {
2
2
  /**
3
3
  * Unblocks a specified user.
4
- * @param {string} target - The player that needs to be unblocked.
4
+ * @param {string} target - The player to be unblocked.
5
5
  * @param {string} username - The unblocking person's username or player ID.
6
6
  * @param {string} password - The unblocking 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
  unblockUser: 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
- let userSearch = await gjReq("getGJUsers20", {
19
- str: username,
20
- secret: "Wmfd2893gb7"
21
- });
22
- if (userSearch.data == -1) throw new Error(-1);
23
- let userAccID = userSearch.data.split(":")[21];
17
+ let userSearch = await gjReq("getGJUsers20", { str: username });
18
+ if (userSearch.data == -1) throw new Error(`-1: Player with the ID or player username "${username}" not found`);
19
+ let userAccID = userSearch.data.split(":")[23];
24
20
 
25
- let recSearch = await gjReq("getGJUsers20", {
26
- str: target,
27
- secret: "Wmfd2893gb7"
28
- });
29
- if (recSearch.data == -1) throw new Error(-1);
30
- let targetAccID = recSearch.data.split(":")[21];
21
+ let recSearch = await gjReq("getGJUsers20", { str: target });
22
+ if (recSearch.data == -1) throw new Error(`-1: Player with the ID or player username "${target}" not found`);
23
+ let targetAccID = recSearch.data.split(":")[23];
31
24
 
32
- const data = {
33
- secret: "Wmfd2893gb7",
25
+ let res = await gjReq("unblockGJUser20", {
34
26
  targetAccountID: targetAccID,
35
27
  accountID: userAccID,
36
- gjp: xor.encrypt(password, 37526)
37
- }
38
-
39
- let res = await gjReq("unblockGJUser20", data);
28
+ gjp2: gjp2(password)
29
+ });
40
30
 
41
- return res.data;
31
+ return Number(res.data);
42
32
  }
43
33
  }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @typedef {Object} AccountSettings
3
+ * @property {("all"|"friends"|"none")?} messages - Who the player allows messages from. Set to "all" to allow messages from everyone, "friends" to make messaging limited to friends, or "none" to disable messaging altogether.
4
+ * @property {Boolean?} friendRequests - Whether the player allows friend requests.
5
+ * @property {("all"|"friends"|"none")?} commentHistory - Who the player allows to view their comments. Set to "all" to allow everyone, "friends" to limit it to friends, or "none" to limit it to yourself.
6
+ * @property {string} youtube - The player's YouTube channel ID/handle, used in this template: `https://youtube.com/@((youtube))` or `https://youtube.com/channel/((youtube))` (only if the provided value starts with UC). Be careful, as not providing this value unsets it on the servers as well.
7
+ * @property {string} twitter - The player's X (formerly Twitter) username, used in this template: `https://x.com/((twitter))`. Be careful, as not providing this value unsets it on the servers as well.
8
+ * @property {string} twitch - The player's Twitch username, used in this template: `https://twitch.tv/((twitch))`. Be careful, as not providing this value unsets it on the servers as well.
9
+ * @property {string} instagram - The player's Instagram username, used in this template: `https://instagram.com/@((instagram))`. Be careful, as not providing this value unsets it on the servers as well.
10
+ * @property {string} tiktok - The player's TikTok username, used in this template: `https://tiktok.com/@((tiktok))`. Be careful, as not providing this value unsets it on the servers as well.
11
+ * @property {string} discord - The player's Discord username. Be careful, as not providing this value unsets it on the servers as well.
12
+ * @property {string} custom - The custom string provided by the player. Be careful, as not providing this value unsets it on the servers as well.
13
+ */
14
+
15
+ module.exports = {
16
+ /**
17
+ * Updates the account settings.
18
+ * @param {string} username - The player's username or player ID.
19
+ * @param {string} password - The player's password.
20
+ * @param {AccountSettings} settings - The settings to set.
21
+ * @returns {number} Returns 1 regardless of whether anything was updated, or -1 if something went wrong.
22
+ */
23
+ updateAccountSettings: async function (username, password, settings) {
24
+ if (!username) throw new Error("Please provide the username or the player ID!");
25
+ if (!password) throw new Error("Please provide the password!");
26
+
27
+ const { gjReq } = require("../misc/gjReq");
28
+ const { gjp2 } = require("../misc/gjp2");
29
+
30
+ let search = await gjReq("getGJUsers20", { str: username });
31
+ if (search.data == -1) throw new Error(`-1: Player with the ID or player username "${username}" not found`);
32
+ let accID = search.data.split(":")[23];
33
+
34
+ const parseAccessIDs = {
35
+ "all": "0",
36
+ "friends": "1",
37
+ "none": "2",
38
+ "0": "0",
39
+ "1": "1",
40
+ "2": "2"
41
+ };
42
+
43
+ const parseBoolean = {
44
+ "true": "0",
45
+ "false": "1",
46
+ "0": "0",
47
+ "1": "1"
48
+ };
49
+
50
+ let messages = parseAccessIDs[settings.messages?.toString()] || "";
51
+ let friendRequests = parseBoolean[settings.friendRequests?.toString()] || "";
52
+ let commentHistory = parseAccessIDs[settings.commentHistory?.toString()] || "";
53
+
54
+ const dataObj = {
55
+ accountID: accID,
56
+ secret: "Wmfv3899gc9",
57
+ gjp2: gjp2(password),
58
+ mS: messages,
59
+ frS: friendRequests,
60
+ cS: commentHistory
61
+ };
62
+
63
+ if (settings.youtube) dataObj.yt = settings.youtube;
64
+ if (settings.twitter) dataObj.twitter = settings.twitter;
65
+ if (settings.twitch) dataObj.twitch = settings.twitch;
66
+ if (settings.instagram) dataObj.instagram = settings.instagram;
67
+ if (settings.tiktok) dataObj.tiktok = settings.tiktok;
68
+ if (settings.discord) dataObj.discord = settings.discord;
69
+ if (settings.custom) dataObj.custom = settings.custom;
70
+
71
+ let res = await gjReq("updateGJAccSettings20", dataObj);
72
+
73
+ return Number(res.data);
74
+ }
75
+ }