This commit is contained in:
Kyle 2020-06-05 15:27:33 +03:00 committed by GitHub
commit 78c061ec41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 158 additions and 93 deletions

14
.env.dist Normal file
View File

@ -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

12
.gitignore vendored
View File

@ -127,14 +127,4 @@ dmypy.json
# Pyre type checker # Pyre type checker
.pyre/ .pyre/
.idea/$CACHE_FILE$ .idea/
.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

5
app.py
View File

@ -1,4 +1,5 @@
from loader import bot, storage from loader import bot, storage
from data.config import SKIP_UPDATES
async def on_startup(dp): async def on_startup(dp):
@ -8,7 +9,9 @@ async def on_startup(dp):
middlewares.setup(dp) middlewares.setup(dp)
from utils.notify_admins import on_startup_notify from utils.notify_admins import on_startup_notify
from utils.set_bot_commands import set_default_commands
await on_startup_notify(dp) await on_startup_notify(dp)
await set_default_commands(dp)
async def on_shutdown(dp): async def on_shutdown(dp):
@ -20,4 +23,4 @@ if __name__ == '__main__':
from aiogram import executor from aiogram import executor
from handlers import dp 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)

View File

@ -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")) SKIP_UPDATES = env.bool("SKIP_UPDATES", False)
admins = [ 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 = { aiogram_redis = {
'host': ip, 'host': REDIS_HOST,
} }
redis = { redis = {
'address': (ip, 6379), 'address': (REDIS_HOST, REDIS_PORT),
'encoding': 'utf8' 'encoding': 'utf8'
} }

37
data/permissions.py Normal file
View File

@ -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,
)

13
docker-compose.yml Normal file
View File

@ -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"

View File

@ -1,9 +1,10 @@
from aiogram import Dispatcher from aiogram import Dispatcher
from .user_filters import IsContributor
# from .is_admin import AdminFilter from .chat_filters import IsGroup, IsPrivate
def setup(dp: Dispatcher): def setup(dp: Dispatcher):
# dp.filters_factory.bind(AdminFilter) dp.filters_factory.bind(IsContributor)
pass dp.filters_factory.bind(IsGroup)
dp.filters_factory.bind(IsPrivate)

15
filters/chat_filters.py Normal file
View File

@ -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

11
filters/user_filters.py Normal file
View File

@ -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"

View File

@ -1,6 +1,7 @@
from .errors import dp # from .channels import dp
from .users import dp from .essential import dp
from .groups import dp # from .groups import dp
from .channels import dp # from .private import dp
# from .users import dp
__all__ = ["dp"] __all__ = ["dp"]

View File

@ -0,0 +1 @@
# __all__ = ["dp"]

View File

@ -1,3 +0,0 @@
from .error_handler import dp
__all__ = ["dp"]

View File

@ -0,0 +1,3 @@
from .errors import dp
__all__ = ["dp"]

View File

@ -1,4 +1,4 @@
import logging from loguru import logger
from loader import dp from loader import dp
@ -18,39 +18,39 @@ async def errors_handler(update, exception):
CantParseEntities, MessageCantBeDeleted) CantParseEntities, MessageCantBeDeleted)
if isinstance(exception, CantDemoteChatCreator): if isinstance(exception, CantDemoteChatCreator):
logging.debug("Can't demote chat creator") logger.debug("Can't demote chat creator")
return True return True
if isinstance(exception, MessageNotModified): if isinstance(exception, MessageNotModified):
logging.debug('Message is not modified') logger.debug('Message is not modified')
return True return True
if isinstance(exception, MessageCantBeDeleted): if isinstance(exception, MessageCantBeDeleted):
logging.debug('Message cant be deleted') logger.debug('Message cant be deleted')
return True return True
if isinstance(exception, MessageToDeleteNotFound): if isinstance(exception, MessageToDeleteNotFound):
logging.debug('Message to delete not found') logger.debug('Message to delete not found')
return True return True
if isinstance(exception, MessageTextIsEmpty): if isinstance(exception, MessageTextIsEmpty):
logging.debug('MessageTextIsEmpty') logger.debug('MessageTextIsEmpty')
return True return True
if isinstance(exception, Unauthorized): if isinstance(exception, Unauthorized):
logging.info(f'Unauthorized: {exception}') logger.info(f'Unauthorized: {exception}')
return True return True
if isinstance(exception, InvalidQueryID): if isinstance(exception, InvalidQueryID):
logging.exception(f'InvalidQueryID: {exception} \nUpdate: {update}') logger.exception(f'InvalidQueryID: {exception} \nUpdate: {update}')
return True return True
if isinstance(exception, TelegramAPIError): if isinstance(exception, TelegramAPIError):
logging.exception(f'TelegramAPIError: {exception} \nUpdate: {update}') logger.exception(f'TelegramAPIError: {exception} \nUpdate: {update}')
return True return True
if isinstance(exception, RetryAfter): if isinstance(exception, RetryAfter):
logging.exception(f'RetryAfter: {exception} \nUpdate: {update}') logger.exception(f'RetryAfter: {exception} \nUpdate: {update}')
return True return True
if isinstance(exception, CantParseEntities): if isinstance(exception, CantParseEntities):
logging.exception(f'CantParseEntities: {exception} \nUpdate: {update}') logger.exception(f'CantParseEntities: {exception} \nUpdate: {update}')
return True return True
logging.exception(f'Update: {update} \n{exception}') logger.exception(f'Update: {update} \n{exception}')

View File

@ -0,0 +1 @@
# __all__ = ["dp"]

View File

@ -0,0 +1 @@
# __all__ = ["dp"]

View File

@ -1,5 +0,0 @@
from .help import dp
from .start import dp
from .echo import dp
__all__ = ["dp"]

View File

@ -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)

View File

@ -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))

View File

@ -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}!')

View File

@ -1,3 +1,3 @@
aiogram==2.7 aiogram==2.8
aiohttp==3.6.2 environs==8.0.0
aioredis==1.3.1 loguru==0.5.0

View File

@ -1,2 +1 @@
from .throttling import rate_limit from .throttling import rate_limit
from . import logging

View File

@ -1,14 +1,20 @@
import logging from loguru import logger
from aiogram import Dispatcher 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): async def on_startup_notify(dp: Dispatcher):
for admin in admins: await mail_to_admins(dp)
try:
await dp.bot.send_message(admin, "Бот Запущен")
except Exception as err:
logging.exception(err)

View File

@ -0,0 +1,7 @@
from aiogram import types
async def set_default_commands(dp):
await dp.bot.set_my_commands([
types.BotCommand("start", "Начало работы с ботом"),
])