import { fetchChoice } from "./choices";
import { npc } from "./openai";
import path from "path";
import { NpcModel } from "./model/NpcModel";
import { makeComment } from "./power-troll/comment";
import http from 'http';
import { addRoutes } from "dok-db-manager";
import express from "express";
import { addCustomRoute } from "./custom/custom";
import { DefinitionManager } from "./word/definition";
import { moderator } from "./power-troll/moderator";
import { TranslateManager } from "./lang/translate";
import { DetectiveManager } from "./detective/whodunit";
import { attachSyncSocket } from "@dobuki/syncopath";
import { WebSocketServer } from "ws";
import { ChatModel } from "openai/resources/index.mjs";
const app = express();
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.setHeader('Access-Control-Allow-Credentials', "true");
next();
});
const port = parseInt(process.env.PORT ?? "4000");
interface Query {
choice?: string;
model?: string;
creature?: string;
jsonp?: string;
}
app.use('/example', express.static(path.join(import.meta.dir, '../example')));
app.use('/html', express.static(path.join(import.meta.dir, '../html')));
app.use("/detective-game", express.static(path.join(import.meta.dir, '../detective')));
app.get("/api", async (req, res) => {
const query = req.query as Query;
let choice = (query.choice ?? "") as string;
const response = await fetchChoice(choice, query.model ?? undefined, query.creature ?? undefined);
return query.jsonp ? res.send(`${query.jsonp}(${JSON.stringify(response)})`) : res.json(response);
});
app.get("ping", (req, res) => {
res.json({ success: true });
});
app.get("/index.html", async (req, res) => {
return res.sendFile(path.join(import.meta.dir, "../index.html"));
});
app.get("/", (req, res) => {
res.send(`
OpenAI NPC Dialog Generator
NPC Dialog Generator using OpenAI
To use this API, first call: "/api", then provide the following query parameters:
- choice [optional]: Choices separated by "|". Ex: choice=A|B|A|C
(note that you must include previous choices to continue a conversation).
You can also insert custom choices like choice=pizza|A
- model [optional]: The chatgpt model to use.
List at: https://platform.openai.com/docs/models
- creature [optional]: A description of the creature. Default is "an angel with wings".
You can check out the NPC dialog demo, which uses this API. Click here:
VIDEO
`);
});
function listRoutes() {
const routes: Record = {}
app._router.stack.forEach((middleware: { route: { methods: {}; path: any; }; name: string; handle: { stack: any[]; }; }) => {
if (middleware.route) { // Route middleware
routes[middleware.route.path] = routes[middleware.route.path] ?? [];
routes[middleware.route.path].push(...Object.keys(middleware.route.methods).map(m => m.toUpperCase()));
} else if (middleware.name === 'router') { // Router middleware
middleware.handle.stack.forEach((handler: { route: { methods: {}; path: any; }; }) => {
if (handler.route) {
routes[handler.route.path] = routes[handler.route.path] ?? [];
routes[handler.route.path].push(...Object.keys(handler.route.methods).map(m => m.toUpperCase()));
}
});
}
});
return routes;
}
app.get('/routes', (req, res) => {
res.json(listRoutes());
});
// Power Troll API
interface CommentQuery {
dictionary?: string;
situation?: string;
model?: string;
seed?: string;
jsonp?: string;
}
app.get("/comment", async (req, res) => {
const query = req.query as CommentQuery;
const { situation, model, seed, dictionary, jsonp, ...customFields } = query;
let situations = ((situation ?? "") as string).split(".");
const cf: Record = {};
Object.entries(customFields).forEach(([kString, value]) => {
const [key, type] = kString.split(":");
cf[key] = {
type,
value,
};
});
const response = await makeComment(
situations, model as ChatModel, seed, dictionary ? JSON.parse(dictionary) : undefined,
cf
);
const formattedResponse = typeof (response) === "object" ? response : {
response,
};
return query.jsonp ? res.type('.js').send(`${query.jsonp}(${JSON.stringify(formattedResponse)})`) : res.json(formattedResponse);
});
addRoutes(app, {
github: {
owner: "jacklehamster",
repo: "power-troll-levels",
},
secret: {
secret: process.env.SECRET_WORD ?? "secret",
},
nocache: true,
nolock: true,
moderator,
});
const definitionManager = new DefinitionManager();
definitionManager.addWordRoutes(app);
const translateManager = new TranslateManager();
translateManager.addTranslateRoutes(app);
const detectiveManager = new DetectiveManager();
detectiveManager.addDetective(app);
addCustomRoute(app);
const options = {
host: '0.0.0.0', // Listen on all network interfaces
port,
};
const server = http.createServer(app);
// Web socket
const wss = new WebSocketServer({ server });
attachSyncSocket(wss);
// // Promo codes
// attachPromoCodes(app, "/promo", {
// useRedis: false,
// });
server.listen(options.port, options.host, () => {
console.log(`Server running at http://${options.host}:${options.port}/`);
const address = server.address();
console.log(address);
});
export { npc, fetchChoice };
export type { NpcModel };