UNPKG

@sodiumlabs/gdapi

Version:

An unofficial Geometry Dash API wrapper

1,330 lines (1,312 loc) 45.6 kB
"use strict"; 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