- Одна formatUtc и один displayName(profile) вместо копий в разных слоях
- commandOf/mentionsUser/textWithoutMention работают по entities для текста и подписей;
убраны askInCaption, regex-поиск упоминаний и отдельный composer.command("ask")
- Фото скачиваются только если модель их видит; пустой вопрос с картинкой формулирует промпт
- Поддержка фото задаётся явно для моделей по умолчанию, для своей AI_MODEL — через AI_IMAGE_INPUT
- Активность участников считается по сохранённой истории, а не отдельными счётчиками;
один хендлер для message и edited_message, упоминания не пишутся дважды
- SQLite: synchronous = NORMAL для WAL
- Кнопки не-админов отклоняются через bot.drop(isAdmin)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
45 lines
1.9 KiB
TypeScript
45 lines
1.9 KiB
TypeScript
/** Личность бота. Список задаётся в `constants/personas.ts` и заливается в БД скриптом `seed`. */
|
||
export interface Persona {
|
||
/** Латиница, цифры, _ и -: id попадает в callback_data (лимит 64 байта). */
|
||
id: string;
|
||
name: string;
|
||
prompt: string;
|
||
}
|
||
|
||
export interface ChatMessage {
|
||
chatId: number;
|
||
messageId: number;
|
||
/** Telegram ID автора; null — для сообщений от имени канала/группы и старых записей. */
|
||
userId: number | null;
|
||
/** Unix-время в секундах, как в Telegram. */
|
||
date: number;
|
||
author: string;
|
||
text: string;
|
||
replyToMessageId: number | null;
|
||
}
|
||
|
||
/** Участник чата, которого бот видел: писал сам или был упомянут по имени-ссылке. */
|
||
export interface ChatMember {
|
||
userId: number;
|
||
username: string | null;
|
||
firstName: string;
|
||
lastName: string | null;
|
||
/** Сколько его сообщений в сохранённой истории чата. */
|
||
messageCount: number;
|
||
/** Unix-время последнего сохранённого сообщения; 0 — сообщений в истории нет. */
|
||
lastSeen: number;
|
||
}
|
||
|
||
/** Данные пользователя Telegram, которые бот запоминает об участнике. */
|
||
export type MemberProfile = Pick<ChatMember, "userId" | "username" | "firstName" | "lastName">;
|
||
|
||
/** Откуда фото: из самого вопроса или из сообщения, на которое ответил спрашивающий. */
|
||
export type ImageSource = "question" | "replied";
|
||
|
||
/** Картинка, которую бот передаёт модели вместе с вопросом. */
|
||
export interface ImageAttachment {
|
||
data: Uint8Array;
|
||
mimeType: string;
|
||
source: ImageSource;
|
||
}
|