Gacha game centered around vore.
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.
 
 
 
vore-gacha/src/SetupServer.ts

192 lines
7.6 KiB

import {DiscordWebhookHandler, OAuthRoute} from "./DiscordWebhookHandler.js";
import {getBaseUrl} from "./FastifyHelpers.js";
import pug from "pug";
import {renderError} from "./PugRenderer.js";
import {GameServer} from "./GameServer.js";
import {checkAndClearXSRFCookie, generateXSRFCookie, XSRFRoute} from "./CookieHelpers.js";
import {SetupCommand, setupComponentInteractionHandler} from "./commands/SetupCommand.js";
import {BaseServer, BaseServerDeps} from "./BaseServer.js";
export class SetupServer extends BaseServer {
readonly gameFactory: () => GameServer
constructor(deps: BaseServerDeps & { gameFactory: () => GameServer }) {
super(deps)
this.gameFactory = deps.gameFactory
}
async _initInternal(): Promise<void> {
this.slashcmd.registerCommand(new SetupCommand(this.slashcmd))
this.slashcmd.on("componentInteraction", setupComponentInteractionHandler)
const gameHandler = new DiscordWebhookHandler({
webhook: this.gameWebhook,
templateFilename: "setup/game.pug",
appId: this.appId,
secret: this.clientSecret,
destinationFunc: () => {
if (this.adminWebhook.isPresent) {
return "clear"
} else {
return "adminChannel"
}
},
})
const adminHandler = new DiscordWebhookHandler({
webhook: this.adminWebhook,
templateFilename: "setup/admin.pug",
appId: this.appId,
secret: this.clientSecret,
destinationFunc: () => {
if (this.gameWebhook.isPresent) {
return "clear"
} else {
return "gameChannel"
}
},
})
this.server.get("/setup", async (req, res) => {
if (!this.gameWebhook.isPresent) {
res.redirect(`setup/gameChannel`)
} else if (!this.adminWebhook.isPresent) {
res.redirect(`setup/adminChannel`)
} else {
res.redirect(`setup/done`)
}
})
this.server.get("/setup/start", async (req, res) => {
res.redirect(".")
})
this.server.get("/game", async (req, res) => {
res.redirect("setup")
})
this.server.get("/game/started", async (req, res) => {
res.redirect("../setup")
})
this.server.get("/game/stop", async (req, res) => {
res.redirect("../setup")
})
this.server.get<XSRFRoute>("/game/start", async (req, res) => {
if (!checkAndClearXSRFCookie(req, res)) {
return renderError({
baseUrl: getBaseUrl(req),
res,
code: 400,
error: "Token was incorrect or not set.",
context: "starting the game",
buttonText: "Return to Setup",
buttonUrl: "setup"
})
}
if (!this.gameWebhook.isPresent || !this.adminWebhook.isPresent) {
return renderError({
baseUrl: getBaseUrl(req),
res,
code: 409,
error: "You can't start the game while one of the channels is not set!",
context: "starting the game",
buttonText: "Finish Setup",
buttonUrl: "setup"
})
}
res.code(200)
res.type("text/html")
res.send(pug.renderFile("static/pages/setup/start.pug", {
startedUrl: "game/start"
}))
setImmediate(async () => {
this.server.log.info("Shutting down the setup server and switching to the game server.")
try {
await this.server.close()
} catch (e) {
this.server.log.error(e, "Failed to shut down the setup server")
}
try {
await this.gameFactory().initialize()
} catch (e) {
this.server.log.error(e, "Failed to start up the game server")
}
this.server.log.info("Successfully switched from the setup server to the game server.")
})
})
this.server.get<OAuthRoute>("/setup/gameChannel", async (req, res) => {
return await gameHandler.handleRequest(req, res)
})
this.server.get<OAuthRoute>("/setup/adminChannel", async (req, res) => {
return await adminHandler.handleRequest(req, res)
})
this.server.get<XSRFRoute>("/setup/clear", async (req, res) => {
if (!checkAndClearXSRFCookie(req, res)) {
return renderError({
baseUrl: getBaseUrl(req),
res,
code: 400,
error: "Token was incorrect or not set.",
context: "clearing the channel setup",
buttonText: "Return to Setup",
buttonUrl: "setup"
})
}
try {
await Promise.all([this.gameWebhook, this.adminWebhook]
.filter((item) => item.isPresent)
.map((item) => item.clearHook()))
} catch (e) {
return renderError({
baseUrl: getBaseUrl(req),
res,
code: 500,
error: e,
context: "clearing and deleting the webhooks",
buttonUrl: "setup/clear",
buttonText: "Try Again"
})
}
res.redirect(".")
})
this.server.get("/setup/done", async (req, res) => {
if (!this.gameWebhook.isPresent) {
res.redirect("gameChannel")
} else if (!this.adminWebhook.isPresent) {
res.redirect("adminChannel")
} else {
const token = generateXSRFCookie(res)
res.code(200)
res.type("text/html")
res.send(pug.renderFile("static/pages/setup/done.pug", {
baseUrl: getBaseUrl(req),
gameModeUrl: `game/start?token=${token}`,
clearUrl: `setup/clear?token=${token}`,
gameSetupUrl: `setup/gameChannel`,
adminSetupUrl: `setup/adminChannel`,
shutdownUrl: `shutdown?token=${token}`
}))
}
})
this.server.get<XSRFRoute>("/shutdown", async (req, res) => {
if (!checkAndClearXSRFCookie(req, res)) {
return renderError({
baseUrl: getBaseUrl(req),
res,
code: 400,
error: "Token was incorrect or not set.",
context: "shutting the server down",
buttonText: "Return to Setup",
buttonUrl: "setup"
})
}
res.code(200)
res.type("text/html")
res.send(pug.renderFile("static/pages/shutdown.pug"))
setImmediate(async () => {
this.server.log.info("Shutting down the setup server.")
try {
await this.server.close()
} catch (e) {
this.server.log.error(e, "Failed to shut down the setup server")
}
this.server.log.info("Shut down. Good night...")
})
})
}
}