ai-adventure-labs/server/api/index.js
2025-08-17 17:55:23 +03:00

196 lines
4.5 KiB
JavaScript

const crypt = require("../crypt");
// methods
const isAuthed = require("./is-authed");
const logIn = require("./log-in");
const setupToken = require("./setup-token");
// authed sessions
global.authed = new WeakMap();
global.authed.tokens = new Object();
function parseRq (bytes) {
try {
return JSON.parse(bytes.toString());
} catch (e) {
return undefined;
}
}
class APIMethods {
constructor (parentObj) {
this.parentObj = parentObj;
this.info.cache = new Object();
// Clear method cache on update config
global.server.on("config.update", () => {
this.info.cache = new Object();
});
}
info (con, req, cb) {
if (!req.fields) req.fields = "*";
if (!req.fieldsExtSource) req.fieldsExtSource = "*";
const cacheKey = `${req.fields}\u0000${req.fieldsExtSource}`;
const cache = this.info.cache[cacheKey];
if (cache) {
return cb({ result: cache, trace_id: req.trace_id, ended: true });
}
const serverInfo = require("./server-info")();
if (req.fields !== "*") {
const fields = Object.fromEntries(req.fields.split(/\s*,\s*/g).map(x => [x.trim(), true]));
Object.keys(serverInfo).forEach(k => {
if (!fields[k]) serverInfo[k] = undefined;
});
}
if (req.fieldsExtSource !== "*" && req.fields.extSource !== undefined) {
const fields = Object.fromEntries(req.fieldsExtSource.split(/\s*,\s*/g).map(x => [x.trim(), true]));
Object.keys(serverInfo).forEach(k => {
if (!fields[k]) serverInfo.extSource[k] = undefined;
});
}
this.info.cache[cacheKey] = serverInfo;
cb({ result: serverInfo, trace_id: req.trace_id, ended: true });
}
authed (con, req, cb) {
isAuthed(con, req, cb);
}
async token (con, req, cb) {
const authedMethod = this.authed;
const isAuthed = await (new Promise((rs, rj) => {
authedMethod(con, req, ({ result, ended }) => {
if (ended)
return rs(result);
});
}));
if (!isAuthed) {
return setupToken(con, req, cb);
}
cb({
error: "already logged-in",
trace_id: req.trace_id,
ended: true
});
}
async login (con, req, cb) {
const authedMethod = this.authed;
const isAuthed = await (new Promise((rs, rj) => {
authedMethod(con, req, ({ result, ended }) => {
if (ended)
return rs(result);
});
}));
if (!isAuthed) {
return logIn(con, req, cb);
}
cb({
error: "already logged-in",
trace_id: req.trace_id,
ended: true
});
}
async characters (con, req, cb) {
const authedMethod = this.authed;
const isAuthed = await (new Promise((rs, rj) => {
authedMethod(con, req, ({ result, ended }) => {
if (ended)
return rs(result);
});
}));
if (!isAuthed) {
return cb({
error: "require authorize",
trace_id: req.trace_id,
ended: true
});
}
// getting characters
const user = global.authed.get(con);
const result = (await user.getCharacters())
.map(character => {
return character;
});
cb({
result, trace_id: req.trace_id, ended: true
});
}
/*setSession (isEncrypted, address, { key, counter }, cb) {
if (!global.config.server.secureMode)
return cb({ error: "Encryption is off by configuration file into server" });
if (!isEncrypted)
return cb({ error: "Encryption required" });
try {
this.parent.sessions[address] = new crypt.AES(key, counter);
return cb({ result: "Session key installed" });
} catch (err) {
return cb({ error: "Invalid params. Must be key and counter" });
}
}*/
}
class API {
constructor () {
this.methods = new APIMethods(this);
this.sessions = global.authed;
}
decrypt (address, bytes) {
throw new Error("Deprecated. Use TLS. If you see this error, please, create issue into: https://git.fullgream.tech/fullgream/ai-adventure-labs/issues");
}
async exec (connection, bytes, cb) {
const request = parseRq(bytes);
if (request === undefined)
return cb({
error: "required JSON object request"
});
if (typeof request === "object" && request !== null) {
const {
method,
trace_id
} = request;
if (!method)
return cb({
error: "method missed",
trace_id: trace_id ?? null,
ended: true
});
if (!trace_id)
return cb({
error: "trace_id missed",
trace_id: null,
ended: true
});
if (this.methods[method] === undefined)
return cb({
error: "unknown method: " + method,
trace_id,
ended: true
});
return this.methods[method](connection, request, cb);
} else {
return cb({
error: "required JSON-object based request",
trace_id: null,
ended: true
});
}
}
}
module.exports = { API };