From 98a2c9dc555f7c836631ede5b08a083899793f5e Mon Sep 17 00:00:00 2001 From: Sima3443 Date: Fri, 31 Jan 2025 01:05:26 +0200 Subject: [PATCH 1/9] fix search --- database/service/search.py | 55 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/database/service/search.py b/database/service/search.py index f87e156..47973bc 100644 --- a/database/service/search.py +++ b/database/service/search.py @@ -1,37 +1,40 @@ -from math import radians, sin, cos, sqrt, atan2 from peewee import fn from loguru import logger -from database.models import Profile # Убедись, что у тебя правильно импортирован Profile -from database.service.profile import get_profile # Функция получения профиля пользователя +from database.models import Profile +from database.service.profile import get_profile -async def elastic_search_user_ids(user_id: int, age_range: int = 3, max_distance: float = 10) -> list: +async def elastic_search_user_ids(user_id: int, age_range: int = 3, distance: float = 0.1) -> list: """ - Ищет подходящие анкеты и возвращает список id пользователей, - отсортированных от ближайших к дальним. + Ищет подходящие анкеты для пользователя и возвращает список id пользователей, + которые подходят под критерии поиска. + Поиск идет по координатам и параметрам анкеты """ - profile: Profile = await get_profile(user_id) # Получаем профиль пользователя + profile: Profile = await get_profile(user_id) - # Haversine formula (расчёт расстояния через SQL) - distance_expr = ( - fn.ACOS( - fn.SIN(fn.RADIANS(profile.latitude)) * fn.SIN(fn.RADIANS(Profile.latitude)) + - fn.COS(fn.RADIANS(profile.latitude)) * fn.COS(fn.RADIANS(Profile.latitude)) * - fn.COS(fn.RADIANS(Profile.longitude - profile.longitude)) - ) * 6371 # 6371 — радиус Земли в километрах - ).alias("distance") + # Вычисляем расстояние по координатам + distance_expr = fn.SQRT( + fn.POW(Profile.latitude - profile.latitude, 2) + + fn.POW(Profile.longitude - profile.longitude, 2) + ) - query = ( - Profile - .select(Profile.user_id, distance_expr) + users = ( + Profile.select(Profile.user_id, distance_expr.alias("distance")) .where( - (Profile.is_active == True) & - ((Profile.gender == profile.find_gender) | (profile.find_gender == "all")) & - ((profile.gender == Profile.find_gender) | (Profile.find_gender == "all")) & - (Profile.age.between(profile.age - age_range, profile.age + age_range)) & - (Profile.user_id != user_id) & - (distance_expr <= max_distance) # Перенесли в WHERE + (Profile.is_active == True) + & (fn.ABS(Profile.latitude - profile.latitude) < distance) + & (fn.ABS(Profile.longitude - profile.longitude) < distance) + & ((Profile.gender == profile.find_gender) | (profile.find_gender == "all")) + & ((profile.gender == Profile.find_gender) | (Profile.find_gender == "all")) + & (Profile.age.between(profile.age - age_range, profile.age + age_range)) + & (Profile.user_id != user_id) + ) + .order_by( + fn.SQRT( + fn.POW(Profile.latitude - profile.latitude, 2) + + fn.POW(Profile.longitude - profile.longitude, 2) + ) ) - .order_by(distance_expr) # Сортировка от ближнего к дальнему ) + logger.info(f"User: {user_id} | начал поиск анкет") - return [row.user_id.id for row in query] \ No newline at end of file + return [i.user_id.id for i in users] \ No newline at end of file From 8f83f1f1bc3cd268354dec23316b7b2dd6b5ae20 Mon Sep 17 00:00:00 2001 From: Sima3443 Date: Fri, 31 Jan 2025 15:35:32 +0200 Subject: [PATCH 2/9] =?UTF-8?q?=F0=9F=AA=84Formatting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/filters/create_profile_filtres.py | 2 +- app/handlers/__init__.py | 1 - app/handlers/admin/admin.py | 4 +- app/handlers/admin/stats.py | 9 ++--- app/handlers/admin/users.py | 10 ++--- app/handlers/bot_utils.py | 50 ++++++++++++------------- app/handlers/msg_text.py | 34 +++++++++-------- app/handlers/user/__init__.py | 1 - app/handlers/user/archive_like.py | 30 +++++++-------- app/handlers/user/cancel.py | 2 +- app/handlers/user/create_profile.py | 18 ++++----- app/handlers/user/edit_profile.py | 14 +++---- app/handlers/user/invite.py | 2 +- app/handlers/user/lang.py | 2 +- app/handlers/user/profile.py | 2 +- app/handlers/user/search_profile.py | 10 ++--- app/handlers/user/sponsor.py | 10 ++--- app/handlers/user/start.py | 7 ++-- app/keyboards/__init__.py | 2 +- app/keyboards/default/admin.py | 6 +-- app/keyboards/default/base.py | 8 ++-- app/keyboards/default/create_profile.py | 2 +- app/keyboards/default/kb_generator.py | 4 +- app/keyboards/inline/archive.py | 2 +- app/keyboards/inline/lang.py | 2 +- app/keyboards/inline/report.py | 11 ++++-- app/middlewares/__init__.py | 6 +-- app/middlewares/admin.py | 4 +- app/middlewares/start.py | 11 +++--- app/middlewares/user.py | 2 +- app/others/commands.py | 4 +- app/others/states.py | 11 ++++-- app/routers.py | 2 +- database/models/likes.py | 2 +- database/models/migrations.py | 6 ++- database/models/profile.py | 2 +- database/service/likes.py | 1 - database/service/profile.py | 6 +-- database/service/search.py | 5 ++- database/service/users.py | 4 +- loader.py | 6 +-- main.py | 1 + utils/base62.py | 3 +- utils/cordinate.py | 5 ++- utils/graphs.py | 2 + utils/logging.py | 9 ++--- 46 files changed, 174 insertions(+), 163 deletions(-) diff --git a/app/filters/create_profile_filtres.py b/app/filters/create_profile_filtres.py index 65bcde3..0891826 100644 --- a/app/filters/create_profile_filtres.py +++ b/app/filters/create_profile_filtres.py @@ -57,7 +57,7 @@ async def __call__(self, message: Message) -> bool: class IsAge(Filter): async def __call__(self, message: Message) -> bool: return bool( - message.text.isdigit() and + message.text.isdigit() and int(message.text) < 100 and int(message.text) > 6 ) diff --git a/app/handlers/__init__.py b/app/handlers/__init__.py index 0d90528..2627d51 100644 --- a/app/handlers/__init__.py +++ b/app/handlers/__init__.py @@ -1,4 +1,3 @@ - from aiogram import Dispatcher from aiogram.types import ErrorEvent diff --git a/app/handlers/admin/admin.py b/app/handlers/admin/admin.py index 8487af7..3533b8c 100644 --- a/app/handlers/admin/admin.py +++ b/app/handlers/admin/admin.py @@ -13,6 +13,6 @@ async def _admin_command(message: types.Message) -> None: """Админ панель""" await message.answer( - text = msg_text.ADMIN_WELCOME, - reply_markup = admin_menu_kb() + text=msg_text.ADMIN_WELCOME, + reply_markup=admin_menu_kb() ) diff --git a/app/handlers/admin/stats.py b/app/handlers/admin/stats.py index 24f6740..2e6467e 100644 --- a/app/handlers/admin/stats.py +++ b/app/handlers/admin/stats.py @@ -13,7 +13,6 @@ from app.handlers.msg_text import msg_text - @router.message(Command("stats"), StateFilter(None)) @router.message(F.text.in_(["📊 Статистика", "📊 Statistics"]), StateFilter(None)) async def _stats_command(message: types.Message) -> None: @@ -25,7 +24,7 @@ async def _stats_command(message: types.Message) -> None: users_stats = await get_users_stats() graph_path = await get_or_create_registration_graph() photo = types.FSInputFile(graph_path) - + text = msg_text.USERS_STATS.format( users_stats["count"], users_stats["banned_count"], @@ -34,8 +33,8 @@ async def _stats_command(message: types.Message) -> None: profile_stats["male_count"], profile_stats["female_count"], ) - + await message.answer_photo(photo, text) - + # Удаляем временный файл - os.remove(graph_path) \ No newline at end of file + os.remove(graph_path) diff --git a/app/handlers/admin/users.py b/app/handlers/admin/users.py index b3d8171..b204e38 100644 --- a/app/handlers/admin/users.py +++ b/app/handlers/admin/users.py @@ -10,18 +10,18 @@ @router.message(F.text.in_( ["👤 Пользователи", "👤 Користувачі", "👤 Users"] - ), StateFilter(None)) +), StateFilter(None)) async def _users_admin_panel(message: types.Message) -> None: """Админ панель управление пользователями""" await message.answer( - text = msg_text.USER_PANEL, - reply_markup = user_ban_or_unban_kb(), + text=msg_text.USER_PANEL, + reply_markup=user_ban_or_unban_kb(), ) @router.message(F.text.in_( ["⚔️ Забанить пользователей", "⚔️ Забанити користувачів", "⚔️ Ban users"] - ), StateFilter(None)) +), StateFilter(None)) async def _ban_users_command(message: types.Message) -> None: """Запрашивает список пользоветелей которых нужно заблокировать""" await message.answer(msg_text.BAN_USERS_PANEL) @@ -29,7 +29,7 @@ async def _ban_users_command(message: types.Message) -> None: @router.message(F.text.in_( ["💊 Разбанить пользователей", "💊 Розбанити користувачів", "💊 Unban users"] - ), StateFilter(None)) +), StateFilter(None)) async def _unban_users_commad(message: types.Message) -> None: """Запрашивает список пользоветелей которых нужно разблокировать""" await message.answer(msg_text.UNBAN_USERS_PANEL) diff --git a/app/handlers/bot_utils.py b/app/handlers/bot_utils.py index dd66cb2..2219ff2 100644 --- a/app/handlers/bot_utils.py +++ b/app/handlers/bot_utils.py @@ -13,10 +13,10 @@ async def menu(user_id: int) -> None: """Отправляет меню пользователю""" await bot.send_message( - chat_id = user_id, - text = msg_text.MENU, - reply_markup = menu_kb, - ) + chat_id=user_id, + text=msg_text.MENU, + reply_markup=menu_kb, + ) async def report_to_profile(user, profile: Profile) -> None: @@ -26,34 +26,34 @@ async def report_to_profile(user, profile: Profile) -> None: try: await send_profile(MODERATOR_GROUP, profile) text = msg_text.REPORT_TO_USER.format(user.username, user.id, profile.user_id.username, profile.user_id) - + await bot.send_message( - chat_id = MODERATOR_GROUP, - text = text, - reply_markup = await block_user_ikb(profile.user_id), - ) + chat_id=MODERATOR_GROUP, + text=text, + reply_markup=await block_user_ikb(profile.user_id), + ) except: logger.error("Сообщение в модераторскую группу не отправленно") - - + + async def send_profile(user_id: int, profile: Profile) -> None: """Отправляет пользователю переданный в функцию профиль""" await bot.send_photo( - chat_id = user_id, - photo = profile.photo, - caption = f"{profile.name}, {profile.age}, {profile.city}\n{profile.description}", - parse_mode = None, - ) - + chat_id=user_id, + photo=profile.photo, + caption=f"{profile.name}, {profile.age}, {profile.city}\n{profile.description}", + parse_mode=None, + ) + async def new_user_alert_to_group(user: Users) -> None: - """Отправляет уведомление в модераторскуб группу о новом пользователе""" + """Отправляет уведомление в модераторскуб группу о новом пользователе""" if MODERATOR_GROUP: - try: + try: await bot.send_message( - chat_id = MODERATOR_GROUP, - text = msg_text.NEW_USER.format(user.username, user.id) - ) + chat_id=MODERATOR_GROUP, + text=msg_text.NEW_USER.format(user.username, user.id) + ) except: logger.error("Сообщение в модераторскую группу не отправленно") @@ -72,6 +72,6 @@ def generate_user_link(user_id: int, username: str = None) -> str: async def sending_user_contact(user_id: int, name: str, user_link: str) -> None: """Отправляет сообщение с контактом пользователя""" await bot.send_message( - chat_id = user_id, - text = msg_text.LIKE_ACCEPT.format(user_link, name), - ) \ No newline at end of file + chat_id=user_id, + text=msg_text.LIKE_ACCEPT.format(user_link, name), + ) diff --git a/app/handlers/msg_text.py b/app/handlers/msg_text.py index 1beb824..a179c48 100644 --- a/app/handlers/msg_text.py +++ b/app/handlers/msg_text.py @@ -133,12 +133,13 @@ def INVALID_AGE(self): @property def INVITE_FRIENDS(self): - return _("Приглашай друзей и получай бонус к своей анкете!\n\nПриглашенные пользователи: {}\n\nСсылка для друзей:\nhttps://t.me/{}?start={}") - + return _( + "Приглашай друзей и получай бонус к своей анкете!\n\nПриглашенные пользователи: {}\n\nСсылка для друзей:\nhttps://t.me/{}?start={}") + @property def ADMIN_WELCOME(self): return _("Вы администратор!") - + @property def USERS_STATS(self): return _(""" @@ -148,47 +149,47 @@ def USERS_STATS(self): 🙍‍♂ Парней: {}\t|🙍‍♀ Девушек: {} """) - + @property def CHANGE_LANG(self): return _("Выберите язык, на который вы хотите переключиться: 🌐") - + @property def DONE_CHANGE_LANG(self): return _("Ваш язык успешно изменён! ✅") - + @property def NEW_USER(self): return _("Появился новый пользователь, @{} | {}") - + @property def REPORT_TO_USER(self): return _("Пользователь: @{} | {} отправил жалобу на анкету пользователя: @{} | {}") - + @property def USER_PANEL(self): return _("Панель управлением пользователями") - + @property def UNBAN_USERS_PANEL(self): return _("💊 Укажите список пользовтелей для разблокировки в формате: 1234567, 234567") - + @property def BAN_USERS_PANEL(self): return _("⚔️ Укажите список пользовтелей для блокировки в формате: 1234567, 234567") - + @property def USER_BANNED(self): return _("Пользователь: {} заблокирован") - + @property def MAILING_PANEL(self): return _("Укажите текст сообщение которое хотите отправить") - + @property def REPORT_TO_PROFILE(self): return _("✅ Ваша жалоба на пользователя отправлена на рассмотрение!") - + @property def RESON_OF_REPORTING(self): return _("""Укажите причину жалобы: @@ -198,5 +199,6 @@ def RESON_OF_REPORTING(self): Если жалоба ошибочная, вы можете вернутся назад. """) - -msg_text = MsgText() \ No newline at end of file + + +msg_text = MsgText() diff --git a/app/handlers/user/__init__.py b/app/handlers/user/__init__.py index 4771024..5350449 100644 --- a/app/handlers/user/__init__.py +++ b/app/handlers/user/__init__.py @@ -13,5 +13,4 @@ from .archive_like import router - __all__ = ["router"] diff --git a/app/handlers/user/archive_like.py b/app/handlers/user/archive_like.py index 6a1967e..922e56a 100644 --- a/app/handlers/user/archive_like.py +++ b/app/handlers/user/archive_like.py @@ -24,8 +24,8 @@ async def like_profile(message: types.Message, state: FSMContext) -> None: return await update_user_username(message.from_user.id, message.from_user.username) await message.answer( - text = msg_text.SEARCH, - reply_markup = arhive_search_kb + text=msg_text.SEARCH, + reply_markup=arhive_search_kb ) await state.set_state(LikeResponse.response) @@ -46,8 +46,8 @@ async def _like_profile(callback: types.CallbackQuery, state: FSMContext) -> Non await state.set_state(LikeResponse.response) await update_user_username(callback.from_user.id, callback.from_user.username) await callback.message.answer( - text = msg_text.SEARCH, - reply_markup = arhive_search_kb + text=msg_text.SEARCH, + reply_markup=arhive_search_kb ) if liker_ids := await get_profile_likes(callback.from_user.id): @@ -69,24 +69,24 @@ async def _like_response(message: types.Message, state: FSMContext) -> None: if message.text == "❤️": """Отправка пользователю которому ответили на лайк""" await sending_user_contact( - user_id = profile.user_id.id, - name = message.from_user.full_name, - user_link = generate_user_link( - user_id = message.from_user.id, - username = message.from_user.username, + user_id=profile.user_id.id, + name=message.from_user.full_name, + user_link=generate_user_link( + user_id=message.from_user.id, + username=message.from_user.username, ) ) - + """Отправка пользователю который ответил на лайк""" await sending_user_contact( - user_id=message.from_user.id, - name=profile.name, - user_link = generate_user_link( - user_id=profile.user_id.id, + user_id=message.from_user.id, + name=profile.name, + user_link=generate_user_link( + user_id=profile.user_id.id, username=profile.user_id.username, ) ) - + await del_like(message.from_user.id, profile.user_id.id) ids.pop(0) diff --git a/app/handlers/user/cancel.py b/app/handlers/user/cancel.py index a90d5c3..511246f 100644 --- a/app/handlers/user/cancel.py +++ b/app/handlers/user/cancel.py @@ -18,4 +18,4 @@ async def cancel_command(message: types.Message, state: FSMContext) -> None: if await state.get_state() == DisableProfile.waiting: return await state.clear() - await menu(message.from_user.id) \ No newline at end of file + await menu(message.from_user.id) diff --git a/app/handlers/user/create_profile.py b/app/handlers/user/create_profile.py index 3a08a7d..8850db8 100644 --- a/app/handlers/user/create_profile.py +++ b/app/handlers/user/create_profile.py @@ -135,15 +135,15 @@ async def _description(message: types.Message, state: FSMContext): data = await state.get_data() await create_profile( user_id=message.from_user.id, - gender = data["gender"], - find_gender = data["find_gender"], - photo = data["photo"], - name = data["name"], - age = data["age"], - city = data["city"], - latitude = data["latitude"], - longitude = data["longitude"], - description = message.text + gender=data["gender"], + find_gender=data["find_gender"], + photo=data["photo"], + name=data["name"], + age=data["age"], + city=data["city"], + latitude=data["latitude"], + longitude=data["longitude"], + description=message.text ) await state.clear() diff --git a/app/handlers/user/edit_profile.py b/app/handlers/user/edit_profile.py index 7e9cd68..2a1f4ce 100644 --- a/app/handlers/user/edit_profile.py +++ b/app/handlers/user/edit_profile.py @@ -24,24 +24,24 @@ async def _edit_profile_description_command(message: types.Message, state: FSMCo """Редактирование описания""" await state.set_state(ProfileEdit.desc) await message.answer(msg_text.DESCRIPTION) - + + @router.message(F.text == "❌", StateFilter(None)) async def _disable_profile_command(message: types.Message, state: FSMContext) -> None: """Отключение профиля""" await state.set_state(DisableProfile.waiting) await update_profile_is_active_status(message.from_user.id, False) await message.answer( - text = msg_text.DISABLE_PROFILE, - reply_markup = profile_return_kb() + text=msg_text.DISABLE_PROFILE, + reply_markup=profile_return_kb() ) - + @router.message(F.text.in_( -["🔙 Вернуть профиль", "🔙 Return profile", "🔙 Повернути профіль"] - ), DisableProfile.waiting) + ["🔙 Вернуть профиль", "🔙 Return profile", "🔙 Повернути профіль"] +), DisableProfile.waiting) async def _activate_profile_command(message: types.Message, state: FSMContext) -> None: await state.clear() await update_profile_is_active_status(message.from_user.id, True) await message.answer(msg_text.ACTIVATE_PROFILE_ALERT) await menu(message.from_user.id) - \ No newline at end of file diff --git a/app/handlers/user/invite.py b/app/handlers/user/invite.py index 1c9f13c..41152cb 100644 --- a/app/handlers/user/invite.py +++ b/app/handlers/user/invite.py @@ -19,5 +19,5 @@ async def _invite_link_command(message: types.Message, user: Users) -> None: user_code: str = encode_base62(message.from_user.id) await message.answer(msg_text.INVITE_FRIENDS.format( user.referral, bot_user.username, user_code - ) + ) ) diff --git a/app/handlers/user/lang.py b/app/handlers/user/lang.py index 2518683..96f58ea 100644 --- a/app/handlers/user/lang.py +++ b/app/handlers/user/lang.py @@ -16,7 +16,7 @@ async def _lang(message: types.Message) -> None: """Предлагает клавиатуру с доступными языками""" await message.answer( msg_text.CHANGE_LANG, - reply_markup = await lang_ikb() + reply_markup=await lang_ikb() ) diff --git a/app/handlers/user/profile.py b/app/handlers/user/profile.py index 1301967..ea116c5 100644 --- a/app/handlers/user/profile.py +++ b/app/handlers/user/profile.py @@ -18,5 +18,5 @@ async def profile_command(message: types.Message) -> None: await send_profile(message.from_user.id, profile) await message.answer( msg_text.PROFILE_MENU, - reply_markup = profile_kb, + reply_markup=profile_kb, ) diff --git a/app/handlers/user/search_profile.py b/app/handlers/user/search_profile.py index 74701b1..a349f66 100644 --- a/app/handlers/user/search_profile.py +++ b/app/handlers/user/search_profile.py @@ -22,7 +22,7 @@ @router.message(F.text == "🔍", StateFilter(None)) async def _search_command(message: types.Message, state: FSMContext) -> None: """Начинает поиск анкет""" - await message.answer(msg_text.SEARCH, reply_markup= search_kb) + await message.answer(msg_text.SEARCH, reply_markup=search_kb) ids = await elastic_search_user_ids(message.from_user.id) if not ids: @@ -49,12 +49,12 @@ async def _search_profile(message: types.Message, state: FSMContext) -> None: if message.text == "❤️": await set_new_like(message.from_user.id, profile.user_id) await message.bot.send_message( - chat_id = profile.user_id.id, - text = msg_text.LIKE_PROFILE, - reply_markup = check_archive_ikb(), + chat_id=profile.user_id.id, + text=msg_text.LIKE_PROFILE, + reply_markup=check_archive_ikb(), ) elif message.text == "💢": - await message.answer(msg_text.REPORT_TO_PROFILE) + await message.answer(msg_text.REPORT_TO_PROFILE) await report_to_profile(message.from_user, profile) ids.pop(0) diff --git a/app/handlers/user/sponsor.py b/app/handlers/user/sponsor.py index 3346e4a..e37b5f2 100644 --- a/app/handlers/user/sponsor.py +++ b/app/handlers/user/sponsor.py @@ -20,15 +20,15 @@ async def _sponsor_command(message: types.Message) -> None: currency="XTR", prices=[types.LabeledPrice(label="XTR", amount=1)] ) - - + + @router.pre_checkout_query() async def pre_checkout_query(event: types.PreCheckoutQuery) -> None: from utils.logging import logger logger.debug(event) await event.answer(True) - - + + @router.message(F.succesful_payment.paylod == "sponsor") async def succesful_payment(message: types.Message) -> None: link = await bot.create_chat_invite_link(MODERATOR_GROUP, member_limit=1) @@ -36,4 +36,4 @@ async def succesful_payment(message: types.Message) -> None: message.from_user.id, message.successful_payment.telegram_payment_charge_id ) - await message.answer(f"Твоя пригласительная ссылка: {link}") \ No newline at end of file + await message.answer(f"Твоя пригласительная ссылка: {link}") diff --git a/app/handlers/user/start.py b/app/handlers/user/start.py index 9483692..42ce0b8 100644 --- a/app/handlers/user/start.py +++ b/app/handlers/user/start.py @@ -12,7 +12,6 @@ from app.keyboards.default.create_profile import start_kb from app.handlers.bot_utils import menu - photo = types.FSInputFile(f"{IMAGES_DIR}/new_logo.webp") @@ -23,7 +22,7 @@ async def _start_command(message: types.Message) -> None: await menu(message.from_user.id) else: await message.answer_photo( - photo = photo, - caption = msg_text.WELCOME, - reply_markup = start_kb(), + photo=photo, + caption=msg_text.WELCOME, + reply_markup=start_kb(), ) diff --git a/app/keyboards/__init__.py b/app/keyboards/__init__.py index 8c08266..fa8b2ad 100644 --- a/app/keyboards/__init__.py +++ b/app/keyboards/__init__.py @@ -1,2 +1,2 @@ from .default import * -from .inline import * \ No newline at end of file +from .inline import * diff --git a/app/keyboards/default/admin.py b/app/keyboards/default/admin.py index e854096..3aba896 100644 --- a/app/keyboards/default/admin.py +++ b/app/keyboards/default/admin.py @@ -31,13 +31,13 @@ def user_ban_or_unban_kb() -> ReplyKeyboardMarkup: resize_keyboard=True, keyboard=[ [ - KeyboardButton(text=_(f"⚔️ Забанить пользователей")), + KeyboardButton(text=_(f"⚔️ Забанить пользователей")), ], [ - KeyboardButton(text=_("💊 Разбанить пользователей")), + KeyboardButton(text=_("💊 Разбанить пользователей")), ], ], one_time_keyboard=True, ) - return kb \ No newline at end of file + return kb diff --git a/app/keyboards/default/base.py b/app/keyboards/default/base.py index f296312..ee43ed9 100644 --- a/app/keyboards/default/base.py +++ b/app/keyboards/default/base.py @@ -8,7 +8,6 @@ from .kb_generator import simple_kb_generator as gen - del_kb = ReplyKeyboardRemove() cancel_kb: ReplyKeyboardMarkup = gen( @@ -16,7 +15,7 @@ ) profile_kb: ReplyKeyboardMarkup = gen( - ["🔄", "🖼", "✍️", "❌"], + ["🔄", "🖼", "✍️", "❌"], ["🔍"] ) @@ -26,12 +25,12 @@ ) search_kb: ReplyKeyboardMarkup = gen( - ["❤️", "💢", "👎"], + ["❤️", "💢", "👎"], ["💤"] ) arhive_search_kb: ReplyKeyboardMarkup = gen( - ["❤️", "👎"], + ["❤️", "👎"], ["💤"] ) @@ -48,7 +47,6 @@ def profile_return_kb() -> ReplyKeyboardMarkup: ) return kb - # async def report_kb() -> ReplyKeyboardMarkup: # kb = ReplyKeyboardMarkup( # resize_keyboard=True, diff --git a/app/keyboards/default/create_profile.py b/app/keyboards/default/create_profile.py index fcaa19e..60fd3d0 100644 --- a/app/keyboards/default/create_profile.py +++ b/app/keyboards/default/create_profile.py @@ -46,4 +46,4 @@ def find_gender_kb() -> ReplyKeyboardMarkup: # ], # ], # ) -# return kb \ No newline at end of file +# return kb diff --git a/app/keyboards/default/kb_generator.py b/app/keyboards/default/kb_generator.py index c8d4f4f..c1141b1 100644 --- a/app/keyboards/default/kb_generator.py +++ b/app/keyboards/default/kb_generator.py @@ -2,7 +2,7 @@ ReplyKeyboardMarkup, KeyboardButton, ) -from loader import _ + def simple_kb_generator(*buttons_list: list, one_time: bool = True, resize: bool = True) -> ReplyKeyboardMarkup: """ @@ -24,4 +24,4 @@ def simple_kb_generator(*buttons_list: list, one_time: bool = True, resize: bool keyboard=keyboard, resize_keyboard=resize, one_time_keyboard=one_time - ) \ No newline at end of file + ) diff --git a/app/keyboards/inline/archive.py b/app/keyboards/inline/archive.py index 3218681..3cf2bee 100644 --- a/app/keyboards/inline/archive.py +++ b/app/keyboards/inline/archive.py @@ -14,4 +14,4 @@ def check_archive_ikb() -> InlineKeyboardMarkup: ], ], ) - return ikb \ No newline at end of file + return ikb diff --git a/app/keyboards/inline/lang.py b/app/keyboards/inline/lang.py index 97443ee..c6b5b8b 100644 --- a/app/keyboards/inline/lang.py +++ b/app/keyboards/inline/lang.py @@ -19,4 +19,4 @@ def lang_ikb() -> InlineKeyboardMarkup: ], ], ) - return ikb \ No newline at end of file + return ikb diff --git a/app/keyboards/inline/report.py b/app/keyboards/inline/report.py index 5ea96ab..41eb12a 100644 --- a/app/keyboards/inline/report.py +++ b/app/keyboards/inline/report.py @@ -9,15 +9,18 @@ def block_user_ikb(user) -> InlineKeyboardMarkup: ikb = InlineKeyboardMarkup( resize_keyboard=True, - + inline_keyboard=[ [ - InlineKeyboardButton(text=_("☠️ Заблокировать пользователя {}").format(user.username), callback_data=f"block_user_{user.id}"), + InlineKeyboardButton( + text=_("☠️ Заблокировать пользователя {}").format(user.username), + callback_data=f"block_user_{user.id}", + ), ], [ InlineKeyboardButton(text=_("Отклонить"), callback_data="..."), ], ], - + ) - return ikb \ No newline at end of file + return ikb diff --git a/app/middlewares/__init__.py b/app/middlewares/__init__.py index 6cb8af5..f0f3e6d 100644 --- a/app/middlewares/__init__.py +++ b/app/middlewares/__init__.py @@ -8,12 +8,12 @@ def setup_middlewares(dp: Dispatcher) -> None: start_router.message.middleware(StartMiddleware()) - + admin_router.message.middleware(AdminMiddleware()) - + user_router.message.middleware(UsersMiddleware()) user_router.callback_query.middleware(UsersMiddleware()) - + start_router.message.middleware(i18n_middleware) admin_router.message.middleware(i18n_middleware) user_router.message.middleware(i18n_middleware) diff --git a/app/middlewares/admin.py b/app/middlewares/admin.py index f3bf449..1744e81 100644 --- a/app/middlewares/admin.py +++ b/app/middlewares/admin.py @@ -8,9 +8,9 @@ class AdminMiddleware(BaseMiddleware): - async def __call__(self, handler: Callable, message: Message, data: dict) -> Any: + async def __call__(self, handler: Callable, message: Message, data: dict) -> Any: if user := await get_user(message.from_user.id): if user.id in ADMINS: data["user"] = user return await handler(message, data) - return \ No newline at end of file + return diff --git a/app/middlewares/start.py b/app/middlewares/start.py index 780b66c..591071c 100644 --- a/app/middlewares/start.py +++ b/app/middlewares/start.py @@ -19,15 +19,14 @@ async def __call__(self, handler: Callable, message: Message, data: dict) -> Any return user = await create_user( - user_id = message.from_user.id, - username = message.from_user.username, - language = message.from_user.language_code, + user_id=message.from_user.id, + username=message.from_user.username, + language=message.from_user.language_code, ) data["user"] = user await new_user_alert_to_group(user) - + if inviter := data["command"].args: await new_referral(decode_base62(inviter)) - + return await handler(message, data) - \ No newline at end of file diff --git a/app/middlewares/user.py b/app/middlewares/user.py index 6bba949..80213d1 100644 --- a/app/middlewares/user.py +++ b/app/middlewares/user.py @@ -4,6 +4,7 @@ from typing import Any, Callable from database.service.users import get_or_create_user + class UsersMiddleware(BaseMiddleware): async def __call__(self, handler: Callable, event: Message | CallbackQuery, data: dict) -> Any: user = await get_or_create_user( @@ -15,4 +16,3 @@ async def __call__(self, handler: Callable, event: Message | CallbackQuery, data data["user"] = user return await handler(event, data) return - \ No newline at end of file diff --git a/app/others/commands.py b/app/others/commands.py index c2022c7..5b84bde 100644 --- a/app/others/commands.py +++ b/app/others/commands.py @@ -13,6 +13,7 @@ def get_default_commands(lang: str = "en"): return commands + def get_admins_commands(lang: str = "en"): commands = get_default_commands(lang) commands.extend( @@ -33,6 +34,7 @@ async def set_default_commands() -> None: language_code=lang, ) + async def set_admins_commands(id: int) -> None: await bot.set_my_commands( get_admins_commands(), scope=BotCommandScopeChat(chat_id=id) @@ -42,4 +44,4 @@ async def set_admins_commands(id: int) -> None: get_admins_commands(lang), scope=BotCommandScopeChat(chat_id=id), language_code=lang, - ) \ No newline at end of file + ) diff --git a/app/others/states.py b/app/others/states.py index 2ae32c0..3978fab 100644 --- a/app/others/states.py +++ b/app/others/states.py @@ -1,8 +1,10 @@ from aiogram.fsm.state import State, StatesGroup + class LikeResponse(StatesGroup): response = State() + class ProfileCreate(StatesGroup): gender = State() find_gender = State() @@ -11,13 +13,16 @@ class ProfileCreate(StatesGroup): age = State() city = State() desc = State() - + + class ProfileEdit(StatesGroup): photo = State() desc = State() - + + class Search(StatesGroup): search = State() - + + class DisableProfile(StatesGroup): waiting = State() diff --git a/app/routers.py b/app/routers.py index 2f488fa..6462a20 100644 --- a/app/routers.py +++ b/app/routers.py @@ -3,4 +3,4 @@ user_router = Router() sponsor_roter = Router() start_router = Router() -admin_router = Router() \ No newline at end of file +admin_router = Router() diff --git a/database/models/likes.py b/database/models/likes.py index eb81dd5..abf249c 100644 --- a/database/models/likes.py +++ b/database/models/likes.py @@ -3,7 +3,7 @@ from .users import Users + class Likes(BaseModel): liker_id = ForeignKeyField(Users, backref='likes_given') liked_id = ForeignKeyField(Users, backref='likes_received') - diff --git a/database/models/migrations.py b/database/models/migrations.py index 01866b5..c20b852 100644 --- a/database/models/migrations.py +++ b/database/models/migrations.py @@ -8,6 +8,8 @@ from playhouse.migrate import PostgresqlMigrator, migrate from ..connect import db + + def export_data(db, model, file): # Экспорт данных data = [] @@ -22,7 +24,7 @@ def json_serial(obj): with open(file, 'w') as f: json.dump(data, f, default=json_serial) - + def import_data(db, model, file): with open(file, 'r') as f: @@ -32,7 +34,7 @@ def import_data(db, model, file): for table in data: table_name = list(table.keys())[0] # Имя таблицы из JSON rows = table[table_name] - + if model is None: print(f"Не удалось найти модель для таблицы {table_name}") continue diff --git a/database/models/profile.py b/database/models/profile.py index 231bb14..915507f 100644 --- a/database/models/profile.py +++ b/database/models/profile.py @@ -2,6 +2,7 @@ from ..connect import BaseModel from .users import Users + class Profile(BaseModel): user_id = ForeignKeyField(Users, backref='profile', primary_key=True) name = CharField(max_length=50) @@ -14,4 +15,3 @@ class Profile(BaseModel): age = IntegerField(index=True) description = CharField(max_length=1000) is_active = BooleanField(default=True, index=True) - diff --git a/database/service/likes.py b/database/service/likes.py index a1b9a68..6082601 100644 --- a/database/service/likes.py +++ b/database/service/likes.py @@ -25,4 +25,3 @@ async def del_like(liked_id: int, liker_id: int) -> None: """Удаляет лайк из БД""" logger.info(f"{liker_id} & {liked_id} | лайк удален") Likes.delete().where((Likes.liker_id == liker_id) & (Likes.liked_id == liked_id)).execute() - diff --git a/database/service/profile.py b/database/service/profile.py index 617fc90..b7d047d 100644 --- a/database/service/profile.py +++ b/database/service/profile.py @@ -33,9 +33,9 @@ async def edit_profile_description(user_id, description): async def create_profile( - user_id: int, gender: str, find_gender: str, - photo: str, name: str, age: int, city: str, - latitude: str, longitude: str, description: str, + user_id: int, gender: str, find_gender: str, + photo: str, name: str, age: int, city: str, + latitude: str, longitude: str, description: str, ): """Создает профиль пользователя, если профиль есть - удаляет его""" if await get_profile(user_id): diff --git a/database/service/search.py b/database/service/search.py index 47973bc..a75fc38 100644 --- a/database/service/search.py +++ b/database/service/search.py @@ -1,8 +1,9 @@ from peewee import fn from loguru import logger -from database.models import Profile +from database.models import Profile from database.service.profile import get_profile + async def elastic_search_user_ids(user_id: int, age_range: int = 3, distance: float = 0.1) -> list: """ Ищет подходящие анкеты для пользователя и возвращает список id пользователей, @@ -37,4 +38,4 @@ async def elastic_search_user_ids(user_id: int, age_range: int = 3, distance: fl ) logger.info(f"User: {user_id} | начал поиск анкет") - return [i.user_id.id for i in users] \ No newline at end of file + return [i.user_id.id for i in users] diff --git a/database/service/users.py b/database/service/users.py index f6c5409..c7b1fdb 100644 --- a/database/service/users.py +++ b/database/service/users.py @@ -35,13 +35,13 @@ async def new_referral(inviter_id: int) -> None: Users.update(referral=Users.referral + 1).where(Users.id == inviter_id).execute() logger.info(f"User: {inviter_id} | привел нового пользователя") - + async def change_language(user_id: int, language: str) -> None: """Изменяет язык пользователя на language""" Users.update(language=language).where(Users.id == user_id).execute() logger.info(f"User: {user_id} | изменил язык на - {language}") - + async def toggle_user_ban(user: Users) -> None: """Меняет статус блокировки пользователя на противоположный""" user.is_banned = not user.is_banned diff --git a/loader.py b/loader.py index eeeb496..46a7940 100644 --- a/loader.py +++ b/loader.py @@ -6,14 +6,15 @@ from data import config from utils.logging import logger - if config.REDIS_URL: from aiogram.fsm.storage.redis import RedisStorage from redis.asyncio.client import Redis + storage = RedisStorage(Redis.from_url(config.REDIS_URL)) logger.info("Storage: Redis") elif not config.REDIS_URL: from aiogram.fsm.storage.memory import MemoryStorage + storage = MemoryStorage() logger.info("Storage: Default") @@ -23,6 +24,5 @@ ) dp = Dispatcher(bot=bot, storage=storage) - i18n = I18n(path=config.LOCALES_DIR, domain=config.I18N_DOMAIN) -_ = i18n.gettext \ No newline at end of file +_ = i18n.gettext diff --git a/main.py b/main.py index debea8e..89f5f8a 100644 --- a/main.py +++ b/main.py @@ -12,6 +12,7 @@ async def on_startup() -> None: await set_default_commands() logger.info("~ Bot startup") + async def on_shutdown() -> None: logger.info("~ Bot shutting down...") diff --git a/utils/base62.py b/utils/base62.py index 5cf897a..fcb4096 100644 --- a/utils/base62.py +++ b/utils/base62.py @@ -2,6 +2,7 @@ BASE62_ALPHABET = string.digits + string.ascii_letters + def encode_base62(num: int) -> str: """Кодирует число""" base = len(BASE62_ALPHABET) @@ -11,6 +12,7 @@ def encode_base62(num: int) -> str: encoded.append(BASE62_ALPHABET[rem]) return ''.join(reversed(encoded)) + def decode_base62(encoded_str: str) -> str: """Декодирует строку""" base = len(BASE62_ALPHABET) @@ -18,4 +20,3 @@ def decode_base62(encoded_str: str) -> str: for char in encoded_str: num = num * base + BASE62_ALPHABET.index(char) return num - diff --git a/utils/cordinate.py b/utils/cordinate.py index 2cecc5a..63826c9 100644 --- a/utils/cordinate.py +++ b/utils/cordinate.py @@ -8,10 +8,11 @@ def get_coordinates(city_name: str, timeout: int = 10) -> list | None: location = geolocator.geocode(city_name) return (location.latitude, location.longitude) if location else None -def find_nearby_profiles(user_coordinates, profiles, max_distance_km=50)-> list: + +def find_nearby_profiles(user_coordinates, profiles, max_distance_km=50) -> list: nearby_profiles = [] for profile in profiles: distance = geodesic(user_coordinates, profile["coordinates"]).kilometers if distance <= max_distance_km: nearby_profiles.append(profile) - return nearby_profiles \ No newline at end of file + return nearby_profiles diff --git a/utils/graphs.py b/utils/graphs.py index dd859d2..193d2bc 100644 --- a/utils/graphs.py +++ b/utils/graphs.py @@ -16,6 +16,7 @@ def get_day_period(days: int = 30): days_ago = today - timedelta(days) return today, days_ago + async def get_or_create_registration_graph(data=None, path=registration_photo_path) -> str: """Создает график регистрации пользователей и возращает путь к фотографии графика""" if data is None: @@ -23,6 +24,7 @@ async def get_or_create_registration_graph(data=None, path=registration_photo_pa create_user_registration_graph(data, path) return path + def create_user_registration_graph(data, path): """Создает график новых пользователей в заданом периоде""" df = pd.DataFrame(data) diff --git a/utils/logging.py b/utils/logging.py index c415af3..df263fb 100644 --- a/utils/logging.py +++ b/utils/logging.py @@ -2,12 +2,11 @@ from data.config import DIR from loguru import logger - logger.add( - f"{DIR}/logs/logs.log", - format='[{time}] [{level}] [{file.name}:{line}] {message}', - level='DEBUG', + f"{DIR}/logs/logs.log", + format='[{time}] [{level}] [{file.name}:{line}] {message}', + level='DEBUG', rotation='1 month', compression='zip') -getLogger('aiogram').addFilter(lambda r: r.getMessage().find('Field \'database_user\' doesn\'t exist in') == -1) \ No newline at end of file +getLogger('aiogram').addFilter(lambda r: r.getMessage().find('Field \'database_user\' doesn\'t exist in') == -1) From bd1df048ed4cea090b59d9e17653c93c27cb2479 Mon Sep 17 00:00:00 2001 From: Sima3443 Date: Sun, 2 Feb 2025 14:34:19 +0200 Subject: [PATCH 3/9] fixs and formating --- app/filters/create_profile_filtres.py | 14 +++++++------- app/handlers/bot_utils.py | 14 +++++++++----- app/handlers/msg_text.py | 21 ++++++++++++++------- app/handlers/user/archive_like.py | 20 ++++++-------------- app/handlers/user/create_profile.py | 2 +- app/handlers/user/edit_profile.py | 12 +++++------- app/handlers/user/invite.py | 5 ++--- app/handlers/user/lang.py | 5 +---- app/handlers/user/profile.py | 5 +---- app/handlers/user/sponsor.py | 6 +++--- app/keyboards/__init__.py | 2 -- app/keyboards/default/admin.py | 3 --- app/keyboards/default/base.py | 22 +++++++++++----------- app/keyboards/default/create_profile.py | 1 + app/keyboards/default/kb_generator.py | 10 +++++----- app/keyboards/inline/report.py | 8 +++----- app/others/commands.py | 6 ++---- database/__init__.py | 2 -- database/connect.py | 15 ++++++++------- database/models/likes.py | 4 ++-- database/models/migrations.py | 6 ++++-- database/models/profile.py | 22 +++++++++++----------- database/models/users.py | 12 ++++++------ database/service/__init__.py | 2 -- database/service/profile.py | 13 ++++++++++--- database/service/search.py | 2 +- database/service/stats.py | 12 +++++------- main.py | 11 ++++++----- utils/base62.py | 2 +- utils/graphs.py | 20 ++++++++++---------- utils/logging.py | 13 ++++++++----- 31 files changed, 143 insertions(+), 149 deletions(-) diff --git a/app/filters/create_profile_filtres.py b/app/filters/create_profile_filtres.py index 0891826..58c422e 100644 --- a/app/filters/create_profile_filtres.py +++ b/app/filters/create_profile_filtres.py @@ -27,7 +27,9 @@ class IsCreate(Filter): async def __call__(self, message: Message) -> bool: - return bool(message.text in ["/create", "Создать анкету", "Create a profile", "Створити анкету"]) + return bool( + message.text in ["/create", "Создать анкету", "Create a profile", "Створити анкету"] + ) class IsGender(Filter): @@ -56,16 +58,14 @@ async def __call__(self, message: Message) -> bool: class IsAge(Filter): async def __call__(self, message: Message) -> bool: - return bool( - message.text.isdigit() and - int(message.text) < 100 and - int(message.text) > 6 - ) + return bool(message.text.isdigit() and int(message.text) < 100 and int(message.text) > 6) class IsCity(Filter): async def __call__(self, message: Message) -> bool: - if coordinates := get_coordinates(message.text): + if message.text.isdigit(): + return False + elif coordinates := get_coordinates(message.text): return {"coordinates": coordinates} return False diff --git a/app/handlers/bot_utils.py b/app/handlers/bot_utils.py index 2219ff2..6ecc4cd 100644 --- a/app/handlers/bot_utils.py +++ b/app/handlers/bot_utils.py @@ -19,18 +19,23 @@ async def menu(user_id: int) -> None: ) -async def report_to_profile(user, profile: Profile) -> None: +async def report_to_profile(user: Users, profile: Profile) -> None: """Отправляет в группу модераторов анкету пользователя на которого пришла жалоба""" if MODERATOR_GROUP: try: await send_profile(MODERATOR_GROUP, profile) - text = msg_text.REPORT_TO_USER.format(user.username, user.id, profile.user_id.username, profile.user_id) + text = msg_text.REPORT_TO_USER.format( + user.username, user.id, profile.user_id.username, profile.user_id.id + ) await bot.send_message( chat_id=MODERATOR_GROUP, text=text, - reply_markup=await block_user_ikb(profile.user_id), + reply_markup=block_user_ikb( + user_id=profile.user_id.id, + username=profile.user_id.username, + ), ) except: logger.error("Сообщение в модераторскую группу не отправленно") @@ -51,8 +56,7 @@ async def new_user_alert_to_group(user: Users) -> None: if MODERATOR_GROUP: try: await bot.send_message( - chat_id=MODERATOR_GROUP, - text=msg_text.NEW_USER.format(user.username, user.id) + chat_id=MODERATOR_GROUP, text=msg_text.NEW_USER.format(user.username, user.id) ) except: logger.error("Сообщение в модераторскую группу не отправленно") diff --git a/app/handlers/msg_text.py b/app/handlers/msg_text.py index a179c48..8266e76 100644 --- a/app/handlers/msg_text.py +++ b/app/handlers/msg_text.py @@ -109,7 +109,9 @@ def DESCRIPTION(self): @property def DISABLE_PROFILE(self): - return _("Ваша анкета временно отключена.\n\nЧтобы снова активировать её, просто нажмите на кнопку.") + return _( + "Ваша анкета временно отключена.\n\nЧтобы снова активировать её, просто нажмите на кнопку." + ) @property def ACTIVATE_PROFILE_ALERT(self): @@ -125,7 +127,9 @@ def INVALID_LONG_RESPONSE(self): @property def INVALID_PHOTO(self): - return _("Неверный формат фотографии! Пожалуйста, загрузите изображение в правильном формате. 🖼️") + return _( + "Неверный формат фотографии! Пожалуйста, загрузите изображение в правильном формате. 🖼️" + ) @property def INVALID_AGE(self): @@ -134,7 +138,8 @@ def INVALID_AGE(self): @property def INVITE_FRIENDS(self): return _( - "Приглашай друзей и получай бонус к своей анкете!\n\nПриглашенные пользователи: {}\n\nСсылка для друзей:\nhttps://t.me/{}?start={}") + "Приглашай друзей и получай бонус к своей анкете!\n\nПриглашенные пользователи: {}\n\nСсылка для друзей:\nhttps://t.me/{}?start={}" + ) @property def ADMIN_WELCOME(self): @@ -142,12 +147,12 @@ def ADMIN_WELCOME(self): @property def USERS_STATS(self): - return _(""" -👤 Пользователей: {}\t|🚫 Заблокированных: {} + return _(""" +👤 Пользователей: {}\t|🚫 Заблокированных: {} 📂 Анкет: {}\t|🔕 Неактивных: {} -🙍‍♂ Парней: {}\t|🙍‍♀ Девушек: {} +🙍‍♂ Парней: {}\t|🙍‍♀ Девушек: {} """) @property @@ -164,7 +169,9 @@ def NEW_USER(self): @property def REPORT_TO_USER(self): - return _("Пользователь: @{} | {} отправил жалобу на анкету пользователя: @{} | {}") + return _( + "Пользователь: @{} | {} отправил жалобу на анкету пользователя: @{} | {}" + ) @property def USER_PANEL(self): diff --git a/app/handlers/user/archive_like.py b/app/handlers/user/archive_like.py index 922e56a..e0a1950 100644 --- a/app/handlers/user/archive_like.py +++ b/app/handlers/user/archive_like.py @@ -23,10 +23,7 @@ async def like_profile(message: types.Message, state: FSMContext) -> None: if await state.get_state() == DisableProfile.waiting: return await update_user_username(message.from_user.id, message.from_user.username) - await message.answer( - text=msg_text.SEARCH, - reply_markup=arhive_search_kb - ) + await message.answer(text=msg_text.SEARCH, reply_markup=arhive_search_kb) await state.set_state(LikeResponse.response) if liker_ids := await get_profile_likes(message.from_user.id): @@ -45,10 +42,7 @@ async def _like_profile(callback: types.CallbackQuery, state: FSMContext) -> Non return await state.set_state(LikeResponse.response) await update_user_username(callback.from_user.id, callback.from_user.username) - await callback.message.answer( - text=msg_text.SEARCH, - reply_markup=arhive_search_kb - ) + await callback.message.answer(text=msg_text.SEARCH, reply_markup=arhive_search_kb) if liker_ids := await get_profile_likes(callback.from_user.id): await state.update_data(ids=liker_ids) @@ -72,9 +66,8 @@ async def _like_response(message: types.Message, state: FSMContext) -> None: user_id=profile.user_id.id, name=message.from_user.full_name, user_link=generate_user_link( - user_id=message.from_user.id, - username=message.from_user.username, - ) + user_id=message.from_user.id, username=message.from_user.username + ), ) """Отправка пользователю который ответил на лайк""" @@ -82,9 +75,8 @@ async def _like_response(message: types.Message, state: FSMContext) -> None: user_id=message.from_user.id, name=profile.name, user_link=generate_user_link( - user_id=profile.user_id.id, - username=profile.user_id.username, - ) + user_id=profile.user_id.id, username=profile.user_id.username + ), ) await del_like(message.from_user.id, profile.user_id.id) diff --git a/app/handlers/user/create_profile.py b/app/handlers/user/create_profile.py index 8850db8..f23ad0f 100644 --- a/app/handlers/user/create_profile.py +++ b/app/handlers/user/create_profile.py @@ -143,7 +143,7 @@ async def _description(message: types.Message, state: FSMContext): city=data["city"], latitude=data["latitude"], longitude=data["longitude"], - description=message.text + description=message.text, ) await state.clear() diff --git a/app/handlers/user/edit_profile.py b/app/handlers/user/edit_profile.py index 2a1f4ce..19d0d23 100644 --- a/app/handlers/user/edit_profile.py +++ b/app/handlers/user/edit_profile.py @@ -31,15 +31,13 @@ async def _disable_profile_command(message: types.Message, state: FSMContext) -> """Отключение профиля""" await state.set_state(DisableProfile.waiting) await update_profile_is_active_status(message.from_user.id, False) - await message.answer( - text=msg_text.DISABLE_PROFILE, - reply_markup=profile_return_kb() - ) + await message.answer(text=msg_text.DISABLE_PROFILE, reply_markup=profile_return_kb()) -@router.message(F.text.in_( - ["🔙 Вернуть профиль", "🔙 Return profile", "🔙 Повернути профіль"] -), DisableProfile.waiting) +@router.message( + F.text.in_(["🔙 Вернуть профиль", "🔙 Return profile", "🔙 Повернути профіль"]), + DisableProfile.waiting, +) async def _activate_profile_command(message: types.Message, state: FSMContext) -> None: await state.clear() await update_profile_is_active_status(message.from_user.id, True) diff --git a/app/handlers/user/invite.py b/app/handlers/user/invite.py index 41152cb..5534cf1 100644 --- a/app/handlers/user/invite.py +++ b/app/handlers/user/invite.py @@ -17,7 +17,6 @@ async def _invite_link_command(message: types.Message, user: Users) -> None: """Дает пользователю его реферальную ссылку""" bot_user = await bot.get_me() user_code: str = encode_base62(message.from_user.id) - await message.answer(msg_text.INVITE_FRIENDS.format( - user.referral, bot_user.username, user_code - ) + await message.answer( + msg_text.INVITE_FRIENDS.format(user.referral, bot_user.username, user_code) ) diff --git a/app/handlers/user/lang.py b/app/handlers/user/lang.py index 96f58ea..92e3f71 100644 --- a/app/handlers/user/lang.py +++ b/app/handlers/user/lang.py @@ -14,10 +14,7 @@ @router.message(Command("lang"), StateFilter(None)) async def _lang(message: types.Message) -> None: """Предлагает клавиатуру с доступными языками""" - await message.answer( - msg_text.CHANGE_LANG, - reply_markup=await lang_ikb() - ) + await message.answer(msg_text.CHANGE_LANG, reply_markup=await lang_ikb()) @router.callback_query(F.data.in_(["ru", "uk", "en"])) diff --git a/app/handlers/user/profile.py b/app/handlers/user/profile.py index ea116c5..56b5a8b 100644 --- a/app/handlers/user/profile.py +++ b/app/handlers/user/profile.py @@ -16,7 +16,4 @@ async def profile_command(message: types.Message) -> None: profile = await get_profile(message.from_user.id) await send_profile(message.from_user.id, profile) - await message.answer( - msg_text.PROFILE_MENU, - reply_markup=profile_kb, - ) + await message.answer(msg_text.PROFILE_MENU, reply_markup=profile_kb) diff --git a/app/handlers/user/sponsor.py b/app/handlers/user/sponsor.py index e37b5f2..ddd2b01 100644 --- a/app/handlers/user/sponsor.py +++ b/app/handlers/user/sponsor.py @@ -18,13 +18,14 @@ async def _sponsor_command(message: types.Message) -> None: description="Небольшая поддержка бота дающая доступ в закрытую группу спонсоров", payload="sponsor", currency="XTR", - prices=[types.LabeledPrice(label="XTR", amount=1)] + prices=[types.LabeledPrice(label="XTR", amount=1)], ) @router.pre_checkout_query() async def pre_checkout_query(event: types.PreCheckoutQuery) -> None: from utils.logging import logger + logger.debug(event) await event.answer(True) @@ -33,7 +34,6 @@ async def pre_checkout_query(event: types.PreCheckoutQuery) -> None: async def succesful_payment(message: types.Message) -> None: link = await bot.create_chat_invite_link(MODERATOR_GROUP, member_limit=1) await bot.refund_star_payment( - message.from_user.id, - message.successful_payment.telegram_payment_charge_id + message.from_user.id, message.successful_payment.telegram_payment_charge_id ) await message.answer(f"Твоя пригласительная ссылка: {link}") diff --git a/app/keyboards/__init__.py b/app/keyboards/__init__.py index fa8b2ad..e69de29 100644 --- a/app/keyboards/__init__.py +++ b/app/keyboards/__init__.py @@ -1,2 +0,0 @@ -from .default import * -from .inline import * diff --git a/app/keyboards/default/admin.py b/app/keyboards/default/admin.py index 3aba896..7db9153 100644 --- a/app/keyboards/default/admin.py +++ b/app/keyboards/default/admin.py @@ -18,10 +18,8 @@ def admin_menu_kb() -> ReplyKeyboardMarkup: [ KeyboardButton(text=_("📩 Рассылка")), ], - ], one_time_keyboard=True, - ) return kb @@ -35,7 +33,6 @@ def user_ban_or_unban_kb() -> ReplyKeyboardMarkup: ], [ KeyboardButton(text=_("💊 Разбанить пользователей")), - ], ], one_time_keyboard=True, diff --git a/app/keyboards/default/base.py b/app/keyboards/default/base.py index ee43ed9..6a2c382 100644 --- a/app/keyboards/default/base.py +++ b/app/keyboards/default/base.py @@ -6,32 +6,31 @@ from loader import _ -from .kb_generator import simple_kb_generator as gen +from .kb_generator import simple_kb_generator as kb_gen del_kb = ReplyKeyboardRemove() -cancel_kb: ReplyKeyboardMarkup = gen( - ["/cancel"] -) -profile_kb: ReplyKeyboardMarkup = gen( +cancel_kb: ReplyKeyboardMarkup = kb_gen(["/cancel"]) + +profile_kb: ReplyKeyboardMarkup = kb_gen( ["🔄", "🖼", "✍️", "❌"], - ["🔍"] + ["🔍"], ) -menu_kb: ReplyKeyboardMarkup = gen( +menu_kb: ReplyKeyboardMarkup = kb_gen( ["🔍", "👤", "🗄"], ["✉️"], ) -search_kb: ReplyKeyboardMarkup = gen( +search_kb: ReplyKeyboardMarkup = kb_gen( ["❤️", "💢", "👎"], - ["💤"] + ["💤"], ) -arhive_search_kb: ReplyKeyboardMarkup = gen( +arhive_search_kb: ReplyKeyboardMarkup = kb_gen( ["❤️", "👎"], - ["💤"] + ["💤"], ) @@ -47,6 +46,7 @@ def profile_return_kb() -> ReplyKeyboardMarkup: ) return kb + # async def report_kb() -> ReplyKeyboardMarkup: # kb = ReplyKeyboardMarkup( # resize_keyboard=True, diff --git a/app/keyboards/default/create_profile.py b/app/keyboards/default/create_profile.py index 60fd3d0..2042e0f 100644 --- a/app/keyboards/default/create_profile.py +++ b/app/keyboards/default/create_profile.py @@ -37,6 +37,7 @@ def find_gender_kb() -> ReplyKeyboardMarkup: ) return kb + # async def contact_keyboard() -> ReplyKeyboardMarkup: # kb = ReplyKeyboardMarkup( # resize_keyboard=True, diff --git a/app/keyboards/default/kb_generator.py b/app/keyboards/default/kb_generator.py index c1141b1..0565760 100644 --- a/app/keyboards/default/kb_generator.py +++ b/app/keyboards/default/kb_generator.py @@ -4,11 +4,13 @@ ) -def simple_kb_generator(*buttons_list: list, one_time: bool = True, resize: bool = True) -> ReplyKeyboardMarkup: +def simple_kb_generator( + *buttons_list: list, one_time: bool = True, resize: bool = True +) -> ReplyKeyboardMarkup: """ Небольшой генератор клавиатуры. !Не желатьельно использовать с текстом который требует перевода. - + :param buttons: строки с названиями кнопок (будут располагаться в одном ряду) :param one_time: скрывать ли клавиатуру после нажатия (по умолчанию True) :param resize: уменьшать ли клавиатуру (по умолчанию True) @@ -21,7 +23,5 @@ def simple_kb_generator(*buttons_list: list, one_time: bool = True, resize: bool kb += [KeyboardButton(text=btn_text)] keyboard.append(kb) return ReplyKeyboardMarkup( - keyboard=keyboard, - resize_keyboard=resize, - one_time_keyboard=one_time + keyboard=keyboard, resize_keyboard=resize, one_time_keyboard=one_time ) diff --git a/app/keyboards/inline/report.py b/app/keyboards/inline/report.py index 41eb12a..d54dcde 100644 --- a/app/keyboards/inline/report.py +++ b/app/keyboards/inline/report.py @@ -6,21 +6,19 @@ from loader import _ -def block_user_ikb(user) -> InlineKeyboardMarkup: +def block_user_ikb(user_id: int, username: str) -> InlineKeyboardMarkup: ikb = InlineKeyboardMarkup( resize_keyboard=True, - inline_keyboard=[ [ InlineKeyboardButton( - text=_("☠️ Заблокировать пользователя {}").format(user.username), - callback_data=f"block_user_{user.id}", + text=_("☠️ Заблокировать пользователя {}").format(username), + callback_data=f"block_user_{user_id}", ), ], [ InlineKeyboardButton(text=_("Отклонить"), callback_data="..."), ], ], - ) return ikb diff --git a/app/others/commands.py b/app/others/commands.py index 5b84bde..ba4ee8f 100644 --- a/app/others/commands.py +++ b/app/others/commands.py @@ -19,7 +19,7 @@ def get_admins_commands(lang: str = "en"): commands.extend( [ BotCommand(command="/admin", description=_("admin panel", locale=lang)), - BotCommand(command="/stats", description=_("stats", locale=lang)) + BotCommand(command="/stats", description=_("stats", locale=lang)), ] ) return commands @@ -36,9 +36,7 @@ async def set_default_commands() -> None: async def set_admins_commands(id: int) -> None: - await bot.set_my_commands( - get_admins_commands(), scope=BotCommandScopeChat(chat_id=id) - ) + await bot.set_my_commands(get_admins_commands(), scope=BotCommandScopeChat(chat_id=id)) for lang in i18n.available_locales: await bot.set_my_commands( get_admins_commands(lang), diff --git a/database/__init__.py b/database/__init__.py index 7f0e5dd..e69de29 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -1,2 +0,0 @@ -from .service import * -from .connect import * diff --git a/database/connect.py b/database/connect.py index a06e25e..0de757a 100644 --- a/database/connect.py +++ b/database/connect.py @@ -1,20 +1,21 @@ -from peewee import PostgresqlDatabase, SqliteDatabase,Model +from peewee import PostgresqlDatabase, SqliteDatabase, Model -from data.config import DB_NAME, DB_HOST ,DB_PORT, DB_USER, DB_PASS, DIR +from data.config import DB_NAME, DB_HOST, DB_PORT, DB_USER, DB_PASS, DIR from utils.logging import logger if DB_NAME and DB_HOST and DB_PORT and DB_USER and DB_PASS: db = PostgresqlDatabase(DB_NAME, host=DB_HOST, port=DB_PORT, user=DB_USER, password=DB_PASS) - logger.info('Database: PostgreSql') - + logger.info("Database: PostgreSql") + else: db = SqliteDatabase(f"{DIR}/database/db.sqlite3") - logger.info('Database: Sqlite') - + logger.info("Database: Sqlite") + db.connect() + class BaseModel(Model): class Meta: - database = db \ No newline at end of file + database = db diff --git a/database/models/likes.py b/database/models/likes.py index abf249c..5abf4b0 100644 --- a/database/models/likes.py +++ b/database/models/likes.py @@ -5,5 +5,5 @@ class Likes(BaseModel): - liker_id = ForeignKeyField(Users, backref='likes_given') - liked_id = ForeignKeyField(Users, backref='likes_received') + liker_id = ForeignKeyField(Users, backref="likes_given") + liked_id = ForeignKeyField(Users, backref="likes_received") diff --git a/database/models/migrations.py b/database/models/migrations.py index c20b852..2009ccc 100644 --- a/database/models/migrations.py +++ b/database/models/migrations.py @@ -2,6 +2,7 @@ from .users import Users from .profile import Profile from .likes import Likes + # Подключение к SQLite from datetime import datetime from data.config import DIR @@ -22,12 +23,12 @@ def json_serial(obj): return obj.isoformat() # Преобразование в ISO 8601 raise TypeError(f"Type {type(obj)} not serializable") - with open(file, 'w') as f: + with open(file, "w") as f: json.dump(data, f, default=json_serial) def import_data(db, model, file): - with open(file, 'r') as f: + with open(file, "r") as f: data = json.load(f) # Импорт данных @@ -43,6 +44,7 @@ def import_data(db, model, file): with db.atomic(): model.insert_many(rows).execute() + # import_data(db, Profile, f"{DIR}/profile.json") # import_data(db, Profile, f"{DIR}/profile.json") # import_data(db, Likes, "like.json") diff --git a/database/models/profile.py b/database/models/profile.py index 915507f..2708757 100644 --- a/database/models/profile.py +++ b/database/models/profile.py @@ -4,14 +4,14 @@ class Profile(BaseModel): - user_id = ForeignKeyField(Users, backref='profile', primary_key=True) - name = CharField(max_length=50) - gender = CharField(choices=['male', 'female'], index=True) - find_gender = CharField(choices=['male', 'female', 'all'], index=True) - city = CharField(max_length=50) - latitude = FloatField() - longitude = FloatField() - photo = TextField() - age = IntegerField(index=True) - description = CharField(max_length=1000) - is_active = BooleanField(default=True, index=True) + user_id = ForeignKeyField(Users, backref="profile", primary_key=True) + name = CharField(max_length=50) + gender = CharField(choices=["male", "female"], index=True) + find_gender = CharField(choices=["male", "female", "all"], index=True) + city = CharField(max_length=50) + latitude = FloatField() + longitude = FloatField() + photo = TextField() + age = IntegerField(index=True) + description = CharField(max_length=1000) + is_active = BooleanField(default=True, index=True) diff --git a/database/models/users.py b/database/models/users.py index 94bffc6..fa2a211 100644 --- a/database/models/users.py +++ b/database/models/users.py @@ -4,9 +4,9 @@ class Users(BaseModel): - id=BigIntegerField(primary_key=True) - username = CharField(default=None, null=True) - language = CharField(default='en') - referral=IntegerField(default=0) - is_banned=BooleanField(default=False) - created_at = DateTimeField(default=lambda: datetime.utcnow()) \ No newline at end of file + id = BigIntegerField(primary_key=True) + username = CharField(default=None, null=True) + language = CharField(default="en") + referral = IntegerField(default=0) + is_banned = BooleanField(default=False) + created_at = DateTimeField(default=lambda: datetime.utcnow()) diff --git a/database/service/__init__.py b/database/service/__init__.py index b5b980c..e69de29 100644 --- a/database/service/__init__.py +++ b/database/service/__init__.py @@ -1,2 +0,0 @@ -# from .admin import * -from .users import * \ No newline at end of file diff --git a/database/service/profile.py b/database/service/profile.py index b7d047d..7fbfb27 100644 --- a/database/service/profile.py +++ b/database/service/profile.py @@ -33,9 +33,16 @@ async def edit_profile_description(user_id, description): async def create_profile( - user_id: int, gender: str, find_gender: str, - photo: str, name: str, age: int, city: str, - latitude: str, longitude: str, description: str, + user_id: int, + gender: str, + find_gender: str, + photo: str, + name: str, + age: int, + city: str, + latitude: str, + longitude: str, + description: str, ): """Создает профиль пользователя, если профиль есть - удаляет его""" if await get_profile(user_id): diff --git a/database/service/search.py b/database/service/search.py index a75fc38..8217bcd 100644 --- a/database/service/search.py +++ b/database/service/search.py @@ -7,7 +7,7 @@ async def elastic_search_user_ids(user_id: int, age_range: int = 3, distance: float = 0.1) -> list: """ Ищет подходящие анкеты для пользователя и возвращает список id пользователей, - которые подходят под критерии поиска. + которые подходят под критерии поиска. Поиск идет по координатам и параметрам анкеты """ profile: Profile = await get_profile(user_id) diff --git a/database/service/stats.py b/database/service/stats.py index 7637c9c..04b4260 100644 --- a/database/service/stats.py +++ b/database/service/stats.py @@ -1,17 +1,15 @@ from peewee import fn, Case -from typing import Any - from ..models.users import Users from ..models.profile import Profile async def get_all_users_registration_data() -> list: - users = Users.select(Users.id, Users.username, Users.created_at).order_by( - Users.referral.desc() - ) + users = Users.select(Users.id, Users.username, Users.created_at).order_by(Users.referral.desc()) # Формируем данные в виде списка словарей - registration_data = [{"username": user.username, "timestamp": user.created_at} for user in users] + registration_data = [ + {"username": user.username, "timestamp": user.created_at} for user in users + ] return registration_data @@ -19,7 +17,7 @@ async def get_users_stats() -> tuple[int, int]: """Возвращает количество пользователей и заблокированных пользователей""" query = Users.select( fn.COUNT(Users.id).alias("count"), - fn.SUM(Case(Users.is_banned, [(True, 1)], 0)).alias("banned_count") + fn.SUM(Case(Users.is_banned, [(True, 1)], 0)).alias("banned_count"), ) return query.dicts().get() diff --git a/main.py b/main.py index 89f5f8a..b4d4686 100644 --- a/main.py +++ b/main.py @@ -3,12 +3,15 @@ from loader import dp, bot from utils.logging import logger +from data.config import SKIP_UPDATES from app.middlewares import setup_middlewares +from app.handlers import setup_handlers async def on_startup() -> None: from app.others.commands import set_default_commands + await set_default_commands() logger.info("~ Bot startup") @@ -16,16 +19,14 @@ async def on_startup() -> None: async def on_shutdown() -> None: logger.info("~ Bot shutting down...") - + async def main(): setup_middlewares(dp) + setup_handlers(dp) dp.startup.register(on_startup) dp.shutdown.register(on_shutdown) - from app.handlers import setup_handlers - setup_handlers(dp) - from data.config import SKIP_UPDATES - await bot(DeleteWebhook(drop_pending_updates=SKIP_UPDATES)) + await bot(DeleteWebhook(drop_pending_updates=SKIP_UPDATES)) await dp.start_polling(bot) diff --git a/utils/base62.py b/utils/base62.py index fcb4096..dba25e6 100644 --- a/utils/base62.py +++ b/utils/base62.py @@ -10,7 +10,7 @@ def encode_base62(num: int) -> str: while num: num, rem = divmod(num, base) encoded.append(BASE62_ALPHABET[rem]) - return ''.join(reversed(encoded)) + return "".join(reversed(encoded)) def decode_base62(encoded_str: str) -> str: diff --git a/utils/graphs.py b/utils/graphs.py index 193d2bc..e1cd9c8 100644 --- a/utils/graphs.py +++ b/utils/graphs.py @@ -7,7 +7,7 @@ from data.config import IMAGES_DIR -registration_photo_path = f'{IMAGES_DIR}/registration_graph.png' +registration_photo_path = f"{IMAGES_DIR}/registration_graph.png" def get_day_period(days: int = 30): @@ -29,15 +29,15 @@ def create_user_registration_graph(data, path): """Создает график новых пользователей в заданом периоде""" df = pd.DataFrame(data) - df['timestamp'] = pd.to_datetime(df['timestamp']) + df["timestamp"] = pd.to_datetime(df["timestamp"]) - df['date'] = df['timestamp'].dt.date + df["date"] = df["timestamp"].dt.date today, ago = get_day_period(30) start_date = datetime(int(ago.year), int(ago.month), int(ago.day)) end_date = datetime(int(today.year), int(today.month), int(today.day)) all_dates = pd.date_range(start=start_date, end=end_date).date - daily_counts = df.groupby('date')['username'].nunique() + daily_counts = df.groupby("date")["username"].nunique() daily_counts_full = pd.Series(daily_counts, index=all_dates).fillna(0) @@ -47,16 +47,16 @@ def create_user_registration_graph(data, path): sns.barplot( x=daily_counts_full.index, y=daily_counts_full, - palette='Blues_d', + palette="Blues_d", hue=daily_counts_full.index, - legend=False + legend=False, ) - plt.title('Приход пользователей за 30 дней', fontsize=16, fontweight='bold') - plt.xlabel('Дата', fontsize=12) - plt.ylabel('Количество уникальных пользователей', fontsize=12) + plt.title("Приход пользователей за 30 дней", fontsize=16, fontweight="bold") + plt.xlabel("Дата", fontsize=12) + plt.ylabel("Количество уникальных пользователей", fontsize=12) plt.xticks(rotation=45) - plt.grid(axis='y', linestyle='--', alpha=0.7) + plt.grid(axis="y", linestyle="--", alpha=0.7) plt.tight_layout() plt.savefig(path) diff --git a/utils/logging.py b/utils/logging.py index df263fb..dbf4177 100644 --- a/utils/logging.py +++ b/utils/logging.py @@ -4,9 +4,12 @@ logger.add( f"{DIR}/logs/logs.log", - format='[{time}] [{level}] [{file.name}:{line}] {message}', - level='DEBUG', - rotation='1 month', - compression='zip') + format="[{time}] [{level}] [{file.name}:{line}] {message}", + level="DEBUG", + rotation="1 month", + compression="zip", +) -getLogger('aiogram').addFilter(lambda r: r.getMessage().find('Field \'database_user\' doesn\'t exist in') == -1) +getLogger("aiogram").addFilter( + lambda r: r.getMessage().find("Field 'database_user' doesn't exist in") == -1 +) From b86b4ee5641552c574636d5d4196d1c3337cac20 Mon Sep 17 00:00:00 2001 From: Sima3443 Date: Sun, 2 Feb 2025 17:45:44 +0200 Subject: [PATCH 4/9] fixs --- app/filters/create_profile_filtres.py | 2 +- app/handlers/user/create_profile.py | 9 ++------- app/handlers/user/edit_profile.py | 1 - app/handlers/user/help.py | 3 +-- app/handlers/user/start.py | 7 ++----- app/keyboards/default/base.py | 2 ++ app/keyboards/default/create_profile.py | 1 + requirements.txt | Bin 1562 -> 1646 bytes 8 files changed, 9 insertions(+), 16 deletions(-) diff --git a/app/filters/create_profile_filtres.py b/app/filters/create_profile_filtres.py index 58c422e..bdbf4a2 100644 --- a/app/filters/create_profile_filtres.py +++ b/app/filters/create_profile_filtres.py @@ -36,7 +36,7 @@ class IsGender(Filter): async def __call__(self, message: Message) -> dict | bool: if message.text in gender_map: return {"gender": gender_map[message.text]} - return False + return class IsFindGender(Filter): diff --git a/app/handlers/user/create_profile.py b/app/handlers/user/create_profile.py index f23ad0f..40c4001 100644 --- a/app/handlers/user/create_profile.py +++ b/app/handlers/user/create_profile.py @@ -15,14 +15,9 @@ import app.filters.create_profile_filtres as filters -@router.message(F.text == "🔄", StateFilter(None)) -async def _retry_create_profile_command(message: types.Message, state: FSMContext): - """Запускает создания профиля заново""" - await _create_profile_command(message, state) - - # create profile -@router.message(filters.IsCreate()) +@router.message(F.text == "🔄", StateFilter(None)) +@router.message(filters.IsCreate(), StateFilter(None)) async def _create_profile_command(message: types.Message, state: FSMContext): """Начало создание профиля""" await message.answer(msg_text.GENDER, reply_markup=gender_kb()) diff --git a/app/handlers/user/edit_profile.py b/app/handlers/user/edit_profile.py index 19d0d23..ef66a30 100644 --- a/app/handlers/user/edit_profile.py +++ b/app/handlers/user/edit_profile.py @@ -39,7 +39,6 @@ async def _disable_profile_command(message: types.Message, state: FSMContext) -> DisableProfile.waiting, ) async def _activate_profile_command(message: types.Message, state: FSMContext) -> None: - await state.clear() await update_profile_is_active_status(message.from_user.id, True) await message.answer(msg_text.ACTIVATE_PROFILE_ALERT) await menu(message.from_user.id) diff --git a/app/handlers/user/help.py b/app/handlers/user/help.py index 26ca675..fb3217a 100644 --- a/app/handlers/user/help.py +++ b/app/handlers/user/help.py @@ -8,10 +8,9 @@ from app.handlers.msg_text import msg_text -photo = types.FSInputFile(f"{IMAGES_DIR}/new_logo.webp") - @router.message(Command("help"), StateFilter(None)) async def _help_command(message: types.Message) -> None: """Команда дающее небольшое описание бота""" + photo = types.FSInputFile(f"{IMAGES_DIR}/new_logo.webp") await message.answer_photo(photo=photo, caption=msg_text.INFO) diff --git a/app/handlers/user/start.py b/app/handlers/user/start.py index 42ce0b8..06bfc67 100644 --- a/app/handlers/user/start.py +++ b/app/handlers/user/start.py @@ -2,18 +2,14 @@ from aiogram.filters import CommandStart from aiogram.filters.state import StateFilter -from app.routers import start_router - from data.config import IMAGES_DIR - from database.service.profile import get_profile +from app.routers import start_router from app.handlers.msg_text import msg_text from app.keyboards.default.create_profile import start_kb from app.handlers.bot_utils import menu -photo = types.FSInputFile(f"{IMAGES_DIR}/new_logo.webp") - @start_router.message(CommandStart(), StateFilter(None)) async def _start_command(message: types.Message) -> None: @@ -21,6 +17,7 @@ async def _start_command(message: types.Message) -> None: if await get_profile(message.from_user.id): await menu(message.from_user.id) else: + photo = types.FSInputFile(f"{IMAGES_DIR}/new_logo.webp") await message.answer_photo( photo=photo, caption=msg_text.WELCOME, diff --git a/app/keyboards/default/base.py b/app/keyboards/default/base.py index 6a2c382..c61278f 100644 --- a/app/keyboards/default/base.py +++ b/app/keyboards/default/base.py @@ -26,11 +26,13 @@ search_kb: ReplyKeyboardMarkup = kb_gen( ["❤️", "💢", "👎"], ["💤"], + one_time=False, ) arhive_search_kb: ReplyKeyboardMarkup = kb_gen( ["❤️", "👎"], ["💤"], + one_time=False, ) diff --git a/app/keyboards/default/create_profile.py b/app/keyboards/default/create_profile.py index 2042e0f..14fb886 100644 --- a/app/keyboards/default/create_profile.py +++ b/app/keyboards/default/create_profile.py @@ -26,6 +26,7 @@ def gender_kb() -> ReplyKeyboardMarkup: def find_gender_kb() -> ReplyKeyboardMarkup: kb = ReplyKeyboardMarkup( + # input_field_placeholder="Выбрете кто вам инетересен:", resize_keyboard=True, keyboard=[ [ diff --git a/requirements.txt b/requirements.txt index 37630af709dae7b8f57156aceb1ad44f8ba1ca3a..c036aa58280202e4376f9e061d1ade4166104a89 100644 GIT binary patch delta 84 zcmbQm^NweO7>i&jLkUABLk@#25SlUQF&J* Date: Sun, 2 Feb 2025 21:38:48 +0200 Subject: [PATCH 5/9] fix bug --- app/handlers/user/lang.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/handlers/user/lang.py b/app/handlers/user/lang.py index 92e3f71..01b60c2 100644 --- a/app/handlers/user/lang.py +++ b/app/handlers/user/lang.py @@ -14,7 +14,7 @@ @router.message(Command("lang"), StateFilter(None)) async def _lang(message: types.Message) -> None: """Предлагает клавиатуру с доступными языками""" - await message.answer(msg_text.CHANGE_LANG, reply_markup=await lang_ikb()) + await message.answer(msg_text.CHANGE_LANG, reply_markup=lang_ikb()) @router.callback_query(F.data.in_(["ru", "uk", "en"])) From 61b7995cd328c21ccefb8ebb569aa0aba0c643ba Mon Sep 17 00:00:00 2001 From: Sima3443 Date: Sun, 2 Feb 2025 22:08:49 +0200 Subject: [PATCH 6/9] edit diagram and fix locales --- data/locales/bot.pot | 62 ++++++++++++------------- data/locales/en/LC_MESSAGES/bot.mo | Bin 9444 -> 9430 bytes data/locales/en/LC_MESSAGES/bot.po | 71 +++++++++++++---------------- data/locales/ru/LC_MESSAGES/bot.mo | Bin 11700 -> 11694 bytes data/locales/ru/LC_MESSAGES/bot.po | 63 +++++++++++++------------ data/locales/uk/LC_MESSAGES/bot.mo | Bin 11694 -> 11688 bytes data/locales/uk/LC_MESSAGES/bot.po | 63 +++++++++++++------------ readme.md | 6 +-- readmeru.md | 5 +- 9 files changed, 130 insertions(+), 140 deletions(-) diff --git a/data/locales/bot.pot b/data/locales/bot.pot index 78b8a65..e42cb99 100644 --- a/data/locales/bot.pot +++ b/data/locales/bot.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: bot VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2025-01-30 23:42+0200\n" +"POT-Creation-Date: 2025-02-02 22:05+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -121,33 +121,33 @@ msgid "" "Чтобы снова активировать её, просто нажмите на кнопку." msgstr "" -#: app/handlers/msg_text.py:116 +#: app/handlers/msg_text.py:118 msgid "" "✅ Ваша анкета успешно восстановлена! Теперь вы снова можете пользоваться " "ботом." msgstr "" -#: app/handlers/msg_text.py:120 +#: app/handlers/msg_text.py:122 msgid "" "Некорректный ответ. Пожалуйста, выбери на клавиатуре или напиши " "правильно. 📝" msgstr "" -#: app/handlers/msg_text.py:124 +#: app/handlers/msg_text.py:126 msgid "Превышен лимит символов. Пожалуйста, сократи сообщение. ✂️" msgstr "" -#: app/handlers/msg_text.py:128 +#: app/handlers/msg_text.py:130 msgid "" "Неверный формат фотографии! Пожалуйста, загрузите изображение в " "правильном формате. 🖼️" msgstr "" -#: app/handlers/msg_text.py:132 +#: app/handlers/msg_text.py:136 msgid "Неверный формат, возраст нужно указывать цифрами. 🔢" msgstr "" -#: app/handlers/msg_text.py:136 +#: app/handlers/msg_text.py:140 msgid "" "Приглашай друзей и получай бонус к своей анкете!\n" "\n" @@ -157,63 +157,63 @@ msgid "" "https://t.me/{}?start={}" msgstr "" -#: app/handlers/msg_text.py:140 +#: app/handlers/msg_text.py:146 msgid "Вы администратор!" msgstr "" -#: app/handlers/msg_text.py:144 +#: app/handlers/msg_text.py:150 msgid "" -" \n" -"👤 Пользователей: {}\t|🚫 Заблокированных: {} \n" +"\n" +"👤 Пользователей: {}\t|🚫 Заблокированных: {}\n" "\n" "📂 Анкет: {}\t|🔕 Неактивных: {}\n" "\n" -"🙍‍♂ Парней: {}\t|🙍‍♀ Девушек: {} \n" +"🙍‍♂ Парней: {}\t|🙍‍♀ Девушек: {}\n" msgstr "" -#: app/handlers/msg_text.py:154 +#: app/handlers/msg_text.py:160 msgid "Выберите язык, на который вы хотите переключиться: 🌐" msgstr "" -#: app/handlers/msg_text.py:158 +#: app/handlers/msg_text.py:164 msgid "Ваш язык успешно изменён! ✅" msgstr "" -#: app/handlers/msg_text.py:162 +#: app/handlers/msg_text.py:168 msgid "Появился новый пользователь, @{} | {}" msgstr "" -#: app/handlers/msg_text.py:166 +#: app/handlers/msg_text.py:172 msgid "" "Пользователь: @{} | {} отправил жалобу на анкету " "пользователя: @{} | {}" msgstr "" -#: app/handlers/msg_text.py:170 +#: app/handlers/msg_text.py:178 msgid "Панель управлением пользователями" msgstr "" -#: app/handlers/msg_text.py:174 +#: app/handlers/msg_text.py:182 msgid "💊 Укажите список пользовтелей для разблокировки в формате: 1234567, 234567" msgstr "" -#: app/handlers/msg_text.py:178 +#: app/handlers/msg_text.py:186 msgid "⚔️ Укажите список пользовтелей для блокировки в формате: 1234567, 234567" msgstr "" -#: app/handlers/msg_text.py:182 +#: app/handlers/msg_text.py:190 msgid "Пользователь: {} заблокирован" msgstr "" -#: app/handlers/msg_text.py:186 +#: app/handlers/msg_text.py:194 msgid "Укажите текст сообщение которое хотите отправить" msgstr "" -#: app/handlers/msg_text.py:190 +#: app/handlers/msg_text.py:198 msgid "✅ Ваша жалоба на пользователя отправлена на рассмотрение!" msgstr "" -#: app/handlers/msg_text.py:194 +#: app/handlers/msg_text.py:202 msgid "" "Укажите причину жалобы:\n" "🔞 Неприличный материал\n" @@ -235,11 +235,11 @@ msgstr "" msgid "📩 Рассылка" msgstr "" -#: app/keyboards/default/admin.py:34 +#: app/keyboards/default/admin.py:32 msgid "⚔️ Забанить пользователей" msgstr "" -#: app/keyboards/default/admin.py:37 +#: app/keyboards/default/admin.py:35 msgid "💊 Разбанить пользователей" msgstr "" @@ -259,15 +259,15 @@ msgstr "" msgid "Я девушка" msgstr "" -#: app/keyboards/default/create_profile.py:32 +#: app/keyboards/default/create_profile.py:33 msgid "Парни" msgstr "" -#: app/keyboards/default/create_profile.py:33 +#: app/keyboards/default/create_profile.py:34 msgid "Девушки" msgstr "" -#: app/keyboards/default/create_profile.py:34 +#: app/keyboards/default/create_profile.py:35 msgid "Все" msgstr "" @@ -279,7 +279,7 @@ msgstr "" msgid "☠️ Заблокировать пользователя {}" msgstr "" -#: app/keyboards/inline/report.py:18 +#: app/keyboards/inline/report.py:20 msgid "Отклонить" msgstr "" @@ -299,11 +299,11 @@ msgstr "" msgid "activate profile" msgstr "" -#: app/others/commands.py:20 +#: app/others/commands.py:21 msgid "admin panel" msgstr "" -#: app/others/commands.py:21 +#: app/others/commands.py:22 msgid "stats" msgstr "" diff --git a/data/locales/en/LC_MESSAGES/bot.mo b/data/locales/en/LC_MESSAGES/bot.mo index e88436d22831364bb6fa1e5deca33617ff65a73c..9a6b67852260d59b8cb73fbc7b627f7549440ba6 100644 GIT binary patch delta 1007 zcmXBS?@NT~Yp-gE9f_kK%Hq_4&bPeo+X z6nTTUW{X_HZcAhy{>C7hb404J9(}kPJ=ln|a4T-XHng#XcX1R+EeBW}#w;Gf0i27| z9x41U@P~<$O!%mh!6LTfcO1c3wa7vIh{M?E6{*27)cG&C8IxosmE`dv4&oK`a_TtV z!2rI)P58@K5II4xitA3{HC%zG{UW`16T8q)wK~k8X{WLwO8+uW1{1CO^3ryn} z?#G(2d!rokU!{nolFO)tAK(T2ftu&oGLc<)9@kP|-V^9=H|VF{G=N-IT2OD6!C}m! zcA$E>+o2}Zg009a$_~^#S!~5Ks0V$9n%Bd}(#|GP*QGF}h4v6=>+hi-A0z)ro|j)4 zLBlBqYn@Ij>I_)9@@I2jMR~@ud>%UzwZpcZh{ns_Ma_m|h9XrRr+TtSj~`Bi`}0mq SsM+bLd*aMko#n3~)A|QvReQSt delta 1020 zcmXBSUu?@!6u|K_rR{3=M|GRF_}RR8sC8Wt^=D=e)3QGpdszHgq@*#UHVc~Vm#h<6 zWSy*u$OMZeoPP;oj3A-p25RERn8u%|aW1SCIe;15Kz{kmK!1A){nVRQAeWU^)SD$SgI7^I z;H}JcXb)<_L&$T=QPem+xEn8{7CMa@x15iqosFUHJBSUM=mZ08{R7lb^Bnm{GGo28 zmD;S^j<&o-hLN4KH!ABLXO)ZoHY=8I6}qYeH9;d(6A6bbM|r(1JLQ|q#(V+yzVq?! bp2V51u8zdHcz47|^`)`{zIrR=Z+HF!i}->r diff --git a/data/locales/en/LC_MESSAGES/bot.po b/data/locales/en/LC_MESSAGES/bot.po index d4b0d6e..2f15929 100644 --- a/data/locales/en/LC_MESSAGES/bot.po +++ b/data/locales/en/LC_MESSAGES/bot.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2025-01-30 23:42+0200\n" +"POT-Creation-Date: 2025-02-02 22:05+0200\n" "PO-Revision-Date: 2024-09-07 14:40+0300\n" "Last-Translator: FULL NAME \n" "Language: en\n" @@ -154,33 +154,33 @@ msgstr "" "Your profile is temporarily disabled.\n" "To reactivate it, just click the button below." -#: app/handlers/msg_text.py:116 +#: app/handlers/msg_text.py:118 msgid "" "✅ Ваша анкета успешно восстановлена! Теперь вы снова можете пользоваться " "ботом." msgstr "✅ Your profile has been successfully restored! You can now use the bot." -#: app/handlers/msg_text.py:120 +#: app/handlers/msg_text.py:122 msgid "" "Некорректный ответ. Пожалуйста, выбери на клавиатуре или напиши " "правильно. 📝" msgstr "Incorrect response. Please choose from the keyboard or write correctly. 📝" -#: app/handlers/msg_text.py:124 +#: app/handlers/msg_text.py:126 msgid "Превышен лимит символов. Пожалуйста, сократи сообщение. ✂️" msgstr "Character limit exceeded. Please shorten the message. ✂️" -#: app/handlers/msg_text.py:128 +#: app/handlers/msg_text.py:130 msgid "" "Неверный формат фотографии! Пожалуйста, загрузите изображение в " "правильном формате. 🖼️" msgstr "Incorrect photo format! Please upload the image in the correct format. 🖼️" -#: app/handlers/msg_text.py:132 +#: app/handlers/msg_text.py:136 msgid "Неверный формат, возраст нужно указывать цифрами. 🔢" msgstr "Incorrect format, age should be specified in numbers. 🔢" -#: app/handlers/msg_text.py:136 +#: app/handlers/msg_text.py:140 msgid "" "Приглашай друзей и получай бонус к своей анкете!\n" "\n" @@ -196,39 +196,39 @@ msgstr "" "Link for friends:\n" "https://t.me/{}?start={}" -#: app/handlers/msg_text.py:140 +#: app/handlers/msg_text.py:146 msgid "Вы администратор!" msgstr "You're the administrator!" -#: app/handlers/msg_text.py:144 +#: app/handlers/msg_text.py:150 msgid "" -" \n" -"👤 Пользователей: {}\t|🚫 Заблокированных: {} \n" +"\n" +"👤 Пользователей: {}\t|🚫 Заблокированных: {}\n" "\n" "📂 Анкет: {}\t|🔕 Неактивных: {}\n" "\n" -"🙍‍♂ Парней: {}\t|🙍‍♀ Девушек: {} \n" +"🙍‍♂ Парней: {}\t|🙍‍♀ Девушек: {}\n" msgstr "" " \n" "👤 Users: {}\t||🚫 Blocked: {} \n" "\n" -"📂 Questionnaires: {}{\t||🔕 Inactive: {}\n" +"📂 Profile: {}\t||🔕 Inactive: {}\n" "\n" "🙍‍♂ Guys: {}\t|🙍‍♀ Girls: {} \n" -#: app/handlers/msg_text.py:154 +#: app/handlers/msg_text.py:160 msgid "Выберите язык, на который вы хотите переключиться: 🌐" msgstr "Select the language you want to switch to: 🌐" -#: app/handlers/msg_text.py:158 +#: app/handlers/msg_text.py:164 msgid "Ваш язык успешно изменён! ✅" msgstr "Your language has been successfully changed! ✅" -#: app/handlers/msg_text.py:162 +#: app/handlers/msg_text.py:168 msgid "Появился новый пользователь, @{} | {}" msgstr "There's a new user, @{} | | {}" -#: app/handlers/msg_text.py:166 +#: app/handlers/msg_text.py:172 msgid "" "Пользователь: @{} | {} отправил жалобу на анкету " "пользователя: @{} | {}" @@ -236,31 +236,31 @@ msgstr "" "User: @{} | {} sent a complaint about the profile ofuser: " "@{} | {}" -#: app/handlers/msg_text.py:170 +#: app/handlers/msg_text.py:178 msgid "Панель управлением пользователями" msgstr "User management panel" -#: app/handlers/msg_text.py:174 +#: app/handlers/msg_text.py:182 msgid "💊 Укажите список пользовтелей для разблокировки в формате: 1234567, 234567" msgstr "💊 Specify the list of users to unlock in the format: 1234567, 234567" -#: app/handlers/msg_text.py:178 +#: app/handlers/msg_text.py:186 msgid "⚔️ Укажите список пользовтелей для блокировки в формате: 1234567, 234567" msgstr "⚔️ Specify the list of users to block in the format: 1234567, 234567" -#: app/handlers/msg_text.py:182 +#: app/handlers/msg_text.py:190 msgid "Пользователь: {} заблокирован" msgstr "User: {} blocked" -#: app/handlers/msg_text.py:186 +#: app/handlers/msg_text.py:194 msgid "Укажите текст сообщение которое хотите отправить" msgstr "Specify the text of the message you want to send" -#: app/handlers/msg_text.py:190 +#: app/handlers/msg_text.py:198 msgid "✅ Ваша жалоба на пользователя отправлена на рассмотрение!" msgstr "✅ Your user complaint has been sent for review!" -#: app/handlers/msg_text.py:194 +#: app/handlers/msg_text.py:202 msgid "" "Укажите причину жалобы:\n" "🔞 Неприличный материал\n" @@ -285,11 +285,11 @@ msgstr "👤 Users" msgid "📩 Рассылка" msgstr "📩 Mailing list" -#: app/keyboards/default/admin.py:34 +#: app/keyboards/default/admin.py:32 msgid "⚔️ Забанить пользователей" msgstr "⚔️ Ban users" -#: app/keyboards/default/admin.py:37 +#: app/keyboards/default/admin.py:35 msgid "💊 Разбанить пользователей" msgstr "💊 Unban users" @@ -309,15 +309,15 @@ msgstr "I'm male" msgid "Я девушка" msgstr "I'm female" -#: app/keyboards/default/create_profile.py:32 +#: app/keyboards/default/create_profile.py:33 msgid "Парни" msgstr "Men" -#: app/keyboards/default/create_profile.py:33 +#: app/keyboards/default/create_profile.py:34 msgid "Девушки" msgstr "Women" -#: app/keyboards/default/create_profile.py:34 +#: app/keyboards/default/create_profile.py:35 msgid "Все" msgstr "All" @@ -329,7 +329,7 @@ msgstr "View👀" msgid "☠️ Заблокировать пользователя {}" msgstr "☠️ Block user {}" -#: app/keyboards/inline/report.py:18 +#: app/keyboards/inline/report.py:20 msgid "Отклонить" msgstr "Reject" @@ -349,17 +349,10 @@ msgstr "additional description" msgid "activate profile" msgstr "activate profile" -#: app/others/commands.py:20 +#: app/others/commands.py:21 msgid "admin panel" msgstr "admin panel" -#: app/others/commands.py:21 +#: app/others/commands.py:22 msgid "stats" msgstr "stats" - -#~ msgid "Отменить жалобу" -#~ msgstr "Cancel the report" - -#~ msgid "📱 Отправить" -#~ msgstr "" - diff --git a/data/locales/ru/LC_MESSAGES/bot.mo b/data/locales/ru/LC_MESSAGES/bot.mo index 49674d62e2bc395610bc2933fbd57f5137b4409d..95a81d4390c330421c992c751572cb7ca1d93aa9 100644 GIT binary patch delta 1004 zcmXBRO-NKx7{>8;n3|?r^I@6Uq|TizOPhh=GP9VlK_U8tSr~1aFhyu1fkH|~=bUFI|1^I+WzUL8 z#V7I_Z?6*>#a_Qi7=K|6`qqnVz*pQfXF7CM>YQm+pv{g*-8pHf>*JO0ZyI9 zyI76yFpFP9w#ZoqySeTXPT)=)s1g~(N$kWbx^2fk?7%Th;S!oyy;Kj$zO&rDr+=fTCicl&&xC4jqy+`B@w&FR8 z-s1C!$Q=K#)ahssv*{?`wGCVr?_&b(1qQ5@6;utvQ4ua7Ey&pS#--qK(FNv?Ww^k8zlIq{2WweV#y6wgafL zEx9kfHD1SwN1PM>q*L_wxr@G29(UF64;fY>X_=O_FPU}&wHMcTP1A60#OtV>b}PP< R9>+8z&U7N^zG?Up{0CoVg`5BY delta 994 zcmY+?&r6g+9LMqRrn%d;wbr(4nc1VZZI+U)TL&vwqf?}&1Yrx}5*?&Ecv(SXpTi2} z!L@bq5KAdq;GrMTQ}hqip^HDdNFZs7C!vCf4w3Z!Hm6RnnR#aBJ2Ri>MdEehLCl^P zk>wJR5q#zrd532_BBl5nL+INfvJ-32k0;TKaomoVuobUh6vuHA-y>VgO(t7-8?0*He80cppNR=CS58H7QXRyg9(u1<%aSQ{T z`ZUhqKKz8u_|J^5IW2uumL%wT*OxFMmQVYpho);+wl()tu2?iMlS>3F^iowCfili@gLZNSII@Qoxow7 z!Z8eoO}1}P54?%ZC`V1Saa^JM99bfxTt9`cu!s6md(32eAG`SQ1Y`IMEv&0G*|wo( z8#!*W&7fvGftu}8)E8Pu%{FwxM4Lm6He6?-&7sbFiD}}IH5&T#NdnPqhfuT4IUkBb yMb2aQHP<%F$}g9+VF diff --git a/data/locales/ru/LC_MESSAGES/bot.po b/data/locales/ru/LC_MESSAGES/bot.po index 21f7ed5..398e8d0 100644 --- a/data/locales/ru/LC_MESSAGES/bot.po +++ b/data/locales/ru/LC_MESSAGES/bot.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2025-01-30 23:42+0200\n" +"POT-Creation-Date: 2025-02-02 22:05+0200\n" "PO-Revision-Date: 2024-09-07 14:40+0300\n" "Last-Translator: FULL NAME \n" "Language: ru\n" @@ -155,7 +155,7 @@ msgstr "" "\n" "Чтобы снова активировать её, просто нажмите на кнопку ниже." -#: app/handlers/msg_text.py:116 +#: app/handlers/msg_text.py:118 msgid "" "✅ Ваша анкета успешно восстановлена! Теперь вы снова можете пользоваться " "ботом." @@ -163,7 +163,7 @@ msgstr "" "✅ Ваша анкета успешно восстановлена! Теперь вы снова можете пользоваться " "ботом." -#: app/handlers/msg_text.py:120 +#: app/handlers/msg_text.py:122 msgid "" "Некорректный ответ. Пожалуйста, выбери на клавиатуре или напиши " "правильно. 📝" @@ -171,11 +171,11 @@ msgstr "" "Некорректный ответ. Пожалуйста, выбери на клавиатуре или напиши " "правильно. 📝" -#: app/handlers/msg_text.py:124 +#: app/handlers/msg_text.py:126 msgid "Превышен лимит символов. Пожалуйста, сократи сообщение. ✂️" msgstr "Превышен лимит символов. Пожалуйста, сократи сообщение. ✂️" -#: app/handlers/msg_text.py:128 +#: app/handlers/msg_text.py:130 msgid "" "Неверный формат фотографии! Пожалуйста, загрузите изображение в " "правильном формате. 🖼️" @@ -183,11 +183,11 @@ msgstr "" "Неверный формат фотографии! Пожалуйста, загрузите изображение в " "правильном формате. 🖼️" -#: app/handlers/msg_text.py:132 +#: app/handlers/msg_text.py:136 msgid "Неверный формат, возраст нужно указывать цифрами. 🔢" msgstr "Неверный формат, возраст нужно указывать цифрами. 🔢" -#: app/handlers/msg_text.py:136 +#: app/handlers/msg_text.py:140 msgid "" "Приглашай друзей и получай бонус к своей анкете!\n" "\n" @@ -203,18 +203,18 @@ msgstr "" "Ссылка для друзей:\n" "https://t.me/{}?start={}" -#: app/handlers/msg_text.py:140 +#: app/handlers/msg_text.py:146 msgid "Вы администратор!" msgstr "Вы администратор!" -#: app/handlers/msg_text.py:144 +#: app/handlers/msg_text.py:150 msgid "" -" \n" -"👤 Пользователей: {}\t|🚫 Заблокированных: {} \n" +"\n" +"👤 Пользователей: {}\t|🚫 Заблокированных: {}\n" "\n" "📂 Анкет: {}\t|🔕 Неактивных: {}\n" "\n" -"🙍‍♂ Парней: {}\t|🙍‍♀ Девушек: {} \n" +"🙍‍♂ Парней: {}\t|🙍‍♀ Девушек: {}\n" msgstr "" " \n" "👤 Пользователей: {}\t|🚫 Заблокированных: {} \n" @@ -223,19 +223,19 @@ msgstr "" "\n" "🙍‍♂ Парней: {}\t|🙍‍♀ Девушек: {} \n" -#: app/handlers/msg_text.py:154 +#: app/handlers/msg_text.py:160 msgid "Выберите язык, на который вы хотите переключиться: 🌐" msgstr "Выберите язык, на который вы хотите переключиться: 🌐" -#: app/handlers/msg_text.py:158 +#: app/handlers/msg_text.py:164 msgid "Ваш язык успешно изменён! ✅" msgstr "Ваш язык успешно изменён! ✅" -#: app/handlers/msg_text.py:162 +#: app/handlers/msg_text.py:168 msgid "Появился новый пользователь, @{} | {}" msgstr "Появился новый пользователь, @{} | {}" -#: app/handlers/msg_text.py:166 +#: app/handlers/msg_text.py:172 msgid "" "Пользователь: @{} | {} отправил жалобу на анкету " "пользователя: @{} | {}" @@ -243,31 +243,31 @@ msgstr "" "Пользователь: @{} | {} отправил жалобу на анкету " "пользователя: @{} | {}" -#: app/handlers/msg_text.py:170 +#: app/handlers/msg_text.py:178 msgid "Панель управлением пользователями" msgstr "Панель управлением пользователями" -#: app/handlers/msg_text.py:174 +#: app/handlers/msg_text.py:182 msgid "💊 Укажите список пользовтелей для разблокировки в формате: 1234567, 234567" msgstr "💊 Укажите список пользовтелей для разблокировки в формате: 1234567, 234567" -#: app/handlers/msg_text.py:178 +#: app/handlers/msg_text.py:186 msgid "⚔️ Укажите список пользовтелей для блокировки в формате: 1234567, 234567" msgstr "⚔️ Укажите список пользовтелей для блокировки в формате: 1234567, 234567" -#: app/handlers/msg_text.py:182 +#: app/handlers/msg_text.py:190 msgid "Пользователь: {} заблокирован" msgstr "Пользователь: {} заблокирован" -#: app/handlers/msg_text.py:186 +#: app/handlers/msg_text.py:194 msgid "Укажите текст сообщение которое хотите отправить" msgstr "Укажите текст сообщение которое хотите отправить" -#: app/handlers/msg_text.py:190 +#: app/handlers/msg_text.py:198 msgid "✅ Ваша жалоба на пользователя отправлена на рассмотрение!" msgstr "✅ Ваша жалоба на пользователя отправлена на рассмотрение!" -#: app/handlers/msg_text.py:194 +#: app/handlers/msg_text.py:202 msgid "" "Укажите причину жалобы:\n" "🔞 Неприличный материал\n" @@ -295,11 +295,11 @@ msgstr "👤 Пользователи" msgid "📩 Рассылка" msgstr "📩 Рассылка" -#: app/keyboards/default/admin.py:34 +#: app/keyboards/default/admin.py:32 msgid "⚔️ Забанить пользователей" msgstr "⚔️ Забанить пользователей" -#: app/keyboards/default/admin.py:37 +#: app/keyboards/default/admin.py:35 msgid "💊 Разбанить пользователей" msgstr "💊 Разбанить пользователей" @@ -319,15 +319,15 @@ msgstr "Я парень" msgid "Я девушка" msgstr "Я девушка" -#: app/keyboards/default/create_profile.py:32 +#: app/keyboards/default/create_profile.py:33 msgid "Парни" msgstr "Парни" -#: app/keyboards/default/create_profile.py:33 +#: app/keyboards/default/create_profile.py:34 msgid "Девушки" msgstr "Девушки" -#: app/keyboards/default/create_profile.py:34 +#: app/keyboards/default/create_profile.py:35 msgid "Все" msgstr "Все" @@ -339,7 +339,7 @@ msgstr "Посмотреть" msgid "☠️ Заблокировать пользователя {}" msgstr "☠️ Заблокировать пользователя {}" -#: app/keyboards/inline/report.py:18 +#: app/keyboards/inline/report.py:20 msgid "Отклонить" msgstr "Отклонить" @@ -359,11 +359,11 @@ msgstr "дополнительное описание" msgid "activate profile" msgstr "активировать профиль" -#: app/others/commands.py:20 +#: app/others/commands.py:21 msgid "admin panel" msgstr "админ панель" -#: app/others/commands.py:21 +#: app/others/commands.py:22 msgid "stats" msgstr "статистика" @@ -372,4 +372,3 @@ msgstr "статистика" #~ msgid "📱 Отправить" #~ msgstr "" - diff --git a/data/locales/uk/LC_MESSAGES/bot.mo b/data/locales/uk/LC_MESSAGES/bot.mo index 911504154d96db54a6704d10680d345776d8c66e..7785a47d432bcfa96ca32f5b5d70261555c9456b 100644 GIT binary patch delta 988 zcmXZaUr1A77{~G7(B_)WW!W;DYiVV+7VEGPi;^Ot)kUPyg{?Fbx>)J<8jAe6k0U?4=_(+LiI-uFGv`#$e^p7S{VFn%qZdLikn zU3!NTRniD19MV$!jUKcwma4H4-PnpwjN&3}$KALe4a{O5Um{1VhhRUR#9qu`4bD52 z`j?>0!T<|yvh-mZ58y1`!|)R6IDWz_786Hv^)`X#P1D8K z6`qP*+S8Cb> ziCQ~BVdz%c2U)$$oAne0^->%3P+(sV3Sndqy@as!A14_2-FxTWbMBlo4-!ujS9Ig8 zh)m>*T*5~lkr%kBKx6^VVgQQ^MT&3*dT|3P*ogD78F%0T3}YHI_!0>%C)liEC$?iB zmg0;e#$19N3rQCIWa+>jjNvqnV6<4|7=FfnY%CF3gm2JZ|AtMtlc-MAf14C6aIi+P5hMFzH~&_}&1?K#>Thp-E?xCHl?5gboqH5z!&C2|KdxR*^? z{9YmQl=tJR$Tdt6^cfaa(MEiQb9sI+;H)Ui9IKI!kSKCViQ#VSKpn^MA$~=>x4oKE zfi%XMTS(QVWVv%*#ZKlSJdVS-2VLBLl>19FgEkgs@H)o09#xeoJc@s?0ps+A_R9^t zfOqjS)~q5pT3C*gxD|6~mw3x+r?nRHh`C1O431-*{1T~gO3{Zcyck2f^f@Glgla`T z;bA<2dY#kTf&bpd&8%BkkJES_)wRygI*9GeYu7pdP%qm1?qe72kq->)-nIsv-X_t$ zX^-{V9dKL2o>td9O*1F*_nEWmdh?KHms`^m>vut+R|y3p^;$R*)x(yj{BfR@tUTya Zc>61JbyUj^nt$s8=6iL>dR{eE`VX0hiB13j diff --git a/data/locales/uk/LC_MESSAGES/bot.po b/data/locales/uk/LC_MESSAGES/bot.po index 25cf2ae..694cb36 100644 --- a/data/locales/uk/LC_MESSAGES/bot.po +++ b/data/locales/uk/LC_MESSAGES/bot.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2025-01-30 23:42+0200\n" +"POT-Creation-Date: 2025-02-02 22:05+0200\n" "PO-Revision-Date: 2024-09-07 14:40+0300\n" "Last-Translator: FULL NAME \n" "Language: uk\n" @@ -155,7 +155,7 @@ msgstr "" "\n" "Щоб знову активувати її, просто натисніть на кнопку нижче." -#: app/handlers/msg_text.py:116 +#: app/handlers/msg_text.py:118 msgid "" "✅ Ваша анкета успешно восстановлена! Теперь вы снова можете пользоваться " "ботом." @@ -164,7 +164,7 @@ msgstr "" "\n" "Тепер ви знову можете користуватися ботом." -#: app/handlers/msg_text.py:120 +#: app/handlers/msg_text.py:122 msgid "" "Некорректный ответ. Пожалуйста, выбери на клавиатуре или напиши " "правильно. 📝" @@ -172,11 +172,11 @@ msgstr "" "Некоректна відповідь. Будь ласка, оберіть на клавіатурі або напишіть " "правильно. 📝" -#: app/handlers/msg_text.py:124 +#: app/handlers/msg_text.py:126 msgid "Превышен лимит символов. Пожалуйста, сократи сообщение. ✂️" msgstr "Перевищено ліміт символів. Будь ласка, скоротіть повідомлення. ✂️" -#: app/handlers/msg_text.py:128 +#: app/handlers/msg_text.py:130 msgid "" "Неверный формат фотографии! Пожалуйста, загрузите изображение в " "правильном формате. 🖼️" @@ -184,11 +184,11 @@ msgstr "" "Невірний формат фотографії! Будь ласка, завантажте зображення у " "правильному форматі. 🖼️" -#: app/handlers/msg_text.py:132 +#: app/handlers/msg_text.py:136 msgid "Неверный формат, возраст нужно указывать цифрами. 🔢" msgstr "Невірний формат, вік потрібно вказувати цифрами. 🔢" -#: app/handlers/msg_text.py:136 +#: app/handlers/msg_text.py:140 msgid "" "Приглашай друзей и получай бонус к своей анкете!\n" "\n" @@ -204,18 +204,18 @@ msgstr "" "Посилання для друзів:\n" "https://t.me/{}?start={}" -#: app/handlers/msg_text.py:140 +#: app/handlers/msg_text.py:146 msgid "Вы администратор!" msgstr "Ви адміністратор!" -#: app/handlers/msg_text.py:144 +#: app/handlers/msg_text.py:150 msgid "" -" \n" -"👤 Пользователей: {}\t|🚫 Заблокированных: {} \n" +"\n" +"👤 Пользователей: {}\t|🚫 Заблокированных: {}\n" "\n" "📂 Анкет: {}\t|🔕 Неактивных: {}\n" "\n" -"🙍‍♂ Парней: {}\t|🙍‍♀ Девушек: {} \n" +"🙍‍♂ Парней: {}\t|🙍‍♀ Девушек: {}\n" msgstr "" " \n" "👤 Користувачів: {}\t|🚫 Заблокованих: {} \n" @@ -224,19 +224,19 @@ msgstr "" "\n" "🙍‍♂ Хлопців: {}\t|🙍‍♀ Дівчат: {} \n" -#: app/handlers/msg_text.py:154 +#: app/handlers/msg_text.py:160 msgid "Выберите язык, на который вы хотите переключиться: 🌐" msgstr "Виберіть мову, на яку ви хочете перемикнутися: 🌐" -#: app/handlers/msg_text.py:158 +#: app/handlers/msg_text.py:164 msgid "Ваш язык успешно изменён! ✅" msgstr "Вашу мову успішно змінено! ✅" -#: app/handlers/msg_text.py:162 +#: app/handlers/msg_text.py:168 msgid "Появился новый пользователь, @{} | {}" msgstr "З'явився новий користувач, @{} | {}" -#: app/handlers/msg_text.py:166 +#: app/handlers/msg_text.py:172 msgid "" "Пользователь: @{} | {} отправил жалобу на анкету " "пользователя: @{} | {}" @@ -244,31 +244,31 @@ msgstr "" "Користувач: @{} | {} надіслав скаргу на анкету користувача:" " @{} | {}" -#: app/handlers/msg_text.py:170 +#: app/handlers/msg_text.py:178 msgid "Панель управлением пользователями" msgstr "Панель управлінням користувачами" -#: app/handlers/msg_text.py:174 +#: app/handlers/msg_text.py:182 msgid "💊 Укажите список пользовтелей для разблокировки в формате: 1234567, 234567" msgstr "💊 Вкажіть список користувачів для розблокування у форматі: 1234567, 234567" -#: app/handlers/msg_text.py:178 +#: app/handlers/msg_text.py:186 msgid "⚔️ Укажите список пользовтелей для блокировки в формате: 1234567, 234567" msgstr "️⚔️ Вкажіть список користувачів для блокування у форматі: 1234567, 234567" -#: app/handlers/msg_text.py:182 +#: app/handlers/msg_text.py:190 msgid "Пользователь: {} заблокирован" msgstr "Користувач: {} заблокований" -#: app/handlers/msg_text.py:186 +#: app/handlers/msg_text.py:194 msgid "Укажите текст сообщение которое хотите отправить" msgstr "Вкажіть текст повідомлення, яке хочете надіслати" -#: app/handlers/msg_text.py:190 +#: app/handlers/msg_text.py:198 msgid "✅ Ваша жалоба на пользователя отправлена на рассмотрение!" msgstr "✅ Ваша скарга на користувача відправлена на розгляд!" -#: app/handlers/msg_text.py:194 +#: app/handlers/msg_text.py:202 msgid "" "Укажите причину жалобы:\n" "🔞 Неприличный материал\n" @@ -296,11 +296,11 @@ msgstr "👤 Користувачі" msgid "📩 Рассылка" msgstr "📩 Розсилка" -#: app/keyboards/default/admin.py:34 +#: app/keyboards/default/admin.py:32 msgid "⚔️ Забанить пользователей" msgstr "⚔️ Забанити користувачів" -#: app/keyboards/default/admin.py:37 +#: app/keyboards/default/admin.py:35 msgid "💊 Разбанить пользователей" msgstr "💊 Розбанити користувачів" @@ -320,15 +320,15 @@ msgstr "Я хлопець" msgid "Я девушка" msgstr "Я дівчина" -#: app/keyboards/default/create_profile.py:32 +#: app/keyboards/default/create_profile.py:33 msgid "Парни" msgstr "Хлопці" -#: app/keyboards/default/create_profile.py:33 +#: app/keyboards/default/create_profile.py:34 msgid "Девушки" msgstr "Дівчата" -#: app/keyboards/default/create_profile.py:34 +#: app/keyboards/default/create_profile.py:35 msgid "Все" msgstr "Всі" @@ -340,7 +340,7 @@ msgstr "Подивитися👀" msgid "☠️ Заблокировать пользователя {}" msgstr "☠️ Заблокувати користувача {}" -#: app/keyboards/inline/report.py:18 +#: app/keyboards/inline/report.py:20 msgid "Отклонить" msgstr "Відхилити" @@ -360,11 +360,11 @@ msgstr "додатковий опис" msgid "activate profile" msgstr "активувати профіль" -#: app/others/commands.py:20 +#: app/others/commands.py:21 msgid "admin panel" msgstr "адмін панель" -#: app/others/commands.py:21 +#: app/others/commands.py:22 msgid "stats" msgstr "статистика" @@ -373,4 +373,3 @@ msgstr "статистика" #~ msgid "📱 Отправить" #~ msgstr "" - diff --git a/readme.md b/readme.md index 19d0f15..09d9339 100644 --- a/readme.md +++ b/readme.md @@ -1,9 +1,9 @@

- diagram + diagram

📸 Screanshots - +

Screenshot 1

@@ -98,4 +98,4 @@ Now you need to customize the `.env` file --- -### Now the bot is ready to run! 🎉 \ No newline at end of file +### Now the bot is ready to run! 🎉 diff --git a/readmeru.md b/readmeru.md index 9aa0716..0cca300 100644 --- a/readmeru.md +++ b/readmeru.md @@ -1,9 +1,9 @@

- diagram + diagram

📸 Скриншоты - +

Screenshot 1

@@ -99,4 +99,3 @@ cp .env.dist .env --- ### Теперь бот готов к запуску! 🎉 - From 4f8bb671aec2677d88c82017b7552a2e2e23fc6b Mon Sep 17 00:00:00 2001 From: Sima3443 Date: Mon, 3 Feb 2025 12:03:56 +0200 Subject: [PATCH 7/9] =?UTF-8?q?=E2=9C=A8=20Update=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- readme.md | 23 ++++++++--------------- readmeru.md | 22 ++++++++-------------- 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/readme.md b/readme.md index 09d9339..4b63792 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,12 @@ +# Telegram dating bot Michalangelo 💞 + +- `Aiogram 3` +- `i18n` +- ORM: `Peewee` +- Database: `PostgreSQL \ Sqlite, Redis` +

- diagram + diagram

📸 Screanshots @@ -10,23 +17,9 @@

Screenshot 2

-
-# 🚀 Let's get started - -## 🛠️ Technology Stack -- `Aiogram 3` -- `Redis` -- `i18n` -- `Peewee` -- `PostgreSQL \ Sqlite` - ---- - ## 📥 Installation Instructions ### 1. Clone the repository diff --git a/readmeru.md b/readmeru.md index 0cca300..906d086 100644 --- a/readmeru.md +++ b/readmeru.md @@ -1,5 +1,12 @@ +# Telegram dating bot Michalangelo 💞 + +- `Aiogram 3` +- `i18n` +- ORM: `Peewee` +- Database: `PostgreSQL \ Sqlite, Redis` +

- diagram + diagram

📸 Скриншоты @@ -10,21 +17,8 @@

Screenshot 2

-
-# 🚀 Давай начнем - -## 🛠️ Стек технологий -- `Aiogram 3` -- `Redis` -- `i18n` -- `Peewee` -- `PostgreSQL \ Sqlite` - ---- ## 📥 Инструкция по установке From ff6c5f1f819f9f4a377608535de82b8a91b1f36c Mon Sep 17 00:00:00 2001 From: devvsima Date: Sat, 8 Feb 2025 01:05:39 +0200 Subject: [PATCH 8/9] =?UTF-8?q?=F0=9F=92=AB=20Update=20to=20SqlAlchemy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.dist | 18 +++--- .gitignore | 4 +- app/handlers/admin/reports.py | 4 +- app/handlers/admin/stats.py | 8 +-- app/handlers/bot_utils.py | 64 ++++++++++++------ app/handlers/user/archive_like.py | 39 +++++------ app/handlers/user/create_profile.py | 21 +++--- app/handlers/user/edit_profile.py | 10 +-- app/handlers/user/invite.py | 4 +- app/handlers/user/lang.py | 4 +- app/handlers/user/profile.py | 6 +- app/handlers/user/search_profile.py | 24 ++++--- app/handlers/user/start.py | 6 +- app/keyboards/default/admin.py | 2 - app/keyboards/default/base.py | 2 - app/keyboards/default/kb_generator.py | 2 +- app/middlewares/__init__.py | 7 ++ app/middlewares/admin.py | 7 +- app/middlewares/database.py | 15 +++++ app/middlewares/start.py | 6 +- app/middlewares/user.py | 2 + data/config.py | 53 ++++++++++----- database/connect.py | 37 +++++++---- database/models/__init__.py | 6 -- database/models/base.py | 23 +++++++ database/models/likes.py | 9 --- database/models/match.py | 13 ++++ database/models/migrations.py | 65 ------------------- database/models/profile.py | 46 +++++++++---- database/models/user.py | 20 ++++++ database/models/users.py | 12 ---- database/service/likes.py | 27 -------- database/service/matchs.py | 38 +++++++++++ database/service/profile.py | 63 ------------------ database/service/profiles.py | 89 ++++++++++++++++++++++++++ database/service/search.py | 55 +++++++++------- database/service/stats.py | 57 ++++++++++------- database/service/users.py | 58 +++++++++-------- loader.py | 12 ++-- main.py | 6 +- readme.md | 2 +- readmeru.md | 2 +- requirements.txt | Bin 1646 -> 1890 bytes utils/graphs.py | 4 +- 44 files changed, 545 insertions(+), 407 deletions(-) create mode 100644 app/middlewares/database.py create mode 100644 database/models/base.py delete mode 100644 database/models/likes.py create mode 100644 database/models/match.py delete mode 100644 database/models/migrations.py create mode 100644 database/models/user.py delete mode 100644 database/models/users.py delete mode 100644 database/service/likes.py create mode 100644 database/service/matchs.py delete mode 100644 database/service/profile.py create mode 100644 database/service/profiles.py diff --git a/.env.dist b/.env.dist index fd65aad..6f08c87 100644 --- a/.env.dist +++ b/.env.dist @@ -3,22 +3,22 @@ TOKEN = "" ADMINS = 12345678, 87654321 # MODERATOR_GROUP_ID = -# SKIP_UPDATES = +# SKIP_UPDATES = # ---< Database >--- -# DB_NAME = +# DB_NAME = # DB_HOST = -# DB_PORT = -# DB_USER = -# DB_PASS = +# DB_PORT = +# DB_USER = +# DB_PASS = # ---< Redis >--- -# REDIS_HOST = -# REDIS_PORT = -# REDIS_DB = +# REDIS_HOST = +# REDIS_PORT = +# REDIS_DB = -# RD_URI = +# RD_URL = diff --git a/.gitignore b/.gitignore index f4600ca..879c297 100644 --- a/.gitignore +++ b/.gitignore @@ -4,12 +4,14 @@ .venv .github + **/__pycache__ **.sqlite **.sqlite3 **.json +**.csv **/.env **/logs **/invites_per_user.png -**/registration_graph.png \ No newline at end of file +**/registration_graph.png diff --git a/app/handlers/admin/reports.py b/app/handlers/admin/reports.py index a34dd3b..2edcf2b 100644 --- a/app/handlers/admin/reports.py +++ b/app/handlers/admin/reports.py @@ -9,8 +9,8 @@ @router.callback_query(F.data.startswith("block_user_"), StateFilter(None)) -async def _block_user_callback(callback: types.CallbackQuery) -> None: +async def _block_user_callback(callback: types.CallbackQuery, session) -> None: """Блокирует пользователя переданого в калбек""" user_id = callback.data[11:] - await ban_or_unban_user(int(user_id), True) + await ban_or_unban_user(session, int(user_id), True) await callback.message.edit_text(msg_text.USER_BANNED.format(user_id)) diff --git a/app/handlers/admin/stats.py b/app/handlers/admin/stats.py index 2e6467e..72bccf7 100644 --- a/app/handlers/admin/stats.py +++ b/app/handlers/admin/stats.py @@ -15,14 +15,14 @@ @router.message(Command("stats"), StateFilter(None)) @router.message(F.text.in_(["📊 Статистика", "📊 Statistics"]), StateFilter(None)) -async def _stats_command(message: types.Message) -> None: +async def _stats_command(message: types.Message, session) -> None: """ Отправляет администратору график регистрации пользователей и статистику пользователей в БД """ - profile_stats = await get_profile_stats() - users_stats = await get_users_stats() - graph_path = await get_or_create_registration_graph() + profile_stats = await get_profile_stats(session) + users_stats = await get_users_stats(session) + graph_path = await get_or_create_registration_graph(session) photo = types.FSInputFile(graph_path) text = msg_text.USERS_STATS.format( diff --git a/app/handlers/bot_utils.py b/app/handlers/bot_utils.py index 6ecc4cd..17138ea 100644 --- a/app/handlers/bot_utils.py +++ b/app/handlers/bot_utils.py @@ -1,14 +1,17 @@ from loader import bot -from data.config import MODERATOR_GROUP +from data.config import tgbot from utils.logging import logger -from database.models.users import Users +from database.models.user import User from database.models.profile import Profile +from database.service.users import get_user from app.handlers.msg_text import msg_text from app.keyboards.default.base import menu_kb from app.keyboards.inline.report import block_user_ikb +MODERATOR_GROUP = tgbot.MODERATOR_GROUP + async def menu(user_id: int) -> None: """Отправляет меню пользователю""" @@ -19,26 +22,47 @@ async def menu(user_id: int) -> None: ) -async def report_to_profile(user: Users, profile: Profile) -> None: +async def report_to_profile(user: User, profile: Profile, session) -> None: """Отправляет в группу модераторов анкету пользователя на которого пришла жалоба""" - if MODERATOR_GROUP: - try: - await send_profile(MODERATOR_GROUP, profile) - text = msg_text.REPORT_TO_USER.format( - user.username, user.id, profile.user_id.username, profile.user_id.id - ) + await send_profile(MODERATOR_GROUP, profile) + reported_user = await get_user(session, profile.user_id) - await bot.send_message( - chat_id=MODERATOR_GROUP, - text=text, - reply_markup=block_user_ikb( - user_id=profile.user_id.id, - username=profile.user_id.username, - ), - ) - except: - logger.error("Сообщение в модераторскую группу не отправленно") + text = msg_text.REPORT_TO_USER.format( + user.username, user.id, reported_user.username, profile.user_id + ) + + await bot.send_message( + chat_id=MODERATOR_GROUP, + text=text, + reply_markup=block_user_ikb( + user_id=profile.user_id, + username=reported_user.username, + ), + ) + + +# async def report_to_profile(user: User, profile: Profile, session) -> None: +# """Отправляет в группу модераторов анкету пользователя +# на которого пришла жалоба""" +# if MODERATOR_GROUP: +# try: +# await send_profile(MODERATOR_GROUP, profile) +# text = msg_text.REPORT_TO_USER.format( +# user.username, user.id, profile.user_id.username, profile.user_id +# ) + +# reported_user = await get_user(session, profile.user_id) +# await bot.send_message( +# chat_id=MODERATOR_GROUP, +# text=text, +# reply_markup=block_user_ikb( +# user_id=profile.user_id, +# username=reported_user.username, +# ), +# ) +# except: +# logger.error("Сообщение в модераторскую группу не отправленно") async def send_profile(user_id: int, profile: Profile) -> None: @@ -51,7 +75,7 @@ async def send_profile(user_id: int, profile: Profile) -> None: ) -async def new_user_alert_to_group(user: Users) -> None: +async def new_user_alert_to_group(user: User) -> None: """Отправляет уведомление в модераторскуб группу о новом пользователе""" if MODERATOR_GROUP: try: diff --git a/app/handlers/user/archive_like.py b/app/handlers/user/archive_like.py index e0a1950..1d05e91 100644 --- a/app/handlers/user/archive_like.py +++ b/app/handlers/user/archive_like.py @@ -4,9 +4,9 @@ from app.routers import user_router as router -from database.service.likes import get_profile_likes, del_like -from database.service.profile import get_profile -from database.service.users import update_user_username +from database.service.matchs import get_profile_likes, del_like +from database.service.profiles import get_profile +from database.service.users import update_user_username, get_user from database.models.profile import Profile from .profile import send_profile @@ -18,17 +18,17 @@ @router.message(F.text == "🗄", StateFilter("*")) -async def like_profile(message: types.Message, state: FSMContext) -> None: +async def like_profile(message: types.Message, state: FSMContext, session) -> None: """Архив лайков анкеты пользовтеля""" if await state.get_state() == DisableProfile.waiting: return - await update_user_username(message.from_user.id, message.from_user.username) + await update_user_username(session, message.from_user.id, message.from_user.username) await message.answer(text=msg_text.SEARCH, reply_markup=arhive_search_kb) await state.set_state(LikeResponse.response) - if liker_ids := await get_profile_likes(message.from_user.id): + if liker_ids := await get_profile_likes(session, message.from_user.id): await state.update_data(ids=liker_ids) - profile = await get_profile(liker_ids[0]) + profile = await get_profile(session, liker_ids[0]) await send_profile(message.from_user.id, profile) else: await message.answer(msg_text.LIKE_ARCHIVE) @@ -36,17 +36,17 @@ async def like_profile(message: types.Message, state: FSMContext) -> None: @router.callback_query(F.data == "archive", StateFilter("*")) -async def _like_profile(callback: types.CallbackQuery, state: FSMContext) -> None: +async def _like_profile(callback: types.CallbackQuery, state: FSMContext, session) -> None: """Архив лайков анкеты пользовтеля""" if await state.get_state() == DisableProfile.waiting: return await state.set_state(LikeResponse.response) - await update_user_username(callback.from_user.id, callback.from_user.username) + await update_user_username(session, callback.from_user.id, callback.from_user.username) await callback.message.answer(text=msg_text.SEARCH, reply_markup=arhive_search_kb) - if liker_ids := await get_profile_likes(callback.from_user.id): + if liker_ids := await get_profile_likes(session, callback.from_user.id): await state.update_data(ids=liker_ids) - profile = await get_profile(liker_ids[0]) + profile = await get_profile(session, liker_ids[0]) await send_profile(callback.from_user.id, profile) else: await callback.message.answer(msg_text.LIKE_ARCHIVE) @@ -54,16 +54,16 @@ async def _like_profile(callback: types.CallbackQuery, state: FSMContext) -> Non @router.message(LikeResponse.response, F.text.in_(["❤️", "👎"])) -async def _like_response(message: types.Message, state: FSMContext) -> None: +async def _like_response(message: types.Message, state: FSMContext, session) -> None: """'Свайпы' людей которые лайкнули анкету пользователя""" data = await state.get_data() ids = data.get("ids") - profile: Profile = await get_profile(ids[0]) + profile: Profile = await get_profile(session, ids[0]) if message.text == "❤️": """Отправка пользователю которому ответили на лайк""" await sending_user_contact( - user_id=profile.user_id.id, + user_id=profile.user_id, name=message.from_user.full_name, user_link=generate_user_link( user_id=message.from_user.id, username=message.from_user.username @@ -71,20 +71,21 @@ async def _like_response(message: types.Message, state: FSMContext) -> None: ) """Отправка пользователю который ответил на лайк""" + + user = await get_user(session, profile.user_id) + await sending_user_contact( user_id=message.from_user.id, name=profile.name, - user_link=generate_user_link( - user_id=profile.user_id.id, username=profile.user_id.username - ), + user_link=generate_user_link(user_id=profile.user_id, username=user.username), ) - await del_like(message.from_user.id, profile.user_id.id) + await del_like(session, message.from_user.id, profile.user_id) ids.pop(0) await state.update_data(ids=ids) if ids: - profile = await get_profile(ids[0]) + profile = await get_profile(session, ids[0]) await send_profile(message.from_user.id, profile) else: await message.answer(msg_text.EMPTY_PROFILE_SEARCH) diff --git a/app/handlers/user/create_profile.py b/app/handlers/user/create_profile.py index 40c4001..cafeb99 100644 --- a/app/handlers/user/create_profile.py +++ b/app/handlers/user/create_profile.py @@ -4,7 +4,7 @@ from app.routers import user_router as router -from database.service.profile import create_profile, edit_profile_photo, edit_profile_description +from database.service.profiles import create_profile, edit_profile_photo, edit_profile_description from app.handlers.msg_text import msg_text from app.handlers.user.profile import profile_command @@ -55,11 +55,11 @@ async def _incorrect_find_gender(message: types.Message): # < photo > @router.message(StateFilter(ProfileCreate.photo, ProfileEdit.photo), filters.IsPhoto()) -async def _photo(message: types.Message, state: FSMContext): +async def _photo(message: types.Message, state: FSMContext, session): photo = message.photo[0].file_id if await state.get_state() == ProfileEdit.photo.state: - await edit_profile_photo(message.from_user.id, photo) - await profile_command(message) + await edit_profile_photo(session, message.from_user.id, photo) + await profile_command(message, session) await state.clear() return @@ -123,26 +123,27 @@ async def _incorrect_city(message: types.Message): # < description > @router.message(StateFilter(ProfileCreate.desc, ProfileEdit.desc), filters.IsDescription()) -async def _description(message: types.Message, state: FSMContext): +async def _description(message: types.Message, state: FSMContext, session): if await state.get_state() == ProfileEdit.desc.state: - await edit_profile_description(message.from_user.id, message.text) + await edit_profile_description(session, message.from_user.id, message.text) else: data = await state.get_data() await create_profile( + session, user_id=message.from_user.id, gender=data["gender"], find_gender=data["find_gender"], photo=data["photo"], name=data["name"], - age=data["age"], + age=int(data["age"]), city=data["city"], - latitude=data["latitude"], - longitude=data["longitude"], + latitude=float(data["latitude"]), + longitude=float(data["longitude"]), description=message.text, ) await state.clear() - await profile_command(message) + await profile_command(message, session) @router.message(StateFilter(ProfileCreate.desc, ProfileEdit.desc)) diff --git a/app/handlers/user/edit_profile.py b/app/handlers/user/edit_profile.py index ef66a30..0a6b359 100644 --- a/app/handlers/user/edit_profile.py +++ b/app/handlers/user/edit_profile.py @@ -2,7 +2,7 @@ from aiogram.fsm.context import FSMContext from aiogram.filters.state import StateFilter -from database.service.profile import update_profile_is_active_status +from database.service.profiles import update_profile_is_active_status from app.routers import user_router as router @@ -27,10 +27,10 @@ async def _edit_profile_description_command(message: types.Message, state: FSMCo @router.message(F.text == "❌", StateFilter(None)) -async def _disable_profile_command(message: types.Message, state: FSMContext) -> None: +async def _disable_profile_command(message: types.Message, state: FSMContext, session) -> None: """Отключение профиля""" await state.set_state(DisableProfile.waiting) - await update_profile_is_active_status(message.from_user.id, False) + await update_profile_is_active_status(session, message.from_user.id, False) await message.answer(text=msg_text.DISABLE_PROFILE, reply_markup=profile_return_kb()) @@ -38,7 +38,7 @@ async def _disable_profile_command(message: types.Message, state: FSMContext) -> F.text.in_(["🔙 Вернуть профиль", "🔙 Return profile", "🔙 Повернути профіль"]), DisableProfile.waiting, ) -async def _activate_profile_command(message: types.Message, state: FSMContext) -> None: - await update_profile_is_active_status(message.from_user.id, True) +async def _activate_profile_command(message: types.Message, state: FSMContext, session) -> None: + await update_profile_is_active_status(session, message.from_user.id, True) await message.answer(msg_text.ACTIVATE_PROFILE_ALERT) await menu(message.from_user.id) diff --git a/app/handlers/user/invite.py b/app/handlers/user/invite.py index 5534cf1..f0446c4 100644 --- a/app/handlers/user/invite.py +++ b/app/handlers/user/invite.py @@ -5,7 +5,7 @@ from app.routers import user_router as router -from database.models.users import Users +from database.models.user import User from app.handlers.msg_text import msg_text @@ -13,7 +13,7 @@ @router.message(F.text == "✉️", StateFilter(None)) -async def _invite_link_command(message: types.Message, user: Users) -> None: +async def _invite_link_command(message: types.Message, user: User) -> None: """Дает пользователю его реферальную ссылку""" bot_user = await bot.get_me() user_code: str = encode_base62(message.from_user.id) diff --git a/app/handlers/user/lang.py b/app/handlers/user/lang.py index 01b60c2..b894211 100644 --- a/app/handlers/user/lang.py +++ b/app/handlers/user/lang.py @@ -18,7 +18,7 @@ async def _lang(message: types.Message) -> None: @router.callback_query(F.data.in_(["ru", "uk", "en"])) -async def _lang_change(callback: types.CallbackQuery) -> None: +async def _lang_change(callback: types.CallbackQuery, session) -> None: """Меняет язык пользователя на выбранный""" - await change_language(callback.from_user.id, callback.data) + await change_language(session, callback.from_user.id, callback.data) await callback.message.edit_text(msg_text.DONE_CHANGE_LANG) diff --git a/app/handlers/user/profile.py b/app/handlers/user/profile.py index 56b5a8b..1d7e9ca 100644 --- a/app/handlers/user/profile.py +++ b/app/handlers/user/profile.py @@ -3,7 +3,7 @@ from app.routers import user_router as router -from database.service.profile import get_profile +from database.service.profiles import get_profile from app.handlers.msg_text import msg_text from app.handlers.bot_utils import send_profile @@ -11,9 +11,9 @@ @router.message(F.text == "👤", StateFilter(None)) -async def profile_command(message: types.Message) -> None: +async def profile_command(message: types.Message, session) -> None: """Отправляет профиль пользователя""" - profile = await get_profile(message.from_user.id) + profile = await get_profile(session, message.from_user.id) await send_profile(message.from_user.id, profile) await message.answer(msg_text.PROFILE_MENU, reply_markup=profile_kb) diff --git a/app/handlers/user/search_profile.py b/app/handlers/user/search_profile.py index a349f66..9b5fc3f 100644 --- a/app/handlers/user/search_profile.py +++ b/app/handlers/user/search_profile.py @@ -7,7 +7,7 @@ from app.routers import user_router as router from database.models.profile import Profile -from database.service.likes import set_new_like +from database.service.matchs import set_new_like from database.service.search import elastic_search_user_ids, get_profile from app.others.states import Search @@ -20,11 +20,11 @@ @router.message(F.text == "🔍", StateFilter(None)) -async def _search_command(message: types.Message, state: FSMContext) -> None: +async def _search_command(message: types.Message, state: FSMContext, session) -> None: """Начинает поиск анкет""" await message.answer(msg_text.SEARCH, reply_markup=search_kb) - ids = await elastic_search_user_ids(message.from_user.id) + ids = await elastic_search_user_ids(session, message.from_user.id) if not ids: await message.answer(msg_text.INVALID_PROFILE_SEARCH) await menu(message.from_user.id) @@ -35,27 +35,31 @@ async def _search_command(message: types.Message, state: FSMContext) -> None: await state.set_state(Search.search) await state.update_data(ids=ids) - profile = await get_profile(ids[0]) + profile = await get_profile(session, ids[0]) await send_profile(message.from_user.id, profile) @router.message(Search.search, F.text.in_(["❤️", "👎", "💢"])) -async def _search_profile(message: types.Message, state: FSMContext) -> None: +async def _search_profile(message: types.Message, state: FSMContext, session) -> None: """Свайпы анкет""" data: dict = await state.get_data() ids: list = data.get("ids", []) - profile: Profile = await get_profile(ids[0]) + profile: Profile = await get_profile(session, ids[0]) if message.text == "❤️": - await set_new_like(message.from_user.id, profile.user_id) + await set_new_like(session, message.from_user.id, profile.user_id) await message.bot.send_message( - chat_id=profile.user_id.id, + chat_id=profile.user_id, text=msg_text.LIKE_PROFILE, reply_markup=check_archive_ikb(), ) elif message.text == "💢": await message.answer(msg_text.REPORT_TO_PROFILE) - await report_to_profile(message.from_user, profile) + await report_to_profile( + session=session, + user=message.from_user, + profile=profile, + ) ids.pop(0) @@ -66,5 +70,5 @@ async def _search_profile(message: types.Message, state: FSMContext) -> None: await state.update_data(ids=ids) - profile: Profile = await get_profile(ids[0]) + profile: Profile = await get_profile(session, ids[0]) await send_profile(message.from_user.id, profile) diff --git a/app/handlers/user/start.py b/app/handlers/user/start.py index 06bfc67..08808ce 100644 --- a/app/handlers/user/start.py +++ b/app/handlers/user/start.py @@ -3,7 +3,7 @@ from aiogram.filters.state import StateFilter from data.config import IMAGES_DIR -from database.service.profile import get_profile +from database.service.profiles import get_profile from app.routers import start_router from app.handlers.msg_text import msg_text @@ -12,9 +12,9 @@ @start_router.message(CommandStart(), StateFilter(None)) -async def _start_command(message: types.Message) -> None: +async def _start_command(message: types.Message, session) -> None: """Стратовая команда""" - if await get_profile(message.from_user.id): + if await get_profile(session, message.from_user.id): await menu(message.from_user.id) else: photo = types.FSInputFile(f"{IMAGES_DIR}/new_logo.webp") diff --git a/app/keyboards/default/admin.py b/app/keyboards/default/admin.py index 7db9153..1f93779 100644 --- a/app/keyboards/default/admin.py +++ b/app/keyboards/default/admin.py @@ -19,7 +19,6 @@ def admin_menu_kb() -> ReplyKeyboardMarkup: KeyboardButton(text=_("📩 Рассылка")), ], ], - one_time_keyboard=True, ) return kb @@ -35,6 +34,5 @@ def user_ban_or_unban_kb() -> ReplyKeyboardMarkup: KeyboardButton(text=_("💊 Разбанить пользователей")), ], ], - one_time_keyboard=True, ) return kb diff --git a/app/keyboards/default/base.py b/app/keyboards/default/base.py index c61278f..6a2c382 100644 --- a/app/keyboards/default/base.py +++ b/app/keyboards/default/base.py @@ -26,13 +26,11 @@ search_kb: ReplyKeyboardMarkup = kb_gen( ["❤️", "💢", "👎"], ["💤"], - one_time=False, ) arhive_search_kb: ReplyKeyboardMarkup = kb_gen( ["❤️", "👎"], ["💤"], - one_time=False, ) diff --git a/app/keyboards/default/kb_generator.py b/app/keyboards/default/kb_generator.py index 0565760..689ef5f 100644 --- a/app/keyboards/default/kb_generator.py +++ b/app/keyboards/default/kb_generator.py @@ -5,7 +5,7 @@ def simple_kb_generator( - *buttons_list: list, one_time: bool = True, resize: bool = True + *buttons_list: list, one_time: bool = False, resize: bool = True ) -> ReplyKeyboardMarkup: """ Небольшой генератор клавиатуры. diff --git a/app/middlewares/__init__.py b/app/middlewares/__init__.py index f0f3e6d..c6e4f81 100644 --- a/app/middlewares/__init__.py +++ b/app/middlewares/__init__.py @@ -1,12 +1,19 @@ from aiogram import Dispatcher + +from .database import DatabaseMiddleware from .user import UsersMiddleware from .start import StartMiddleware from .admin import AdminMiddleware + from app.routers import start_router, admin_router, user_router from app.middlewares.i18n import i18n_middleware def setup_middlewares(dp: Dispatcher) -> None: + from database.connect import async_session + + dp.update.middleware(DatabaseMiddleware(async_session)) + start_router.message.middleware(StartMiddleware()) admin_router.message.middleware(AdminMiddleware()) diff --git a/app/middlewares/admin.py b/app/middlewares/admin.py index 1744e81..c6481c0 100644 --- a/app/middlewares/admin.py +++ b/app/middlewares/admin.py @@ -1,15 +1,18 @@ from aiogram import BaseMiddleware from aiogram.types import Message -from data.config import ADMINS +from data.config import tgbot from database.service.users import get_user from typing import Any, Callable +ADMINS = tgbot.ADMINS + class AdminMiddleware(BaseMiddleware): async def __call__(self, handler: Callable, message: Message, data: dict) -> Any: - if user := await get_user(message.from_user.id): + session = data["session"] + if user := await get_user(session, message.from_user.id): if user.id in ADMINS: data["user"] = user return await handler(message, data) diff --git a/app/middlewares/database.py b/app/middlewares/database.py new file mode 100644 index 0000000..134285b --- /dev/null +++ b/app/middlewares/database.py @@ -0,0 +1,15 @@ +from aiogram import BaseMiddleware + +from typing import Any + +from sqlalchemy.ext.asyncio import async_sessionmaker + + +class DatabaseMiddleware(BaseMiddleware): + def __init__(self, session_pool: async_sessionmaker): + self.session_pool = session_pool + + async def __call__(self, handler, event, data) -> Any: + async with self.session_pool() as session: + data["session"] = session + return await handler(event, data) diff --git a/app/middlewares/start.py b/app/middlewares/start.py index 591071c..b102510 100644 --- a/app/middlewares/start.py +++ b/app/middlewares/start.py @@ -12,13 +12,15 @@ class StartMiddleware(BaseMiddleware): async def __call__(self, handler: Callable, message: Message, data: dict) -> Any: - if user := await get_user(message.from_user.id): + session = data["session"] + if user := await get_user(session, message.from_user.id): if not user.is_banned: data["user"] = user return await handler(message, data) return user = await create_user( + session, user_id=message.from_user.id, username=message.from_user.username, language=message.from_user.language_code, @@ -27,6 +29,6 @@ async def __call__(self, handler: Callable, message: Message, data: dict) -> Any await new_user_alert_to_group(user) if inviter := data["command"].args: - await new_referral(decode_base62(inviter)) + await new_referral(session, decode_base62(inviter)) return await handler(message, data) diff --git a/app/middlewares/user.py b/app/middlewares/user.py index 80213d1..f2f97a9 100644 --- a/app/middlewares/user.py +++ b/app/middlewares/user.py @@ -7,7 +7,9 @@ class UsersMiddleware(BaseMiddleware): async def __call__(self, handler: Callable, event: Message | CallbackQuery, data: dict) -> Any: + session = data["session"] user = await get_or_create_user( + session, user_id=event.from_user.id, username=event.from_user.username, language=event.from_user.language_code, diff --git a/data/config.py b/data/config.py index 1b987ae..384d987 100644 --- a/data/config.py +++ b/data/config.py @@ -6,31 +6,54 @@ env = Env() env.read_env() + # ---< Telegram bot >--- -TG_TOKEN: str = env.str("TOKEN", default=None) -ADMINS: list = env.list("ADMINS", default=None, subcast=int) -MODERATOR_GROUP: int = env.int("MODERATOR_GROUP_ID", default=None) -SKIP_UPDATES: bool = env.bool("SKIP_UPDATES", default=False) +class TelegramBotSettings: + TOKEN: str = env.str("TOKEN", default=None) + SKIP_UPDATES: bool = env.bool("SKIP_UPDATES", default=False) + + ADMINS: list = env.list("ADMINS", default=None, subcast=int) + MODERATOR_GROUP: int = env.int("MODERATOR_GROUP_ID", default=None) + # ---< Database >--- -DB_NAME: str = env.str("DB_NAME", default=None) -DB_HOST: str = env.str("DB_HOST", default="localhost") -DB_PORT: int = env.int("DB_PORT", default=5432) -DB_USER: str = env.str("DB_USER", default="postgres") -DB_PASS: str = env.str("DB_PASS", default="postgres") +class DatabaseSettings: + NAME: str = env.str("DB_NAME", default=None) + HOST: str = env.str("DB_HOST", default="localhost") + PORT: int = env.int("DB_PORT", default=5432) + USER: str = env.str("DB_USER", default="postgres") + PASS: str = env.str("DB_PASS", default="postgres") + + DB_URL: str = env.str("DB_URL", default=f"sqlite+aiosqlite:///{DIR}/database/db.sqlite3") + + if all([NAME, HOST, PORT, USER, PASS]): + DB_URL = f"postgresql+asyncpg://{USER}:{PASS}@{HOST}:{PORT}/{NAME}" + + ECHO = False + POOL_SIZE = 5 + MAX_OVERFLOW = 10 + # ---< Redis >--- -REDIS_HOST: str = env.str("REDIS_HOST", default=None) -REDIS_PORT: int = env.int("REDIS_PORT", default=6379) -REDIS_DB: int = env.int("REDIS_DB", default=5) +class RedisSettings: + HOST: str = env.str("REDIS_HOST", default=None) + PORT: int = env.int("REDIS_PORT", default=6379) + DB: int = env.int("REDIS_DB", default=5) + + URL: str = env.str("RD_URL", default=None) -REDIS_URL: str = env.str("RD_URI", default=None) + if all([HOST, PORT, DB]): + URL = f"redis://{HOST}:{PORT}/{DB}" -if all([REDIS_DB, REDIS_HOST, REDIS_PORT]): - REDIS_URL = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}" # ---< Other >--- +TIME_ZONE = "UTC" + I18N_DOMAIN = "bot" IMAGES_DIR = rf"{DIR}/images" LOCALES_DIR = f"{DIR}/data/locales" + +tgbot = TelegramBotSettings() +database = DatabaseSettings() +redis = RedisSettings() diff --git a/database/connect.py b/database/connect.py index 0de757a..74036b1 100644 --- a/database/connect.py +++ b/database/connect.py @@ -1,21 +1,34 @@ -from peewee import PostgresqlDatabase, SqliteDatabase, Model - -from data.config import DB_NAME, DB_HOST, DB_PORT, DB_USER, DB_PASS, DIR +from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine +from data.config import database from utils.logging import logger +from .models.base import BaseModel -if DB_NAME and DB_HOST and DB_PORT and DB_USER and DB_PASS: - db = PostgresqlDatabase(DB_NAME, host=DB_HOST, port=DB_PORT, user=DB_USER, password=DB_PASS) - logger.info("Database: PostgreSql") -else: - db = SqliteDatabase(f"{DIR}/database/db.sqlite3") +if database.DB_URL.startswith("sqlite"): logger.info("Database: Sqlite") +else: + logger.info("Database: PostgreSql") + +async_engine = create_async_engine( + url=database.DB_URL, + echo=database.ECHO, + pool_size=database.POOL_SIZE, + max_overflow=database.MAX_OVERFLOW, +) +async_session = async_sessionmaker( + bind=async_engine, + class_=AsyncSession, + expire_on_commit=False, +) + -db.connect() +async def create_db(): + async with async_engine.begin() as conn: + await conn.run_sync(BaseModel.metadata.create_all) -class BaseModel(Model): - class Meta: - database = db +async def drop_db(): + async with async_engine.begin() as conn: + await conn.run_sync(BaseModel.metadata.drop_all) diff --git a/database/models/__init__.py b/database/models/__init__.py index 5c2ccf9..e69de29 100644 --- a/database/models/__init__.py +++ b/database/models/__init__.py @@ -1,6 +0,0 @@ -from .users import Users -from .profile import Profile -from .likes import Likes -from ..connect import db - -db.create_tables([Users, Profile, Likes]) diff --git a/database/models/base.py b/database/models/base.py new file mode 100644 index 0000000..cf628dc --- /dev/null +++ b/database/models/base.py @@ -0,0 +1,23 @@ +from sqlalchemy import func, DateTime +from sqlalchemy.orm import Mapped, DeclarativeBase, mapped_column + +from typing import Annotated +from datetime import datetime + +created_at = Annotated[datetime, mapped_column(DateTime, default=func.now())] +updated_at = Annotated[datetime, mapped_column(DateTime, default=func.now(), onupdate=func.now())] + + +class BaseModel(DeclarativeBase): + created_at: Mapped[created_at] + updated_at: Mapped[updated_at] + + repr_cols_num = 3 + repr_cols = tuple() + + def __repr__(self): + cols = [] + for idx, col in enumerate(self.__table__.columns.keys()): + if col in self.repr_cols or idx < self.repr_cols_num: + col.append(f"{col}={getattr(self, col)}") + return f"<{self.__class__.name} {', '.join(cols)}>" diff --git a/database/models/likes.py b/database/models/likes.py deleted file mode 100644 index 5abf4b0..0000000 --- a/database/models/likes.py +++ /dev/null @@ -1,9 +0,0 @@ -from peewee import ForeignKeyField -from ..connect import BaseModel - -from .users import Users - - -class Likes(BaseModel): - liker_id = ForeignKeyField(Users, backref="likes_given") - liked_id = ForeignKeyField(Users, backref="likes_received") diff --git a/database/models/match.py b/database/models/match.py new file mode 100644 index 0000000..539daaa --- /dev/null +++ b/database/models/match.py @@ -0,0 +1,13 @@ +from sqlalchemy import ForeignKey, Integer +from sqlalchemy.orm import Mapped, mapped_column + +from .base import BaseModel + + +class Match(BaseModel): + __tablename__ = "matchs" + + id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) + sender_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + receiver_id: Mapped[int] = mapped_column(ForeignKey("users.id")) + message: Mapped[str] = mapped_column(nullable=True) diff --git a/database/models/migrations.py b/database/models/migrations.py deleted file mode 100644 index 2009ccc..0000000 --- a/database/models/migrations.py +++ /dev/null @@ -1,65 +0,0 @@ -import json -from .users import Users -from .profile import Profile -from .likes import Likes - -# Подключение к SQLite -from datetime import datetime -from data.config import DIR -from playhouse.migrate import PostgresqlMigrator, migrate - -from ..connect import db - - -def export_data(db, model, file): - # Экспорт данных - data = [] - for model in [model]: # Добавьте сюда все ваши модели - rows = [item.__data__ for item in model.select()] - data.append({model._meta.table_name: rows}) - - def json_serial(obj): - if isinstance(obj, datetime): - return obj.isoformat() # Преобразование в ISO 8601 - raise TypeError(f"Type {type(obj)} not serializable") - - with open(file, "w") as f: - json.dump(data, f, default=json_serial) - - -def import_data(db, model, file): - with open(file, "r") as f: - data = json.load(f) - - # Импорт данных - for table in data: - table_name = list(table.keys())[0] # Имя таблицы из JSON - rows = table[table_name] - - if model is None: - print(f"Не удалось найти модель для таблицы {table_name}") - continue - - # Вставка данных в PostgreSQL - with db.atomic(): - model.insert_many(rows).execute() - - -# import_data(db, Profile, f"{DIR}/profile.json") -# import_data(db, Profile, f"{DIR}/profile.json") -# import_data(db, Likes, "like.json") - -# migrator = PostgresqlMigrator(db) -# from peewee import CharField, BigIntegerField, DateTimeField, IntegerField, BooleanField - -# migrate( -# migrator.drop_column('users', 'role'), -# migrator.drop_column('users', 'is_invited'), -# migrator.add_column('users', 'is_banned', BooleanField(default=False)), -# ) - -# import_data() -# db.execute_sql("ALTER TABLE users DROP COLUMN role;") -# db.execute_sql("ALTER TABLE users DROP COLUMN is_invited;") -# db.execute_sql("UPDATE users SET is_banned = NOT is_invited;") -# db.execute_sql("ALTER TABLE users DROP COLUMN is_invited;") diff --git a/database/models/profile.py b/database/models/profile.py index 2708757..7918ed1 100644 --- a/database/models/profile.py +++ b/database/models/profile.py @@ -1,17 +1,35 @@ -from peewee import TextField, IntegerField, CharField, FloatField, BooleanField, ForeignKeyField -from ..connect import BaseModel -from .users import Users +from sqlalchemy import BigInteger, String, Boolean, Integer, ForeignKey +from sqlalchemy.orm import Mapped, mapped_column + +from .base import BaseModel + +from enum import Enum + + +# class Gender(Enum): +# male = "male" +# female = "female" + + +# class FindGender(Enum): +# male = "male" +# female = "female" +# all = "all" class Profile(BaseModel): - user_id = ForeignKeyField(Users, backref="profile", primary_key=True) - name = CharField(max_length=50) - gender = CharField(choices=["male", "female"], index=True) - find_gender = CharField(choices=["male", "female", "all"], index=True) - city = CharField(max_length=50) - latitude = FloatField() - longitude = FloatField() - photo = TextField() - age = IntegerField(index=True) - description = CharField(max_length=1000) - is_active = BooleanField(default=True, index=True) + __tablename__ = "profiles" + + user_id: Mapped[int] = mapped_column( + ForeignKey("users.id", ondelete="CASCADE"), primary_key=True + ) + name: Mapped[str] + gender: Mapped[str] + find_gender: Mapped[str] + city: Mapped[str] + latitude: Mapped[float] + longitude: Mapped[float] + photo: Mapped[str] + age: Mapped[int] + description: Mapped[str] + is_active: Mapped[bool] = mapped_column(default=True) diff --git a/database/models/user.py b/database/models/user.py new file mode 100644 index 0000000..1f9635a --- /dev/null +++ b/database/models/user.py @@ -0,0 +1,20 @@ +from sqlalchemy import BigInteger, String, Boolean, Integer +from sqlalchemy.orm import Mapped, mapped_column, relationship + + +from .base import BaseModel + + +class User(BaseModel): + __tablename__ = "users" + + id: Mapped[int] = mapped_column(BigInteger, primary_key=True) + username: Mapped[str] = mapped_column(String, nullable=True) + language: Mapped[str] = mapped_column(String, default="en") + referral: Mapped[int] = mapped_column(Integer, default=0) + is_banned: Mapped[bool] = mapped_column(Boolean, default=False) + + # profile: Mapped["Profile"] = relationship(backref="user_id") + + def __repr__(self): + return f"{self.id} | {self.username}" diff --git a/database/models/users.py b/database/models/users.py deleted file mode 100644 index fa2a211..0000000 --- a/database/models/users.py +++ /dev/null @@ -1,12 +0,0 @@ -from peewee import CharField, BigIntegerField, DateTimeField, IntegerField, BooleanField -from datetime import datetime -from ..connect import BaseModel - - -class Users(BaseModel): - id = BigIntegerField(primary_key=True) - username = CharField(default=None, null=True) - language = CharField(default="en") - referral = IntegerField(default=0) - is_banned = BooleanField(default=False) - created_at = DateTimeField(default=lambda: datetime.utcnow()) diff --git a/database/service/likes.py b/database/service/likes.py deleted file mode 100644 index 6082601..0000000 --- a/database/service/likes.py +++ /dev/null @@ -1,27 +0,0 @@ -from ..models.likes import Likes - -from utils.logging import logger - - -async def set_new_like(liker_id: int, liked_id: int) -> None: - """Добавляет в БД лайк пользователя, - если лайк уже есть - ничего не делает""" - existing_like = Likes.get_or_none(liker_id=liker_id, liked_id=liked_id) - - if existing_like: - logger.info(f"Повторился лайк: {liker_id} & {liked_id}") - else: - Likes.create(liker_id=liker_id, liked_id=liked_id) - logger.info(f"User: {liker_id} | лайкнул пользователя {liked_id}") - - -async def get_profile_likes(user_id: int) -> list: - """Возращает список пользователей которые лайкнули анкету""" - ids = Likes.select(Likes).where(Likes.liked_id == user_id) - return [i.liker_id.id for i in ids] - - -async def del_like(liked_id: int, liker_id: int) -> None: - """Удаляет лайк из БД""" - logger.info(f"{liker_id} & {liked_id} | лайк удален") - Likes.delete().where((Likes.liker_id == liker_id) & (Likes.liked_id == liked_id)).execute() diff --git a/database/service/matchs.py b/database/service/matchs.py new file mode 100644 index 0000000..3554b15 --- /dev/null +++ b/database/service/matchs.py @@ -0,0 +1,38 @@ +from sqlalchemy import select, insert +from sqlalchemy.ext.asyncio import AsyncSession + +from ..models.match import Match +from utils.logging import logger + + +async def set_new_like(session: AsyncSession, sender_id: int, receiver_id: int) -> None: + """Добавляет лайк в БД, если он уже есть - ничего не делает""" + stmt = select(Match).where(Match.sender_id == sender_id, Match.receiver_id == receiver_id) + result = await session.execute(stmt) + existing_like = result.scalar() + + if existing_like: + logger.info(f"Повторился лайк: {sender_id} & {receiver_id}") + else: + stmt = insert(Match).values(sender_id=sender_id, receiver_id=receiver_id) + await session.execute(stmt) + await session.commit() + logger.info(f"User: {sender_id} | лайкнул пользователя {receiver_id}") + + +async def get_profile_likes(session: AsyncSession, user_id: int) -> list: + """Возвращает список пользователей, которые лайкнули анкету""" + stmt = select(Match.sender_id).where(Match.receiver_id == user_id) + result = await session.execute(stmt) + + return [row[0] for row in result.fetchall()] + + +async def del_like(session: AsyncSession, receiver_id: int, sender_id: int) -> None: + """Удаляет лайк из БД""" + stmt = Match.__table__.delete().where( + (Match.sender_id == sender_id) & (Match.receiver_id == receiver_id) + ) + await session.execute(stmt) + await session.commit() + logger.info(f"{sender_id} & {receiver_id} | лайк удален") diff --git a/database/service/profile.py b/database/service/profile.py deleted file mode 100644 index 7fbfb27..0000000 --- a/database/service/profile.py +++ /dev/null @@ -1,63 +0,0 @@ -from ..models.profile import Profile - -from utils.logging import logger - - -async def get_profile(user_id: int): - """Возвращает профиль пользователя""" - return Profile.get_or_none(Profile.user_id == user_id) - - -async def delete_profile(user_id: int): - """Удаляет профиль пользователя""" - Profile.delete().where(Profile.user_id == user_id).execute() - logger.info(f"User: {user_id} | удалил профиль") - - -async def update_profile_is_active_status(user_id: int, is_active: bool) -> None: - """Задает профилю статус, активны/не активный""" - Profile.update(is_active=is_active).where(Profile.user_id == user_id).execute() - logger.info(f"User: {user_id} | поменял стату профиля на - {is_active}") - - -async def edit_profile_photo(user_id, photo): - """Изменяет фотографию пользователя""" - Profile.update(photo=photo).where(Profile.user_id == user_id).execute() - logger.info(f"User: {user_id} | изменил фотографию") - - -async def edit_profile_description(user_id, description): - """Изменяет описание пользователя""" - Profile.update(description=description).where(Profile.user_id == user_id).execute() - logger.info(f"User | {user_id} изменил описание") - - -async def create_profile( - user_id: int, - gender: str, - find_gender: str, - photo: str, - name: str, - age: int, - city: str, - latitude: str, - longitude: str, - description: str, -): - """Создает профиль пользователя, если профиль есть - удаляет его""" - if await get_profile(user_id): - await delete_profile(user_id) - - Profile.create( - user_id=user_id, - gender=gender, - find_gender=find_gender, - photo=photo, - name=name, - age=age, - city=city, - latitude=latitude, - longitude=longitude, - description=description, - ) - logger.info(f"User: {user_id} | создал анкету") diff --git a/database/service/profiles.py b/database/service/profiles.py new file mode 100644 index 0000000..5fd68bb --- /dev/null +++ b/database/service/profiles.py @@ -0,0 +1,89 @@ +from sqlalchemy import select, update, delete +from sqlalchemy.orm import joinedload +from sqlalchemy.ext.asyncio import AsyncSession + +from ..models.profile import Profile +from utils.logging import logger + + +async def get_profile(session: AsyncSession, user_id: int): + """Возвращает профиль пользователя""" + return await session.get(Profile, user_id) + + +async def get_profile_with_user(session: AsyncSession, user_id: int): + """Возвращает профиль пользователя с данными пользователя""" + stmt = select(Profile).options(joinedload(Profile.user)).where(Profile.user_id == user_id) + result = await session.execute(stmt) + return result.scalar_one_or_none() + + +async def delete_profile(session: AsyncSession, user_id: int): + """Удаляет профиль пользователя""" + stmt = delete(Profile).where(Profile.user_id == user_id) + await session.execute(stmt) + await session.commit() + logger.info(f"User: {user_id} | удалил профиль") + + +async def update_profile_is_active_status( + session: AsyncSession, user_id: int, is_active: bool +) -> None: + """Задает профилю статус, активный/не активный""" + await session.execute( + update(Profile).where(Profile.user_id == user_id).values(is_active=is_active) + ) + await session.commit() + logger.info(f"User: {user_id} | поменял статус профиля на - {is_active}") + + +async def edit_profile_photo(session: AsyncSession, user_id: int, photo: str): + """Изменяет фотографию пользователя""" + await session.execute(update(Profile).where(Profile.user_id == user_id).values(photo=photo)) + await session.commit() + logger.info(f"User: {user_id} | изменил фотографию") + + +async def edit_profile_description(session: AsyncSession, user_id: int, description: str): + """Изменяет описание пользователя""" + + await session.execute( + update(Profile).where(Profile.user_id == user_id).values(description=description) + ) + await session.commit() + logger.info(f"User | {user_id} изменил описание") + + +async def create_profile( + session: AsyncSession, + user_id: int, + gender: str, + find_gender: str, + photo: str, + name: str, + age: int, + city: str, + latitude: str, + longitude: str, + description: str, +): + """Создает профиль пользователя, если профиль есть - удаляет его""" + if await get_profile(session, user_id): + await delete_profile(session, user_id) + + profile = Profile( + user_id=user_id, + gender=gender, + find_gender=find_gender, + photo=photo, + name=name, + age=age, + city=city, + latitude=latitude, + longitude=longitude, + description=description, + ) + + session.add(profile) + await session.commit() + logger.info(f"User: {user_id} | создал анкету") diff --git a/database/service/search.py b/database/service/search.py index 8217bcd..331b194 100644 --- a/database/service/search.py +++ b/database/service/search.py @@ -1,41 +1,48 @@ -from peewee import fn +from sqlalchemy import select, and_, or_, func +from sqlalchemy.ext.asyncio import AsyncSession from loguru import logger -from database.models import Profile -from database.service.profile import get_profile +from database.models.profile import Profile +from database.service.profiles import get_profile -async def elastic_search_user_ids(user_id: int, age_range: int = 3, distance: float = 0.1) -> list: + +async def elastic_search_user_ids( + session: AsyncSession, user_id: int, age_range: int = 3, distance: float = 0.1 +) -> list: """ Ищет подходящие анкеты для пользователя и возвращает список id пользователей, которые подходят под критерии поиска. - Поиск идет по координатам и параметрам анкеты + Поиск идет по координатам и параметрам анкеты. """ - profile: Profile = await get_profile(user_id) + profile: Profile = await get_profile(session, user_id) + if not profile: + return [] # Вычисляем расстояние по координатам - distance_expr = fn.SQRT( - fn.POW(Profile.latitude - profile.latitude, 2) - + fn.POW(Profile.longitude - profile.longitude, 2) + distance_expr = func.sqrt( + func.pow(Profile.latitude - profile.latitude, 2) + + func.pow(Profile.longitude - profile.longitude, 2) ) - users = ( - Profile.select(Profile.user_id, distance_expr.alias("distance")) + stmt = ( + select(Profile.user_id) .where( - (Profile.is_active == True) - & (fn.ABS(Profile.latitude - profile.latitude) < distance) - & (fn.ABS(Profile.longitude - profile.longitude) < distance) - & ((Profile.gender == profile.find_gender) | (profile.find_gender == "all")) - & ((profile.gender == Profile.find_gender) | (Profile.find_gender == "all")) - & (Profile.age.between(profile.age - age_range, profile.age + age_range)) - & (Profile.user_id != user_id) - ) - .order_by( - fn.SQRT( - fn.POW(Profile.latitude - profile.latitude, 2) - + fn.POW(Profile.longitude - profile.longitude, 2) + and_( + Profile.is_active == True, + func.abs(Profile.latitude - profile.latitude) < distance, + func.abs(Profile.longitude - profile.longitude) < distance, + or_(Profile.gender == profile.find_gender, profile.find_gender == "all"), + or_(profile.gender == Profile.find_gender, Profile.find_gender == "all"), + Profile.age.between(profile.age - age_range, profile.age + age_range), + Profile.user_id != user_id, ) ) + .order_by(distance_expr) ) + + result = await session.execute(stmt) + user_ids = [row[0] for row in result.fetchall()] + logger.info(f"User: {user_id} | начал поиск анкет") - return [i.user_id.id for i in users] + return user_ids diff --git a/database/service/stats.py b/database/service/stats.py index 04b4260..50eba78 100644 --- a/database/service/stats.py +++ b/database/service/stats.py @@ -1,34 +1,45 @@ -from peewee import fn, Case +from sqlalchemy import select, func, case +from sqlalchemy.ext.asyncio import AsyncSession -from ..models.users import Users +from ..models.user import User from ..models.profile import Profile -async def get_all_users_registration_data() -> list: - users = Users.select(Users.id, Users.username, Users.created_at).order_by(Users.referral.desc()) - # Формируем данные в виде списка словарей - registration_data = [ - {"username": user.username, "timestamp": user.created_at} for user in users - ] - return registration_data +async def get_all_users_registration_data(session: AsyncSession) -> list: + """Возвращает список пользователей с датой регистрации""" + stmt = select(User.id, User.username, User.created_at).order_by(User.referral.desc()) + result = await session.execute(stmt) + users = result.fetchall() + return [{"username": user.username, "timestamp": user.created_at} for user in users] -async def get_users_stats() -> tuple[int, int]: + +async def get_users_stats(session: AsyncSession) -> tuple[int, int]: """Возвращает количество пользователей и заблокированных пользователей""" - query = Users.select( - fn.COUNT(Users.id).alias("count"), - fn.SUM(Case(Users.is_banned, [(True, 1)], 0)).alias("banned_count"), + stmt = select( + func.count(User.id).label("count"), + func.sum(case((User.is_banned == True, 1), else_=0)).label("banned_count"), ) - return query.dicts().get() + result = await session.execute(stmt) + stats = result.fetchone() + + return {"count": stats[0], "banned_count": stats[1]} -async def get_profile_stats() -> dict: - """Возвращает количество: пользовательских анкет, - анкет парне, анкет девушек, не активныханкет""" - query = Profile.select( - fn.COUNT(Profile.user_id).alias("count"), - fn.SUM(Case(None, [(Profile.gender == "male", 1)], 0)).alias("male_count"), - fn.SUM(Case(None, [(Profile.gender == "female", 1)], 0)).alias("female_count"), - fn.SUM(Case(None, [(Profile.is_active == False, 1)], 0)).alias("inactive_profile"), +async def get_profile_stats(session: AsyncSession) -> dict: + """Возвращает количество анкет (всего, мужчин, женщин, неактивных)""" + stmt = select( + func.count(Profile.user_id).label("count"), + func.sum(case((Profile.gender == "male", 1), else_=0)).label("male_count"), + func.sum(case((Profile.gender == "female", 1), else_=0)).label("female_count"), + func.sum(case((Profile.is_active == False, 1), else_=0)).label("inactive_profile"), ) - return query.dicts().get() + result = await session.execute(stmt) + stats = result.fetchone() + + return { + "count": stats[0], + "male_count": stats[1], + "female_count": stats[2], + "inactive_profile": stats[3], + } diff --git a/database/service/users.py b/database/service/users.py index c7b1fdb..9147d0e 100644 --- a/database/service/users.py +++ b/database/service/users.py @@ -1,54 +1,60 @@ -from ..models.users import Users +from sqlalchemy import select, update +from sqlalchemy.ext.asyncio import AsyncSession +from ..models.user import User from utils.logging import logger -async def get_user(user_id: int) -> Users | None: +async def get_user(session: AsyncSession, user_id: int) -> User | None: """Возвращает пользователя по его id""" - try: - return Users.get(Users.id == user_id) - except: - return None + return await session.get(User, user_id) -async def get_or_create_user(user_id: int, username: str = None, language: str = None) -> Users: +async def get_or_create_user( + session: AsyncSession, user_id: int, username: str = None, language: str = None +) -> User: """Возвращает пользователя по его id, если его нет - создает""" - if user := await get_user(user_id): + if user := await get_user(session, user_id): return user - return await create_user(user_id, username, language) + return await create_user(session, user_id, username, language) -async def create_user(user_id: int, username: str = None, language: str = None) -> Users: +async def create_user( + session: AsyncSession, user_id: int, username: str = None, language: str = None +) -> User: """Создает нового пользователя""" logger.info(f"New user: {user_id} | {username}") - return Users.create(id=user_id, username=username, language=language) + user = User(id=user_id, username=username, language=language) + session.add(user) + await session.commit() + return user -async def update_user_username(user_id: int, username: str = None) -> None: +async def update_user_username(session: AsyncSession, user_id: int, username: str = None) -> None: """Обновляет данные пользователя""" - Users.update(username=username).where(Users.id == user_id).execute() + await session.execute(update(User).where(User.id == user_id).values(username=username)) + await session.commit() logger.info(f"Update user: {user_id} | {username}") -async def new_referral(inviter_id: int) -> None: +async def new_referral(session: AsyncSession, inviter_id: int) -> None: """Добавляет приведенного реферала к пользователю inviter_id""" - Users.update(referral=Users.referral + 1).where(Users.id == inviter_id).execute() + await session.execute( + update(User).where(User.id == inviter_id).values(referral=User.referral + 1) + ) + await session.commit() logger.info(f"User: {inviter_id} | привел нового пользователя") -async def change_language(user_id: int, language: str) -> None: +async def change_language(session: AsyncSession, user_id: int, language: str) -> None: """Изменяет язык пользователя на language""" - Users.update(language=language).where(Users.id == user_id).execute() + await session.execute(update(User).where(User.id == user_id).values(language=language)) + await session.commit() logger.info(f"User: {user_id} | изменил язык на - {language}") -async def toggle_user_ban(user: Users) -> None: - """Меняет статус блокировки пользователя на противоположный""" - user.is_banned = not user.is_banned - user.save() - - -async def ban_or_unban_user(user_id: int, is_banned: bool) -> None: +async def ban_or_unban_user(session: AsyncSession, user_id: int, is_banned: bool) -> None: """Меняет статус блокировки пользователя на заданный""" - Users.update(is_banned=is_banned).where(Users.id == user_id).execute() - logger.info(f"User: {user_id} | стату блокироваки изминен на - {is_banned}") + await session.execute(update(User).where(User.id == user_id).values(is_banned=is_banned)) + await session.commit() + logger.info(f"User: {user_id} | статус блокировки изменен на - {is_banned}") diff --git a/loader.py b/loader.py index 46a7940..b8e4c30 100644 --- a/loader.py +++ b/loader.py @@ -3,26 +3,26 @@ from aiogram.enums import ParseMode from aiogram.utils.i18n import I18n -from data import config +from data.config import redis, tgbot, I18N_DOMAIN, LOCALES_DIR from utils.logging import logger -if config.REDIS_URL: +if redis.URL: from aiogram.fsm.storage.redis import RedisStorage from redis.asyncio.client import Redis - storage = RedisStorage(Redis.from_url(config.REDIS_URL)) + storage = RedisStorage(Redis.from_url(redis.URL)) logger.info("Storage: Redis") -elif not config.REDIS_URL: +elif not redis.URL: from aiogram.fsm.storage.memory import MemoryStorage storage = MemoryStorage() logger.info("Storage: Default") bot = Bot( - config.TG_TOKEN, + token=tgbot.TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML), ) dp = Dispatcher(bot=bot, storage=storage) -i18n = I18n(path=config.LOCALES_DIR, domain=config.I18N_DOMAIN) +i18n = I18n(path=LOCALES_DIR, domain=I18N_DOMAIN) _ = i18n.gettext diff --git a/main.py b/main.py index b4d4686..07a8789 100644 --- a/main.py +++ b/main.py @@ -3,7 +3,7 @@ from loader import dp, bot from utils.logging import logger -from data.config import SKIP_UPDATES +from data.config import tgbot from app.middlewares import setup_middlewares from app.handlers import setup_handlers @@ -11,7 +11,9 @@ async def on_startup() -> None: from app.others.commands import set_default_commands + from database.connect import create_db + await create_db() await set_default_commands() logger.info("~ Bot startup") @@ -26,7 +28,7 @@ async def main(): dp.startup.register(on_startup) dp.shutdown.register(on_shutdown) - await bot(DeleteWebhook(drop_pending_updates=SKIP_UPDATES)) + await bot(DeleteWebhook(drop_pending_updates=tgbot.SKIP_UPDATES)) await dp.start_polling(bot) diff --git a/readme.md b/readme.md index 4b63792..64c9737 100644 --- a/readme.md +++ b/readme.md @@ -2,7 +2,7 @@ - `Aiogram 3` - `i18n` -- ORM: `Peewee` +- ORM: `SqlAlchemy` - Database: `PostgreSQL \ Sqlite, Redis`

diff --git a/readmeru.md b/readmeru.md index 906d086..d9834f7 100644 --- a/readmeru.md +++ b/readmeru.md @@ -2,7 +2,7 @@ - `Aiogram 3` - `i18n` -- ORM: `Peewee` +- ORM: `SqlAlchemy` - Database: `PostgreSQL \ Sqlite, Redis`

diff --git a/requirements.txt b/requirements.txt index c036aa58280202e4376f9e061d1ade4166104a89..65d4e293dcc060bd375541941f2a7c6bdc825bae 100644 GIT binary patch delta 236 zcmaFI^N4T45ywo1e1>9%LWUfMOokGMR0dlhG+@wUFk&zSk_HUC3|tI}K-pA=T!ti| znq;sFkenfd35cAy*Ic}qp^_mFC{@6a4mZGRdY(~j+h9aQmRG>V_kP@)GF-YTN zZ>EWszCgpXfldHf3o;ZWV+pntBvS;GD+QVw3}mMPb%RuaQ~({g`6|;-Cgos;Kn5QM cN1)Nk3>iQLxj=`26d6Gj0To+JKFPWi04^yk*Z=?k delta 28 kcmaFF_l{@6k;y!a2Aks;6Bs8yVCvYsg838E str: +async def get_or_create_registration_graph(session, data=None, path=registration_photo_path) -> str: """Создает график регистрации пользователей и возращает путь к фотографии графика""" if data is None: - data = await get_all_users_registration_data() + data = await get_all_users_registration_data(session) create_user_registration_graph(data, path) return path From 85505a6dd9d28694c82ff395a470c3c1e01c9859 Mon Sep 17 00:00:00 2001 From: devvsima Date: Sat, 8 Feb 2025 01:08:11 +0200 Subject: [PATCH 9/9] Update --- requirements.txt | Bin 1890 -> 1652 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index 65d4e293dcc060bd375541941f2a7c6bdc825bae..c603eb0ef11a5caabfd9fa33026ea636db37b0c9 100644 GIT binary patch delta 80 zcmaFF_l0Ld38UG>Qe{S?i8BKy^Dwq?n=7y}V!sgAqh< zay8>>R#PC`Y_m3#B%`G-Ln1>qLq1%eF;L2qftP`c0VGodlq+Q@UsOb4kj zV9=Xv%dE|4FgcTXy<{p-rW}Y7@`eoNKvfo#1zEg3i-9JT0Ns`Y)@=q9hqw=9M*%}I zLnYAF`9M}W(22TWU*v&pt^}(GIolGf$6#_O%U4#AXN)HMvnq-f0nJSVLXew)?g6VZ K*__SF$p`?6nlxYl