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", "Начало работы с ботом"), + ])