commit 812448282a5c52311a0cdb05e7db12b34a21524d Author: payzinn Date: Sat Jan 11 03:09:05 2025 +0600 init diff --git a/.env b/.env new file mode 100644 index 0000000..44551ad --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +BOT_TOKEN=7880464408:AAEiLDCgB4r2XVNtEoZHbwKJnFmDUbGSc0Y +DATABASE_URL=postgresql+asyncpg://postgres:2780@host.docker.internal/delete_message +# DATABASE_URL=postgresql+asyncpg://postgres:2780@localhost/delete_message +ADMINS = [6155921710, 6297555082] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..93526df --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +venv/ +__pycache__/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8f9468b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.11-slim-bullseye + +ENV PYTHONUNBUFFERED=1 +ENV PYTHONWARNINGS="ignore" +ENV SQLALCHEMY_WARN_20=0 +ENV PYTHONDONTWRITEBYTECODE=1 + +WORKDIR / + +COPY requirements.txt . + +RUN pip install --no-cache-dir --upgrade pip \ + && pip install --no-cache-dir -r requirements.txt + +COPY . . + +CMD ["python", "bot.py"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..41263a8 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# DELETING_MESSAGES + +## Описание +Бот добавляет в базу данных тех, кто может писать в чат + +# Запуск через python + +### 1. Создаём виртуальное окружение +```cmd + python -m venv venv +``` + +### 2. Активируем виртуальное окружение +```cmd + venv\Scripts\activate +``` +### 3. Устанавливаем зависимости +```cmd + pip install -r requirements.txt +``` + +### 4. Переименовываем .env copy в .env + Вставляем свой токен бота + + +### 5. Запуск +```cmd + python bot.py +``` + +# Запуск через Docker + +### 1. Создание докер приложения + перейдите в директорию с ботом и пропишите следующую команду (с точкой) +```cmd + docker build -t название . +``` + +### 2. Активируем докер приложение +```cmd + docker run название +``` + +# Добавление админа + + чтобы добавить админа нужно в файле .env в список ADMINS добавить айди админа \ No newline at end of file diff --git a/bot.py b/bot.py new file mode 100644 index 0000000..2f16b32 --- /dev/null +++ b/bot.py @@ -0,0 +1,18 @@ +import asyncio +from handlers import router +from aiogram import Bot, Dispatcher +from config import BOT_TOKEN + +bot = Bot(token=BOT_TOKEN) +dp = Dispatcher() + + +async def main(): + dp.include_router(router) + await dp.start_polling(bot) + +if __name__ == "__main__": + try: + asyncio.run(main()) + except KeyboardInterrupt: + print('Exit') \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 0000000..e78241e --- /dev/null +++ b/config.py @@ -0,0 +1,8 @@ +import os +from dotenv import load_dotenv + + +load_dotenv() +BOT_TOKEN = os.getenv('BOT_TOKEN') +DATABASE_URL = os.getenv('DATABASE_URL') +ADMINS = list(map(int, os.getenv("ADMINS", "").strip("[]").split(","))) \ No newline at end of file diff --git a/db.py b/db.py new file mode 100644 index 0000000..7bacdb5 --- /dev/null +++ b/db.py @@ -0,0 +1,23 @@ +import logging +logging.basicConfig(level=logging.ERROR) +logging.getLogger('sqlalchemy.pool').setLevel(logging.ERROR) +logging.getLogger('sqlalchemy').setLevel(logging.ERROR) +logging.getLogger('sqlalchemy').propagate = False +from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine +from sqlalchemy.orm import sessionmaker +from sqlalchemy.ext.asyncio import async_sessionmaker +from models import Base +from config import DATABASE_URL +import warnings +warnings.filterwarnings("ignore") + +# Создание асинхронного движка для подключения к базе данных +engine = create_async_engine(DATABASE_URL, echo=False, pool_pre_ping=True) + +# Создание сессий для работы с базой данных +async_session = async_sessionmaker(engine, expire_on_commit=False, class_=AsyncSession) + +# Функция для инициализации базы данных +async def init_db(): + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) # Создание всех таблиц, определенных в моделях diff --git a/delete_message_backup.dump b/delete_message_backup.dump new file mode 100644 index 0000000..479dcf4 Binary files /dev/null and b/delete_message_backup.dump differ diff --git a/handlers.py b/handlers.py new file mode 100644 index 0000000..71eb303 --- /dev/null +++ b/handlers.py @@ -0,0 +1,88 @@ +from aiogram.filters import CommandStart, Command +from aiogram.types import Message, CallbackQuery +from aiogram import F, Router +from aiogram.fsm.state import StatesGroup, State +from aiogram.fsm.context import FSMContext +from db import async_session +from models import Users +from sqlalchemy.future import select +from sqlalchemy import and_ +from states import Admin +from config import ADMINS + +router = Router() + +@router.message(CommandStart()) +async def start(message: Message, state: FSMContext): + if message.from_user.id in ADMINS: + await state.clear() + await message.reply(f"Привет, я бот который следит за сообщениями в группе, и удаляет сообщения тех пользователей кого нет в моём списке.\n/admin_id") + else: + await message.delete() + await message.answer( + "Приветствую! Вы недавно в нашем чате? Тогда вам обязательно нужно [ознакомиться с методичкой для новичков](https://telegra.ph/Segodnya-reshila-napisat-metodichku-dlya-novichkov-kto-po-kakim-libo-prichinam-ne-smotrel-video-iz-chata-01-08-3).", + parse_mode="Markdown", + disable_web_page_preview=True + ) + +@router.message(Command("admin_id")) +async def admin_command(message: Message, state: FSMContext): + if message.from_user.id in ADMINS: + await state.set_state(Admin.users) + await message.reply("Пожалуйста, введите ID пользователей, чьи сообщения не будут удаляться. Каждый ID должен быть на отдельной строке.") + else: + await message.delete() + await message.answer( + "Приветствую! Вы недавно в нашем чате? Тогда вам обязательно нужно [ознакомиться с методичкой для новичков](https://telegra.ph/Segodnya-reshila-napisat-metodichku-dlya-novichkov-kto-po-kakim-libo-prichinam-ne-smotrel-video-iz-chata-01-08-3).", + parse_mode="Markdown", + disable_web_page_preview=True + ) + +@router.message(Admin.users) +async def check_id(message: Message, state: FSMContext): + if not message.text.isalpha(): + ids = message.text.split("\n") + valid_ids = [] + + async with async_session() as session: + for user_id in ids: + try: + user_id_int = int(user_id.strip()) + valid_ids.append(user_id_int) + + result = await session.execute(select(Users).where(Users.user_id == user_id_int)) + existing_user = result.scalars().first() + + if not existing_user: + new_user = Users(user_id=user_id_int) + session.add(new_user) + except ValueError: + await message.reply(f"⛔ Ошибка: ID `{user_id}` не является числом.") + continue + + await session.commit() + + await message.reply("Список ID пользователей, чьи сообщения не будут удаляться, успешно обновлен! 👍") + await state.clear() + else: + await message.reply("⛔ Ошибка: ID должны состоять только из цифр.") + await state.clear() + +@router.message() +async def delete_messages(message: Message): + user_id = message.from_user.id + + if user_id in ADMINS: + return + + async with async_session() as session: + result = await session.execute(select(Users).where(Users.user_id == user_id)) + existing_user = result.scalars().first() + + if not existing_user: + await message.delete() + await message.answer( + "Приветствую! Вы недавно в нашем чате? Тогда вам обязательно нужно [ознакомиться с методичкой для новичков](https://telegra.ph/Segodnya-reshila-napisat-metodichku-dlya-novichkov-kto-po-kakim-libo-prichinam-ne-smotrel-video-iz-chata-01-08-3).", + parse_mode="Markdown", + disable_web_page_preview=True + ) diff --git a/models.py b/models.py new file mode 100644 index 0000000..b3e281a --- /dev/null +++ b/models.py @@ -0,0 +1,11 @@ +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy import BigInteger, Column, Integer + +# Создание базового класса для моделей +Base = declarative_base() + +class Users(Base): + __tablename__ = 'users' + + id = Column(Integer, primary_key=True, index=True) + user_id = Column(BigInteger, unique=True, index = True) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..fc8590d Binary files /dev/null and b/requirements.txt differ diff --git a/states.py b/states.py new file mode 100644 index 0000000..2c85229 --- /dev/null +++ b/states.py @@ -0,0 +1,7 @@ +from aiogram import F +from aiogram.fsm.state import StatesGroup, State + + +class Admin(StatesGroup): + users = State() + \ No newline at end of file