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.
94 lines
3.4 KiB
94 lines
3.4 KiB
import { type IRequestStrict, Router } from 'itty-router';
|
|
import type { Database } from '../db/database';
|
|
import { buildGeneratorPage, buildResponsesPage, wrapPage } 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';
|
|
|
|
interface WebEnv {
|
|
readonly BASE_URL: string,
|
|
readonly CREDITS_URL: string,
|
|
readonly DISCORD_APP_ID: string
|
|
}
|
|
|
|
|
|
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
|
|
})
|
|
const responses = buildResponsesPage({
|
|
tables: Array.from(results.db.tables.values()),
|
|
results: results.rolled,
|
|
creditsUrl: env.CREDITS_URL,
|
|
includesGenerator: true
|
|
})
|
|
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;
|
|
}
|
|
|