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.
192 lines
7.6 KiB
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...")
|
|
})
|
|
})
|
|
}
|
|
} |