Add Node.js client

This commit is contained in:
Changhua
2023-01-20 11:33:47 +08:00
parent 41f73ec8c3
commit 64e9e812e9
20 changed files with 4841 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
export class Context {}
export class Interaction {
constructor(input: string) {
this.input = input;
this.options = {};
}
input: string;
output?: string;
options: any;
}
export interface Command {
name: string;
follow: (interaction: Interaction) => number;
run: (ctx: Context, interaction: Interaction) => string | Promise<string>;
}
+29
View File
@@ -0,0 +1,29 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { log } from '../utils/log';
import { Interaction, Command, Context } from './base-command';
import rsp from './rock-scissors-paper';
import stock from './stock';
let commands: Command[] = [rsp, stock];
export const handleCommand = async (ctx: Context, input: string): Promise<string> => {
const interaction = new Interaction(input);
const choice = commands
.map((c) => {
return { score: c.follow(interaction), command: c };
})
?.sort((a, b) => {
return a.score - b.score;
})
?.filter((x) => x.score > 0)
?.pop();
if (!choice) {
log.debug('no command found');
return '';
}
const reply = await choice.command.run(ctx, interaction);
return reply;
};
+38
View File
@@ -0,0 +1,38 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { log } from '../utils/log';
import { Interaction, Command, Context } from './base-command';
function RandomNum(max: number): number {
return Math.floor(Math.random() * (max + 1));
}
const keywords = ['rock', 'paper', 'scissors'];
export default {
name: 'rock-scissors-paper',
follow: (interaction: Interaction): number => {
const i = keywords.find((k) => {
return interaction.input.includes(k);
});
log.debug(`rock-scissors-paper follow-up: ${i}`);
interaction.options.pick = i ?? undefined;
return i ? 1 : 0;
},
run: (ctx: Context, interaction: Interaction): string => {
const pick: string = interaction.options.pick as string;
const playerPick = keywords.findIndex((x) => x == pick);
const botPick = RandomNum(2);
let result = 'tied';
if (playerPick == botPick) result = 'Tied';
else if (playerPick == 0 && botPick == 2) result = 'Win';
else if ((playerPick - botPick) % 3 == 1) result = 'Win';
else result = 'Lose';
const content = `You picked **${pick}** and I picked **${keywords[botPick]}**, You **${result}**`;
return content;
}
} as Command;
+28
View File
@@ -0,0 +1,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { stocks } from 'stock-api';
import { Interaction, Command, Context } from './base-command';
function getPrice(code: string): Promise<string> {
return stocks.tencent.getStocks([code]).then((res) => {
return JSON.stringify(res[0]);
});
}
export default {
name: 'stock',
follow: (interaction: Interaction): number => {
let match = /(S[HZ]\d{6})/.exec(interaction.input);
if (match) {
let stock = match && match[0];
interaction.options.stock = stock;
return 1;
}
return 0;
},
run: async (ctx: Context, interaction: Interaction): Promise<string> => {
const pick: string = interaction.options.stock as string;
const content = await getPrice(pick);
return content;
}
} as Command;