chore: stylize sse code; fix: add sseclient-py to requirements
This commit is contained in:
@@ -2,8 +2,8 @@ from uuid import UUID
|
||||
from _io import BufferedReader
|
||||
from typing import cast, Iterator
|
||||
from datetime import datetime
|
||||
import json
|
||||
import time
|
||||
from json import JSONDecodeError, loads
|
||||
from time import sleep
|
||||
|
||||
from requests.exceptions import ConnectionError, HTTPError
|
||||
from sseclient import SSEClient
|
||||
@@ -1105,59 +1105,59 @@ class Client:
|
||||
@refresh_on_error
|
||||
def stream_notifications(self) -> Iterator[StreamConnect | StreamNotification]:
|
||||
"""Слушать SSE поток уведомлений
|
||||
|
||||
|
||||
Yields:
|
||||
StreamConnect | StreamNotification: События подключения или уведомления
|
||||
|
||||
|
||||
Example:
|
||||
```python
|
||||
from itd import ITDClient
|
||||
|
||||
|
||||
client = ITDClient(cookies='refresh_token=...')
|
||||
|
||||
|
||||
# Запуск прослушивания
|
||||
for event in client.stream_notifications():
|
||||
if isinstance(event, StreamConnect):
|
||||
print(f'Подключено: {event.user_id}')
|
||||
else:
|
||||
print(f'Уведомление: {event.type} от {event.actor.username}')
|
||||
|
||||
|
||||
# Остановка из другого потока или обработчика
|
||||
# client.stop_stream()
|
||||
```
|
||||
"""
|
||||
self._stream_active = True
|
||||
|
||||
|
||||
while self._stream_active:
|
||||
try:
|
||||
response = stream_notifications(self.token)
|
||||
response.raise_for_status()
|
||||
|
||||
|
||||
client = SSEClient(response)
|
||||
|
||||
|
||||
for event in client.events():
|
||||
if not self._stream_active:
|
||||
response.close()
|
||||
return
|
||||
|
||||
|
||||
try:
|
||||
if not event.data or event.data.strip() == '':
|
||||
continue
|
||||
|
||||
data = json.loads(event.data)
|
||||
|
||||
|
||||
data = loads(event.data)
|
||||
|
||||
if 'userId' in data and 'timestamp' in data and 'type' not in data:
|
||||
yield StreamConnect.model_validate(data)
|
||||
else:
|
||||
yield StreamNotification.model_validate(data)
|
||||
|
||||
except json.JSONDecodeError:
|
||||
|
||||
except JSONDecodeError:
|
||||
print(f'Не удалось распарсить сообщение: {event.data}')
|
||||
continue
|
||||
except Exception as e:
|
||||
print(f'Ошибка обработки события: {e}')
|
||||
continue
|
||||
|
||||
|
||||
except Unauthorized:
|
||||
if self.cookies and self._stream_active:
|
||||
print('Токен истек, обновляем...')
|
||||
@@ -1169,27 +1169,27 @@ class Client:
|
||||
if not self._stream_active:
|
||||
return
|
||||
print(f'Ошибка соединения: {e}, переподключение через 5 секунд...')
|
||||
time.sleep(5)
|
||||
sleep(5)
|
||||
continue
|
||||
|
||||
|
||||
def stop_stream(self):
|
||||
"""Остановить прослушивание SSE потока
|
||||
|
||||
|
||||
Example:
|
||||
```python
|
||||
import threading
|
||||
from itd import ITDClient
|
||||
|
||||
|
||||
client = ITDClient(cookies='refresh_token=...')
|
||||
|
||||
|
||||
# Запуск в отдельном потоке
|
||||
def listen():
|
||||
for event in client.stream_notifications():
|
||||
print(event)
|
||||
|
||||
|
||||
thread = threading.Thread(target=listen)
|
||||
thread.start()
|
||||
|
||||
|
||||
# Остановка через 10 секунд
|
||||
import time
|
||||
time.sleep(10)
|
||||
@@ -1197,4 +1197,5 @@ class Client:
|
||||
thread.join()
|
||||
```
|
||||
"""
|
||||
print('stop event')
|
||||
self._stream_active = False
|
||||
@@ -1,11 +1,8 @@
|
||||
from uuid import UUID
|
||||
from datetime import datetime
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from itd.enums import NotificationType, NotificationTargetType
|
||||
from itd.models.user import UserNotification
|
||||
from itd.models.notification import Notification
|
||||
|
||||
|
||||
class StreamConnect(BaseModel):
|
||||
@@ -14,20 +11,7 @@ class StreamConnect(BaseModel):
|
||||
timestamp: int
|
||||
|
||||
|
||||
class StreamNotification(BaseModel):
|
||||
class StreamNotification(Notification):
|
||||
"""Уведомление из SSE потока"""
|
||||
id: UUID
|
||||
type: NotificationType
|
||||
|
||||
target_type: NotificationTargetType | None = Field(None, alias='targetType')
|
||||
target_id: UUID | None = Field(None, alias='targetId')
|
||||
|
||||
preview: str | None = None
|
||||
read_at: datetime | None = Field(None, alias='readAt')
|
||||
created_at: datetime = Field(alias='createdAt')
|
||||
|
||||
user_id: UUID = Field(alias='userId')
|
||||
actor: UserNotification
|
||||
|
||||
read: bool = False
|
||||
sound: bool = True
|
||||
|
||||
@@ -16,7 +16,7 @@ def get_unread_notifications_count(token: str):
|
||||
|
||||
def stream_notifications(token: str):
|
||||
"""Получить SSE поток уведомлений
|
||||
|
||||
|
||||
Returns:
|
||||
Response: Streaming response для SSE
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user