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
This commit is contained in:
@@ -1,58 +1,4 @@
|
||||
import {Message} from "typescript-telegram-bot-api";
|
||||
import {Requirements} from "./requirements";
|
||||
import {Command} from "./command";
|
||||
|
||||
export type ArgsMode = "none" | "optional" | "required";
|
||||
|
||||
export abstract class ChatCommand {
|
||||
|
||||
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");
|
||||
}
|
||||
export abstract class ChatCommand extends Command {
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
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");
|
||||
}
|
||||
Reference in New Issue
Block a user