Better error handling + general cleanup (#182)
* chore: cleanup .gitignore
- remove unused /typings, not using typescript
- remove .next as this is not using next.js
+ add editors to ignore file
+ add exceptions for more .env files, .env.local, etc.
+ seperate lockfiles and add yarn lockfile
* feat(package.json): add dev command
* feat: better error handling 1/4
+ add status codes to all of the errors.
? I understand this is similar to robtop so I didn't change any of the very cryptic responses, i.e. -1, -2, -3.
* feat: cleanup unused params & add status codes
* chore(servers.json): remove weird space in json
* feat: final status codes
* fix(leaderboard): fix comment for private server
* fix(merge): merge on 7da5632
* revert: revert icon.js
This commit is contained in:
parent
4d1ea03115
commit
a37125ed59
26 changed files with 472 additions and 372 deletions
12
.gitignore
vendored
12
.gitignore
vendored
|
@ -1,6 +1,9 @@
|
||||||
# Ew
|
# Ew
|
||||||
extra
|
extra
|
||||||
|
|
||||||
|
# Package manager lockfiles
|
||||||
package-lock.json
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
|
@ -40,9 +43,6 @@ build/Release
|
||||||
node_modules/
|
node_modules/
|
||||||
jspm_packages/
|
jspm_packages/
|
||||||
|
|
||||||
# TypeScript v1 declaration files
|
|
||||||
typings/
|
|
||||||
|
|
||||||
# Optional npm cache directory
|
# Optional npm cache directory
|
||||||
.npm
|
.npm
|
||||||
|
|
||||||
|
@ -60,6 +60,8 @@ typings/
|
||||||
|
|
||||||
# dotenv environment variables file
|
# dotenv environment variables file
|
||||||
.env
|
.env
|
||||||
|
.env.*
|
||||||
|
|
||||||
# next.js build output
|
# Editors
|
||||||
.next
|
.idea
|
||||||
|
.vscode
|
|
@ -21,14 +21,14 @@ module.exports = async (app, req, res, level) => {
|
||||||
const raw_data = level.data;
|
const raw_data = level.data;
|
||||||
|
|
||||||
const response_data = analyze_level(level, raw_data);
|
const response_data = analyze_level(level, raw_data);
|
||||||
return res.send(response_data);
|
return res.status(200).send(response_data);
|
||||||
} else {
|
} else {
|
||||||
zlib.unzip(levelString, (err, buffer) => {
|
zlib.unzip(levelString, (err, buffer) => {
|
||||||
if (err) { return res.send("-2"); }
|
if (err) { return res.status(500).send("-2"); }
|
||||||
|
|
||||||
const raw_data = buffer.toString();
|
const raw_data = buffer.toString();
|
||||||
const response_data = analyze_level(level, raw_data);
|
const response_data = analyze_level(level, raw_data);
|
||||||
return res.send(response_data);
|
return res.status(200).send(response_data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module.exports = async (app, req, res) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
if (req.offline) return res.send("-1")
|
if (req.offline) return res.status(500).send("-1")
|
||||||
|
|
||||||
let count = +req.query.count || 10
|
let count = +req.query.count || 10
|
||||||
if (count > 1000) count = 1000
|
if (count > 1000) count = 1000
|
||||||
|
@ -20,14 +20,14 @@ module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
req.gdRequest(path, req.gdParams(params), function(err, resp, body) {
|
req.gdRequest(path, req.gdParams(params), function(err, resp, body) {
|
||||||
|
|
||||||
if (err) return res.send("-1")
|
if (err) return res.status(500).send("-1")
|
||||||
|
|
||||||
comments = body.split('|')
|
comments = body.split('|')
|
||||||
comments = comments.map(x => x.split(':'))
|
comments = comments.map(x => x.split(':'))
|
||||||
comments = comments.map(x => x.map(x => app.parseResponse(x, "~")))
|
comments = comments.map(x => x.map(x => app.parseResponse(x, "~")))
|
||||||
if (req.query.type == "profile") comments.filter(x => x[0][2])
|
if (req.query.type == "profile") comments.filter(x => x[0][2])
|
||||||
else comments = comments.filter(x => x[0] && x[0][2])
|
else comments = comments.filter(x => x[0] && x[0][2])
|
||||||
if (!comments.length) return res.send("-1")
|
if (!comments.length) return res.status(204).send("-1")
|
||||||
|
|
||||||
let pages = body.split('#')[1].split(":")
|
let pages = body.split('#')[1].split(":")
|
||||||
let lastPage = +Math.ceil(+pages[0] / +pages[2]);
|
let lastPage = +Math.ceil(+pages[0] / +pages[2]);
|
||||||
|
@ -79,7 +79,7 @@ module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return res.send(commentArray)
|
return res.status(200).send(commentArray)
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -6,7 +6,7 @@ module.exports = async (app, req, res, api, ID, analyze) => {
|
||||||
|
|
||||||
function rejectLevel() {
|
function rejectLevel() {
|
||||||
if (!api) return res.redirect('search/' + req.params.id)
|
if (!api) return res.redirect('search/' + req.params.id)
|
||||||
else return res.send("-1")
|
else return res.status(500).send("-1")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.offline) {
|
if (req.offline) {
|
||||||
|
@ -22,7 +22,7 @@ module.exports = async (app, req, res, api, ID, analyze) => {
|
||||||
req.gdRequest('downloadGJLevel22', { levelID }, function (err, resp, body) {
|
req.gdRequest('downloadGJLevel22', { levelID }, function (err, resp, body) {
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
if (analyze && api && req.server.downloadsDisabled) return res.send("-3")
|
if (analyze && api && req.server.downloadsDisabled) return res.status(403).send("-3")
|
||||||
else if (!api && levelID < 0) return res.redirect(`/?daily=${levelID * -1}`)
|
else if (!api && levelID < 0) return res.redirect(`/?daily=${levelID * -1}`)
|
||||||
else return rejectLevel()
|
else return rejectLevel()
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ module.exports = async (app, req, res, api, ID, analyze) => {
|
||||||
if (analyze) return app.run.analyze(app, req, res, level)
|
if (analyze) return app.run.analyze(app, req, res, level)
|
||||||
|
|
||||||
function sendLevel() {
|
function sendLevel() {
|
||||||
if (api) return res.send(level)
|
if (api) return res.status(200).send(level)
|
||||||
|
|
||||||
else return fs.readFile('./html/level.html', 'utf8', function (err, data) {
|
else return fs.readFile('./html/level.html', 'utf8', function (err, data) {
|
||||||
let html = data;
|
let html = data;
|
||||||
|
@ -78,7 +78,7 @@ module.exports = async (app, req, res, api, ID, analyze) => {
|
||||||
let regex = new RegExp(`\\[\\[${x.toUpperCase()}\\]\\]`, "g")
|
let regex = new RegExp(`\\[\\[${x.toUpperCase()}\\]\\]`, "g")
|
||||||
html = html.replace(regex, app.clean(level[x]))
|
html = html.replace(regex, app.clean(level[x]))
|
||||||
})
|
})
|
||||||
return res.send(html)
|
return res.status(200).send(html)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,19 +3,19 @@ let gauntletNames = ["Fire", "Ice", "Poison", "Shadow", "Lava", "Bonus", "Chaos"
|
||||||
|
|
||||||
module.exports = async (app, req, res) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
if (req.offline) return res.send("-1")
|
if (req.offline) return res.status(500).send("-1")
|
||||||
|
|
||||||
let cached = cache[req.id]
|
let cached = cache[req.id]
|
||||||
if (app.config.cacheGauntlets && cached && cached.data && cached.indexed + 2000000 > Date.now()) return res.send(cached.data) // half hour cache
|
if (app.config.cacheGauntlets && cached && cached.data && cached.indexed + 2000000 > Date.now()) return res.status(200).send(cached.data) // half hour cache
|
||||||
|
|
||||||
req.gdRequest('getGJGauntlets21', {}, function (err, resp, body) {
|
req.gdRequest('getGJGauntlets21', {}, function (err, resp, body) {
|
||||||
|
|
||||||
if (err) return res.send("-1")
|
if (err) return res.status(500).send("-1")
|
||||||
let gauntlets = body.split('#')[0].split('|').map(x => app.parseResponse(x)).filter(x => x[3])
|
let gauntlets = body.split('#')[0].split('|').map(x => app.parseResponse(x)).filter(x => x[3])
|
||||||
let gauntletList = gauntlets.map(x => ({ id: +x[1], name: gauntletNames[+x[1] - 1] || "Unknown", levels: x[3].split(",") }))
|
let gauntletList = gauntlets.map(x => ({ id: +x[1], name: gauntletNames[+x[1] - 1] || "Unknown", levels: x[3].split(",") }))
|
||||||
|
|
||||||
if (app.config.cacheGauntlets) cache[req.id] = {data: gauntletList, indexed: Date.now()}
|
if (app.config.cacheGauntlets) cache[req.id] = {data: gauntletList, indexed: Date.now()}
|
||||||
res.send(gauntletList)
|
res.status(200).send(gauntletList)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
632
api/icon.js
632
api/icon.js
|
@ -1,311 +1,389 @@
|
||||||
const sharp = require('sharp');
|
// this file is a potential candidate for worst code on github
|
||||||
const Canvas = require('canvas')
|
// i advise you to turn back now
|
||||||
const psd = require('ag-psd')
|
// seriously, it's not too late
|
||||||
|
|
||||||
|
const Jimp = require('jimp');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const mainPath = `../icons/`
|
const icons = require('../icons/gameSheet.json');
|
||||||
const icons = require('../misc/icons/gameSheet.json');
|
const colors = require('../icons/colors.json');
|
||||||
const colors = require('../misc/icons/colors.json');
|
const forms = require('../icons/forms.json')
|
||||||
const forms = require('../misc/icons/forms.json')
|
const offsets = require('../icons/offsets.json');
|
||||||
const offsets = require('../misc/icons/offsets.json')
|
|
||||||
const legOffsets = require('../misc/icons/legOffsets.json')
|
|
||||||
|
|
||||||
let canvasSize = 300
|
|
||||||
let halfCanvas = canvasSize/2
|
|
||||||
let TRANSPARENT = {r: 0, g: 0, b: 0, alpha: 0}
|
|
||||||
let cache = {}
|
|
||||||
|
|
||||||
let partNames = {
|
|
||||||
"1": "Primary",
|
|
||||||
"2": "Secondary",
|
|
||||||
"3": "UFO Dome",
|
|
||||||
"glow": "Glow",
|
|
||||||
"extra": "White",
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert hex to RGB
|
|
||||||
let hexRegex = /^[A-Fa-f0-9]{6}$/
|
let hexRegex = /^[A-Fa-f0-9]{6}$/
|
||||||
function hexConvert(hex) { hex = hex.replace('#', ''); return {val: hex, r: '0x' + hex[0] + hex[1] | 0, g: '0x' + hex[2] + hex[3] | 0, b: '0x' + hex[4] + hex[5] | 0}; }
|
function hexConvert(hex) { hex = hex.replace('#', ''); return {r: '0x' + hex[0] + hex[1] | 0, g: '0x' + hex[2] + hex[3] | 0, b: '0x' + hex[4] + hex[5] | 0}; }
|
||||||
|
function recolor(img, col) {
|
||||||
// get path name from icon form and ID
|
return img.scan(0, 0, img.bitmap.width, img.bitmap.height, function (x, y, idx) {
|
||||||
function getIconPath(icon, formName) {
|
if (img.bitmap.data.slice(idx, idx+3).every(function(val) {return val >= 20 && val <= 255})) { // If it's not "black, i.e. we want to recolor it"
|
||||||
return `${mainPath}${formName}_${icon < 10 ? "0" : ""}${icon}`
|
this.bitmap.data[idx] = colors[col].r / (255 / this.bitmap.data[idx]);
|
||||||
|
this.bitmap.data[idx + 1] = colors[col].g / (255 / this.bitmap.data[idx + 1]);
|
||||||
|
this.bitmap.data[idx + 2] = colors[col].b / (255 / this.bitmap.data[idx + 2]);
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// get color from param input
|
/* Caveat of genFileName is that if there are any falsey values in the arguments they are ignored.
|
||||||
function getColor(colInput, defaultCol) {
|
This is usually a good thing though - avoid issues by not putting something like 0 instead of '0' */
|
||||||
colInput = String(colInput)
|
function genFileName(...args) { return args.filter(function(val) {return val}).join('_') +'_001.png' }
|
||||||
let foundColor = colors[colInput]
|
function fromIcons(filename) { return `./icons/${filename}` }
|
||||||
if (foundColor) {
|
let cache = {};
|
||||||
foundColor.val = colInput
|
|
||||||
return foundColor
|
|
||||||
}
|
|
||||||
else if (colInput.match(hexRegex)) { // custom hex code
|
|
||||||
let hexCol = hexConvert(colInput)
|
|
||||||
colors[colInput.toLowerCase()] = hexCol
|
|
||||||
return hexCol
|
|
||||||
}
|
|
||||||
else if (!foundColor && defaultCol) {
|
|
||||||
let def = colors[defaultCol]
|
|
||||||
def.val = defaultCol
|
|
||||||
return def
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = async (app, req, res) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
async function buildIcon(account=[], userCode) {
|
function buildIcon(account=[], usercode) {
|
||||||
|
|
||||||
let form = forms[req.query.form] || forms["icon"]
|
let { form, ind } = forms[req.query.form] || {};
|
||||||
|
form = form || 'player';
|
||||||
|
ind = ind || 21;
|
||||||
|
|
||||||
let iconID = req.query.icon || account[form.index] || 1;
|
let iconID = req.query.icon || account[ind] || 1;
|
||||||
let col1 = getColor(req.query.col1 || account[10], "0")
|
let col1 = req.query.col1 || account[10] || 0;
|
||||||
let col2 = getColor(req.query.col2 || account[11], "3")
|
let col2 = req.query.col2 || account[11] || 3;
|
||||||
let colG = getColor(req.query.colG || req.query.colg)
|
let colG = req.query.colG || req.query.colg
|
||||||
let colW = getColor(req.query.colW || req.query.colw || req.query.col3)
|
let colW = req.query.colW || req.query.colw || req.query.col3
|
||||||
|
let outline = req.query.glow || account[28] || "0";
|
||||||
|
|
||||||
let useGlow = req.query.glow || account[28] || false;
|
let topless = form == "bird" && req.query.topless
|
||||||
if (useGlow && ["false", "0"].includes(useGlow)) useGlow = false
|
let drawLegs = !(req.query.noLegs > 0)
|
||||||
if (col1.r == 0 && col1.g == 0 && col1.b == 0 ) useGlow = true
|
let autoSize = req.query.size == "auto"
|
||||||
|
let sizeParam = autoSize || (req.query.size && !isNaN(req.query.size))
|
||||||
|
if (outline == "0" || outline == "false") outline = false;
|
||||||
|
|
||||||
// bit of a hacky solution for glow color but whatev
|
if (iconID && iconID.toString().length == 1) iconID = "0" + iconID;
|
||||||
let glowColor = colG || col2
|
|
||||||
if (glowColor.r == 0 && glowColor.g == 0 && glowColor.b == 0) glowColor = col1
|
|
||||||
if (glowColor.r == 0 && glowColor.g == 0 && glowColor.b == 0) glowColor = {r: 255, g: 255, b: 255}
|
|
||||||
|
|
||||||
let psdExport = req.query.psd || false
|
function genImageName(...args) { return genFileName(form, iconID, ...args) }
|
||||||
let topless = form.name == "UFO" ? req.query.topless || false : false
|
|
||||||
|
|
||||||
let customSize = req.query.size == "auto" ? "auto" : +req.query.size || null
|
let icon, glow, extra;
|
||||||
|
function setBaseIcons() {
|
||||||
let iconPath = getIconPath(iconID, form.form)
|
icon = genImageName(isSpecial && '01');
|
||||||
|
glow = genImageName(isSpecial && '01', '2');
|
||||||
let iconCode = `${form.name}-${iconID}-${col1.val}-${col2.val}-${colG ? colG.val : "x"}-${colW ? colW.val : "x"}-${useGlow ? 1 : 0}`
|
extra = genImageName(isSpecial && '01', 'extra');
|
||||||
let cachable = !topless && !customSize && !psdExport
|
|
||||||
if (cachable && cache[iconCode]) return res.end(cache[iconCode].buffer)
|
|
||||||
|
|
||||||
// default to 1 if icon ID does not exist
|
|
||||||
if (!fs.existsSync(getPartName(1).slice(1))) { // slice 1 from filename since fs reads paths differently
|
|
||||||
iconID = 1
|
|
||||||
iconPath = getIconPath(1, form.form)
|
|
||||||
}
|
|
||||||
|
|
||||||
// get path of icon 'part' (1: primary, 2: secondary, 3: ufo top, extra: white, glow: glow, )
|
|
||||||
function getPartName(part, robotPart) {
|
|
||||||
let path = iconPath
|
|
||||||
if (form.legs) path += `_0${robotPart || 1}`
|
|
||||||
if (!part || part == "1") return `${path}_001.png`
|
|
||||||
else return `${path}_${part}_001.png`
|
|
||||||
}
|
|
||||||
|
|
||||||
// recolor white parts of icon to specified color
|
|
||||||
async function recolor(img, col) {
|
|
||||||
let rawData = await img.raw().toBuffer({resolveWithObject: true})
|
|
||||||
for (let i=0; i<rawData.data.length; i += 4) { // [R, G, B, A]
|
|
||||||
if (rawData.data[i + 3] > 0) {
|
|
||||||
rawData.data[i] = col.r / (255 / rawData.data[i]);
|
|
||||||
rawData.data[i + 1] = col.g / (255 / rawData.data[i + 1]);
|
|
||||||
rawData.data[i + 2] = col.b / (255 / rawData.data[i + 2]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return sharp(rawData.data, {raw: {width: rawData.info.width, height: rawData.info.height, channels: 4, background: TRANSPARENT}}).png()
|
let isSpecial = ['robot', 'spider'].includes(form);
|
||||||
}
|
setBaseIcons();
|
||||||
|
|
||||||
// color icon part and add to layer list
|
if (!fs.existsSync(fromIcons(icon)) || (isSpecial && !fs.existsSync(fromIcons(genImageName('02'))))) {
|
||||||
async function addLayer(part, color, legSection) {
|
iconID = '01';
|
||||||
|
setBaseIcons();
|
||||||
let leg = legSection ? legSection.leg : null
|
|
||||||
|
|
||||||
let partName = getPartName(part, leg)
|
|
||||||
let offsetData = icons[partName.slice(mainPath.length)]
|
|
||||||
let { spriteSize, spriteOffset } = offsetData
|
|
||||||
|
|
||||||
let builtPart = sharp(partName.slice(1)) // slice 1 from filename since sharp also reads paths differently
|
|
||||||
if (color) builtPart = await recolor(builtPart, color)
|
|
||||||
|
|
||||||
let left = halfCanvas - Math.floor(spriteSize[0] / 2) + spriteOffset[0]
|
|
||||||
let top = halfCanvas - Math.floor(spriteSize[1] / 2) - spriteOffset[1]
|
|
||||||
|
|
||||||
if (legSection) {
|
|
||||||
left += Math.floor(legSection.xPos)
|
|
||||||
top -= Math.floor(legSection.yPos)
|
|
||||||
// if (legSection.darken) builtPart.tint({r: 100, g: 100, b: 100})
|
|
||||||
if (legSection.rotation) {
|
|
||||||
builtPart.rotate(legSection.rotation, {background: TRANSPARENT})
|
|
||||||
if (part == "glow") { left--; top--; }
|
|
||||||
}
|
|
||||||
if (legSection.yScale) builtPart.resize({width: spriteSize[0], height: Math.floor(spriteSize[1] * legSection.yScale), fit: "fill"})
|
|
||||||
if (legSection.xFlip) builtPart.flop()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let layerData = {
|
let ex = fromIcons(extra)
|
||||||
partName, spriteOffset, spriteSize, leg,
|
let hasExtra = fs.existsSync(ex)
|
||||||
layerName: partNames[part],
|
|
||||||
behind: legSection && legSection.darken,
|
|
||||||
isGlow: part == "glow",
|
|
||||||
input: await builtPart.toBuffer(),
|
|
||||||
left, top
|
|
||||||
}
|
|
||||||
|
|
||||||
if (legSection) {
|
let cols = [col1, col2, colG, colW]
|
||||||
if (!legLayers[legSection.leg]) legLayers[legSection.leg] = [layerData]
|
cols.forEach(col => {
|
||||||
else legLayers[legSection.leg].push(layerData)
|
if (!col) return
|
||||||
}
|
col = col.toString()
|
||||||
|
if (col.match(hexRegex)) colors[col.toLowerCase()] = hexConvert(col)
|
||||||
else layers.push(layerData)
|
|
||||||
}
|
|
||||||
|
|
||||||
// build all layers of icon segment (col1, col2, glow, extra)
|
|
||||||
async function buildFullLayer(legSection) {
|
|
||||||
let hasExtra = fs.existsSync(getPartName("extra", legSection ? legSection.leg : null).slice(1))
|
|
||||||
|
|
||||||
if (form.form == "bird" && !topless) await addLayer(3, null, legSection) // ufo top
|
|
||||||
await addLayer(2, col2, legSection) // secondary color
|
|
||||||
if (useGlow) await addLayer("glow", glowColor, legSection) // glow
|
|
||||||
await addLayer(1, col1, legSection) // primary color
|
|
||||||
if (hasExtra) await addLayer("extra", colW, legSection) // extra
|
|
||||||
|
|
||||||
// if (legSection) {
|
|
||||||
// let foundLeg = legLayers[legSection.leg]
|
|
||||||
// foundLeg.forEach(x => layers.push(x))
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
let layers = []
|
|
||||||
let legLayers = []
|
|
||||||
let legData = form.legs ? legOffsets[form.form] || [] : []
|
|
||||||
let parentSize = icons[getPartName(1).slice(mainPath.length)].spriteSize
|
|
||||||
let canvas = sharp({create: {width: canvasSize, height: canvasSize, channels: 4, background: TRANSPARENT}})
|
|
||||||
|
|
||||||
// if (legData.length) {
|
|
||||||
// for (let i=0; i<legData.length; i++) {
|
|
||||||
// await buildFullLayer(legData[i])
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
await buildFullLayer()
|
|
||||||
|
|
||||||
// if (legData.length) layers = legLayers.flat().filter(x => x).sort((a, b) => !!b.behind - !!a.behind).sort((a, b) => !!b.isGlow - !!a.isGlow)
|
|
||||||
|
|
||||||
canvas.composite(layers)
|
|
||||||
|
|
||||||
let rawData = await canvas.toBuffer({resolveWithObject: true})
|
|
||||||
let minX = canvasSize; let maxX = 0;
|
|
||||||
let minY = canvasSize; let maxY = 0;
|
|
||||||
for (let i=0; i<rawData.data.length; i += 4) { // [R, G, B, A]
|
|
||||||
let pixelIndex = i/4
|
|
||||||
let x = pixelIndex % canvasSize;
|
|
||||||
let y = Math.floor(pixelIndex / canvasSize);
|
|
||||||
let alpha = rawData.data[i + 3];
|
|
||||||
if (alpha > 0) {
|
|
||||||
if (x < minX) minX = x
|
|
||||||
if (x > maxX) maxX = x
|
|
||||||
if (y < minY) minY = y
|
|
||||||
if (y > maxY) maxY = y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// need to make a new sharp instance so everything is merged. bit hacky but it works
|
|
||||||
let dimensions = [maxX - minX, maxY - minY]
|
|
||||||
|
|
||||||
if (!psdExport) {
|
|
||||||
let finalIcon = sharp(rawData.data, {raw: {width: canvasSize, height: canvasSize, channels: 4}})
|
|
||||||
.extract({left: minX, top: minY, width: dimensions[0], height: dimensions[1]})
|
|
||||||
|
|
||||||
if (customSize) {
|
|
||||||
let isThicc = dimensions[0] > dimensions[1]
|
|
||||||
let squareSize = req.query.size == "auto" ? (isThicc ? dimensions[0] : dimensions[1]) : Math.floor(req.query.size)
|
|
||||||
if (squareSize < 32) squareSize = 32
|
|
||||||
if (squareSize > 256) squareSize = 256
|
|
||||||
|
|
||||||
// use longest side to make square
|
|
||||||
if (isThicc) finalIcon.resize({
|
|
||||||
width: dimensions[isThicc ? 0 : 1],
|
|
||||||
height: dimensions[isThicc ? 0 : 1],
|
|
||||||
fit: "contain",
|
|
||||||
background: TRANSPARENT
|
|
||||||
})
|
|
||||||
finalIcon.resize({width: squareSize, height: squareSize, fit: "contain", background: TRANSPARENT})
|
|
||||||
}
|
|
||||||
finalIcon.png().toBuffer().then(x => {
|
|
||||||
res.end(x) // send file
|
|
||||||
if (cachable) { // cache for a bit
|
|
||||||
cache[iconCode] = { buffer: x, timeoutID: setTimeout(function() {delete cache[iconCode]}, 10000000) } // cache file for 3 hours
|
|
||||||
if (userCode) cache[userCode] = { buffer: x, timeoutID: setTimeout(function() {delete cache[userCode]}, 300000) } // 5 min cache for player icons
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
let psdLayers = layers.map(x => {
|
|
||||||
let Image = Canvas.Image
|
|
||||||
let canvas = Canvas.createCanvas(...dimensions)
|
|
||||||
let ctx = canvas.getContext('2d');
|
|
||||||
const img = new Image()
|
|
||||||
img.onload = () => {
|
|
||||||
ctx.drawImage(img, 0 + x.left - minX, 0 + x.top - minY)
|
|
||||||
}
|
|
||||||
img.onerror = err => { throw err }
|
|
||||||
img.src = x.input
|
|
||||||
return {name: x.layerName, canvas, leg: x.leg}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (form.legs) {
|
if (!colors[col1] || isNaN(colors[col1].r)) col1 = colors[+col1] ? +col1 : 0
|
||||||
let legLayers = []
|
if (!colors[col2] || isNaN(colors[col2].r)) col2 = colors[+col2] ? +col2 : 3
|
||||||
for (let i=1; i<=form.legs + 1; i++) legLayers.push({name: i == 1 ? "Base" : `Leg ${i}`, opened: true, children: []})
|
if (!colors[colG] || isNaN(colors[colG].r)) colG = colors[+colG] ? +colG : null
|
||||||
psdLayers.forEach(x => {
|
if (!colors[colW] || isNaN(colors[colW].r)) colW = colors[+colW] ? +colW : null
|
||||||
legLayers[x.leg-1].children.push(x)
|
if (colW && (!hasExtra || colW == 12)) colW = null
|
||||||
})
|
|
||||||
psdLayers = legLayers.reverse()
|
if (col1 == 15 || col1 === "000000") outline = true;
|
||||||
|
|
||||||
|
let iconCode = `${req.query.form == "cursed" ? "cursed" : form}${topless ? "top" : ""}-${iconID}-${col1}-${col2}-${colG || "x"}-${colW || "x"}-${outline ? 1 : 0}`
|
||||||
|
|
||||||
|
if (!sizeParam && (!isSpecial || drawLegs) && cache[iconCode]) return res.end(cache[iconCode].value)
|
||||||
|
|
||||||
|
let useExtra = false
|
||||||
|
let originalOffset = icons[icon].spriteOffset;
|
||||||
|
let minusOrigOffset = function(x, y) { return x - originalOffset[y] }
|
||||||
|
let offset = icons[glow].spriteOffset.map(minusOrigOffset);
|
||||||
|
let robotLeg1, robotLeg2, robotLeg3, robotLeg3b, robotLeg2b, robotLeg1b, robotLeg1c;
|
||||||
|
let robotOffset1, robotOffset2, robotOffset3, robotOffset1b, robotOffset2b, robotOffset3b;
|
||||||
|
let robotGlow1, robotGlow2, robotGlow3, glowOffset
|
||||||
|
let ufoTop, ufoOffset, ufoCoords, ufoSprite
|
||||||
|
let extrabit, offset2, size2;
|
||||||
|
|
||||||
|
if (isSpecial) {
|
||||||
|
const legs = [1,2,3].map(function(val) {return genImageName(`0${val+1}`)});
|
||||||
|
const glows = [1,2,3].map(function(val) {return genImageName(`0${val+1}`, '2')});
|
||||||
|
robotOffset1 = icons[legs[0]].spriteOffset.map(minusOrigOffset).concat(icons[legs[0]].spriteSize);
|
||||||
|
robotOffset2 = icons[legs[1]].spriteOffset.map(minusOrigOffset).concat(icons[legs[1]].spriteSize);
|
||||||
|
robotOffset3 = icons[legs[2]].spriteOffset.map(minusOrigOffset).concat(icons[legs[2]].spriteSize);
|
||||||
|
|
||||||
|
robotOffset1b = icons[glows[0]].spriteOffset.map(minusOrigOffset).concat(icons[glows[0]].spriteSize);
|
||||||
|
robotOffset2b = icons[glows[1]].spriteOffset.map(minusOrigOffset).concat(icons[glows[1]].spriteSize);
|
||||||
|
robotOffset3b = icons[glows[2]].spriteOffset.map(minusOrigOffset).concat(icons[glows[2]].spriteSize);
|
||||||
|
|
||||||
|
robotLeg1 = new Jimp(fromIcons(legs[0])); robotGlow1 = new Jimp(fromIcons(glows[0]))
|
||||||
|
robotLeg2 = new Jimp(fromIcons(legs[1])); robotGlow2 = new Jimp(fromIcons(glows[1]))
|
||||||
|
robotLeg3 = new Jimp(fromIcons(legs[2])); robotGlow3 = new Jimp(fromIcons(glows[2]))
|
||||||
|
|
||||||
|
glowOffset = offsets[form][+iconID] || []
|
||||||
}
|
}
|
||||||
|
|
||||||
const photoshop = {
|
Jimp.read(fromIcons(glow)).then(async function (image) {
|
||||||
width: dimensions[0],
|
|
||||||
height: dimensions[1],
|
let size = [image.bitmap.width, image.bitmap.height]
|
||||||
children: psdLayers
|
let glow = recolor(image, col2)
|
||||||
};
|
let imgOff = isSpecial ? 100 : 0
|
||||||
|
|
||||||
const buffer = psd.writePsdBuffer(photoshop);
|
let eb = fromIcons(extra)
|
||||||
return res.end(buffer)
|
if (fs.existsSync(eb)) {
|
||||||
|
extrabit = icons[extra]
|
||||||
|
offset2 = extrabit.spriteOffset.map(minusOrigOffset);
|
||||||
|
size2 = extrabit.spriteSize;
|
||||||
|
extra = new Jimp(eb);
|
||||||
|
if (colW) await Jimp.read(eb).then(e => { extra = recolor(e, colW) })
|
||||||
|
useExtra = true
|
||||||
|
}
|
||||||
|
|
||||||
|
Jimp.read(fromIcons(icon)).then(async function (ic) {
|
||||||
|
|
||||||
|
let iconSize = [ic.bitmap.width, ic.bitmap.height]
|
||||||
|
recolor(ic, col1)
|
||||||
|
ic.composite(glow, (iconSize[0] / 2) - (size[0] / 2) + offset[0], (iconSize[1] / 2) - (size[1] / 2) - offset[1], { mode: Jimp.BLEND_DESTINATION_OVER })
|
||||||
|
|
||||||
|
if (form == "bird" && !topless) {
|
||||||
|
ufoTop = genImageName('3')
|
||||||
|
ufoOffset = icons[ufoTop].spriteOffset.map(minusOrigOffset).concat(icons[ufoTop].spriteSize);
|
||||||
|
ufoCoords = [imgOff + (iconSize[0] / 2) - (ufoOffset[2] / 2) + ufoOffset[0], (iconSize[1] / 2) - (ufoOffset[3] / 2) - ufoOffset[1] + 300 - iconSize[1]]
|
||||||
|
ufoSprite = fromIcons(ufoTop)
|
||||||
|
ic.contain(iconSize[0], 300, Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_BOTTOM)
|
||||||
|
// Only add dome if there's no glow, otherwise the dome will be outlined as well
|
||||||
|
if (!outline) ic.composite(await Jimp.read(ufoSprite), ufoCoords[0], ufoCoords[1], {mode: Jimp.BLEND_DESTINATION_OVER})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drawLegs && (form == "robot" || req.query.form == "cursed")) {
|
||||||
|
|
||||||
|
ic.contain(iconSize[0], 300, Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_TOP)
|
||||||
|
ic.contain(iconSize[0] + 200, 300, Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_TOP)
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotGlow1)).then(rob => {
|
||||||
|
rob.rotate(-45)
|
||||||
|
robotGlow1 = recolor(rob, col2)
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotGlow2)).then(rob => {
|
||||||
|
rob.rotate(45)
|
||||||
|
robotGlow2 = recolor(rob, col2)
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotGlow3)).then(rob => {
|
||||||
|
robotGlow3 = recolor(rob, col2)
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotLeg1)).then(rob => {
|
||||||
|
rob.rotate(-45)
|
||||||
|
recolor(rob, col1)
|
||||||
|
rob.composite(robotGlow1, (robotOffset1[2] - robotOffset1b[2]) + (glowOffset[0] || 1), ((robotOffset1[3] - robotOffset1b[3]) / 2) + (glowOffset[1] || 0), { mode: Jimp.BLEND_DESTINATION_OVER })
|
||||||
|
robotLeg1 = rob
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotLeg2)).then(rob => {
|
||||||
|
rob.rotate(45)
|
||||||
|
recolor(rob, col1)
|
||||||
|
rob.composite(robotGlow2, ((robotOffset2[2] - robotOffset2b[2]) / 4) + (glowOffset[4] || 0), ((robotOffset2[3] - robotOffset2b[3]) / 2) + (glowOffset[5] || 0), { mode: Jimp.BLEND_DESTINATION_OVER })
|
||||||
|
robotLeg2 = rob
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotLeg2)).then(rob => {
|
||||||
|
robotLeg2b = rob.color([{ apply: 'darken', params: [20] }]).rotate(-5)
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotLeg3)).then(rob => {
|
||||||
|
recolor(rob, col1)
|
||||||
|
rob.composite(robotGlow3, ((robotOffset3[2] - robotOffset3b[2]) / 2) + (glowOffset[2] || 0), ((robotOffset3[3] - robotOffset3b[3]) / 2) + (glowOffset[3] || 0), { mode: Jimp.BLEND_DESTINATION_OVER })
|
||||||
|
robotLeg3 = rob
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotLeg3)).then(rob => {
|
||||||
|
robotLeg3b = rob.color([{ apply: 'darken', params: [10] }])
|
||||||
|
})
|
||||||
|
|
||||||
|
ic.composite(robotLeg2b, 100 + (iconSize[0] / 2) - (robotOffset2[2]) + robotOffset2[0] - 31, (iconSize[1] / 2) - (robotOffset2[3]) - robotOffset2[1] + 73)
|
||||||
|
ic.composite(robotLeg3b, 100 + (iconSize[0] / 2) - (robotOffset3[2]) + robotOffset3[0] + 20, (iconSize[1] / 2) - (robotOffset3[3]) - robotOffset3[1] + 78)
|
||||||
|
ic.composite(robotLeg2, 100 + (iconSize[0] / 2) - (robotOffset2[2]) + robotOffset2[0] - 20, (iconSize[1] / 2) - (robotOffset2[3]) - robotOffset2[1] + 73)
|
||||||
|
ic.composite(robotLeg3, 100 + (iconSize[0] / 2) - (robotOffset3[2]) + robotOffset3[0] + 40, (iconSize[1] / 2) - (robotOffset3[3]) - robotOffset3[1] + 78)
|
||||||
|
ic.composite(robotLeg1, 100 + (iconSize[0] / 2) - (robotOffset1[2]) + robotOffset1[0] - 20, (iconSize[1] / 2) - (robotOffset1[3]) - robotOffset1[1] + 50)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (drawLegs && form == "spider") {
|
||||||
|
|
||||||
|
let spiderBody;
|
||||||
|
ic.contain(iconSize[0], 300, Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_TOP)
|
||||||
|
ic.contain(iconSize[0] + 200, 300, Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_TOP)
|
||||||
|
|
||||||
|
if (iconID == "07") {
|
||||||
|
robotOffset2[2] -= 10
|
||||||
|
robotOffset2[1] += 12
|
||||||
|
robotOffset1b[3] -= 105
|
||||||
|
robotOffset2b[3] -= 150
|
||||||
|
robotOffset2b[2] -= 60
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iconID == "16") {
|
||||||
|
robotOffset1b[3] -= 100
|
||||||
|
robotOffset2b[3] -= 200
|
||||||
|
robotOffset2b[2] -= 30
|
||||||
|
}
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotGlow1)).then(rob => {
|
||||||
|
if (robotGlow1.bitmap.width < 10) robotGlow1.opacity(0)
|
||||||
|
else robotGlow1 = recolor(rob, col2)
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotGlow2)).then(rob => {
|
||||||
|
robotGlow2 = recolor(rob, col2)
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotGlow3)).then(rob => {
|
||||||
|
robotGlow3 = recolor(rob, col2)
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotLeg1)).then(rob => {
|
||||||
|
recolor(rob, col1)
|
||||||
|
rob.composite(robotGlow1, ((robotOffset1[2] - robotOffset1b[2]) / 2) + (glowOffset[2] || 0), ((robotOffset1[3] - robotOffset1b[3]) / 4) + (glowOffset[3] || 0), { mode: Jimp.BLEND_DESTINATION_OVER })
|
||||||
|
robotLeg1 = rob
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotLeg2)).then(rob => {
|
||||||
|
recolor(rob, col1)
|
||||||
|
rob.composite(robotGlow2, ((robotOffset2[2] - robotOffset2b[2]) / 6) + (glowOffset[0] || 0), ((robotOffset2[3] - robotOffset2b[3]) / 6) + (glowOffset[1] || 0), { mode: Jimp.BLEND_DESTINATION_OVER })
|
||||||
|
rob.rotate(-40)
|
||||||
|
robotLeg2 = rob
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotLeg1)).then(rob => {
|
||||||
|
robotLeg1b = rob.color([{ apply: 'darken', params: [20] }])
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotLeg1b)).then(rob => {
|
||||||
|
robotLeg1c = rob.mirror(true, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(robotLeg3)).then(rob => {
|
||||||
|
recolor(rob, col1)
|
||||||
|
rob.composite(robotGlow3, ((robotOffset3[2] - robotOffset3b[2]) / 2) + (glowOffset[4] || 0), ((robotOffset3[3] - robotOffset3b[3]) / 2) + (glowOffset[5] || 0), { mode: Jimp.BLEND_DESTINATION_OVER })
|
||||||
|
robotLeg3 = rob
|
||||||
|
})
|
||||||
|
|
||||||
|
await Jimp.read(new Jimp(ic)).then(rob => {
|
||||||
|
spiderBody = rob
|
||||||
|
})
|
||||||
|
|
||||||
|
ic.composite(robotLeg3, 100 + (iconSize[0] / 2) - (robotOffset3[2]) + (robotOffset3[0]), (iconSize[1] / 2) - (robotOffset2[3]) - robotOffset2[1] + 77)
|
||||||
|
ic.composite(robotLeg1b, 100 + (iconSize[0] / 2) - (robotOffset1[2]) + robotOffset1[0] + 35, (iconSize[1] / 2) - (robotOffset1[3]) - robotOffset1[1] + 70)
|
||||||
|
ic.composite(robotLeg1c, 100 + (iconSize[0] / 2) - (robotOffset1[2]) + robotOffset1[0] + 75, (iconSize[1] / 2) - (robotOffset1[3]) - robotOffset1[1] + 70)
|
||||||
|
// ^ BELOW
|
||||||
|
ic.composite(spiderBody, 0, 0)
|
||||||
|
// v ABOVE
|
||||||
|
ic.composite(robotLeg2, 100 + (iconSize[0] / 2) - (robotOffset2[2]) + robotOffset2[0] - 60, (iconSize[1] / 2) - (robotOffset2[3]) - robotOffset2[1] + 75)
|
||||||
|
ic.composite(robotLeg1, 100 + (iconSize[0] / 2) - (robotOffset1[2]) + robotOffset1[0] + 7, (iconSize[1] / 2) - (robotOffset1[3]) - robotOffset1[1] + 70)
|
||||||
|
}
|
||||||
|
|
||||||
|
// every now and then jimp does a fucky wucky uwu and this line errors. seems to be an issue with the lib itself :v
|
||||||
|
try { if (useExtra) ic.composite(extra, imgOff + (iconSize[0] / 2) - (size2[0] / 2) + offset2[0], (iconSize[1] / 2) - (size2[1] / 2) - offset2[1] + (form == "bird" && !req.query.topless ? 300 - iconSize[1] : 0)) }
|
||||||
|
catch(e) {}
|
||||||
|
|
||||||
|
let finalSize = [ic.bitmap.width, ic.bitmap.height]
|
||||||
|
|
||||||
|
function finish(img) {
|
||||||
|
img.autocrop(0.01, false)
|
||||||
|
if (form == "swing") img.resize(120, 111)
|
||||||
|
if (img.bitmap.height == 300) ic.autocrop(1, false)
|
||||||
|
if (sizeParam) {
|
||||||
|
let thicc = img.bitmap.width > img.bitmap.height
|
||||||
|
let imgSize = req.query.size == "auto" ? (thicc ? img.bitmap.width : img.bitmap.height) : Math.round(req.query.size)
|
||||||
|
if (imgSize < 32) imgSize = 32
|
||||||
|
if (imgSize > 512) imgSize = 512
|
||||||
|
if (thicc) img.contain(img.bitmap.width, img.bitmap.width, Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_MIDDLE)
|
||||||
|
else img.contain(img.bitmap.height, img.bitmap.height, Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_MIDDLE)
|
||||||
|
img.resize(imgSize, Jimp.AUTO)
|
||||||
|
}
|
||||||
|
img.getBuffer(Jimp.AUTO, (err, buffer) => {
|
||||||
|
if (!sizeParam && drawLegs) {
|
||||||
|
cache[iconCode] = { value: buffer, timeoutID: setTimeout(function() {delete cache[iconCode]}, 10000000) } // 3 hour cache
|
||||||
|
if (usercode) cache[usercode] = { value: buffer, timeoutID: setTimeout(function() {delete cache[usercode]}, 300000) } // 5 min cache for player icons
|
||||||
|
}
|
||||||
|
return res.end(buffer, 'base64')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outline) return finish(ic)
|
||||||
|
|
||||||
|
else {
|
||||||
|
|
||||||
|
ic.getBuffer(Jimp.AUTO, function (err, buff) {
|
||||||
|
|
||||||
|
const Canvas = require('canvas')
|
||||||
|
, Image = Canvas.Image
|
||||||
|
, canvas = Canvas.createCanvas(finalSize[0] + 10, finalSize[1] + 10)
|
||||||
|
, ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
if (!colG) colG = (col2 == 15 || col2 == "000000" ? col1 : col2)
|
||||||
|
if (colG == 15 || colG == "000000") colG = 12
|
||||||
|
|
||||||
|
const img = new Image()
|
||||||
|
img.onload = () => {
|
||||||
|
var dArr = [-1, -1, 0, -1, 1, -1, -1, 0, 1, 0, -1, 1, 0, 1, 1, 1], // offset array
|
||||||
|
s = 2, i = 0, x = canvas.width / 2 - finalSize[0] / 2, y = canvas.height / 2 - finalSize[1] / 2;
|
||||||
|
|
||||||
|
for (; i < dArr.length; i += 2) ctx.drawImage(img, x + dArr[i] * s, y + dArr[i + 1] * s);
|
||||||
|
|
||||||
|
ctx.globalCompositeOperation = "source-in";
|
||||||
|
ctx.fillStyle = `rgba(${colors[colG].r}, ${colors[colG].g}, ${colors[colG].b}, 1})`;
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.globalCompositeOperation = "source-over";
|
||||||
|
ctx.imageSmoothingEnabled = false;
|
||||||
|
|
||||||
|
// Add UFO top last so it doesn't get glow'd
|
||||||
|
if (form == "bird" && !topless) {
|
||||||
|
const dome = new Image()
|
||||||
|
dome.src = ufoSprite
|
||||||
|
ctx.drawImage(dome, ufoCoords[0]+5, ufoCoords[1]+5)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.drawImage(img, x, y)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
img.onerror = err => { throw err }
|
||||||
|
img.src = buff
|
||||||
|
|
||||||
|
Jimp.read(canvas.toBuffer()).then(b => {
|
||||||
|
return finish(b)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let username = req.params.text
|
||||||
|
let userCode;
|
||||||
|
res.contentType('image/png');
|
||||||
|
|
||||||
// ==================================== //
|
if (req.offline || req.query.hasOwnProperty("noUser") || req.query.hasOwnProperty("nouser") || username == "icon") return buildIcon()
|
||||||
|
|
||||||
// OLD CODE IS BEING USED FOR ROBOTS AND SPIDERS
|
else if (app.config.cachePlayerIcons && !Object.keys(req.query).filter(x => !["form", "forceGD"].includes(x)).length) {
|
||||||
let formCheck = forms[req.query.form]
|
userCode = `${req.id}u-${username.toLowerCase()}-${forms[req.query.form] ? req.query.form : 'cube'}`
|
||||||
if (formCheck && formCheck.legs) return app.run.icon_old(app, req, res)
|
if (cache[userCode]) return res.end(cache[userCode].value)
|
||||||
|
}
|
||||||
|
|
||||||
let username = req.params.text
|
let accountMode = !req.query.hasOwnProperty("player") && Number(req.params.id)
|
||||||
let userCode;
|
let foundID = app.userCache(req.id, username)
|
||||||
res.contentType('image/png');
|
let skipRequest = accountMode || foundID
|
||||||
|
let forceGD = req.query.hasOwnProperty("forceGD")
|
||||||
|
|
||||||
if (req.offline || req.query.hasOwnProperty("noUser") || req.query.hasOwnProperty("nouser") || username == "icon") return buildIcon()
|
// skip request by causing fake error lmao
|
||||||
|
req.gdRequest(skipRequest ? "" : 'getGJUsers20', skipRequest ? {} : req.gdParams({ str: username, forceGD }, !forceGD), function (err1, res1, body1) {
|
||||||
|
|
||||||
else if (app.config.cachePlayerIcons && !Object.keys(req.query).filter(x => !["form", "forceGD"].includes(x)).length) {
|
let result = foundID ? foundID[0] : (accountMode || err1) ? username : app.parseResponse(body1)[16];
|
||||||
userCode = `${req.id}u-${username.toLowerCase()}-${forms[req.query.form] ? req.query.form : 'cube'}`
|
|
||||||
if (cache[userCode]) return res.end(cache[userCode].value)
|
|
||||||
}
|
|
||||||
|
|
||||||
let accountMode = !req.query.hasOwnProperty("player") && Number(req.params.id)
|
req.gdRequest('getGJUserInfo20', req.gdParams({ targetAccountID: result, forceGD }, !forceGD), function (err2, res2, body2) {
|
||||||
let foundID = app.userCache(req.id, username)
|
|
||||||
let skipRequest = accountMode || foundID
|
|
||||||
let forceGD = req.query.hasOwnProperty("forceGD")
|
|
||||||
|
|
||||||
// skip request by causing fake error lmao
|
if (err2) return buildIcon();
|
||||||
req.gdRequest(skipRequest ? "" : 'getGJUsers20', skipRequest ? {} : req.gdParams({ str: username, forceGD }, !forceGD), function (err1, res1, body1) {
|
let iconData = app.parseResponse(body2)
|
||||||
|
if (!foundID && !forceGD) app.userCache(req.id, iconData[16], iconData[2], iconData[1])
|
||||||
|
return buildIcon(iconData, userCode);
|
||||||
|
|
||||||
let result = foundID ? foundID[0] : (accountMode || err1) ? username : app.parseResponse(body1)[16];
|
})
|
||||||
|
});
|
||||||
req.gdRequest('getGJUserInfo20', req.gdParams({ targetAccountID: result, forceGD }, !forceGD), function (err2, res2, body2) {
|
|
||||||
|
|
||||||
if (err2) return buildIcon();
|
|
||||||
let iconData = app.parseResponse(body2)
|
|
||||||
if (!foundID && !forceGD) app.userCache(req.id, iconData[16], iconData[2], iconData[1])
|
|
||||||
return buildIcon(iconData, userCode);
|
|
||||||
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -9,8 +9,9 @@ let caches = [{"stars": null, "coins": null, "demons": null, "diamonds": null},
|
||||||
|
|
||||||
module.exports = async (app, req, res, post) => {
|
module.exports = async (app, req, res, post) => {
|
||||||
|
|
||||||
if (req.isGDPS) return res.send("-2")
|
// Accurate leaderboard returns 418 because private servers do not use.
|
||||||
if (!app.sheetsKey) return res.send([])
|
if (req.isGDPS) return res.status(418).send("-2")
|
||||||
|
if (!app.sheetsKey) return res.status(500).send([])
|
||||||
let gdMode = post || req.query.hasOwnProperty("gd")
|
let gdMode = post || req.query.hasOwnProperty("gd")
|
||||||
let modMode = !gdMode && req.query.hasOwnProperty("mod")
|
let modMode = !gdMode && req.query.hasOwnProperty("mod")
|
||||||
let cache = caches[gdMode ? 2 : modMode ? 1 : 0]
|
let cache = caches[gdMode ? 2 : modMode ? 1 : 0]
|
||||||
|
@ -18,7 +19,7 @@ module.exports = async (app, req, res, post) => {
|
||||||
let type = req.query.type ? req.query.type.toLowerCase() : 'stars'
|
let type = req.query.type ? req.query.type.toLowerCase() : 'stars'
|
||||||
if (type == "usercoins") type = "coins"
|
if (type == "usercoins") type = "coins"
|
||||||
if (!indexes.includes(type)) type = "stars"
|
if (!indexes.includes(type)) type = "stars"
|
||||||
if (lastIndex[modMode ? 1 : 0][type] + 600000 > Date.now() && cache[type]) return res.send(gdMode ? cache[type] : JSON.parse(cache[type])) // 10 min cache
|
if (lastIndex[modMode ? 1 : 0][type] + 600000 > Date.now() && cache[type]) return res.status(200).send(gdMode ? cache[type] : JSON.parse(cache[type])) // 10 min cache
|
||||||
|
|
||||||
sheet.useApiKey(app.sheetsKey)
|
sheet.useApiKey(app.sheetsKey)
|
||||||
sheet.loadInfo().then(async () => {
|
sheet.loadInfo().then(async () => {
|
||||||
|
@ -29,7 +30,7 @@ module.exports = async (app, req, res, post) => {
|
||||||
if (modMode) cellIndex += indexes.length
|
if (modMode) cellIndex += indexes.length
|
||||||
|
|
||||||
let cell = tab.getCell(1, cellIndex).value
|
let cell = tab.getCell(1, cellIndex).value
|
||||||
if (!cell || typeof cell != "string" || cell.startsWith("GoogleSpreadsheetFormulaError")) { console.log("Spreadsheet Error:"); console.log(cell); return res.send("-1") }
|
if (!cell || typeof cell != "string" || cell.startsWith("GoogleSpreadsheetFormulaError")) { console.log("Spreadsheet Error:"); console.log(cell); return res.status(500).send("-1") }
|
||||||
let leaderboard = JSON.parse(cell.replace(/~( |$)/g, ""))
|
let leaderboard = JSON.parse(cell.replace(/~( |$)/g, ""))
|
||||||
|
|
||||||
let gdFormatting = ""
|
let gdFormatting = ""
|
||||||
|
@ -40,7 +41,7 @@ module.exports = async (app, req, res, post) => {
|
||||||
caches[modMode ? 1 : 0][type] = JSON.stringify(leaderboard)
|
caches[modMode ? 1 : 0][type] = JSON.stringify(leaderboard)
|
||||||
caches[2][type] = gdFormatting
|
caches[2][type] = gdFormatting
|
||||||
lastIndex[modMode ? 1 : 0][type] = Date.now()
|
lastIndex[modMode ? 1 : 0][type] = Date.now()
|
||||||
return res.send(gdMode ? gdFormatting : leaderboard)
|
return res.status(200).send(gdMode ? gdFormatting : leaderboard)
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -2,12 +2,13 @@ const request = require('request')
|
||||||
|
|
||||||
module.exports = async (app, req, res) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
if (req.isGDPS) return res.send("0")
|
// Accurate leaderboard returns 418 because Private servers do not use.
|
||||||
|
if (req.isGDPS) return res.status(418).send("0")
|
||||||
|
|
||||||
request.post('http://robtopgames.com/Boomlings/get_scores.php', {
|
request.post('http://robtopgames.com/Boomlings/get_scores.php', {
|
||||||
form : { secret: app.config.params.secret || "Wmfd2893gb7", name: "Player" } }, function(err, resp, body) {
|
form : { secret: app.config.params.secret || "Wmfd2893gb7", name: "Player" } }, function(err, resp, body) {
|
||||||
|
|
||||||
if (err || !body || body == 0) return res.send("0")
|
if (err || !body || body == 0) return res.status(500).send("0")
|
||||||
|
|
||||||
let info = body.split(" ").filter(x => x.includes(";"))
|
let info = body.split(" ").filter(x => x.includes(";"))
|
||||||
let users = []
|
let users = []
|
||||||
|
@ -36,7 +37,7 @@ module.exports = async (app, req, res) => {
|
||||||
users.push(user)
|
users.push(user)
|
||||||
})
|
})
|
||||||
|
|
||||||
return res.send(users)
|
return res.status(200).send(users)
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
module.exports = async (app, req, res) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
if (req.offline) return res.send("-1")
|
if (req.offline) return res.status(500).send("-1")
|
||||||
|
|
||||||
let amount = 100;
|
let amount = 100;
|
||||||
let count = req.query.count ? parseInt(req.query.count) : null
|
let count = req.query.count ? parseInt(req.query.count) : null
|
||||||
|
@ -18,9 +18,9 @@ module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
req.gdRequest('getGJLevelScores211', params, function(err, resp, body) {
|
req.gdRequest('getGJLevelScores211', params, function(err, resp, body) {
|
||||||
|
|
||||||
if (err) return res.send({error: true, lastWorked: app.timeSince(req.id)})
|
if (err) return res.status(500).send({error: true, lastWorked: app.timeSince(req.id)})
|
||||||
scores = body.split('|').map(x => app.parseResponse(x)).filter(x => x[1])
|
scores = body.split('|').map(x => app.parseResponse(x)).filter(x => x[1])
|
||||||
if (!scores.length) return res.send([])
|
if (!scores.length) return res.status(500).send([])
|
||||||
else app.trackSuccess(req.id)
|
else app.trackSuccess(req.id)
|
||||||
|
|
||||||
scores.forEach(x => {
|
scores.forEach(x => {
|
||||||
|
@ -43,7 +43,7 @@ module.exports = async (app, req, res) => {
|
||||||
app.userCache(req.id, x.accountID, x.playerID, x.username)
|
app.userCache(req.id, x.accountID, x.playerID, x.username)
|
||||||
})
|
})
|
||||||
|
|
||||||
return res.send(scores.slice(0, amount))
|
return res.status(200).send(scores.slice(0, amount))
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
module.exports = async (app, req, res) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
if (req.offline) return res.send("-1")
|
if (req.offline) return res.status(500).send("-1")
|
||||||
|
|
||||||
let amount = 100;
|
let amount = 100;
|
||||||
let count = req.query.count ? parseInt(req.query.count) : null
|
let count = req.query.count ? parseInt(req.query.count) : null
|
||||||
|
@ -16,9 +16,9 @@ module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
req.gdRequest('getGJScores20', params, function(err, resp, body) {
|
req.gdRequest('getGJScores20', params, function(err, resp, body) {
|
||||||
|
|
||||||
if (err) return res.send("-1")
|
if (err) return res.status(500).send("-1")
|
||||||
scores = body.split('|').map(x => app.parseResponse(x)).filter(x => x[1])
|
scores = body.split('|').map(x => app.parseResponse(x)).filter(x => x[1])
|
||||||
if (!scores.length) return res.send("-1")
|
if (!scores.length) return res.status(500).send("-1")
|
||||||
|
|
||||||
scores.forEach(x => {
|
scores.forEach(x => {
|
||||||
let keys = Object.keys(x)
|
let keys = Object.keys(x)
|
||||||
|
@ -42,6 +42,6 @@ module.exports = async (app, req, res) => {
|
||||||
keys.forEach(k => delete x[k])
|
keys.forEach(k => delete x[k])
|
||||||
app.userCache(req.id, x.accountID, x.playerID, x.username)
|
app.userCache(req.id, x.accountID, x.playerID, x.username)
|
||||||
})
|
})
|
||||||
return res.send(scores)
|
return res.status(200).send(scores)
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -6,7 +6,7 @@ module.exports = async (app, req, res, api, analyze) => {
|
||||||
|
|
||||||
function rejectLevel() {
|
function rejectLevel() {
|
||||||
if (!api) return res.redirect('search/' + req.params.id)
|
if (!api) return res.redirect('search/' + req.params.id)
|
||||||
else return res.send("-1")
|
else return res.status(500).send("-1")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.offline) return rejectLevel()
|
if (req.offline) return rejectLevel()
|
||||||
|
@ -37,7 +37,7 @@ module.exports = async (app, req, res, api, analyze) => {
|
||||||
|
|
||||||
function sendLevel() {
|
function sendLevel() {
|
||||||
|
|
||||||
if (api) return res.send(level)
|
if (api) return res.status(200).send(level)
|
||||||
|
|
||||||
else return fs.readFile('./html/level.html', 'utf8', function (err, data) {
|
else return fs.readFile('./html/level.html', 'utf8', function (err, data) {
|
||||||
let html = data;
|
let html = data;
|
||||||
|
@ -50,7 +50,7 @@ module.exports = async (app, req, res, api, analyze) => {
|
||||||
})
|
})
|
||||||
if (req.server.downloadsDisabled) html = html.replace('id="additional" class="', 'id="additional" class="downloadDisabled ')
|
if (req.server.downloadsDisabled) html = html.replace('id="additional" class="', 'id="additional" class="downloadDisabled ')
|
||||||
.replace('analyzeBtn"', 'analyzeBtn" style="filter: opacity(30%)"')
|
.replace('analyzeBtn"', 'analyzeBtn" style="filter: opacity(30%)"')
|
||||||
return res.send(html)
|
return res.status(200).send(html)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,17 +3,17 @@ let cache = {}
|
||||||
|
|
||||||
module.exports = async (app, req, res) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
if (req.offline) return res.send("-1")
|
if (req.offline) return res.status(500).send("-1")
|
||||||
|
|
||||||
let cached = cache[req.id]
|
let cached = cache[req.id]
|
||||||
if (app.config.cacheMapPacks && cached && cached.data && cached.indexed + 5000000 > Date.now()) return res.send(cached.data) // 1.5 hour cache
|
if (app.config.cacheMapPacks && cached && cached.data && cached.indexed + 5000000 > Date.now()) return res.status(200).send(cached.data) // 1.5 hour cache
|
||||||
let params = { count: 250, page: 0 }
|
let params = { count: 250, page: 0 }
|
||||||
let packs = []
|
let packs = []
|
||||||
|
|
||||||
function mapPackLoop() {
|
function mapPackLoop() {
|
||||||
req.gdRequest('getGJMapPacks21', params, function (err, resp, body) {
|
req.gdRequest('getGJMapPacks21', params, function (err, resp, body) {
|
||||||
|
|
||||||
if (err) return res.send("-1")
|
if (err) return res.status(500).send("-1")
|
||||||
|
|
||||||
let newPacks = body.split('#')[0].split('|').map(x => app.parseResponse(x)).filter(x => x[2])
|
let newPacks = body.split('#')[0].split('|').map(x => app.parseResponse(x)).filter(x => x[2])
|
||||||
packs = packs.concat(newPacks)
|
packs = packs.concat(newPacks)
|
||||||
|
@ -36,7 +36,7 @@ module.exports = async (app, req, res) => {
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if (app.config.cacheMapPacks) cache[req.id] = {data: mappacks, indexed: Date.now()}
|
if (app.config.cacheMapPacks) cache[req.id] = {data: mappacks, indexed: Date.now()}
|
||||||
return res.send(mappacks)
|
return res.status(200).send(mappacks)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
mapPackLoop()
|
mapPackLoop()
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
module.exports = async (app, req, res) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
|
if (req.method !== 'POST') return res.status(405).send("Method not allowed.")
|
||||||
|
|
||||||
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
||||||
if (!req.body.password) return res.status(400).send("No password provided!")
|
if (!req.body.password) return res.status(400).send("No password provided!")
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
module.exports = async (app, req, res, api) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
|
if (req.method !== 'POST') return res.status(405).send("Method not allowed.")
|
||||||
|
|
||||||
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
||||||
if (!req.body.password) return res.status(400).send("No password provided!")
|
if (!req.body.password) return res.status(400).send("No password provided!")
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
module.exports = async (app, req, res, api) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
|
if (req.method !== 'POST') return res.status(405).send("Method not allowed.")
|
||||||
|
|
||||||
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
||||||
if (!req.body.password) return res.status(400).send("No password provided!")
|
if (!req.body.password) return res.status(400).send("No password provided!")
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
module.exports = async (app, req, res, api) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
|
if (req.method !== 'POST') return res.status(405).send("Method not allowed.")
|
||||||
|
|
||||||
if (req.body.count) return app.run.countMessages(app, req, res)
|
if (req.body.count) return app.run.countMessages(app, req, res)
|
||||||
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
module.exports = async (app, req, res, api) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
|
if (req.method !== 'POST') return res.status(405).send("Method not allowed.")
|
||||||
|
|
||||||
if (!req.body.targetID) return res.status(400).send("No target ID provided!")
|
if (!req.body.targetID) return res.status(400).send("No target ID provided!")
|
||||||
if (!req.body.message) return res.status(400).send("No message provided!")
|
if (!req.body.message) return res.status(400).send("No message provided!")
|
||||||
|
|
|
@ -3,6 +3,8 @@ function sha1(data) { return crypto.createHash("sha1").update(data, "binary").di
|
||||||
|
|
||||||
module.exports = async (app, req, res) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
|
if (req.method !== 'POST') return res.status(405).send("Method not allowed.")
|
||||||
|
|
||||||
if (!req.body.ID) return res.status(400).send("No ID provided!")
|
if (!req.body.ID) return res.status(400).send("No ID provided!")
|
||||||
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
||||||
if (!req.body.password) return res.status(400).send("No password provided!")
|
if (!req.body.password) return res.status(400).send("No password provided!")
|
||||||
|
|
|
@ -11,6 +11,8 @@ function getTime(time) {
|
||||||
|
|
||||||
module.exports = async (app, req, res) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
|
if (req.method !== 'POST') return res.status(405).send("Method not allowed.")
|
||||||
|
|
||||||
if (!req.body.comment) return res.status(400).send("No comment provided!")
|
if (!req.body.comment) return res.status(400).send("No comment provided!")
|
||||||
if (!req.body.username) return res.status(400).send("No username provided!")
|
if (!req.body.username) return res.status(400).send("No username provided!")
|
||||||
if (!req.body.levelID) return res.status(400).send("No level ID provided!")
|
if (!req.body.levelID) return res.status(400).send("No level ID provided!")
|
||||||
|
|
|
@ -3,6 +3,8 @@ function sha1(data) { return crypto.createHash("sha1").update(data, "binary").di
|
||||||
|
|
||||||
module.exports = async (app, req, res) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
|
if (req.method !== 'POST') return res.status(405).send("Method not allowed.")
|
||||||
|
|
||||||
if (!req.body.comment) return res.status(400).send("No comment provided!")
|
if (!req.body.comment) return res.status(400).send("No comment provided!")
|
||||||
if (!req.body.username) return res.status(400).send("No username provided!")
|
if (!req.body.username) return res.status(400).send("No username provided!")
|
||||||
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
if (!req.body.accountID) return res.status(400).send("No account ID provided!")
|
||||||
|
|
|
@ -4,7 +4,7 @@ module.exports = async (app, req, res, api, getLevels) => {
|
||||||
|
|
||||||
if (req.offline) {
|
if (req.offline) {
|
||||||
if (!api) return res.redirect('/search/' + req.params.id)
|
if (!api) return res.redirect('/search/' + req.params.id)
|
||||||
else return res.send("-1")
|
else return res.status(500).send("-1")
|
||||||
}
|
}
|
||||||
|
|
||||||
let username = getLevels || req.params.id
|
let username = getLevels || req.params.id
|
||||||
|
@ -42,7 +42,7 @@ module.exports = async (app, req, res, api, getLevels) => {
|
||||||
|
|
||||||
if (err2 || dumbGDPSError) {
|
if (err2 || dumbGDPSError) {
|
||||||
if (!api) return res.redirect('/search/' + req.params.id)
|
if (!api) return res.redirect('/search/' + req.params.id)
|
||||||
else return res.send("-1")
|
else return res.status(500).send("-1")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundID) app.userCache(req.id, account[16], account[2], account[1])
|
if (!foundID) app.userCache(req.id, account[16], account[2], account[1])
|
||||||
|
@ -78,7 +78,7 @@ module.exports = async (app, req, res, api, getLevels) => {
|
||||||
glow: account[28] == "1",
|
glow: account[28] == "1",
|
||||||
}
|
}
|
||||||
|
|
||||||
if (api) return res.send(userData)
|
if (api) return res.status(200).send(userData)
|
||||||
|
|
||||||
else fs.readFile('./html/profile.html', 'utf8', function(err, data) {
|
else fs.readFile('./html/profile.html', 'utf8', function(err, data) {
|
||||||
let html = data;
|
let html = data;
|
||||||
|
@ -87,7 +87,7 @@ module.exports = async (app, req, res, api, getLevels) => {
|
||||||
let regex = new RegExp(`\\[\\[${x.toUpperCase()}\\]\\]`, "g")
|
let regex = new RegExp(`\\[\\[${x.toUpperCase()}\\]\\]`, "g")
|
||||||
html = html.replace(regex, app.clean(userData[x]))
|
html = html.replace(regex, app.clean(userData[x]))
|
||||||
})
|
})
|
||||||
return res.send(html)
|
return res.status(200).send(html)
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,17 +5,17 @@ let demonList = {}
|
||||||
|
|
||||||
module.exports = async (app, req, res) => {
|
module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
if (req.offline) return res.send(req.query.hasOwnProperty("err") ? "err" : "-1")
|
if (req.offline) return res.status(500).send(req.query.hasOwnProperty("err") ? "err" : "-1")
|
||||||
|
|
||||||
let demonMode = req.query.hasOwnProperty("demonlist") || req.query.hasOwnProperty("demonList") || req.query.type == "demonlist" || req.query.type == "demonList"
|
let demonMode = req.query.hasOwnProperty("demonlist") || req.query.hasOwnProperty("demonList") || req.query.type == "demonlist" || req.query.type == "demonList"
|
||||||
if (demonMode) {
|
if (demonMode) {
|
||||||
if (!req.server.demonList) return res.send('-1')
|
if (!req.server.demonList) return res.status(400).send('-1')
|
||||||
let dList = demonList[req.id]
|
let dList = demonList[req.id]
|
||||||
if (!dList || !dList.list.length || dList.lastUpdated + 600000 < Date.now()) { // 10 minute cache
|
if (!dList || !dList.list.length || dList.lastUpdated + 600000 < Date.now()) { // 10 minute cache
|
||||||
return request.get(req.server.demonList + 'api/v2/demons/listed/?limit=100', function (err1, resp1, list1) {
|
return request.get(req.server.demonList + 'api/v2/demons/listed/?limit=100', function (err1, resp1, list1) {
|
||||||
if (err1) return res.send("-1")
|
if (err1) return res.status(500).send("-1")
|
||||||
else return request.get(req.server.demonList + 'api/v2/demons/listed/?limit=100&after=100', function (err2, resp2, list2) {
|
else return request.get(req.server.demonList + 'api/v2/demons/listed/?limit=100&after=100', function (err2, resp2, list2) {
|
||||||
if (err2) return res.send("-1")
|
if (err2) return res.status(500).send("-1")
|
||||||
demonList[req.id] = {list: JSON.parse(list1).concat(JSON.parse(list2)).map(x => String(x.level_id)), lastUpdated: Date.now()}
|
demonList[req.id] = {list: JSON.parse(list1).concat(JSON.parse(list2)).map(x => String(x.level_id)), lastUpdated: Date.now()}
|
||||||
return app.run.search(app, req, res)
|
return app.run.search(app, req, res)
|
||||||
})
|
})
|
||||||
|
@ -85,7 +85,7 @@ module.exports = async (app, req, res) => {
|
||||||
filters.str = demonMode ? demonList[req.id].list : filters.str.split(",")
|
filters.str = demonMode ? demonList[req.id].list : filters.str.split(",")
|
||||||
listSize = filters.str.length
|
listSize = filters.str.length
|
||||||
filters.str = filters.str.slice(filters.page*amount, filters.page*amount + amount)
|
filters.str = filters.str.slice(filters.page*amount, filters.page*amount + amount)
|
||||||
if (!filters.str.length) return res.send("-1")
|
if (!filters.str.length) return res.status(400).send("-1")
|
||||||
filters.str = filters.str.map(x => String(Number(x) + (+req.query.l || 0))).join()
|
filters.str = filters.str.map(x => String(Number(x) + (+req.query.l || 0))).join()
|
||||||
filters.page = 0
|
filters.page = 0
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
req.gdRequest('getGJLevels21', req.gdParams(filters), function(err, resp, body) {
|
req.gdRequest('getGJLevels21', req.gdParams(filters), function(err, resp, body) {
|
||||||
|
|
||||||
if (err) return res.send("-1")
|
if (err) return res.status(500).send("-1")
|
||||||
let splitBody = body.split('#')
|
let splitBody = body.split('#')
|
||||||
let preRes = splitBody[0].split('|')
|
let preRes = splitBody[0].split('|')
|
||||||
let authorList = {}
|
let authorList = {}
|
||||||
|
@ -154,7 +154,7 @@ module.exports = async (app, req, res) => {
|
||||||
})
|
})
|
||||||
|
|
||||||
if (filters.type == 10) parsedLevels = parsedLevels.slice((+filters.page) * amount, (+filters.page + 1) * amount)
|
if (filters.type == 10) parsedLevels = parsedLevels.slice((+filters.page) * amount, (+filters.page + 1) * amount)
|
||||||
return res.send(parsedLevels)
|
return res.status(200).send(parsedLevels)
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -4,14 +4,15 @@ module.exports = async (app, req, res) => {
|
||||||
|
|
||||||
// temporary solution until song api is re-enabled
|
// temporary solution until song api is re-enabled
|
||||||
|
|
||||||
if (req.offline) return res.send('-1')
|
if (req.offline) return res.status(500).send('-1')
|
||||||
|
|
||||||
let songID = req.params.song
|
let songID = req.params.song
|
||||||
req.gdRequest('getGJSongInfo', {songID: songID}, function(err, resp, body) {
|
req.gdRequest('getGJSongInfo', {songID: songID}, function(err, resp, body) {
|
||||||
if (err) return res.send('-1')
|
if (err) return res.status(400).send('-1')
|
||||||
else if (body < 0) return res.send(false)
|
else if (body < 0) return res.send(false)
|
||||||
request.get('https://www.newgrounds.com/audio/listen/' + songID, function(err2, resp2, song) {
|
request.get('https://www.newgrounds.com/audio/listen/' + songID, function(err2, resp2, song) {
|
||||||
return res.send(resp2.statusCode == 200)
|
console.log(resp2.statusCode)
|
||||||
|
return res.status(200).send(resp2.statusCode == 200)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
65
index.js
65
index.js
|
@ -184,8 +184,8 @@ app.clean = function(text) {if (!text || typeof text != "string") return text; e
|
||||||
app.use('/assets', express.static(__dirname + '/assets', {maxAge: "7d"}));
|
app.use('/assets', express.static(__dirname + '/assets', {maxAge: "7d"}));
|
||||||
app.use('/assets/css', express.static(__dirname + '/assets/css')); // override maxAge
|
app.use('/assets/css', express.static(__dirname + '/assets/css')); // override maxAge
|
||||||
|
|
||||||
app.get("/sizecheck.js", function(req, res) { res.sendFile(__dirname + "/misc/sizecheck.js") })
|
app.get("/sizecheck.js", function(req, res) { res.status(200).sendFile(__dirname + "/misc/sizecheck.js") })
|
||||||
app.get("/dragscroll.js", function(req, res) { res.sendFile(__dirname + "/misc/dragscroll.js") })
|
app.get("/dragscroll.js", function(req, res) { res.status(200).sendFile(__dirname + "/misc/dragscroll.js") })
|
||||||
|
|
||||||
app.get("/assets/:dir*?", function(req, res) {
|
app.get("/assets/:dir*?", function(req, res) {
|
||||||
let main = (req.params.dir || "").toLowerCase()
|
let main = (req.params.dir || "").toLowerCase()
|
||||||
|
@ -193,10 +193,10 @@ app.get("/assets/:dir*?", function(req, res) {
|
||||||
|
|
||||||
if (dir.includes('.') || !req.path.endsWith("/")) {
|
if (dir.includes('.') || !req.path.endsWith("/")) {
|
||||||
if (!req.params[0]) main = ""
|
if (!req.params[0]) main = ""
|
||||||
if (req.params.dir == "deatheffects" || req.params.dir == "trails") return res.sendFile(__dirname + "/assets/deatheffects/0.png")
|
if (req.params.dir == "deatheffects" || req.params.dir == "trails") return res.status(200).sendFile(__dirname + "/assets/deatheffects/0.png")
|
||||||
else if (req.params.dir == "gdps" && req.params[0].endsWith("_icon.png")) return res.sendFile(__dirname + "/assets/gdps/unknown_icon.png")
|
else if (req.params.dir == "gdps" && req.params[0].endsWith("_icon.png")) return res.status(200).sendFile(__dirname + "/assets/gdps/unknown_icon.png")
|
||||||
else if (req.params.dir == "gdps" && req.params[0].endsWith("_logo.png")) return res.sendFile(__dirname + "/assets/gdps/unknown_logo.png")
|
else if (req.params.dir == "gdps" && req.params[0].endsWith("_logo.png")) return res.status(200).sendFile(__dirname + "/assets/gdps/unknown_logo.png")
|
||||||
return res.send(`<p style="font-size: 20px; font-family: aller, helvetica, arial">Looks like this file doesn't exist ¯\\_(ツ)_/¯<br><a href='/assets/${main}'>View directory listing for <b>/assets/${main}</b></a></p>`)
|
return res.status(404).send(`<p style="font-size: 20px; font-family: aller, helvetica, arial">Looks like this file doesn't exist ¯\\_(ツ)_/¯<br><a href='/assets/${main}'>View directory listing for <b>/assets/${main}</b></a></p>`)
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = `./assets/${dir}`
|
let path = `./assets/${dir}`
|
||||||
|
@ -205,7 +205,7 @@ app.get("/assets/:dir*?", function(req, res) {
|
||||||
|
|
||||||
assetPage = fs.readFileSync('./html/assets.html', 'utf8')
|
assetPage = fs.readFileSync('./html/assets.html', 'utf8')
|
||||||
let assetData = JSON.stringify({files: files.filter(x => x.includes('.')), directories: files.filter(x => !x.includes('.'))})
|
let assetData = JSON.stringify({files: files.filter(x => x.includes('.')), directories: files.filter(x => !x.includes('.'))})
|
||||||
res.send(assetPage.replace('{NAME}', dir || "assets").replace('{DATA}', assetData))
|
res.status(200).send(assetPage.replace('{NAME}', dir || "assets").replace('{DATA}', assetData))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ let downloadDisabled = ['daily', 'weekly']
|
||||||
let gdpsHide = ['achievements', 'messages']
|
let gdpsHide = ['achievements', 'messages']
|
||||||
|
|
||||||
app.get("/", function(req, res) {
|
app.get("/", function(req, res) {
|
||||||
if (req.query.hasOwnProperty("offline") || (req.offline && !req.query.hasOwnProperty("home"))) res.sendFile(__dirname + "/html/offline.html")
|
if (req.query.hasOwnProperty("offline") || (req.offline && !req.query.hasOwnProperty("home"))) res.status(200).sendFile(__dirname + "/html/offline.html")
|
||||||
else {
|
else {
|
||||||
fs.readFile('./html/home.html', 'utf8', function (err, data) {
|
fs.readFile('./html/home.html', 'utf8', function (err, data) {
|
||||||
let html = data;
|
let html = data;
|
||||||
|
@ -249,26 +249,26 @@ app.get("/", function(req, res) {
|
||||||
html = html.replace('id="dl" style="display: none', 'style="display: block')
|
html = html.replace('id="dl" style="display: none', 'style="display: block')
|
||||||
.replace('No active <span id="noLevel">daily</span> level!', '[Blocked by RobTop]')
|
.replace('No active <span id="noLevel">daily</span> level!', '[Blocked by RobTop]')
|
||||||
}
|
}
|
||||||
return res.send(html)
|
return res.status(200).send(html)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get("/achievements", function(req, res) { res.sendFile(__dirname + "/html/achievements.html") })
|
app.get("/achievements", function(req, res) { res.status(200).sendFile(__dirname + "/html/achievements.html") })
|
||||||
app.get("/analyze/:id", function(req, res) { res.sendFile(__dirname + "/html/analyze.html") })
|
app.get("/analyze/:id", function(req, res) { res.status(200).sendFile(__dirname + "/html/analyze.html") })
|
||||||
app.get("/api", function(req, res) { res.sendFile(__dirname + "/html/api.html") })
|
app.get("/api", function(req, res) { res.status(200).sendFile(__dirname + "/html/api.html") })
|
||||||
app.get("/boomlings", function(req, res) { res.sendFile(__dirname + "/html/boomlings.html") })
|
app.get("/boomlings", function(req, res) { res.status(200).sendFile(__dirname + "/html/boomlings.html") })
|
||||||
app.get("/comments/:id", function(req, res) { res.sendFile(__dirname + "/html/comments.html") })
|
app.get("/comments/:id", function(req, res) { res.status(200).sendFile(__dirname + "/html/comments.html") })
|
||||||
app.get("/demon/:id", function(req, res) { res.sendFile(__dirname + "/html/demon.html") })
|
app.get("/demon/:id", function(req, res) { res.status(200).sendFile(__dirname + "/html/demon.html") })
|
||||||
app.get("/gauntlets", function(req, res) { res.sendFile(__dirname + "/html/gauntlets.html") })
|
app.get("/gauntlets", function(req, res) { res.status(200).sendFile(__dirname + "/html/gauntlets.html") })
|
||||||
app.get("/gdps", function(req, res) { res.sendFile(__dirname + "/html/gdps.html") })
|
app.get("/gdps", function(req, res) { res.status(200).sendFile(__dirname + "/html/gdps.html") })
|
||||||
app.get("/iconkit", function(req, res) { res.sendFile(__dirname + "/html/iconkit.html") })
|
app.get("/iconkit", function(req, res) { res.status(200).sendFile(__dirname + "/html/iconkit.html") })
|
||||||
app.get("/leaderboard", function(req, res) { res.sendFile(__dirname + "/html/leaderboard.html") })
|
app.get("/leaderboard", function(req, res) { res.status(200).sendFile(__dirname + "/html/leaderboard.html") })
|
||||||
app.get("/leaderboard/:text", function(req, res) { res.sendFile(__dirname + "/html/levelboard.html") })
|
app.get("/leaderboard/:text", function(req, res) { res.status(200).sendFile(__dirname + "/html/levelboard.html") })
|
||||||
app.get("/mappacks", function(req, res) { res.sendFile(__dirname + "/html/mappacks.html") })
|
app.get("/mappacks", function(req, res) { res.status(200).sendFile(__dirname + "/html/mappacks.html") })
|
||||||
app.get("/messages", function(req, res) { res.sendFile(__dirname + "/html/messages.html") })
|
app.get("/messages", function(req, res) { res.status(200).sendFile(__dirname + "/html/messages.html") })
|
||||||
app.get("/search", function(req, res) { res.sendFile(__dirname + "/html/filters.html") })
|
app.get("/search", function(req, res) { res.status(200).sendFile(__dirname + "/html/filters.html") })
|
||||||
app.get("/search/:text", function(req, res) { res.sendFile(__dirname + "/html/search.html") })
|
app.get("/search/:text", function(req, res) { res.status(200).sendFile(__dirname + "/html/search.html") })
|
||||||
|
|
||||||
|
|
||||||
// API
|
// API
|
||||||
|
@ -276,7 +276,7 @@ app.get("/search/:text", function(req, res) { res.sendFile(__dirname + "/html/se
|
||||||
app.get("/api/analyze/:id", RL, function(req, res) { app.run.level(app, req, res, true, true) })
|
app.get("/api/analyze/:id", RL, function(req, res) { app.run.level(app, req, res, true, true) })
|
||||||
app.get("/api/boomlings", function(req, res) { app.run.boomlings(app, req, res) })
|
app.get("/api/boomlings", function(req, res) { app.run.boomlings(app, req, res) })
|
||||||
app.get("/api/comments/:id", RL2, function(req, res) { app.run.comments(app, req, res) })
|
app.get("/api/comments/:id", RL2, function(req, res) { app.run.comments(app, req, res) })
|
||||||
app.get("/api/credits", function(req, res) { res.send(require('./misc/credits.json')) })
|
app.get("/api/credits", function(req, res) { res.status(200).send(require('./misc/credits.json')) })
|
||||||
app.get("/api/gauntlets", function(req, res) { app.run.gauntlets(app, req, res) })
|
app.get("/api/gauntlets", function(req, res) { app.run.gauntlets(app, req, res) })
|
||||||
app.get("/api/leaderboard", function(req, res) { app.run[req.query.hasOwnProperty("accurate") ? "accurate" : "scores"](app, req, res) })
|
app.get("/api/leaderboard", function(req, res) { app.run[req.query.hasOwnProperty("accurate") ? "accurate" : "scores"](app, req, res) })
|
||||||
app.get("/api/leaderboardLevel/:id", RL2, function(req, res) { app.run.leaderboardLevel(app, req, res) })
|
app.get("/api/leaderboardLevel/:id", RL2, function(req, res) { app.run.leaderboardLevel(app, req, res) })
|
||||||
|
@ -310,24 +310,23 @@ app.get("/:id", function(req, res) { app.run.level(app, req, res) })
|
||||||
// MISC
|
// MISC
|
||||||
|
|
||||||
app.get("/icon/:text", function(req, res) { app.run.icon(app, req, res) })
|
app.get("/icon/:text", function(req, res) { app.run.icon(app, req, res) })
|
||||||
app.get("/api/userCache", function(req, res) { res.send(app.accountCache) })
|
app.get("/api/userCache", function(req, res) { res.status(200).send(app.accountCache) })
|
||||||
app.get("/api/achievements", function(req, res) { res.send({achievements, types: achievementTypes, shopIcons, colors: colorList }) })
|
app.get("/api/achievements", function(req, res) { res.status(200).send({achievements, types: achievementTypes, shopIcons, colors: colorList }) })
|
||||||
app.get("/api/music", function(req, res) { res.send(music) })
|
app.get("/api/music", function(req, res) { res.status(200).send(music) })
|
||||||
app.get("/api/gdps", function(req, res) {res.send(req.query.hasOwnProperty("current") ? app.safeServers.find(x => req.server.id == x.id) : app.safeServers) })
|
app.get("/api/gdps", function(req, res) {res.status(200).send(req.query.hasOwnProperty("current") ? app.safeServers.find(x => req.server.id == x.id) : app.safeServers) })
|
||||||
app.get('/api/icons', function(req, res) {
|
app.get('/api/icons', function(req, res) {
|
||||||
let sample = [JSON.stringify(sampleIcons[Math.floor(Math.random() * sampleIcons.length)].slice(1))]
|
let sample = [JSON.stringify(sampleIcons[Math.floor(Math.random() * sampleIcons.length)].slice(1))]
|
||||||
let iconserver = req.isGDPS ? req.server.name : undefined
|
let iconserver = req.isGDPS ? req.server.name : undefined
|
||||||
res.send({icons: gdIcons, colors: colorList, colorOrder, whiteIcons, server: iconserver, noCopy: req.onePointNine || req.offline, sample});
|
res.status(200).send({icons: gdIcons, colors: colorList, colorOrder, whiteIcons, server: iconserver, noCopy: req.onePointNine || req.offline, sample});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('*', function(req, res) {
|
app.get('*', function(req, res) {
|
||||||
if (req.path.startsWith('/api')) res.send('-1')
|
if (req.path.startsWith('/api')) res.status(404).send('-1')
|
||||||
else res.redirect('/search/404%20')
|
else res.redirect('/search/404%20')
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(function (err, req, res, next) {
|
app.use(function (err, req, res, next) {
|
||||||
if (err && err.message == "Response timeout") res.status(500).send('Internal server error! (Timed out)')
|
if (err && err.message == "Response timeout") res.status(504).send('Internal server error! (Timed out)')
|
||||||
else if (err) console.log(err)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
process.on('uncaughtException', (e) => { console.log(e) });
|
process.on('uncaughtException', (e) => { console.log(e) });
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "node ./index.js"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ag-psd": "^14.3.2",
|
"ag-psd": "^14.3.2",
|
||||||
"canvas": "^2.8.0",
|
"canvas": "^2.8.0",
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
"targetAccountID": "targetBddpvouKE"
|
"targetAccountID": "targetBddpvouKE"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"name": "1.9 GDPS",
|
"name": "1.9 GDPS",
|
||||||
"link": "https://absolllute.com/gdps/",
|
"link": "https://absolllute.com/gdps/",
|
||||||
|
|
Loading…
Reference in a new issue