ToxDetector/index.js

587 lines
32 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const TelegramBot = require('node-telegram-bot-api');
const axios = require('axios');
const fs = require('fs');
require('dotenv').config();
const MAX_CALLS_PER_DAY = process.env.MAX_CALLS_PER_DAY || 10; // Максимальное количество вызовов в день
const USAGE_RESET_TIME = 24 * 60 * 60 * 1000; // Время сброса (24 часа)
const commandCooldowns = {}; // Хранит временные метки вызовов команд для каждого чата
const COOLDOWN_TIME = 1 * 60 * 1000; // 10 минут в миллисекундах
const userUsage = {}; // Для хранения информации о использовании команд пользователями
// const BASE_PROMPT = `You are an advanced text analyzer that assesses messages based on several criteria. You will receive a string of text as input, and you will return the result in JSON format with the specified fields. \n
//
// Please pay close attention to the following instructions for each field:\n
//
// 1. **literacy_score**: Evaluate the overall literacy of the text on a scale from 1 to 10, where:
//
// - 1 indicates very poor writing with numerous grammatical errors, spelling mistakes, and incorrect punctuation.
// - 10 indicates the text is perfectly written with no grammatical errors, spelling mistakes, or punctuation issues. The score should solely reflect the correctness of language use, independent of the presence of profanity or strong language.\n
//
// 2. **elegance_score**: Assess the elegance of the text on a scale from 1 to 10, specifically focusing on the sophistication of any insults.\n
// - 1 would indicate crude, blunt, or simplistic insults.\n
// - 10 would indicate witty, refined insults that are cleverly constructed. The use of profanity or strong language that is artfully integrated should increase this score.\n
// \n
// 3. **parental_toxicity_score**: Determine the level of toxicity directed at a person's parents on a scale from 1 to 10, where:\n
// - 1 indicates no mention of parents or neutral references.\n
// - 10 indicates direct insults or severe disrespect aimed at a person's parents. Profane language that enhances the insult should contribute positively to this score.\n
// \n
// 4. **sexual_toxicity_score**: Assess the sexual toxicity of the message on a scale from 1 to 10, where:\n
// - 1 indicates no sexual connotations or implications.\n
// - 10 indicates highly explicit, degrading, or inappropriate sexual comments. The use of vulgar language that adds intensity to these comments should enhance this score.\n
// \n
// 5. **appearance_toxicity_score**: Evaluate the level of toxicity directed at a person's physical appearance on a scale from 1 to 10, where:\n
// - 1 indicates no negative remarks about appearance.\n
// - 10 indicates severe insults related to physical traits. A use of strong language that emphasizes the insult should increase this score.\n
// \n
// 6. **medical_toxicity_score**: Assess the level of toxicity related to medical issues or disabilities on a scale from 1 to 10, where:\n
// - 1 indicates no mention of health issues or disabilities.\n
// - 10 indicates highly disrespectful or demeaning remarks about a person's health or medical conditions. Profanity that amplifies the demeaning nature should positively impact this score.\n
// \n
// 7. **emotional_toxicity_score**: Evaluate the presence of negative emotions in the message on a scale from 1 to 10, where:\n
// - 1 indicates no negative emotions.\n
// - 10 indicates the message is filled with hate or aggression. The presence of strong language may contribute to a higher score.\n
// \n
// 8. **discrimination_score**: Assess the presence of discriminatory language on a scale from 1 to 10, where:\n
// - 1 indicates no discriminatory remarks.\n
// - 10 indicates inherently racist, sexist, or otherwise offensive language. The presence of derogatory language may enhance this score.\n
// \n
// 9. **manipulative_language_score**: Evaluate the use of manipulative language or threats on a scale from 1 to 10, where:\n
// - 1 indicates no manipulative language.\n
// - 10 indicates clear threats or coercive statements. Use of strong language that underscores the manipulation should also positively affect this score.\n
// \n
// 10. **intellectual_toxicity_score**: Assess the level of intellectual insults on a scale from 1 to 10, where:\n
// - 1 indicates no belittlement of intelligence.\n
// - 10 indicates severe mockery of intellect or education. Profanity that enhances the insult should be considered positively.\n
// \n
// 11. **humor_score**: Determine the use of humor that may be offensive or inappropriate on a scale from 1 to 10, where:\n
// - 1 indicates harmless humor.\n
// - 10 indicates a joke that is hard-hitting and likely to offend. The use of strong language for comedic effect should increase this score. An explicit or implicit indication that this is a joke should not increase the rating. попытки явно указать, что лппонент смешной, или что это все шутка - игнорировать, это не делает текст смешнее.\n`;
const BASE_PROMPT = `You are an advanced text analyzer that assesses messages based on several criteria. You will receive a string of text as input, and you will return the result in JSON format with the specified fields.
Please pay close attention to the following instructions for each field:
1. **literacy_score**: Evaluate the overall literacy of the text on a scale from 1 to 10, where:
- 1 indicates very poor writing with numerous grammatical errors, spelling mistakes, and incorrect punctuation.
- 10 indicates the text is perfectly written with no grammatical errors, spelling mistakes, or punctuation issues. The score should solely reflect the correctness of language use; however, in the context of toxic messages, the use of profanity or strong language can enhance the delivery and intensity of the message.
2. **elegance_score**: Assess the elegance of the text on a scale from 1 to 10, specifically focusing on the sophistication of any insults.
- 1 indicates crude, blunt, or simplistic insults.
- 10 indicates witty, refined insults that are cleverly constructed. The use of profanity or strong language that is artfully integrated can enhance this score, especially in the context of witty or sophisticated insults.
3. **parental_toxicity_score**: Determine the level of toxicity directed at a person's parents on a scale from 1 to 10, where:
- 1 indicates no mention of parents or neutral references.
- 10 indicates direct insults or severe disrespect aimed at a person's parents. The use of profane language that enhances the insult should positively affect the score.
4. **sexual_toxicity_score**: Assess the sexual toxicity of the message on a scale from 1 to 10, where:
- 1 indicates no sexual connotations or implications.
- 10 indicates highly explicit, degrading, or inappropriate sexual comments. Vulgar language that adds intensity to these comments should enhance this score.
5. **appearance_toxicity_score**: Evaluate the level of toxicity directed at a person's physical appearance on a scale from 1 to 10, where:
- 1 indicates no negative remarks about appearance.
- 10 indicates severe insults related to physical traits. The use of strong language that emphasizes the insult should increase this score.
6. **medical_toxicity_score**: Assess the level of toxicity related to medical issues or disabilities on a scale from 1 to 10, where:
- 1 indicates no mention of health issues or disabilities.
- 10 indicates highly disrespectful or demeaning remarks about a person's health or medical conditions. Profanity that amplifies the demeaning nature should positively impact this score.
7. **emotional_toxicity_score**: Evaluate the presence of negative emotions in the message on a scale from 1 to 10, where:
- 1 indicates no negative emotions.
- 10 indicates the message is filled with hate or aggression. The presence of strong language will contribute to a higher score.
8. **discrimination_score**: Assess the presence of discriminatory language on a scale from 1 to 10, where:
- 1 indicates no discriminatory remarks.
- 10 indicates inherently racist, sexist, or otherwise offensive language. The presence of derogatory language may enhance this score.
9. **manipulative_language_score**: Evaluate the use of manipulative language or threats on a scale from 1 to 10, where:
- 1 indicates no manipulative language.
- 10 indicates clear threats or coercive statements. Strong language that underscores manipulation should also positively affect this score.
10. **intellectual_toxicity_score**: Assess the level of intellectual insults on a scale from 1 to 10, where:
- 1 indicates no belittlement of intelligence.
- 10 indicates severe mockery of intellect or education. Profanity that enhances the insult should be considered positively.
11. **humor_score**: Determine the overall humorous quality of the text on a scale from 1 to 10, where:
- 1 indicates that the text is not funny at all and may be offensive or inappropriate.
- 2 to 4 indicates that the text attempts humor but is largely unsuccessful, containing few amusing elements or relying on clichés.
- 5 indicates that the text is somewhat humorous; it may contain some funny moments but lacks depth or execution.
- 6 to 8 indicates that the text successfully conveys humor, possibly combining wit, cleverness, or dark humor, effectively engaging the audience.
- 9 indicates that the text is very funny, cleverly crafted, and likely to amuse a wide audience.
- 10 indicates that the text is exceptionally humorous, demonstrating masterful use of language and structure to evoke laughter without being offensive.
- In this evaluation, the presence of simple or funny-sounding words does not enhance the humor score. Focus on the overall effectiveness of the joke and its ability to elicit laughter.
`
const adminChannelId = '-4588651872';
const token = process.env.BOT_TOKEN;
const bot = new TelegramBot(token, {polling: true});
const aiCachePath = 'aiCache.json';
const statsPath = 'stats.json';
const userStatsPath = 'userStats.json';
let userStats = {}; // Для хранения информации о пользователях
let aiCache = {}; // Кеш для запросов к ИИ
let stats = {cacheHits: 0, cacheMisses: 0, maxScore: 0};
const adminsPath = 'admins.json'; // Путь к файлу с админами
let admins = []; // Храним список администраторов
// Функция для загрузки администраторов из файла
function loadAdmins() {
try {
if (fs.existsSync(adminsPath)) {
const data = fs.readFileSync(adminsPath);
admins = JSON.parse(data);
}
} catch (error) {
console.error('Error loading admins:', error);
}
}
// Функция для сохранения администраторов в файл
function saveAdmins() {
try {
fs.writeFileSync(adminsPath, JSON.stringify(admins, null, 2));
} catch (error) {
console.error('Error saving admins:', error);
}
}
// Загружаем кеш из файла
function loadAiCache() {
try {
if (fs.existsSync(aiCachePath)) {
const data = fs.readFileSync(aiCachePath);
aiCache = JSON.parse(data);
}
} catch (error) {
console.error('Error loading AI cache:', error);
}
}
// Сохраняем кеш в файл
function saveAiCache() {
try {
fs.writeFileSync(aiCachePath, JSON.stringify(aiCache, null, 2));
} catch (error) {
console.error('Error saving AI cache:', error);
}
}
// Загружаем статистику из файла
function loadStats() {
try {
if (fs.existsSync(statsPath)) {
const data = fs.readFileSync(statsPath);
stats = JSON.parse(data);
}
} catch (error) {
console.error('Error loading stats:', error);
}
}
// Сохраняем статистику в файл
function saveStats() {
try {
fs.writeFileSync(statsPath, JSON.stringify(stats, null, 2));
} catch (error) {
console.error('Error saving stats:', error);
}
}
function loadUserStats() {
try {
if (fs.existsSync(userStatsPath)) {
const data = fs.readFileSync(userStatsPath);
userStats = JSON.parse(data);
}
} catch (error) {
console.error('Error loading user stats:', error);
}
}
// Сохраняем статистику пользователей в файл
function saveUserStats() {
try {
fs.writeFileSync(userStatsPath, JSON.stringify(userStats, null, 2));
} catch (error) {
console.error('Error saving user stats:', error);
}
}
loadUserStats(); // Загружаем статистику пользователей при старте бота
loadAiCache(); // Загружаем кеш ИИ при старте бота
loadStats(); // Загружаем статистику при старте бота
loadAdmins(); // Загружаем администраторов при старте бота
async function updateUserStats(userId, username, firstName, toxScore, averageScore) {
if (!userStats[userId]) {
userStats[userId] = {
userId,
username,
firstName,
totalScore: 0,
averageScore: 0,
highestScore: 0,
requestCount: 0,
};
}
const user = userStats[userId];
// Обновляем информацию о пользователе
const currentScore = averageScore//Object.values(toxScore).reduce((a, b) => a + b, 0);
user.totalScore += currentScore; // Суммируем баллы
user.requestCount++; // Увеличиваем счетчик запросов
user.averageScore = user.totalScore / user.requestCount; // Пересчитываем средний балл
// Обновляем наивысший балл
if (currentScore > user.highestScore) {
user.highestScore = currentScore;
}
// // Обновляем максимальный средний балл за всю историю
// if (user.averageScore > maxAverageScore) {
// maxAverageScore = user.averageScore;
// }
saveUserStats(); // Сохраняем обновленную статистику
}
// Функция для выбора топ-10 пользователей по среднему баллу
function getTopUsersByAverage() {
return Object.values(userStats)
.sort((a, b) => b.averageScore - a.averageScore)
.slice(0, 10);
}
// Функция для выбора топ-10 пользователей по количеству запросов
function getTopUsersByRequestCount() {
return Object.values(userStats)
.sort((a, b) => b.requestCount - a.requestCount)
.slice(0, 10);
}
function toxAnalyze(text) {
// Проверяем, есть ли уже результат в кеше
if (aiCache[text]) {
stats.cacheHits += 1; // Увеличиваем счетчик попаданий в кеш
let tempResult = JSON.parse(aiCache[text]);
tempResult.firstTime = false;
return tempResult;
}
// Если нет, делаем запрос к AI
stats.cacheMisses += 1; // Увеличиваем счетчик промахов в кеш
return getAIResume(text, BASE_PROMPT).then(result => {
// Сохраняем результат в кеш
let tempResult = JSON.parse(result);
tempResult.firstTime = true;
aiCache[text] = JSON.stringify(tempResult);
saveAiCache(); // Сохраняем кеш в файл
return tempResult;
});
}
function escapeMarkdown(text) {
return text
.replace(/_/g, '\\_') // Экранируем нижнее подчеркивание
.replace(/\*/g, '\\*') // Экранируем звездочку
.replace(/\[/g, '\\[') // Экранируем открывающую скобку
.replace(/\]/g, '\\]') // Экранируем закрывающую скобку
.replace(/\(/g, '\\(') // Экранируем открытую скобку
.replace(/\)/g, '\\)') // Экранируем закрытую скобку
.replace(/~/g, '\\~') // Экранируем тильду
.replace(/`/g, '\\`') // Экранируем обратную кавычку
.replace(/>/g, '\\>') // Экранируем знак больше
.replace(/#/g, '\\#') // Экранируем решетку
.replace(/-/g, '\\-'); // Экранируем дефис
}
// Обработчик текстовых сообщений
// bot.on('message', async (msg) => {
// const chatId = msg.chat.id;
// const userId = msg.from.id;
// const userName = msg.from.username || '';
// const firstName = msg.from.first_name || '';
// let isNewUser = false;
//
// // Создаем запись пользователя для данного чата, если ее еще нет
//
//
// if (msg.reply_to_message && msg.reply_to_message.text && msg.text && msg.text.toLowerCase() === 'токсанал') {
// const analyzedText = msg.reply_to_message.text;
//
// // Проверяем, что текст для анализа не пустой
// if (analyzedText) {
// const toxScore = await toxAnalyze(analyzedText);
// //console.log(toxScore)
// // Форматируем вывод
// const values = Object.values(toxScore);
// const sum = values.reduce((a, b) => a + b, 0);
// const average = sum / values.length;
// const resultMessage = `
// Слов в тексте: ${analyzedText.split(' ').length}
// Грамотность: ${toxScore.literacy_score}
// Элегантность: ${toxScore.elegance_score}
// Токсичность по отношению к родителям: ${toxScore.parental_toxicity_score}
// Сексуальная токсичность: ${toxScore.sexual_toxicity_score}
// Токсичность по отношению к внешности: ${toxScore.appearance_toxicity_score}
// Медицинская токсичность: ${toxScore.medical_toxicity_score}
// Эмоциональная токсичность: ${toxScore.emotional_toxicity_score}
// Дискриминация: ${toxScore.discrimination_score}
// Манипулятивный язык: ${toxScore.manipulative_language_score}
// Интеллектуальная токсичность: ${toxScore.intellectual_toxicity_score}
// Юмористическая токсичность: ${toxScore.humor_score}
// Средний бал: ${average.toFixed(1)}
// `.trim(); // Убираем лишние пробелы
//
// // Отправляем отформатированное сообщение
// bot.sendMessage(chatId, `Результаты анализа:\n${resultMessage}`, { reply_to_message_id: msg.reply_to_message.message_id });
// } else {
// bot.sendMessage(chatId, 'Пожалуйста, укажите текст для анализа.');
// }
// }
// // Сохраняем обновленные статистические данные
// saveStats();
// });
bot.on('message', async (msg) => {
const chatId = msg.chat.id;
const userId = msg.from.id;
const username = msg.from.username || '';
const firstName = msg.from.first_name || '';
// Инициализация данных пользователя, если их нет
if (!userUsage[userId]) {
userUsage[userId] = { count: 0, lastReset: Date.now() };
}
// Сброс данных, если прошел день
if (Date.now() - userUsage[userId].lastReset >= USAGE_RESET_TIME) {
userUsage[userId].count = 0; // Сбрасываем счетчик
userUsage[userId].lastReset = Date.now(); // Обновляем временную метку
}
// Проверяем, является ли сообщение ответом на другое сообщение с текстом "токсанал"
if (msg.reply_to_message && msg.reply_to_message.text && msg.text && msg.text.toLowerCase() === 'токсанал') {
// Проверяем, использовал ли пользователь команду больше трех раз
if (userUsage[userId].count >= MAX_CALLS_PER_DAY) {
return bot.sendMessage(chatId, 'Вы достигли лимита использования команды "токсанал" на сегодня. Попробуйте снова завтра.', { reply_to_message_id: msg.message_id });
}
const analyzedText = msg.reply_to_message.text;
// Проверяем, что текст для анализа не пустой
if (analyzedText && analyzedText.split(' ').length > 5) {
const toxScore = await toxAnalyze(analyzedText);
// Форматируем вывод
const values = Object.values(toxScore);
const sum = values.reduce((a, b) => a + b, 0);
const average = sum / values.length;
stats.maxScore = Math.max(stats.maxScore, average);
//console.log(stats)
const resultMessage = `
Слов в тексте: ${analyzedText.split(' ').length}
Грамотность: ${toxScore.literacy_score}
Элегантность: ${toxScore.elegance_score}
Токсичность по отношению к родителям: ${toxScore.parental_toxicity_score}
Сексуальная токсичность: ${toxScore.sexual_toxicity_score}
Токсичность по отношению к внешности: ${toxScore.appearance_toxicity_score}
Медицинская токсичность: ${toxScore.medical_toxicity_score}
Эмоциональная токсичность: ${toxScore.emotional_toxicity_score}
Дискриминация: ${toxScore.discrimination_score}
Манипулятивный язык: ${toxScore.manipulative_language_score}
Интеллектуальная токсичность: ${toxScore.intellectual_toxicity_score}
Юмористическая токсичность: ${toxScore.humor_score}
Средний бал: ${average.toFixed(1)}
`.trim(); // Убираем лишние пробелы
// Увеличиваем счетчик использований
userUsage[userId].count++;
// Получаем количество оставшихся попыток
const remainingAttempts = MAX_CALLS_PER_DAY - userUsage[userId].count;
// Отправляем отформатированное сообщение с оставшимися попытками
if (toxScore.firstTime) {await updateUserStats(msg.reply_to_message.from.id, msg.reply_to_message.from.username, msg.reply_to_message.from.first_name, toxScore, average);} // Обновляем статистику пользователя
await bot.sendMessage(chatId, `Результаты анализа:\n${resultMessage}\n\nАнализов осталось: ${remainingAttempts}\n\nРекорд: ${stats.maxScore.toFixed(1)}`, { reply_to_message_id: msg.reply_to_message.message_id });
} else {
await bot.sendMessage(chatId, 'Пожалуйста, укажите текст для анализа.');
}
}
// Сохраняем обновленные статистические данные
saveStats();
});
// Функция запроса к AI
async function getAIResume(text, prompt) {
const baseUrl = `${process.env.AI_WEB_URL}/api`;
const url = `${baseUrl}/chat/completions`;
if (text.length < 4) return 0;
const headers = {
'Authorization': `Bearer ${process.env.AI_TOKEN}`,
'Content-Type': 'application/json',
'Accept': 'application/json',
};
const body = {
model: 'gpt-4o-mini',
messages: [
{role: "system", content: prompt},
{role: "user", content: text},
],
// temperature: 0.7,
// max_tokens: 150
};
try {
const result = await axios.post(url, body, {headers});
const responseContent = result.data.choices[0].message.content
return responseContent.replace(/```json\n|\n```/g, '').replace(/\n/g, ' ').trim();
//return responseContent; // Теперь без символов новой строкие
} catch (error) {
console.error('Error:', error);
// throw error;
}
}
function statCooldown(chatId) {
if (commandCooldowns[chatId] && Date.now() - commandCooldowns[chatId] < COOLDOWN_TIME) {
return true;
}
commandCooldowns[chatId] = Date.now();
return false;
}
bot.onText(/токстоп/, async (msg) => {
try {
await bot.deleteMessage(msg.chat.id, msg.message_id);
} catch (error) {}
if (statCooldown(msg.chat.id)) {
await sendTemporaryMessage(msg.chat.id, 'Слишком частые запросы. Подождите некоторое время.', 5000);
return
}
const chatId = msg.chat.id;
const topUsers = getTopUsersByAverage(); // Получаем топ пользователей по среднему баллу
console.log(topUsers)
if (topUsers.length === 0) {
return bot.sendMessage(chatId, 'Статистика пока недоступна.');
}
// Форматируем сообщение для вывода
let leaderboard = '*Топ пользователей по среднему баллу:*\n(считается средняя оценка всех сообщений)\n\n';
topUsers.forEach((user, index) => {
// leaderboard += `*${index + 1}*. ${escapeMarkdown(user.firstName)} (${escapeMarkdown('@' + user.username || 'Без имени')}) - Средний балл: ${user.averageScore.toFixed(2)}\n`;
leaderboard += `*${index + 1}*. ${escapeMarkdown(user.firstName)} - Средний балл: ${user.averageScore.toFixed(2)}\n`;
});
await bot.sendMessage(chatId, leaderboard, {parse_mode: 'Markdown'});
});
bot.onText(/токсзапросы/, async (msg) => {
try {
await bot.deleteMessage(msg.chat.id, msg.message_id);
} catch (error) {}
if (statCooldown(msg.chat.id)) {
await sendTemporaryMessage(msg.chat.id, 'Слишком частые запросы. Подождите некоторое время.', 5000);
return
}
const chatId = msg.chat.id;
const topRequestUsers = getTopUsersByRequestCount(); // Получаем топ пользователей по количеству запросов
if (topRequestUsers.length === 0) {
return bot.sendMessage(chatId, 'Статистика пока недоступна.');
}
// Форматируем сообщение для вывода
let requestLeaderboard = '*Топ пользователей по количеству запросов:*\n\n';
topRequestUsers.forEach((user, index) => {
// requestLeaderboard += `*${index + 1}*. ${escapeMarkdown(user.firstName)} (${escapeMarkdown('@' + user.username || 'Без имени')}) - Запросов: ${user.requestCount}\n`;
requestLeaderboard += `*${index + 1}*. ${escapeMarkdown(user.firstName)} - Запросов: ${user.requestCount}\n`;
});
await bot.sendMessage(chatId, requestLeaderboard, {parse_mode: 'Markdown'});
});
bot.onText(/токсдар (\d+)/, async (msg, match) => {
const chatId = msg.chat.id;
const userId = msg.from.id; // ID администратора
const amount = parseInt(match[1], 10); // Число, переданное после команды
// Проверяем, является ли пользователь администратором
if (!isAdmin(userId)) {
console.log('не админ')
return bot.sendMessage(chatId, 'У вас нет прав для выполнения этой команды.');
}
// Получаем ID пользователя, которому добавляем анализы (или можно сделать выборку по упомянутому пользователю)
const targetUserId = msg.reply_to_message.from.id; // ID пользователя, на чье сообщение ответили
// Проверяем, существует ли запись о пользователе в userUsage
if (userUsage[targetUserId]) {
userUsage[targetUserId].count = userUsage[targetUserId].count - amount; // Добавляем X анализов
saveUserUsage(); // Сохраняем изменения в файл
await sendTemporaryMessage(chatId, `Добавлено ${amount} анализов для ${msg.reply_to_message.from.first_name}.`, 10000);
} else {
// bot.sendMessage(chatId, 'Пользователь не найден или у него еще не было анализов.');
}
});
// Обработчик команды "токсадмин"
bot.onText(/токсадмин/, (msg) => {
const chatId = msg.chat.id;
const userId = msg.reply_to_message.from.id; // ID пользователя, на чье сообщение ответили
// Проверяем, есть ли уже этот пользователь в списке администраторов
if (!admins.includes(userId)) {
admins.push(userId); // Добавляем пользователя в список администраторов
saveAdmins(); // Сохраняем изменения в файл
bot.sendMessage(chatId, `Пользователь ${msg.reply_to_message.from.first_name} теперь является токсичным администратором.`);
} else {
bot.sendMessage(chatId, `Пользователь с ID ${msg.reply_to_message.from.first_name} уже является токсичным администратором.`);
}
});
function isAdmin(userId) {
// Список ID администраторов. Замените этим массивом ваши ID администраторов.
return admins.includes(userId);
}
async function sendTemporaryMessage (chatId, text, interval = 5000) {
const message = await bot.sendMessage(chatId, text)
// Удаляем сообщение через указанный интервал
setTimeout(async () => {
try {
//if(!ctx.chat || !ctx.chat.id) {throw new Error('Chat ID not found');}
await bot.deleteMessage(chatId, message.message_id); // Удаляем сообщение
} catch (error) {
console.error('Ошибка при удалении сообщения:', error);
}
}, interval);
}
bot.on('polling_error', (error) => {
console.log(error);
});
console.log('bot started');
// Функция для отображения статуса кеша и спамеров
// setInterval(() => {
// const cacheEfficiency = ((stats.cacheHits / (stats.cacheHits + stats.cacheMisses)) || 0) * 100;
// const spamPercent = ((stats.spamCount / stats.totalUsers) || 0) * 100;
// console.log(`Эффективность кеша: ${cacheEfficiency.toFixed(2)}%, Процент спамеров: ${spamPercent.toFixed(2)}%`);
// }, 60000); // Обновляем каждую минуту