Add endpoints and game utilities
This commit is contained in:
parent
56f2195962
commit
6a174e4d36
7 changed files with 213 additions and 1 deletions
33
src/endpoints/guess_letter.ts
Normal file
33
src/endpoints/guess_letter.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { database } from "$/main";
|
||||
import { addLetter } from "$/utils/game";
|
||||
import { ServerRoute } from "@hapi/hapi";
|
||||
import Joi from "joi";
|
||||
|
||||
const route: ServerRoute = {
|
||||
method: `POST`, path: `/{channel}/guess`,
|
||||
options: {
|
||||
validate: {
|
||||
params: Joi.object({
|
||||
channel: Joi.string().alphanum(),
|
||||
}),
|
||||
payload: Joi.object({
|
||||
guess: Joi.string().length(1),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async handler(request) {
|
||||
// @ts-ignore
|
||||
const guess = request.payload.guess.toUpperCase();
|
||||
const { channel } = request.params;
|
||||
|
||||
let data = await database.getChannel(channel);
|
||||
console.log(data)
|
||||
if (data.solution.includes(guess)) {
|
||||
data.current = addLetter(data.key, data.current, guess);
|
||||
} else {
|
||||
data.incorrect++;
|
||||
};
|
||||
return `${data.current} (incorrect: ${data.incorrect}/6)`;
|
||||
},
|
||||
};
|
||||
export default route;
|
||||
33
src/endpoints/new_game.ts
Normal file
33
src/endpoints/new_game.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { database } from "$/main";
|
||||
import { anonymizePhrase, convertToKey, spacePhrase } from "$/utils/game";
|
||||
import { ServerRoute } from "@hapi/hapi";
|
||||
import Joi from "joi";
|
||||
|
||||
const route: ServerRoute = {
|
||||
method: `POST`, path: `/{channel}/game`,
|
||||
options: {
|
||||
validate: {
|
||||
params: Joi.object({
|
||||
channel: Joi.string().alphanum(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async handler(request) {
|
||||
const { channel } = request.params;
|
||||
|
||||
let data = await database.getChannel(channel);
|
||||
|
||||
// TODO: Get the proper phrase
|
||||
let phrase = "Hello world";
|
||||
|
||||
let spaced = spacePhrase(phrase.toUpperCase());
|
||||
let anonymized = anonymizePhrase(spaced);
|
||||
data.current = anonymized;
|
||||
data.solution = spaced;
|
||||
data.incorrect = 0;
|
||||
data.key = convertToKey(spaced);
|
||||
|
||||
return `${data.current} (incorrect: ${data.incorrect}/6)`;
|
||||
},
|
||||
};
|
||||
export default route;
|
||||
54
src/endpoints/nightbot.ts
Normal file
54
src/endpoints/nightbot.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import { nightbotCustomHeadersSchema } from "$/schemas/nightbot";
|
||||
import { ServerRoute } from "@hapi/hapi";
|
||||
import boom from "@hapi/boom";
|
||||
import Joi from "joi";
|
||||
|
||||
const subcommands = {
|
||||
"start": {
|
||||
method: `POST`,
|
||||
modOnly: true,
|
||||
},
|
||||
"show": {
|
||||
method: `GET`,
|
||||
modOnly: false,
|
||||
},
|
||||
};
|
||||
|
||||
const route: ServerRoute = {
|
||||
method: `GET`, path: `/nightbot`,
|
||||
options: {
|
||||
validate: {
|
||||
query: Joi.object({
|
||||
args: Joi.string().allow("").required(),
|
||||
msg: Joi.string(),
|
||||
}),
|
||||
headers: nightbotCustomHeadersSchema.unknown(),
|
||||
},
|
||||
},
|
||||
async handler(request) {
|
||||
let args = (<string>request.query.args)
|
||||
.split(` `)
|
||||
.filter(x => x.length > 0);
|
||||
|
||||
if (args.length < 1) {
|
||||
return `Not enough arguments`;
|
||||
};
|
||||
|
||||
let channelData = new URLSearchParams(request.headers["nightbot-channel"]);
|
||||
let channel = channelData.get(`name`);
|
||||
let userData = new URLSearchParams(request.headers["nightbot-user"]);
|
||||
let user = userData.get(`name`);
|
||||
|
||||
if (!channel) { throw boom.badData(`Missing channel name`) };
|
||||
if (!user) { throw boom.badData(`Missing user name`) };
|
||||
|
||||
// User is guessing a letter
|
||||
if (args[0].length == 1) {
|
||||
return (await request.server.inject({
|
||||
method: `POST`, url: `/${channel}/guess`,
|
||||
payload: { guess: args[0] }
|
||||
})).payload;
|
||||
};
|
||||
},
|
||||
};
|
||||
export default route;
|
||||
20
src/endpoints/setup_channel.ts
Normal file
20
src/endpoints/setup_channel.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { database } from "$/main";
|
||||
import { ServerRoute } from "@hapi/hapi";
|
||||
import Joi from "joi";
|
||||
|
||||
const route: ServerRoute = {
|
||||
method: `POST`, path: `/channels`,
|
||||
options: {
|
||||
validate: {
|
||||
payload: Joi.object({
|
||||
channel: Joi.string().alphanum(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async handler(request, h) {
|
||||
// @ts-ignore
|
||||
await database.createChannel(request.payload.channel);
|
||||
return h.close;
|
||||
},
|
||||
};
|
||||
export default route;
|
||||
13
src/schemas/nightbot.ts
Normal file
13
src/schemas/nightbot.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import Joi from "joi";
|
||||
|
||||
export const nightbotCustomHeadersSchema = Joi.object({
|
||||
"nightbot-response-url": Joi
|
||||
.string()
|
||||
.uri({ scheme: `https` }),
|
||||
"nightbot-user": Joi
|
||||
.string(),
|
||||
"nightbot-channel": Joi
|
||||
.string(),
|
||||
})
|
||||
.meta({ className: `nightbotCustomHeaders` })
|
||||
.description(`The custom headers Nightbot makes requests with`);
|
||||
|
|
@ -2,7 +2,7 @@ import { databaseOptions } from "$/types/config";
|
|||
import fs from "fs";
|
||||
|
||||
export class JSONDatabase {
|
||||
private data = {};
|
||||
private data: any = {};
|
||||
private conf: databaseOptions;
|
||||
|
||||
constructor(conf: databaseOptions) {
|
||||
|
|
@ -22,4 +22,17 @@ export class JSONDatabase {
|
|||
public shutdown() {
|
||||
fs.writeFileSync(this.conf.uri, JSON.stringify(this.data));
|
||||
};
|
||||
|
||||
public async createChannel(name: string) {
|
||||
this.data[name] = {
|
||||
current: null,
|
||||
solution: null,
|
||||
key: null,
|
||||
incorrect: 0,
|
||||
};
|
||||
};
|
||||
|
||||
public async getChannel(name: string) {
|
||||
return this.data[name];
|
||||
};
|
||||
};
|
||||
46
src/utils/game.ts
Normal file
46
src/utils/game.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
export function addLetter(key: any, current: string, letter: string) {
|
||||
let indexes = key[letter];
|
||||
for (const i of indexes) {
|
||||
current = current.slice(0, i) + letter.toUpperCase() + current.slice(i+1);
|
||||
};
|
||||
return current;
|
||||
};
|
||||
|
||||
export function convertToKey(phrase: string) {
|
||||
let key: {[index: string]: number[]} = {};
|
||||
for (var i = 0; i < phrase.length; i++) {
|
||||
let letter = phrase[i].toUpperCase();
|
||||
if (!letter.match(/[a-zA-Z]/)) { continue };
|
||||
if (key[letter] == null) {
|
||||
key[letter] = [];
|
||||
};
|
||||
key[letter].push(i);
|
||||
};
|
||||
return key;
|
||||
};
|
||||
|
||||
export function anonymizePhrase(phrase: string) {
|
||||
let anon = ``;
|
||||
for (const letter of phrase) {
|
||||
if (letter.match(/[A-Za-z]/)) {
|
||||
anon += `_`;
|
||||
} else {
|
||||
anon += letter;
|
||||
};
|
||||
};
|
||||
return anon;
|
||||
};
|
||||
|
||||
export function spacePhrase(phrase: string) {
|
||||
let spaced = ``;
|
||||
for (const letter of phrase) {
|
||||
if (letter.match(/[A-Za-z]/)) {
|
||||
spaced += `${letter} `;
|
||||
} else if (letter == ` `) {
|
||||
spaced += `█ `;
|
||||
} else {
|
||||
spaced += letter;
|
||||
};
|
||||
};
|
||||
return spaced;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue