From c28e5832053011dbd07179b7d4bb1d8bee855728 Mon Sep 17 00:00:00 2001 From: Whyverum Date: Mon, 8 Dec 2025 16:42:19 +0700 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=BF=D1=80=D0=B5=D0=B4=D1=8B=D0=B4=D1=83=D1=89=D0=B5?= =?UTF-8?q?=D0=B3=D0=BE=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=82=D0=B0=20?= =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot.log | 4 - bot.py | 405 -------------------------------------------------------- 2 files changed, 409 deletions(-) delete mode 100644 bot.log delete mode 100644 bot.py diff --git a/bot.log b/bot.log deleted file mode 100644 index b5a094e..0000000 --- a/bot.log +++ /dev/null @@ -1,4 +0,0 @@ -2025-12-08 13:08:26,502:WARNING:discord.client: PyNaCl is not installed, voice will NOT be supported -2025-12-08 13:08:26,504:INFO:discord.client: logging in using static token -2025-12-08 14:08:52,657:WARNING:discord.client: PyNaCl is not installed, voice will NOT be supported -2025-12-08 14:08:52,659:INFO:discord.client: logging in using static token diff --git a/bot.py b/bot.py deleted file mode 100644 index b25ed08..0000000 --- a/bot.py +++ /dev/null @@ -1,405 +0,0 @@ -import discord -from discord.ext import commands, tasks -from discord.utils import get -import datetime -import logging -import os -import json - -# --- Настройки и константы --- -BOT_TOKEN = '11' -WELCOME_CHANNEL_ID = 1342797233250107482 # ID канала для приветствий -ADMIN_ROLE_NAME = "Администратор" - -WARNINGS_FILE = "warnings.json" -REMINDERS_FILE = "reminders.json" -BLACKLIST_FILE = "blacklist.json" - -# --- Логирование --- -logging.basicConfig( - filename='bot.log', - level=logging.INFO, - format='%(asctime)s:%(levelname)s:%(name)s: %(message)s' -) - -# --- Интенты --- -intents = discord.Intents.default() -intents.message_content = True -intents.members = True - -# --- Глобальные переменные --- -reminders = [] -user_warnings = {} -blacklist = [] - -# --- Хелп команда --- -class MyHelpCommand(commands.HelpCommand): - async def send_bot_help(self, mapping): - channel = self.get_destination() - help_text = ( - "**Доступные команды:**\n" - "`!help` — показать это сообщение\n" - "`!rules` — показать правила сервера\n" - "`!reminder add <минуты> <текст>` — добавить напоминание (только для админов)\n" - "`!reminder list` — показать все активные напоминания\n" - "`!reminder remove <номер>` — удалить напоминание\n" - "`!kick @пользователь [причина]` — исключить участника\n" - "`!ban @пользователь [причина]` — забанить участника\n" - "`!unban имя#дискриминатор` — разбанить участника\n" - "`!mute @пользователь [причина]` — заглушить участника\n" - "`!unmute @пользователь` — снять заглушение\n" - "`!warn @пользователь [причина]` — выдать предупреждение\n" - "`!warnings @пользователь` — посмотреть предупреждения\n" - "`!clear <кол-во>` — удалить сообщения\n" - "`!blacklist_show` — показать чёрный список (админ)\n" - "`!blacklist_add <слово>` — добавить слово в чёрный список (админ)\n" - "`!blacklist_remove <слово>` — удалить слово из чёрного списка (админ)\n" - ) - await channel.send(help_text) - -# --- Инициализация бота --- -bot = commands.Bot(command_prefix='!', intents=intents, help_command=MyHelpCommand()) - -# --- Функции загрузки и сохранения данных --- -def load_data(): - global reminders, user_warnings - if os.path.isfile(WARNINGS_FILE): - with open(WARNINGS_FILE, 'r', encoding='utf-8') as f: - try: - user_warnings.update(json.load(f)) - except json.JSONDecodeError: - user_warnings.clear() - if os.path.isfile(REMINDERS_FILE): - with open(REMINDERS_FILE, 'r', encoding='utf-8') as f: - try: - reminders.extend(json.load(f)) - except json.JSONDecodeError: - reminders.clear() - -def save_warnings(): - with open(WARNINGS_FILE, 'w', encoding='utf-8') as f: - json.dump(user_warnings, f, ensure_ascii=False, indent=2) - -def save_reminders(): - with open(REMINDERS_FILE, 'w', encoding='utf-8') as f: - json.dump(reminders, f, ensure_ascii=False, indent=2) - -def load_blacklist_local(): - global blacklist - if os.path.isfile(BLACKLIST_FILE): - try: - with open(BLACKLIST_FILE, 'r', encoding='utf-8') as f: - blacklist = json.load(f) - except Exception: - blacklist = [] - else: - blacklist = [] - -def save_blacklist_local(): - with open(BLACKLIST_FILE, 'w', encoding='utf-8') as f: - json.dump(blacklist, f, ensure_ascii=False, indent=2) - -# --- Проверка и создание ролей --- -async def ensure_roles_exist(): - for guild in bot.guilds: - muted_role = get(guild.roles, name="Muted") - if not muted_role: - try: - muted_role = await guild.create_role(name="Muted") - for channel in guild.channels: - await channel.set_permissions(muted_role, send_messages=False, speak=False) - logging.info(f"Создана роль 'Muted' в {guild.name}") - except Exception as e: - logging.error(f"Ошибка при создании роли Muted в {guild.name}: {e}") - - new_member_role = get(guild.roles, name="New Member") - if not new_member_role: - try: - new_member_role = await guild.create_role(name="New Member") - logging.info(f"Создана роль 'New Member' в {guild.name}") - except Exception as e: - logging.error(f"Ошибка при создании роли New Member в {guild.name}: {e}") - -# --- События --- - -@bot.event -async def on_ready(): - print(f'Бот запущен как {bot.user}') - if not check_reminders.is_running(): - check_reminders.start() - load_data() - load_blacklist_local() - await ensure_roles_exist() - -@bot.event -async def on_member_join(member): - role = get(member.guild.roles, name="New Member") - if role: - await member.add_roles(role) - channel = bot.get_channel(WELCOME_CHANNEL_ID) - if channel: - await channel.send(f"Приветствуем {member.mention} на сервере!") - -@bot.event -async def on_message(message): - if message.author.bot: - return - # Проверка на запрещённые слова - msg_lower = message.content.lower() - if any(word in msg_lower for word in blacklist): - try: - await message.delete() - await message.channel.send(f"{message.author.mention}, ваше сообщение содержит запрещённые слова.") - logging.info(f"Удалено сообщение с запрещёнными словами от {message.author} в {message.channel}") - except Exception as e: - logging.error(f"Ошибка при удалении сообщения: {e}") - return - - await bot.process_commands(message) - -# --- Проверка прав администратора --- -def is_admin(): - def predicate(ctx): - return get(ctx.author.roles, name=ADMIN_ROLE_NAME) is not None or ctx.author.guild_permissions.administrator - return commands.check(predicate) - -# --- Команды модерации и управления --- - -@bot.command() -@is_admin() -async def blacklist_show(ctx): - if not blacklist: - await ctx.send("Чёрный список пуст.") - else: - await ctx.send("Чёрный список:\n" + ", ".join(blacklist)) - -@bot.command() -@is_admin() -async def blacklist_add(ctx, *, word: str): - word = word.lower() - if word in blacklist: - await ctx.send(f"Слово `{word}` уже в чёрном списке.") - else: - blacklist.append(word) - save_blacklist_local() - await ctx.send(f"Слово `{word}` добавлено в чёрный список.") - -@bot.command() -@is_admin() -async def blacklist_remove(ctx, *, word: str): - word = word.lower() - if word not in blacklist: - await ctx.send(f"Слово `{word}` отсутствует в чёрном списке.") - else: - blacklist.remove(word) - save_blacklist_local() - await ctx.send(f"Слово `{word}` удалено из чёрного списка.") - -@bot.command() -@is_admin() -async def rules(ctx): - rules_text = ( - "**Правила сервера:**\n" - "1. Уважайте других участников.\n" - "2. Запрещена реклама и спам.\n" - "3. Не используйте запрещённые слова.\n" - "4. Соблюдайте тематику каналов.\n" - "5. Выполняйте указания модераторов.\n" - ) - await ctx.send(rules_text) - -@bot.command() -@is_admin() -async def kick(ctx, member: discord.Member, *, reason=None): - try: - await member.kick(reason=reason) - await ctx.send(f"{member} был исключён. Причина: {reason}") - logging.info(f"{member} был исключён администратором {ctx.author}. Причина: {reason}") - except Exception as e: - await ctx.send(f"Не удалось исключить {member}.") - logging.error(f"Ошибка при исключении: {e}") - -@bot.command() -@is_admin() -async def ban(ctx, member: discord.Member, *, reason=None): - try: - await member.ban(reason=reason) - await ctx.send(f"{member} был забанен. Причина: {reason}") - logging.info(f"{member} был забанен администратором {ctx.author}. Причина: {reason}") - except Exception as e: - await ctx.send(f"Не удалось забанить {member}.") - logging.error(f"Ошибка при бане: {e}") - - -@bot.command() -@commands.has_permissions(ban_members=True) -async def unban(ctx, *, member_name): - banned_users = [] - async for ban_entry in ctx.guild.bans(): - banned_users.append(ban_entry) - - # Если указан полный тег с # - if '#' in member_name: - try: - name, discriminator = member_name.split('#') - except ValueError: - await ctx.send("Неверный формат пользователя. Используйте Имя#Тег.") - return - - for ban_entry in banned_users: - user = ban_entry.user - if (user.name, user.discriminator) == (name, discriminator): - try: - await ctx.guild.unban(user) - await ctx.send(f"Пользователь {user} разбанен.") - return - except Exception as e: - await ctx.send("Ошибка при разбане.") - logging.error(f"Ошибка при разбане: {e}") - return - - await ctx.send(f"Пользователь {member_name} не найден в бан-листе.") - return - - # Если указан только имя без тега — ищем все совпадения по имени - matching = [ban_entry.user for ban_entry in banned_users if ban_entry.user.name.lower() == member_name.lower()] - - if not matching: - await ctx.send(f"Пользователь с именем `{member_name}` не найден в бан-листе.") - return - - if len(matching) == 1: - user = matching[0] - try: - await ctx.guild.unban(user) - await ctx.send(f"Пользователь {user} разбанен.") - except Exception as e: - await ctx.send("Ошибка при разбане.") - logging.error(f"Ошибка при разбане: {e}") - return - - # Если совпадений несколько — выводим список для выбора - msg = "Найдено несколько пользователей с таким именем. Укажите полный тег для разбанивания:\n" - for user in matching: - msg += f"- {user.name}#{user.discriminator}\n" - await ctx.send(msg) - -@bot.command() -@is_admin() -async def mute(ctx, member: discord.Member, *, reason=None): - muted_role = get(ctx.guild.roles, name="Muted") - if not muted_role: - await ctx.send("Роль Muted не найдена.") - return - try: - await member.add_roles(muted_role) - await ctx.send(f"{member} заглушен. Причина: {reason}") - except Exception as e: - await ctx.send("Не удалось выдать мут.") - logging.error(f"Ошибка при муте: {e}") - -@bot.command() -@is_admin() -async def unmute(ctx, member: discord.Member): - muted_role = get(ctx.guild.roles, name="Muted") - if not muted_role: - await ctx.send("Роль Muted не найдена.") - return - try: - await member.remove_roles(muted_role) - await ctx.send(f"С мутом снято с {member}.") - except Exception as e: - await ctx.send("Не удалось снять мут.") - logging.error(f"Ошибка при снятии мута: {e}") - -@bot.command() -@is_admin() -async def warn(ctx, member: discord.Member, *, reason=None): - user_id = str(member.id) - if user_id not in user_warnings: - user_warnings[user_id] = [] - user_warnings[user_id].append({"reason": reason or "Без причины", "date": str(datetime.datetime.now())}) - save_warnings() - await ctx.send(f"{member} получил предупреждение. Причина: {reason or 'Без причины'}") - -@bot.command() -async def warnings(ctx, member: discord.Member): - user_id = str(member.id) - warns = user_warnings.get(user_id, []) - if not warns: - await ctx.send(f"У пользователя {member} нет предупреждений.") - return - msg = f"Предупреждения пользователя {member}:\n" - for i, w in enumerate(warns, 1): - msg += f"{i}. {w['reason']} ({w['date']})\n" - await ctx.send(msg) - -@bot.command() -@is_admin() -async def clear(ctx, amount: int): - if amount <= 0: - await ctx.send("Количество должно быть положительным числом.") - return - deleted = await ctx.channel.purge(limit=amount + 1) - await ctx.send(f"Удалено сообщений: {len(deleted)-1}", delete_after=5) - -# --- Команды напоминаний --- -@bot.group() -@is_admin() -async def reminder(ctx): - if ctx.invoked_subcommand is None: - await ctx.send("Используйте `!reminder add <минуты> <текст>`, `!reminder list` или `!reminder remove <номер>`") - -@reminder.command(name="add") -async def reminder_add(ctx, minutes: int, *, text: str): - if minutes <= 0: - await ctx.send("Время должно быть положительным числом минут.") - return - remind_time = datetime.datetime.now() + datetime.timedelta(minutes=minutes) - reminders.append({ - "time": remind_time.timestamp(), - "channel_id": ctx.channel.id, - "user_mention": ctx.author.mention, - "text": text - }) - save_reminders() - await ctx.send(f"Напоминание добавлено через {minutes} минут: {text}") - -@reminder.command(name="list") -async def reminder_list(ctx): - if not reminders: - await ctx.send("Активных напоминаний нет.") - return - msg = "Активные напоминания:\n" - for i, rem in enumerate(reminders, 1): - t = datetime.datetime.fromtimestamp(rem["time"]).strftime("%Y-%m-%d %H:%M:%S") - msg += f"{i}. Через {t} — {rem['text']} (от {rem['user_mention']})\n" - await ctx.send(msg) - -@reminder.command(name="remove") -async def reminder_remove(ctx, number: int): - if number <= 0 or number > len(reminders): - await ctx.send("Неверный номер напоминания.") - return - removed = reminders.pop(number - 1) - save_reminders() - await ctx.send(f"Удалено напоминание: {removed['text']}") - -# --- Фоновая задача проверки напоминаний --- -@tasks.loop(seconds=30) -async def check_reminders(): - now = datetime.datetime.now().timestamp() - to_remove = [] - for rem in reminders: - if rem['time'] <= now: - channel = bot.get_channel(rem['channel_id']) - if channel: - await channel.send(f"{rem['user_mention']} Напоминание: {rem['text']}") - to_remove.append(rem) - for rem in to_remove: - reminders.remove(rem) - if to_remove: - save_reminders() - -# --- Запуск бота --- -bot.run(BOT_TOKEN)