Support for custom lists!
/api/search/1,2,3,4,5,6,7,8?list
This commit is contained in:
parent
2e6f104501
commit
6782ba7877
11 changed files with 47 additions and 29 deletions
|
@ -13,7 +13,7 @@ Obviously, GDBrowser isn't perfect when it comes to GD private servers, since bo
|
|||
|
||||
You can tweak the endpoint (e.g. boomlings.com) in index.js
|
||||
|
||||
You can also check out `/misc/gdpsConfig.js` to tweak some additional GDPS settings such as whether to decrypt level descriptions or if timestamps should end with "ago"
|
||||
You can also check out `gdpsConfig.js` to tweak some additional GDPS settings such as whether to decrypt level descriptions or if timestamps should end with "ago"
|
||||
|
||||
GDPS compatibility is still a HUGE work in progress, so pull requests would be greatly appreciated if you manage to make any improvements!
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@ module.exports = async (app, req, res) => {
|
|||
if (app.offline) return res.send("-1")
|
||||
|
||||
let amount = 10;
|
||||
let count = req.query.count ? parseInt(req.query.count) : null
|
||||
let count = +req.query.count
|
||||
if (count && count > 0) {
|
||||
if (count > 10) amount = 10
|
||||
if (count > 100) amount = 100
|
||||
else amount = count;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ module.exports = async (app, req, res) => {
|
|||
customSong: req.query.hasOwnProperty("customSong") ? 1 : 0,
|
||||
|
||||
type: req.query.type || 0,
|
||||
count: amount
|
||||
}
|
||||
|
||||
let foundPack = mapPacks[req.params.text.toLowerCase()]
|
||||
|
@ -66,19 +67,19 @@ 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) {
|
||||
|
||||
if (err || !body || body == '-1' || body.startsWith("<!")) return res.send("-1")
|
||||
let splitBody = body.split('#')
|
||||
let preRes = splitBody[0].split('|', 10)
|
||||
let preRes = splitBody[0].split('|')
|
||||
let authorList = {}
|
||||
let songList = {}
|
||||
let authors = splitBody[1].split('|')
|
||||
let songs = '~' + splitBody[2]; songs = songs.split('|~1~:').map(x => app.parseResponse(x + '|~1~', '~|~'))
|
||||
songs.forEach(x => {songList[x['~1']] = x['2']})
|
||||
|
||||
authors.splice(10, 999)
|
||||
authors.forEach(x => {
|
||||
if (x.startsWith('~')) return
|
||||
let arr = x.split(':')
|
||||
|
@ -87,7 +88,7 @@ module.exports = async (app, req, res) => {
|
|||
let levelArray = preRes.map(x => app.parseResponse(x)).filter(x => x[1])
|
||||
let parsedLevels = []
|
||||
|
||||
await levelArray.forEach(async (x, y) => {
|
||||
levelArray.forEach(async (x, y) => {
|
||||
|
||||
let level = new Level(x)
|
||||
let songSearch = songs.find(y => y['~1'] == x[35])
|
||||
|
@ -113,19 +114,29 @@ module.exports = async (app, req, res) => {
|
|||
//this is broken if you're not on page 0, blame robtop
|
||||
if (filters.page == 0 && y == 0) {
|
||||
let pages = splitBody[3].split(":");
|
||||
level.results = +pages[0];
|
||||
level.pages = +Math.ceil(pages[0] / 10);
|
||||
|
||||
if (filters.gauntlet || foundPack) {
|
||||
if (filters.gauntlet) { // gauntlet page stuff
|
||||
level.results = levelArray.length
|
||||
level.pages = 1
|
||||
}
|
||||
|
||||
else if (filters.type == 10) { // custom page stuff
|
||||
level.results = levelArray.length
|
||||
level.pages = amount ? +Math.ceil(levelArray.length / amount) : 1
|
||||
}
|
||||
|
||||
else { // normal page stuff
|
||||
level.results = +pages[0];
|
||||
level.pages = +pages[0] == 9999 ? 1000 : +Math.ceil(pages[0] / amount);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
parsedLevels[y] = level
|
||||
})
|
||||
|
||||
return res.send(parsedLevels.slice(0, amount))
|
||||
if (filters.type == 10) parsedLevels = parsedLevels.slice((+filters.page) * amount, (+filters.page + 1) * amount)
|
||||
return res.send(parsedLevels)
|
||||
|
||||
})
|
||||
}
|
|
@ -81,7 +81,6 @@ img, .noSelect {
|
|||
font-size: 6vh;
|
||||
}
|
||||
|
||||
|
||||
.bigger {
|
||||
font-size: 3.5vh;
|
||||
}
|
||||
|
@ -95,6 +94,10 @@ img, .noSelect {
|
|||
margin-top: 0.5%;
|
||||
}
|
||||
|
||||
.pre {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.valign {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
</div>
|
||||
|
||||
<div id="analysisDiv" style="margin-top: 2%; display:none">
|
||||
<h2 id="levelName"></h2>
|
||||
<h2 class="pre" id="levelName"></h2>
|
||||
<p></p>
|
||||
<h3 id="objectCount"></h3>
|
||||
|
||||
|
|
|
@ -243,7 +243,7 @@
|
|||
<p>Use an asterisk (*) as your search query if you do not wish to search by level name (if you intend on using filters)</p>
|
||||
|
||||
<br>
|
||||
<p class="reveal" onclick="$('#params-search').slideToggle(100)"><b>Parameters (18)</b></p>
|
||||
<p class="reveal" onclick="$('#params-search').slideToggle(100)"><b>Parameters (19)</b></p>
|
||||
<div class="subdiv" id="params-search">
|
||||
<p>Buckle up... there's a lot</p>
|
||||
|
||||
|
@ -265,6 +265,7 @@
|
|||
|
||||
<br>
|
||||
<p><b>Params that require anything</b> (e.g. ?mappack=yes or ?mappack)</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>
|
||||
<p>twoPlayer: Only return two player mode levels</p>
|
||||
|
|
|
@ -258,7 +258,7 @@ fetch(`../api${!history ? window.location.pathname : "/comments/" + lvl.playerID
|
|||
<p class="commentPercent inline">${x.percent ? x.percent + "%" : ""}</p>
|
||||
|
||||
<div class="commentAlign">
|
||||
<p class="commentText" style="color: rgb(${!history && x.playerID == lvl.authorID ? "255,255,75" : x.browserColor ? "255,180,255" : x.color})">${clean(x.content)}</p>
|
||||
<p class="pre commentText" style="color: rgb(${!history && x.playerID == lvl.authorID ? "255,255,75" : x.browserColor ? "255,180,255" : x.color})">${clean(x.content)}</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="commentDate" id="date-${x.ID}">${x.date}</p>
|
||||
|
@ -283,7 +283,7 @@ fetch(`../api${!history ? window.location.pathname : "/comments/" + lvl.playerID
|
|||
<p class="commentPercent inline">${x.percent ? x.percent + "%" : ""}</p>
|
||||
|
||||
<div class="commentAlign">
|
||||
<p class="commentText" style="color: rgb(${!history && x.playerID == lvl.authorID ? "255,255,75" : x.browserColor ? "255,180,255" : x.color})">${clean(x.content)}</p>
|
||||
<p class="pre commentText" style="color: rgb(${!history && x.playerID == lvl.authorID ? "255,255,75" : x.browserColor ? "255,180,255" : x.color})">${clean(x.content)}</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="commentDate compactDate" id="date-${x.ID}">${x.date}</p>
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<div class="epicbox supercenter gs" style="width: 126vh; height: 80%; pointer-events: none"></div>
|
||||
|
||||
<div class="center" style="position:absolute; top: 8%; left: 0%; right: 0%">
|
||||
<h1 id="header"></h1>
|
||||
<h1 class="pre" id="header"></h1>
|
||||
</div>
|
||||
|
||||
<div style="position: absolute; left: 7%; top: 45%; height: 10%;">
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<div class="fancybox bounce center supercenter">
|
||||
<h2 class="smaller center" style="font-size: 5.5vh">Level Info</h2>
|
||||
<p class="bigger center" id="levelInfo" style="line-height: 5vh; margin-top: 1.5vh;">
|
||||
<span style="color:lime">[[NAME]]</span><br>
|
||||
<span class="pre" style="color:lime">[[NAME]]</span><br>
|
||||
ID: <span style="color:yellow">[[ID]]</span>[[ORIGINALINFO]][[LOWDETAIL]][[PASS]][[UPLOAD]][[UPDATE]][[HACKED]]
|
||||
<br>Version: <span style="color:yellow">[[VERSION]]</span>
|
||||
<br>GD Version: <span style="color:yellow">[[GAMEVERSION]]</span>
|
||||
|
@ -31,7 +31,7 @@
|
|||
<div class="fancybox bounce center supercenter">
|
||||
<h2 class="smaller center" style="font-size: 5.5vh">Saved!</h2>
|
||||
<p class="bigger center" style="line-height: 5vh; margin-top: 1.5vh;">
|
||||
<span style="color:yellow">[[NAME]]</span> has been added to your <a class="youCanClickThis2" style="color:lime" href="../search/levels?type=saved">saved levels</a> list.
|
||||
<span class="pre" style="color:yellow">[[NAME]]</span> has been added to your <a class="youCanClickThis2" style="color:lime" href="../search/levels?type=saved">saved levels</a> list.
|
||||
</p>
|
||||
<img src="../assets/ok.png" width=20%; class="gdButton center" onclick="location.reload()">
|
||||
</div>
|
||||
|
@ -76,18 +76,18 @@
|
|||
</div>
|
||||
|
||||
<div class="center" style="width: 70%; margin: 1% auto">
|
||||
<h1 style="transform: scale(1.2)">[[NAME]]</h1>
|
||||
<h1 class="pre" style="transform: scale(1.2)">[[NAME]]</h1>
|
||||
</div>
|
||||
|
||||
<div class="center" style="position:absolute; top: 9%; left: 0%; right: 0%; height: 5%;">
|
||||
<h2 class="inline slightlySmaller normalCursor gdButton" id="authorName"><a class="linkButton" id="authorLink" href="../u/[[AUTHOR]]">By [[AUTHOR]]</a></h2>
|
||||
<h2 class="pre inline slightlySmaller normalCursor gdButton" id="authorName"><a class="linkButton" id="authorLink" href="../u/[[AUTHOR]]">By [[AUTHOR]]</a></h2>
|
||||
<h2 class="inline slightlySmaller normalCursor sideSpaceC">
|
||||
<img class="inline valign" id="copiedBadge" style="height: 60%; cursor:help" src="../assets/copied.png" title="Level is a copy or a collaboration">
|
||||
<img class="inline valign" id="largeBadge" style="height: 60%; margin-left: -7%; cursor:help" src="../assets/large.png" title="Contains more than 40,000 objects"></h2>
|
||||
</div>
|
||||
|
||||
<div class="transparentBox center" style="position:absolute; bottom: 32%; left: 0; right: 0; width: 75vh; margin-left: auto; margin-right: auto">
|
||||
<p style="padding: 0 5%; white-space:normal">[[DESCRIPTION]]</p>
|
||||
<p class="pre" style="padding: 0 5%; white-space:normal">[[DESCRIPTION]]</p>
|
||||
</div>
|
||||
|
||||
<div class="center valign" style="position:absolute; top: 10.5%; left: 27%; transform:scale(0.8); height: 100%; width: 20%">
|
||||
|
@ -112,8 +112,8 @@
|
|||
|
||||
<div class="brownBox" id="songBox" style="position:absolute; bottom: 4%; left: 0; right: 0; width: 85vh; height: 20%; margin-left: auto; margin-right: auto;">
|
||||
<div style="margin-left: 0.5%">
|
||||
<h1 class="slightlySmaller" id="songname">[[SONGNAME]]</h1>
|
||||
<h2 class="smaller">By: [[SONGAUTHOR]] <a class="songLink" href="https://[[SONGAUTHOR]].newgrounds.com" target="_blank"><img class="gdButton valign" src="../assets/more.png" width="12%"></a></h2>
|
||||
<h1 class="pre slightlySmaller" id="songname">[[SONGNAME]]</h1>
|
||||
<h2 class="pre smaller">By: [[SONGAUTHOR]] <a class="songLink" href="https://[[SONGAUTHOR]].newgrounds.com" target="_blank"><img class="gdButton valign" src="../assets/more.png" width="12%"></a></h2>
|
||||
</div>
|
||||
<a class="songLink" href="https://www.newgrounds.com/audio/listen/[[SONGID]]" target="_blank"><img class="gdButton sideButton" src="../assets/playsong.png" style="position:absolute; right: 1%; top: 50%; width: 11%; height: auto;"></a>
|
||||
</div>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<div class="epicbox supercenter gs" style="width: 126vh; height: 80%; pointer-events: none"></div>
|
||||
|
||||
<div class="center" style="position:absolute; top: 8%; left: 0%; right: 0%">
|
||||
<h1 id="header"></h1>
|
||||
<h1 class="pre" id="header"></h1>
|
||||
</div>
|
||||
|
||||
<div style="position:absolute; top: 2%; left: 1.5%; width: 10%; height: 25%; pointer-events: none">
|
||||
|
|
|
@ -238,7 +238,7 @@ fetch(`../api/comments/[[ACCOUNTID]]?type=profile&page=${page}`).then(res => res
|
|||
<div class="comment">
|
||||
<h2>[[USERNAME]]</h2>
|
||||
<div class="commentAlign">
|
||||
<p class="commentText" style="color: rgb(${"[[USERNAME]]" == "RobTop" ? "50, 255, 255" : "[[MODERATOR]]" == "2" ? "75, 255, 75" : x.browserColor ? "255, 180, 255" : "255, 255, 255"})">${clean(x.content)}</p>
|
||||
<p class="pre commentText" style="color: rgb(${"[[USERNAME]]" == "RobTop" ? "50, 255, 255" : "[[MODERATOR]]" == "2" ? "75, 255, 75" : x.browserColor ? "255, 180, 255" : "255, 255, 255"})">${clean(x.content)}</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="commentDate">${x.date}</p>
|
||||
|
|
|
@ -120,6 +120,8 @@ 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')
|
||||
let count = url.searchParams.get('count')
|
||||
let loading = false;
|
||||
let gauntlets = ["Fire", "Ice", "Poison", "Shadow", "Lava", "Bonus", "Chaos", "Demon", "Time", "Crystal", "Magic", "Spike", "Monster", "Doom", "Death"]
|
||||
|
||||
|
@ -129,7 +131,7 @@ let results = 0
|
|||
let legalPages = true
|
||||
let superSearch = ['*', '*?type=mostliked', '*?type=mostdownloaded', '*?type=recent'].includes(window.location.href.split('/')[4].toLowerCase())
|
||||
|
||||
let searchFilters = `../api/search/${type == 'saved' ? JSON.parse(localStorage.getItem('saved') || '[]').reverse().toString() : accID || path}?page=[PAGE]${window.location.search.replace(/\?/g, "&").replace("page", "nope")}`
|
||||
let searchFilters = `../api/search/${type == 'saved' ? JSON.parse(localStorage.getItem('saved') || '[]').reverse().toString() : accID || path}?page=[PAGE]${count ? "" : "&count=10"}${window.location.search.replace(/\?/g, "&").replace("page", "nope")}`
|
||||
|
||||
if (type == "followed") {
|
||||
let followed = localStorage.followed ? JSON.parse(localStorage.followed) : []
|
||||
|
@ -179,9 +181,9 @@ function Append(firstLoad) {
|
|||
}
|
||||
|
||||
$('#searchBox').append(`<div class="searchresult">
|
||||
<h1 class="lessspaced">${x.name}</h1>
|
||||
<h2 class="lessSpaced smaller inline gdButton ${hasAuthor ? "" : "green unregistered"}">${hasAuthor ? `<a href="../u/${x.author}">By ${x.author}</a>` : `<a href="../search/${x.authorID}?user">By ${x.author}</a>`}</h2><h2 class="inline" style="margin-left: 1.5%; transform:translateY(30%)"> ${x.copiedID == '0' ? "" : '<img class="valign sideSpace" src="../assets/copied.png" height="12%">'}${x.large ? '<img class="valign sideSpaceD" src="../assets/large.png" height="12%">' : ''}</h2>
|
||||
<h3 class="lessSpaced ${x.customSong == 0 ? "blue" : "whatIfItWasPurple"}" style="overflow: hidden;">${x.songName.replace(/[^ -~]/g, "")}</h3>
|
||||
<h1 class="lessspaced pre">${x.name}</h1>
|
||||
<h2 class="lessSpaced pre smaller inline gdButton ${hasAuthor ? "" : "green unregistered"}">${hasAuthor ? `<a href="../u/${x.author}">By ${x.author}</a>` : `<a href="../search/${x.authorID}?user">By ${x.author}</a>`}</h2><h2 class="inline" style="margin-left: 1.5%; transform:translateY(30%)"> ${x.copiedID == '0' ? "" : '<img class="valign sideSpace" src="../assets/copied.png" height="12%">'}${x.large ? '<img class="valign sideSpaceD" src="../assets/large.png" height="12%">' : ''}</h2>
|
||||
<h3 class="lessSpaced pre ${x.customSong == 0 ? "blue" : "whatIfItWasPurple"}" style="overflow: hidden;">${x.songName.replace(/[^ -~]/g, "")}</h3>
|
||||
<h3 class="lessSpaced">
|
||||
<img class="valign" src="../assets/time.png" height="14%"> ${x.length}
|
||||
<img class="valign" src="../assets/download.png" height="14%"> ${x.downloads}
|
||||
|
@ -225,6 +227,7 @@ if (type == 6 || type == 'featured') $('#header').text("Featured")
|
|||
if (type == 7 || type == 'magic') $('#header').text("Magic Levels")
|
||||
if (type == 11 || type == 'awarded' || type == 'starred') $('#header').text("Awarded Levels")
|
||||
if (type == 16 || type == 'halloffame' || type == 'hof') $('#header').text("Hall of Fame")
|
||||
if (path != "*" && (type == 10 || list != null)) $('#header').text("List of Levels")
|
||||
if (type == 'followed') $('#header').text("Followed Creators")
|
||||
document.title = $('#header').text() || "Level Search"
|
||||
$('#meta-title').attr('content', $('#header').text() || "Level Search")
|
||||
|
|
Loading…
Reference in a new issue