24 Commits

Author SHA1 Message Date
Andrey
0c29609e4a hot fix 2024-11-17 22:43:41 +03:00
Andrey
cb0f94c718 some fix 2024-11-17 22:10:45 +03:00
b2c27040aa some fix with emoji function 2024-11-17 22:09:37 +03:00
Andrey
47c5b2f083 hotfix 2024-11-17 01:20:51 +03:00
Andrey
e0e0a6de51 add new func in voice bot 2024-11-17 00:50:55 +03:00
502c07a2c9 some fix 2024-11-16 18:45:05 +03:00
Andrey
ee9eafa09f some fix 2024-11-14 00:24:37 +03:00
ANDREY KATYKHIN
b8b92434ff Merge pull request #5 from KerradKerridi/dev-3
refactor voice_bot
2024-11-14 00:06:13 +03:00
Andrey
767acacc18 refactor voice_bot 2024-11-14 00:05:37 +03:00
ANDREY KATYKHIN
bc454fce8c Merge pull request #4 from KerradKerridi/dev-3
fix with html tags
2024-10-31 22:00:09 +03:00
5c3fece394 fix with html tags 2024-10-31 21:58:46 +03:00
ANDREY KATYKHIN
198b522976 Merge pull request #3 from KerradKerridi/dev-3
Dev-3 Добавил новые функции MediaGroup, разные типы файлов, ответы пользователю
2024-07-21 23:24:44 +05:00
Andrey
5050767b60 add new func for ban 2024-07-21 21:22:45 +03:00
Andrey
33fa84943d add answer for user 2024-07-21 13:24:18 +03:00
KatykhinAA
0704e6b3fe all type message can process 2024-07-20 22:41:48 +03:00
KatykhinAA
0b7f718f8a refactor MediaGroup. Add database 2024-07-20 16:54:43 +03:00
KatykhinAA
54234e59ec some fix 2024-07-20 14:18:58 +03:00
KatykhinAA
095e0398d0 some fix 2024-07-18 23:30:41 +03:00
KatykhinAA
a3b53d26e2 add mediaGroup func 2024-07-17 00:15:15 +03:00
KatykhinAA
88889fe87c mediaGroup start work 2024-07-16 22:25:32 +03:00
Andrey
3a30edc1ab HOT_FIX_3 add blacklist
fix db init
2024-07-16 21:55:22 +03:00
Andrey
09a071c014 HOT_FIX_2 for handle_start_message 2024-07-15 23:46:05 +03:00
Andrey
01f6cbd37d HOT FIX for handle_start_message 2024-07-15 23:10:32 +03:00
ANDREY KATYKHIN
3cb487b617 Merge pull request #2 from KerradKerridi/dev-1
Dev-1
2024-07-16 00:36:40 +05:00
57 changed files with 2135 additions and 1029 deletions

3
.gitignore vendored
View File

@@ -1 +1,4 @@
/database/tg-bot-database
/settings.ini
/myenv/
/venv/

View File

@@ -1,22 +1,17 @@
import sqlite3
import os
import sqlite3
from datetime import datetime
from logs.custom_logger import Logger
# Инициализируем логгер
db_logger = Logger(name='db')
# Получение абсолютного пути к текущей директории
current_dir = os.getcwd()
from logs.custom_logger import logger
class BotDB:
def __init__(self, name):
def __init__(self, current_dir, name):
self.db_file = os.path.join(current_dir, name)
self.conn = None
self.cursor = None
self.logger = db_logger.get_logger()
self.logger.info(f'Подключен к базе данных: {self.db_file}')
self.logger = logger
self.logger.info(f'Инициация базы данных: {self.db_file}')
def connect(self):
"""Создание соединения и курсора."""
@@ -62,7 +57,7 @@ class BotDB:
self.logger.info(f'Получена текущая версия миграции: {version}')
return version
except Exception as e:
self.logger.error(f'Ошибка при получении текущей версии миграции: {e}')
self.logger.error(f'Ошибка при получении текущей версии миграции: {str(e)}')
raise
finally:
self.close()
@@ -105,27 +100,8 @@ class BotDB:
finally:
self.close()
# TODO: Deprecated. Остался только в voice боте, удалить и оттуда
def get_error_message_from_db(self, id: int):
"""
@deprecated
Функция для запроса к базе данных и получения сообщений ошибки. В аргументы передаются:
id - идентификатор ошибки
"""
# Подключаемся к базе
try:
self.connect()
self.cursor.execute(f"SELECT * FROM error_messages WHERE id=?", (id,))
response_from_database = str(self.cursor.fetchone()[1])
return response_from_database
except sqlite3.Error as error:
self.logger.error(f"Ошибка при получении сообщения об ошибка voice_bot: {error}")
finally:
self.close()
def add_new_user_in_db(self, user_id: int, first_name: str, full_name: str, username: str, is_bot: bool,
language_code: str, date_added: str,
date_changed: str):
language_code: str, emoji: str, date_added: str, date_changed: str):
"""
Добавляет нового пользователя в базу данных.
@@ -136,6 +112,7 @@ class BotDB:
username (str): Username пользователя в Telegram.
is_bot (bool): Флаг, указывающий, является ли пользователь ботом.
language_code (str): Код языка пользователя.
emoji (str): Эмодзи закрепленная за пользователем
date_added (str): Дата добавления пользователя в базу.
date_changed (str): Дата последнего изменения данных пользователя.
@@ -147,11 +124,12 @@ class BotDB:
try:
self.connect()
self.cursor.execute("INSERT INTO 'our_users' ('user_id', 'first_name', 'full_name', 'username', 'is_bot', "
"'language_code', 'date_added', 'date_changed') VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
"'language_code', 'emoji', 'date_added', 'date_changed') VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
(user_id, first_name, full_name,
username, is_bot, language_code, date_added, date_changed))
username, is_bot, language_code, emoji, date_added, date_changed))
self.conn.commit()
self.logger.info(f"Новый пользователь добавлен в базу: user_id={user_id}, first_name={first_name}")
self.logger.info(
f"Новый пользователь добавлен в базу: user_id={user_id}, first_name={first_name}, emoji={emoji}")
return None
except sqlite3.Error as error:
self.logger.error(f"Ошибка при добавлении пользователя в базу: {error}. "
@@ -244,6 +222,68 @@ class BotDB:
finally:
self.close()
def get_user_id_by_username(self, username: str):
"""
Возвращает user_id пользователя из базы данных по его user_name в Telegram.
Args:
username (str): Username пользователя.
Returns:
user_id (int): Идентификатор пользователя в Telegram.
None: Если пользователь не найден.
Raises:
sqlite3.Error: Если произошла ошибка при выполнении запроса.
"""
try:
self.connect()
self.cursor.execute("SELECT user_id FROM our_users WHERE username = ?", (username,))
result = self.cursor.fetchone()
if result:
user_id = result[0]
self.logger.info(f"User_id пользователя найден: username={username}, user_id={user_id}")
return user_id
else:
self.logger.info(f"Пользователь с username={username} не найден в базе данных.")
return None
except sqlite3.Error as error:
self.logger.error(f"Ошибка при получении username из базы данных: {error}")
raise
finally:
self.close()
def get_full_name_by_id(self, user_id: str):
"""
Возвращает full_name пользователя из базы данных по его username в Telegram.
Args:
user_id (int): Идентификатор пользователя в Telegram.
Returns:
full_name (str): Username пользователя.
None: Если пользователь не найден.
Raises:
sqlite3.Error: Если произошла ошибка при выполнении запроса.
"""
try:
self.connect()
self.cursor.execute("SELECT full_name FROM our_users WHERE user_id = ?", (user_id,))
result = self.cursor.fetchone()
if result:
full_name = result[0]
self.logger.info(f"Username пользователя найден: user_id={user_id}, full_name={full_name}")
return full_name
else:
self.logger.info(f"Пользователь с user_id={user_id} не найден в базе данных.")
return None
except sqlite3.Error as error:
self.logger.error(f"Ошибка при получении username из базы данных: {error}")
raise
finally:
self.close()
def get_all_user_id(self):
"""
Возвращает список всех user_id из базы данных.
@@ -301,11 +341,6 @@ class BotDB:
finally:
self.close()
def change_name(self, user_id):
#TODO: реализовать функцию изменения имени пользователя по которому к нему обращается бот. Обновляем поля first_name, date_changed
#result = self.cursor.execute("UPDATE 'our_users' SET (?) WHERE user_id = (?)", (new_user_name), )
pass
def get_info_about_stickers(self, user_id: int):
"""
Проверяет, получил ли пользователь стикеры.
@@ -608,9 +643,11 @@ class BotDB:
f"Запуск функции update_username_and_full_name: user_id={user_id}, username={username}, full_name={full_name}")
try:
self.connect()
self.cursor.execute("UPDATE our_users SET username = ?, full_name = ? WHERE user_id = ?", (username, full_name, user_id,))
self.cursor.execute("UPDATE our_users SET username = ?, full_name = ? WHERE user_id = ?",
(username, full_name, user_id,))
self.conn.commit()
self.logger.info(f"Функция update_username_and_full_name. Данные пользователя: user_id={user_id} успешно обновлены")
self.logger.info(
f"Функция update_username_and_full_name. Данные пользователя: user_id={user_id} успешно обновлены")
return True
except sqlite3.Error as error:
self.logger.error(f"Ошибка в функции update_username_and_full_name: {error}")
@@ -621,15 +658,15 @@ class BotDB:
def update_date_for_user(self, date: str, user_id: int):
"""
#TODO: Не возвращается ошибка sqlite3. Error. Тест не перехватывает. Возвращается no such table: our_users
Обновляет дату последнего изменения данных пользователя в базе.
Обновляет дату последнего изменения данных пользователя в базе
Args:
date (str): Новая дата изменения.
user_id (int): Идентификатор пользователя в Telegram.
date (str): Новая дата изменения
user_id (int): Идентификатор пользователя в Telegram
Returns:
None: Если обновление прошло успешно.
sqlite3. Error: Если произошла ошибка при выполнении запроса.
None: Если обновление прошло успешно
sqlite3. Error: Если произошла ошибка при выполнении запроса
"""
self.logger.info(f"Запуск функции update_date_for_user: user_id={user_id}, date={date}")
try:
@@ -645,6 +682,107 @@ class BotDB:
finally:
self.close()
def check_emoji(self, emoji: str):
"""
Проверяет, есть ли уже такой emoji в таблице.
Args:
emoji: emoji для проверки.
Returns:
True, если эмодзи уже есть, иначе False.
Raises:
None: В случае ошибки возвращается None
"""
self.logger.info(f"Запуск функции check_emoji: emoji={emoji}")
try:
self.connect()
self.cursor.execute("SELECT 1 FROM our_users WHERE emoji = ?", (emoji,))
result = self.cursor.fetchone()
return bool(result)
except sqlite3.Error as error:
self.logger.error(f"Ошибка проверки эмодзи в базе: {error}")
return None
finally:
self.close()
def update_emoji_for_user(self, user_id: int, emoji: str):
"""
Обновляет эмодзи для пользователя в базе если его ранее не было установлено
Args:
user_id (int): Идентификатор пользователя в Telegram
emoji (str): Эмодзи пользователя
Returns:
None: Если обновление прошло успешно
sqlite3. Error: Если произошла ошибка при выполнении запроса
"""
self.logger.info(f"Запуск функции update_emoji_for_user: user_id={user_id}, emoji={emoji}")
try:
self.connect()
self.cursor.execute("UPDATE our_users SET emoji = ? WHERE user_id = ?",
(emoji, user_id,))
self.conn.commit()
self.logger.info(f"Эмоджи обновлен для пользователя: user_id={user_id}")
except sqlite3.Error as error:
self.logger.error(f"Ошибка обновления эмодзи для пользователя: {error}")
return error
finally:
self.close()
def check_emoji_for_user(self, user_id: int):
"""
Проверяет, есть ли уже у пользователя назначенный emoji.
Args:
user_id: user_id пользователя.
Returns:
True, если эмодзи такого нет, иначе False.
Raises:
error: В случае ошибки возвращается error
"""
self.logger.info(f"Запуск функции check_emoji_for_user: user_id={user_id}")
try:
self.connect()
self.cursor.execute("SELECT emoji FROM our_users WHERE user_id = ?", (user_id,))
pre_result = self.cursor.fetchone()
# Возвращаем "Смайл не определен", если pre_result или pre_result[0] is None
result = pre_result[0] if pre_result else None
return str(result) if result is not None else "Смайл еще не определен"
except sqlite3.Error as error:
self.logger.error(f"Ошибка проверки эмодзи в базе: {error}")
return error
finally:
self.close()
def refresh_listen_audio(self, user_id: int):
"""
Очищает всю информацию о прослушанных аудио пользователем
Args:
user_id: user_id пользователя.
Returns:
None - если все очищено успешно
Raises:
error: В случае ошибки возвращается error
"""
self.logger.info(f"Запуск функции check_emoji_for_user: user_id={user_id}")
try:
self.connect()
self.cursor.execute("DELETE FROM listen_audio_users WHERE user_id = ?", (user_id,))
return None
except sqlite3.Error as error:
self.logger.error(f"Ошибка проверки эмодзи в базе: {error}")
return error
finally:
self.close()
def is_admin(self, user_id: int):
"""
Проверяет, является ли пользователь администратором.
@@ -665,7 +803,7 @@ class BotDB:
result = self.cursor.fetchone()
return bool(result)
except sqlite3.Error as error:
self.logger.error(f"Ошибка добавления сообщения в базу данных: {error}")
self.logger.error(f"Ошибка проверки прав пользователя админа: {error}")
return None
finally:
self.close()
@@ -826,77 +964,320 @@ class BotDB:
finally:
self.close()
def add_audio_record(self, file_name, author_id, date_added, listen_count, file_id):
"""Добавляет информацию о войсе юзера в БД"""
def get_post_content_from_telegram_by_last_id(self, last_post_id: int):
self.logger.info(
f"Запуск функции add_audio_record (file_name = {file_name}, author_id = {author_id}, date_added = {date_added}")
f"Запуск функции get_post_content_from_telegram_by_last_id, идентификатор поста {last_post_id}")
try:
self.connect()
result = self.cursor.execute("""
SELECT cpft.content_name, cpft.content_type
FROM post_from_telegram_suggest pft
JOIN message_link_to_content mltc
ON pft.message_id = mltc.post_id
JOIN content_post_from_telegram cpft
ON cpft.message_id = mltc.message_id
WHERE pft.helper_text_message_id = ?
""", (last_post_id,))
post_content = result.fetchall()
self.logger.info(
f"Функция get_post_content_from_telegram_by_last_id получила список контента: {post_content}")
return post_content
finally:
self.close()
def get_post_ids_from_telegram_by_last_id(self, last_post_id: int):
self.logger.info(
f"Запуск функции get_post_ids_from_telegram_by_last_id, идентификатор поста {last_post_id}")
try:
self.connect()
result = self.cursor.execute("""
SELECT mltc.message_id
FROM post_from_telegram_suggest pft
JOIN message_link_to_content mltc
ON pft.message_id = mltc.post_id
WHERE pft.helper_text_message_id = ?
""", (last_post_id,))
post_ids = result.fetchall()
self.logger.info(f"Функция get_post_ids_from_telegram_by_last_id "
f"получила идентификаторы сообщений: {post_ids}")
return post_ids
except Exception as e:
self.logger.error(f"Ошибка в функции get_post_ids_from_telegram_by_last_id {str(e)}")
return False
finally:
self.close()
def get_post_text_from_telegram_by_last_id(self, last_post_id: int):
self.logger.info(f"Запуск функции get_post_text_from_telegram_by_last_id, идентификатор поста {last_post_id}")
try:
self.connect()
result = self.cursor.execute("SELECT text "
"FROM post_from_telegram_suggest WHERE helper_text_message_id = ?",
(last_post_id,))
text = result.fetchone()[0]
self.logger.info(f"Функция get_post_text_from_telegram_by_last_id получила text")
return text
except Exception as e:
self.logger.error(f"Ошибка в функции get_post_text_from_telegram_by_last_id {str(e)}")
def get_author_id_by_message_id(self, message_id: int):
self.logger.info(f"Запуск функции get_author_id_by_message_id, идентификатор поста {message_id}")
try:
self.connect()
result = self.cursor.execute("SELECT author_id "
"FROM post_from_telegram_suggest WHERE message_id = ?",
(message_id,))
author_id = result.fetchone()[0]
self.logger.info(f"Функция get_author_id_by_message_id получила author_id {author_id}")
return author_id
except Exception as e:
self.logger.error(f"Ошибка в функции get_author_id_by_message_id {str(e)}")
def get_author_id_by_helper_message_id(self, helper_text_message_id: int):
self.logger.info(f"Запуск функции get_author_id_by_helper_message_id, идентификатор поста "
f"{helper_text_message_id}")
try:
self.connect()
result = self.cursor.execute("SELECT author_id "
"FROM post_from_telegram_suggest WHERE helper_text_message_id = ?",
(helper_text_message_id,))
author_id = result.fetchone()[0]
self.logger.info(f"Функция get_author_id_by_helper_message_id получила author_id {author_id}")
return author_id
except Exception as e:
self.logger.error(f"Ошибка в функции get_author_id_by_helper_message_id {str(e)}")
def get_user_id_by_message_id_for_voice_bot(self, message_id: int):
self.logger.info(f"Запуск функции get_user_id_by_message_id_for_voice_bot, идентификатор поста "
f"{message_id}")
try:
self.connect()
result = self.cursor.execute("SELECT user_id "
"FROM audio_moderate WHERE message_id = ?",
(message_id,))
user_id = result.fetchone()[0]
self.logger.info(f"Функция get_user_id_by_message_id_for_voice_bot получила author_id {user_id}")
return user_id
except Exception as e:
self.logger.error(f"Ошибка в функции get_user_id_by_message_id_for_voice_bot {str(e)}")
def set_user_id_and_message_id_for_voice_bot(self, message_id: int, user_id: int):
self.logger.info(f"Запуск функции set_user_id_and_message_id_for_voice_bot, идентификатор поста "
f"{message_id}, user_id {user_id}")
try:
self.connect()
result = self.cursor.execute(
"INSERT INTO `audio_message_reference` (file_name, author_id, date_added, listen_count, file_id) VALUES (?, ?, ?, ?, ?)",
"INSERT INTO audio_moderate (message_id, user_id)"
"VALUES (?, ?)", (message_id, user_id))
self.conn.commit()
self.logger.info(f"Функция set_user_id_and_message_id_for_voice_bot отработала успешно")
return True
except Exception as e:
self.logger.error(f"Ошибка в функции set_user_id_and_message_id_for_voice_bot {str(e)}")
def get_user_id_by_file_name(self, file_name: str):
self.logger.info(f"Запуск функции get_user_id_by_file_name, идентификатор файла "
f"{file_name}")
try:
self.connect()
result = self.cursor.execute("SELECT author_id "
"FROM audio_message_reference WHERE file_name = ?",
(file_name,))
user_id = result.fetchone()[0]
self.logger.info(f"Функция get_user_id_by_file_name получила user_id {user_id}")
return user_id
except Exception as e:
self.logger.error(f"Ошибка в функции get_user_id_by_file_name {str(e)}")
def get_date_by_file_name(self, file_name: str):
self.logger.info(f"Запуск функции get_date_by_file_name, идентификатор файла "
f"{file_name}")
try:
self.connect()
result = self.cursor.execute("SELECT date_added "
"FROM audio_message_reference WHERE file_name = ?",
(file_name,))
date_added = result.fetchone()[0]
self.logger.info(f"Функция get_date_by_file_name получила date_added {date_added}")
return date_added
except Exception as e:
self.logger.error(f"Ошибка в функции get_date_by_file_name {str(e)}")
def add_post_content_in_db(self, post_id: int, message_id: int, content_name: str, type_content: str):
self.logger.info(
f"Запуск функции add_post_content_in_db: post_id={post_id}, message_id={message_id}, "
f"content_name={content_name}, content_type={type_content}")
try:
self.connect()
self.cursor.execute(
"INSERT INTO message_link_to_content (post_id, message_id)"
"VALUES (?, ?)", (post_id, message_id))
self.conn.commit()
self.cursor.execute(
"INSERT INTO content_post_from_telegram (message_id, content_name, content_type)"
"VALUES (?, ?, ?)", (message_id, content_name, type_content))
self.conn.commit()
self.logger.info(f"Функция add_post_content_in_db отработала успешно")
return True
except Exception as e:
self.logger.error(f"Ошибка в функции add_post_content_in_db при добавлении поста в базу данных: {e}")
return False
def add_post_in_db(self, message_id: int, text: str, author_id: int):
self.logger.info(
f"Запуск функции add_post_in_db: message_id={message_id}, "
f"author_id={author_id}")
try:
today = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
self.connect()
self.cursor.execute(
"INSERT INTO post_from_telegram_suggest (message_id, text, author_id, created_at)"
"VALUES (?, ?, ?, ?)", (message_id, text, author_id, today))
self.conn.commit()
self.logger.info(f"Функция add_post_in_db отработала успешно")
return True
except Exception as e:
self.logger.error(f"Ошибка в функции add_post_in_db при добавлении поста в базу данных: {e}")
return False
def update_helper_message_in_db(self, message_id: int, helper_message_id: int):
self.logger.info(
f"Запуск функции update_helper_message_in_db: message_id={message_id}, "
f"helper_message_id={helper_message_id}")
try:
self.connect()
self.cursor.execute(
"UPDATE post_from_telegram_suggest SET helper_text_message_id = ? WHERE message_id = ?",
(helper_message_id, message_id,))
self.conn.commit()
self.logger.info(f"Функция update_helper_message_in_db отработала успешно")
return True
except Exception as e:
self.logger.error(f"Ошибка в функции update_helper_message_in_db при добавлении поста в базу данных: {e}")
return False
def add_audio_record(self, file_name, author_id, date_added, listen_count, file_id):
"""Добавляет информацию о войсе юзера в БД"""
self.logger.info(
f"Запуск функции add_audio_record (file_name = {file_name}, author_id = {author_id},"
f" date_added = {date_added}")
try:
self.connect()
result = self.cursor.execute(
"INSERT INTO `audio_message_reference` (file_name, author_id, date_added, listen_count, file_id) "
"VALUES (?, ?, ?, ?, ?)",
(file_name, author_id, date_added, listen_count, file_id))
self.conn.commit()
self.logger.info(
f"Аудио успешно добавлено в БД (file_name = {file_name}, author_id = {author_id}, date_added = {date_added}")
f"Аудио успешно добавлено в БД (file_name = {file_name}, author_id = {author_id}, "
f"date_added = {date_added}")
return None
except sqlite3.Error as error:
print(error)
self.logger.error(f"Ошибка при добавлении войса в базу: {error}")
raise
finally:
self.close()
def last_date_audio(self):
"""Получаем дату последнего войса"""
self.logger.info(
f"Запуск функции last_date_audio")
try:
self.connect()
result = self.cursor.execute(
"SELECT `date_added` FROM `audio_message_reference` ORDER BY date_added DESC LIMIT 1")
return result.fetchone()[0]
last_date = result.fetchone()[0]
self.logger.info(f"Последняя дата сообщения {last_date}")
return last_date
except sqlite3.Error as error:
print(error)
self.logger.error(f"Ошибка получения последней даты войса: {error}")
raise
finally:
self.close()
def get_last_user_audio_record(self, user_id):
"""Получает данные о количестве записей пользователя"""
self.logger.info(
f"Запуск функции get_last_user_audio_record. user_id={user_id}")
try:
self.connect()
result = self.cursor.execute("SELECT `file_id` FROM `audio_message_reference` WHERE `author_id` = ?",
r = self.cursor.execute("SELECT `file_id` FROM `audio_message_reference` WHERE `author_id` = ?",
(user_id,))
return bool(len(result.fetchall()))
result = bool(len(r.fetchall()))
self.logger.info(
f"Результат функции get_last_user_audio_record: {result}")
return result
except sqlite3.Error as error:
print(error)
self.logger.error(f"Ошибка получения последней даты войса: {error}")
raise
finally:
self.close()
def delete_listen_count_for_user(self, user_id):
"""Удаляет данные о прослушанных пользователем аудио"""
self.logger.info(
f"Запуск функции delete_listen_count_for_user. user_id={user_id}")
try:
self.connect()
self.cursor.execute("DELETE FROM `listen_audio_users` WHERE `user_id` = ?",
(user_id,))
self.conn.commit()
self.logger.info(
f"Функция delete_listen_count_for_user успешно отработала")
return None
except sqlite3.Error as error:
self.logger.error(f"Ошибка удаления записей прослушивания по пользователю: {error}")
raise
finally:
self.close()
def get_id_for_audio_record(self, user_id):
"""Получает ID аудио сообщения пользователя"""
self.logger.info(
f"Запуск функции get_id_for_audio_record. user_id={user_id}")
try:
self.connect()
result = self.cursor.execute(
"SELECT `file_id` FROM `audio_message_reference` WHERE `author_id` = ? ORDER BY date_added DESC LIMIT 1",
r = self.cursor.execute(
"SELECT `file_id` FROM `audio_message_reference` WHERE `author_id` = ? "
"ORDER BY date_added DESC LIMIT 1",
(user_id,))
return result.fetchone()[0]
result = r.fetchone()[0]
self.logger.info(
f"Результат функции get_id_for_audio_record: {result}")
return result
except sqlite3.Error as error:
print(error)
self.logger.error(f"Ошибка получения последней даты войса: {error}")
raise
finally:
self.close()
def get_path_for_audio_record(self, user_id):
"""Получает данные о названии файла"""
self.logger.info(
f"Запуск функции get_path_for_audio_record. user_id={user_id}")
try:
self.connect()
result = self.cursor.execute(
"SELECT `file_name` FROM `audio_message_reference` WHERE `author_id` = ? ORDER BY date_added DESC LIMIT 1",
r = self.cursor.execute(
"SELECT `file_name` "
"FROM `audio_message_reference` "
"WHERE `author_id` = ? "
"ORDER BY date_added "
"DESC LIMIT 1",
(user_id,))
return result.fetchone()[0]
result = r.fetchone()[0]
self.logger.info(
f"Результат функции get_path_for_audio_record: {result}")
return result
except sqlite3.Error as error:
print(error)
self.logger.error(f"Ошибка получения последней даты войса: {error}")
raise
finally:
self.close()
def check_listen_audio(self, user_id):
"""Проверяет прослушано ли аудио пользователем"""
self.logger.info(
f"Запуск функции check_listen_audio. user_id={user_id}")
try:
self.connect()
query_listen_audio = self.cursor.execute(
@@ -913,14 +1294,19 @@ class BotDB:
new_sign = []
for i in new_sign1:
new_sign.append(i[0])
self.logger.info(
f"Функция check_listen_audio успешно отработала.")
return new_sign
except sqlite3.Error as error:
print(error)
self.logger.error(f"Ошибка получения последней даты войса: {error}")
raise
finally:
self.close()
def mark_listened_audio(self, file_name, user_id):
"""Отмечает аудио прослушанным для конкретного пользователя."""
self.logger.info(
f"Запуск функции mark_listened_audio. file_name={file_name}, user_id={user_id}")
try:
self.connect()
result = self.cursor.execute(
@@ -928,7 +1314,8 @@ class BotDB:
(file_name, user_id, 1))
return self.conn.commit()
except sqlite3.Error as error:
print(error)
self.logger.error(f"Ошибка получения последней даты войса: {error}")
raise
finally:
self.close()

View File

@@ -1 +1 @@
from .main import admin_router
from .admin_handlers import admin_router

View File

@@ -5,20 +5,14 @@ from aiogram.filters import Command, StateFilter
from aiogram.fsm.context import FSMContext
from helper_bot.filters.main import ChatTypeFilter
from helper_bot.keyboards.main import get_reply_keyboard_admin, create_keyboard_with_pagination, \
create_keyboard_for_ban_days, create_keyboard_for_approve_ban
from helper_bot.keyboards.keyboards import get_reply_keyboard_admin, create_keyboard_with_pagination, \
create_keyboard_for_ban_days, create_keyboard_for_approve_ban, create_keyboard_for_ban_reason
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
from helper_bot.utils.helper_func import check_access, add_days_to_date, get_banned_users_buttons, get_banned_users_list
from logs.custom_logger import Logger
from database.db import BotDB
from logs.custom_logger import logger
admin_router = Router()
#Инициализируем логгер
admin_logger = Logger(name='admin_handler')
logger = admin_logger.get_logger()
bdf = BaseDependencyFactory()
GROUP_FOR_POST = bdf.settings['Telegram']['group_for_posts']
GROUP_FOR_MESSAGE = bdf.settings['Telegram']['group_for_message']
@@ -29,7 +23,7 @@ PREVIEW_LINK = bdf.settings['Telegram']['preview_link']
LOGS = bdf.settings['Settings']['logs']
TEST = bdf.settings['Settings']['test']
BotDB = BotDB('database/tg-bot-database')
BotDB = bdf.get_db()
@admin_router.message(
@@ -66,6 +60,48 @@ async def get_last_users(message: types.Message):
reply_markup=keyboard)
@admin_router.message(
ChatTypeFilter(chat_type=["private"]),
StateFilter("ADMIN"),
F.text == 'Бан по нику'
)
async def ban_by_nickname(message: types.Message, state: FSMContext):
await message.answer('Пришли мне username блокируемого пользователя')
await state.set_state('PRE_BAN')
@admin_router.message(
ChatTypeFilter(chat_type=["private"]),
F.text == 'Отменить'
)
async def decline_ban(message: types.Message, state: FSMContext):
await state.set_data({})
await state.set_state("ADMIN")
logger.info(f"Отмена процедуры блокировки")
markup = get_reply_keyboard_admin()
await message.answer('Вернулись в меню', reply_markup=markup)
@admin_router.message(
ChatTypeFilter(chat_type=["private"]),
StateFilter("PRE_BAN")
)
async def ban_by_nickname_step_2(message: types.Message, state: FSMContext):
logger.info(
f"Функция ban_by_nickname_2. Получен никнейм пользователя: {message.text}")
user_name = message.text
user_id = BotDB.get_user_id_by_username(user_name)
await state.update_data(user_id=user_id, user_name=user_name, message_for_user=None,
date_to_unban=None)
full_name = BotDB.get_full_name_by_id(user_id)
markup = create_keyboard_for_ban_reason()
await message.answer(
text=f"<b>Выбран пользователь:\nid:</b> {user_id}\n<b>username:</b> {user_name}\n"
f"Имя:{full_name}\nВыбери причину бана из списка или напиши ее в чат",
reply_markup=markup)
await state.set_state('BAN_2')
@admin_router.message(
ChatTypeFilter(chat_type=["private"]),
StateFilter("ADMIN"),
@@ -120,12 +156,12 @@ async def ban_user_step_3(message: types.Message, state: FSMContext):
@admin_router.message(
ChatTypeFilter(chat_type=["private"]),
StateFilter("BAN_FINAL")
StateFilter("BAN_FINAL"),
F.text == 'Подтвердить'
)
async def approve_ban(message: types.Message, state: FSMContext):
user_data = await state.get_data()
logger.info(f"Переход на финальный шаг бана пользователя. Словарь с данными для бана: {user_data})")
if message.text == 'Подтвердить':
exists = BotDB.check_user_in_blacklist(user_data['user_id'])
if exists:
await message.reply(f"Пользователь уже был заблокирован ранее.")

View File

@@ -1 +1 @@
from .main import callback_router
from .callback_handlers import callback_router

View File

@@ -0,0 +1,281 @@
import html
import traceback
from aiogram import Router, F
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery
from helper_bot.keyboards.keyboards import create_keyboard_with_pagination, get_reply_keyboard_admin, \
create_keyboard_for_ban_reason
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
from helper_bot.utils.helper_func import send_text_message, send_photo_message, get_banned_users_list, \
get_banned_users_buttons, delete_user_blacklist, send_media_group_to_channel, \
send_video_message, send_video_note_message, send_audio_message, send_voice_message
from logs.custom_logger import logger
callback_router = Router()
bdf = BaseDependencyFactory()
GROUP_FOR_POST = bdf.settings['Telegram']['group_for_posts']
GROUP_FOR_MESSAGE = bdf.settings['Telegram']['group_for_message']
MAIN_PUBLIC = bdf.settings['Telegram']['main_public']
GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs']
IMPORTANT_LOGS = bdf.settings['Telegram']['important_logs']
PREVIEW_LINK = bdf.settings['Telegram']['preview_link']
LOGS = bdf.settings['Settings']['logs']
TEST = bdf.settings['Settings']['test']
BotDB = bdf.get_db()
@callback_router.callback_query(
F.data == "publish"
)
async def post_for_group(call: CallbackQuery, state: FSMContext):
logger.info(
f'Получен callback-запрос с действием: {call.data} от пользователя {call.from_user.full_name} (ID сообщения: {call.message.message_id})')
text_post = html.escape(str(call.message.text))
text_post_with_photo = html.escape(str(call.message.caption))
if call.message.content_type == 'text' and call.message.text != "^":
try:
# Пересылаем сообщение в канал
await send_text_message(MAIN_PUBLIC, call.message, text_post)
# Получаем из базы автора
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
# Очищаем предложку и удаляем оттуда пост
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
logger.info(f'Текст сообщения опубликован в канале {MAIN_PUBLIC}.')
await call.answer(text='Выложено!', cache_time=3)
# Отвечаем пользователю
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
except Exception as e:
if e.message != 'Forbidden: bot was blocked by the user':
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
logger.error(f'Ошибка при публикации текста в канал {MAIN_PUBLIC}: {str(e)}')
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
elif call.message.content_type == 'photo':
try:
await send_photo_message(MAIN_PUBLIC, call.message, call.message.photo[-1].file_id, text_post_with_photo)
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
# Удаляем пост из предложки
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
logger.info(f'Пост с фото опубликован в канале {MAIN_PUBLIC}.')
await call.answer(text='Выложено!', cache_time=3)
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
except Exception as e:
if e.message != 'Forbidden: bot was blocked by the user':
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
logger.error(f'Ошибка при публикации фотографии в канал {MAIN_PUBLIC}: {str(e)}')
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
elif call.message.content_type == 'video':
try:
await send_video_message(MAIN_PUBLIC, call.message, call.message.video.file_id, text_post_with_photo)
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
logger.info(f'Пост с видео опубликован в канале {MAIN_PUBLIC}.')
await call.answer(text='Выложено!', cache_time=3)
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
except Exception as e:
if e.message != 'Forbidden: bot was blocked by the user':
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
logger.error(f'Ошибка при публикации видео в канал {MAIN_PUBLIC}: {str(e)}')
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
elif call.message.content_type == 'video_note':
try:
await send_video_note_message(MAIN_PUBLIC, call.message, call.message.video_note.file_id)
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
logger.info(f'Пост с кружком опубликован в канале {MAIN_PUBLIC}.')
await call.answer(text='Выложено!', cache_time=3)
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
except Exception as e:
if e.message != 'Forbidden: bot was blocked by the user':
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
logger.error(f'Ошибка при публикации кружка в канал {MAIN_PUBLIC}: {str(e)}')
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
elif call.message.content_type == 'audio':
try:
await send_audio_message(MAIN_PUBLIC, call.message, call.message.audio.file_id, text_post_with_photo)
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
logger.info(f'Пост с аудио опубликован в канале {MAIN_PUBLIC}.')
await call.answer(text='Выложено!', cache_time=3)
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
except Exception as e:
if e.message != 'Forbidden: bot was blocked by the user':
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
logger.error(f'Ошибка при публикации аудио в канал {MAIN_PUBLIC}: {str(e)}')
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
elif call.message.content_type == 'voice':
try:
await send_voice_message(MAIN_PUBLIC, call.message, call.message.voice.file_id)
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
logger.info(f'Пост с войсом опубликован в канале {MAIN_PUBLIC}.')
await call.answer(text='Выложено!', cache_time=3)
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
except Exception as e:
if e.message != 'Forbidden: bot was blocked by the user':
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
logger.error(f'Ошибка при публикации войса в канал {MAIN_PUBLIC}: {str(e)}')
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
elif call.message.text == "^":
# Получаем контент медиагруппы и текст для публикации
post_content = BotDB.get_post_content_from_telegram_by_last_id(call.message.message_id)
pre_text = BotDB.get_post_text_from_telegram_by_last_id(call.message.message_id)
post_text = html.escape(str(pre_text))
# Готовим список для удаления
post_ids = BotDB.get_post_ids_from_telegram_by_last_id(call.message.message_id)
message_ids = [row[0] for row in post_ids]
message_ids.append(call.message.message_id)
# Выкладываем пост в канал
await send_media_group_to_channel(bot=call.bot, chat_id=MAIN_PUBLIC, post_content=post_content,
post_text=post_text)
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
author_id = BotDB.get_author_id_by_helper_message_id(call.message.message_id)
# TODO: Удалить фотки с локалки после выкладки?
await call.bot.delete_messages(chat_id=GROUP_FOR_POST, message_ids=message_ids)
await call.answer(text='Выложено!', cache_time=3)
await send_text_message(author_id, call.message, 'Твой пост был выложен🥰')
@callback_router.callback_query(
F.data == "decline"
)
async def decline_post_for_group(call: CallbackQuery, state: FSMContext):
logger.info(
f'Получен callback-запрос с данными: {call.data} от пользователя {call.from_user.full_name} (ID: {call.from_user.id})')
try:
if call.message.content_type == 'text' and call.message.text != "^" or call.message.content_type == 'photo' \
or call.message.content_type == 'audio' or call.message.content_type == 'voice' \
or call.message.content_type == 'video' or call.message.content_type == 'video_note':
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
author_id = BotDB.get_author_id_by_message_id(call.message.message_id)
logger.info(
f'Сообщение отклонено админом {call.from_user.full_name} (ID: {call.from_user.id}).')
await call.answer(text='Отклонено!', cache_time=3)
await send_text_message(author_id, call.message, 'Твой пост был отклонен😔')
if call.message.text == '^':
post_ids = BotDB.get_post_ids_from_telegram_by_last_id(call.message.message_id)
message_ids = [row[0] for row in post_ids]
message_ids.append(call.message.message_id)
await call.bot.delete_messages(chat_id=GROUP_FOR_POST, message_ids=message_ids)
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
author_id = BotDB.get_author_id_by_helper_message_id(call.message.message_id)
await call.answer(text='Удалено!', cache_time=3)
await send_text_message(author_id, call.message, 'Твой пост был отклонен😔')
except Exception as e:
if e.message != 'Forbidden: bot was blocked by the user':
await call.bot.send_message(IMPORTANT_LOGS,
f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
logger.error(f'Ошибка при удалении сообщения в группе {GROUP_FOR_POST}: {str(e)}')
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
@callback_router.callback_query(
F.data.contains('ban')
)
async def process_ban_user(call: CallbackQuery, state: FSMContext):
user_id = call.data[4:]
logger.info(
f"Вызов функции process_ban_user. Данные callback: {call.data} пользователь: {user_id}")
user_name = BotDB.get_username(user_id=user_id)
if user_name:
await state.update_data(user_id=user_id, user_name=user_name, message_for_user=None,
date_to_unban=None)
markup = create_keyboard_for_ban_reason()
await call.message.answer(
text=f"<b>Выбран пользователь:\nid:</b> {user_id}\n<b>username:</b> {user_name}\nИмя:{call.message.from_user.full_name}\nВыбери причину бана из списка или напиши ее в чат",
reply_markup=markup)
await state.set_state('BAN_2')
else:
markup = get_reply_keyboard_admin()
await call.message.answer(text='Пользователь с таким ID не найден в базе', markup=markup)
await state.set_state('ADMIN')
@callback_router.callback_query(
F.data.contains('unlock')
)
async def process_unlock_user(call: CallbackQuery):
user_id = call.data[7:]
user_name = BotDB.get_username(user_id=user_id)
delete_user_blacklist(user_id)
logger.info(f"Разблокирован пользователь с ID: {user_id} username:{user_name}")
username = BotDB.get_username(user_id)
await call.answer(f'Пользователь разблокирован {username}', show_alert=True)
@callback_router.callback_query(
F.data == 'return'
)
async def return_to_main_menu(call: CallbackQuery):
await call.message.delete()
logger.info(f"Запуск админ панели для пользователя: {call.message.from_user.id}")
markup = get_reply_keyboard_admin()
await call.message.answer("Добро пожаловать в админку. Выбери что хочешь:",
reply_markup=markup)
@callback_router.callback_query(
F.data.contains('page')
)
async def change_page(call: CallbackQuery):
page_number = int(call.data[5:])
logger.info(f"Переход на страницу {page_number}")
if call.message.text == 'Список пользователей которые последними обращались к боту':
list_users = BotDB.get_last_users_from_db()
# TODO: Здесь где-то надо добавить обработку ошибки IndexError: list index out of range
keyboard = create_keyboard_with_pagination(int(page_number), len(list_users), list_users,
'ban')
await call.bot.edit_message_reply_markup(chat_id=call.message.chat.id, message_id=call.message.message_id,
reply_markup=keyboard)
else:
# Готовим сообщения
message_user = get_banned_users_list(int(page_number) * 7 - 7)
await call.bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
text=message_user)
# Готовим клавиатуру
buttons = get_banned_users_buttons()
keyboard = create_keyboard_with_pagination(int(call.data[5:]), len(buttons), buttons, 'unlock')
await call.bot.edit_message_reply_markup(chat_id=call.message.chat.id, message_id=call.message.message_id,
reply_markup=keyboard)

View File

@@ -1,165 +0,0 @@
import traceback
from aiogram import Router, F, types
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery
from database.db import BotDB
from helper_bot.keyboards.main import create_keyboard_with_pagination, get_reply_keyboard_admin, \
create_keyboard_for_ban_reason
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
from helper_bot.utils.helper_func import send_text_message, send_photo_message, get_banned_users_list, \
get_banned_users_buttons, delete_user_blacklist, get_help_message_id, send_media_group_message
from logs.custom_logger import Logger
callback_router = Router()
#Инициализируем логгер
callback_logger = Logger(name='callback_logger')
logger = callback_logger.get_logger()
bdf = BaseDependencyFactory()
GROUP_FOR_POST = bdf.settings['Telegram']['group_for_posts']
GROUP_FOR_MESSAGE = bdf.settings['Telegram']['group_for_message']
MAIN_PUBLIC = bdf.settings['Telegram']['main_public']
GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs']
IMPORTANT_LOGS = bdf.settings['Telegram']['important_logs']
PREVIEW_LINK = bdf.settings['Telegram']['preview_link']
LOGS = bdf.settings['Settings']['logs']
TEST = bdf.settings['Settings']['test']
BotDB = BotDB('database/tg-bot-database')
@callback_router.callback_query(
F.data == "publish"
)
async def post_for_group(call: CallbackQuery, state: FSMContext):
logger.info(
f'Получен callback-запрос с данными: {call.data} от пользователя {call.from_user.full_name} (ID: {call.from_user.id})')
if call.data == 'publish' and call.message.content_type == 'text' and call.message.text != "^":
try:
await send_text_message(MAIN_PUBLIC, call.message, call.message.text)
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
logger.info(f'Текст сообщения опубликован в канале {MAIN_PUBLIC}.')
await call.answer(text='Выложено!', show_alert=True, cache_time=3)
except Exception as e:
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
logger.error(f'Ошибка при публикации текста в канал {MAIN_PUBLIC}: {str(e)}')
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
elif call.data == 'publish' and call.message.content_type == 'photo':
try:
print(f'CALLMESSAGE - {call.message.text}')
await send_photo_message(MAIN_PUBLIC, call.message, call.message.photo[-1].file_id, call.message.caption)
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
logger.info(f'Пост с фото опубликован в канале {MAIN_PUBLIC}.')
await call.answer(text='Выложено!', show_alert=True, cache_time=3)
except Exception as e:
await call.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
logger.error(f'Ошибка при публикации фотографии в канал {MAIN_PUBLIC}: {str(e)}')
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
elif call.data == 'publish' and call.message.text == "^":
user_data = await state.get_data()
media_group_message_id = get_help_message_id(call.message.message_id, user_data)
await call.bot.copy_message(chat_id=MAIN_PUBLIC, from_chat_id=GROUP_FOR_POST,message_id=media_group_message_id, reply_markup=None)
#await call.bot.copy_messages(chat_id=MAIN_PUBLIC, from_chat_id=GROUP_FOR_POST, message_ids=[media_group_message_id, media_group_message_id-1])
await call.bot.delete_message(chat_id=MAIN_PUBLIC, message_id=media_group_message_id)
print(user_data['media_group_message_id'])
print(user_data['help_message_id'])
await call.answer(text='Выложено!', show_alert=True, cache_time=3)
@callback_router.callback_query(
F.data == "decline"
)
async def decline_post_for_group(call: CallbackQuery, state: FSMContext):
logger.info(
f'Получен callback-запрос с данными: {call.data} от пользователя {call.from_user.full_name} (ID: {call.from_user.id})')
try:
if call.message.content_type == 'text' and call.message.text != "^":
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
logger.info(
f'Сообщение отклонено админом {call.from_user.full_name} (ID: {call.from_user.id}).')
await call.answer(text='Отклонено!', show_alert=True, cache_time=3)
if call.message.text == '^':
user_data = await state.get_data()
media_group_message_id = get_help_message_id(call.message.message_id, user_data)
await call.bot.delete_message(chat_id=MAIN_PUBLIC, message_id=media_group_message_id)
except Exception as e:
await call.bot.send_message(IMPORTANT_LOGS,
f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
logger.error(f'Ошибка при удалении сообщения в группе {GROUP_FOR_POST}: {str(e)}')
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
@callback_router.callback_query(
F.data.contains('ban')
)
async def process_ban_user(call: CallbackQuery, state: FSMContext):
user_id = call.data[4:]
logger.info(
f"Вызов функции process_ban_user. Данные callback: {call.data} пользователь: {user_id}")
user_name = BotDB.get_username(user_id=user_id)
if user_name:
await state.update_data(user_id=user_id, user_name=user_name, message_for_user=None,
date_to_unban=None)
markup = create_keyboard_for_ban_reason()
await call.message.answer(
text=f"Выбран пользователь:\nid: {user_id}\nusername:{user_name}. Выбери причину бана из списка или напиши ее в чат",
reply_markup=markup)
await state.set_state('BAN_2')
else:
markup = get_reply_keyboard_admin()
await call.message.answer(text='Пользователь с таким ID не найден в базе', markup=markup)
await state.set_state('ADMIN')
@callback_router.callback_query(
F.data.contains('unlock')
)
async def process_unlock_user(call: CallbackQuery):
user_id = call.data[7:]
user_name = BotDB.get_username(user_id=user_id)
delete_user_blacklist(user_id)
logger.info(f"Разблокирован пользователь с ID: {user_id}\nusername:{user_name}")
username = BotDB.get_username(user_id)
await call.answer(f'Пользователь разблокирован {username}', show_alert=True)
@callback_router.callback_query(
F.data == 'return'
)
async def return_to_main_menu(call: CallbackQuery):
await call.message.delete()
logger.info(f"Запуск админ панели для пользователя: {call.message.from_user.id}")
markup = get_reply_keyboard_admin()
await call.message.answer("Добро пожаловать в админку. Выбери что хочешь:",
reply_markup=markup)
@callback_router.callback_query(
F.data.contains('page')
)
async def change_page(call: CallbackQuery):
page_number = int(call.data[5:])
logger.info(f"Переход на страницу {page_number}")
if call.message.text == 'Список пользователей которые последними обращались к боту':
list_users = BotDB.get_last_users_from_db()
#TODO: Здесь где-то надо добавить обработку ошибки IndexError: list index out of range
keyboard = create_keyboard_with_pagination(int(page_number), len(list_users), list_users,
'ban')
await call.bot.edit_message_reply_markup(chat_id=call.message.chat.id, message_id=call.message.message_id,
reply_markup=keyboard)
else:
#Готовим сообщения
message_user = get_banned_users_list(int(page_number) * 7 - 7)
await call.bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
text=message_user)
#Готовим клавиатуру
buttons = get_banned_users_buttons()
keyboard = create_keyboard_with_pagination(int(call.data[5:]), len(buttons), buttons, 'unlock')
await call.bot.edit_message_reply_markup(chat_id=call.message.chat.id, message_id=call.message.message_id,
reply_markup=keyboard)

View File

@@ -1 +1 @@
from .main import group_router
from .group_handlers import group_router

View File

@@ -1,19 +1,14 @@
from aiogram import Router, types
from aiogram.fsm.context import FSMContext
from database.db import BotDB
from helper_bot.filters.main import ChatTypeFilter
from helper_bot.keyboards.main import get_reply_keyboard_leave_chat
from helper_bot.keyboards.keyboards import get_reply_keyboard_leave_chat
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
from helper_bot.utils.helper_func import send_text_message
from logs.custom_logger import Logger
from logs.custom_logger import logger
group_router = Router()
#Инициализируем логгер
group_logger = Logger(name='group_logger')
logger = group_logger.get_logger()
bdf = BaseDependencyFactory()
GROUP_FOR_POST = bdf.settings['Telegram']['group_for_posts']
GROUP_FOR_MESSAGE = bdf.settings['Telegram']['group_for_message']
@@ -24,7 +19,7 @@ PREVIEW_LINK = bdf.settings['Telegram']['preview_link']
LOGS = bdf.settings['Settings']['logs']
TEST = bdf.settings['Settings']['test']
BotDB = BotDB('database/tg-bot-database')
BotDB = bdf.get_db()
@group_router.message(

View File

@@ -1 +1 @@
from .main import private_router
from .private_handlers import private_router

View File

@@ -1,287 +0,0 @@
import random
import traceback
from datetime import datetime
from pathlib import Path
from time import sleep
from aiogram import types, Router, F
from aiogram.filters import Command, StateFilter
from aiogram.fsm.context import FSMContext
from aiogram.types import FSInputFile
from helper_bot.filters.main import ChatTypeFilter
from helper_bot.keyboards import get_reply_keyboard, get_reply_keyboard_for_post
from helper_bot.keyboards.main import get_reply_keyboard_leave_chat
from helper_bot.middlewares.text_middleware import AlbumMiddleware
from helper_bot.utils import messages
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
from helper_bot.utils.helper_func import get_first_name, get_text_message, send_text_message, send_photo_message, \
process_photo_album, send_media_group_message, check_username_and_full_name
from logs.custom_logger import Logger
from database.db import BotDB
private_router = Router()
private_router.message.middleware(AlbumMiddleware())
#Инициализируем логгер
private_logger = Logger(name='private_handler')
logger = private_logger.get_logger()
bdf = BaseDependencyFactory()
GROUP_FOR_POST = bdf.settings['Telegram']['group_for_posts']
GROUP_FOR_MESSAGE = bdf.settings['Telegram']['group_for_message']
MAIN_PUBLIC = bdf.settings['Telegram']['main_public']
GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs']
IMPORTANT_LOGS = bdf.settings['Telegram']['important_logs']
PREVIEW_LINK = bdf.settings['Telegram']['preview_link']
LOGS = bdf.settings['Settings']['logs']
TEST = bdf.settings['Settings']['test']
BotDB = BotDB('database/tg-bot-database')
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
Command("start")
)
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
F.text == 'Вернуться в бота'
)
async def handle_start_message(message: types.Message, state: FSMContext):
try:
user_id = message.from_user.id
full_name = message.from_user.full_name
username = message.from_user.username
await message.forward(chat_id=GROUP_FOR_LOGS)
is_need_update = check_username_and_full_name(user_id, username, full_name)
if is_need_update:
BotDB.update_username_and_full_name(user_id, username, full_name)
await message.answer(f"Давно не виделись! Вижу что ты изменился;) Теперь буду звать тебя: {full_name} и ник @{username}")
await message.bot.send_message(chat_id=GROUP_FOR_LOGS, text=f'Для пользователя: {user_id} обновлены данные в БД.\nНовое имя: {full_name}\nНовый ник:{username}')
sleep(2)
await state.set_state("START")
logger.info(
f"Формирование приветственного сообщения для пользователя. Сообщение: {message.text} "
f"Имя автора сообщения: {message.from_user.full_name})")
name_stick_hello = list(Path('Stick').rglob('Hello_*'))
random_stick_hello = random.choice(name_stick_hello)
random_stick_hello = FSInputFile(path=random_stick_hello)
logger.info(f"Стикер успешно получен из БД")
await message.answer_sticker(random_stick_hello)
sleep(0.3)
except Exception as e:
logger.error(f"Произошла ошибка handle_start_message при получении стикеров. Ошибка:{str(e)}")
await message.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка при получении стикеров: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
try:
user_id = message.from_user.id
full_name = message.from_user.full_name
username = message.from_user.username
first_name = message.from_user.first_name
is_bot = message.from_user.is_bot
language_code = message.from_user.language_code
current_date = datetime.now()
date = current_date.strftime("%Y-%m-%d %H:%M:%S")
if not BotDB.user_exists(user_id):
BotDB.add_new_user_in_db(user_id, first_name, full_name, username, is_bot, language_code, date,
date)
BotDB.update_date_for_user(date, user_id)
markup = get_reply_keyboard(BotDB, message.from_user.id)
hello_message = messages.get_message(get_first_name(message), 'HELLO_MESSAGE')
await message.answer(hello_message, reply_markup=markup)
except Exception as e:
logger.error(
f"Произошла ошибка при отправке приветственного сообщения для пользователя {message.from_user.id} Имя: {message.from_user.full_name}. Ошибка: {str(e)}")
await message.bot.send_message(IMPORTANT_LOGS,
f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
@private_router.message(
StateFilter("START"),
ChatTypeFilter(chat_type=["private"]),
F.text == '📢Предложить свой пост'
)
async def suggest_post(message: types.Message, state: FSMContext):
try:
await message.forward(chat_id=GROUP_FOR_LOGS)
await state.set_state("SUGGEST")
current_state = await state.get_state()
logger.info(
f"Вызов функции suggest_post. Сообщение: {message.text} Имя автора сообщения: {message.from_user.full_name} Идентификатор сообщения: {message.message_id}. State - {current_state}")
markup = types.ReplyKeyboardRemove()
suggest_news = messages.get_message(get_first_name(message), 'SUGGEST_NEWS')
await message.answer(suggest_news)
sleep(0.3)
suggest_news_2 = messages.get_message(get_first_name(message), 'SUGGEST_NEWS_2')
await message.answer(suggest_news_2, reply_markup=markup)
except Exception as e:
await message.bot.send_message(IMPORTANT_LOGS,
f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
F.text == '👋🏼Сказать пока!'
)
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
F.text == 'Выйти из чата'
)
async def end_message(message: types.Message, state: FSMContext):
try:
logger.info(
f"Вызов функции end_message. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
name_stick_bye = list(Path('Stick').rglob('Universal_*'))
random_stick_bye = random.choice(name_stick_bye)
random_stick_bye = FSInputFile(path=random_stick_bye)
await message.answer_sticker(random_stick_bye)
except Exception as e:
logger.error(
f"Ошибка в функции end_message при получении стикера: {str(e)} Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
await message.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
try:
markup = types.ReplyKeyboardRemove()
bye_message = messages.get_message(get_first_name(message), 'BYE_MESSAGE')
await message.answer(bye_message, reply_markup=markup)
await state.set_state("START")
except Exception as e:
logger.error(
f"Ошибка в функции stickers при получении сообщения: {str(e)} Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
await message.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
@private_router.message(
StateFilter("SUGGEST"),
ChatTypeFilter(chat_type=["private"]),
)
async def suggest_router(message: types.Message, state: FSMContext, album: list = None):
logger.info(
f"Вызов функции suggest_router. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
try:
if message.content_type == 'text':
lower_text = message.text.lower()
post_text, is_anonymous = get_text_message(lower_text, message.from_user.full_name,
message.from_user.username)
markup = get_reply_keyboard_for_post()
if is_anonymous:
await send_text_message(GROUP_FOR_POST, message, post_text, markup)
else:
await send_text_message(GROUP_FOR_POST, message, post_text, markup)
markup_for_user = get_reply_keyboard(BotDB, message.from_user.id)
success_send_message = messages.get_message(get_first_name(message), 'SUCCESS_SEND_MESSAGE')
await message.answer(success_send_message, reply_markup=markup_for_user)
await state.set_state("START")
elif message.content_type == 'photo' and message.media_group_id is None:
lower_caption = message.caption.lower()
markup = get_reply_keyboard_for_post()
post_caption, is_anonymous = get_text_message(lower_caption, message.from_user.full_name,
message.from_user.username)
#TODO: тут какая-то шляпа
if is_anonymous:
await send_photo_message(GROUP_FOR_POST, message,
message.photo[-1].file_id, post_caption, markup)
else:
await send_photo_message(GROUP_FOR_POST, message,
message.photo[-1].file_id, post_caption, markup)
markup_for_user = get_reply_keyboard(BotDB, message.from_user.id)
success_send_message = messages.get_message(get_first_name(message), 'SUCCESS_SEND_MESSAGE')
await message.answer(success_send_message, reply_markup=markup_for_user)
await state.set_state("START")
elif message.media_group_id is not None:
post_caption = " "
if album[0].caption:
lower_caption = album[0].caption.lower()
post_caption, is_anonymous = get_text_message(lower_caption, message.from_user.full_name,
message.from_user.username)
media_group = process_photo_album(album, post_caption)
media_group_message_id = await send_media_group_message(GROUP_FOR_POST, message,
media_group)
sleep(0.2)
markup = get_reply_keyboard_for_post()
help_message_id = await send_text_message(GROUP_FOR_POST, message, "^", markup)
await state.update_data(media_group_message_id=media_group_message_id, help_message_id=help_message_id)
markup_for_user = get_reply_keyboard(BotDB, message.from_user.id)
success_send_message = messages.get_message(get_first_name(message), 'SUCCESS_SEND_MESSAGE')
await message.answer(success_send_message, reply_markup=markup_for_user)
await state.set_state("START")
else:
await message.bot.send_message(message.chat.id,
'Я пока не умею работать с таким сообщением. Пришли текст и фото/фоты(ы)')
except Exception as e:
await message.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
F.text == '🤪Хочу стикеры'
)
async def stickers(message: types.Message, state: FSMContext):
logger.info(
f"Вызов функции stickers. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
markup = get_reply_keyboard(BotDB, message.from_user.id)
try:
BotDB.update_info_about_stickers(user_id=message.from_user.id)
await message.forward(chat_id=GROUP_FOR_LOGS)
await message.answer(text='Хорошо, лови, добавить можно отсюда: https://t.me/addstickers/love_biysk',
reply_markup=markup)
await state.set_state("START")
except Exception as e:
await message.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
logger.error(
f"Ошибка функции stickers. Ошибка: {str(e)} Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
@private_router.message(
StateFilter("START"),
ChatTypeFilter(chat_type=["private"]),
F.text == '📩Связаться с админами'
)
async def connect_with_admin(message: types.Message, state: FSMContext):
logger.info(
f"Вызов функции connect_with_admin. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
admin_message = messages.get_message(get_first_name(message), 'CONNECT_WITH_ADMIN')
await message.answer(admin_message, parse_mode="html")
await message.forward(chat_id=GROUP_FOR_LOGS)
await state.set_state("PRE_CHAT")
@private_router.message(
StateFilter("PRE_CHAT"),
ChatTypeFilter(chat_type=["private"]),
)
@private_router.message(
StateFilter("CHAT"),
ChatTypeFilter(chat_type=["private"]),
)
async def resend_message_in_group_for_message(message: types.Message, state: FSMContext):
logger.info(
f"Попытка пересылки сообщения в связь с админами. Сообщение: {message.text} Имя автора сообщения: {message.from_user.full_name} Идентификатор сообщения: {message.message_id})")
await message.forward(chat_id=GROUP_FOR_MESSAGE)
current_date = datetime.now()
date = current_date.strftime("%Y-%m-%d %H:%M:%S")
BotDB.add_new_message_in_db(message.text, message.from_user.id, message.message_id + 1, date)
question = messages.get_message(get_first_name(message), 'QUESTION')
user_state = await state.get_state()
if user_state == "PRE_CHAT":
markup = get_reply_keyboard(BotDB, message.from_user.id)
await message.answer(question, reply_markup=markup)
await state.set_state("START")
elif user_state == "CHAT":
markup = get_reply_keyboard_leave_chat()
await message.answer(question, reply_markup=markup)
# @private_router.message(
# ChatTypeFilter(chat_type=["private"])
# )
# async def default(message: types.Message, state: FSMContext):
# markup = get_reply_keyboard(BotDB, message.from_user.id)
# await message.answer('Кажется ты заблудился. Держи клавиатуру, твое состояние сброшено на начало', reply_markup=markup)
# await state.set_state("START")

View File

@@ -0,0 +1,419 @@
import random
import traceback
from datetime import datetime
from pathlib import Path
from time import sleep
from aiogram import types, Router, F
from aiogram.filters import Command, StateFilter
from aiogram.fsm.context import FSMContext
from aiogram.types import FSInputFile
from helper_bot.filters.main import ChatTypeFilter
from helper_bot.keyboards import get_reply_keyboard, get_reply_keyboard_for_post
from helper_bot.keyboards.keyboards import get_reply_keyboard_leave_chat
from helper_bot.middlewares.album_middleware import AlbumMiddleware
from helper_bot.middlewares.blacklist_middleware import BlacklistMiddleware
from helper_bot.utils import messages
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
from helper_bot.utils.helper_func import get_first_name, get_text_message, send_text_message, send_photo_message, \
send_media_group_message_to_private_chat, prepare_media_group_from_middlewares, send_video_message, \
send_video_note_message, send_audio_message, send_voice_message, add_in_db_media, \
update_user_info, check_user_emoji
from logs.custom_logger import logger
private_router = Router()
private_router.message.middleware(AlbumMiddleware())
private_router.message.middleware(BlacklistMiddleware())
bdf = BaseDependencyFactory()
GROUP_FOR_POST = bdf.settings['Telegram']['group_for_posts']
GROUP_FOR_MESSAGE = bdf.settings['Telegram']['group_for_message']
MAIN_PUBLIC = bdf.settings['Telegram']['main_public']
GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs']
IMPORTANT_LOGS = bdf.settings['Telegram']['important_logs']
PREVIEW_LINK = bdf.settings['Telegram']['preview_link']
LOGS = bdf.settings['Settings']['logs']
TEST = bdf.settings['Settings']['test']
BotDB = bdf.get_db()
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
Command("emoji")
)
async def handle_emoji_message(message: types.Message, state: FSMContext):
await message.forward(chat_id=GROUP_FOR_LOGS)
user_emoji = check_user_emoji(message)
await state.set_state("START")
if user_emoji is not None:
await message.answer(f'Твоя эмодзя - {user_emoji}', parse_mode='HTML')
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
Command("restart")
)
async def handle_restart_message(message: types.Message, state: FSMContext):
try:
markup = get_reply_keyboard(BotDB, message.from_user.id)
await message.forward(chat_id=GROUP_FOR_LOGS)
await state.set_state("START")
await update_user_info('love', message)
check_user_emoji(message)
await message.answer('Я перезапущен!', reply_markup=markup, parse_mode='HTML')
except Exception as e:
logger.error(f"Произошла ошибка handle_restart_message. Ошибка:{str(e)}")
await message.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка handle_restart_message: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
Command("start")
)
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
F.text == 'Вернуться в бота'
)
async def handle_start_message(message: types.Message, state: FSMContext):
try:
await message.forward(chat_id=GROUP_FOR_LOGS)
await update_user_info('love', message)
check_user_emoji(message)
await state.set_state("START")
logger.info(
f"Формирование приветственного сообщения для пользователя. Сообщение: {message.text} "
f"Имя автора сообщения: {message.from_user.full_name})")
name_stick_hello = list(Path('Stick').rglob('Hello_*'))
random_stick_hello = random.choice(name_stick_hello)
random_stick_hello = FSInputFile(path=random_stick_hello)
logger.info(f"Стикер успешно получен из БД")
await message.answer_sticker(random_stick_hello)
sleep(0.3)
except Exception as e:
logger.error(f"Произошла ошибка handle_start_message при получении стикеров. Ошибка:{str(e)}")
await message.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка при получении стикеров: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
try:
markup = get_reply_keyboard(BotDB, message.from_user.id)
hello_message = messages.get_message(get_first_name(message), 'HELLO_MESSAGE')
await message.answer(hello_message, reply_markup=markup, parse_mode='HTML')
except Exception as e:
logger.error(
f"Произошла ошибка при отправке приветственного сообщения для пользователя {message.from_user.id} Имя: {message.from_user.full_name}. Ошибка: {str(e)}")
await message.bot.send_message(IMPORTANT_LOGS,
f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
@private_router.message(
StateFilter("START"),
ChatTypeFilter(chat_type=["private"]),
F.text == '📢Предложить свой пост'
)
async def suggest_post(message: types.Message, state: FSMContext):
try:
user_id = message.from_user.id
current_date = datetime.now()
date = current_date.strftime("%Y-%m-%d %H:%M:%S")
BotDB.update_date_for_user(date, user_id)
await message.forward(chat_id=GROUP_FOR_LOGS)
await state.set_state("SUGGEST")
current_state = await state.get_state()
logger.info(
f"Вызов функции suggest_post. Сообщение: {message.text} Имя автора сообщения: {message.from_user.full_name} Идентификатор сообщения: {message.message_id}. State - {current_state}")
markup = types.ReplyKeyboardRemove()
suggest_news = messages.get_message(get_first_name(message), 'SUGGEST_NEWS')
await message.answer(suggest_news)
sleep(0.3)
suggest_news_2 = messages.get_message(get_first_name(message), 'SUGGEST_NEWS_2')
await message.answer(suggest_news_2, reply_markup=markup)
except Exception as e:
await message.bot.send_message(IMPORTANT_LOGS,
f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
F.text == '👋🏼Сказать пока!'
)
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
F.text == 'Выйти из чата'
)
async def end_message(message: types.Message, state: FSMContext):
try:
user_id = message.from_user.id
current_date = datetime.now()
date = current_date.strftime("%Y-%m-%d %H:%M:%S")
BotDB.update_date_for_user(date, user_id)
await message.forward(chat_id=GROUP_FOR_LOGS)
logger.info(
f"Вызов функции end_message. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
name_stick_bye = list(Path('Stick').rglob('Universal_*'))
random_stick_bye = random.choice(name_stick_bye)
random_stick_bye = FSInputFile(path=random_stick_bye)
await message.answer_sticker(random_stick_bye)
except Exception as e:
logger.error(
f"Ошибка в функции end_message при получении стикера: {str(e)} Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
await message.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
try:
markup = types.ReplyKeyboardRemove()
bye_message = messages.get_message(get_first_name(message), 'BYE_MESSAGE')
await message.answer(bye_message, reply_markup=markup)
await state.set_state("START")
except Exception as e:
logger.error(
f"Ошибка в функции stickers при получении сообщения: {str(e)} Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
await message.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
@private_router.message(
StateFilter("SUGGEST"),
ChatTypeFilter(chat_type=["private"]),
)
async def suggest_router(message: types.Message, state: FSMContext, album: list = None):
logger.info(
f"Вызов функции suggest_router. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
first_name = get_first_name(message)
try:
post_caption = ''
if message.media_group_id is not None:
await send_text_message(GROUP_FOR_LOGS, message,
f'Закинул медиагруппу, пользователь: имя - {first_name}, ник - {message.from_user.username}')
else:
await message.forward(chat_id=GROUP_FOR_LOGS)
if message.content_type == 'text':
lower_text = message.text.lower()
# Получаем текст сообщения и преобразовываем его по правилам
post_text = get_text_message(lower_text, first_name,
message.from_user.username)
# Получаем клавиатуру для поста
markup = get_reply_keyboard_for_post()
# Отправляем сообщение в приватный канал
sent_message_id = await send_text_message(GROUP_FOR_POST, message, post_text, markup)
# Записываем в базу пост
BotDB.add_post_in_db(sent_message_id, message.text, message.from_user.id)
# Отправляем юзеру ответ, что сообщение отравлено и возвращаем его в меню
markup_for_user = get_reply_keyboard(BotDB, message.from_user.id)
success_send_message = messages.get_message(first_name, 'SUCCESS_SEND_MESSAGE')
await message.answer(success_send_message, reply_markup=markup_for_user)
await state.set_state("START")
elif message.content_type == 'photo' and message.media_group_id is None:
if message.caption:
lower_caption = message.caption.lower()
# Получаем текст сообщения и преобразовываем его по правилам
post_caption = get_text_message(lower_caption, first_name,
message.from_user.username)
markup = get_reply_keyboard_for_post()
# Отправляем фото и текст в приватный канал
sent_message = await send_photo_message(GROUP_FOR_POST, message,
message.photo[-1].file_id, post_caption, markup)
# Записываем в базу пост и контент
BotDB.add_post_in_db(sent_message.message_id, sent_message.caption, message.from_user.id)
await add_in_db_media(sent_message)
# Отправляем юзеру ответ и возвращаем его в меню
markup_for_user = get_reply_keyboard(BotDB, message.from_user.id)
success_send_message = messages.get_message(first_name, 'SUCCESS_SEND_MESSAGE')
await message.answer(success_send_message, reply_markup=markup_for_user)
await state.set_state("START")
elif message.content_type == 'video' and message.media_group_id is None:
if message.caption:
lower_caption = message.caption.lower()
post_caption = get_text_message(lower_caption, first_name,
message.from_user.username)
markup = get_reply_keyboard_for_post()
# Получаем текст сообщения и преобразовываем его по правилам
# Отправляем видео и текст в приватный канал
sent_message = await send_video_message(GROUP_FOR_POST, message,
message.video.file_id, post_caption, markup)
# Записываем в базу пост и контент
BotDB.add_post_in_db(sent_message.message_id, sent_message.caption, message.from_user.id)
await add_in_db_media(sent_message)
# Записываем в базу пост и контент
BotDB.add_post_in_db(sent_message.message_id, sent_message.caption, message.from_user.id)
await add_in_db_media(sent_message)
# Отправляем юзеру ответ и возвращаем его в меню
markup_for_user = get_reply_keyboard(BotDB, message.from_user.id)
success_send_message = messages.get_message(first_name, 'SUCCESS_SEND_MESSAGE')
await message.answer(success_send_message, reply_markup=markup_for_user)
await state.set_state("START")
elif message.content_type == 'video_note' and message.media_group_id is None:
markup = get_reply_keyboard_for_post()
# Отправляем видеокружок в приватный канал
sent_message = await send_video_note_message(GROUP_FOR_POST, message,
message.video_note.file_id, markup)
# Записываем в базу пост и контент
BotDB.add_post_in_db(sent_message.message_id, sent_message.caption, message.from_user.id)
await add_in_db_media(sent_message)
# Отправляем юзеру ответ и возвращаем его в меню
markup_for_user = get_reply_keyboard(BotDB, message.from_user.id)
success_send_message = messages.get_message(first_name, 'SUCCESS_SEND_MESSAGE')
await message.answer(success_send_message, reply_markup=markup_for_user)
await state.set_state("START")
elif message.content_type == 'audio' and message.media_group_id is None:
if message.caption:
lower_caption = message.caption.lower()
# Получаем текст сообщения и преобразовываем его по правилам
post_caption = get_text_message(lower_caption, first_name,
message.from_user.username)
markup = get_reply_keyboard_for_post()
# Отправляем аудио и текст в приватный канал
sent_message = await send_audio_message(GROUP_FOR_POST, message,
message.audio.file_id, post_caption, markup)
# Записываем в базу пост и контент
BotDB.add_post_in_db(sent_message.message_id, sent_message.caption, message.from_user.id)
await add_in_db_media(sent_message)
# Отправляем юзеру ответ и возвращаем его в меню
markup_for_user = get_reply_keyboard(BotDB, message.from_user.id)
success_send_message = messages.get_message(first_name, 'SUCCESS_SEND_MESSAGE')
await message.answer(success_send_message, reply_markup=markup_for_user)
await state.set_state("START")
elif message.content_type == 'voice' and message.media_group_id is None:
markup = get_reply_keyboard_for_post()
# Отправляем войс и текст в приватный канал
sent_message = await send_voice_message(GROUP_FOR_POST, message,
message.voice.file_id, markup)
# Записываем в базу пост и контент
BotDB.add_post_in_db(sent_message.message_id, sent_message.caption, message.from_user.id)
await add_in_db_media(sent_message)
# Отправляем юзеру ответ и возвращаем его в меню
markup_for_user = get_reply_keyboard(BotDB, message.from_user.id)
success_send_message = messages.get_message(first_name, 'SUCCESS_SEND_MESSAGE')
await message.answer(success_send_message, reply_markup=markup_for_user)
await state.set_state("START")
elif message.media_group_id is not None:
post_caption = " "
# Получаем сообщение и проверяем есть ли подпись. Если подпись есть, то преобразуем ее через функцию
if album[0].caption:
lower_caption = album[0].caption.lower()
post_caption = get_text_message(lower_caption, first_name,
message.from_user.username)
# Иначе обрабатываем фото и получаем медиагруппу
media_group = await prepare_media_group_from_middlewares(album, post_caption)
# Отправляем медиагруппу в секретный чат
media_group_message_id = await send_media_group_message_to_private_chat(GROUP_FOR_POST, message,
media_group)
sleep(0.2)
# Получаем клавиатуру и отправляем еще одно текстовое сообщение с кнопками
markup = get_reply_keyboard_for_post()
help_message_id = await send_text_message(GROUP_FOR_POST, message, "^", markup)
# Записываем в state идентификаторы текстового сообщения И последнего сообщения медиагруппы
BotDB.update_helper_message_in_db(message_id=media_group_message_id, helper_message_id=help_message_id)
# Получаем клавиатуру для пользователя, благодарим за пост, и возвращаем в дефолтное сообщение
markup_for_user = get_reply_keyboard(BotDB, message.from_user.id)
success_send_message = messages.get_message(first_name, 'SUCCESS_SEND_MESSAGE')
await message.answer(success_send_message, reply_markup=markup_for_user)
await state.set_state("START")
else:
await message.bot.send_message(message.chat.id,
'Я пока не умею работать с таким сообщением. '
'Пришли текст и фото/фоты(ы). А лучше перешли это сообщение админу @kerrad1\n'
'Мы добавим его к обработке если необходимо')
except Exception as e:
await message.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
F.text == '🤪Хочу стикеры'
)
async def stickers(message: types.Message, state: FSMContext):
logger.info(
f"Вызов функции stickers. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
markup = get_reply_keyboard(BotDB, message.from_user.id)
try:
BotDB.update_info_about_stickers(user_id=message.from_user.id)
await message.forward(chat_id=GROUP_FOR_LOGS)
await message.answer(text='Хорошо, лови, добавить можно отсюда: https://t.me/addstickers/love_biysk',
reply_markup=markup)
await state.set_state("START")
except Exception as e:
await message.bot.send_message(chat_id=IMPORTANT_LOGS,
text=f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")
logger.error(
f"Ошибка функции stickers. Ошибка: {str(e)} Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
@private_router.message(
StateFilter("START"),
ChatTypeFilter(chat_type=["private"]),
F.text == '📩Связаться с админами'
)
async def connect_with_admin(message: types.Message, state: FSMContext):
logger.info(
f"Вызов функции connect_with_admin. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
user_id = message.from_user.id
current_date = datetime.now()
date = current_date.strftime("%Y-%m-%d %H:%M:%S")
BotDB.update_date_for_user(date, user_id)
admin_message = messages.get_message(get_first_name(message), 'CONNECT_WITH_ADMIN')
await message.answer(admin_message, parse_mode="html")
await message.forward(chat_id=GROUP_FOR_LOGS)
await state.set_state("PRE_CHAT")
@private_router.message(
StateFilter("PRE_CHAT"),
ChatTypeFilter(chat_type=["private"]),
)
@private_router.message(
StateFilter("CHAT"),
ChatTypeFilter(chat_type=["private"]),
)
async def resend_message_in_group_for_message(message: types.Message, state: FSMContext):
user_id = message.from_user.id
current_date = datetime.now()
date = current_date.strftime("%Y-%m-%d %H:%M:%S")
BotDB.update_date_for_user(date, user_id)
logger.info(
f"Попытка пересылки сообщения в связь с админами. Сообщение: {message.text} Имя автора сообщения: {message.from_user.full_name} Идентификатор сообщения: {message.message_id})")
await message.forward(chat_id=GROUP_FOR_MESSAGE)
current_date = datetime.now()
date = current_date.strftime("%Y-%m-%d %H:%M:%S")
BotDB.add_new_message_in_db(message.text, message.from_user.id, message.message_id + 1, date)
question = messages.get_message(get_first_name(message), 'QUESTION')
user_state = await state.get_state()
if user_state == "PRE_CHAT":
markup = get_reply_keyboard(BotDB, message.from_user.id)
await message.answer(question, reply_markup=markup)
await state.set_state("START")
elif user_state == "CHAT":
markup = get_reply_keyboard_leave_chat()
await message.answer(question, reply_markup=markup)

View File

@@ -1 +1 @@
from .main import get_reply_keyboard_for_post, get_reply_keyboard
from .keyboards import get_reply_keyboard_for_post, get_reply_keyboard

View File

@@ -5,8 +5,9 @@ from aiogram.utils.keyboard import ReplyKeyboardBuilder, InlineKeyboardBuilder
def get_reply_keyboard_for_post():
builder = InlineKeyboardBuilder()
builder.row(types.InlineKeyboardButton(
text="Опубликовать", callback_data="publish"),
types.InlineKeyboardButton(
text="Опубликовать", callback_data="publish")
)
builder.row(types.InlineKeyboardButton(
text="Отклонить", callback_data="decline")
)
markup = builder.as_markup(resize_keyboard=True, one_time_keyboard=True)
@@ -34,6 +35,7 @@ def get_reply_keyboard_leave_chat():
def get_reply_keyboard_admin():
builder = ReplyKeyboardBuilder()
builder.add(types.KeyboardButton(text="Бан (Список)"))
builder.add(types.KeyboardButton(text="Бан по нику"))
builder.add(types.KeyboardButton(text="Разбан (список)"))
builder.add(types.KeyboardButton(text="Вернуться в бота"))
markup = builder.as_markup(resize_keyboard=True, one_time_keyboard=True)
@@ -59,7 +61,6 @@ def create_keyboard_with_pagination(page: int, total_items: int, array_items: li
# Создаем билдер для клавиатуры
keyboard = InlineKeyboardBuilder()
# TODO: Тут поправить на 9 объектов, а не 7. Клавиатуру переделал
# Вычисляем стартовый номер для текущей страницы
start_index = (page - 1) * 9
@@ -88,6 +89,9 @@ def create_keyboard_for_ban_reason():
builder = ReplyKeyboardBuilder()
builder.add(types.KeyboardButton(text="Спам"))
builder.add(types.KeyboardButton(text="Заебал стикерами"))
builder.row(types.KeyboardButton(text="Реклама здесь: @kerrad1 "))
builder.row(types.KeyboardButton(text="Тема с лагерями: https://vk.com/topic-75343895_50049913"))
builder.row(types.KeyboardButton(text="Отменить"))
markup = builder.as_markup(resize_keyboard=True, one_time_keyboard=True)
return markup
@@ -97,7 +101,8 @@ def create_keyboard_for_ban_days():
builder.add(types.KeyboardButton(text="1"))
builder.add(types.KeyboardButton(text="7"))
builder.add(types.KeyboardButton(text="30"))
builder.add(types.KeyboardButton(text="Навсегда"))
builder.row(types.KeyboardButton(text="Навсегда"))
builder.row(types.KeyboardButton(text="Отменить"))
markup = builder.as_markup(resize_keyboard=True, one_time_keyboard=True)
return markup

View File

@@ -1,16 +1,31 @@
import asyncio
from collections import defaultdict
from typing import Any, Dict, Union
from aiogram import BaseMiddleware
from aiogram.types import Message
class BulkTextMiddleware(BaseMiddleware):
class AlbumMiddleware(BaseMiddleware):
def __init__(self, latency: Union[int, float] = 0.1):
# Initialize latency and album_data dictionary
self.latency = latency
self.texts = defaultdict(list)
self.album_data = {}
#
def collect_album_messages(self, event: Message):
"""
Collect messages of the same media group.
"""
# # Check if media_group_id exists in album_data
if event.media_group_id not in self.album_data:
# # Create a new entry for the media group
self.album_data[event.media_group_id] = {"messages": []}
#
# # Append the new message to the media group
self.album_data[event.media_group_id]["messages"].append(event)
#
# # Return the total number of messages in the current media group
return len(self.album_data[event.media_group_id]["messages"])
#
async def __call__(self, handler, event: Message, data: Dict[str, Any]) -> Any:
@@ -18,29 +33,29 @@ class BulkTextMiddleware(BaseMiddleware):
Main middleware logic.
"""
# # If the event has no media_group_id, pass it to the handler immediately
key = (event.chat.id, event.from_user.id)
if not event.text:
if not event.media_group_id:
return await handler(event, data)
self.texts[key].append(event)
total_before = len(self.texts[key])
#
# # Collect messages of the same media group
total_before = self.collect_album_messages(event)
#
# # Wait for a specified latency period
await asyncio.sleep(self.latency)
#
# # Check the total number of messages after the latency
total_after = len(self.texts[key])
total_after = len(self.album_data[event.media_group_id]["messages"])
#
# # If new messages were added during the latency, exit
if total_before != total_after:
return
#
# # Sort the album messages by message_id and add to data
msg_texts = self.texts[key]
msg_texts.sort(key=lambda x: x.message_id)
data["texts"] = ''.join([msg.text for msg in msg_texts])
album_messages = self.album_data[event.media_group_id]["messages"]
album_messages.sort(key=lambda x: x.message_id)
data["album"] = album_messages
#
# Remove the media group from tracking to free up memory
del self.texts[key]
# # Remove the media group from tracking to free up memory
del self.album_data[event.media_group_id]
# # Call the original event handler
return await handler(event, data)
#

View File

@@ -0,0 +1,21 @@
from typing import Dict, Any
from aiogram import BaseMiddleware, types
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
from logs.custom_logger import logger
bdf = BaseDependencyFactory()
BotDB = bdf.get_db()
class BlacklistMiddleware(BaseMiddleware):
async def __call__(self, handler, event: types.Message, data: Dict[str, Any]) -> Any:
logger.info(f'Вызов BlacklistMiddleware для пользователя {event.from_user.username}')
if BotDB.check_user_in_blacklist(user_id=event.from_user.id):
logger.info(f'BlacklistMiddleware результат для пользователя: {event.from_user.username} заблокирован!')
user_info = BotDB.get_blacklist_users_by_id(event.from_user.id)
await event.answer(
f"<b>Ты заблокирован.</b>\n<b>Причина блокировки:</b> {user_info[2]}\n<b>Дата разбана:</b> {user_info[3]}")
return False
logger.info(f'BlacklistMiddleware результат для пользователя: {event.from_user.username} доступ разрешен')
return await handler(event, data)

View File

@@ -1,61 +1,46 @@
import asyncio
from collections import defaultdict
from typing import Any, Dict, Union
from aiogram import BaseMiddleware
from aiogram.types import Message
class AlbumMiddleware(BaseMiddleware):
class BulkTextMiddleware(BaseMiddleware):
def __init__(self, latency: Union[int, float] = 0.1):
# Initialize latency and album_data dictionary
self.latency = latency
self.album_data = {}
self.texts = defaultdict(list)
#
def collect_album_messages(self, event: Message):
"""
Collect messages of the same media group.
"""
# # Check if media_group_id exists in album_data
if event.media_group_id not in self.album_data:
# # Create a new entry for the media group
self.album_data[event.media_group_id] = {"messages": []}
#
# # Append the new message to the media group
self.album_data[event.media_group_id]["messages"].append(event)
#
# # Return the total number of messages in the current media group
return len(self.album_data[event.media_group_id]["messages"])
#
async def __call__(self, handler, event: Message, data: Dict[str, Any]) -> Any:
"""
Main middleware logic.
"""
# # If the event has no media_group_id, pass it to the handler immediately
if not event.media_group_id:
key = (event.chat.id, event.from_user.id)
if not event.text:
return await handler(event, data)
#
# # Collect messages of the same media group
total_before = self.collect_album_messages(event)
#
self.texts[key].append(event)
total_before = len(self.texts[key])
# # Wait for a specified latency period
await asyncio.sleep(self.latency)
#
# # Check the total number of messages after the latency
total_after = len(self.album_data[event.media_group_id]["messages"])
total_after = len(self.texts[key])
#
# # If new messages were added during the latency, exit
if total_before != total_after:
return
#
# # Sort the album messages by message_id and add to data
album_messages = self.album_data[event.media_group_id]["messages"]
album_messages.sort(key=lambda x: x.message_id)
data["album"] = album_messages
msg_texts = self.texts[key]
msg_texts.sort(key=lambda x: x.message_id)
data["texts"] = ''.join([msg.text for msg in msg_texts])
#
# # Remove the media group from tracking to free up memory
del self.album_data[event.media_group_id]
# Remove the media group from tracking to free up memory
del self.texts[key]
# # Call the original event handler
return await handler(event, data)
#

View File

@@ -2,6 +2,10 @@ import configparser
import os
import sys
from database.db import BotDB
current_dir = os.getcwd()
class BaseDependencyFactory:
def __init__(self):
@@ -10,6 +14,8 @@ class BaseDependencyFactory:
self.config = configparser.ConfigParser()
self.config.read(config_path)
self.settings = {}
self.database = BotDB(current_dir, 'database/tg-bot-database')
for section in self.config.sections():
self.settings[section] = {}
for key in self.config[section]:
@@ -23,3 +29,7 @@ class BaseDependencyFactory:
def get_settings(self):
return self.settings
def get_db(self) -> BotDB:
"""Возвращает подключение к базе данных."""
return self.database

View File

@@ -1,15 +1,27 @@
import html
import os
import random
from datetime import datetime, timedelta
from time import sleep
import emoji
from aiogram import types
from aiogram.types import InputMediaPhoto
from aiogram.types import InputMediaPhoto, FSInputFile, InputMediaVideo, InputMediaAudio
from database.db import BotDB
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
from logs.custom_logger import logger
BotDB = BotDB('database/tg-bot-database')
bdf = BaseDependencyFactory()
GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs']
emoji_list = list(emoji.EMOJI_DATA.keys())
BotDB = bdf.get_db()
def get_first_name(message: types.Message) -> str:
return message.from_user.first_name
first_name = html.escape(message.from_user.first_name)
return first_name
def get_text_message(post_text: str, first_name: str, username: str):
@@ -22,50 +34,187 @@ def get_text_message(post_text: str, first_name: str, username: str):
username: Юзернейм автора поста
Returns:
Кортеж из двух элементов:
- Сформированный текст сообщения.
- Флаг, указывающий, является ли пост анонимным (True - анонимный, False - не анонимный).
str: - Сформированный текст сообщения.
"""
if "неанон" in post_text or "не анон" in post_text:
is_anonymous = False
return f'Пост из ТГ:\n{post_text}\n\nАвтор поста: {first_name} @{username}', is_anonymous
return f'Пост из ТГ:\n{post_text}\n\nАвтор поста: {first_name} @{username}'
elif "анон" in post_text:
is_anonymous = True
return f'Пост из ТГ:\n{post_text}\n\nПост опубликован анонимно', is_anonymous
return f'Пост из ТГ:\n{post_text}\n\nПост опубликован анонимно'
else:
is_anonymous = False
return f'Пост из ТГ:\n{post_text}\n\nАвтор поста: {first_name} @{username}', is_anonymous
return f'Пост из ТГ:\n{post_text}\n\nАвтор поста: {first_name} @{username}'
def process_photo_album(album, post_caption: str = ''):
async def download_file(message: types.Message, file_id: str):
"""
Создает список InputMediaPhoto для альбома.
Скачивает файл по file_id из Telegram.
Args:
message: сообщение
file_id: File ID фотографии
filename: Имя файла, под которым будет сохранено фото
Returns:
Путь к сохраненному файлу, если файл был скачан успешно, иначе None
"""
try:
os.makedirs("files", exist_ok=True)
os.makedirs("files/photos", exist_ok=True)
os.makedirs("files/videos", exist_ok=True)
os.makedirs("files/music", exist_ok=True)
os.makedirs("files/voice", exist_ok=True)
os.makedirs("files/video_notes", exist_ok=True)
file = await message.bot.get_file(file_id)
file_path = os.path.join("files", file.file_path)
await message.bot.download_file(file_path=file.file_path, destination=file_path)
return file_path
except Exception as e:
logger.error(f"Ошибка скачивания фотографии: {e}")
return None
async def prepare_media_group_from_middlewares(album, post_caption: str = ''):
"""
Создает MediaGroup.
Args:
album: Album объект из Telegram API.
post_caption: Текст подписи к первому фото.
Returns:
Список InputMediaPhoto.
Список InputMediaPhoto (MediaGroup).
"""
photo_media = []
media_group = []
for i, message in enumerate(album):
if i == 0:
photo_media.append(InputMediaPhoto(media=message.photo[-1].file_id, caption=post_caption))
if message.photo:
file_id = message.photo[-1].file_id
media_type = 'photo'
elif message.video:
file_id = message.video.file_id
media_type = 'video'
elif message.audio:
file_id = message.audio.file_id
media_type = 'audio'
else:
photo_media.append(InputMediaPhoto(media=message.photo[-1].file_id))
return photo_media
# Если нет фото, видео или аудио, пропускаем сообщение
continue
# Формируем объект MediaGroup с учетом типа медиа
if i == len(album) - 1:
if media_type == 'photo':
media_group.append(InputMediaPhoto(media=file_id, caption=post_caption))
elif media_type == 'video':
media_group.append(InputMediaVideo(media=file_id, caption=post_caption))
elif media_type == 'audio':
media_group.append(InputMediaAudio(media=file_id, caption=post_caption))
else:
if media_type == 'photo':
media_group.append(InputMediaPhoto(media=file_id))
elif media_type == 'video':
media_group.append(InputMediaVideo(media=file_id))
elif media_type == 'audio':
media_group.append(InputMediaAudio(media=file_id))
return media_group # Возвращаем MediaGroup
async def send_media_group_message(chat_id: int, message: types.Message, media_group: list[InputMediaPhoto]):
async def add_in_db_media_mediagroup(sent_message):
"""
Идентификатор медиа-группы
Args:
sent_message: sent_message объект из Telegram API
Returns:
Список InputFile (FSInputFile).
"""
media_group_message_id = sent_message[-1].message_id # Получаем идентификатор медиа-группы
for i, message in enumerate(sent_message):
if message.photo:
file_id = message.photo[-1].file_id
file_path = await download_file(message, file_id=file_id)
BotDB.add_post_content_in_db(media_group_message_id, message.message_id, file_path, 'photo')
elif message.video:
file_id = message.video.file_id
file_path = await download_file(message, file_id=file_id)
BotDB.add_post_content_in_db(media_group_message_id, message.message_id, file_path, 'video')
else:
# Если нет фото, видео или аудио, или другой контент, пропускаем сообщение
continue
async def add_in_db_media(sent_message):
"""
Args:
sent_message: sent_message объект из Telegram API
Returns:
Список InputFile (FSInputFile).
"""
if sent_message.photo:
file_id = sent_message.photo[-1].file_id
file_path = await download_file(sent_message, file_id=file_id)
BotDB.add_post_content_in_db(sent_message.message_id, sent_message.message_id, file_path, 'photo')
elif sent_message.video:
file_id = sent_message.video.file_id
file_path = await download_file(sent_message, file_id=file_id)
BotDB.add_post_content_in_db(sent_message.message_id, sent_message.message_id, file_path, 'video')
elif sent_message.voice:
file_id = sent_message.voice.file_id
file_path = await download_file(sent_message, file_id=file_id)
BotDB.add_post_content_in_db(sent_message.message_id, sent_message.message_id, file_path, 'voice')
elif sent_message.audio:
file_id = sent_message.audio.file_id
file_path = await download_file(sent_message, file_id=file_id)
BotDB.add_post_content_in_db(sent_message.message_id, sent_message.message_id, file_path, 'audio')
elif sent_message.video_note:
file_id = sent_message.video_note.file_id
file_path = await download_file(sent_message, file_id=file_id)
BotDB.add_post_content_in_db(sent_message.message_id, sent_message.message_id, file_path, 'video_note')
async def send_media_group_message_to_private_chat(chat_id: int, message: types.Message,
media_group: list[InputMediaPhoto]):
sent_message = await message.bot.send_media_group(
chat_id=chat_id,
media=media_group,
)
BotDB.add_post_in_db(sent_message[-1].message_id, sent_message[-1].caption, message.from_user.id)
await add_in_db_media_mediagroup(sent_message)
message_id = sent_message[-1].message_id
return message_id
async def send_media_group_to_channel(bot, chat_id: int, post_content: list[tuple[str]], post_text: str):
"""
Отправляет медиа-группу с подписью к последнему файлу.
Args:
bot: Экземпляр бота aiogram.
chat_id: ID чата для отправки.
post_content: Список кортежей с путями к файлам.
post_text: Текст подписи.
"""
media = []
for file_path in post_content:
try:
file = FSInputFile(path=file_path[0])
type = file_path[1]
if type == 'video':
media.append(types.InputMediaVideo(media=file))
if type == 'photo':
media.append(types.InputMediaPhoto(media=file))
except FileNotFoundError:
logger.error(f"Файл не найден: {file_path[0]}")
return
# Добавляем подпись к последнему файлу
if media:
media[-1].caption = post_text
await bot.send_media_group(chat_id=chat_id, media=media)
async def send_text_message(chat_id, message: types.Message, post_text: str, markup: types.ReplyKeyboardMarkup = None):
if markup is None:
sent_message = await message.bot.send_message(
@@ -84,20 +233,90 @@ async def send_text_message(chat_id, message: types.Message, post_text: str, mar
return message_id
async def send_photo_message(chat_id, message: types.Message, photo: str, post_text: str, markup: types.ReplyKeyboardMarkup = None):
async def send_photo_message(chat_id, message: types.Message, photo: str, post_text: str,
markup: types.ReplyKeyboardMarkup = None):
if markup is None:
await message.bot.send_photo(
sent_message = await message.bot.send_photo(
chat_id=chat_id,
caption=post_text,
photo=photo
)
else:
await message.bot.send_photo(
sent_message = await message.bot.send_photo(
chat_id=chat_id,
caption=post_text,
photo=photo,
reply_markup=markup
)
return sent_message
async def send_video_message(chat_id, message: types.Message, video: str, post_text: str = "",
markup: types.ReplyKeyboardMarkup = None):
if markup is None:
sent_message = await message.bot.send_video(
chat_id=chat_id,
caption=post_text,
video=video
)
else:
sent_message = await message.bot.send_video(
chat_id=chat_id,
caption=post_text,
video=video,
reply_markup=markup
)
return sent_message
async def send_video_note_message(chat_id, message: types.Message, video_note: str,
markup: types.ReplyKeyboardMarkup = None):
if markup is None:
sent_message = await message.bot.send_video_note(
chat_id=chat_id,
video_note=video_note
)
else:
sent_message = await message.bot.send_video_note(
chat_id=chat_id,
video_note=video_note,
reply_markup=markup
)
return sent_message
async def send_audio_message(chat_id, message: types.Message, audio: str, post_text: str,
markup: types.ReplyKeyboardMarkup = None):
if markup is None:
sent_message = await message.bot.send_audio(
chat_id=chat_id,
caption=post_text,
audio=audio
)
else:
sent_message = await message.bot.send_audio(
chat_id=chat_id,
caption=post_text,
audio=audio,
reply_markup=markup
)
return sent_message
async def send_voice_message(chat_id, message: types.Message, voice: str,
markup: types.ReplyKeyboardMarkup = None):
if markup is None:
sent_message = await message.bot.send_voice(
chat_id=chat_id,
voice=voice
)
else:
sent_message = await message.bot.send_voice(
chat_id=chat_id,
voice=voice,
reply_markup=markup
)
return sent_message
def check_access(user_id: int):
@@ -153,37 +372,18 @@ def get_banned_users_buttons():
return user_ids
def get_help_message_id(media_group_message_id: int, data: dict) -> int:
"""
Получает идентификатор сообщения помощи по идентификатору сообщения группы.
Args:
media_group_message_id: Идентификатор сообщения группы
data: Словарь с данными.
Returns:
Идентификатор сообщения помощи.
"""
if 'help_message_id' in data and 'media_group_message_id' in data:
return data['media_group_message_id']
else:
return 0
def delete_user_blacklist(user_id: int):
return BotDB.delete_user_blacklist(user_id=user_id)
def check_username_and_full_name(user_id: int, username: str, full_name: str):
username_db, full_name_db = BotDB.get_username_and_full_name(user_id=user_id)
return not username == username_db and full_name == full_name_db
return username != username_db or full_name != full_name_db
def unban_notifier(self):
# Получение сегодняшней даты в формате DD-MM-YYYY
current_date = datetime.now()
print('Мы в функции unban_notifier')
today = current_date.strftime("%d-%m-%Y")
# Получение списка разблокированных пользователей
unblocked_users = self.BotDB.get_users_for_unblock_today(today)
@@ -193,3 +393,52 @@ def unban_notifier(self):
# Отправка сообщения в канал
self.bot.send_message(self.GROUP_FOR_MESSAGE, message)
async def update_user_info(source: str, message: types.Message):
# Собираем данные
full_name = message.from_user.full_name
username = message.from_user.username
first_name = get_first_name(message)
is_bot = message.from_user.is_bot
language_code = message.from_user.language_code
user_id = message.from_user.id
current_date = datetime.now()
date = current_date.strftime("%Y-%m-%d %H:%M:%S")
# Выбираем эмодзю, пробегаемся циклом и смотрим что в базе такого еще не было
user_emoji = get_random_emoji()
if not BotDB.user_exists(user_id):
BotDB.add_new_user_in_db(user_id, first_name, full_name, username, is_bot, language_code, user_emoji, date,
date)
else:
is_need_update = check_username_and_full_name(user_id, username, full_name)
if is_need_update:
BotDB.update_username_and_full_name(user_id, username, full_name)
if source != 'voice':
await message.answer(
f"Давно не виделись! Вижу что ты изменился;) Теперь буду звать тебя: {full_name}")
await message.bot.send_message(chat_id=GROUP_FOR_LOGS,
text=f'Для пользователя: {user_id} обновлены данные в БД.\nНовое имя: {full_name}\nНовый ник:{username}. Новый эмодзи:{user_emoji}')
sleep(1)
BotDB.update_date_for_user(date, user_id)
def check_user_emoji(message: types.Message):
user_id = message.from_user.id
user_emoji = BotDB.check_emoji_for_user(user_id=user_id)
if user_emoji is None:
user_emoji = get_random_emoji()
BotDB.update_emoji_for_user(user_id=user_id, emoji=user_emoji)
return user_emoji
def get_random_emoji():
attempts = 0
while attempts < 100:
user_emoji = random.choice(emoji_list)
if not BotDB.check_emoji(user_emoji):
return user_emoji
attempts += 1
logger.error("Не удалось найти уникальный эмодзи после нескольких попыток.")
return "Эмоджи не определен"

View File

@@ -1,5 +1,3 @@
def get_message(username: str, type_message: str):
constants = {
'HELLO_MESSAGE': "Привет, username!👋🏼&Меня зовут Виби, я бот канала 'Влюбленный Бийск'❤🤖"
@@ -25,7 +23,7 @@ def get_message(username: str, type_message: str):
"&Мы рассмотрим и ответим тебе в ближайшее время☺️❤️",
"DEL_MESSAGE": "username, напиши свое обращение или предложение✍"
"&Мы рассмотрим и ответим тебе в ближайшее время☺❤",
"BYE_MESSAGE": "Если позднее захочешь предложить еще один пост или обратиться к админам с вопросом, то просто пришли в чат команду 👉 /start"
"BYE_MESSAGE": "Если позднее захочешь предложить еще один пост или обратиться к админам с вопросом, то просто пришли в чат команду 👉 /restart"
"&&И тебе пока!👋🏼❤️",
"USER_ERROR": "Увы, я не понимаю тебя😐💔 Выбери один из пунктов в нижнем меню, а затем пиши.",
"QUESTION": "Сообщение успешно отправлено❤️ Ответим, как только сможем😉",

View File

@@ -7,6 +7,7 @@ class StateUser(StatesGroup):
ADMIN = State()
CHAT = State()
PRE_CHAT = State()
PRE_BAN = State()
BAN_2 = State()
BAN_3 = State()
BAN_4 = State()

View File

@@ -1,45 +1,24 @@
import datetime
import os
import loguru
from loguru import logger
class Logger:
def __init__(self, name):
self.logger = loguru.logger.bind(name=name)
logger = logger.bind(name='main_log')
# Получение сегодняшней даты для имени файла
today = datetime.date.today().strftime('%Y-%m-%d')
# Получение сегодняшней даты для имени файла
today = datetime.date.today().strftime('%Y-%m-%d')
# Создание папки для логов
current_dir = os.path.dirname(os.path.abspath(__file__))
if not os.path.exists(current_dir):
# Создание папки для логов
current_dir = os.path.dirname(os.path.abspath(__file__))
if not os.path.exists(current_dir):
# Если не существует, создаем ее
os.makedirs(current_dir)
filename = f'{current_dir}/helper_bot_{today}.log'
filename = f'{current_dir}/helper_bot_{today}.log'
# Настройка формата логов
self.logger.add(
# Настройка формата логов
logger.add(
filename,
rotation="00:00",
retention="5 days",
compression="zip",
format="{time:YYYY-MM-DD at HH:mm:ss} | {level} | {name} | {line} | {message}",
)
def get_logger(self):
return self.logger
def info(self, message):
self.logger.info(message)
def debug(self, message):
self.logger.debug(message)
def warning(self, message):
self.logger.warning(message)
def error(self, message):
self.logger.error(message)
def critical(self, message):
self.logger.critical(message)
)

View File

@@ -1,16 +1,14 @@
import os
from database.db import BotDB
# Получаем текущий рабочий каталог
current_dir = os.path.dirname(os.path.abspath(__file__))
# Получаем текущую директорию
current_dir = os.path.dirname(__file__)
# Переходим на уровень выше, чтобы выйти из папки migrations/
# Переходим на уровень выше
parent_dir = os.path.dirname(current_dir)
# Строим путь до файла
tg_bot_database_path = os.path.join(parent_dir, "tg-bot-database")
BotDB = BotDB(f'{tg_bot_database_path}')
BotDB = BotDB(parent_dir, 'database/tg-bot-database')
def get_filename():
@@ -31,5 +29,6 @@ def main():
BotDB.create_table(migrations_init)
BotDB.update_version(0, get_filename())
if __name__ == "__main__":
main()

View File

@@ -1,7 +1,14 @@
import os
from database.db import BotDB
BotDB = BotDB('tg-bot-database')
# Получаем текущую директорию
current_dir = os.path.dirname(__file__)
# Переходим на уровень выше
parent_dir = os.path.dirname(current_dir)
BotDB = BotDB(parent_dir, 'database/tg-bot-database')
def get_filename():

View File

@@ -0,0 +1,61 @@
import os
from database.db import BotDB
# Получаем текущую директорию
current_dir = os.path.dirname(__file__)
# Переходим на уровень выше
parent_dir = os.path.dirname(current_dir)
BotDB = BotDB(parent_dir, 'database/tg-bot-database')
def get_filename():
"""Возвращает имя файла без расширения."""
filename = os.path.basename(__file__)
filename = os.path.splitext(filename)[0]
return filename
def main():
# Проверка версии миграций
current_version = BotDB.get_current_version() # Добавьте функцию для получения версии
# Выполнение миграций и проверка последней версии
if current_version < 2:
# Скрипты миграции
create_table_sql_1 = """
CREATE TABLE IF NOT EXISTS "post_from_telegram_suggest"
(
message_id INTEGER not null,
text TEXT,
helper_text_message_id INTEGER,
author_id INTEGER,
created_at TEXT
);
"""
create_table_sql_2 = """
CREATE TABLE IF NOT EXISTS message_link_to_content (
post_id INTEGER NOT NULL,
message_id INTEGER NOT NULL
);
"""
create_table_sql_3 = """
CREATE TABLE IF NOT EXISTS content_post_from_telegram (
message_id INTEGER NOT NULL,
content_name TEXT NOT NULL,
content_type TEXT
);
"""
# Применение миграции
BotDB.create_table(create_table_sql_1)
BotDB.create_table(create_table_sql_2)
BotDB.create_table(create_table_sql_3)
filename = get_filename()
BotDB.update_version(2, filename)
if __name__ == "__main__":
main()

View File

@@ -20,3 +20,4 @@ attrs~=23.2.0
typing_extensions~=4.12.2
aiohttp~=3.9.5
aiogram~=3.10.0
emoji~=2.14.0

View File

@@ -1,7 +1,7 @@
import asyncio
from helper_bot.main import start_bot
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
if __name__ == '__main__':
asyncio.run(start_bot(BaseDependencyFactory()))

View File

@@ -1,13 +1,17 @@
from datetime import datetime
import os
import sqlite3
from datetime import datetime
import pytest
from database.db import BotDB
@pytest.fixture
def bot():
"""Фикстура для создания объекта BotDB."""
return BotDB("test.db")
current_dir = os.getcwd()
return BotDB(current_dir, "test.db")
@pytest.fixture(autouse=True, )
@@ -104,12 +108,12 @@ def setup_db():
);
""")
#blacklist mock data
# blacklist mock data
cursor.execute("INSERT INTO blacklist (user_id, user_name, message_for_user, date_to_unban) VALUES (?, ?, ?, ?)",
(user_id, username, message_for_user, next_date))
cursor.execute("INSERT INTO blacklist (user_id, user_name, message_for_user, date_to_unban) VALUES (?, ?, ?, ?)",
(user_id_2, username_2, message_for_user_2, date))
#our_users mock data
# our_users mock data
cursor.execute(
"INSERT INTO our_users (user_id, first_name, full_name, username, date_added, date_changed, has_stickers)"
" VALUES (?, ?, ?, ?, ?, ?, ?)", (user_id, first_name, full_name, username, date, date, has_stickers)
@@ -118,7 +122,7 @@ def setup_db():
"INSERT INTO our_users (user_id, first_name, full_name, username, date_added, date_changed, has_stickers)"
" VALUES (?, ?, ?, ?, ?, ?, ?)", (user_id_2, first_name_2, full_name_2, username_2, date, date, has_stickers_2)
)
#messages mock data
# messages mock data
cursor.execute(
"INSERT INTO user_messages (message_text, user_id, message_id, date) "
"VALUES (?, ?, ?, ?)",
@@ -127,7 +131,7 @@ def setup_db():
"INSERT INTO user_messages (message_text, user_id, message_id, date) "
"VALUES (?, ?, ?, ?)",
(message_text_2, user_id_2, message_id_2, date))
#mock admins
# mock admins
cursor.execute(
"INSERT INTO admins (user_id, role) "
"VALUES (?, ?)",
@@ -248,12 +252,13 @@ def test_add_new_user_in_db(bot):
username = "@petr_ivanov"
is_bot = False
language_code = "ru"
emoji = '🦀'
date_added = "2024-07-09"
date_changed = "2024-07-09"
# Вызываем функцию add_new_user_in_db
bot.add_new_user_in_db(
user_id, first_name, full_name, username, is_bot, language_code, date_added, date_changed
user_id, first_name, full_name, username, is_bot, language_code, emoji, date_added, date_changed
)
# Проверяем наличие записи в базе данных
@@ -281,7 +286,7 @@ def test_add_new_user_in_db_duplicate_user_id(bot, setup_db):
# Попытка добавить пользователя с тем же user_id
with pytest.raises(sqlite3.IntegrityError):
bot.add_new_user_in_db(
user_id, "Марина", "Марина Альфредовна", "marina", False, "bg", "2024-07-09", "2024-07-09"
user_id, "Марина", "Марина Альфредовна", "marina", False, "bg", "🦀", "2024-07-09", "2024-07-09"
)
@@ -293,12 +298,13 @@ def test_add_new_user_in_db_empty_first_name(bot):
username = "@boris"
is_bot = False
language_code = "fr"
emoji = "🦀"
date_added = "2024-07-09"
date_changed = "2024-07-09"
# Вызываем функцию add_new_user_in_db
bot.add_new_user_in_db(
user_id, first_name, full_name, username, is_bot, language_code, date_added, date_changed
user_id, first_name, full_name, username, is_bot, language_code, emoji, date_added, date_changed
)
# Проверяем наличие записи в базе данных

View File

@@ -1,315 +0,0 @@
import configparser
import os
import sys
from pathlib import Path
from time import sleep
from database.db import BotDB
import telebot
import random
from datetime import datetime
import time
from telebot import types
#Настройки
config_path = os.path.join(sys.path[0], 'settings.ini')
config = configparser.ConfigParser()
config.read(config_path)
#TELEGRAM
BOT_TOKEN = config.get('Telegram', 'listen_bot_token')
GROUP_FOR_POST = config.get('Telegram', 'group_for_posts')
GROUP_FOR_MESSAGE = config.get('Telegram', 'group_for_message')
MAIN_PUBLIC = config.get('Telegram', 'main_public')
GROUP_FOR_LOGS = config.get('Telegram', 'group_for_logs')
IMPORTANT_LOGS = config.get('Telegram', 'important_logs')
PREVIEW_LINK = config.getboolean('Telegram', 'PREVIEW_LINK')
#SETTINGS
LOGS = config.getboolean('Settings', 'logs')
TEST = config.getboolean('Settings', 'test')
#Инициализируем бота и базку
bot = telebot.TeleBot(BOT_TOKEN, parse_mode=None)
BotDB = BotDB('database/tg-bot-database')
def telegram_bot():
@bot.message_handler(commands=['start'])
def send_welcome(message):
try:
name_stick_hello = list(Path('Stick').rglob('Hello_*'))
number_stick_hello = random.randint(1, len(name_stick_hello))
random_stick_hello = open(name_stick_hello[number_stick_hello], 'rb')
#logging
if LOGS:
bot.forward_message(chat_id=GROUP_FOR_LOGS,
from_chat_id=message.chat.id,
message_id=message.message_id)
bot.send_sticker(message.chat.id, random_stick_hello)
sleep(0.3)
except:
if LOGS:
bot.send_message(IMPORTANT_LOGS, BotDB.get_error_message_from_db(7))
markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
item1 = types.KeyboardButton("🎤Высказаться")
item2 = types.KeyboardButton("🎧Послушать")
markup.add(item1, item2)
bot.send_message(message.chat.id, "<b>Привет.</b>", parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(0.3)
bot.send_message(message.chat.id, "<i>Здесь можно послушать голосовые сообщения от совершенно незнакомых людей из Бийска</i>", parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(1)
bot.send_message(message.chat.id, "Это почти как написать письмо, положить его в бутылку и швырнуть в океан. Никогда не узнаешь, послушал его кто-то или нет и ответить тоже не получится..", parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(0.8)
bot.send_message(message.chat.id, "Записывать можно всё что угодно — никаких правил нет. Главное — твой голос, <i>хотя бы на 5-10 секунд</i>", parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(1.5)
bot.send_message(message.chat.id, "Здесь всё анонимно: тот, кому я отправлю твое сообщение, не узнает ни твое имя, ни твой аккаунт (так что можно не стесняться говорить то, что не стал(а) бы выкладывать в собственные соцсети)", parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(1.3)
bot.send_message(message.chat.id, "Если не знаешь, что сказать, можешь просто прочитать любое текстовое сообщение из недавно полученных или отправленных (или спеть, рассказать стихотворенье)", parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(0.8)
bot.send_message(message.chat.id,
"Так же можешь ознакомиться с инструкцией к боту по команде /help",
parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(0.8)
msg = bot.send_message(message.chat.id, "<b>ну всё, достаточно инструкций. записывайся! Микрофон твой - </b> 🎤", parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
bot.register_next_step_handler(msg, standup)
def last_message():
# функция с отображением сообщения "Последнее сообщение было записано"
date_from_db = BotDB.last_date_audio()
parse_date = datetime.strptime(date_from_db, "%Y-%m-%d %H:%M:%S")
last_voice_time_timestamp = time.mktime(parse_date.timetuple())
time_now_timestamp = time.time()
date_difference = time_now_timestamp - last_voice_time_timestamp
# считаем минуты, часы, дни
much_minutes_ago = round(date_difference / 60, 0)
much_hour_ago = round(date_difference / 3600, 0)
much_days_ago = int(round(much_hour_ago / 24, 0))
message_with_date = ''
if much_minutes_ago <= 60:
word_minute = plural_time(1, much_minutes_ago)
message_with_date = f'<b>Последнее сообщение было записано {word_minute} назад</b>'
elif much_minutes_ago > 60 and much_hour_ago <= 24:
word_hour = plural_time(2, much_hour_ago)
message_with_date = f'<b>Последнее сообщение было записано {word_hour} назад</b>'
elif much_hour_ago > 24:
word_day = plural_time(3, much_days_ago)
message_with_date = f'<b>Последнее сообщение было записано {word_day} назад</b>'
return message_with_date
def standup(message):
# Клавиатуру добавляем
markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
item1 = types.KeyboardButton("🎤Высказаться")
item2 = types.KeyboardButton("🎧Послушать")
markup.add(item1, item2)
try:
if message.text == '🎤Высказаться':
markup = types.ReplyKeyboardRemove()
if LOGS:
# logging
bot.forward_message(chat_id=GROUP_FOR_LOGS,
from_chat_id=message.chat.id,
message_id=message.message_id)
if TEST:
bot.forward_message(chat_id=GROUP_FOR_LOGS, from_chat_id=message.chat.id, message_id=message.id)
bot.send_message(chat_id=message.chat.id, text='Хорошо, теперь пришли мне свое голосовое сообщение', reply_markup=markup)
message_with_date = last_message()
msg = bot.send_message(chat_id=message.chat.id, text=message_with_date, parse_mode="html")
bot.register_next_step_handler(msg, save_voice_message)
elif message.text == '🎧Послушать':
check_audio = BotDB.check_listen_audio(user_id=message.from_user.id)
list_audio = list(check_audio)
if TEST:
bot.forward_message(chat_id=GROUP_FOR_LOGS, from_chat_id=message.chat.id, message_id=message.id)
if list_audio == []:
bot.send_message(message.chat.id, 'Прости, ты прослушал все аудио😔. Возвращайся позже, возможно наша база пополнится', reply_markup=markup)
message_with_date = last_message()
msg = bot.send_message(chat_id=message.chat.id, text=message_with_date, parse_mode="html")
bot.register_next_step_handler(msg, standup)
else:
number_element = random.randint(0, len(list_audio) - 1)
audio_for_user = check_audio[number_element]
path = Path(f'voice_users/{audio_for_user}.ogg')
voice = open(path, 'rb')
#Маркируем сообщение как прослушанное
BotDB.mark_listened_audio(audio_for_user, user_id=message.from_user.id)
msg = bot.send_voice(message.chat.id, voice=voice, reply_markup=markup)
bot.register_next_step_handler(msg, standup)
if LOGS:
# logging
bot.forward_message(chat_id=GROUP_FOR_LOGS,
from_chat_id=message.chat.id,
message_id=message.message_id)
if TEST:
bot.forward_message(chat_id=GROUP_FOR_LOGS, from_chat_id=message.chat.id, message_id=message.id)
elif message.text == '/restart':
msg = bot.send_message(message.chat.id, 'Я перезапущен, и готов к работе🥳', reply_markup=markup)
bot.forward_message(chat_id=GROUP_FOR_LOGS,
from_chat_id=message.chat.id,
message_id=message.message_id)
bot.register_next_step_handler(msg, standup)
elif message.text == '/help':
help_function(message)
else:
msg = bot.send_message(chat_id=message.chat.id, text='Я тебя не понял, воспользуйся меню', reply_markup=markup)
bot.register_next_step_handler(msg, standup)
except Exception as e:
msg = bot.send_message(chat_id=message.chat.id, text='Я не могу прислать тебе голосовое, потому что они скрыты у тебя в настройках. Открой для меня голосовые и возвращайся❤️', reply_markup=markup)
bot.register_next_step_handler(msg, standup)
def plural_time(type, n):
word = []
if type == 1:
word = ['минуту', 'минуты', 'минут']
elif type == 2:
word = ['час', 'часа', 'часов']
elif type == 3:
word = ['день', 'дня', 'дней']
else:
pass
if n % 10 == 1 and n % 100 != 11:
p = 0
elif 2 <= n % 10 <= 4 and (n % 100 < 10 or n % 100 >= 20):
p = 1
else:
p = 2
new_number = int(n)
return str(new_number) + ' ' + word[p]
def save_voice_message(message):
if message.content_type == 'voice':
if TEST:
bot.forward_message(chat_id=GROUP_FOR_LOGS, from_chat_id=message.chat.id, message_id=message.id)
file_name = ''
file_id = 1
#Проверяем что запись о файле есть в базе данных
is_having_audio_from_user = BotDB.get_last_user_audio_record(user_id=message.from_user.id)
if is_having_audio_from_user is False:
#Если нет, то генерируем имя файла
file_name = f'message_from_{message.from_user.id}_number_{file_id}'
else:
#Иначе берем последнюю запись из БД, добавляем к ней 1, и создаем новую запись
file_name = BotDB.get_path_for_audio_record(user_id=message.from_user.id)
file_id = BotDB.get_id_for_audio_record(message.from_user.id) + 1
path = Path(f'voice_users/{file_name}.ogg')
if path.exists():
file_name = f'message_from_{message.from_user.id}_number_{file_id}'
else:
pass
#Собираем инфо о сообщении
author_id = message.from_user.id
time_UTC = int(time.time())
date_added = datetime.fromtimestamp(time_UTC)
#Сохраняем в базку
BotDB.add_audio_record(file_name, author_id, date_added, 0, file_id)
#Сохраняем файл на сервер
file_info = bot.get_file(message.voice.file_id)
downloaded_file = bot.download_file(file_info.file_path)
with open(f'voice_users/{file_name}.ogg', 'wb') as new_file:
new_file.write(downloaded_file)
#инициализируем кнопки
markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
item1 = types.KeyboardButton("🎤Высказаться")
item2 = types.KeyboardButton("🎧Послушать")
markup.add(item1, item2)
bot.send_message(chat_id=message.chat.id, text='Окей, сохранил!👌', reply_markup=markup)
#menu_standup(message=message)
bot.register_next_step_handler(message, standup)
else:
#TODO: Если пришлют фото, он не работает
if TEST:
bot.forward_message(chat_id=GROUP_FOR_LOGS, from_chat_id=message.chat.id, message_id=message.id)
markup = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
item1 = types.KeyboardButton("🎤Высказаться")
item2 = types.KeyboardButton("🎧Послушать")
markup.add(item1, item2)
msg = bot.send_message(chat_id=message.chat.id, text='Я тебя не понимаю🤷‍♀️ запиши голосовое', reply_markup=markup)
bot.register_next_step_handler(msg, standup)
@bot.message_handler(commands=['restart'])
def restart_function(message):
return standup(message)
@bot.message_handler(commands=['help'])
def help_function(message):
msg = bot.send_message(chat_id=message.chat.id, text='Скорее всего ответы на твои вопросы есть здесь, ознакомься: https://telegra.ph/Instrukciya-k-botu-Golosa-Bijsk-10-11-2'
'\nЕсли это не поможет, пиши в тг: @Kerrad1',disable_web_page_preview=not PREVIEW_LINK)
bot.register_next_step_handler(msg, standup)
@bot.message_handler(commands=['send'])
def notify(message):
"""Функция для рассылки сообщений пользователям бота"""
admins = [842766148]
command_sender = message.from_user.id
if command_sender in admins:
markup = types.InlineKeyboardMarkup(row_width=1)
button = types.InlineKeyboardButton(text='Я прочитал ', callback_data='from_user')
success_send_message = 0
error_send_message = 0
markup.add(button)
user_ids = BotDB.get_all_user_id()
# Парсим список id юзеров для рассылки и рассылаем сообщения
for i in user_ids:
username = BotDB.get_username(i)
try:
bot.send_message(chat_id=i,
text='Привет, на связи админ. Первая тестовая рассылка через этого бота, не суди строго, обещаю не злоупотреблять этим))\n'
'Собственно хотел сказать следующее, сегодня ночью обновил бота, добавил ему две функции /restart и /help. '
'Рекомендую ознакомиться со статьей в /help, там я подробно описал как сейчас все работает. '
'Если у тебя будут предложения по доработке бота или новому функционал, пиши не стесняйся @Kerrad1. '
'Так же прошу нажать на кнопку под сообщением, чтобы я понял что ты прочитал сообщение❤️\n\nНа этом у меня все, пока, до следующего релиза', reply_markup=markup)
bot.send_message(chat_id=message.chat.id,
text=f'Успешно отправлено - @{username}')
success_send_message += 1
except Exception as e:
bot.send_message(chat_id=message.chat.id,
text=f'Этому юзеру не отправилось - @{username}')
error_send_message += 1
bot.send_message(chat_id=message.chat.id,
text=f'<b>Количество успешных отправок</b> - {success_send_message}', parse_mode='html')
bot.send_message(chat_id=message.chat.id,
text=f'<b>Количество неуспешных отправок</b> - {error_send_message}', parse_mode='html')
standup(message)
else:
bot.send_message(command_sender, f'у вас нет прав для запуска команды')
bot.forward_message(chat_id=GROUP_FOR_LOGS, from_chat_id=message.chat.id, message_id=message.id)
standup(message)
@bot.callback_query_handler(func=lambda call: True)
def post_for_group(call):
if call.data == 'from_user' and call.message.content_type == 'text':
try:
command_sender = call.message.from_user.id
bot.answer_callback_query(call.id, text="Мне приятно, спасибо ❤")
#Попробовать варианты если не сработает call.from_user.username
bot.send_message(chat_id=842766148, text=f'Юзер с ником @{call.message.chat.username} по имени {call.message.chat.first_name} прочитал сообщение')
except:
print('что-то не так')
if __name__ == '__main__':
telegram_bot()
while True:
try:
bot.polling(none_stop=True)
bot.enable_save_next_step_handlers(delay=2)
bot.load_next_step_handlers()
except ConnectionError as e:
if LOGS:
bot.send_message(IMPORTANT_LOGS, "Ошибка соединения, потерял войс бот связь")
except Exception as r:
if LOGS:
bot.send_message(IMPORTANT_LOGS, "Произошло что-то непредвиденное, хелп. Войс бот болеет")

0
voice_bot/__init__.py Normal file
View File

View File

View File

@@ -0,0 +1,68 @@
import time
from datetime import datetime
from pathlib import Path
from aiogram import Router, F
from aiogram.types import CallbackQuery
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
callback_router = Router()
bdf = BaseDependencyFactory()
GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs']
GROUP_FOR_POST = bdf.settings['Telegram']['group_for_posts']
IMPORTANT_LOGS = bdf.settings['Telegram']['important_logs']
PREVIEW_LINK = bdf.settings['Telegram']['preview_link']
LOGS = bdf.settings['Settings']['logs']
TEST = bdf.settings['Settings']['test']
BotDB = bdf.get_db()
@callback_router.callback_query(
F.data == "save"
)
async def save_voice_message(call: CallbackQuery):
file_name = ''
file_id = 1
user_id = BotDB.get_user_id_by_message_id_for_voice_bot(call.message.message_id)
# Проверяем что запись о файле есть в базе данных
is_having_audio_from_user = BotDB.get_last_user_audio_record(user_id=user_id)
if is_having_audio_from_user is False:
# Если нет, то генерируем имя файла
file_name = f'message_from_{user_id}_number_{file_id}'
else:
# Иначе берем последнюю запись из БД, добавляем к ней 1, и создаем новую запись
file_name = BotDB.get_path_for_audio_record(user_id=user_id)
file_id = BotDB.get_id_for_audio_record(user_id) + 1
path = Path(f'voice_users/{file_name}.ogg')
if path.exists():
file_name = f'message_from_{user_id}_number_{file_id}'
else:
pass
# Собираем инфо о сообщении
time_UTC = int(time.time())
date_added = datetime.fromtimestamp(time_UTC)
# Сохраняем в базку
BotDB.add_audio_record(file_name, user_id, date_added, 0, file_id)
file_info = await call.message.bot.get_file(file_id=call.message.voice.file_id)
downloaded_file = await call.message.bot.download_file(file_path=file_info.file_path)
with open(f'voice_users/{file_name}.ogg', 'wb') as new_file:
new_file.write(downloaded_file.read())
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
await call.answer(text='Сохранено!', cache_time=3)
@callback_router.callback_query(
F.data == "delete"
)
async def delete_voice_message(call: CallbackQuery):
# Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки
await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id)
await call.answer(text='Удалено!', cache_time=3)

View File

@@ -0,0 +1,235 @@
import random
import time
from pathlib import Path
from aiogram import Router, types, F
from aiogram.filters import Command, StateFilter
from aiogram.fsm.context import FSMContext
from aiogram.types import FSInputFile
from helper_bot.filters.main import ChatTypeFilter
from helper_bot.middlewares.blacklist_middleware import BlacklistMiddleware
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
from helper_bot.utils.helper_func import update_user_info, check_user_emoji, send_voice_message
from logs.custom_logger import logger
from voice_bot.keyboards.keyboards import get_main_keyboard, get_reply_keyboard_for_voice
from voice_bot.utils.helper_func import last_message
voice_router = Router()
bdf = BaseDependencyFactory()
GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs']
GROUP_FOR_POST = bdf.settings['Telegram']['group_for_posts']
IMPORTANT_LOGS = bdf.settings['Telegram']['important_logs']
PREVIEW_LINK = bdf.settings['Telegram']['preview_link']
LOGS = bdf.settings['Settings']['logs']
TEST = bdf.settings['Settings']['test']
BotDB = bdf.get_db()
voice_router.message.middleware(BlacklistMiddleware())
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command("restart")
)
async def restart_function(message: types.Message, state: FSMContext):
await message.forward(chat_id=GROUP_FOR_LOGS)
await update_user_info('voice', message)
check_user_emoji(message)
markup = get_main_keyboard()
await message.answer(text='Я перезапущен!',
reply_markup=markup)
await state.set_state('START')
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command("emoji")
)
async def handle_emoji_message(message: types.Message, state: FSMContext):
await message.forward(chat_id=GROUP_FOR_LOGS)
user_emoji = check_user_emoji(message)
await state.set_state("START")
if user_emoji is not None:
await message.answer(f'Твоя эмодзя - {user_emoji}', parse_mode='HTML')
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command("help")
)
async def help_function(message: types.Message, state: FSMContext):
await message.forward(chat_id=GROUP_FOR_LOGS)
await update_user_info('voice', message)
await message.answer(
text='Скорее всего ответы на твои вопросы есть здесь, ознакомься: https://telegra.ph/Instrukciya-k-botu-Golosa-Bijsk-10-11-2'
'\nЕсли это не поможет, пиши в личку: @Kerrad1', disable_web_page_preview=not PREVIEW_LINK)
await state.set_state('START')
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command("start")
)
async def start(message: types.Message, state: FSMContext):
await state.set_state("START")
await message.forward(chat_id=GROUP_FOR_LOGS)
await update_user_info('voice', message)
user_emoji = check_user_emoji(message)
try:
name_stick_hello = list(Path('Stick').rglob('Hello_*'))
random_stick_hello = random.choice(name_stick_hello)
random_stick_hello = FSInputFile(path=random_stick_hello)
logger.info(f"Стикер успешно получен из БД. Наименование стикера: {name_stick_hello}")
await message.answer_sticker(random_stick_hello)
time.sleep(0.3)
except Exception as e:
if LOGS:
await message.bot.send_message(IMPORTANT_LOGS, f'Отправка приветственных стикеров лажает. Ошибка: {e}')
markup = get_main_keyboard()
await message.answer(text="<b>Привет.</b>", parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(0.3)
await message.answer(text="<i>Здесь можно послушать голосовые сообщения от совершенно незнакомых людей из "
"Бийска</i>",
parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(1)
await message.answer(text="Это почти как написать письмо, положить его в бутылку и швырнуть в океан. Никогда не "
"узнаешь, послушал его кто-то или нет и ответить тоже не получится..",
parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(0.8)
await message.answer(text="Записывать можно всё что угодно — никаких правил нет. Главное — твой голос, <i>хотя "
"бы на 5-10 секунд</i>",
parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(1.5)
await message.answer(text="Здесь всё анонимно: тот, кому я отправлю твое сообщение, не узнает ни твое имя, "
"ни твой аккаунт (так что можно не стесняться говорить то, что не стал(а) бы "
"выкладывать в собственные соцсети)",
parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(1.3)
await message.answer(text="Если не знаешь, что сказать, можешь просто прочитать любое текстовое сообщение из "
"недавно полученных или отправленных (или спеть, рассказать стихотворенье)",
parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(0.8)
await message.answer(text=f"Любые войсы будут помечены эмоджи. <b>Твой эмоджи - </b>{user_emoji}"
f"Таким эмоджи будут помечены твои сообщения для других "
f"Но другие люди не узнают кто за каким эмоджи скрывается:)",
parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(0.8)
await message.answer(text="Так же можешь ознакомиться с инструкцией к боту по команде /help",
parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
time.sleep(0.8)
await message.answer(text="<b>Ну всё, достаточно инструкций. записывайся! Микрофон твой - </b> 🎤",
parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK)
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command("refresh")
)
async def refresh_listen_function(message: types.Message, state: FSMContext):
await message.forward(chat_id=GROUP_FOR_LOGS)
await update_user_info('voice', message)
markup = get_main_keyboard()
BotDB.delete_listen_count_for_user(message.from_user.id)
await message.answer(
text='Прослушивания очищены. Можешь начать слушать заново🤗', disable_web_page_preview=not PREVIEW_LINK,
markup=markup)
await state.set_state('START')
@voice_router.message(
StateFilter("START"),
ChatTypeFilter(chat_type=["private"]),
F.text == '🎤Высказаться'
)
async def standup_write(message: types.Message, state: FSMContext):
await message.forward(chat_id=GROUP_FOR_LOGS)
markup = types.ReplyKeyboardRemove()
await message.answer(text='Хорошо, теперь пришли мне свое голосовое сообщение', reply_markup=markup)
try:
message_with_date = last_message()
await message.answer(text=message_with_date, parse_mode="html")
except Exception as e:
logger.error(f'Не удалось получить дату последнего сообщения - {e}')
await state.set_state('STANDUP_WRITE')
@voice_router.message(
StateFilter("STANDUP_WRITE"),
ChatTypeFilter(chat_type=["private"]),
)
async def suggest_voice(message: types.Message, state: FSMContext):
logger.info(
f"Вызов функции suggest_voice. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
await message.forward(chat_id=GROUP_FOR_LOGS)
markup = get_main_keyboard()
if message.content_type == 'voice':
markup_for_voice = get_reply_keyboard_for_voice()
# Отправляем аудио в приватный канал
sent_message = await send_voice_message(GROUP_FOR_POST, message,
message.voice.file_id, markup_for_voice)
# Сохраняем в базу инфо о посте
BotDB.set_user_id_and_message_id_for_voice_bot(sent_message.message_id, message.from_user.id)
# Отправляем юзеру ответ и возвращаем его в меню
await message.answer(text='Окей, сохранил!👌', reply_markup=markup)
await state.set_state('START')
else:
# TODO: Если пришлют фото, он не работает
await message.forward(chat_id=GROUP_FOR_LOGS)
await message.answer(text='Я тебя не понимаю🤷‍♀️ запиши голосовое', reply_markup=markup)
await state.set_state('STANDUP_WRITE')
@voice_router.message(
StateFilter("START"),
ChatTypeFilter(chat_type=["private"]),
F.text == '🎧Послушать'
)
async def standup_listen_audio(message: types.Message):
check_audio = BotDB.check_listen_audio(user_id=message.from_user.id)
list_audio = list(check_audio)
markup = get_main_keyboard()
if not list_audio:
await message.answer(text='Прости, ты прослушал все аудио😔. Возвращайся позже, возможно наша база пополнится',
reply_markup=markup)
try:
message_with_date = last_message()
await message.answer(text=message_with_date, parse_mode="html")
except Exception as e:
logger.error(f'Не удалось получить последнюю дату {e}')
else:
# Получаем ссылку на аудио сообщение пользователя
number_element = random.randint(0, len(list_audio) - 1)
audio_for_user = check_audio[number_element]
# Получаем автора записи + эмодзи по нему
user_id = BotDB.get_user_id_by_file_name(audio_for_user)
date_added = BotDB.get_date_by_file_name(audio_for_user)
user_emoji = BotDB.check_emoji_for_user(user_id)
path = Path(f'voice_users/{audio_for_user}.ogg')
voice = FSInputFile(path)
# Маркируем сообщение как прослушанное
BotDB.mark_listened_audio(audio_for_user, user_id=message.from_user.id)
# Формируем подпись
if user_emoji:
caption = f'{user_emoji}\nДата записи: {date_added}'
else:
caption = f'Дата записи: {date_added}'
await message.bot.send_voice(chat_id=message.chat.id, voice=voice, caption=caption, reply_markup=markup)
await message.answer(text=f'Осталось непрослушанных: <b>{len(check_audio) - 1}</b>', reply_markup=markup)

View File

View File

@@ -0,0 +1,22 @@
from aiogram import types
from aiogram.utils.keyboard import ReplyKeyboardBuilder, InlineKeyboardBuilder
def get_main_keyboard():
builder = ReplyKeyboardBuilder()
builder.add(types.KeyboardButton(text="🎤Высказаться"))
builder.add(types.KeyboardButton(text="🎧Послушать"))
markup = builder.as_markup(resize_keyboard=True)
return markup
def get_reply_keyboard_for_voice():
builder = InlineKeyboardBuilder()
builder.row(types.InlineKeyboardButton(
text="Сохранить", callback_data="save")
)
builder.row(types.InlineKeyboardButton(
text="Удалить", callback_data="delete")
)
markup = builder.as_markup(resize_keyboard=True, one_time_keyboard=True)
return markup

19
voice_bot/main.py Normal file
View File

@@ -0,0 +1,19 @@
from aiogram import Bot, Dispatcher
from aiogram.client.default import DefaultBotProperties
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.fsm.strategy import FSMStrategy
from voice_bot.handlers.callback_handler import callback_router
from voice_bot.handlers.voice_handler import voice_router
async def start_bot(bdf):
token = bdf.settings['Telegram']['listen_bot_token']
bot = Bot(token=token, default=DefaultBotProperties(
parse_mode='HTML',
link_preview_is_disabled=bdf.settings['Telegram']['preview_link']
))
dp = Dispatcher(storage=MemoryStorage(), fsm_strategy=FSMStrategy.GLOBAL_USER)
dp.include_routers(voice_router, callback_router)
await bot.delete_webhook(drop_pending_updates=True)
await dp.start_polling(bot, skip_updates=True)

View File

View File

@@ -0,0 +1,56 @@
import time
from datetime import datetime
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
bdf = BaseDependencyFactory()
BotDB = bdf.get_db()
def last_message():
# функция с отображением сообщения "Последнее сообщение было записано"
date_from_db = BotDB.last_date_audio()
if date_from_db is None:
return None
parse_date = datetime.strptime(date_from_db, "%Y-%m-%d %H:%M:%S")
last_voice_time_timestamp = time.mktime(parse_date.timetuple())
time_now_timestamp = time.time()
date_difference = time_now_timestamp - last_voice_time_timestamp
# считаем минуты, часы, дни
much_minutes_ago = round(date_difference / 60, 0)
much_hour_ago = round(date_difference / 3600, 0)
much_days_ago = int(round(much_hour_ago / 24, 0))
message_with_date = ''
if much_minutes_ago <= 60:
word_minute = plural_time(1, much_minutes_ago)
message_with_date = f'<b>Последнее сообщение было записано {word_minute} назад</b>'
elif much_minutes_ago > 60 and much_hour_ago <= 24:
word_hour = plural_time(2, much_hour_ago)
message_with_date = f'<b>Последнее сообщение было записано {word_hour} назад</b>'
elif much_hour_ago > 24:
word_day = plural_time(3, much_days_ago)
message_with_date = f'<b>Последнее сообщение было записано {word_day} назад</b>'
return message_with_date
def plural_time(type, n):
word = []
if type == 1:
word = ['минуту', 'минуты', 'минут']
elif type == 2:
word = ['час', 'часа', 'часов']
elif type == 3:
word = ['день', 'дня', 'дней']
else:
pass
if n % 10 == 1 and n % 100 != 11:
p = 0
elif 2 <= n % 10 <= 4 and (n % 100 < 10 or n % 100 >= 20):
p = 1
else:
p = 2
new_number = int(n)
return str(new_number) + ' ' + word[p]

View File

@@ -0,0 +1,6 @@
def get_message(username: str, type_message: str):
constants = {
}
message = constants[type_message]
return message.replace('username', username).replace('&', '\n')

9
voice_bot_v2.py Normal file
View File

@@ -0,0 +1,9 @@
import asyncio
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
from voice_bot.main import start_bot
bdf = BaseDependencyFactory()
if __name__ == '__main__':
asyncio.run(start_bot(BaseDependencyFactory()))