From 0efb404a0112fde2d106f3fa2d82af74197c4839 Mon Sep 17 00:00:00 2001 From: Lncvrt Date: Sat, 21 Feb 2026 12:19:22 -0700 Subject: [PATCH] Add getting comments --- README.md | 6 +- src/comments/account copy/get.ts | 40 ++++++++++++ src/comments/level copy/get.ts | 40 ++++++++++++ src/index.ts | 56 +++++++++++++++++ src/lib/util.ts | 22 ++++++- src/routes/comments/account/get.ts | 44 ++++++++++++++ src/routes/comments/account/history/get.ts | 66 ++++++++++++++++++++ src/routes/comments/level/get.ts | 71 ++++++++++++++++++++++ 8 files changed, 340 insertions(+), 5 deletions(-) create mode 100644 src/comments/account copy/get.ts create mode 100644 src/comments/level copy/get.ts create mode 100644 src/routes/comments/account/get.ts create mode 100644 src/routes/comments/account/history/get.ts create mode 100644 src/routes/comments/level/get.ts diff --git a/README.md b/README.md index 9d41cd8..2d09527 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ This is very early in development and will not be finished for a long time likel - [x] Get classic level scores - [x] Get plat level scores - [x] Get daily/weekly level +- [x] Get level comments +- [x] Get account comments +- [x] Get account comment history - [ ] Get event level - [ ] Get Levels List - [ ] Get save data @@ -22,9 +25,6 @@ This is very early in development and will not be finished for a long time likel - [ ] Get user (profile?) - [ ] Get user info - [ ] Get messages (account?) -- [ ] Get comments -- [ ] Get comment history -- [ ] Get account comments - [ ] Get account friend requests - [ ] Get user list (friends list?) - [ ] Get rewards (chests?) diff --git a/src/comments/account copy/get.ts b/src/comments/account copy/get.ts new file mode 100644 index 0000000..647186b --- /dev/null +++ b/src/comments/account copy/get.ts @@ -0,0 +1,40 @@ +import axios from 'axios' +import { jsonResponse, splitGd } from '../../../lib/util' + +export const handler = async () => { + const request = await axios.post( + 'https://www.boomlings.com/database/getGJMapPacks21.php', + new URLSearchParams({ + gameVersion: '22', + binaryVersion: '45', + count: '250', + page: '0', + secret: 'Wmfd2893gb7' + }), + { + headers: { + 'User-Agent': ' ', + Cookie: 'gd=1' + } + } + ) + + const responseText = request.data as string + const responseSplit = responseText.split('#')[0].split('|') + + return jsonResponse( + responseSplit.map(item => { + const split = splitGd(item) + return { + id: split['1'], + name: split['2'], + levels: split['3'].split(','), + stars: split['4'], + coins: split['5'], + difficulty: split['6'], + barColor: JSON.parse('[' + split['7'] + ']'), + textColor: JSON.parse('[' + split['8'] + ']') + } + }) + ) +} diff --git a/src/comments/level copy/get.ts b/src/comments/level copy/get.ts new file mode 100644 index 0000000..647186b --- /dev/null +++ b/src/comments/level copy/get.ts @@ -0,0 +1,40 @@ +import axios from 'axios' +import { jsonResponse, splitGd } from '../../../lib/util' + +export const handler = async () => { + const request = await axios.post( + 'https://www.boomlings.com/database/getGJMapPacks21.php', + new URLSearchParams({ + gameVersion: '22', + binaryVersion: '45', + count: '250', + page: '0', + secret: 'Wmfd2893gb7' + }), + { + headers: { + 'User-Agent': ' ', + Cookie: 'gd=1' + } + } + ) + + const responseText = request.data as string + const responseSplit = responseText.split('#')[0].split('|') + + return jsonResponse( + responseSplit.map(item => { + const split = splitGd(item) + return { + id: split['1'], + name: split['2'], + levels: split['3'].split(','), + stars: split['4'], + coins: split['5'], + difficulty: split['6'], + barColor: JSON.parse('[' + split['7'] + ']'), + textColor: JSON.parse('[' + split['8'] + ']') + } + }) + ) +} diff --git a/src/index.ts b/src/index.ts index c8b11b9..90915a5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,6 +12,10 @@ import { handler as leaderboardsLevelGetHandler } from './routes/leaderboards/le import { handler as mapPacksGetHandler } from './routes/map-packs/get' +import { handler as commentsAccountGetHandler } from './routes/comments/account/get' +import { handler as commentsAccountHistoryGetHandler } from './routes/comments/account/history/get' +import { handler as commentsLevelGetHandler } from './routes/comments/level/get' + dotenv.config() const app = new Elysia().use( @@ -120,6 +124,58 @@ app.get('/weekly-level', () => eventLevelGetHandler('1'), { tags: ['Levels'] } }) +app.get('/comments/account', handler => commentsAccountGetHandler(handler), { + detail: { + description: 'The endpoint for getting account comments', + tags: ['Accounts', 'Comments'] + }, + query: t.Object({ + id: t.String({ description: 'This is the account ID.' }), + page: t.Optional( + t.String({ + description: + 'The page you want to get, starts from `0`. Default is `0`.' + }) + ) + }) +}) +app.get( + '/comments/account/history', + handler => commentsAccountHistoryGetHandler(handler), + { + detail: { + description: 'The endpoint for getting account comment history', + tags: ['Accounts', 'Comments'] + }, + query: t.Object({ + id: t.String({ description: 'This is the user ID.' }), + page: t.Optional( + t.String({ + description: + 'The page you want to get, starts from `0`. Default is `0`.' + }) + ) + }) + } +) +app.get('/comments/level', handler => commentsLevelGetHandler(handler), { + detail: { + description: 'The endpoint for getting level comments', + tags: ['Levels', 'Comments'] + }, + query: t.Object({ + id: t.String({ description: 'This is the level ID.' }), + page: t.Optional( + t.String({ + description: + 'The page you want to get, starts from `0`. Default is `0`.' + }) + ), + mode: t.Union([t.Literal('0'), t.Literal('1')], { + description: '0 for top, 1 for recent' + }) + }) +}) app.get( '/', () => diff --git a/src/lib/util.ts b/src/lib/util.ts index fab96b9..c305465 100644 --- a/src/lib/util.ts +++ b/src/lib/util.ts @@ -5,8 +5,11 @@ export const jsonResponse = (data: any, status = 200) => { }) } -export const splitGd = (input: string): Record => { - const parts = input.split(':') +export const splitGd = ( + input: string, + splitKey: string = ':' +): Record => { + const parts = input.split(splitKey) const result: Record = {} for (let i = 0; i < parts.length - 1; i += 2) { result[parts[i]] = parts[i + 1] @@ -54,3 +57,18 @@ export const formatTime = (seconds: number): string => { return parts.join(' ') || '0s' } + +//Taken from https://github.com/GDColon/GDBrowser/blob/master/index.js#L164-L173 +export const parseResponse = (responseBody: string, splitter = ':') => { + if (!responseBody || responseBody == '-1') return {} + if (responseBody.startsWith('\nWarning:')) + responseBody = responseBody.split('\n').slice(2).join('\n').trim() // GDPS'es are wild + if (responseBody.startsWith('
')) + responseBody = responseBody.split('
').slice(2).join('
').trim() // Seriously screw this + let response = responseBody.split('#')[0].split(splitter) + let res: any = {} + for (let i = 0; i < response.length; i += 2) { + res[response[i]] = response[i + 1] + } + return res +} diff --git a/src/routes/comments/account/get.ts b/src/routes/comments/account/get.ts new file mode 100644 index 0000000..8b55b45 --- /dev/null +++ b/src/routes/comments/account/get.ts @@ -0,0 +1,44 @@ +import axios from 'axios' +import { jsonResponse, parseResponse, splitGd } from '../../../lib/util' +import { Context } from 'elysia' + +export const handler = async (handler: Context) => { + const id = handler.query.id + const page = handler.query.page + + const request = await axios.post( + 'https://www.boomlings.com/database/getGJAccountComments20.php', + new URLSearchParams({ + gameVersion: '22', + binaryVersion: '45', + accountID: id, + page: page ?? '0', + secret: 'Wmfd2893gb7' + }), + { + headers: { + 'User-Agent': ' ', + Cookie: 'gd=1' + } + } + ) + + const responseText = request.data as string + const responseSplit = responseText + .split('|') + .map(x => x.split(':')) + .map(x => x.map(x => parseResponse(x, '~'))) + + return jsonResponse( + responseSplit.map(item => { + const commentInfo = item[0] + + return { + id: +commentInfo['6'], + content: atob(commentInfo['2']), + likes: +commentInfo['4'], + date: commentInfo['9'] + ' ago' + } + }) + ) +} diff --git a/src/routes/comments/account/history/get.ts b/src/routes/comments/account/history/get.ts new file mode 100644 index 0000000..56ce732 --- /dev/null +++ b/src/routes/comments/account/history/get.ts @@ -0,0 +1,66 @@ +import axios from 'axios' +import { jsonResponse, parseResponse } from '../../../../lib/util' +import { Context } from 'elysia' + +export const handler = async (handler: Context) => { + const id = handler.query.id + const page = handler.query.page + + const request = await axios.post( + 'https://www.boomlings.com/database/getGJCommentHistory.php', + new URLSearchParams({ + gameVersion: '22', + binaryVersion: '45', + page: page ?? '0', + secret: 'Wmfd2893gb7', + mode: '1', + userID: id + }), + { + headers: { + 'User-Agent': ' ', + Cookie: 'gd=1' + } + } + ) + + const responseText = request.data as string + const responseSplit = responseText + .split('|') + .map(x => x.split(':')) + .map(x => x.map(x => parseResponse(x, '~'))) + + return jsonResponse( + responseSplit.map(item => { + const commentInfo = item[0] + const accountInfo = item[1] + + return { + id: +commentInfo['6'], + levelId: +commentInfo['1'], + content: atob(commentInfo['2']), + likes: +commentInfo['4'], + date: commentInfo['9'] + ' ago', + commentColor: commentInfo['12'] + ? JSON.parse('[' + commentInfo['12'] + ']') + : [255, 255, 255], + account: { + username: accountInfo['1'], + moderator: +accountInfo['15'], + playerId: +accountInfo['11'], + accountId: +accountInfo['16'], + icon: { + form: ['icon', 'ship', 'ball', 'ufo', 'wave', 'robot', 'spider'][ + +accountInfo['14'] + ], + icon: +accountInfo['9'], + col1: +accountInfo['10'], + col2: +accountInfo['11'], + colG: +accountInfo['51'], + glow: +accountInfo['15'] > 1 + } + } + } + }) + ) +} diff --git a/src/routes/comments/level/get.ts b/src/routes/comments/level/get.ts new file mode 100644 index 0000000..39fa3de --- /dev/null +++ b/src/routes/comments/level/get.ts @@ -0,0 +1,71 @@ +import axios from 'axios' +import { jsonResponse, parseResponse, splitGd } from '../../../lib/util' +import { Context } from 'elysia' + +export const handler = async (handler: Context) => { + const id = handler.query.id + const page = handler.query.page + const mode = handler.query.mode + + const request = await axios.post( + 'https://www.boomlings.com/database/getGJComments21.php', + new URLSearchParams({ + gameVersion: '22', + binaryVersion: '45', + udid: 'BEA53432-326F-4D39-91D7-2B51B849825E', + uuid: '241138636', + accountID: '28945106', + gjp2: '836845372d7a726b35f627bcc491d4e122782c17', + page: page ?? '0', + total: '0', + secret: 'Wmfd2893gb7', + mode, + levelID: id + }), + { + headers: { + 'User-Agent': ' ', + Cookie: 'gd=1' + } + } + ) + + const responseText = request.data as string + const responseSplit = responseText + .split('|') + .map(x => x.split(':')) + .map(x => x.map(x => parseResponse(x, '~'))) + + return jsonResponse( + responseSplit.map(item => { + const commentInfo = item[0] + const accountInfo = item[1] + + return { + id: +commentInfo['6'], + content: atob(commentInfo['2']), + likes: +commentInfo['4'], + date: commentInfo['9'] + ' ago', + commentColor: commentInfo['12'] + ? JSON.parse('[' + commentInfo['12'] + ']') + : [255, 255, 255], + account: { + username: accountInfo['1'], + moderator: +accountInfo['15'], + playerId: +accountInfo['11'], + accountId: +accountInfo['16'], + icon: { + form: ['icon', 'ship', 'ball', 'ufo', 'wave', 'robot', 'spider'][ + +accountInfo['14'] + ], + icon: +accountInfo['9'], + col1: +accountInfo['10'], + col2: +accountInfo['11'], + colG: +accountInfo['51'], + glow: +accountInfo['15'] > 1 + } + } + } + }) + ) +}