search patch
This commit is contained in:
parent
86d5e03157
commit
5306640238
26
app/core/models/search_models.py
Normal file
26
app/core/models/search_models.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from uuid import UUID
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import Optional, List, Any
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
|
class UserSearchResult(BaseModel):
|
||||||
|
user_id: UUID
|
||||||
|
login: str
|
||||||
|
full_name: Optional[str] = None
|
||||||
|
custom_name: Optional[str] = None
|
||||||
|
created_at: datetime = Field(..., description="Дата регистрации")
|
||||||
|
profile: Optional[Any] = Field(None, description="Модель как у /profile/{user_id}")
|
||||||
|
|
||||||
|
|
||||||
|
class SearchData(BaseModel):
|
||||||
|
users: List[UserSearchResult]
|
||||||
|
groups: List[Any] = []
|
||||||
|
channels: List[Any] = []
|
||||||
|
messages: List[Any] = []
|
||||||
|
|
||||||
|
|
||||||
|
class SearchResponse(BaseModel):
|
||||||
|
status: str
|
||||||
|
data: SearchData
|
||||||
|
|
||||||
42
app/core/services/search_service.py
Normal file
42
app/core/services/search_service.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import httpx
|
||||||
|
from app.core import config
|
||||||
|
from app.core.localizer import localizer
|
||||||
|
from app.core.http_client import authorized_get
|
||||||
|
from app.core.models.search_models import SearchResponse, SearchData
|
||||||
|
|
||||||
|
|
||||||
|
async def search_by_query(login: str, token: str, query: str):
|
||||||
|
"""
|
||||||
|
Поиск по строке: пользователи (префикс), далее можно расширить под группы/каналы/сообщения.
|
||||||
|
|
||||||
|
:return: tuple (ok: bool, data: SearchData | str)
|
||||||
|
"""
|
||||||
|
url = f"{config.BASE_URL}/v1/feed/search"
|
||||||
|
headers = {"Authorization": f"Bearer {token}"}
|
||||||
|
params = {"query": query}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = await authorized_get(url, login=login, access_token=token, headers=headers, params=params)
|
||||||
|
|
||||||
|
print("response.status_code", response.status_code)
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
if data.get("status") == "fine":
|
||||||
|
model = SearchResponse(**data)
|
||||||
|
return True, model.data
|
||||||
|
return False, data.get("detail", localizer.translate("Произошла ошибка"))
|
||||||
|
|
||||||
|
if response.status_code in [401, 403]:
|
||||||
|
error_data = response.json()
|
||||||
|
return False, error_data.get("detail", localizer.translate("Недостаточно прав или неавторизован"))
|
||||||
|
|
||||||
|
if response.status_code == 422:
|
||||||
|
return False, 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}"
|
||||||
|
|
||||||
@ -20,6 +20,7 @@ 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
|
||||||
from app.core.models.chat_models import PrivateMessageSendRequest, MessageItem
|
from app.core.models.chat_models import PrivateMessageSendRequest, MessageItem
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
from app.core.services.search_service import search_by_query
|
||||||
|
|
||||||
class YobbleHomeView(QWidget):
|
class YobbleHomeView(QWidget):
|
||||||
REQUIRED_PERMISSIONS = {
|
REQUIRED_PERMISSIONS = {
|
||||||
@ -271,6 +272,8 @@ class YobbleHomeView(QWidget):
|
|||||||
self.search_input.setPlaceholderText("Поиск…")
|
self.search_input.setPlaceholderText("Поиск…")
|
||||||
self.search_input.hide()
|
self.search_input.hide()
|
||||||
top_bar_layout.addWidget(self.search_input, 1)
|
top_bar_layout.addWidget(self.search_input, 1)
|
||||||
|
# Запуск поиска по Enter
|
||||||
|
self.search_input.returnPressed.connect(self.on_search_submit)
|
||||||
|
|
||||||
# Новые кнопки справа
|
# Новые кнопки справа
|
||||||
self.search_button = QPushButton("🔍")
|
self.search_button = QPushButton("🔍")
|
||||||
@ -664,6 +667,38 @@ class YobbleHomeView(QWidget):
|
|||||||
self.search_button.show()
|
self.search_button.show()
|
||||||
self.notification_button.show()
|
self.notification_button.show()
|
||||||
|
|
||||||
|
def on_search_submit(self):
|
||||||
|
"""Обработчик Enter в поле поиска."""
|
||||||
|
query = (self.search_input.text() or "").strip()
|
||||||
|
if len(query) < 1:
|
||||||
|
self.show_notification(localizer.translate("Введите минимум 1 символ"), is_error=True)
|
||||||
|
return
|
||||||
|
# Запускаем асинхронный поиск
|
||||||
|
asyncio.ensure_future(self._do_search(query))
|
||||||
|
|
||||||
|
async def _do_search(self, query: str):
|
||||||
|
"""Вызов серверного поиска и показ краткого результата."""
|
||||||
|
# Получаем текущие учётные данные
|
||||||
|
login = self.username
|
||||||
|
token = await get_current_access_token()
|
||||||
|
if not token:
|
||||||
|
self.show_notification(localizer.translate("Не найден токен авторизации"), is_error=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
ok, data_or_error = await search_by_query(login, token, query)
|
||||||
|
if not ok:
|
||||||
|
self.show_notification(str(data_or_error), is_error=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
data = data_or_error
|
||||||
|
users_cnt = len(getattr(data, 'users', []) or [])
|
||||||
|
groups_cnt = len(getattr(data, 'groups', []) or [])
|
||||||
|
channels_cnt = len(getattr(data, 'channels', []) or [])
|
||||||
|
messages_cnt = len(getattr(data, 'messages', []) or [])
|
||||||
|
self.show_notification(
|
||||||
|
localizer.translate(f"Найдено: пользователи {users_cnt}, беседы {groups_cnt}, паблики {channels_cnt}, сообщения {messages_cnt}")
|
||||||
|
)
|
||||||
|
|
||||||
def handle_notification_click(self):
|
def handle_notification_click(self):
|
||||||
"""Пустышка для кнопки уведомлений."""
|
"""Пустышка для кнопки уведомлений."""
|
||||||
show_themed_messagebox(
|
show_themed_messagebox(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user