From 80830372425133cb6004bbf362d20b7f4d0a3883 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 | 81 ++++++++++++++++++++++ src/lib/util.ts | 22 +++++- src/routes/comments/account/get.ts | 53 ++++++++++++++ src/routes/comments/account/history/get.ts | 76 ++++++++++++++++++++ src/routes/comments/level/get.ts | 76 ++++++++++++++++++++ 8 files changed, 389 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..7bad4d3 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,83 @@ 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`.' + }) + ), + amount: t.Optional( + t.String({ + description: + 'The amount of comments you want to get. Default is `10`. Range is `1`-`100`.' + }) + ) + }) +}) +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`.' + }) + ), + amount: t.Optional( + t.String({ + description: + 'The amount of comments you want to get. Default is `10`. Range is `1`-`100`.' + }) + ), + mode: t.Optional( + t.Union([t.Literal('recent'), t.Literal('top')], { + description: 'Default is `recent`.' + }) + ) + }) + } +) +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`.' + }) + ), + amount: t.Optional( + t.String({ + description: + 'The amount of comments you want to get. Default is `10`. Range is `1`-`100`.' + }) + ), + mode: t.Optional( + t.Union([t.Literal('recent'), t.Literal('top')], { + description: 'Default is `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..f7bed57 --- /dev/null +++ b/src/routes/comments/account/get.ts @@ -0,0 +1,53 @@ +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 amount = handler.query.amount + + const request = await axios.post( + 'https://www.boomlings.com/database/getGJAccountComments20.php', + new URLSearchParams({ + gameVersion: '22', + binaryVersion: '45', + accountID: id, + page: page ?? '0', + count: amount ?? '10', + 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] + + const data = { + id: +commentInfo['6'], + content: commentInfo['2'], + decodeFailed: false, + likes: +commentInfo['4'], + date: commentInfo['9'] + ' ago' + } + try { + data.content = atob(data.content) + } catch { + data.decodeFailed = true + } + return data + }) + ) +} diff --git a/src/routes/comments/account/history/get.ts b/src/routes/comments/account/history/get.ts new file mode 100644 index 0000000..75b0e22 --- /dev/null +++ b/src/routes/comments/account/history/get.ts @@ -0,0 +1,76 @@ +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 mode = handler.query.mode + const amount = handler.query.amount + + const request = await axios.post( + 'https://www.boomlings.com/database/getGJCommentHistory.php', + new URLSearchParams({ + gameVersion: '22', + binaryVersion: '45', + page: page ?? '0', + secret: 'Wmfd2893gb7', + mode: mode ? (mode == 'recent' ? '0' : '1') : '0', //Don't worry about it + userID: id, + count: amount ?? '10' + }), + { + 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] + + const data = { + id: +commentInfo['6'], + levelId: +commentInfo['1'], + content: commentInfo['2'], + decodeFailed: false, + 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 + } + } + } + try { + data.content = atob(data.content) + } catch { + data.decodeFailed = true + } + return data + }) + ) +} diff --git a/src/routes/comments/level/get.ts b/src/routes/comments/level/get.ts new file mode 100644 index 0000000..d219f8c --- /dev/null +++ b/src/routes/comments/level/get.ts @@ -0,0 +1,76 @@ +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 amount = handler.query.amount + + const request = await axios.post( + 'https://www.boomlings.com/database/getGJComments21.php', + new URLSearchParams({ + gameVersion: '22', + binaryVersion: '45', + page: page ?? '0', + total: '0', + secret: 'Wmfd2893gb7', + mode: mode ? (mode == 'recent' ? '0' : '1') : '0', //Don't worry about it + levelID: id, + count: amount ?? '10' + }), + { + 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] + + const data = { + id: +commentInfo['6'], + content: commentInfo['2'], + decodeFailed: false, + 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 + } + } + } + try { + data.content = atob(data.content) + } catch { + data.decodeFailed = true + } + return data + }) + ) +}