Merge d0f0142111
into b1a872a060
This commit is contained in:
commit
78c061ec41
14
.env.dist
Normal file
14
.env.dist
Normal 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
12
.gitignore
vendored
|
@ -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
5
app.py
|
@ -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)
|
||||||
|
|
|
@ -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
37
data/permissions.py
Normal 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
13
docker-compose.yml
Normal 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"
|
|
@ -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
15
filters/chat_filters.py
Normal 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
11
filters/user_filters.py
Normal 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"
|
|
@ -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"]
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
# __all__ = ["dp"]
|
|
@ -1,3 +0,0 @@
|
||||||
from .error_handler import dp
|
|
||||||
|
|
||||||
__all__ = ["dp"]
|
|
3
handlers/essential/__init__.py
Normal file
3
handlers/essential/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from .errors import dp
|
||||||
|
|
||||||
|
__all__ = ["dp"]
|
|
@ -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}')
|
|
@ -0,0 +1 @@
|
||||||
|
# __all__ = ["dp"]
|
1
handlers/private/__init__.py
Normal file
1
handlers/private/__init__.py
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# __all__ = ["dp"]
|
|
@ -1,5 +0,0 @@
|
||||||
from .help import dp
|
|
||||||
from .start import dp
|
|
||||||
from .echo import dp
|
|
||||||
|
|
||||||
__all__ = ["dp"]
|
|
|
@ -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)
|
|
|
@ -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))
|
|
|
@ -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}!')
|
|
|
@ -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
|
||||||
|
|
|
@ -1,2 +1 @@
|
||||||
from .throttling import rate_limit
|
from .throttling import rate_limit
|
||||||
from . import logging
|
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
7
utils/set_bot_commands.py
Normal file
7
utils/set_bot_commands.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
from aiogram import types
|
||||||
|
|
||||||
|
|
||||||
|
async def set_default_commands(dp):
|
||||||
|
await dp.bot.set_my_commands([
|
||||||
|
types.BotCommand("start", "Начало работы с ботом"),
|
||||||
|
])
|
Loading…
Reference in New Issue
Block a user