@sodiumlabs/gdapi
Version:
An unofficial Geometry Dash API wrapper
1,330 lines (1,312 loc) • 45.6 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
APIError: () => APIError,
BOOMLINGS_URL: () => BOOMLINGS_URL,
COMMON_SECRET: () => COMMON_SECRET,
GDAPI: () => GDAPI,
GEOMETRY_DASH_URL: () => GEOMETRY_DASH_URL,
GauntletName: () => GauntletName,
LevelDemonDifficulty: () => LevelDemonDifficulty,
LevelDifficultyDenominator: () => LevelDifficultyDenominator,
LevelDifficultyNumerator: () => LevelDifficultyNumerator,
LevelEpicRating: () => LevelEpicRating,
LevelLength: () => LevelLength,
ListDifficulty: () => ListDifficulty,
MUSIC_LIBRARY_VERSION_URL: () => MUSIC_LIBRARY_VERSION_URL,
MapPackDifficulty: () => MapPackDifficulty,
ParseError: () => ParseError,
REST: () => REST,
SFX_LIBRARY_VERSION_URL: () => SFX_LIBRARY_VERSION_URL,
SearchLevelsDemonFilter: () => SearchLevelsDemonFilter,
SearchLevelsDifficulty: () => SearchLevelsDifficulty,
SearchLevelsType: () => SearchLevelsType,
SearchListsDemonFilter: () => SearchListsDemonFilter,
SearchListsDifficulty: () => SearchListsDifficulty,
SearchListsType: () => SearchListsType,
SongNewType: () => SongNewType,
SongNong: () => SongNong,
UserCommentHistoryState: () => UserCommentHistoryState,
UserFriendsState: () => UserFriendsState,
UserMessageState: () => UserMessageState,
UserModeratorLevel: () => UserModeratorLevel,
gauntletMappings: () => gauntletMappings,
gauntletSchema: () => gauntletSchema,
levelMappings: () => levelMappings,
levelSchema: () => levelSchema,
listMappings: () => listMappings,
listSchema: () => listSchema,
mapPacksMappings: () => mapPacksMappings,
mapPacksSchema: () => mapPacksSchema,
parseGroups: () => parseGroups,
parseObject: () => parseObject,
parseObjectList: () => parseObjectList,
parseRawObject: () => parseRawObject,
parseRawSong: () => parseRawSong,
parseSong: () => parseSong,
parseSongList: () => parseSongList,
parseTuple: () => parseTuple,
parseTupleList: () => parseTupleList,
songMappings: () => songMappings,
songSchema: () => songSchema,
userMappings: () => userMappings,
userSchema: () => userSchema,
version: () => version
});
module.exports = __toCommonJS(index_exports);
// src/resources/gauntlets.ts
var import_zod = require("zod");
var gauntletMappings = {
1: "id",
3: "levels"
};
var GauntletName = /* @__PURE__ */ ((GauntletName2) => {
GauntletName2[GauntletName2["Fire"] = 1] = "Fire";
GauntletName2[GauntletName2["Ice"] = 2] = "Ice";
GauntletName2[GauntletName2["Poison"] = 3] = "Poison";
GauntletName2[GauntletName2["Shadow"] = 4] = "Shadow";
GauntletName2[GauntletName2["Lava"] = 5] = "Lava";
GauntletName2[GauntletName2["Bonus"] = 6] = "Bonus";
GauntletName2[GauntletName2["Chaos"] = 7] = "Chaos";
GauntletName2[GauntletName2["Demon"] = 8] = "Demon";
GauntletName2[GauntletName2["Time"] = 9] = "Time";
GauntletName2[GauntletName2["Crystal"] = 10] = "Crystal";
GauntletName2[GauntletName2["Magic"] = 11] = "Magic";
GauntletName2[GauntletName2["Spike"] = 12] = "Spike";
GauntletName2[GauntletName2["Monster"] = 13] = "Monster";
GauntletName2[GauntletName2["Doom"] = 14] = "Doom";
GauntletName2[GauntletName2["Death"] = 15] = "Death";
GauntletName2[GauntletName2["Forest"] = 16] = "Forest";
GauntletName2[GauntletName2["Force"] = 18] = "Force";
GauntletName2[GauntletName2["Water"] = 21] = "Water";
GauntletName2[GauntletName2["Haunted"] = 22] = "Haunted";
GauntletName2[GauntletName2["Halloween"] = 29] = "Halloween";
GauntletName2[GauntletName2["Inferno"] = 33] = "Inferno";
GauntletName2[GauntletName2["Portal"] = 34] = "Portal";
GauntletName2[GauntletName2["Strange"] = 35] = "Strange";
GauntletName2[GauntletName2["Fantasy"] = 36] = "Fantasy";
GauntletName2[GauntletName2["Christmas"] = 37] = "Christmas";
GauntletName2[GauntletName2["Mystery"] = 39] = "Mystery";
GauntletName2[GauntletName2["Cursed"] = 40] = "Cursed";
GauntletName2[GauntletName2["Cyborg"] = 41] = "Cyborg";
GauntletName2[GauntletName2["Castle"] = 42] = "Castle";
GauntletName2[GauntletName2["World"] = 46] = "World";
GauntletName2[GauntletName2["Galaxy"] = 47] = "Galaxy";
GauntletName2[GauntletName2["Universe"] = 48] = "Universe";
GauntletName2[GauntletName2["Discord"] = 49] = "Discord";
GauntletName2[GauntletName2["Split"] = 50] = "Split";
GauntletName2[GauntletName2["NCSI"] = 51] = "NCSI";
GauntletName2[GauntletName2["NCSII"] = 52] = "NCSII";
return GauntletName2;
})(GauntletName || {});
var gauntletSchema = import_zod.z.object({
/**
* The gauntlet ID
*/
id: import_zod.z.coerce.number().int(),
/**
* The level IDs
*/
levels: import_zod.z.string().transform((val) => val.split(",")).pipe(import_zod.z.array(import_zod.z.coerce.number().int()))
});
// src/resources/levels.ts
var import_zod2 = require("zod");
var levelMappings = {
1: "id",
2: "name",
3: "description",
5: "version",
6: "playerId",
8: "difficultyDenominator",
9: "difficultyNumerator",
10: "downloads",
12: "officialSong",
13: "gameVersion",
14: "likes",
15: "length",
16: "dislikes",
17: "demon",
18: "stars",
19: "featureScore",
25: "auto",
30: "copiedId",
31: "twoPlayer",
35: "customSongId",
37: "coins",
38: "verifiedCoins",
39: "starsRequested",
42: "epic",
43: "demonDifficulty",
44: "isGauntlet",
45: "objects"
};
var LevelDifficultyDenominator = /* @__PURE__ */ ((LevelDifficultyDenominator2) => {
LevelDifficultyDenominator2[LevelDifficultyDenominator2["NA"] = 0] = "NA";
LevelDifficultyDenominator2[LevelDifficultyDenominator2["Assigned"] = 10] = "Assigned";
return LevelDifficultyDenominator2;
})(LevelDifficultyDenominator || {});
var LevelDifficultyNumerator = /* @__PURE__ */ ((LevelDifficultyNumerator2) => {
LevelDifficultyNumerator2[LevelDifficultyNumerator2["Unrated"] = 0] = "Unrated";
LevelDifficultyNumerator2[LevelDifficultyNumerator2["Easy"] = 10] = "Easy";
LevelDifficultyNumerator2[LevelDifficultyNumerator2["Normal"] = 20] = "Normal";
LevelDifficultyNumerator2[LevelDifficultyNumerator2["Hard"] = 30] = "Hard";
LevelDifficultyNumerator2[LevelDifficultyNumerator2["Harder"] = 40] = "Harder";
LevelDifficultyNumerator2[LevelDifficultyNumerator2["Insane"] = 50] = "Insane";
return LevelDifficultyNumerator2;
})(LevelDifficultyNumerator || {});
var LevelLength = /* @__PURE__ */ ((LevelLength2) => {
LevelLength2[LevelLength2["Tiny"] = 0] = "Tiny";
LevelLength2[LevelLength2["Short"] = 1] = "Short";
LevelLength2[LevelLength2["Medium"] = 2] = "Medium";
LevelLength2[LevelLength2["Long"] = 3] = "Long";
LevelLength2[LevelLength2["XL"] = 4] = "XL";
LevelLength2[LevelLength2["Platformer"] = 5] = "Platformer";
return LevelLength2;
})(LevelLength || {});
var LevelEpicRating = /* @__PURE__ */ ((LevelEpicRating2) => {
LevelEpicRating2[LevelEpicRating2["None"] = 0] = "None";
LevelEpicRating2[LevelEpicRating2["Epic"] = 1] = "Epic";
LevelEpicRating2[LevelEpicRating2["Legendary"] = 2] = "Legendary";
LevelEpicRating2[LevelEpicRating2["Mythic"] = 3] = "Mythic";
return LevelEpicRating2;
})(LevelEpicRating || {});
var LevelDemonDifficulty = /* @__PURE__ */ ((LevelDemonDifficulty2) => {
LevelDemonDifficulty2[LevelDemonDifficulty2["Easy"] = 3] = "Easy";
LevelDemonDifficulty2[LevelDemonDifficulty2["Medium"] = 4] = "Medium";
LevelDemonDifficulty2[LevelDemonDifficulty2["Hard"] = 0] = "Hard";
LevelDemonDifficulty2[LevelDemonDifficulty2["Insane"] = 5] = "Insane";
LevelDemonDifficulty2[LevelDemonDifficulty2["Extreme"] = 6] = "Extreme";
return LevelDemonDifficulty2;
})(LevelDemonDifficulty || {});
var levelSchema = import_zod2.z.object({
/**
* The id of the level
*/
id: import_zod2.z.coerce.number().int(),
/**
* The name of the level
*/
name: import_zod2.z.string(),
/**
* The level description
*/
description: import_zod2.z.string().transform((val) => Buffer.from(val, "base64").toString("utf-8")),
/**
* The version of the level published
*/
version: import_zod2.z.coerce.number().int(),
/**
* The player ID of the level author
*/
playerId: import_zod2.z.coerce.number().int(),
/**
* Returns 0 if the level is N/A, returns 10 if a difficulty is assigned.
*
* @type {LevelDifficultyDenominator}
*/
difficultyDenominator: import_zod2.z.coerce.number().int(),
/**
* The nominator used for calculating the level difficulty. Divided by the denominator to get the difficulty icon.
*
* Nowadays just 0 = unrated, 10 = easy, 20 = normal, 30 = hard, 40 = harder, 50 = insane.
*
* Can be also used to determine the demon difficulty as a side-effect of the voting system.
*
* @type {LevelDifficultyNumerator}
*/
difficultyNumerator: import_zod2.z.coerce.number().int(),
/**
* The amount of times the level has been downloaded
*/
downloads: import_zod2.z.coerce.number().int(),
/**
* The official song number used by the level, if applicable
*/
officialSong: import_zod2.z.coerce.number().int().optional(),
/**
* The GD version the level was uploaded in.
* Divide the version number by ten to get the correct number.
*/
gameVersion: import_zod2.z.coerce.number().int().transform((val) => {
if (val === 1) {
return 10;
}
if (val <= 7) {
return val + 9;
}
if (val === 10) {
return 17;
}
return val;
}),
/**
* likes - dislikes
*/
likes: import_zod2.z.coerce.number().int(),
/**
* A number from 0-4, where 0 is tiny and 4 is XL
*
* @type {LevelLength}
*/
length: import_zod2.z.coerce.number().int(),
/**
* dislikes - likes
*/
dislikes: import_zod2.z.coerce.number().int().optional(),
/**
* If the level's difficulty is demon
*/
demon: import_zod2.z.coerce.boolean(),
/**
* The amount of stars rewarded for completing the level
*/
stars: import_zod2.z.coerce.number().int(),
/**
* 0 if the level is not featured, otherwise a positive number. The higher it is, the higher the level appears on the featured levels list.
*/
featureScore: import_zod2.z.coerce.number().int(),
/**
* If the level's difficulty is auto
*/
auto: import_zod2.z.coerce.boolean(),
/**
* The ID the of the original level (if the level was copied)
*/
copiedId: import_zod2.z.coerce.number().int(),
/**
* Whether the level uses two player mode
*/
twoPlayer: import_zod2.z.coerce.boolean(),
/**
* The ID of the custom Newgrounds song used in the level
*/
customSongId: import_zod2.z.coerce.number().int(),
/**
* The number of user coins placed in the level
*/
coins: import_zod2.z.coerce.number().int(),
/**
* If the level's user coins are verified (silver)
*/
verifiedCoins: import_zod2.z.coerce.boolean(),
/**
* The star value requested for the level
*/
starsRequested: import_zod2.z.coerce.number().int(),
/**
* The epic rating for the level
*
* @type {LevelEpicRating}
*/
epic: import_zod2.z.coerce.number().int(),
/**
* The difficulty of the demon rating. Can also be used to determine the level difficulty non-demons had before rating as a side-effect of the voting system.
*
* @type {LevelDemonDifficulty}
*/
demonDifficulty: import_zod2.z.coerce.number().int(),
/**
* If the level is in a gauntlet
*/
isGauntlet: import_zod2.z.coerce.boolean(),
/**
* The amount of objects in the level, used to determine if the level is considered "large". It caps at 65535
*/
objects: import_zod2.z.coerce.number().int()
});
// src/resources/lists.ts
var import_zod3 = require("zod");
var listMappings = {
1: "id",
2: "name",
3: "description",
5: "version",
7: "difficulty",
10: "downloads",
14: "likes",
19: "rated",
28: "uploadedAt",
29: "updatedAt",
49: "accountId",
50: "username",
51: "levels",
55: "reward",
56: "rewardRequirement"
};
var ListDifficulty = /* @__PURE__ */ ((ListDifficulty2) => {
ListDifficulty2[ListDifficulty2["NA"] = -1] = "NA";
ListDifficulty2[ListDifficulty2["Auto"] = 0] = "Auto";
ListDifficulty2[ListDifficulty2["Easy"] = 1] = "Easy";
ListDifficulty2[ListDifficulty2["Normal"] = 2] = "Normal";
ListDifficulty2[ListDifficulty2["Hard"] = 3] = "Hard";
ListDifficulty2[ListDifficulty2["Harder"] = 4] = "Harder";
ListDifficulty2[ListDifficulty2["Insane"] = 5] = "Insane";
ListDifficulty2[ListDifficulty2["EasyDemon"] = 6] = "EasyDemon";
ListDifficulty2[ListDifficulty2["MediumDemon"] = 7] = "MediumDemon";
ListDifficulty2[ListDifficulty2["HardDemon"] = 8] = "HardDemon";
ListDifficulty2[ListDifficulty2["InsaneDemon"] = 9] = "InsaneDemon";
ListDifficulty2[ListDifficulty2["ExtremeDemon"] = 10] = "ExtremeDemon";
return ListDifficulty2;
})(ListDifficulty || {});
var listSchema = import_zod3.z.object({
/**
* The id of the list
*/
id: import_zod3.z.coerce.number().int(),
/**
* The name of the list
*/
name: import_zod3.z.string(),
/**
* The list description
*/
description: import_zod3.z.string().transform((val) => Buffer.from(val, "base64").toString("utf-8")),
/**
* The version of the list published
*/
version: import_zod3.z.coerce.number().int(),
/**
* The difficulty of this list
*
* @type {ListDifficulty}
*/
difficulty: import_zod3.z.coerce.number().int(),
/**
* The amount of times the list has been downloaded
*/
downloads: import_zod3.z.coerce.number().int(),
/**
* likes - dislikes
*/
likes: import_zod3.z.coerce.number().int(),
/**
* If the list is rated or not
*/
rated: import_zod3.z.coerce.boolean(),
/**
* The timestamp of when the list was uploaded
*/
uploadedAt: import_zod3.z.coerce.number().int(),
/**
* The timestamp of when the list was last updated
*/
updatedAt: import_zod3.z.coerce.number().int(),
/**
* The account ID of the list author
*/
accountId: import_zod3.z.coerce.number().int(),
/**
* The username of the list author
*/
username: import_zod3.z.string(),
/**
* All level IDs in the list
*/
levels: import_zod3.z.string().transform((val) => val.split(",")).pipe(import_zod3.z.array(import_zod3.z.coerce.number().int())),
/**
* The amount of diamonds awarded upon beating the required amount of levels in the list
*/
reward: import_zod3.z.coerce.number().int(),
/**
* The amount of levels needed to claim the list reward
*/
rewardRequirement: import_zod3.z.coerce.number().int()
});
// src/resources/mapPacks.ts
var import_zod4 = require("zod");
var mapPacksMappings = {
1: "id",
2: "name",
3: "levels",
4: "stars",
5: "coins",
6: "difficulty",
7: "textColor",
8: "barColor"
};
var MapPackDifficulty = /* @__PURE__ */ ((MapPackDifficulty2) => {
MapPackDifficulty2[MapPackDifficulty2["Auto"] = 0] = "Auto";
MapPackDifficulty2[MapPackDifficulty2["Easy"] = 1] = "Easy";
MapPackDifficulty2[MapPackDifficulty2["Normal"] = 2] = "Normal";
MapPackDifficulty2[MapPackDifficulty2["Hard"] = 3] = "Hard";
MapPackDifficulty2[MapPackDifficulty2["Harder"] = 4] = "Harder";
MapPackDifficulty2[MapPackDifficulty2["Insane"] = 5] = "Insane";
MapPackDifficulty2[MapPackDifficulty2["HardDemon"] = 6] = "HardDemon";
MapPackDifficulty2[MapPackDifficulty2["EasyDemon"] = 7] = "EasyDemon";
MapPackDifficulty2[MapPackDifficulty2["MediumDemon"] = 8] = "MediumDemon";
MapPackDifficulty2[MapPackDifficulty2["InsaneDemon"] = 9] = "InsaneDemon";
MapPackDifficulty2[MapPackDifficulty2["ExtremeDemon"] = 10] = "ExtremeDemon";
return MapPackDifficulty2;
})(MapPackDifficulty || {});
var mapPacksSchema = import_zod4.z.object({
/**
* The Map Pack ID
*/
id: import_zod4.z.coerce.number().int(),
/**
* The Map Pack name
*/
name: import_zod4.z.string(),
/**
* The level IDs
*/
levels: import_zod4.z.string().transform((val) => val.split(",")).pipe(import_zod4.z.array(import_zod4.z.coerce.number().int())),
/**
* Stars given when completed
*/
stars: import_zod4.z.coerce.number().int(),
/**
* Coins given when completed
*/
coins: import_zod4.z.coerce.number().int(),
/**
* The Map Pack difficulty
*
* @type {MapPackDifficulty}
*/
difficulty: import_zod4.z.coerce.number().int(),
/**
* The RGB color of the title text
*/
textColor: import_zod4.z.string().transform((val) => val.split(",")).pipe(import_zod4.z.array(import_zod4.z.coerce.number().int()).length(3)),
/**
* The RGB color of the completion bar
*/
barColor: import_zod4.z.string().transform((val) => val.split(",")).pipe(import_zod4.z.array(import_zod4.z.coerce.number().int()).length(3))
});
// src/resources/songs.ts
var import_zod5 = require("zod");
var songMappings = {
1: "id",
2: "name",
3: "artistId",
4: "artistName",
5: "size",
6: "videoId",
7: "youtubeURL",
8: "isVerified",
9: "songPriority",
10: "link",
11: "nong",
12: "extraArtistIds",
13: "new",
14: "newType",
15: "extraArtistNames"
};
var SongNong = /* @__PURE__ */ ((SongNong2) => {
SongNong2[SongNong2["None"] = 0] = "None";
SongNong2[SongNong2["NCS"] = 1] = "NCS";
return SongNong2;
})(SongNong || {});
var SongNewType = /* @__PURE__ */ ((SongNewType2) => {
SongNewType2[SongNewType2["Yellow"] = 0] = "Yellow";
SongNewType2[SongNewType2["Blue"] = 1] = "Blue";
return SongNewType2;
})(SongNewType || {});
var songSchema = import_zod5.z.object({
/**
* The ID of the song on Newgrounds
*/
id: import_zod5.z.coerce.number().int().optional(),
/**
* The name of the song
*/
name: import_zod5.z.string(),
/**
* Newgrounds Artist ID
*/
artistId: import_zod5.z.coerce.number().int(),
/**
* The name of the artist who made the song
*/
artistName: import_zod5.z.string(),
/**
* Size of the song in MB, rounded to two decimal places
*/
size: import_zod5.z.coerce.number(),
/**
* The Video ID for the songs YouTube Video
*/
videoId: import_zod5.z.string().optional(),
/**
* The URL of the newgrounds user's youtube channel
*/
youtubeURL: import_zod5.z.string().optional(),
/**
* If the song artist is scouted on newgrounds
*/
isVerified: import_zod5.z.coerce.boolean(),
/**
* Priority over the song list
*/
songPriority: import_zod5.z.coerce.number().int().optional(),
/**
* Link to the song's mp3
*/
link: import_zod5.z.string().transform((val) => decodeURIComponent(val)),
/**
* Type of NONG (Not on Newgrounds)
*
* @type {SongNong}
*/
nong: import_zod5.z.coerce.number().int().optional(),
/**
* IDs of extra artists
*/
extraArtistIds: import_zod5.z.string().transform((val) => val.split(".")).pipe(import_zod5.z.array(import_zod5.z.coerce.number().int())).optional(),
/**
* Whether the NEW icon shows up or not
*/
new: import_zod5.z.coerce.boolean(),
/**
* Type of NEW icon. 0 for Yellow, 1 for Blue
*
* @type {SongNewType}
*/
newType: import_zod5.z.coerce.number().int().optional(),
/**
* Artist names in the format [id, name][]
*/
extraArtistNames: import_zod5.z.string().transform((val) => {
const result = [];
const elements = val.split(",");
for (let i = 0; i < elements.length; i += 2) {
result.push(elements.slice(i, i + 2));
}
return result;
}).pipe(import_zod5.z.array(import_zod5.z.tuple([import_zod5.z.coerce.number().int(), import_zod5.z.string()]))).optional()
});
// src/resources/users.ts
var import_zod6 = require("zod");
var userMappings = {
1: "username",
2: "id",
3: "stars",
4: "totalDemons",
6: "ranking",
7: "accountHighlight",
8: "creatorPoints",
9: "iconId",
10: "primaryColor",
11: "secondaryColor",
13: "secretCoins",
14: "iconType",
15: "special",
16: "accountId",
17: "userCoins",
18: "messageState",
19: "friendsState",
20: "youtube",
21: "accIcon",
22: "accShip",
23: "accBall",
24: "accBird",
25: "accDart",
26: "accRobot",
28: "accGlow",
29: "isRegistered",
30: "globalRank",
42: "age",
43: "accSpider",
44: "twitter",
45: "twitch",
46: "diamonds",
48: "accExplosion",
49: "moderatorLevel",
50: "commentHistoryState",
51: "glowColor",
52: "moons",
53: "accSwing",
54: "accJetpack",
55: "demons",
56: "classicLevels",
57: "platformerLevels"
};
var UserMessageState = /* @__PURE__ */ ((UserMessageState2) => {
UserMessageState2[UserMessageState2["All"] = 0] = "All";
UserMessageState2[UserMessageState2["FriendsOnly"] = 1] = "FriendsOnly";
UserMessageState2[UserMessageState2["None"] = 2] = "None";
return UserMessageState2;
})(UserMessageState || {});
var UserFriendsState = /* @__PURE__ */ ((UserFriendsState2) => {
UserFriendsState2[UserFriendsState2["All"] = 0] = "All";
UserFriendsState2[UserFriendsState2["None"] = 1] = "None";
return UserFriendsState2;
})(UserFriendsState || {});
var UserCommentHistoryState = /* @__PURE__ */ ((UserCommentHistoryState2) => {
UserCommentHistoryState2[UserCommentHistoryState2["All"] = 0] = "All";
UserCommentHistoryState2[UserCommentHistoryState2["FriendsOnly"] = 1] = "FriendsOnly";
UserCommentHistoryState2[UserCommentHistoryState2["None"] = 2] = "None";
return UserCommentHistoryState2;
})(UserCommentHistoryState || {});
var UserModeratorLevel = /* @__PURE__ */ ((UserModeratorLevel2) => {
UserModeratorLevel2[UserModeratorLevel2["None"] = 0] = "None";
UserModeratorLevel2[UserModeratorLevel2["Moderator"] = 1] = "Moderator";
UserModeratorLevel2[UserModeratorLevel2["ElderModerator"] = 2] = "ElderModerator";
return UserModeratorLevel2;
})(UserModeratorLevel || {});
var userSchema = import_zod6.z.object({
/**
* The name of player
*/
username: import_zod6.z.string(),
/**
* The ID of player
*/
id: import_zod6.z.coerce.number().int(),
/**
* The count of stars player have
*/
stars: import_zod6.z.coerce.number().int(),
/**
* The count of diamonds player have
*/
diamonds: import_zod6.z.coerce.number().int().optional(),
/**
* The amount of moons the player have
*/
moons: import_zod6.z.coerce.number().int(),
/**
* The count of coins the player have
*/
secretCoins: import_zod6.z.coerce.number().int(),
/**
* The count of usercoins player have
*/
userCoins: import_zod6.z.coerce.number().int(),
/**
* First color of the player
*/
primaryColor: import_zod6.z.coerce.number().int(),
/**
* Second color of the player
*/
secondaryColor: import_zod6.z.coerce.number().int(),
/**
* Glow color of the player
*/
glowColor: import_zod6.z.coerce.number().int().optional(),
/**
* The special number of the player
*/
special: import_zod6.z.coerce.number().int().optional(),
/**
* The account ID of the player
*/
accountId: import_zod6.z.coerce.number().int(),
/**
* @type {UserMessageState}
*/
messageState: import_zod6.z.coerce.number().int().optional(),
/**
* @type {UserFriendsState}
*/
friendsState: import_zod6.z.coerce.number().int().optional(),
/**
* The time since the last levelScore submit
*/
age: import_zod6.z.string().optional(),
/**
* @type {UserModeratorLevel}
*/
moderatorLevel: import_zod6.z.coerce.number().int().optional(),
/**
* @type {UserCommentHistoryState}
*/
commentHistoryState: import_zod6.z.coerce.number().int().optional(),
/**
* If an account is registered or not
*/
isRegistered: import_zod6.z.coerce.boolean().optional(),
/**
* The global rank of this player
*/
globalRank: import_zod6.z.coerce.number().int().optional(),
/**
* The global leaderboard position of the player
*/
ranking: import_zod6.z.coerce.number().int().optional(),
/**
* The count of creatorpoints player have
*/
creatorPoints: import_zod6.z.coerce.number().int(),
/**
* The count of demons player have
*/
totalDemons: import_zod6.z.coerce.number().int(),
/**
* Breakdown of the player's demons, in the format
* `{easy},{medium},{hard},{insane},{extreme},{easyPlatformer},{mediumPlatformer},{hardPlatformer},{insanePlatformer},{extremePlatformer},{weekly},{gauntlet}`
*/
demons: import_zod6.z.string().transform((val) => val.split(",")).pipe(import_zod6.z.array(import_zod6.z.coerce.number().int())).optional(),
/**
* Breakdown of the player's classic mode non-demons, in the format
* `{auto},{easy},{normal},{hard},{harder},{insane},{daily},{gauntlet}`
*/
classicLevels: import_zod6.z.string().transform((val) => val.split(",")).pipe(import_zod6.z.array(import_zod6.z.coerce.number().int())).optional(),
/**
* Breakdown of the player's platformer mode non-demons, in the format
* `{auto},{easy},{normal},{hard},{harder},{insane}`
*/
platformerLevels: import_zod6.z.string().transform((val) => val.split(",")).pipe(import_zod6.z.array(import_zod6.z.coerce.number().int())).optional(),
/**
* The youtube url of the player
*/
youtube: import_zod6.z.coerce.string().optional(),
/**
* The twitter of the player
*/
twitter: import_zod6.z.coerce.string().optional(),
/**
* The twitch of the player
*/
twitch: import_zod6.z.coerce.string().optional(),
iconId: import_zod6.z.coerce.number().int().optional(),
/**
* The iconType of the player
*/
iconType: import_zod6.z.coerce.number().int().optional(),
/**
* The icon number of the player
*/
accIcon: import_zod6.z.coerce.number().int().optional(),
/**
* The ship number of the player
*/
accShip: import_zod6.z.coerce.number().int().optional(),
/**
* The ball number of the player
*/
accBall: import_zod6.z.coerce.number().int().optional(),
/**
* The bird number of the player
*/
accBird: import_zod6.z.coerce.number().int().optional(),
/**
* The dart (wave) number of the player
*/
accDart: import_zod6.z.coerce.number().int().optional(),
/**
* The robot number of the player
*/
accRobot: import_zod6.z.coerce.number().int().optional(),
/**
* The glow number of the player
*/
accGlow: import_zod6.z.coerce.number().int().optional(),
/**
* The swing number of the player
*/
accSwing: import_zod6.z.coerce.number().int().optional(),
/**
* The jetpack number of the player
*/
accJetpack: import_zod6.z.coerce.number().int().optional(),
/**
* The spider number of the player
*/
accSpider: import_zod6.z.coerce.number().int().optional(),
/**
* The explosion number of the player
*/
accExplosion: import_zod6.z.coerce.number().int().optional(),
/**
* The accountID of the player. Is used for highlighting the player on the leaderboards
*/
accountHighlight: import_zod6.z.coerce.number().int().optional()
});
// src/APIError.ts
var APIError = class extends Error {
constructor(message, options, response) {
super(message, options);
this.response = response;
this.response = response || null;
}
static {
__name(this, "APIError");
}
};
// src/constants.ts
var BOOMLINGS_URL = "https://www.boomlings.com";
var GEOMETRY_DASH_URL = "https://www.geometrydash.com";
var SFX_LIBRARY_VERSION_URL = "https://geometrydashfiles.b-cdn.net/sfx/sfxlibrary_version.txt";
var MUSIC_LIBRARY_VERSION_URL = "https://geometrydashfiles.b-cdn.net/music/musiclibrary_version_02.txt";
// src/GDAPI.ts
var import_zod7 = require("zod");
// src/parser.ts
var ParseError = class extends Error {
static {
__name(this, "ParseError");
}
};
var parseRawObject = /* @__PURE__ */ __name((data) => {
const elements = data.split(":");
if (elements.length % 2 !== 0)
throw new ParseError(`Invalid GD object, got ${elements.length} elements. [${data}]`);
const props = [];
for (let i = 0; i < elements.length; i += 2) {
const key = elements[i];
const value = elements[i + 1];
props.push([key, value]);
}
return props;
}, "parseRawObject");
var parseObject = /* @__PURE__ */ __name((data, mappings, schema) => {
const entries = parseRawObject(data);
const object = {};
for (const [key, value] of entries) {
if (!(key in mappings)) continue;
object[mappings[+key]] = value;
}
return schema.parse(object);
}, "parseObject");
var parseTupleList = /* @__PURE__ */ __name((list, schema) => {
const rawTuples = list.split("|");
const tuples = [];
for (const rawTuple of rawTuples) {
const tuple = parseTuple(rawTuple, schema);
tuples.push(tuple);
}
return tuples;
}, "parseTupleList");
var parseObjectList = /* @__PURE__ */ __name((list, mappings, schema) => {
const rawObjects = list.split("|");
const objects = [];
for (const rawObject of rawObjects) {
const object = parseObject(rawObject, mappings, schema);
objects.push(object);
}
return objects;
}, "parseObjectList");
var parseTuple = /* @__PURE__ */ __name((data, schema) => {
const rawTuple = data.split(":");
return schema.parse(rawTuple);
}, "parseTuple");
var parseGroups = /* @__PURE__ */ __name((data, count) => {
const groups = data.split("#");
if (groups.length !== count) {
throw new ParseError(`Invalid group count, expected ${count} but got ${groups.length}`);
}
return groups;
}, "parseGroups");
var parseRawSong = /* @__PURE__ */ __name((data) => {
const elements = `~${data}~`.split("|");
if (elements.length % 2 !== 0)
throw new ParseError(`Invalid GD object, got ${elements.length} elements. [${data}]`);
const props = [];
for (let i = 0; i < elements.length; i += 2) {
const key = elements[i].slice(1, -1);
const value = elements[i + 1].slice(1, -1);
props.push([key, value]);
}
return props;
}, "parseRawSong");
var parseSong = /* @__PURE__ */ __name((data, mappings, schema) => {
const entries = parseRawSong(data);
const object = {};
for (const [key, value] of entries) {
if (!(key in mappings)) continue;
object[mappings[+key]] = value;
}
return schema.parse(object);
}, "parseSong");
var parseSongList = /* @__PURE__ */ __name((list, mappings, schema) => {
const rawSongs = list.split(":");
const songs = [];
for (const rawSong of rawSongs) {
const song = parseSong(rawSong, mappings, schema);
songs.push(song);
}
return songs;
}, "parseSongList");
// src/REST.ts
var REST = class {
static {
__name(this, "REST");
}
/**
* Throws {@link APIError} if the request fail
*
* @param path - Must start with `/`
*/
async request(method, path, body) {
if (!path.startsWith("/")) {
throw new Error(`Invalid path: ${path}`);
}
const url = `${BOOMLINGS_URL}${path}`;
const encodedBody = body ? new URLSearchParams(body).toString() : void 0;
const headers = new Headers({
"User-Agent": "",
"Content-Type": "application/x-www-form-urlencoded"
});
let res;
try {
res = await fetch(url, { method, headers, body: encodedBody });
} catch (err) {
throw new APIError(`Failed to fetch ${url}`, { cause: err });
}
if (!res.ok) {
throw new APIError(`Invalid response from ${url}: ${res.statusText} (Code: ${res.status})`, void 0, res);
}
return res;
}
async post(path, body) {
const res = await this.request("POST", path, body);
const text = await res.text();
if (text.length <= 3 && text.startsWith("-")) {
throw new APIError(`Invalid request (Error code: ${text})`, void 0, res);
}
return text;
}
};
// src/secrets.ts
var COMMON_SECRET = "Wmfd2893gb7";
// src/GDAPI.ts
var dailyOrWeeklySchema = import_zod7.z.tuple([import_zod7.z.coerce.number().int()]);
var paginationSchema = import_zod7.z.tuple([import_zod7.z.coerce.number().int(), import_zod7.z.coerce.number().int(), import_zod7.z.coerce.number().int()]);
var creatorSchema = import_zod7.z.tuple([import_zod7.z.coerce.number().int(), import_zod7.z.string(), import_zod7.z.coerce.number().int()]);
var versionSchema = import_zod7.z.coerce.number().int();
var GDAPI = class {
static {
__name(this, "GDAPI");
}
rest;
constructor() {
this.rest = new REST();
}
async getDailyLevel() {
const data = await this.rest.post("/database/getGJDailyLevel.php", {
secret: COMMON_SECRET,
weekly: "0"
});
const result = parseTupleList(data, dailyOrWeeklySchema);
return {
index: result[0][0],
timeLeft: result[1][0]
};
}
// TODO: this. Currently returns the same as the daily level, for some reasons
/*public async getWeeklyLevel(): Promise<WeeklyLevel> {
const data = await this.rest.post("/database/getGJDailyLevel.php", {
secret: COMMON_SECRET,
weekly: "1",
});
const result = parseTupleList(data, dailyOrWeeklySchema);
return {
index: result[0][0],
timeLeft: result[1][0],
};
}*/
async getCurrentSFXLibraryVersion() {
const res = await fetch(SFX_LIBRARY_VERSION_URL);
const data = await res.text();
const version2 = versionSchema.parse(data);
return version2;
}
async getCurrentMusicLibraryVersion() {
const res = await fetch(MUSIC_LIBRARY_VERSION_URL);
const data = await res.text();
const version2 = versionSchema.parse(data);
return version2;
}
async getGauntlets() {
const data = await this.rest.post("/database/getGJGauntlets21.php", {
secret: COMMON_SECRET,
special: "1"
});
const [rawGauntlets, hash] = parseGroups(data, 2);
const gauntlets = parseObjectList(rawGauntlets, gauntletMappings, gauntletSchema);
return {
gauntlets,
hash
};
}
/**
* @example
* ```ts
* searchLevels({
* type: SearchLevelsType.Query,
* query: "bloodbath"
* });
* ```
*/
async searchLevels(options) {
const requestOptions = {
secret: COMMON_SECRET,
type: options.type.toString()
};
if (options.page !== void 0) requestOptions.page = options.page.toString();
if (options.query !== void 0) requestOptions.str = options.query;
if (options.gauntlet !== void 0) requestOptions.gauntlet = options.gauntlet.toString();
if (options.difficulty !== void 0) requestOptions.diff = options.difficulty.toString();
if (options.demonFilter !== void 0) requestOptions.demonFilter = options.demonFilter.toString();
if (options.length !== void 0) requestOptions.len = options.length.toString();
if (options.featured !== void 0) requestOptions.featured = options.featured ? "1" : "0";
if (options.original !== void 0) requestOptions.original = options.original ? "1" : "0";
if (options.twoPlayer !== void 0) requestOptions.twoPlayer = options.twoPlayer ? "1" : "0";
if (options.coins !== void 0) requestOptions.coins = options.coins ? "1" : "0";
if (options.epic !== void 0) requestOptions.epic = options.epic ? "1" : "0";
if (options.legendary !== void 0) requestOptions.legendary = options.legendary ? "1" : "0";
if (options.mythic !== void 0) requestOptions.mythic = options.mythic ? "1" : "0";
if (options.noStar !== void 0) requestOptions.noStar = options.noStar ? "1" : "0";
if (options.star !== void 0) requestOptions.star = options.star ? "1" : "0";
if (options.song !== void 0) requestOptions.song = options.song.toString();
if (options.customSong !== void 0) requestOptions.customSong = options.customSong.toString();
const data = await this.rest.post("/database/getGJLevels21.php", requestOptions);
const [rawLevels, rawCreators, rawSongs, rawPagination, hash] = parseGroups(data, 5);
const levels = parseObjectList(rawLevels, levelMappings, levelSchema);
const creators = parseTupleList(rawCreators, creatorSchema);
const songs = rawSongs ? parseSongList(rawSongs, songMappings, songSchema) : [];
const pagination = parseTuple(rawPagination, paginationSchema);
return {
levels,
creators: creators.map((c) => ({
userId: c[0],
username: c[1],
accountId: c[2]
})),
songs,
page: {
total: pagination[0],
offset: pagination[1],
amount: pagination[2]
},
hash
};
}
/**
* @example
* ```ts
* searchLists({
* type: SearchListType.Query,
* query: "Name"
* });
* ```
*/
async searchLists(options) {
const requestOptions = {
secret: COMMON_SECRET,
type: options.type.toString()
};
if (options.page !== void 0) requestOptions.page = options.page.toString();
if (options.query !== void 0) requestOptions.str = options.query;
if (options.difficulty !== void 0) requestOptions.diff = options.difficulty.toString();
if (options.demonFilter !== void 0) requestOptions.demonFilter = options.demonFilter.toString();
if (options.rated !== void 0) requestOptions.rated = options.rated ? "1" : "0";
const data = await this.rest.post("/database/getGJLevelLists.php", requestOptions);
const [rawLists, rawCreators, rawPagination, hash] = parseGroups(data, 4);
const lists = parseObjectList(rawLists, listMappings, listSchema);
const creators = parseTupleList(rawCreators, creatorSchema);
const pagination = parseTuple(rawPagination, paginationSchema);
return {
lists,
creators: creators.map((c) => ({
userId: c[0],
username: c[1],
accountId: c[2]
})),
page: {
total: pagination[0],
offset: pagination[1],
amount: pagination[2]
},
hash
};
}
/**
* @param page - Starts at 0
*/
async getMapPacks(page = 0) {
const data = await this.rest.post("/database/getGJMapPacks21.php", {
secret: COMMON_SECRET,
page: page.toString()
});
const [rawPacks, rawPagination, hash] = parseGroups(data, 3);
const packs = parseObjectList(rawPacks, mapPacksMappings, mapPacksSchema);
const pagination = parseTuple(rawPagination, paginationSchema);
return {
packs,
page: {
total: pagination[0],
offset: pagination[1],
amount: pagination[2]
},
hash
};
}
async getSongById(songId) {
const data = await this.rest.post("/database/getGJSongInfo.php", {
secret: COMMON_SECRET,
songID: songId
});
return parseSong(data, songMappings, songSchema);
}
async getUserById(accountId) {
const data = await this.rest.post("/database/getGJUserInfo20.php", {
secret: COMMON_SECRET,
targetAccountID: accountId.toString()
});
return parseObject(data, userMappings, userSchema);
}
async getUserByName(name) {
const data = await this.rest.post("/database/getGJUsers20.php", {
secret: COMMON_SECRET,
str: name
});
const [rawUser] = parseGroups(data, 2);
return parseObject(rawUser, userMappings, userSchema);
}
async getUserLeaderboard(options) {
const requestOptions = {
secret: COMMON_SECRET,
type: options?.type || "top"
};
if (options?.count !== void 0) requestOptions.count = options.count.toString();
const data = await this.rest.post("/database/getGJScores20.php", requestOptions);
const realData = data.slice(0, -1);
return parseObjectList(realData, userMappings, userSchema);
}
};
// src/requests.ts
var SearchLevelsType = /* @__PURE__ */ ((SearchLevelsType2) => {
SearchLevelsType2[SearchLevelsType2["Query"] = 0] = "Query";
SearchLevelsType2[SearchLevelsType2["MostDownloaded"] = 1] = "MostDownloaded";
SearchLevelsType2[SearchLevelsType2["MostLiked"] = 2] = "MostLiked";
SearchLevelsType2[SearchLevelsType2["Trending"] = 3] = "Trending";
SearchLevelsType2[SearchLevelsType2["Recent"] = 4] = "Recent";
SearchLevelsType2[SearchLevelsType2["UserLevels"] = 5] = "UserLevels";
SearchLevelsType2[SearchLevelsType2["Featured"] = 6] = "Featured";
SearchLevelsType2[SearchLevelsType2["Magic"] = 7] = "Magic";
SearchLevelsType2[SearchLevelsType2["ModeratorSentLevels"] = 8] = "ModeratorSentLevels";
SearchLevelsType2[SearchLevelsType2["Awarded"] = 11] = "Awarded";
SearchLevelsType2[SearchLevelsType2["MostLikedInGDWorld"] = 15] = "MostLikedInGDWorld";
SearchLevelsType2[SearchLevelsType2["HallOfFame"] = 16] = "HallOfFame";
SearchLevelsType2[SearchLevelsType2["FeaturedInGDWorld"] = 17] = "FeaturedInGDWorld";
SearchLevelsType2[SearchLevelsType2["DailyHistory"] = 21] = "DailyHistory";
SearchLevelsType2[SearchLevelsType2["WeeklyHistory"] = 22] = "WeeklyHistory";
SearchLevelsType2[SearchLevelsType2["LevelList"] = 25] = "LevelList";
return SearchLevelsType2;
})(SearchLevelsType || {});
var SearchLevelsDifficulty = /* @__PURE__ */ ((SearchLevelsDifficulty2) => {
SearchLevelsDifficulty2[SearchLevelsDifficulty2["NA"] = -1] = "NA";
SearchLevelsDifficulty2[SearchLevelsDifficulty2["Demons"] = -2] = "Demons";
SearchLevelsDifficulty2[SearchLevelsDifficulty2["Easy"] = 1] = "Easy";
SearchLevelsDifficulty2[SearchLevelsDifficulty2["Normal"] = 2] = "Normal";
SearchLevelsDifficulty2[SearchLevelsDifficulty2["Hard"] = 3] = "Hard";
SearchLevelsDifficulty2[SearchLevelsDifficulty2["Harder"] = 4] = "Harder";
SearchLevelsDifficulty2[SearchLevelsDifficulty2["Insane"] = 5] = "Insane";
return SearchLevelsDifficulty2;
})(SearchLevelsDifficulty || {});
var SearchLevelsDemonFilter = /* @__PURE__ */ ((SearchLevelsDemonFilter2) => {
SearchLevelsDemonFilter2[SearchLevelsDemonFilter2["EasyDemon"] = 1] = "EasyDemon";
SearchLevelsDemonFilter2[SearchLevelsDemonFilter2["MediumDemon"] = 2] = "MediumDemon";
SearchLevelsDemonFilter2[SearchLevelsDemonFilter2["HardDemon"] = 3] = "HardDemon";
SearchLevelsDemonFilter2[SearchLevelsDemonFilter2["InsaneDemon"] = 4] = "InsaneDemon";
SearchLevelsDemonFilter2[SearchLevelsDemonFilter2["ExtremeDemon"] = 5] = "ExtremeDemon";
return SearchLevelsDemonFilter2;
})(SearchLevelsDemonFilter || {});
var SearchListsType = /* @__PURE__ */ ((SearchListsType2) => {
SearchListsType2[SearchListsType2["Query"] = 0] = "Query";
SearchListsType2[SearchListsType2["MostDownloaded"] = 1] = "MostDownloaded";
SearchListsType2[SearchListsType2["MostLiked"] = 2] = "MostLiked";
SearchListsType2[SearchListsType2["Trending"] = 3] = "Trending";
SearchListsType2[SearchListsType2["Recent"] = 4] = "Recent";
SearchListsType2[SearchListsType2["UserLists"] = 5] = "UserLists";
SearchListsType2[SearchListsType2["Awarded"] = 11] = "Awarded";
SearchListsType2[SearchListsType2["SentLists"] = 27] = "SentLists";
return SearchListsType2;
})(SearchListsType || {});
var SearchListsDifficulty = /* @__PURE__ */ ((SearchListsDifficulty2) => {
SearchListsDifficulty2[SearchListsDifficulty2["NA"] = -1] = "NA";
SearchListsDifficulty2[SearchListsDifficulty2["Demons"] = -2] = "Demons";
SearchListsDifficulty2[SearchListsDifficulty2["Easy"] = 1] = "Easy";
SearchListsDifficulty2[SearchListsDifficulty2["Normal"] = 2] = "Normal";
SearchListsDifficulty2[SearchListsDifficulty2["Hard"] = 3] = "Hard";
SearchListsDifficulty2[SearchListsDifficulty2["Harder"] = 4] = "Harder";
SearchListsDifficulty2[SearchListsDifficulty2["Insane"] = 5] = "Insane";
return SearchListsDifficulty2;
})(SearchListsDifficulty || {});
var SearchListsDemonFilter = /* @__PURE__ */ ((SearchListsDemonFilter2) => {
SearchListsDemonFilter2[SearchListsDemonFilter2["EasyDemon"] = 1] = "EasyDemon";
SearchListsDemonFilter2[SearchListsDemonFilter2["MediumDemon"] = 2] = "MediumDemon";
SearchListsDemonFilter2[SearchListsDemonFilter2["HardDemon"] = 3] = "HardDemon";
SearchListsDemonFilter2[SearchListsDemonFilter2["InsaneDemon"] = 4] = "InsaneDemon";
SearchListsDemonFilter2[SearchListsDemonFilter2["ExtremeDemon"] = 5] = "ExtremeDemon";
return SearchListsDemonFilter2;
})(SearchListsDemonFilter || {});
// src/index.ts
var version = "0.0.0";
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
APIError,
BOOMLINGS_URL,
COMMON_SECRET,
GDAPI,
GEOMETRY_DASH_URL,
GauntletName,
LevelDemonDifficulty,
LevelDifficultyDenominator,
LevelDifficultyNumerator,
LevelEpicRating,
LevelLength,
ListDifficulty,
MUSIC_LIBRARY_VERSION_URL,
MapPackDifficulty,
ParseError,
REST,
SFX_LIBRARY_VERSION_URL,
SearchLevelsDemonFilter,
SearchLevelsDifficulty,
SearchLevelsType,
SearchListsDemonFilter,
SearchListsDifficulty,
SearchListsType,
SongNewType,
SongNong,
UserCommentHistoryState,
UserFriendsState,
UserMessageState,
UserModeratorLevel,
gauntletMappings,
gauntletSchema,
levelMappings,
levelSchema,
listMappings,
listSchema,
mapPacksMappings,
mapPacksSchema,
parseGroups,
parseObject,
parseObjectList,
parseRawObject,
parseRawSong,
parseSong,
parseSongList,
parseTuple,
parseTupleList,
songMappings,
songSchema,
userMappings,
userSchema,
version
});
//# sourceMappingURL=index.js.map