Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

Помощь с ботом

Мар
143
34
Пользователь
Помогите мне пж, не могу сделать систему кика в /sysban 2 уровня
Пыталюст сделать чтобы при /sysban @user 2(ур) [дней] [причина] он исключал человека из всех бесед где есть бот, но у меня не получается сделать) помогите сделать


Код:
const database = require('../databases.js');
const { checkSysAccess, getAccessLevelName } = require('./sysadmin.js');
const { hasCommandAccess, getAccessDeniedMessage } = require('../utils/commandAccess.js');
const { extractNumericId } = require('../utils/userUtils.js');
const vk = require('../vkInstance.js');
const util = require('util');
const fs = require('fs');
const path = require('path');
const databaseQuery = util.promisify(database.query);
const SYSBANNED_FILE = path.join(__dirname, '../data/sysbanned.json');
// Хранилище для отслеживания частоты использования команды
const commandUsage = new Map();
// Кэш забаненных пользователей для быстрой проверки
const bannedUsersCache = new Map();
const CACHE_UPDATE_INTERVAL = 60000; // Обновление кэша каждую минуту
// Функция обновления кэша забаненных пользователей
async function updateBannedUsersCache() {
  try {
    const now = Math.floor(Date.now() / 1000);
    const query = 'SELECT userid, time, level FROM sysbanned WHERE level = 2 AND (time = 0 OR time > ?)';
    const results = await databaseQuery(query, [now]);
    
    bannedUsersCache.clear();
    results.forEach(row => {
      bannedUsersCache.set(Number(row.userid), {
        level: row.level,
        time: row.time
      });
    });
    
    console.log(`[SYSBAN] Кэш забаненных обновлен: ${bannedUsersCache.size} пользователей`);
  } catch (error) {
    console.error('[SYSBAN] Ошибка обновления кэша:', error);
  }
}
// Обновляем кэш при старте и каждую минуту
updateBannedUsersCache();
setInterval(updateBannedUsersCache, CACHE_UPDATE_INTERVAL);
function isLevel2Banned(userId) {
  if (!fs.existsSync(SYSBANNED_FILE)) return false;
  const data = JSON.parse(fs.readFileSync(SYSBANNED_FILE, 'utf-8'));
  const now = Math.floor(Date.now() / 1000);
  const ban = data.find(u => u.userid === userId && u.level === 2 && (u.time === 0 || u.time > now));
  return !!ban;
}
// Функция для проверки лимита использования команды
function checkCommandLimit(userId) {
  const now = Date.now();
  const userUsage = commandUsage.get(userId) || { count: 0, lastReset: now, blockedUntil: 0 };
  
  // Проверяем, не заблокирован ли пользователь
  if (userUsage.blockedUntil > now) {
    const minutesLeft = Math.ceil((userUsage.blockedUntil - now) / 60000);
    return { 
      allowed: false, 
      message: `❌ Превышен лимит использования команды. Попробуйте через ${minutesLeft} мин.` 
    };
  }
  
  // Сбрасываем счетчик, если прошло больше 10 минут с последнего сброса
  if (now - userUsage.lastReset > 600000) { // 10 минут в миллисекундах
    userUsage.count = 0;
    userUsage.lastReset = now;
  }
  
  // Увеличиваем счетчик
  userUsage.count++;
  
  // Если использовано 3 раза подряд, блокируем на 10 минут
  if (userUsage.count >= 3) {
    userUsage.blockedUntil = now + 600000; // 10 минут
    userUsage.count = 0;
    commandUsage.set(userId, userUsage);
    return { 
      allowed: false, 
      message: '❌ Превышен лимит использования команды. Команда заблокирована на 10 минут.' 
    };
  }
  
  commandUsage.set(userId, userUsage);
  return { allowed: true };
}
// Улучшенная функция для кика пользователя из всех бесед
async function kickUserFromAllChats(userId) {
  try {
    // Получаем список всех бесед, где есть бот
    const conversations = await vk.api.messages.getConversations({
      count: 200,
    });
    let kickedCount = 0;
    const errors = [];
    const kickPromises = [];
    for (const item of conversations.items) {
      const peerId = item.conversation.peer.id;
      
      // Только беседы
      if (peerId <= 2000000000) {
        continue;
      }
    // Беседа отключена
     if (
       item.conversation.chat_settings?.state === 'disabled'
  ) {
    continue;
  }
     // Нет настроек беседы = мёртвый чат
     if (!item.conversation.chat_settings) {
    continue;
  }
    // Бот не может писать
     if (
       item.conversation.can_write &&
       item.conversation.can_write.allowed === false
  ) {
    continue;
  }
  // Сразу пытаемся кикнуть
  const kickPromise = vk.api.messages.removeChatUser({
    chat_id: peerId - 2000000000,
    user_id: userId
  })
  .then(() => {
    kickedCount++;
    console.log(
      `[SYSBAN] Пользователь ${userId} кикнут из беседы ${peerId}`
    );
  })
  .catch(error => {
    // Игнорируем недоступные беседы
    if (
      error.code === 945 ||
      error.message?.includes('Chat was disabled')
    ) {
      return;
    }
    // Пользователя уже нет
    if (
      error.code === 935 ||
      error.message?.includes('User not in chat')
    ) {
      return;
    }
    const errorMsg =
      `Ошибка при кике из беседы ${peerId}: ${error.message}`;
    console.error(`[SYSBAN] ${errorMsg}`);
    errors.push(errorMsg);
  });
  kickPromises.push(kickPromise);
}
    // Ждем завершения всех операций кика
    await Promise.allSettled(kickPromises);
    
    return { kickedCount, errors };
  } catch (error) {
    console.error('[SYSBAN] Ошибка при кике пользователя из всех бесед:', error);
    return { kickedCount: 0, errors: [error.message] };
  }
}
// Функция для автоматического кика при попытке добавить в беседу
async function setupAutoKick() {
  try {
    // Слушаем новые сообщения о добавлении в беседу
    const eventHandler = async (event) => {
      if (event.type === 'message_new') {
        const message = event.object.message;
        
        // Проверяем, что это действие с беседой
        if (message.action && message.action.type === 'chat_invite_user') {
          const invitedUserId = message.action.member_id;
          
          // Быстрая проверка по кэшу
          if (bannedUsersCache.has(invitedUserId)) {
            console.log(`[SYSBAN] Обнаружена попытка добавить забаненного пользователя ${invitedUserId} в беседу ${message.peer_id}`);
            
            // Немедленно кикаем
            try {
              await vk.api.messages.removeChatUser({
                chat_id: message.peer_id - 2000000000,
                user_id: invitedUserId
              });
              
              console.log(`[SYSBAN] Забаненный пользователь ${invitedUserId} автоматически кикнут из беседы ${message.peer_id}`);
              
              // Отправляем уведомление в беседу
              await vk.api.messages.send({
                peer_id: message.peer_id,
                message: `🚫 Пользователь [id${invitedUserId}|заблокирован] в системе бота и не может быть добавлен в беседы.`,
                random_id: Math.floor(Math.random() * 1e9),
                disable_mentions: true
              });
            } catch (kickError) {
              console.error(`[SYSBAN] Ошибка при автоматическом кике:`, kickError);
            }
          }
        }
      }
    };
    
    // Подключаем обработчик (способ подключения зависит от вашей архитектуры)
    // vk.updates.on('message_new', eventHandler);
    console.log('[SYSBAN] Автоматический кик настроен');
    
  } catch (error) {
    console.error('[SYSBAN] Ошибка настройки авто-кика:', error);
  }
}
// Запускаем авто-кик
setupAutoKick();
// Очистка старых записей раз в час
setInterval(() => {
  const now = Date.now();
  for (const [userId, data] of commandUsage.entries()) {
    if (data.blockedUntil < now && now - data.lastReset > 3600000) { // если блокировка прошла и прошёл час
      commandUsage.delete(userId);
    }
  }
}, 3600000); // Каждый час
module.exports = {
  command: '/sysban',
  description: 'Блокировка пользователя в системе бота (2 степени)',
  async execute(context) {
    try {
      // Проверка лимита использования
      const limitCheck = checkCommandLimit(context.senderId);
      if (!limitCheck.allowed) {
        return context.reply(limitCheck.message);
      }
      const hasAccess = await hasCommandAccess(context.senderId, 'sysban');
      if (!hasAccess) return context.reply(getAccessDeniedMessage('sysban'));
      const args = context.text.split(' ');
      if (args.length < 4) return context.reply('❌ Использование:\n/sysban [ID] [1|2] [дни|0] [причина]');
      const userId = await extractNumericId(args[1]);
      if (!userId) return context.reply('❌ Ошибка | Некорректный ID пользователя');
      if (userId === context.senderId) return context.reply('❌ Ошибка | Нельзя заблокировать самого себя');
      if (global.botId && Number(userId) === Number(global.botId)) return context.reply('🤖 Нельзя заблокировать бота');
      const senderAccess = await checkSysAccess(context.senderId);
      let targetAccess = 0;
      try { targetAccess = await checkSysAccess(userId); } catch {}
      if (targetAccess >= senderAccess && targetAccess > 0) {
        return context.reply(`❌ Ошибка | Вы не можете заблокировать пользователя с уровнем "${getAccessLevelName(targetAccess)}"`);
      }
      const banLevel = parseInt(args[2]);
      if (![1, 2].includes(banLevel)) return context.reply('❌ Уровень ЧСБ может быть только 1 или 2');
      const banDays = parseInt(args[3]);
      if (isNaN(banDays) || banDays < 0) return context.reply('❌ Некорректный срок блокировки');
      const reason = args.slice(4).join(' ') || 'Не указана';
      const now = Math.floor(Date.now() / 1000);
      const endTime = banDays === 0 ? 0 : now + banDays * 86400;
      const query = `
        INSERT INTO sysbanned (userid, time, reason, who, level)
        VALUES (?, ?, ?, ?, ?)
        ON DUPLICATE KEY UPDATE
          time = VALUES(time),
          reason = VALUES(reason),
          who = VALUES(who),
          level = VALUES(level)
      `;
      await databaseQuery(query, [userId, endTime, reason, context.senderId, banLevel]);
      // Обновляем кэш сразу после бана
      if (banLevel === 2) {
        bannedUsersCache.set(Number(userId), {
          level: 2,
          time: endTime
        });
      }
      let userDisplay = `@id${userId}`;
      try {
        const u = (await vk.api.users.get({ user_ids: userId }))[0];
        if (u) userDisplay = `[id${userId}|${u.first_name} ${u.last_name}]`;
      } catch {}
      const banType = banLevel === 1 ? '🚫 Запрет команд' : '⛔ Полный запрет бота';
      let message = `🚨 ${userDisplay} заблокирован в системе бота\n\n`;
      message += `🔐 Тип: ${banType}\n`;
      message += `🕒 Срок: ${banDays === 0 ? 'Навсегда' : banDays + ' дн.'}\n`;
      message += `📝 Причина: ${reason}`;
      await context.send({ message, disable_mentions: true });
      try {
        await vk.api.messages.send({
          peer_id: userId,
          message,
          random_id: Math.floor(Math.random() * 1e9),
          disable_mentions: true
        });
      } catch {}
      // Если это полный запрет (уровень 2), кикаем пользователя из всех бесед
      if (banLevel === 2) {
        const { kickedCount, errors } = await kickUserFromAllChats(userId);
        
        // Отправляем подробное сообщение о результате кика
        let kickMessage = '';
        if (kickedCount > 0) {
          kickMessage = `👢 Пользователь ${userDisplay} был кикнут из ${kickedCount} бесед`;
        } else {
          kickMessage = `⚠️ Пользователь ${userDisplay} не был найден в беседах`;
        }
        
        if (errors.length > 0) {
          kickMessage += `\n\n❌ Ошибки (${errors.length}):\n`;
          // Показываем только первые 3 ошибки
          errors.slice(0, 3).forEach(err => {
            kickMessage += `• ${err}\n`;
          });
        }
        
        await context.send({
          message: kickMessage,
          disable_mentions: true
        });
        // Запускаем дополнительную проверку через 5 секунд
        // (на случай, если пользователь был онлайн и не сразу кикнулся)
        setTimeout(async () => {
          console.log(`[SYSBAN] Повторная проверка пользователя ${userId} через 5 секунд`);
          const { kickedCount: additionalKicks } = await kickUserFromAllChats(userId);
          if (additionalKicks > 0) {
            await context.send({
              message: `👢 Дополнительно кикнуто из ${additionalKicks} бесед (повторная проверка)`,
              disable_mentions: true
            });
          }
        }, 5000);
      }
      // Сбрасываем счетчик после успешного выполнения
      const userUsage = commandUsage.get(context.senderId);
      if (userUsage) {
        userUsage.count = 0;
        userUsage.lastReset = Date.now();
        commandUsage.set(context.senderId, userUsage);
      }
    } catch (error) {
      console.error('SYSBAN ERROR:', error);
      context.reply('❌ Ошибка выполнения sysban');
    }
  }
};
// Экспортируем кэш для использования в других модулях
module.exports.bannedUsersCache = bannedUsersCache;
module.exports.isUserBanned = (userId) => bannedUsersCache.has(Number(userId));
 
Новичок
Окт
300
860
Активный
2.20. Запрещено публиковать ответы, сгенерированные при помощи ChatGPT или аналогичных ИИ-моделей.
JavaScript:
const database = require('../databases.js');
const { checkSysAccess, getAccessLevelName } = require('./sysadmin.js');
const { hasCommandAccess, getAccessDeniedMessage } = require('../utils/commandAccess.js');
const { extractNumericId } = require('../utils/userUtils.js');
const vk = require('../vkInstance.js');
const util = require('util');
const fs = require('fs');
const path = require('path');
const databaseQuery = util.promisify(database.query);
const SYSBANNED_FILE = path.join(__dirname, '../data/sysbanned.json');
// Хранилище для отслеживания частоты использования команды
const commandUsage = new Map();
// Кэш забаненных пользователей для быстрой проверки
const bannedUsersCache = new Map();
const CACHE_UPDATE_INTERVAL = 60000; // Обновление кэша каждую минуту
// Функция обновления кэша забаненных пользователей
async function updateBannedUsersCache() {
  try {
    const now = Math.floor(Date.now() / 1000);
    const query = 'SELECT userid, time, level FROM sysbanned WHERE level = 2 AND (time = 0 OR time > ?)';
    const results = await databaseQuery(query, [now]);
    
    bannedUsersCache.clear();
    results.forEach(row => {
      bannedUsersCache.set(Number(row.userid), {
        level: row.level,
        time: row.time
      });
    });
    
    console.log(`[SYSBAN] Кэш забаненных обновлен: ${bannedUsersCache.size} пользователей`);
  } catch (error) {
    console.error('[SYSBAN] Ошибка обновления кэша:', error);
  }
}
// Обновляем кэш при старте и каждую минуту
updateBannedUsersCache();
setInterval(updateBannedUsersCache, CACHE_UPDATE_INTERVAL);
function isLevel2Banned(userId) {
  if (!fs.existsSync(SYSBANNED_FILE)) return false;
  const data = JSON.parse(fs.readFileSync(SYSBANNED_FILE, 'utf-8'));
  const now = Math.floor(Date.now() / 1000);
  const ban = data.find(u => u.userid === userId && u.level === 2 && (u.time === 0 || u.time > now));
  return !!ban;
}
// Функция для проверки лимита использования команды
function checkCommandLimit(userId) {
  const now = Date.now();
  const userUsage = commandUsage.get(userId) || { count: 0, lastReset: now, blockedUntil: 0 };
 
  // Проверяем, не заблокирован ли пользователь
  if (userUsage.blockedUntil > now) {
    const minutesLeft = Math.ceil((userUsage.blockedUntil - now) / 60000);
    return {
      allowed: false,
      message: `❌ Превышен лимит использования команды. Попробуйте через ${minutesLeft} мин.`
    };
  }
 
  // Сбрасываем счетчик, если прошло больше 10 минут с последнего сброса
  if (now - userUsage.lastReset > 600000) { // 10 минут в миллисекундах
    userUsage.count = 0;
    userUsage.lastReset = now;
  }
 
  // Увеличиваем счетчик
  userUsage.count++;
 
  // Если использовано 3 раза подряд, блокируем на 10 минут
  if (userUsage.count >= 3) {
    userUsage.blockedUntil = now + 600000; // 10 минут
    userUsage.count = 0;
    commandUsage.set(userId, userUsage);
    return {
      allowed: false,
      message: '❌ Превышен лимит использования команды. Команда заблокирована на 10 минут.'
    };
  }
 
  commandUsage.set(userId, userUsage);
  return { allowed: true };
}
// Улучшенная функция для кика пользователя из всех бесед
async function kickUserFromAllChats(userId) {
  try {
    let kickedCount = 0;
    const errors = [];
    const kickPromises = [];
    let offset = 0;
    const pageSize = 200;
    for (;;) {
      const conversations = await vk.api.messages.getConversations({
        count: pageSize,
        offset,
        extended: 1
      });
      const items = conversations.items || [];
      if (!items.length) break;
      for (const item of items) {
        const peerId = item.conversation.peer.id;
        if (peerId <= 2000000000) continue;
        if (item.conversation.chat_settings?.state === 'disabled') continue;
        const chatId = peerId - 2000000000;
        const kickPromise = vk.api.messages.removeChatUser({
          chat_id: chatId,
          member_id: userId
        })
          .then(() => {
            kickedCount++;
            console.log(
              `[SYSBAN] Пользователь ${userId} кикнут из беседы ${peerId}`
            );
          })
          .catch(error => {
            if (
              error.code === 945 ||
              error.message?.includes('Chat was disabled')
            ) {
              return;
            }
            if (
              error.code === 935 ||
              error.message?.includes('User not in chat')
            ) {
              return;
            }
            const errorMsg =
              `Ошибка при кике из беседы ${peerId}: ${error.message}`;
            console.error(`[SYSBAN] ${errorMsg}`);
            errors.push(errorMsg);
          });
        kickPromises.push(kickPromise);
      }
      offset += items.length;
      if (items.length < pageSize) break;
    }
    await Promise.allSettled(kickPromises);
    return { kickedCount, errors };
  } catch (error) {
    console.error('[SYSBAN] Ошибка при кике пользователя из всех бесед:', error);
    return { kickedCount: 0, errors: [error.message] };
  }
}
// Функция для автоматического кика при попытке добавить в беседу
async function setupAutoKick() {
  try {
    // Слушаем новые сообщения о добавлении в беседу
    const eventHandler = async (event) => {
      if (event.type === 'message_new') {
        const message = event.object.message;
        
        // Проверяем, что это действие с беседой
        if (message.action && message.action.type === 'chat_invite_user') {
          const invitedUserId = message.action.member_id;
          
          // Быстрая проверка по кэшу
          if (bannedUsersCache.has(invitedUserId)) {
            console.log(`[SYSBAN] Обнаружена попытка добавить забаненного пользователя ${invitedUserId} в беседу ${message.peer_id}`);
            
            // Немедленно кикаем
            try {
              await vk.api.messages.removeChatUser({
                chat_id: message.peer_id - 2000000000,
                member_id: invitedUserId
              });
              
              console.log(`[SYSBAN] Забаненный пользователь ${invitedUserId} автоматически кикнут из беседы ${message.peer_id}`);
              
              // Отправляем уведомление в беседу
              await vk.api.messages.send({
                peer_id: message.peer_id,
                message: `🚫 Пользователь [id${invitedUserId}|заблокирован] в системе бота и не может быть добавлен в беседы.`,
                random_id: Math.floor(Math.random() * 1e9),
                disable_mentions: true
              });
            } catch (kickError) {
              console.error(`[SYSBAN] Ошибка при автоматическом кике:`, kickError);
            }
          }
        }
      }
    };
    
    // Подключаем обработчик (способ подключения зависит от вашей архитектуры)
    // vk.updates.on('message_new', eventHandler);
    console.log('[SYSBAN] Автоматический кик настроен');
    
  } catch (error) {
    console.error('[SYSBAN] Ошибка настройки авто-кика:', error);
  }
}
// Запускаем авто-кик
setupAutoKick();
// Очистка старых записей раз в час
setInterval(() => {
  const now = Date.now();
  for (const [userId, data] of commandUsage.entries()) {
    if (data.blockedUntil < now && now - data.lastReset > 3600000) { // если блокировка прошла и прошёл час
      commandUsage.delete(userId);
    }
  }
}, 3600000); // Каждый час
module.exports = {
  command: '/sysban',
  description: 'Блокировка пользователя в системе бота (2 степени)',
  async execute(context) {
    try {
      // Проверка лимита использования
      const limitCheck = checkCommandLimit(context.senderId);
      if (!limitCheck.allowed) {
        return context.reply(limitCheck.message);
      }
      const hasAccess = await hasCommandAccess(context.senderId, 'sysban');
      if (!hasAccess) return context.reply(getAccessDeniedMessage('sysban'));
      const args = context.text.split(' ');
      if (args.length < 4) return context.reply('❌ Использование:\n/sysban [ID] [1|2] [дни|0] [причина]');
      const userId = await extractNumericId(args[1]);
      if (!userId) return context.reply('❌ Ошибка | Некорректный ID пользователя');
      if (userId === context.senderId) return context.reply('❌ Ошибка | Нельзя заблокировать самого себя');
      if (global.botId && Number(userId) === Number(global.botId)) return context.reply('🤖 Нельзя заблокировать бота');
      const senderAccess = await checkSysAccess(context.senderId);
      let targetAccess = 0;
      try { targetAccess = await checkSysAccess(userId); } catch {}
      if (targetAccess >= senderAccess && targetAccess > 0) {
        return context.reply(`❌ Ошибка | Вы не можете заблокировать пользователя с уровнем "${getAccessLevelName(targetAccess)}"`);
      }
      const banLevel = parseInt(args[2]);
      if (![1, 2].includes(banLevel)) return context.reply('❌ Уровень ЧСБ может быть только 1 или 2');
      const banDays = parseInt(args[3]);
      if (isNaN(banDays) || banDays < 0) return context.reply('❌ Некорректный срок блокировки');
      const reason = args.slice(4).join(' ') || 'Не указана';
      const now = Math.floor(Date.now() / 1000);
      const endTime = banDays === 0 ? 0 : now + banDays * 86400;
      const query = `
        INSERT INTO sysbanned (userid, time, reason, who, level)
        VALUES (?, ?, ?, ?, ?)
        ON DUPLICATE KEY UPDATE
          time = VALUES(time),
          reason = VALUES(reason),
          who = VALUES(who),
          level = VALUES(level)
      `;
      await databaseQuery(query, [userId, endTime, reason, context.senderId, banLevel]);
      // Обновляем кэш сразу после бана
      if (banLevel === 2) {
        bannedUsersCache.set(Number(userId), {
          level: 2,
          time: endTime
        });
      }
      let userDisplay = `@id${userId}`;
      try {
        const u = (await vk.api.users.get({ user_ids: userId }))[0];
        if (u) userDisplay = `[id${userId}|${u.first_name} ${u.last_name}]`;
      } catch {}
      const banType = banLevel === 1 ? '🚫 Запрет команд' : '⛔ Полный запрет бота';
      let message = `🚨 ${userDisplay} заблокирован в системе бота\n\n`;
      message += `🔐 Тип: ${banType}\n`;
      message += `🕒 Срок: ${banDays === 0 ? 'Навсегда' : banDays + ' дн.'}\n`;
      message += `📝 Причина: ${reason}`;
      await context.send({ message, disable_mentions: true });
      try {
        await vk.api.messages.send({
          peer_id: userId,
          message,
          random_id: Math.floor(Math.random() * 1e9),
          disable_mentions: true
        });
      } catch {}
      // Если это полный запрет (уровень 2), кикаем пользователя из всех бесед
      if (banLevel === 2) {
        const { kickedCount, errors } = await kickUserFromAllChats(userId);
        
        // Отправляем подробное сообщение о результате кика
        let kickMessage = '';
        if (kickedCount > 0) {
          kickMessage = `👢 Пользователь ${userDisplay} был кикнут из ${kickedCount} бесед`;
        } else {
          kickMessage = `⚠️ Пользователь ${userDisplay} не был найден в беседах`;
        }
        
        if (errors.length > 0) {
          kickMessage += `\n\n❌ Ошибки (${errors.length}):\n`;
          // Показываем только первые 3 ошибки
          errors.slice(0, 3).forEach(err => {
            kickMessage += `• ${err}\n`;
          });
        }
        
        await context.send({
          message: kickMessage,
          disable_mentions: true
        });
        // Запускаем дополнительную проверку через 5 секунд
        // (на случай, если пользователь был онлайн и не сразу кикнулся)
        setTimeout(async () => {
          console.log(`[SYSBAN] Повторная проверка пользователя ${userId} через 5 секунд`);
          const { kickedCount: additionalKicks } = await kickUserFromAllChats(userId);
          if (additionalKicks > 0) {
            await context.send({
              message: `👢 Дополнительно кикнуто из ${additionalKicks} бесед (повторная проверка)`,
              disable_mentions: true
            });
          }
        }, 5000);
      }
      // Сбрасываем счетчик после успешного выполнения
      const userUsage = commandUsage.get(context.senderId);
      if (userUsage) {
        userUsage.count = 0;
        userUsage.lastReset = Date.now();
        commandUsage.set(context.senderId, userUsage);
      }
    } catch (error) {
      console.error('SYSBAN ERROR:', error);
      context.reply('❌ Ошибка выполнения sysban');
    }
  }
};
// Экспортируем кэш для использования в других модулях
module.exports.bannedUsersCache = bannedUsersCache;
module.exports.isUserBanned = (userId) => bannedUsersCache.has(Number(userId));
 
Мар
143
34
Пользователь
JavaScript:
const database = require('../databases.js');
const { checkSysAccess, getAccessLevelName } = require('./sysadmin.js');
const { hasCommandAccess, getAccessDeniedMessage } = require('../utils/commandAccess.js');
const { extractNumericId } = require('../utils/userUtils.js');
const vk = require('../vkInstance.js');
const util = require('util');
const fs = require('fs');
const path = require('path');
const databaseQuery = util.promisify(database.query);
const SYSBANNED_FILE = path.join(__dirname, '../data/sysbanned.json');
// Хранилище для отслеживания частоты использования команды
const commandUsage = new Map();
// Кэш забаненных пользователей для быстрой проверки
const bannedUsersCache = new Map();
const CACHE_UPDATE_INTERVAL = 60000; // Обновление кэша каждую минуту
// Функция обновления кэша забаненных пользователей
async function updateBannedUsersCache() {
  try {
    const now = Math.floor(Date.now() / 1000);
    const query = 'SELECT userid, time, level FROM sysbanned WHERE level = 2 AND (time = 0 OR time > ?)';
    const results = await databaseQuery(query, [now]);
   
    bannedUsersCache.clear();
    results.forEach(row => {
      bannedUsersCache.set(Number(row.userid), {
        level: row.level,
        time: row.time
      });
    });
   
    console.log(`[SYSBAN] Кэш забаненных обновлен: ${bannedUsersCache.size} пользователей`);
  } catch (error) {
    console.error('[SYSBAN] Ошибка обновления кэша:', error);
  }
}
// Обновляем кэш при старте и каждую минуту
updateBannedUsersCache();
setInterval(updateBannedUsersCache, CACHE_UPDATE_INTERVAL);
function isLevel2Banned(userId) {
  if (!fs.existsSync(SYSBANNED_FILE)) return false;
  const data = JSON.parse(fs.readFileSync(SYSBANNED_FILE, 'utf-8'));
  const now = Math.floor(Date.now() / 1000);
  const ban = data.find(u => u.userid === userId && u.level === 2 && (u.time === 0 || u.time > now));
  return !!ban;
}
// Функция для проверки лимита использования команды
function checkCommandLimit(userId) {
  const now = Date.now();
  const userUsage = commandUsage.get(userId) || { count: 0, lastReset: now, blockedUntil: 0 };
 
  // Проверяем, не заблокирован ли пользователь
  if (userUsage.blockedUntil > now) {
    const minutesLeft = Math.ceil((userUsage.blockedUntil - now) / 60000);
    return {
      allowed: false,
      message: `❌ Превышен лимит использования команды. Попробуйте через ${minutesLeft} мин.`
    };
  }
 
  // Сбрасываем счетчик, если прошло больше 10 минут с последнего сброса
  if (now - userUsage.lastReset > 600000) { // 10 минут в миллисекундах
    userUsage.count = 0;
    userUsage.lastReset = now;
  }
 
  // Увеличиваем счетчик
  userUsage.count++;
 
  // Если использовано 3 раза подряд, блокируем на 10 минут
  if (userUsage.count >= 3) {
    userUsage.blockedUntil = now + 600000; // 10 минут
    userUsage.count = 0;
    commandUsage.set(userId, userUsage);
    return {
      allowed: false,
      message: '❌ Превышен лимит использования команды. Команда заблокирована на 10 минут.'
    };
  }
 
  commandUsage.set(userId, userUsage);
  return { allowed: true };
}
// Улучшенная функция для кика пользователя из всех бесед
async function kickUserFromAllChats(userId) {
  try {
    let kickedCount = 0;
    const errors = [];
    const kickPromises = [];
    let offset = 0;
    const pageSize = 200;
    for (;;) {
      const conversations = await vk.api.messages.getConversations({
        count: pageSize,
        offset,
        extended: 1
      });
      const items = conversations.items || [];
      if (!items.length) break;
      for (const item of items) {
        const peerId = item.conversation.peer.id;
        if (peerId <= 2000000000) continue;
        if (item.conversation.chat_settings?.state === 'disabled') continue;
        const chatId = peerId - 2000000000;
        const kickPromise = vk.api.messages.removeChatUser({
          chat_id: chatId,
          member_id: userId
        })
          .then(() => {
            kickedCount++;
            console.log(
              `[SYSBAN] Пользователь ${userId} кикнут из беседы ${peerId}`
            );
          })
          .catch(error => {
            if (
              error.code === 945 ||
              error.message?.includes('Chat was disabled')
            ) {
              return;
            }
            if (
              error.code === 935 ||
              error.message?.includes('User not in chat')
            ) {
              return;
            }
            const errorMsg =
              `Ошибка при кике из беседы ${peerId}: ${error.message}`;
            console.error(`[SYSBAN] ${errorMsg}`);
            errors.push(errorMsg);
          });
        kickPromises.push(kickPromise);
      }
      offset += items.length;
      if (items.length < pageSize) break;
    }
    await Promise.allSettled(kickPromises);
    return { kickedCount, errors };
  } catch (error) {
    console.error('[SYSBAN] Ошибка при кике пользователя из всех бесед:', error);
    return { kickedCount: 0, errors: [error.message] };
  }
}
// Функция для автоматического кика при попытке добавить в беседу
async function setupAutoKick() {
  try {
    // Слушаем новые сообщения о добавлении в беседу
    const eventHandler = async (event) => {
      if (event.type === 'message_new') {
        const message = event.object.message;
       
        // Проверяем, что это действие с беседой
        if (message.action && message.action.type === 'chat_invite_user') {
          const invitedUserId = message.action.member_id;
         
          // Быстрая проверка по кэшу
          if (bannedUsersCache.has(invitedUserId)) {
            console.log(`[SYSBAN] Обнаружена попытка добавить забаненного пользователя ${invitedUserId} в беседу ${message.peer_id}`);
           
            // Немедленно кикаем
            try {
              await vk.api.messages.removeChatUser({
                chat_id: message.peer_id - 2000000000,
                member_id: invitedUserId
              });
             
              console.log(`[SYSBAN] Забаненный пользователь ${invitedUserId} автоматически кикнут из беседы ${message.peer_id}`);
             
              // Отправляем уведомление в беседу
              await vk.api.messages.send({
                peer_id: message.peer_id,
                message: `🚫 Пользователь [id${invitedUserId}|заблокирован] в системе бота и не может быть добавлен в беседы.`,
                random_id: Math.floor(Math.random() * 1e9),
                disable_mentions: true
              });
            } catch (kickError) {
              console.error(`[SYSBAN] Ошибка при автоматическом кике:`, kickError);
            }
          }
        }
      }
    };
   
    // Подключаем обработчик (способ подключения зависит от вашей архитектуры)
    // vk.updates.on('message_new', eventHandler);
    console.log('[SYSBAN] Автоматический кик настроен');
   
  } catch (error) {
    console.error('[SYSBAN] Ошибка настройки авто-кика:', error);
  }
}
// Запускаем авто-кик
setupAutoKick();
// Очистка старых записей раз в час
setInterval(() => {
  const now = Date.now();
  for (const [userId, data] of commandUsage.entries()) {
    if (data.blockedUntil < now && now - data.lastReset > 3600000) { // если блокировка прошла и прошёл час
      commandUsage.delete(userId);
    }
  }
}, 3600000); // Каждый час
module.exports = {
  command: '/sysban',
  description: 'Блокировка пользователя в системе бота (2 степени)',
  async execute(context) {
    try {
      // Проверка лимита использования
      const limitCheck = checkCommandLimit(context.senderId);
      if (!limitCheck.allowed) {
        return context.reply(limitCheck.message);
      }
      const hasAccess = await hasCommandAccess(context.senderId, 'sysban');
      if (!hasAccess) return context.reply(getAccessDeniedMessage('sysban'));
      const args = context.text.split(' ');
      if (args.length < 4) return context.reply('❌ Использование:\n/sysban [ID] [1|2] [дни|0] [причина]');
      const userId = await extractNumericId(args[1]);
      if (!userId) return context.reply('❌ Ошибка | Некорректный ID пользователя');
      if (userId === context.senderId) return context.reply('❌ Ошибка | Нельзя заблокировать самого себя');
      if (global.botId && Number(userId) === Number(global.botId)) return context.reply('🤖 Нельзя заблокировать бота');
      const senderAccess = await checkSysAccess(context.senderId);
      let targetAccess = 0;
      try { targetAccess = await checkSysAccess(userId); } catch {}
      if (targetAccess >= senderAccess && targetAccess > 0) {
        return context.reply(`❌ Ошибка | Вы не можете заблокировать пользователя с уровнем "${getAccessLevelName(targetAccess)}"`);
      }
      const banLevel = parseInt(args[2]);
      if (![1, 2].includes(banLevel)) return context.reply('❌ Уровень ЧСБ может быть только 1 или 2');
      const banDays = parseInt(args[3]);
      if (isNaN(banDays) || banDays < 0) return context.reply('❌ Некорректный срок блокировки');
      const reason = args.slice(4).join(' ') || 'Не указана';
      const now = Math.floor(Date.now() / 1000);
      const endTime = banDays === 0 ? 0 : now + banDays * 86400;
      const query = `
        INSERT INTO sysbanned (userid, time, reason, who, level)
        VALUES (?, ?, ?, ?, ?)
        ON DUPLICATE KEY UPDATE
          time = VALUES(time),
          reason = VALUES(reason),
          who = VALUES(who),
          level = VALUES(level)
      `;
      await databaseQuery(query, [userId, endTime, reason, context.senderId, banLevel]);
      // Обновляем кэш сразу после бана
      if (banLevel === 2) {
        bannedUsersCache.set(Number(userId), {
          level: 2,
          time: endTime
        });
      }
      let userDisplay = `@id${userId}`;
      try {
        const u = (await vk.api.users.get({ user_ids: userId }))[0];
        if (u) userDisplay = `[id${userId}|${u.first_name} ${u.last_name}]`;
      } catch {}
      const banType = banLevel === 1 ? '🚫 Запрет команд' : '⛔ Полный запрет бота';
      let message = `🚨 ${userDisplay} заблокирован в системе бота\n\n`;
      message += `🔐 Тип: ${banType}\n`;
      message += `🕒 Срок: ${banDays === 0 ? 'Навсегда' : banDays + ' дн.'}\n`;
      message += `📝 Причина: ${reason}`;
      await context.send({ message, disable_mentions: true });
      try {
        await vk.api.messages.send({
          peer_id: userId,
          message,
          random_id: Math.floor(Math.random() * 1e9),
          disable_mentions: true
        });
      } catch {}
      // Если это полный запрет (уровень 2), кикаем пользователя из всех бесед
      if (banLevel === 2) {
        const { kickedCount, errors } = await kickUserFromAllChats(userId);
       
        // Отправляем подробное сообщение о результате кика
        let kickMessage = '';
        if (kickedCount > 0) {
          kickMessage = `👢 Пользователь ${userDisplay} был кикнут из ${kickedCount} бесед`;
        } else {
          kickMessage = `⚠️ Пользователь ${userDisplay} не был найден в беседах`;
        }
       
        if (errors.length > 0) {
          kickMessage += `\n\n❌ Ошибки (${errors.length}):\n`;
          // Показываем только первые 3 ошибки
          errors.slice(0, 3).forEach(err => {
            kickMessage += `• ${err}\n`;
          });
        }
       
        await context.send({
          message: kickMessage,
          disable_mentions: true
        });
        // Запускаем дополнительную проверку через 5 секунд
        // (на случай, если пользователь был онлайн и не сразу кикнулся)
        setTimeout(async () => {
          console.log(`[SYSBAN] Повторная проверка пользователя ${userId} через 5 секунд`);
          const { kickedCount: additionalKicks } = await kickUserFromAllChats(userId);
          if (additionalKicks > 0) {
            await context.send({
              message: `👢 Дополнительно кикнуто из ${additionalKicks} бесед (повторная проверка)`,
              disable_mentions: true
            });
          }
        }, 5000);
      }
      // Сбрасываем счетчик после успешного выполнения
      const userUsage = commandUsage.get(context.senderId);
      if (userUsage) {
        userUsage.count = 0;
        userUsage.lastReset = Date.now();
        commandUsage.set(context.senderId, userUsage);
      }
    } catch (error) {
      console.error('SYSBAN ERROR:', error);
      context.reply('❌ Ошибка выполнения sysban');
    }
  }
};
// Экспортируем кэш для использования в других модулях
module.exports.bannedUsersCache = bannedUsersCache;
module.exports.isUserBanned = (userId) => bannedUsersCache.has(Number(userId));
Как сделал если не секрет?)
 
Мар
143
34
Пользователь
Не робит
Код:
[INFO] Всего загружено команд: 190
Системные таблицы проверены и готовы к использованию
Таблица chat_bans готова к использованию
[SYSBAN] Кэш забаненных обновлен: 0 пользователей
DEBUG: isSysBanned checking for userId: 166379753
DEBUG: isSysBanned checking for userId: 166379753
[DEBUG] Checking access for user 166379753 to command sysban, sysAccess: 14
[DEBUG] No individual access file for user 166379753, using default: true
[SYSBAN] Кэш забаненных обновлен: 0 пользователей
[SYSBAN] Повторная проверка пользователя 1054275617 через 5 секунд
[SYSBAN] Кэш забаненных обновлен: 0 пользователей
[SYSBAN] Кэш забаненных обновлен: 0 пользователей

Артём Калашников, сегодня в 18:30
/sysban @arabischer 2 0

WHITE MANAGER, сегодня в 18:30
🚨 Arabiacher Almaza заблокирован в системе бота

🔐 Тип: ⛔ Полный запрет бота
🕒 Срок: Навсегда
📝 Причина: Не указана

WHITE MANAGER, сегодня в 18:30
⚠️ Пользователь Arabiacher Almaza не был найден в беседах
 
Сен
393
201
Пользователь
Не робит
Код:
DEBUG: isSysBanned checking for userId: 166379753
DEBUG: isSysBanned checking for userId: 166379753
[DEBUG] Checking access for user 166379753 to command sysban, sysAccess: 14
[DEBUG] No individual access file for user 166379753, using default: true
[SYSBAN] Кэш забаненных обновлен: 0 пользователей
[SYSBAN] Повторная проверка пользователя 1054275617 через 5 секунд
[SYSBAN] Кэш забаненных обновлен: 0 пользователей

Артём Калашников, сегодня в 18:30
/sysban @arabischer 2 0

WHITE MANAGER, сегодня в 18:30
🚨 Arabiacher Almaza заблокирован в системе бота

🔐 Тип: ⛔ Полный запрет бота
🕒 Срок: Навсегда
📝 Причина: Не указана

WHITE MANAGER, сегодня в 18:30
⚠️ Пользователь Arabiacher Almaza не был найден в беседах
у бота во всех беседах есть админка? если нет то и не кикнет,если сохраняешь id_chat то при sysban сначала кэшировать,а потом он удаляет по техоньку по id_chat с user_id,если его нет в беседе то не сможет кикнуть ( не сразу иза ограничение апи запросов)
 
Мар
143
34
Пользователь
у бота во всех беседах есть админка? если нет то и не кикнет,если сохраняешь id_chat то при sysban сначала кэшировать,а потом он удаляет по техоньку по id_chat с user_id,если его нет в беседе то не сможет кикнуть ( не сразу иза ограничение апи запросов)
во всех есть админка у меня пока что 2 группы токо
 
Новичок
Окт
300
860
Активный
Не робит
Код:
[INFO] Всего загружено команд: 190
Системные таблицы проверены и готовы к использованию
Таблица chat_bans готова к использованию
[SYSBAN] Кэш забаненных обновлен: 0 пользователей
DEBUG: isSysBanned checking for userId: 166379753
DEBUG: isSysBanned checking for userId: 166379753
[DEBUG] Checking access for user 166379753 to command sysban, sysAccess: 14
[DEBUG] No individual access file for user 166379753, using default: true
[SYSBAN] Кэш забаненных обновлен: 0 пользователей
[SYSBAN] Повторная проверка пользователя 1054275617 через 5 секунд
[SYSBAN] Кэш забаненных обновлен: 0 пользователей
[SYSBAN] Кэш забаненных обновлен: 0 пользователей

Артём Калашников, сегодня в 18:30
/sysban @arabischer 2 0

WHITE MANAGER, сегодня в 18:30
🚨 Arabiacher Almaza заблокирован в системе бота

🔐 Тип: ⛔ Полный запрет бота
🕒 Срок: Навсегда
📝 Причина: Не указана

WHITE MANAGER, сегодня в 18:30
⚠️ Пользователь Arabiacher Almaza не был найден в беседах
сделай полный дебаг и чекай
 
Июл
367
324
Редактор
Помогите мне пж, не могу сделать систему кика в /sysban 2 уровня
Пыталюст сделать чтобы при /sysban @user 2(ур) [дней] [причина] он исключал человека из всех бесед где есть бот, но у меня не получается сделать) помогите сделать


Код:
const database = require('../databases.js');
const { checkSysAccess, getAccessLevelName } = require('./sysadmin.js');
const { hasCommandAccess, getAccessDeniedMessage } = require('../utils/commandAccess.js');
const { extractNumericId } = require('../utils/userUtils.js');
const vk = require('../vkInstance.js');
const util = require('util');
const fs = require('fs');
const path = require('path');
const databaseQuery = util.promisify(database.query);
const SYSBANNED_FILE = path.join(__dirname, '../data/sysbanned.json');
// Хранилище для отслеживания частоты использования команды
const commandUsage = new Map();
// Кэш забаненных пользователей для быстрой проверки
const bannedUsersCache = new Map();
const CACHE_UPDATE_INTERVAL = 60000; // Обновление кэша каждую минуту
// Функция обновления кэша забаненных пользователей
async function updateBannedUsersCache() {
  try {
    const now = Math.floor(Date.now() / 1000);
    const query = 'SELECT userid, time, level FROM sysbanned WHERE level = 2 AND (time = 0 OR time > ?)';
    const results = await databaseQuery(query, [now]);
    
    bannedUsersCache.clear();
    results.forEach(row => {
      bannedUsersCache.set(Number(row.userid), {
        level: row.level,
        time: row.time
      });
    });
    
    console.log(`[SYSBAN] Кэш забаненных обновлен: ${bannedUsersCache.size} пользователей`);
  } catch (error) {
    console.error('[SYSBAN] Ошибка обновления кэша:', error);
  }
}
// Обновляем кэш при старте и каждую минуту
updateBannedUsersCache();
setInterval(updateBannedUsersCache, CACHE_UPDATE_INTERVAL);
function isLevel2Banned(userId) {
  if (!fs.existsSync(SYSBANNED_FILE)) return false;
  const data = JSON.parse(fs.readFileSync(SYSBANNED_FILE, 'utf-8'));
  const now = Math.floor(Date.now() / 1000);
  const ban = data.find(u => u.userid === userId && u.level === 2 && (u.time === 0 || u.time > now));
  return !!ban;
}
// Функция для проверки лимита использования команды
function checkCommandLimit(userId) {
  const now = Date.now();
  const userUsage = commandUsage.get(userId) || { count: 0, lastReset: now, blockedUntil: 0 };
  
  // Проверяем, не заблокирован ли пользователь
  if (userUsage.blockedUntil > now) {
    const minutesLeft = Math.ceil((userUsage.blockedUntil - now) / 60000);
    return { 
      allowed: false, 
      message: `❌ Превышен лимит использования команды. Попробуйте через ${minutesLeft} мин.` 
    };
  }
  
  // Сбрасываем счетчик, если прошло больше 10 минут с последнего сброса
  if (now - userUsage.lastReset > 600000) { // 10 минут в миллисекундах
    userUsage.count = 0;
    userUsage.lastReset = now;
  }
  
  // Увеличиваем счетчик
  userUsage.count++;
  
  // Если использовано 3 раза подряд, блокируем на 10 минут
  if (userUsage.count >= 3) {
    userUsage.blockedUntil = now + 600000; // 10 минут
    userUsage.count = 0;
    commandUsage.set(userId, userUsage);
    return { 
      allowed: false, 
      message: '❌ Превышен лимит использования команды. Команда заблокирована на 10 минут.' 
    };
  }
  
  commandUsage.set(userId, userUsage);
  return { allowed: true };
}
// Улучшенная функция для кика пользователя из всех бесед
async function kickUserFromAllChats(userId) {
  try {
    // Получаем список всех бесед, где есть бот
    const conversations = await vk.api.messages.getConversations({
      count: 200,
    });
    let kickedCount = 0;
    const errors = [];
    const kickPromises = [];
    for (const item of conversations.items) {
      const peerId = item.conversation.peer.id;
      
      // Только беседы
      if (peerId <= 2000000000) {
        continue;
      }
    // Беседа отключена
     if (
       item.conversation.chat_settings?.state === 'disabled'
  ) {
    continue;
  }
     // Нет настроек беседы = мёртвый чат
     if (!item.conversation.chat_settings) {
    continue;
  }
    // Бот не может писать
     if (
       item.conversation.can_write &&
       item.conversation.can_write.allowed === false
  ) {
    continue;
  }
  // Сразу пытаемся кикнуть
  const kickPromise = vk.api.messages.removeChatUser({
    chat_id: peerId - 2000000000,
    user_id: userId
  })
  .then(() => {
    kickedCount++;
    console.log(
      `[SYSBAN] Пользователь ${userId} кикнут из беседы ${peerId}`
    );
  })
  .catch(error => {
    // Игнорируем недоступные беседы
    if (
      error.code === 945 ||
      error.message?.includes('Chat was disabled')
    ) {
      return;
    }
    // Пользователя уже нет
    if (
      error.code === 935 ||
      error.message?.includes('User not in chat')
    ) {
      return;
    }
    const errorMsg =
      `Ошибка при кике из беседы ${peerId}: ${error.message}`;
    console.error(`[SYSBAN] ${errorMsg}`);
    errors.push(errorMsg);
  });
  kickPromises.push(kickPromise);
}
    // Ждем завершения всех операций кика
    await Promise.allSettled(kickPromises);
    
    return { kickedCount, errors };
  } catch (error) {
    console.error('[SYSBAN] Ошибка при кике пользователя из всех бесед:', error);
    return { kickedCount: 0, errors: [error.message] };
  }
}
// Функция для автоматического кика при попытке добавить в беседу
async function setupAutoKick() {
  try {
    // Слушаем новые сообщения о добавлении в беседу
    const eventHandler = async (event) => {
      if (event.type === 'message_new') {
        const message = event.object.message;
        
        // Проверяем, что это действие с беседой
        if (message.action && message.action.type === 'chat_invite_user') {
          const invitedUserId = message.action.member_id;
          
          // Быстрая проверка по кэшу
          if (bannedUsersCache.has(invitedUserId)) {
            console.log(`[SYSBAN] Обнаружена попытка добавить забаненного пользователя ${invitedUserId} в беседу ${message.peer_id}`);
            
            // Немедленно кикаем
            try {
              await vk.api.messages.removeChatUser({
                chat_id: message.peer_id - 2000000000,
                user_id: invitedUserId
              });
              
              console.log(`[SYSBAN] Забаненный пользователь ${invitedUserId} автоматически кикнут из беседы ${message.peer_id}`);
              
              // Отправляем уведомление в беседу
              await vk.api.messages.send({
                peer_id: message.peer_id,
                message: `🚫 Пользователь [id${invitedUserId}|заблокирован] в системе бота и не может быть добавлен в беседы.`,
                random_id: Math.floor(Math.random() * 1e9),
                disable_mentions: true
              });
            } catch (kickError) {
              console.error(`[SYSBAN] Ошибка при автоматическом кике:`, kickError);
            }
          }
        }
      }
    };
    
    // Подключаем обработчик (способ подключения зависит от вашей архитектуры)
    // vk.updates.on('message_new', eventHandler);
    console.log('[SYSBAN] Автоматический кик настроен');
    
  } catch (error) {
    console.error('[SYSBAN] Ошибка настройки авто-кика:', error);
  }
}
// Запускаем авто-кик
setupAutoKick();
// Очистка старых записей раз в час
setInterval(() => {
  const now = Date.now();
  for (const [userId, data] of commandUsage.entries()) {
    if (data.blockedUntil < now && now - data.lastReset > 3600000) { // если блокировка прошла и прошёл час
      commandUsage.delete(userId);
    }
  }
}, 3600000); // Каждый час
module.exports = {
  command: '/sysban',
  description: 'Блокировка пользователя в системе бота (2 степени)',
  async execute(context) {
    try {
      // Проверка лимита использования
      const limitCheck = checkCommandLimit(context.senderId);
      if (!limitCheck.allowed) {
        return context.reply(limitCheck.message);
      }
      const hasAccess = await hasCommandAccess(context.senderId, 'sysban');
      if (!hasAccess) return context.reply(getAccessDeniedMessage('sysban'));
      const args = context.text.split(' ');
      if (args.length < 4) return context.reply('❌ Использование:\n/sysban [ID] [1|2] [дни|0] [причина]');
      const userId = await extractNumericId(args[1]);
      if (!userId) return context.reply('❌ Ошибка | Некорректный ID пользователя');
      if (userId === context.senderId) return context.reply('❌ Ошибка | Нельзя заблокировать самого себя');
      if (global.botId && Number(userId) === Number(global.botId)) return context.reply('🤖 Нельзя заблокировать бота');
      const senderAccess = await checkSysAccess(context.senderId);
      let targetAccess = 0;
      try { targetAccess = await checkSysAccess(userId); } catch {}
      if (targetAccess >= senderAccess && targetAccess > 0) {
        return context.reply(`❌ Ошибка | Вы не можете заблокировать пользователя с уровнем "${getAccessLevelName(targetAccess)}"`);
      }
      const banLevel = parseInt(args[2]);
      if (![1, 2].includes(banLevel)) return context.reply('❌ Уровень ЧСБ может быть только 1 или 2');
      const banDays = parseInt(args[3]);
      if (isNaN(banDays) || banDays < 0) return context.reply('❌ Некорректный срок блокировки');
      const reason = args.slice(4).join(' ') || 'Не указана';
      const now = Math.floor(Date.now() / 1000);
      const endTime = banDays === 0 ? 0 : now + banDays * 86400;
      const query = `
        INSERT INTO sysbanned (userid, time, reason, who, level)
        VALUES (?, ?, ?, ?, ?)
        ON DUPLICATE KEY UPDATE
          time = VALUES(time),
          reason = VALUES(reason),
          who = VALUES(who),
          level = VALUES(level)
      `;
      await databaseQuery(query, [userId, endTime, reason, context.senderId, banLevel]);
      // Обновляем кэш сразу после бана
      if (banLevel === 2) {
        bannedUsersCache.set(Number(userId), {
          level: 2,
          time: endTime
        });
      }
      let userDisplay = `@id${userId}`;
      try {
        const u = (await vk.api.users.get({ user_ids: userId }))[0];
        if (u) userDisplay = `[id${userId}|${u.first_name} ${u.last_name}]`;
      } catch {}
      const banType = banLevel === 1 ? '🚫 Запрет команд' : '⛔ Полный запрет бота';
      let message = `🚨 ${userDisplay} заблокирован в системе бота\n\n`;
      message += `🔐 Тип: ${banType}\n`;
      message += `🕒 Срок: ${banDays === 0 ? 'Навсегда' : banDays + ' дн.'}\n`;
      message += `📝 Причина: ${reason}`;
      await context.send({ message, disable_mentions: true });
      try {
        await vk.api.messages.send({
          peer_id: userId,
          message,
          random_id: Math.floor(Math.random() * 1e9),
          disable_mentions: true
        });
      } catch {}
      // Если это полный запрет (уровень 2), кикаем пользователя из всех бесед
      if (banLevel === 2) {
        const { kickedCount, errors } = await kickUserFromAllChats(userId);
        
        // Отправляем подробное сообщение о результате кика
        let kickMessage = '';
        if (kickedCount > 0) {
          kickMessage = `👢 Пользователь ${userDisplay} был кикнут из ${kickedCount} бесед`;
        } else {
          kickMessage = `⚠️ Пользователь ${userDisplay} не был найден в беседах`;
        }
        
        if (errors.length > 0) {
          kickMessage += `\n\n❌ Ошибки (${errors.length}):\n`;
          // Показываем только первые 3 ошибки
          errors.slice(0, 3).forEach(err => {
            kickMessage += `• ${err}\n`;
          });
        }
        
        await context.send({
          message: kickMessage,
          disable_mentions: true
        });
        // Запускаем дополнительную проверку через 5 секунд
        // (на случай, если пользователь был онлайн и не сразу кикнулся)
        setTimeout(async () => {
          console.log(`[SYSBAN] Повторная проверка пользователя ${userId} через 5 секунд`);
          const { kickedCount: additionalKicks } = await kickUserFromAllChats(userId);
          if (additionalKicks > 0) {
            await context.send({
              message: `👢 Дополнительно кикнуто из ${additionalKicks} бесед (повторная проверка)`,
              disable_mentions: true
            });
          }
        }, 5000);
      }
      // Сбрасываем счетчик после успешного выполнения
      const userUsage = commandUsage.get(context.senderId);
      if (userUsage) {
        userUsage.count = 0;
        userUsage.lastReset = Date.now();
        commandUsage.set(context.senderId, userUsage);
      }
    } catch (error) {
      console.error('SYSBAN ERROR:', error);
      context.reply('❌ Ошибка выполнения sysban');
    }
  }
};
// Экспортируем кэш для использования в других модулях
module.exports.bannedUsersCache = bannedUsersCache;
module.exports.isUserBanned = (userId) => bannedUsersCache.has(Number(userId));

getConversations не возвращает беседы где есть пользователь, либо бот не видит их через свой токен. Добавь console.log прямо в цикл перед киком и посмотри сколько бесед вообще возвращается, скорее всего 0.
 
Мар
143
34
Пользователь
getConversations не возвращает беседы где есть пользователь, либо бот не видит их через свой токен. Добавь console.log прямо в цикл перед киком и посмотри сколько бесед вообще возвращается, скорее всего 0.
дайте лучше номер строки лучше)
 
Июл
367
324
Редактор
Мар
143
34
Пользователь
Зачем? Проблема не в синтаксисе, а в логике. Просто добавь console.log(conversations.items.length) после получения бесед и скинь что выведет.
Код:
[INFO] Всего загружено команд: 190
Системные таблицы проверены и готовы к использованию
Таблица chat_bans готова к использованию
[SYSBAN] Кэш забаненных обновлен: 0 пользователей
DEBUG: isSysBanned checking for userId: 166379753
DEBUG: isSysBanned checking for userId: 166379753
[DEBUG] Checking access for user 166379753 to command sysban, sysAccess: 14
[DEBUG] No individual access file for user 166379753, using default: true
[SYSBAN] Повторная проверка пользователя 1054275617 через 5 секунд
[SYSBAN] Кэш забаненных обновлен: 0 пользователей
 
Июл
367
324
Редактор
Код:
[INFO] Всего загружено команд: 190
Системные таблицы проверены и готовы к использованию
Таблица chat_bans готова к использованию
[SYSBAN] Кэш забаненных обновлен: 0 пользователей
DEBUG: isSysBanned checking for userId: 166379753
DEBUG: isSysBanned checking for userId: 166379753
[DEBUG] Checking access for user 166379753 to command sysban, sysAccess: 14
[DEBUG] No individual access file for user 166379753, using default: true
[SYSBAN] Повторная проверка пользователя 1054275617 через 5 секунд
[SYSBAN] Кэш забаненных обновлен: 0 пользователей

Все равно не кикает

Беседы вообще не логируются, это значит что getConversations возвращает пустой массив или падает до цикла. Возможно токен бота не имеет доступа к беседам, проверь scope токена - нужен messages.
 
Мар
143
34
Пользователь
Беседы вообще не логируются, это значит что getConversations возвращает пустой массив или падает до цикла. Возможно токен бота не имеет доступа к беседам, проверь scope токена - нужен messages.
Попробую пересоздать токен, потому что не помню давал там я messages или нет
 
Мар
143
34
Пользователь
Беседы вообще не логируются, это значит что getConversations возвращает пустой массив или падает до цикла. Возможно токен бота не имеет доступа к беседам, проверь scope токена - нужен messages.
Поменял Токен не помогло...
 
Сверху