From 529b5aeb69e92a5697751248b34342e2755f380d Mon Sep 17 00:00:00 2001 From: Kyle Date: Thu, 4 Jun 2020 20:21:38 +0300 Subject: [PATCH 1/2] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83?= =?UTF-8?q?=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 12 +------ app.py | 5 ++- data/config.py | 20 +++++++----- filters/__init__.py | 9 ++--- handlers/__init__.py | 9 ++--- handlers/channels/__init__.py | 1 + handlers/errors/__init__.py | 3 -- handlers/errors/error_handler.py | 56 -------------------------------- handlers/groups/__init__.py | 1 + handlers/users/__init__.py | 5 --- handlers/users/echo.py | 7 ---- handlers/users/help.py | 16 --------- handlers/users/start.py | 9 ----- requirements.txt | 45 +++++++++++++++++++++++-- utils/misc/__init__.py | 1 - utils/notify_admins.py | 22 ++++++++----- 16 files changed, 85 insertions(+), 136 deletions(-) delete mode 100644 handlers/errors/__init__.py delete mode 100644 handlers/errors/error_handler.py delete mode 100644 handlers/users/echo.py delete mode 100644 handlers/users/help.py delete mode 100644 handlers/users/start.py diff --git a/.gitignore b/.gitignore index 668c254..7ed07d0 100644 --- a/.gitignore +++ b/.gitignore @@ -127,14 +127,4 @@ dmypy.json # Pyre type checker .pyre/ -.idea/$CACHE_FILE$ -.idea/.gitignore -.idea/aiogram-bot-template.iml -.idea/codeStyles/ -.idea/deployment.xml -.idea/dictionaries -.idea/inspectionProfiles/ -.idea/misc.xml -.idea/modules.xml -.idea/vagrant.xml -.idea/vcs.xml +.idea/ diff --git a/app.py b/app.py index f1293d1..4d2b46a 100644 --- a/app.py +++ b/app.py @@ -1,4 +1,5 @@ from loader import bot, storage +from data.config import SKIP_UPDATES async def on_startup(dp): @@ -8,7 +9,9 @@ async def on_startup(dp): middlewares.setup(dp) from utils.notify_admins import on_startup_notify + from utils.set_bot_commands import set_default_commands await on_startup_notify(dp) + await set_default_commands(dp) async def on_shutdown(dp): @@ -20,4 +23,4 @@ if __name__ == '__main__': from aiogram import executor from handlers import dp - executor.start_polling(dp, on_startup=on_startup, on_shutdown=on_shutdown) + executor.start_polling(dp, on_startup=on_startup, on_shutdown=on_shutdown, skip_updates=SKIP_UPDATES) diff --git a/data/config.py b/data/config.py index 5bce25d..c47b8cd 100644 --- a/data/config.py +++ b/data/config.py @@ -1,20 +1,22 @@ -import os +from environs import Env -from dotenv import load_dotenv +env = Env() +env.read_env() -load_dotenv() +BOT_TOKEN = env("BOT_TOKEN") -BOT_TOKEN = str(os.getenv("BOT_TOKEN")) -admins = [ -] +SKIP_UPDATES = env.bool("SKIP_UPDATES", False) +JOIN_NO_MEDIA_TIME = env.int("JOIN_NO_MEDIA_TIME", 10) +ADMINS_ID = env.list("ADMINS_ID") -ip = os.getenv("ip") +REDIS_HOST = env("REDIS_HOST", "127.0.0.1") +REDIS_PORT = env("REDIS_PORT", 6379) aiogram_redis = { - 'host': ip, + 'host': REDIS_HOST, } redis = { - 'address': (ip, 6379), + 'address': (REDIS_HOST, REDIS_PORT), 'encoding': 'utf8' } diff --git a/filters/__init__.py b/filters/__init__.py index 2ba789c..331fdff 100644 --- a/filters/__init__.py +++ b/filters/__init__.py @@ -1,9 +1,10 @@ from aiogram import Dispatcher - -# from .is_admin import AdminFilter +from .user_filters import IsContributor +from .chat_filters import IsGroup, IsPrivate def setup(dp: Dispatcher): - # dp.filters_factory.bind(AdminFilter) - pass + dp.filters_factory.bind(IsContributor) + dp.filters_factory.bind(IsGroup) + dp.filters_factory.bind(IsPrivate) diff --git a/handlers/__init__.py b/handlers/__init__.py index d8db2bb..95e1691 100644 --- a/handlers/__init__.py +++ b/handlers/__init__.py @@ -1,6 +1,7 @@ -from .errors import dp -from .users import dp -from .groups import dp -from .channels import dp +# from .channels import dp +from .essential import dp +# from .groups import dp +# from .private import dp +# from .users import dp __all__ = ["dp"] diff --git a/handlers/channels/__init__.py b/handlers/channels/__init__.py index e69de29..22747cb 100644 --- a/handlers/channels/__init__.py +++ b/handlers/channels/__init__.py @@ -0,0 +1 @@ +# __all__ = ["dp"] diff --git a/handlers/errors/__init__.py b/handlers/errors/__init__.py deleted file mode 100644 index 4a40b9b..0000000 --- a/handlers/errors/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .error_handler import dp - -__all__ = ["dp"] diff --git a/handlers/errors/error_handler.py b/handlers/errors/error_handler.py deleted file mode 100644 index 57ce53c..0000000 --- a/handlers/errors/error_handler.py +++ /dev/null @@ -1,56 +0,0 @@ -import logging - -from loader import dp - - -@dp.errors_handler() -async def errors_handler(update, exception): - """ - Exceptions handler. Catches all exceptions within task factory tasks. - :param dispatcher: - :param update: - :param exception: - :return: stdout logging - """ - from aiogram.utils.exceptions import (Unauthorized, InvalidQueryID, TelegramAPIError, - CantDemoteChatCreator, MessageNotModified, MessageToDeleteNotFound, - MessageTextIsEmpty, RetryAfter, - CantParseEntities, MessageCantBeDeleted) - - if isinstance(exception, CantDemoteChatCreator): - logging.debug("Can't demote chat creator") - return True - - if isinstance(exception, MessageNotModified): - logging.debug('Message is not modified') - return True - if isinstance(exception, MessageCantBeDeleted): - logging.debug('Message cant be deleted') - return True - - if isinstance(exception, MessageToDeleteNotFound): - logging.debug('Message to delete not found') - return True - - if isinstance(exception, MessageTextIsEmpty): - logging.debug('MessageTextIsEmpty') - return True - - if isinstance(exception, Unauthorized): - logging.info(f'Unauthorized: {exception}') - return True - - if isinstance(exception, InvalidQueryID): - logging.exception(f'InvalidQueryID: {exception} \nUpdate: {update}') - return True - - if isinstance(exception, TelegramAPIError): - logging.exception(f'TelegramAPIError: {exception} \nUpdate: {update}') - return True - if isinstance(exception, RetryAfter): - logging.exception(f'RetryAfter: {exception} \nUpdate: {update}') - return True - if isinstance(exception, CantParseEntities): - logging.exception(f'CantParseEntities: {exception} \nUpdate: {update}') - return True - logging.exception(f'Update: {update} \n{exception}') diff --git a/handlers/groups/__init__.py b/handlers/groups/__init__.py index e69de29..22747cb 100644 --- a/handlers/groups/__init__.py +++ b/handlers/groups/__init__.py @@ -0,0 +1 @@ +# __all__ = ["dp"] diff --git a/handlers/users/__init__.py b/handlers/users/__init__.py index 4f3c9f7..e69de29 100644 --- a/handlers/users/__init__.py +++ b/handlers/users/__init__.py @@ -1,5 +0,0 @@ -from .help import dp -from .start import dp -from .echo import dp - -__all__ = ["dp"] diff --git a/handlers/users/echo.py b/handlers/users/echo.py deleted file mode 100644 index 93cd2fe..0000000 --- a/handlers/users/echo.py +++ /dev/null @@ -1,7 +0,0 @@ -from aiogram import types -from loader import dp - - -@dp.message_handler() -async def bot_echo(message: types.Message): - await message.answer(message.text) diff --git a/handlers/users/help.py b/handlers/users/help.py deleted file mode 100644 index 7226861..0000000 --- a/handlers/users/help.py +++ /dev/null @@ -1,16 +0,0 @@ -from aiogram import types -from aiogram.dispatcher.filters.builtin import CommandHelp - -from loader import dp -from utils.misc import rate_limit - - -@rate_limit(5, 'help') -@dp.message_handler(CommandHelp()) -async def bot_help(message: types.Message): - text = [ - 'Список команд: ', - '/start - Начать диалог', - '/help - Получить справку' - ] - await message.answer('\n'.join(text)) diff --git a/handlers/users/start.py b/handlers/users/start.py deleted file mode 100644 index 54abb72..0000000 --- a/handlers/users/start.py +++ /dev/null @@ -1,9 +0,0 @@ -from aiogram import types -from aiogram.dispatcher.filters.builtin import CommandStart - -from loader import dp - - -@dp.message_handler(CommandStart()) -async def bot_start(message: types.Message): - await message.answer(f'Привет, {message.from_user.full_name}!') diff --git a/requirements.txt b/requirements.txt index 7613d94..70447a5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,44 @@ -aiogram==2.7 + +# Autocreated by +# pip freeze > requirements.txt + +aiogram==2.8 aiohttp==3.6.2 -aioredis==1.3.1 \ No newline at end of file +aioredis==1.3.1 +appdirs==1.4.3 +APScheduler==3.6.3 +async-timeout==3.0.1 +asyncio==3.4.3 +attrs==19.3.0 +Babel==2.8.0 +CacheControl==0.12.6 +certifi==2020.4.5.1 +chardet==3.0.4 +colorama==0.4.3 +contextlib2==0.6.0 +distlib==0.3.0 +distro==1.4.0 +environs==7.4.0 +hiredis==1.0.1 +html5lib==1.0.1 +idna==2.9 +ipaddr==2.2.0 +lockfile==0.12.2 +loguru==0.4.1 +marshmallow==3.6.0 +msgpack==0.6.2 +multidict==4.7.5 +packaging==20.3 +pep517==0.8.2 +progress==1.5 +pyparsing==2.4.6 +pytoml==0.1.21 +pytz==2020.1 +redis==3.5.1 +requests==2.22.0 +retrying==1.3.3 +six==1.14.0 +tzlocal==2.1 +urllib3==1.25.8 +webencodings==0.5.1 +yarl==1.4.2 diff --git a/utils/misc/__init__.py b/utils/misc/__init__.py index 3f7248a..05dba85 100644 --- a/utils/misc/__init__.py +++ b/utils/misc/__init__.py @@ -1,2 +1 @@ from .throttling import rate_limit -from . import logging diff --git a/utils/notify_admins.py b/utils/notify_admins.py index c920196..4173724 100644 --- a/utils/notify_admins.py +++ b/utils/notify_admins.py @@ -1,14 +1,20 @@ -import logging +from loguru import logger from aiogram import Dispatcher +from aiogram.utils.exceptions import ChatNotFound -from data.config import admins +from data.config import ADMINS_ID + + +async def mail_to_admins(dp): + for admin in ADMINS_ID: + try: + await dp.bot.send_message(admin, "Бот Запущен и готов к работе с группами!") + except ChatNotFound: + logger.error("Чат с админом не найден") + except Exception as err: + logger.exception(err) async def on_startup_notify(dp: Dispatcher): - for admin in admins: - try: - await dp.bot.send_message(admin, "Бот Запущен") - - except Exception as err: - logging.exception(err) + await mail_to_admins(dp) From d0f0142111315eb039b16e11592d793d86efce3a Mon Sep 17 00:00:00 2001 From: Kyle Date: Thu, 4 Jun 2020 20:58:29 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83?= =?UTF-8?q?=D1=80=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit догрузил в гит остальные файлы (git add .), а то до этого забыл. Почистил requirements.txt, чтобы это выглядело по-человечески. Остальные библиотеки подтягиваются прописанными библиотеками. Версии указывал строго --- .env.dist | 14 +++++++++ data/permissions.py | 37 ++++++++++++++++++++++ docker-compose.yml | 13 ++++++++ filters/chat_filters.py | 15 +++++++++ filters/user_filters.py | 11 +++++++ handlers/essential/__init__.py | 3 ++ handlers/essential/errors.py | 56 ++++++++++++++++++++++++++++++++++ handlers/private/__init__.py | 1 + requirements.txt | 45 ++------------------------- utils/set_bot_commands.py | 7 +++++ 10 files changed, 159 insertions(+), 43 deletions(-) create mode 100644 .env.dist create mode 100644 data/permissions.py create mode 100644 docker-compose.yml create mode 100644 filters/chat_filters.py create mode 100644 filters/user_filters.py create mode 100644 handlers/essential/__init__.py create mode 100644 handlers/essential/errors.py create mode 100644 handlers/private/__init__.py create mode 100644 utils/set_bot_commands.py diff --git a/.env.dist b/.env.dist new file mode 100644 index 0000000..136ff40 --- /dev/null +++ b/.env.dist @@ -0,0 +1,14 @@ + +# Telegram API Token +BOT_TOKEN= + +# Не надо использовать пробел после "," +ADMINS_ID=123456789,987654321 + +# Указываем пропускать ли боту апдейты при запуске +SKIP_UPDATES=False + +# Параметры для Redis +REDIS_HOST=127.0.0.1 +REDIS_PORT=6379 + diff --git a/data/permissions.py b/data/permissions.py new file mode 100644 index 0000000..7bdc109 --- /dev/null +++ b/data/permissions.py @@ -0,0 +1,37 @@ +from aiogram import types + +# Права пользователя, только вошедшего в чат +new_user_added = types.ChatPermissions( + can_send_messages=False, + can_send_media_messages=False, + can_send_polls=False, + can_send_other_messages=False, + can_add_web_page_previews=False, + can_invite_users=False, + can_change_info=False, + can_pin_messages=False, +) + +# Права пользователя, подтвердившего, что он не бот +user_allowed = types.ChatPermissions( + can_send_messages=True, + can_send_media_messages=True, + can_send_polls=True, + can_send_other_messages=True, + can_add_web_page_previews=True, + can_invite_users=True, + can_change_info=False, + can_pin_messages=False, +) + +# Права пользователя в муте +user_ro = types.ChatPermissions( + can_send_messages=False, + can_send_media_messages=False, + can_send_polls=False, + can_send_other_messages=False, + can_add_web_page_previews=False, + can_invite_users=True, + can_change_info=False, + can_pin_messages=False, +) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9231779 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +version: '3.1' +services: + commonmoder: + container_name: commonmoder + build: + context: . + network_mode: "host" + + command: python app.py + restart: always + + env_file: + - ".env" diff --git a/filters/chat_filters.py b/filters/chat_filters.py new file mode 100644 index 0000000..6f6facf --- /dev/null +++ b/filters/chat_filters.py @@ -0,0 +1,15 @@ +from aiogram import types +from aiogram.dispatcher.filters import BoundFilter + + +class IsGroup(BoundFilter): + + async def check(self, message: types.Message): + return message.chat.type in (types.ChatType.GROUP, + types.ChatType.SUPER_GROUP) + + +class IsPrivate(BoundFilter): + + async def check(self, message: types.Message): + return message.chat.type == types.ChatType.PRIVATE diff --git a/filters/user_filters.py b/filters/user_filters.py new file mode 100644 index 0000000..448aec0 --- /dev/null +++ b/filters/user_filters.py @@ -0,0 +1,11 @@ +from aiogram import types +from aiogram.dispatcher.filters import BoundFilter + +from loader import bot + + +class IsContributor(BoundFilter): + + async def check(self, message: types.Message): + member = await bot.get_chat_member(message.chat.id, message.from_user.id) + return member.custom_title == "Contributor" diff --git a/handlers/essential/__init__.py b/handlers/essential/__init__.py new file mode 100644 index 0000000..a160ef4 --- /dev/null +++ b/handlers/essential/__init__.py @@ -0,0 +1,3 @@ +from .errors import dp + +__all__ = ["dp"] diff --git a/handlers/essential/errors.py b/handlers/essential/errors.py new file mode 100644 index 0000000..0d71962 --- /dev/null +++ b/handlers/essential/errors.py @@ -0,0 +1,56 @@ +from loguru import logger + +from loader import dp + + +@dp.errors_handler() +async def errors_handler(update, exception): + """ + Exceptions handler. Catches all exceptions within task factory tasks. + :param dispatcher: + :param update: + :param exception: + :return: stdout logging + """ + from aiogram.utils.exceptions import (Unauthorized, InvalidQueryID, TelegramAPIError, + CantDemoteChatCreator, MessageNotModified, MessageToDeleteNotFound, + MessageTextIsEmpty, RetryAfter, + CantParseEntities, MessageCantBeDeleted) + + if isinstance(exception, CantDemoteChatCreator): + logger.debug("Can't demote chat creator") + return True + + if isinstance(exception, MessageNotModified): + logger.debug('Message is not modified') + return True + if isinstance(exception, MessageCantBeDeleted): + logger.debug('Message cant be deleted') + return True + + if isinstance(exception, MessageToDeleteNotFound): + logger.debug('Message to delete not found') + return True + + if isinstance(exception, MessageTextIsEmpty): + logger.debug('MessageTextIsEmpty') + return True + + if isinstance(exception, Unauthorized): + logger.info(f'Unauthorized: {exception}') + return True + + if isinstance(exception, InvalidQueryID): + logger.exception(f'InvalidQueryID: {exception} \nUpdate: {update}') + return True + + if isinstance(exception, TelegramAPIError): + logger.exception(f'TelegramAPIError: {exception} \nUpdate: {update}') + return True + if isinstance(exception, RetryAfter): + logger.exception(f'RetryAfter: {exception} \nUpdate: {update}') + return True + if isinstance(exception, CantParseEntities): + logger.exception(f'CantParseEntities: {exception} \nUpdate: {update}') + return True + logger.exception(f'Update: {update} \n{exception}') diff --git a/handlers/private/__init__.py b/handlers/private/__init__.py new file mode 100644 index 0000000..22747cb --- /dev/null +++ b/handlers/private/__init__.py @@ -0,0 +1 @@ +# __all__ = ["dp"] diff --git a/requirements.txt b/requirements.txt index 70447a5..91fc8ea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,44 +1,3 @@ - -# Autocreated by -# pip freeze > requirements.txt - aiogram==2.8 -aiohttp==3.6.2 -aioredis==1.3.1 -appdirs==1.4.3 -APScheduler==3.6.3 -async-timeout==3.0.1 -asyncio==3.4.3 -attrs==19.3.0 -Babel==2.8.0 -CacheControl==0.12.6 -certifi==2020.4.5.1 -chardet==3.0.4 -colorama==0.4.3 -contextlib2==0.6.0 -distlib==0.3.0 -distro==1.4.0 -environs==7.4.0 -hiredis==1.0.1 -html5lib==1.0.1 -idna==2.9 -ipaddr==2.2.0 -lockfile==0.12.2 -loguru==0.4.1 -marshmallow==3.6.0 -msgpack==0.6.2 -multidict==4.7.5 -packaging==20.3 -pep517==0.8.2 -progress==1.5 -pyparsing==2.4.6 -pytoml==0.1.21 -pytz==2020.1 -redis==3.5.1 -requests==2.22.0 -retrying==1.3.3 -six==1.14.0 -tzlocal==2.1 -urllib3==1.25.8 -webencodings==0.5.1 -yarl==1.4.2 +environs==8.0.0 +loguru==0.5.0 diff --git a/utils/set_bot_commands.py b/utils/set_bot_commands.py new file mode 100644 index 0000000..90f3a96 --- /dev/null +++ b/utils/set_bot_commands.py @@ -0,0 +1,7 @@ +from aiogram import types + + +async def set_default_commands(dp): + await dp.bot.set_my_commands([ + types.BotCommand("start", "Начало работы с ботом"), + ])