|
|
|
@ -16,17 +16,18 @@ from aiogram import Bot, types
|
|
|
|
|
|
|
|
|
|
from functools import wraps |
|
|
|
|
|
|
|
|
|
# не очень красивый способ создание общего объекта ORM для всех |
|
|
|
|
# функций модуля |
|
|
|
|
engine = create_engine("sqlite:///" + str(settings.DB_PATH)) |
|
|
|
|
Session = sessionmaker(bind=engine) |
|
|
|
|
session = Session() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def auth(func): |
|
|
|
|
"""Аутентификация. |
|
|
|
|
"""Декоратор для аутентификации. |
|
|
|
|
|
|
|
|
|
Проверяем, что у юзера есть полномочия на выполнение действия - он |
|
|
|
|
должен быть в белом списке. |
|
|
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
async def wrapper(message): |
|
|
|
@ -47,7 +48,10 @@ def auth(func):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def only_admins(func): |
|
|
|
|
"""Действия только для админов.""" |
|
|
|
|
"""Декоратора аутентификации для администраторов. |
|
|
|
|
|
|
|
|
|
Данные действия с ботом могут выполнять только администраторы. |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
async def wrapper(message): |
|
|
|
|
uid = message["from"]["id"] |
|
|
|
@ -61,7 +65,21 @@ def only_admins(func):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def _clean_up(message_id: int, delay_min: int, bot: Bot) -> None: |
|
|
|
|
"""Удаление сообщенния message_id через delay_min минут.""" |
|
|
|
|
"""Поставить таймер на удаление сообщения. |
|
|
|
|
|
|
|
|
|
Внутренняя функция для удаления сообщения. Пишет в базу id |
|
|
|
|
сообщения и время, когда его нужно удалить. Ждет `delay_min` и |
|
|
|
|
пробует удалить сообщение. |
|
|
|
|
|
|
|
|
|
Parameters |
|
|
|
|
---------- |
|
|
|
|
message_id : int |
|
|
|
|
Идентификатор сообщения, присвоенный ему Телеграмом. |
|
|
|
|
delay_min : int |
|
|
|
|
Количество минут, через которое это сообщение нужно удалить. |
|
|
|
|
bot : Bot |
|
|
|
|
Объект бота, через который сообщение будет отправленно в канал. |
|
|
|
|
""" |
|
|
|
|
exp = datetime.now() + timedelta(minutes=delay_min) |
|
|
|
|
msg: Messages_to_delete = Messages_to_delete( |
|
|
|
|
message_id=message_id, deletion_date=exp |
|
|
|
@ -80,10 +98,16 @@ async def _clean_up(message_id: int, delay_min: int, bot: Bot) -> None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_new_token() -> str: |
|
|
|
|
"""Возвращает токен для приглашения пользователя. |
|
|
|
|
"""Получить токен. |
|
|
|
|
|
|
|
|
|
Длина токена 16 символов, срок действия 5 минут. Токен записывается в базу. |
|
|
|
|
Возвращает токен для приглашения нового пользователя. |
|
|
|
|
|
|
|
|
|
Returns |
|
|
|
|
------- |
|
|
|
|
token : str |
|
|
|
|
Токен для доступа к группе. Длина - 16 символов. Длина токена |
|
|
|
|
16 символов, срок действия 5 минут. Токен и его срок годности |
|
|
|
|
записываются в базу. |
|
|
|
|
""" |
|
|
|
|
token = token_urlsafe(16) |
|
|
|
|
exp = datetime.now() + timedelta(minutes=5) |
|
|
|
@ -95,7 +119,22 @@ def get_new_token() -> str:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_token(token: str) -> bool: |
|
|
|
|
"""Проверяет, находится ли токен в базе, возвращает True, если токен есть и не истек. затем удаляет токен из базы.""" |
|
|
|
|
"""Проверить валидность токена. |
|
|
|
|
|
|
|
|
|
Токен считается валидным если он соотвествует сразу двум условиям: |
|
|
|
|
он есть в базе, срок его действия не истек. После проверки токен |
|
|
|
|
будет удален из базы. |
|
|
|
|
|
|
|
|
|
Parameters |
|
|
|
|
---------- |
|
|
|
|
token : str |
|
|
|
|
Токен. Длина не проверяется. |
|
|
|
|
|
|
|
|
|
Returns |
|
|
|
|
------- |
|
|
|
|
result : bool |
|
|
|
|
Результат проверки токена. |
|
|
|
|
""" |
|
|
|
|
finded_token = session.query(Token).filter(Token.token == token).one_or_none() |
|
|
|
|
|
|
|
|
|
if finded_token and not finded_token.expired(): |
|
|
|
@ -107,7 +146,16 @@ def check_token(token: str) -> bool:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def add_new_user_to_allowed_list(user_id: int) -> None: |
|
|
|
|
"""Добавляет пользователя в белый список. Если пользователь в нем уже есть, то игнорирует ошибку и ведет себя так, словно его добавили впервые.""" |
|
|
|
|
"""Добавить пользователя в белый список. |
|
|
|
|
|
|
|
|
|
Если пользователь в нем уже есть, то игнорирует ошибку и ведет |
|
|
|
|
себя так, словно его добавили впервые. |
|
|
|
|
|
|
|
|
|
Parameters |
|
|
|
|
---------- |
|
|
|
|
user_id : int |
|
|
|
|
Идентификатор пользователя. |
|
|
|
|
""" |
|
|
|
|
new_user: Allowed_user = Allowed_user(user_id=user_id, date_add=datetime.now()) |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
@ -119,7 +167,13 @@ def add_new_user_to_allowed_list(user_id: int) -> None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def delete_user_from_allowed_list(user_id: str) -> None: |
|
|
|
|
"""Удаляет пользователя из белого списка.""" |
|
|
|
|
"""Удалить пользователя из белого списка. |
|
|
|
|
|
|
|
|
|
Parameters |
|
|
|
|
---------- |
|
|
|
|
user_id : int |
|
|
|
|
Идентификатор пользователя. |
|
|
|
|
""" |
|
|
|
|
user: Allowed_user = ( |
|
|
|
|
session.query(Allowed_user) |
|
|
|
|
.filter(Allowed_user.user_id == user_id) |
|
|
|
@ -131,14 +185,33 @@ def delete_user_from_allowed_list(user_id: str) -> None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_static(name: str) -> str: |
|
|
|
|
"""Возвращает содержимое из файла переданного в name.""" |
|
|
|
|
"""Считать содержимое файла. |
|
|
|
|
|
|
|
|
|
Возвращает содержимое файла. Поддерживает Markdown. |
|
|
|
|
|
|
|
|
|
Parameters |
|
|
|
|
---------- |
|
|
|
|
name : str |
|
|
|
|
Имя файла вместе с папкой. Рекомендуется размещать файлы с |
|
|
|
|
текстом в папке `/static`. |
|
|
|
|
|
|
|
|
|
Returns |
|
|
|
|
------- |
|
|
|
|
msg : str |
|
|
|
|
Содержимое файла, переданное в `name`. |
|
|
|
|
""" |
|
|
|
|
with open(name, "r") as f: |
|
|
|
|
msg = f.read() |
|
|
|
|
return msg |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def delete_old_messages(bot: Bot) -> None: |
|
|
|
|
"""Удаляет сообещния, если их delete_date меньше чем время сейчас.""" |
|
|
|
|
"""Удалить старые сообщения. |
|
|
|
|
|
|
|
|
|
Удаляет сообщения, если их delete_date меньше чем время сейчас. |
|
|
|
|
Если сообщения в чате не найдено - выводит сообщение в лог и |
|
|
|
|
удалет сообщение из базы. |
|
|
|
|
""" |
|
|
|
|
msg_list: Messages_to_delete = ( |
|
|
|
|
session.query(Messages_to_delete).order_by(Messages_to_delete.id).all() |
|
|
|
|
) |
|
|
|
@ -160,7 +233,25 @@ async def delete_old_messages(bot: Bot) -> None:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_text_from_command(message: types.Message) -> str: |
|
|
|
|
"""Вернет текст из команды для бота (но не саму команду). Парсит message["entities"].""" |
|
|
|
|
"""Получить текст сообщения, отправленного боту. |
|
|
|
|
|
|
|
|
|
Вернет текст из команды для бота (но не саму команду). |
|
|
|
|
|
|
|
|
|
Parameters |
|
|
|
|
---------- |
|
|
|
|
message : types.Message |
|
|
|
|
Сообщения, из которого нужно извлечь текст. |
|
|
|
|
|
|
|
|
|
Returns |
|
|
|
|
------- |
|
|
|
|
text : str |
|
|
|
|
Текст (тело) сообщения без команды. |
|
|
|
|
|
|
|
|
|
Notes |
|
|
|
|
----- |
|
|
|
|
Парсит message["entities"], поэтому в качестве аргумента не нужна |
|
|
|
|
команда, а только объект сообщения. |
|
|
|
|
""" |
|
|
|
|
command_length = int(message["entities"][0]["length"]) |
|
|
|
|
return message.text[command_length:].strip() |
|
|
|
|
|
|
|
|
@ -168,7 +259,22 @@ def get_text_from_command(message: types.Message) -> str:
|
|
|
|
|
async def send_message_to_chat( |
|
|
|
|
msg_date: datetime, delete_after: int, text: str, bot: Bot |
|
|
|
|
) -> None: |
|
|
|
|
"""Отправляет сообщение в чат, ставит таймер на удаление через delete_after минут.""" |
|
|
|
|
"""Отправить сообщение в чат. |
|
|
|
|
|
|
|
|
|
Отправляет сообщение в чат, ставит таймер на удаление. |
|
|
|
|
|
|
|
|
|
Parameters |
|
|
|
|
---------- |
|
|
|
|
msg_date : datetime |
|
|
|
|
Время отправки сообщения. На его основе высчитывается время |
|
|
|
|
удаления. |
|
|
|
|
delete_after : int |
|
|
|
|
Количество минут, после которого нужно удалить сообщение. |
|
|
|
|
text : str |
|
|
|
|
Сообщение для отправки в канал. |
|
|
|
|
bot : Bot |
|
|
|
|
Объект бота, через которого будет отправлено сообщение. |
|
|
|
|
""" |
|
|
|
|
deletion_time = msg_date + timedelta(minutes=delete_after) |
|
|
|
|
text += f"\n\nБудет удалено в *{deletion_time}*" |
|
|
|
|
|
|
|
|
|