From f3a2812cccbba03bd6e453f235f76a670ac050ac Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 4 Oct 2025 03:19:51 +0300 Subject: [PATCH] profile patch --- app/core/models/chat_models.py | 15 +++++++++++- app/core/services/chat_service.py | 40 ++++++++++++++++++++++++++++++- app/ui/views/yobble_home_view.py | 40 ++++++++++++++++++++++++++++--- 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/app/core/models/chat_models.py b/app/core/models/chat_models.py index d600d8d..29f7465 100644 --- a/app/core/models/chat_models.py +++ b/app/core/models/chat_models.py @@ -75,4 +75,17 @@ class PrivateMessageSendData(BaseModel): class PrivateMessageSendResponse(BaseModel): status: str - data: PrivateMessageSendData \ No newline at end of file + data: PrivateMessageSendData + + +# create private chat +class PrivateChatCreateData(BaseModel): + chat_id: UUID = Field(..., description="ID созданного или существующего приватного чата") + chat_type: Literal["private", "self"] + status: str + message: str + + +class PrivateChatCreateResponse(BaseModel): + status: str + data: PrivateChatCreateData diff --git a/app/core/services/chat_service.py b/app/core/services/chat_service.py index cec8d63..a13cf9e 100644 --- a/app/core/services/chat_service.py +++ b/app/core/services/chat_service.py @@ -4,7 +4,8 @@ from app.core.localizer import localizer from app.core.models.chat_models import ( PrivateChatListResponse, PrivateChatListData, PrivateChatHistoryResponse, PrivateChatHistoryData, - PrivateMessageSendRequest, PrivateMessageSendResponse + PrivateMessageSendRequest, PrivateMessageSendResponse, + PrivateChatCreateResponse, PrivateChatCreateData ) from uuid import UUID from app.core.http_client import get_client, authorized_get, authorized_post @@ -116,3 +117,40 @@ async def send_private_message(login: str, token: str, payload: "PrivateMessageS return False, f"{localizer.translate('Сетевая ошибка')}: {e}" except Exception as e: return False, f"{localizer.translate('Произошла ошибка')}: {e}" + +async def create_private_chat(login: str, token: str, target_user_id: str): + """ + ??????? (??? ???????? ????????????) ????????? ??? ? ?????????????. + :return: tuple (ok: bool, data: PrivateChatCreateData | str) + """ + url = f"{config.BASE_URL}/v1/chat/private/create" + headers = {"Authorization": f"Bearer {token}"} + params = {"target_user_id": target_user_id} + + try: + response = await authorized_post(url, login=login, access_token=token, headers=headers, params=params) + + if response.status_code == 200: + data = response.json() + if data.get("status") == "fine": + model = PrivateChatCreateResponse(**data) + return True, model.data + return False, data.get("detail", localizer.translate("????????? ??????")) + + if response.status_code in [401, 403, 404]: + error_data = response.json() + return False, error_data.get("detail", localizer.translate("???????????? ???? ??? ?????? ?? ??????")) + + if response.status_code == 422: + error_data = response.json() + detail = error_data.get("detail") + if isinstance(detail, list): + return False, ", ".join([e.get("msg", localizer.translate("???????????? ?????????")) for e in detail]) + return False, detail or localizer.translate("???????????? ?????????") + + return False, f"{localizer.translate('??????????? ??????')}: {response.status_code}" + + except httpx.RequestError as e: + return False, f"{localizer.translate('??????? ??????')}: {e}" + except Exception as e: + return False, f"{localizer.translate('?????????? ??????')}: {e}" diff --git a/app/ui/views/yobble_home_view.py b/app/ui/views/yobble_home_view.py index 1611dfc..c38813e 100644 --- a/app/ui/views/yobble_home_view.py +++ b/app/ui/views/yobble_home_view.py @@ -19,10 +19,11 @@ from app.core.services.auth_service import get_user_role from app.core.database import get_current_access_token from app.core.localizer import localizer from app.ui.views.chat_view import ChatView -from app.core.services.chat_service import get_chat_history, send_private_message +from app.core.services.chat_service import get_chat_history, send_private_message, create_private_chat from app.core.models.chat_models import PrivateMessageSendRequest, MessageItem from uuid import UUID from app.core.services.search_service import search_by_query +import app.core.config as config class YobbleHomeView(QWidget): REQUIRED_PERMISSIONS = { @@ -741,8 +742,8 @@ class YobbleHomeView(QWidget): def open_profile_view(self, user: dict): try: self.profile_view = ProfileView(user) - # stub handlers for actions - self.profile_view.start_chat_clicked.connect(lambda u: self.show_notification("Скоро: написать сообщение")) + # create private chat on click + self.profile_view.start_chat_clicked.connect(lambda u: asyncio.ensure_future(self._start_private_chat(u))) self.profile_view.follow_clicked.connect(lambda u: self.show_notification("Скоро: подписка")) self.bottom_bar.hide() self.burger_menu_button.hide() @@ -752,6 +753,27 @@ class YobbleHomeView(QWidget): except Exception as e: self.show_notification(str(e), is_error=True) + async def _start_private_chat(self, user: dict): + try: + target_user_id = str(user.get("user_id") or (user.get("profile") or {}).get("user_id") or "") + if not target_user_id: + self.show_notification("Не удалось определить пользователя", is_error=True) + return + token = await get_current_access_token() + if not token: + self.show_notification("Нет токена авторизации", is_error=True) + return + ok, data = await create_private_chat(self.username, token, target_user_id) + if not ok: + self.show_notification(str(data), is_error=True) + return + # открыть чат + from uuid import UUID as _UUID + chat_uuid = _UUID(str(data.chat_id)) if hasattr(data, 'chat_id') else _UUID(str(data.get('chat_id'))) + self.open_chat_view(chat_uuid) + except Exception as e: + self.show_notification(str(e), is_error=True) + def close_profile_view(self): self.content_stack.setCurrentWidget(self.search_results_view) self.bottom_bar.show() @@ -973,3 +995,15 @@ class YobbleHomeView(QWidget): }} """ + # def _update_window_title(self, title): + # def set_title(): + # window = self.window() + # if not window: + # return + + # title = f"{title} | {config.APP_HEADER}" + + # window.setWindowTitle(title) + + # # Откладываем выполнение, чтобы `self.window()` уже был готов + # QTimer.singleShot(0, set_title)