update error logging

cutting all kind of prefixes for prompt making
This commit is contained in:
2026-01-28 16:40:29 +03:00
parent 9a76d36568
commit 63c64dfa8e
19 changed files with 107 additions and 100 deletions
+2 -1
View File
@@ -2,6 +2,7 @@
import {CallbackQuery, InlineKeyboardButton} from "typescript-telegram-bot-api";
import {Requirements} from "./requirements";
import {bot} from "../index";
import {logError} from "../util/utils";
export abstract class CallbackCommand {
@@ -22,7 +23,7 @@ export abstract class CallbackCommand {
}
async answerCallbackQuery(query: CallbackQuery): Promise<void> {
bot.answerCallbackQuery(this.getOptions(query)).catch(console.error);
bot.answerCallbackQuery(this.getOptions(query)).catch(logError);
}
asButton(): InlineKeyboardButton {
+14 -6
View File
@@ -8,8 +8,6 @@ import {Requirements} from "../base/requirements";
import {Requirement} from "../base/requirement";
import {Environment} from "../common/environment";
const cancelledText = "```Ollama\n❌ Отменено```";
export class OllamaCancel extends CallbackCommand {
data = "/cancel_ollama";
@@ -48,17 +46,27 @@ export class OllamaCancel extends CallbackCommand {
if (msg?.text?.trim()?.length > 0) {
content = msg?.text.trim();
if (content.length + cancelledText.length > 4096) {
content = content.substring(0, 4096 - cancelledText.length - 2) + "\n";
if (content.length + Environment.ollamaCancelledText.length > 4096) {
content = content.substring(0, 4096 - Environment.ollamaCancelledText.length - 2) + "\n";
}
}
const newText = `${content ? content : ""}${Environment.ollamaCancelledText}`;
try {
await bot.editMessageText({
chat_id: chatId,
message_id: messageId,
text: `${content ? content : ""}${cancelledText}`,
text: newText,
parse_mode: "Markdown",
reply_markup: {inline_keyboard: []},
}).catch(logError);
});
if (msg) {
await MessageStore.put(msg);
}
} catch (e) {
logError(e);
}
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ export class Ae extends ChatCommand {
return;
}
console.error(`${text}
logError(`${text}
* Stacktrace: ${e.stack}`);
await oldSendMessage(msg, text).catch(logError);
+10 -11
View File
@@ -1,19 +1,18 @@
import {ChatCommand} from "../base/chat-command";
import {Message} from "typescript-telegram-bot-api";
import {
collectReplyChainText,
escapeMarkdownV2Text,
extractText,
logError,
oldReplyToMessage,
startIntervalEditor
} from "../util/utils";
import {Environment} from "../common/environment";
import {bot, googleAi} from "../index";
import {MessageStore} from "../common/message-store";
import {Requirements} from "../base/requirements";
import {Requirement} from "../base/requirement";
import {ApiError} from "@google/genai";
import {
collectReplyChainText,
escapeMarkdownV2Text,
logError,
oldReplyToMessage,
startIntervalEditor
} from "../util/utils";
export class GeminiChat extends ChatCommand {
command = "gemini";
@@ -34,13 +33,13 @@ export class GeminiChat extends ChatCommand {
const chatId = msg.chat.id;
const messageParts = await collectReplyChainText(msg, "/gemini");
const messageParts = await collectReplyChainText(msg);
console.log("MESSAGE PARTS", messageParts);
const chatMessages = messageParts.map(part => {
return {
role: part.bot ? "assistant" : "user",
content: (Environment.USE_NAMES_IN_PROMPT && !part.bot ? `MESSAGE FROM USER "${part.name}":\n` : "") + extractText(part.content, "/gemini")
content: (Environment.USE_NAMES_IN_PROMPT && !part.bot ? `MESSAGE FROM USER "${part.name}":\n` : "") + part.content
};
});
chatMessages.reverse();
@@ -134,7 +133,7 @@ export class GeminiChat extends ChatCommand {
await oldReplyToMessage(waitMessage, `⏱️ ${diff}s`);
}
} catch (error) {
console.error(error);
logError(error);
if (error instanceof ApiError) {
if (error.status === 429) {
+1 -1
View File
@@ -29,7 +29,7 @@ export class GeminiListModels extends ChatCommand {
parse_mode: "HTML"
});
} catch (e) {
console.error(e);
logError(e);
await replyToMessage({message: msg, text: "Не получилось загрузить список моделей"}).catch(logError);
}
}
+3 -4
View File
@@ -5,7 +5,6 @@ import {Message} from "typescript-telegram-bot-api";
import {
collectReplyChainText,
escapeMarkdownV2Text,
extractText,
logError,
oldReplyToMessage,
startIntervalEditor
@@ -34,14 +33,14 @@ export class MistralChat extends ChatCommand {
const chatId = msg.chat.id;
const messageParts = await collectReplyChainText(msg, "/mistral");
const messageParts = await collectReplyChainText(msg);
console.log("MESSAGE PARTS", messageParts);
const chatMessages = messageParts.map(part => {
const content = [];
content.push({
type: "text",
text: (Environment.USE_NAMES_IN_PROMPT && !part.bot ? `MESSAGE FROM USER "${part.name}":\n` : "") + extractText(part.content, Environment.BOT_PREFIX),
text: (Environment.USE_NAMES_IN_PROMPT && !part.bot ? `MESSAGE FROM USER "${part.name}":\n` : "") + part.content,
});
if (part.images && part.images.length > 0) {
@@ -143,7 +142,7 @@ export class MistralChat extends ChatCommand {
await oldReplyToMessage(waitMessage, `⏱️ ${diff}s`);
}
} catch (error) {
console.error(error);
logError(error);
await oldReplyToMessage(waitMessage, `Произошла ошибка!\n${error.toString()}`).catch(logError);
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ export class MistralListModels extends ChatCommand {
parse_mode: "HTML"
});
} catch (e) {
console.error(e);
logError(e);
await oldReplyToMessage(msg, "Не получилось загрузить список моделей").catch(logError);
}
}
+2 -3
View File
@@ -4,7 +4,6 @@ import {abortOllamaRequest, bot, getOllamaRequest, ollama, ollamaRequests} from
import {
collectReplyChainText,
escapeMarkdownV2Text,
extractText,
logError,
oldReplyToMessage,
startIntervalEditor
@@ -37,7 +36,7 @@ export class OllamaChat extends ChatCommand {
const chatMessages = messageParts.map(part => {
return {
role: part.bot ? "assistant" : "user",
content: (Environment.USE_NAMES_IN_PROMPT && !part.bot ? `MESSAGE FROM USER "${part.name}":\n` : "") + extractText(part.content, Environment.BOT_PREFIX),
content: (Environment.USE_NAMES_IN_PROMPT && !part.bot ? `MESSAGE FROM USER "${part.name}":\n` : "") + part.content,
images: part.images
};
});
@@ -198,7 +197,7 @@ export class OllamaChat extends ChatCommand {
reply_markup: {inline_keyboard: []}
}).catch(logError);
console.error(error);
logError(error);
await oldReplyToMessage(waitMessage, `Произошла ошибка!\n${error.toString()}`).catch(logError);
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ export class OllamaListModels extends ChatCommand {
parse_mode: "HTML"
});
} catch (e) {
console.error(e);
logError(e);
await oldReplyToMessage(msg, "Не получилось загрузить список моделей").catch(logError);
}
}
+1 -1
View File
@@ -182,7 +182,7 @@ export class OllamaPrompt extends ChatCommand {
reply_markup: {inline_keyboard: []}
}).catch(logError);
console.error(error);
logError(error);
await oldReplyToMessage(waitMessage, `Произошла ошибка!\n${error.toString()}`).catch(logError);
}
}
+2 -2
View File
@@ -4,7 +4,7 @@ import {Requirement} from "../base/requirement";
import {Message} from "typescript-telegram-bot-api";
import {bot, ollama} from "../index";
import {WebSearchResponse} from "../model/web-search-response";
import {editMessageText} from "../util/utils";
import {editMessageText, logError} from "../util/utils";
import {Environment} from "../common/environment";
export class OllamaSearch extends ChatCommand {
@@ -42,7 +42,7 @@ export class OllamaSearch extends ChatCommand {
await editMessageText(chatId, wait.message_id, message);
} catch (error) {
console.error(error);
logError(error);
}
return Promise.resolve();
}
+2 -2
View File
@@ -34,7 +34,7 @@ try {
GlobalFonts.registerFromPath("./assets/JetBrainsMono-Italic.ttf", "JetBrainsMonoItalic");
GlobalFonts.registerFromPath("./assets/JetBrainsMono-Regular.ttf", "JetBrainsMonoRegular");
} catch (e) {
console.error(e);
logError(e);
}
export class Quote extends ChatCommand {
@@ -75,7 +75,7 @@ export class Quote extends ChatCommand {
},
}).catch(logError);
} catch (e) {
console.error(e);
logError(e);
await oldSendMessage(msg, "Не смог собрать цитату 😢").catch(logError);
}
}
+1
View File
@@ -36,6 +36,7 @@ export class Environment {
static MISTRAL_MODEL: string;
static waitText = "⏳ Дайте-ка подумать...";
static ollamaCancelledText = "```Ollama\n❌ Отменено```";
static load() {
Environment.BOT_TOKEN = process.env.BOT_TOKEN;
+6 -8
View File
@@ -1,7 +1,6 @@
import {StoredMessage} from "../model/stored-message";
import {Message} from "typescript-telegram-bot-api";
import {extractTextMessage} from "../util/utils";
import {Environment} from "./environment";
import {extractTextMessage, isStoredMessage} from "../util/utils";
import {messageDao} from "../index";
export class MessageStore {
@@ -15,19 +14,18 @@ export class MessageStore {
return this.map;
}
static async put(m: Message, prefix: string = Environment.BOT_PREFIX) {
const msg: StoredMessage = {
static async put(m: Message | StoredMessage) {
const msg: StoredMessage = isStoredMessage(m) ? m : {
chatId: m.chat.id,
id: m.message_id,
replyToMessageId: m.reply_to_message?.message_id ?? null,
fromId: m.from.id,
text: extractTextMessage(m, prefix),
text: extractTextMessage(m),
date: m.date ?? 0,
};
this.map.set(this.key(m.chat.id, m.message_id), msg);
await messageDao.insert(messageDao.mapTo([m]));
this.map.set(this.key(msg.chatId, msg.id), msg);
await messageDao.insert(messageDao.mapStoredTo([msg]));
}
static async get(chatId: number, messageId: number): Promise<StoredMessage | null> {
+2 -1
View File
@@ -1,6 +1,7 @@
import "dotenv/config";
import {drizzle, LibSQLDatabase} from "drizzle-orm/libsql";
import {Environment} from "../common/environment";
import {logError} from "../util/utils";
export class DatabaseManager {
@@ -10,7 +11,7 @@ export class DatabaseManager {
try {
DatabaseManager.db = drizzle(Environment.DB_PATH);
} catch (e) {
console.error(e);
logError(e);
}
}
}
+3 -2
View File
@@ -1,5 +1,6 @@
import * as fs from "fs";
import {Environment} from "../common/environment";
import {logError} from "../util/utils";
export let muted: Set<number> = new Set<number>();
@@ -57,7 +58,7 @@ export async function readData(): Promise<void> {
return Promise.resolve();
} catch (e) {
console.error(e);
logError(e);
return Promise.reject(e);
}
}
@@ -91,7 +92,7 @@ export async function retrieveAnswers(): Promise<void> {
json.day.forEach(e => dayAnswers.push(e));
return Promise.resolve();
} catch (e) {
console.error(e);
logError(e);
return Promise.reject(e);
}
}
+7 -9
View File
@@ -3,10 +3,8 @@ import {DatabaseManager} from "./database-manager";
import {StoredMessage} from "../model/stored-message";
import {and, eq} from "drizzle-orm";
import {inArray} from "drizzle-orm/sql/expressions/conditions";
import {Message} from "typescript-telegram-bot-api";
import {Dao} from "../base/dao";
import {buildExcludedSet, extractTextMessage} from "../util/utils";
import {Environment} from "../common/environment";
import {buildExcludedSet} from "../util/utils";
export class MessageDao extends Dao<StoredMessage> {
@@ -82,14 +80,14 @@ export class MessageDao extends Dao<StoredMessage> {
return true;
}
mapTo(messages: Message[]): MessageInsert[] {
mapStoredTo(messages: StoredMessage[]): MessageInsert[] {
return messages.map(msg => {
return {
chatId: msg.chat.id,
id: msg.message_id,
replyToMessageId: msg.reply_to_message?.message_id,
fromId: msg.from.id,
text: extractTextMessage(msg, Environment.BOT_PREFIX),
chatId: msg.chatId,
id: msg.id,
replyToMessageId: msg.replyToMessageId,
fromId: msg.fromId,
text: msg.text,
date: msg.date,
};
});
+5 -5
View File
@@ -71,7 +71,7 @@ import {GeminiGetModel} from "./commands/gemini-get-model";
import {GeminiSetModel} from "./commands/gemini-set-model";
import {Debug} from "./commands/debug";
process.setUncaughtExceptionCaptureCallback(console.error);
process.setUncaughtExceptionCaptureCallback(logError);
Environment.load();
DatabaseManager.init();
@@ -112,7 +112,7 @@ export function abortOllamaRequest(uuid: string): boolean {
updateOllamaRequest(uuid, {...request, done: true});
return true;
} catch (e) {
console.error(e);
logError(e);
return false;
}
}
@@ -227,7 +227,7 @@ async function main() {
console.log("Bot started!");
} catch (error) {
console.error(error);
logError(error);
}
}
@@ -336,7 +336,7 @@ bot.on("inline_query", async (query) => {
results: queryResults,
});
} catch (e) {
console.error(e);
logError(e);
}
} else {
await bot.answerInlineQuery({
@@ -351,4 +351,4 @@ bot.on("callback_query", async (query) => {
await findAndExecuteCallbackCommand(callbackCommands, query);
});
main().catch(console.error);
main().catch(logError);
+37 -35
View File
@@ -40,7 +40,7 @@ export const ignoreIfMarkupFailed = (e: Error | TelegramError) => {
}
};
export const logError = (e: Error | TelegramError) => {
export const logError = (e: Error | TelegramError | string) => {
console.error(e);
};
@@ -231,7 +231,7 @@ export async function editMessageText(chatId: number, messageId: number, message
}).catch(ignoreIfMarkupFailed);
return Promise.resolve();
} catch (e) {
console.error(e);
logError(e);
if (e instanceof TelegramError && e.response.description.includes("Too Many Requests")) {
const delay = Number(e.message.split("retry after ")[1]) || 30;
@@ -301,7 +301,7 @@ export async function oldReplyToMessage(message: Message, text: string, parseMod
}
export async function sendErrorPlaceholder(message: Message): Promise<Message> {
return await sendMessage({message: message, text: "Произошла ошибка ⚠️"}).catch(console.error) as Message;
return await sendMessage({message: message, text: "Произошла ошибка ⚠️"}).catch(logError) as Message;
}
export async function initSystemSpecs(): Promise<void> {
@@ -446,34 +446,32 @@ export async function getUserAvatar(userId: number): Promise<Buffer | null> {
return Buffer.from(res.data);
}
export function extractTextMessage(msg: Message, prefix: string = ""): string | null {
let text = (msg?.text ?? msg?.caption ?? "").trim();
if (text.toLowerCase().startsWith(prefix.toLowerCase())) {
text = text.substring(prefix.length);
}
text = text.trim();
export function extractTextMessage(msg: Message | StoredMessage | string): string | null {
const text = (typeof msg === "string" ? msg : isStoredMessage(msg) ? msg.text : msg?.text ?? msg?.caption ?? "").trim();
if (text.length === 0) return null;
return text;
}
export function extractTextStored(msg: StoredMessage, prefix: string): string {
let text = (msg?.text ?? "").trim();
export function cutPrefixes(msg: Message | StoredMessage | string): string {
const prefixes = [
Environment.BOT_PREFIX,
`/gemini@${botUser.username}`,
"/gemini",
`/mistral@${botUser.username}`,
"/mistral"
];
const text = extractTextMessage(msg);
let newText = text;
for (const prefix of prefixes) {
if (text.toLowerCase().startsWith(prefix.toLowerCase())) {
text = text.substring(prefix.length).trim();
newText = newText.substring(prefix.length).trim();
break;
}
}
return text;
}
export function extractText(text: string, prefix: string): string {
if (!text) return "";
if (text.toLowerCase().startsWith(prefix.toLowerCase())) {
text = text.substring(prefix.length).trim();
}
return text;
return newText;
}
export function isStoredMessage(msg: Message | StoredMessage): msg is StoredMessage {
@@ -502,7 +500,7 @@ export async function loadImageIfExists(msg: Message | StoredMessage): Promise<s
try {
fs.writeFileSync(imageFilePath, src);
} catch (e) {
console.error(e);
logError(e);
imageFilePath = null;
}
}
@@ -511,18 +509,18 @@ export async function loadImageIfExists(msg: Message | StoredMessage): Promise<s
return imageFilePath;
}
export async function collectReplyChainText(triggerMsg: Message, prefix: string = Environment.BOT_PREFIX, limit: number = 40, includeTrigger = true): Promise<MessagePart[]> {
export async function collectReplyChainText(triggerMsg: Message, limit: number = 40, includeTrigger = true, cutPrefix: boolean = true): Promise<MessagePart[]> {
const chatId = triggerMsg.chat.id as number;
const parts: MessagePart[] = [];
if (includeTrigger) {
const t = extractTextMessage(triggerMsg, prefix);
const img = (await loadImageIfExists(triggerMsg)) /*|| triggerMsg.reply_to_message ?
(await loadImageIfExists(triggerMsg.reply_to_message)) : null*/;
if (t) {
const t = extractTextMessage(triggerMsg);
const text = cutPrefix ? cutPrefixes(t) : t;
const img = await loadImageIfExists(triggerMsg);
if (text) {
parts.push({
bot: triggerMsg.from.id === botUser.id,
content: t,
content: text,
name: triggerMsg.from.first_name,
images: img ? [img] : []
});
@@ -534,7 +532,8 @@ export async function collectReplyChainText(triggerMsg: Message, prefix: string
return parts;
}
const firstText = extractTextMessage(first, prefix);
const ft = extractTextMessage(first);
const firstText = cutPrefix ? cutPrefixes(ft) : ft;
if (firstText || first.photo) {
const img = await loadImageIfExists(first);
parts.push({
@@ -553,14 +552,17 @@ export async function collectReplyChainText(triggerMsg: Message, prefix: string
if (!parentId) break;
const parent = await messageDao.getById({chatId: chatId, id: parentId});
if (!parent?.text && !parent?.photoMaxSizeFilePath) break;
const pt = extractTextMessage(parent);
const parentText = cutPrefix ? cutPrefixes(pt) : pt;
if (!parentText && !parent?.photoMaxSizeFilePath) break;
const user = await UserStore.get(parent.fromId);
const img = await loadImageIfExists(parent);
parts.push({
bot: parent.fromId === botUser.id,
content: extractTextStored(parent, prefix),
content: parentText,
name: user?.firstName,
images: img ? [img] : []
});
@@ -829,7 +831,7 @@ export function startIntervalEditor(params: {
lastSent = next;
} catch (e) {
if ((e?.description ?? e?.message ?? "").includes("message is not modified")) return;
console.error("edit failed:", e);
logError("edit failed: " + e);
}
};