From a85ee726c9f64f941fee513c8455f715aa38eb9b Mon Sep 17 00:00:00 2001 From: Lncvrt Date: Fri, 30 Jan 2026 21:35:43 -0700 Subject: [PATCH] Add a way to submit splash texts --- src/index.ts | 16 +++ src/routes/berrydash/splash-text/post.ts | 120 +++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 src/routes/berrydash/splash-text/post.ts diff --git a/src/index.ts b/src/index.ts index ff89c80..680b431 100644 --- a/src/index.ts +++ b/src/index.ts @@ -46,6 +46,7 @@ import { handler as berryDashAccountSavePostHandler } from './routes/berrydash/a import { handler as berryDashChatroomReportPostHandler } from './routes/berrydash/chatroom/report/post' import { handler as berryDashSplashTextGetHandler } from './routes/berrydash/splash-text/get' +import { handler as berryDashSplashTextPostHandler } from './routes/berrydash/splash-text/post' dotenv.config({ quiet: true }) @@ -958,6 +959,21 @@ app.get('/berrydash/splash-text', berryDashSplashTextGetHandler, { tags: ['Berry Dash', 'Splash Texts'] } }) +app.post('/berrydash/splash-text', berryDashSplashTextPostHandler, { + detail: { + description: 'The endpoint for submitting splash texts.', + tags: ['Berry Dash', 'Splash Texts'] + }, + body: t.Object({ + token: t.String(), + content: t.String() + }), + headers: t.Object({ + authorization: t.String({ + description: 'This is your session token' + }) + }) +}) app.all('*', () => jsonResponse( { diff --git a/src/routes/berrydash/splash-text/post.ts b/src/routes/berrydash/splash-text/post.ts new file mode 100644 index 0000000..60097c9 --- /dev/null +++ b/src/routes/berrydash/splash-text/post.ts @@ -0,0 +1,120 @@ +import { Context } from 'elysia' +import { + getClientIp, + getDatabaseConnection, + jsonResponse, + validateTurnstile +} from '../../../lib/util' +import { checkAuthorization } from '../../../lib/auth' +import { berryDashSplashTexts } from '../../../lib/tables' + +type Body = { + token: string + content: string +} + +export async function handler (context: Context) { + const dbInfo0 = getDatabaseConnection(0) + const dbInfo1 = getDatabaseConnection(1) + + if (!dbInfo0 || !dbInfo1) + return jsonResponse( + { success: false, message: 'Failed to connect to database' }, + 500 + ) + const { connection: connection0, db: db0 } = dbInfo0 + const { connection: connection1, db: db1 } = dbInfo0 + + const ip = getClientIp(context) + if (!ip) { + connection0.end() + connection1.end() + return jsonResponse( + { + success: false, + message: 'Failed to get required info' + }, + 400 + ) + } + const authorizationToken = context.headers.authorization + const authResult = await checkAuthorization( + authorizationToken as string, + db0, + ip + ) + if (!authResult.valid) { + connection0.end() + connection1.end() + return jsonResponse({ success: false, message: 'Unauthorized' }, 401) + } + const userId = authResult.id + + const body = context.body as Body + if (!body.token || !body.content) { + connection0.end() + connection1.end() + return jsonResponse( + { + success: false, + message: 'Token and content must be in POST data' + }, + 400 + ) + } + if (body.content.length > 72) { + connection0.end() + connection1.end() + return jsonResponse( + { + success: false, + message: 'Splash texts cannot be over 72 characters' + }, + 400 + ) + } + if ( + !/^[ a-zA-Z0-9!@#\$%\^&\*\(\)_\+\-=\[\]\{\};\':",\.<>\/\?\\\\|`~]+$/.test( + body.content + ) + ) { + connection0.end() + connection1.end() + return jsonResponse( + { + success: false, + message: 'Invalid characters in splash' + }, + 400 + ) + } + + const result = await validateTurnstile(body.token, ip) + if (!result.success) { + connection0.end() + connection1.end() + return jsonResponse( + { + success: false, + message: 'Unable to verify captcha key' + }, + 400 + ) + } + + const time = Math.floor(Date.now() / 1000) + await db1 + .insert(berryDashSplashTexts) + .values({ userId, content: atob(body.content), timestamp: time }) + + connection0.end() + connection1.end() + + return jsonResponse( + { + success: true, + message: null + }, + 200 + ) +}