Scenario generator for vore roleplay and story ideas. https://scenario-generator.deliciousreya.net/responses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

113 lines
4.0 KiB

import { type IRequestStrict, Router } from 'itty-router';
import type { Database } from '../db/database';
import { buildGeneratorPage, buildResponsesPage } from '../../common/template';
import { CSS, JS } from './bundles/client.generated';
import type { HashedBundled } from '../../common/bundle';
import { getSourceMapFileName, SourceMapExtension, SourceMaps } from './bundles/sourcemaps';
import { collapseWhiteSpace } from 'collapse-white-space';
import { getQuerySingleton, takeLast } from '../request/query';
import { StringTemplateBuilder } from './template';
interface WebEnv {
readonly BASE_URL: string,
readonly CREDITS_URL: string,
readonly DISCORD_APP_ID: string
}
export function wrapPage(
{ title, bodyContent, script, styles, noscriptStyles }:
{ readonly title: string, readonly bodyContent: string, readonly script: string, readonly styles: string, readonly noscriptStyles: string }): string {
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>${title}</title>
<script>${script}</script>
<style>${styles}</style>
<noscript><style>${noscriptStyles}</style></noscript>
</head>
<body>
${bodyContent}
</body>
</html>`;
}
export function webRouter(base: string) {
function getSourceMappedJS(name: keyof typeof JS) {
const { bundled, hash }: HashedBundled = JS[name];
return bundled + `\n//# sourceMappingURL=${getSourceMapFileName(name, hash, SourceMapExtension.JS)}`;
}
function getSourceMappedCSS(name: keyof typeof CSS) {
const { bundled, hash }: HashedBundled = CSS[name];
return bundled + `\n/*# sourceMappingURL=${getSourceMapFileName(name, hash, SourceMapExtension.CSS)} */`;
}
async function handleMainPage(req: IRequestStrict, env: WebEnv, db: Database): Promise<string> {
const results = await db.getGeneratorPageForDiscordSet(
getQuerySingleton(req.query['server'], takeLast) ?? null);
const generator = buildGeneratorPage({
creditsUrl: env.CREDITS_URL,
clientId: env.DISCORD_APP_ID,
generatorTargetUrl: env.BASE_URL,
results: results.rolled,
editable: !results.final,
selected: results.selected,
includesResponses: true,
builder: StringTemplateBuilder,
})
const responses = buildResponsesPage({
tables: Array.from(results.db.tables.values()),
results: results.rolled,
creditsUrl: env.CREDITS_URL,
includesGenerator: true,
builder: StringTemplateBuilder,
})
const wrapped = wrapPage({
title: 'Vore Scenario Generator',
script: getSourceMappedJS('combinedGeneratorResponses'),
styles: getSourceMappedCSS('combinedGeneratorResponses'),
noscriptStyles: getSourceMappedCSS('noscript'),
bodyContent: [generator, responses].join('')
})
return collapseWhiteSpace(wrapped, { style: 'html' });
}
const router = Router<IRequestStrict, [env: WebEnv, db: Database, ctx: ExecutionContext]>({ base })
.get('/responses', async (req, _env, _db, _ctx) => {
const url = new URL(req.url);
url.pathname = base;
url.hash = '#responses';
return Response.redirect(url.toString(), 303);
})
.get('/generator', async (req, _env, _db, _ctx) => {
const url = new URL(req.url);
url.pathname = base;
url.hash = '#generator';
return Response.redirect(url.toString(), 303);
})
.get('/scenario', async (_req, _env, _db, _ctx) => {
// TODO: implement me
return new Response('Not yet supported', { status: 404 });
})
.get('/', handleMainPage)
.post('/', handleMainPage);
for (const key in CSS) {
if (CSS.hasOwnProperty(key)) {
const result = CSS[key as keyof typeof CSS]
if (result.sourceMap) {
router.get(`/${getSourceMapFileName(key, result.hash, SourceMapExtension.CSS)}`, () => result.sourceMap)
}
}
}
for (const key in JS) {
if (JS.hasOwnProperty(key)) {
const result = JS[key as keyof typeof JS]
if (result.sourceMap) {
router.get(`/${getSourceMapFileName(key, result.hash, SourceMapExtension.JS)}`, () => result.sourceMap)
}
}
}
for (const [filename, contents] of SourceMaps) {
router.get(`/${filename}`, () => contents);
}
return router;
}