Compare commits

...

5 Commits

Author SHA1 Message Date
f8b98de8b0 feat: добавить модуль вывода справочной информации и интегрировать его в бота
- Вынесен текст справки и функция отправки справочного сообщения в отдельный модуль infoSender.js
- При старте бота в личных сообщениях автоматически отправляется справка
- Добавлена проверка на групповой чат для команды /summy и общего обработчика сообщений
- В коде бота закомментирована устаревшая функция sendHelp с примером старой справки
- Обновлен формат отправки справки с Markdown на более структурированный и информативный текст
2025-06-30 21:16:43 +03:00
9f32e97eca fix: удалить исходное сообщение после команды /summy
Добавлена строка await ctx.deleteMessage() для удаления сообщения пользователя с командой /summy, чтобы избежать захламления чата.
2025-06-30 20:46:34 +03:00
c0cda72db5 fix(bot): сделать проверку isAdmin асинхронной и добавить логирование ошибок
- Исправлен метод isAdmin на асинхронный с ожиданием результата
- Добавлен вывод ошибок в лог при проверке статуса пользователя
- В хэндлере команды /summy добавлена проверка прав администратора с удалением сообщения, если пользователь не админ
2025-06-30 20:41:54 +03:00
523c533aea fix(bot): убрать неиспользуемую функцию searchInCache из импорта promptResponser 2025-06-30 20:37:46 +03:00
f22e89a461 fix(bot): убрать отладочные console.log и закомментировать команды summary
Удалены лишние console.log для чистоты вывода и закомментирован блок команд summary_day, summary_hours и summary_last для временного отключения их обработки.
2025-06-30 20:36:59 +03:00
2 changed files with 158 additions and 65 deletions

154
bot.js
View File

@ -5,8 +5,9 @@ const { OpenRouterClient } = require('openrouter-kit');
const { getPrompt } = require('./prompts.js'); const { getPrompt } = require('./prompts.js');
const logger = require('./logger.js'); const logger = require('./logger.js');
const callAI = require("./requestAI"); const callAI = require("./requestAI");
const {searchInCache, searchInPrompts, saveInPrompts} = require("./promptResponser"); const {searchInPrompts, saveInPrompts} = require("./promptResponser");
const INSTRUCTIONS = require("./promptGen"); const INSTRUCTIONS = require("./promptGen");
const {sendHelp} = require("./infoSender");
require('dotenv').config(); require('dotenv').config();
const char = {name:'marina'} const char = {name:'marina'}
class TelegramHistoryBot { class TelegramHistoryBot {
@ -29,14 +30,16 @@ class TelegramHistoryBot {
this.init(); this.init();
} }
isAdmin (ctx, userId = ctx.from.id) { async isAdmin(ctx, userId = ctx.from.id) {
try { try {
const member = ctx.getChatMember(userId) const member = await ctx.getChatMember(userId)
return ['creator', 'administrator'].includes(member.status) return ['creator', 'administrator'].includes(member.status)
} catch { } catch (error) {
logger.error('Ошибка проверки статуса пользователя:', error)
return false return false
} }
} }
async init() { async init() {
try { try {
await this.loadHistory(); await this.loadHistory();
@ -69,13 +72,33 @@ class TelegramHistoryBot {
} }
setupHandlers() { setupHandlers() {
const isGroupChat = (ctx) => {
return ctx.chat.type === 'group' || ctx.chat.type === 'supergroup';
};
this.bot.start(async (ctx) => {
if (isGroupChat(ctx)) {
return; // Игнорируем в группах
}
await sendHelp(ctx);
});
this.bot.command('summy', async (ctx) => { this.bot.command('summy', async (ctx) => {
if (!(await this.isAdmin(ctx))) {
await ctx.deleteMessage()
return
}
if (!isGroupChat(ctx)) {
await ctx.reply('❗ Эта команда работает только в группах');
return;
}
const message = ctx.message.text || ''; const message = ctx.message.text || '';
await ctx.deleteMessage();
const args = message.replace(/^\/summy(@\w+)?\s*/, ''); // удаляет /summy и возможный @botname const args = message.replace(/^\/summy(@\w+)?\s*/, ''); // удаляет /summy и возможный @botname
const trimmed = args.trim(); // удаляет лишние пробелы по краям, если нужно const trimmed = args.trim(); // удаляет лишние пробелы по краям, если нужно
logger.info('📊 Получена команда /summy с запросом: ' + trimmed); logger.info('📊 Получена команда /summy с запросом: ' + trimmed);
let request = await callAI('', trimmed, 'request'); let request = await callAI('', trimmed, 'request');
console.log('получили отвкт: ', typeof request, request)
if (typeof request === 'string') { if (typeof request === 'string') {
try { try {
@ -84,7 +107,7 @@ console.log('получили отвкт: ', typeof request, request)
request = {persona: "Карл Маркс", messages: 22, hours: 0}; request = {persona: "Карл Маркс", messages: 22, hours: 0};
} }
} }
console.log('ищем персону')
let prompt = await searchInPrompts(request["persona"]) let prompt = await searchInPrompts(request["persona"])
if (!prompt) { if (!prompt) {
logger.info('⚠️ Не найден подходящий prompt для запроса, генерируем...') logger.info('⚠️ Не найден подходящий prompt для запроса, генерируем...')
@ -93,54 +116,54 @@ console.log('ищем персону')
} else { } else {
logger.info('✅ Найден подходящий prompt для запроса') logger.info('✅ Найден подходящий prompt для запроса')
} }
//handleSummaryCommand
const options = {persona:request["persona"], promptToUse:prompt} const options = {persona:request["persona"], promptToUse:prompt}
if (request["messages"]>0) { if (request["messages"]>0) {
await this.handleSummaryCommand(ctx, 'last', request["messages"], options); await this.handleSummaryCommand(ctx, 'last', request["messages"], options);
} else { } else {
await this.handleSummaryCommand(ctx, 'hours', request["hours"], options); await this.handleSummaryCommand(ctx, 'hours', request["hours"], options);
} }
//await ctx.reply(prompt)
}); });
// Команды суммаризации - должны быть ДО обработки обычных сообщений // Команды суммаризации - должны быть ДО обработки обычных сообщений
this.bot.command('summary_day', async (ctx) => { // this.bot.command('summary_day', async (ctx) => {
// if (!this.isAdmin(ctx)) { // // if (!this.isAdmin(ctx)) {
// await ctx.deleteMessage // // await ctx.deleteMessage
// return // // return
// // }
// logger.info('📊 Получена команда summary_day');
// const args = ctx.message.text.split(' ');
// if (args.length > 1) {
// char.name=args[1]
// } // }
logger.info('📊 Получена команда summary_day'); // await ctx.deleteMessage()
const args = ctx.message.text.split(' '); // await this.handleSummaryCommand(ctx, 'day');
if (args.length > 1) { // });
char.name=args[1] //
} // this.bot.command('summary_hours', async (ctx) => {
await ctx.deleteMessage() // logger.info('📊 Получена команда summary_hours');
await this.handleSummaryCommand(ctx, 'day'); // const args = ctx.message.text.split(' ');
}); // if (args.length < 2 || isNaN(parseInt(args[1]))) {
// await ctx.reply('❗ Укажите количество часов: /summary_hours 6');
this.bot.command('summary_hours', async (ctx) => { // return;
logger.info('📊 Получена команда summary_hours'); // }
const args = ctx.message.text.split(' '); // const hours = parseInt(args[1]);
if (args.length < 2 || isNaN(parseInt(args[1]))) { // await ctx.deleteMessage()
await ctx.reply('❗ Укажите количество часов: /summary_hours 6'); // await this.handleSummaryCommand(ctx, 'hours', hours);
return; // });
} //
const hours = parseInt(args[1]); // this.bot.command('summary_last', async (ctx) => {
await ctx.deleteMessage() // logger.info('📊 Получена команда summary_last');
await this.handleSummaryCommand(ctx, 'hours', hours); // const args = ctx.message.text.split(' ');
}); // if (args.length < 2 || isNaN(parseInt(args[1]))) {
// await ctx.reply('❗ Укажите количество сообщений: /summary_last 50');
this.bot.command('summary_last', async (ctx) => { // return;
logger.info('📊 Получена команда summary_last'); // }
const args = ctx.message.text.split(' '); // const count = parseInt(args[1]);
if (args.length < 2 || isNaN(parseInt(args[1]))) { // await ctx.deleteMessage()
await ctx.reply('❗ Укажите количество сообщений: /summary_last 50'); // await this.handleSummaryCommand(ctx, 'last', count);
return; // });
}
const count = parseInt(args[1]);
await ctx.deleteMessage()
await this.handleSummaryCommand(ctx, 'last', count);
});
// Команды помощи // Команды помощи
//this.bot.command('summary_help', async (ctx) => await this.sendHelp(ctx)); //this.bot.command('summary_help', async (ctx) => await this.sendHelp(ctx));
@ -149,6 +172,9 @@ console.log('ищем персону')
// Общий обработчик сообщений (исключая команды) // Общий обработчик сообщений (исключая команды)
this.bot.on('message', async (ctx) => { this.bot.on('message', async (ctx) => {
// Пропускаем все команды // Пропускаем все команды
if (!isGroupChat(ctx)) {
return;
}
if (ctx.message.text && ctx.message.text.startsWith('/')) { if (ctx.message.text && ctx.message.text.startsWith('/')) {
return; return;
} }
@ -506,26 +532,26 @@ ${conversationFlow}`;
return summary; return summary;
} }
async sendHelp(ctx) { // async sendHelp(ctx) {
const helpText = ` // const helpText = `
🤖 <b>Бот сохраняет всю историю чата</b> // 🤖 <b>Бот сохраняет всю историю чата</b>
//
📊 <b>Команды суммаризации:</b> // 📊 <b>Команды суммаризации:</b>
/summary_day - суммаризация за сутки // /summary_day - суммаризация за сутки
/summary_hours N - за последние N часов // /summary_hours N - за последние N часов
/summary_last N - последние N сообщений // /summary_last N - последние N сообщений
//
💡 <b>Примеры:</b> // 💡 <b>Примеры:</b>
/summary_hours 6 - за последние 6 часов // /summary_hours 6 - за последние 6 часов
/summary_last 50 - последние 50 сообщений // /summary_last 50 - последние 50 сообщений
//
Бот сохраняет все сообщения и создает живые истории на основе переписки. // Бот сохраняет все сообщения и создает живые истории на основе переписки.
//
🔧 Поддерживаются все типы сообщений: текст, фото, видео, аудио, документы, стикеры и др. // 🔧 Поддерживаются все типы сообщений: текст, фото, видео, аудио, документы, стикеры и др.
`.trim(); // `.trim();
//
await ctx.reply(helpText, { parse_mode: 'HTML' }); // await ctx.reply(helpText, { parse_mode: 'HTML' });
} // }
} }
// Запуск бота // Запуск бота

67
infoSender.js Normal file
View File

@ -0,0 +1,67 @@
/**
* Модуль для отправки справочной информации
*/
const helpText = `
🚀 **САММАРИ БОТ** - *Ваш умный помощник для переписок!*
*Полностью бесплатный сервис от [Rockzo.ru](https://rockzo.ru)*
🎭 **Магия персонажей в действии!**
Превратите скучную переписку в увлекательный анализ через призму любимых персонажей!
🔥 **Главная команда:**
\`/summy [ваш запрос]\` - создайте уникальную суммаризацию!
💡 **Примеры использования:**
\`/summy Проанализируй последние 50 сообщений как Шерлок Холмс\`
\`/summy Виталий Бианки, за последние сутки\`
\`/summy Расскажи как Стив Джобс о наших идеях за 3 часа\`
\`/summy Оцени дискуссию глазами психолога, 100 сообщений\`
🎨 **Не бойтесь экспериментировать!**
Пробуйте разных персонажей: от классиков до современных героев
Задавайте необычные ракурсы анализа
Выбирайте ЛИБО количество сообщений, ЛИБО временной период
Придумывайте креативные подходы к анализу!
**Важная информация:**
🏢 Работает только в группах и каналах
👑 Требуются права администратора для использования
💬 В личке доступна только эта справка
🆓 **Абсолютно бесплатно навсегда!**
📊 Указывайте либо количество сообщений, либо временной период (не комбинируйте!)
🌟 *Превратите каждую переписку в произведение искусства!*
---
💻 Разработано с командой **[Rockzo.ru](https://rockzo.ru)**
`;
/**
* Отправляет справочное сообщение пользователю
* @param {Object} ctx - Контекст Telegraf
* @returns {Promise<void>}
*/
async function sendHelp(ctx) {
try {
await ctx.reply(helpText, { parse_mode: 'Markdown' });
} catch (error) {
// Если Markdown не работает, отправляем обычный текст
const plainText = helpText.replace(/[`*_]/g, '');
await ctx.reply(plainText);
}
}
/**
* Получить текст справки (без отправки)
* @returns {string} Текст справки
*/
function getHelpText() {
return helpText;
}
module.exports = {
sendHelp,
getHelpText
};