Участники чата, промпты в файлах, личности только из кода
- Бот запоминает участников (имя, фамилия, ник, активность) и ID автора каждого сообщения - Упоминания в вопросе (@ник и по имени-ссылке) передаются модели с данными участника - Новые инструменты агента: list_chat_members, read_member_messages (поиск по нику/имени) - Бот обращается к людям по имени - Промпты вынесены в prompts/system.md и prompts/personas/<id>.md - Личности больше не редактируются из чата: скрипт seed синхронизирует их с БД при старте - Оставлена одна личность boltun (Dirty D) - Миграция старых баз: колонка messages.user_id Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,15 @@
|
||||
import type { Message, User } from "grammy/types";
|
||||
import type { ChatMessage } from "../types.js";
|
||||
import type { Message, MessageEntity, User } from "grammy/types";
|
||||
import type { ChatMessage, MemberProfile } from "../types.js";
|
||||
|
||||
const TELEGRAM_MESSAGE_LIMIT = 4096;
|
||||
|
||||
export const toMemberProfile = (user: User): MemberProfile => ({
|
||||
userId: user.id,
|
||||
username: user.username ?? null,
|
||||
firstName: user.first_name,
|
||||
lastName: user.last_name ?? null,
|
||||
});
|
||||
|
||||
export const displayName = (user: User): string => {
|
||||
const name = [user.first_name, user.last_name].filter(Boolean).join(" ");
|
||||
|
||||
@@ -43,6 +50,7 @@ export const toChatMessage = (msg: Message): ChatMessage | undefined => {
|
||||
return {
|
||||
chatId: msg.chat.id,
|
||||
messageId: msg.message_id,
|
||||
userId: msg.from?.id ?? null,
|
||||
date: msg.date,
|
||||
author: msg.from ? displayName(msg.from) : (msg.sender_chat?.title ?? "Аноним"),
|
||||
text,
|
||||
@@ -50,6 +58,26 @@ export const toChatMessage = (msg: Message): ChatMessage | undefined => {
|
||||
};
|
||||
};
|
||||
|
||||
const messageEntities = (msg: Message): { text: string; entities: MessageEntity[] } => ({
|
||||
text: msg.text ?? msg.caption ?? "",
|
||||
entities: msg.entities ?? msg.caption_entities ?? [],
|
||||
});
|
||||
|
||||
/** Ники из упоминаний `@username` (без собаки), без повторов. */
|
||||
export const mentionedUsernames = (msg: Message): string[] => {
|
||||
const { text, entities } = messageEntities(msg);
|
||||
|
||||
const usernames = entities
|
||||
.filter((entity) => entity.type === "mention")
|
||||
.map((entity) => text.slice(entity.offset + 1, entity.offset + entity.length));
|
||||
|
||||
return [...new Set(usernames)];
|
||||
};
|
||||
|
||||
/** Пользователи, упомянутые по имени-ссылке — так Telegram упоминает людей без ника. */
|
||||
export const mentionedUsers = (msg: Message): User[] =>
|
||||
messageEntities(msg).entities.flatMap((entity) => (entity.type === "text_mention" ? [entity.user] : []));
|
||||
|
||||
/** Режет длинный ответ на части под лимит Telegram, по возможности по переносам строк. */
|
||||
export const splitMessage = (text: string): string[] => {
|
||||
if (text.length <= TELEGRAM_MESSAGE_LIMIT) return text ? [text] : [];
|
||||
|
||||
Reference in New Issue
Block a user