Files
tg-chat-bot/src/base/command.ts
T
melod1n a736f786c2 feat(openai): add chat streaming and model commands
- add /openai (/chatgpt) chat command using OpenAI Responses API (streaming + incremental edits)
- add /openAIListModels, /openAIGetModel, /openAISetModel
- introduce base Command class and migrate non-chat commands to it
- wire OpenAI client + env vars (OPENAI_API_KEY, OPENAI_MODEL)
- bump deps (@google/genai, systeminformation, @types/node) and add openai
2026-02-03 13:39:01 +03:00

59 lines
1.6 KiB
TypeScript

import {Message} from "typescript-telegram-bot-api";
import {Requirements} from "./requirements";
export type ArgsMode = "none" | "optional" | "required";
export abstract class Command {
regexp?: RegExp | null;
command?: string | string[];
argsMode: ArgsMode = "none";
requirements?: Requirements = null;
title?: string;
description?: string;
get finalRegexp(): RegExp {
if (!this.regexp) {
const inferred = name(this.constructor.name);
const names = this.command ?? inferred;
this.regexp = createCommandRegExp(names, this.argsMode);
}
return this.regexp;
}
abstract execute(
msg: Message,
match?: RegExpExecArray
): Promise<void>;
}
export function name(s: string) {
return s
.replace(/Command$/, "")
.replace(/([a-z0-9])([A-Z])/g, "$1$2")
.toLowerCase();
}
function escapeRe(s: string) {
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
export function createCommandRegExp(
names: string | string[],
argsMode: ArgsMode = "optional",
) {
const list = Array.isArray(names) ? names : [names];
const group = list.map(escapeRe).join("|");
const base = `^\\/(${group})(?:@([\\w_]+))?`; // (1)=cmd, (2)=bot
const tail =
argsMode === "none"
? "\\s*$"
: argsMode === "required"
? "\\s+([\\s\\S]+)\\s*$" // (3)=args обязателен
: "(?:\\s+([\\s\\S]+))?\\s*$"; // (3)=args опционален
return new RegExp(base + tail, "i");
}