From 8d8b4d1526690839eec1c13e3617c843d8a2d780 Mon Sep 17 00:00:00 2001 From: oatmealine Date: Sun, 26 Jan 2020 23:26:12 +0300 Subject: [PATCH] download level added --- src/downloadGJLevel22.ts | 38 ++++++++++++++++++++++++++++++++++++++ src/hash.ts | 17 +++++++++++++++++ src/index.ts | 5 ++++- src/xor.ts | 11 +++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/downloadGJLevel22.ts create mode 100644 src/xor.ts diff --git a/src/downloadGJLevel22.ts b/src/downloadGJLevel22.ts new file mode 100644 index 0000000..4cfbcae --- /dev/null +++ b/src/downloadGJLevel22.ts @@ -0,0 +1,38 @@ +import * as xor from './xor'; +import * as hashes from './hash'; + +module.exports = (app) : void => { + app.post('/' + app.get('config').addtopath + 'database/downloadGJLevel22.php', async (req, res) => { + let level = await app.get('db').collection('levels').findOneAndUpdate({ + id: Number(req.body.levelID) + }, { + $inc: {downloads: 1} + }); + + if (level.value == null) return res.status(200).send('-1'); + + level = level.value; + + let gameVer = Number(req.body.gameVersion || 1); + let xor_pw = level.password; + + let description = level.description; + + if (gameVer > 19) { + if (level.password != 0) + xor_pw = xor.encode(String(level.password), '26364'); + } else { + description = Buffer.from(description, 'base64').toString('utf8'); + } + + let response = `1:${level.id}:2:${level.name}:3:${description}:4:${level.level_data}:5:${1 /* level version, placeholder*/}:6:${level.user_id}:8:10:9:${level.difficulty}:10:${level.downloads}:11:1:12:${level.audio_track}:13:${level.game_version}:14:${level.likes}:17:${Number(level.difficulty >= 60)}:43:${Math.max((level.difficulty-60)/10, 0)}:25:${Number(level.auto)}:18:${level.stars}:19:${Number(level.featured)}:42:${Number(level.epic)}:45:${level.objects}:15:${level.length}:30:${level.original}:31:1:28:${0 /* upload date */}:29:${0 /* update date*/}:35:${level.song_id}:36:${level.extra_data}:37:${level.coins}:38:${Number(level.rated_coins)}:39:${level.requested_stars}:46:1:47:2:48:1:40:${Number(level.ldm)}:27:${xor_pw}`; + + response += `#${hashes.hashLevel(level.level_data)}#`; + level.demon = level.difficulty >= 60; + let extraData = ['user_id', 'stars', 'demon', 'id', 'rated_coins', 'featured'].map(key => Number(level[key])).join(','); + extraData += `,${level.password},${0 /* featured id */}`; + response += `${hashes.hashSolo2(extraData)}#${extraData}`; + + res.status(200).send(response); + }); +}; \ No newline at end of file diff --git a/src/hash.ts b/src/hash.ts index c2d4efb..1ed53bb 100644 --- a/src/hash.ts +++ b/src/hash.ts @@ -6,4 +6,21 @@ export function hashLevels(levels : any[]) : string { let shasum = crypto.createHash('sha1'); shasum.update(c + 'xI25fpAapCQg'); return shasum.digest('hex'); +} + +export function hashLevel(level : string) : string { + let data = ''; + let l = Math.floor(level.length / 40); + for (let i = 0; i < 40; i++) + data += level[i * l]; + + let shasum = crypto.createHash('sha1'); + shasum.update(data + 'xI25fpAapCQg'); + return shasum.digest('hex'); +} + +export function hashSolo2(data : string) : string { + let shasum = crypto.createHash('sha1'); + shasum.update(data + 'xI25fpAapCQg'); + return shasum.digest('hex'); } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 991dceb..51245ed 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,8 +27,11 @@ dbClient.connect((err) => { require('./getGJLevels21')(app); require('./uploadGJLevel21')(app); + require('./downloadGJLevel22')(app); app.get('*', (req, res) => res.status(404).send('wrong page dumbass')); - app.listen(config.port); + app.listen(config.port, () => { + console.log(`expressjs server launched on port ${config.port}, gdps should now function properly`); + }); }); \ No newline at end of file diff --git a/src/xor.ts b/src/xor.ts new file mode 100644 index 0000000..70087fa --- /dev/null +++ b/src/xor.ts @@ -0,0 +1,11 @@ +export function encode(str : string, key : string) : string { + return Buffer.from(Array.from( + str, + (c : string, i) => String.fromCharCode(c.charCodeAt(0) ^ key.charCodeAt(i % key.length)) + ).join('')).toString('base64'); +} + +export function decode(str : string, key : string) : string { + str = Buffer.from(str, 'base64').toString('utf8'); + return Array(str.length).fill(0).map((_, i) => String.fromCharCode(str.charCodeAt(i) ^ key.charCodeAt(i % key.length))).join(''); +} \ No newline at end of file