Map packs are no longer hardcoded, THANK GOD

This commit is contained in:
GDColon 2020-11-02 11:16:35 -05:00
parent 301e32f8b9
commit 72ffcc4947
10 changed files with 106 additions and 33 deletions

View file

@ -93,8 +93,6 @@ gdpsConfig.js - Tweak small settings for GDPS'es here, such as whether to decryp
level.json - An array of the official GD tracks, and also difficulty face stuff for level searching
mapPacks.json - The IDs for the levels in map packs. I can't believe I have to hardcode this
secretStuff.json - GJP goes here, needed for level leaderboards. Not included in the repo for obvious reasons
sizecheck.js - Excecuted on most pages, used for the 'page isn't wide enough' message, back button, and a few other things

33
api/mappack.js Normal file
View file

@ -0,0 +1,33 @@
const request = require('request')
const difficulties = ["unrated", "easy", "normal", "hard", "harder", "insane", "demon"]
let cache = {data: null, indexed: 0}
module.exports = async (app, req, res) => {
if (app.offline) return res.send("-1")
else if (app.config.cacheMapPacks && cache.data != null && cache.indexed + 20000000 > Date.now()) return res.send(cache.data) // 6 hour cache
request.post(app.endpoint + 'getGJMapPacks21.php', req.gdParams({ count: 100 }), function (err, resp, body) {
if (err || !body || body == '-1' || body.startsWith("<!")) return res.send("-1")
let packs = body.split('#')[0].split('|').map(x => app.parseResponse(x)).filter(x => x[2])
let mappacks = packs.map(x => ({ // "packs.map()" laugh now please
id: +x[1],
name: x[2],
levels: x[3].split(","),
stars: +x[4],
coins: +x[5],
difficulty: difficulties[+x[6]],
barColor: x[7],
textColor: x[8]
}))
if (app.config.cacheMapPacks) cache = {data: mappacks, indexed: Date.now()}
return res.send(mappacks)
})
}

View file

@ -1,5 +1,4 @@
const request = require('request')
const mapPacks = require('../misc/mapPacks.json')
const levels = require('../misc/level.json').music
const Level = require('../classes/Level.js')
@ -38,10 +37,7 @@ module.exports = async (app, req, res) => {
count: amount
}
let foundPack = mapPacks[req.params.text.toLowerCase()]
if (foundPack) filters.str = `${foundPack[0]},${foundPack[1]},${foundPack[2]}`;
if (req.query.gauntlet || req.query.hasOwnProperty("mappack") || req.query.type == "saved") filters.type = 10
if (req.query.gauntlet || req.query.hasOwnProperty("mappack") || req.query.hasOwnProperty("list") || req.query.type == "saved") filters.type = 10
if (req.query.songID && filters.customSong == 0 && levels.find(x => req.query.songID.toLowerCase() == x[0].toLowerCase())) {
filters.song = levels.findIndex(x => req.query.songID.toLowerCase() == x[0].toLowerCase())
@ -67,7 +63,6 @@ module.exports = async (app, req, res) => {
if (req.query.hasOwnProperty("creators")) filters.type = 12
if (req.params.text == "*") delete filters.str
else if (req.query.hasOwnProperty("list")) filters.type = 10
request.post(app.endpoint + 'getGJLevels21.php', req.gdParams(filters), async function(err, resp, body) {

View file

@ -544,7 +544,7 @@ input::-webkit-inner-spin-button {
.mappack {
vertical-align: top;
width: 250px;
height: 50px;
height: 60px;
margin: 0px 9px 210px 9px;
display: inline-block;
cursor: pointer;

View file

@ -12,10 +12,11 @@ module.exports = {
binaryVersion: '35',
},
rateLimiting: true, // Enables rate limiting to avoid api spam, feel free to disable for private use
ipForwarding: true, // Forwards 'x-real-ip' to the servers (requested by robtop)
rateLimiting: true, // Enables rate limiting to avoid api spam, feel free to disable for private use.
ipForwarding: true, // Forwards 'x-real-ip' to the servers. (requested by robtop)
base64descriptions: true, // Are level descriptions encoded in Base64?
xorPasswords: true, // Are level passwords XOR encrypted?
cacheMapPacks: true, // Caches map packs to speed up loading. Useful if they're rarely updated.
timestampSuffix: " ago", // Suffix to add after timestamps, if any.
// more settings soon

View file

@ -27,6 +27,7 @@
<div class="category-content">
<a class="header-link" href="#level">Levels</a>
<a class="header-link" href="#search">Searching</a>
<a class="header-link" href="#mappacks">Map Packs</a>
<a class="header-link" href="#levelleaderboard">Level Leaderboards</a>
</div>
</div>
@ -264,7 +265,7 @@
<p>creators: A comment seperated list of account IDs. Only levels by those players will be returned</p>
<br>
<p><b>Params that require anything</b> (e.g. ?mappack=yes or ?mappack)</p>
<p><b>Params that require anything</b> (e.g. ?featured=yes or ?featured)</p>
<p>list: Reads and returns a custom list of levels (search query should be a comma seperated list of IDs)</p>
<p>featured: Only return featured levels</p>
<p>original: Only return non-copied levels</p>
@ -274,7 +275,6 @@
<p>starred: Only return levels with a star rating</p>
<p>noStar: Only return levels without a star rating</p>
<p>customSong: Reads the 'song' parameter as a custom song ID instead of an official one</p>
<p>mappack: Reads the search query as the name of a map pack and returns the 3 levels if pack exists</p>
<p>user: Reads the search query as a player's ID and returns their levels</p>
<br>
@ -371,10 +371,57 @@
<div class="seperator"></div>
</main>
<main>
<div id="mappacks" class="anchor"></div>
<div class="main-block">
<h1>Map Packs</h1>
<p>/api/mappacks</p>
<p>Returns the list of map packs</p>
<br>
<p class="reveal" onclick="$('#params-mappacks').slideToggle(100)"><b>Parameters (0)</b></p>
<div class="subdiv" id="params-mappacks">
<p>No parameters for this one!</p>
</div>
<br>
<p class="reveal" onclick="$('#response-mappacks').slideToggle(100)"><b>Response (8)</b></p>
<div class="subdiv" id="response-mappacks">
<p>The API will return an array of each map pack with the following information:</p>
<p>id: The ID of the map</p>
<p>name: The name of the pack</p>
<p>levels: An array of level IDs in the map pack. Fetch with /search/ using the ?list parameter</p>
<p>stars: The amount of stars rewarded for completing the pack</p>
<p>coins: Basically the only reason people play map packs LOL</p>
<p>difficulty: The (usually inaccurate) difficulty face of the map pack</p>
<p>barColor: The RGB color of the pack's progress bar</p>
<p>textColor: The RGB color of the pack's name</p>
</div>
<br>
<p class="reveal" onclick="$('#request-mappacks').slideToggle(100)"><b>Example</b></p>
<div class="subdiv" id="request-mappacks">
<p><b>Example Request</b></p>
<p>/api/mappacks</p>
<br>
<p><b>Example Response</b></p>
<pre><p class="fetch" link="/api/mappacks">...</p></pre>
</div>
<br>
</div>
<div class="seperator"></div>
</main>
<main>
<div id="levelleaderboard" class="anchor"></div>
<div class="main-block">
<h1>Level Leaderboards</h1>
<h1>Level Leaderboards (usually broken)</h1>
<p>/api/leaderboardLevel/levelID</p>
<p>Returns the leaderboard for a level</p>
@ -519,7 +566,7 @@
<main>
<div id="commenting" class="anchor"></div>
<div class="main-block">
<h1>Commenting</h1>
<h1>Commenting (usually broken)</h1>
<p>POST: /postComment</p>
<p>Leaves a comment on a level. This one is a POST request!</p>
@ -560,7 +607,7 @@
<main>
<div id="profileposting" class="anchor"></div>
<div class="main-block">
<h1>Profile Posting</h1>
<h1>Profile Posting (usually broken)</h1>
<p>POST: /postProfileComment</p>
<p>Leaves a profile post. This one is a POST request!</p>
@ -597,7 +644,7 @@
<main>
<div id="liking" class="anchor"></div>
<div class="main-block">
<h1>Liking</h1>
<h1>Liking (usually broken)</h1>
<p>POST: /like</p>
<p>Likes/dislikes level, comment, or post. This one is a POST request!</p>
@ -638,7 +685,7 @@
<main>
<div id="messages" class="anchor"></div>
<div class="main-block">
<h1>Messages</h1>
<h1>Messages (usually broken)</h1>
<p>POST:<br>
<b>/messages</b> (fetches messages, includes subject but not actual content. blame robtop)<br>
<b>/messages/messageID</b> (reads a message)<br>

View file

@ -30,7 +30,7 @@
<div id="customlist" class="popup">
<div class="brownBox bounce center supercenter" style="width: 100vh; height: 56%; padding-top: 0.3%; padding-bottom: 3.5%; padding-left: 1%">
<img class="gdButton" src="../assets/close.png" width="9%" style="position: absolute; top: -8.5%; left: -5.5vh" onclick="$('#filters').hide()">
<img class="gdButton" src="../assets/close.png" width="9%" style="position: absolute; top: -8.5%; left: -5.5vh" onclick="$('#customlist').hide()">
<h1>Custom List</h1><br>
<p id="listInfo" style="margin-top: 1%; margin-bottom: 1.5%">Paste a <span style="color: yellow">comma-seperated</span> list of <span style="color: cyan">Level IDs</span> to create a custom list!</p>
<textarea id="listLevels" placeholder="18025697, 23189196, 27786218, 27728679, 25706351" style="margin-bottom: 2%; font-size: 2.5vh"></textarea>
@ -244,7 +244,7 @@ $('#listLevels, #listName').on('input blur', function (event) {
if (levels.length > 1 && levels.length <= 100) {
$('#listInfo').html(`A list of <span style='color: yellow'>${levels.length}</span> levels will be created.`)
$('#listLink').attr('href', `./${levels.join(",")}?list&count=${+$('#pageSize').val()}${$('#listName').val().length ? `&header=${encodeURIComponent($('#listName').val())}` : ""}`)
$('#listLink').attr('href', `../search/${levels.join(",")}?list&count=${+$('#pageSize').val()}${$('#listName').val().length ? `&header=${encodeURIComponent($('#listName').val())}` : ""}`)
$('#createList').removeClass('disabled')
}

View file

@ -23,10 +23,8 @@
<div style="position:absolute; top: 2%; left: -1.95%; width: 10%; height: 25%; pointer-events: none">
<img class="gdButton yesClick" id="backButton" src="../assets/back.png" height="30%" onclick="backButton()">
</div>
</div>
<br>
</div>
</body>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
@ -34,13 +32,15 @@
<script>
fetch('../api/mappacks').then(res => res.json()).then(packs => {
keys = Object.keys(packs)
keys.forEach(x => {
packs.forEach(x => {
$('#packList').append(`
<div class="mappack">
<a href="../search/${x}?mappack=1">
<img src="../difficulty/${packs[x][3]}.png" height="220%"><br>
<h3 class="gauntletText"">${x.replace("Pack", "<br>Pack")}</h3></div></a>`)
<a href="../search/${x.levels.join(",")}?list&header=${encodeURIComponent(x.name)}">
<img src="../difficulty/${x.difficulty}.png" width="42%"><br>
<h3 class="gauntletText"">${x.name.replace("Pack", "<br>Pack")}<br>
<span style="color: rgb(${x.textColor})">${x.stars}</span><img class="valign" src="../assets/star.png" style="cursor: help; width: 14%; margin-left: 2%; transform: translateY(-10%);" title="Stars">
<span style="color: rgb(${x.barColor})">${x.coins}</span><img class="valign" src="../assets/coin.png" style="cursor: help; width: 14%; margin-left: 2%; transform: translateY(-10%);" title="Secret Coins">
</h3></div></a>`)
})
});

View file

@ -117,7 +117,6 @@ let accID;
let path = location.pathname.replace('/search/', "")
let url = new URL(window.location.href)
let gauntlet = url.searchParams.get('gauntlet')
let mappack = url.searchParams.get('mappack')
let userMode = url.searchParams.get('user')
let type = url.searchParams.get('type')
let list = url.searchParams.get('list')
@ -152,6 +151,8 @@ function Append(firstLoad) {
fetch(searchFilters.replace("[PAGE]", page)).then(res => res.json()).then(res => {
if (res == '-1' || res.length == 0) { $('#loading').hide(); $('#pageUp').hide(); return loading = false }
if (firstLoad) {
pages = res[0].pages
results = res[0].results
@ -164,11 +165,9 @@ function Append(firstLoad) {
$('#pagenum').text(`Page 1${pages ? ` of ${pages}` : ""}`)
}
if (res == '-1' || (pages && page >= pages) || (!pages && res.length < 9 && type != "recent")) $('#pageUp').hide()
if ((pages && page+1 >= pages) || (!pages && res.length < 9 && type != "recent")) $('#pageUp').hide()
else $('#pageUp').show()
if (res == '-1' || res.length == 0) { $('#loading').hide(); return loading = false }
res.forEach((x, y) => {
let hasAuthor = (x.accountID != "0")
if (y == 0 && (type == 5 || typeof userMode == 'string')) {

View file

@ -131,7 +131,7 @@ app.get("/api/credits", function(req, res) { res.send(require('./misc/credits.js
app.get("/api/leaderboard", function(req, res) { app.run[req.query.hasOwnProperty("accurate") ? "accurate" : "scores"](app, req, res) })
app.get("/api/leaderboardLevel/:id", RL, function(req, res) { app.run.leaderboardLevel(app, req, res) })
app.get("/api/level/:id", RL, async function(req, res) { app.run.level(app, req, res, api) })
app.get("/api/mappacks", async function(req, res) { res.send(require('./misc/mapPacks.json')) })
app.get("/api/mappacks", async function(req, res) { app.run.mappack(app, req, res) })
app.get("/api/profile/:id", function(req, res) { app.run.profile(app, req, res, api) })
app.get("/api/search/:text", function(req, res) { app.run.search(app, req, res) })