better time usings
This commit is contained in:
parent
04b516a52d
commit
4eede0c8c0
@ -313,107 +313,6 @@ conda run -n AniWorld python -m pytest tests/ -v -s
|
||||
|
||||
---
|
||||
|
||||
## ✅ Completed Sections (Can be removed from this document)
|
||||
|
||||
The following sections have been successfully completed:
|
||||
|
||||
### Deprecated Pydantic V1 API Usage
|
||||
|
||||
**Count:** ~20 warnings
|
||||
|
||||
**Location:** `src/config/settings.py`
|
||||
|
||||
**Issue:**
|
||||
|
||||
```python
|
||||
# Deprecated usage
|
||||
Field(default="value", env="ENV_VAR")
|
||||
|
||||
# Should be:
|
||||
Field(default="value", json_schema_extra={"env": "ENV_VAR"})
|
||||
```
|
||||
|
||||
**Files to Update:**
|
||||
|
||||
- `src/config/settings.py` - Update Field definitions
|
||||
- `src/server/models/config.py` - Update validators to `@field_validator`
|
||||
|
||||
---
|
||||
|
||||
### Deprecated datetime.utcnow() Usage
|
||||
|
||||
**Count:** ~100+ warnings
|
||||
|
||||
**Issue:**
|
||||
|
||||
```python
|
||||
# Deprecated
|
||||
datetime.utcnow()
|
||||
|
||||
# Should use
|
||||
datetime.now(datetime.UTC)
|
||||
```
|
||||
|
||||
**Files to Update:**
|
||||
|
||||
- `src/server/services/auth_service.py`
|
||||
- `src/server/services/download_service.py`
|
||||
- `src/server/services/progress_service.py`
|
||||
- `src/server/services/websocket_service.py`
|
||||
- `src/server/database/service.py`
|
||||
- `src/server/database/models.py`
|
||||
- All test files using `datetime.utcnow()`
|
||||
|
||||
---
|
||||
|
||||
### Deprecated FastAPI on_event
|
||||
|
||||
**Count:** 4 warnings
|
||||
|
||||
**Location:** `src/server/fastapi_app.py`
|
||||
|
||||
**Issue:**
|
||||
|
||||
```python
|
||||
# Deprecated
|
||||
@app.on_event("startup")
|
||||
@app.on_event("shutdown")
|
||||
|
||||
# Should use lifespan
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
# Startup
|
||||
yield
|
||||
# Shutdown
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Deprecated Pydantic .dict() Method
|
||||
|
||||
**Count:** ~5 warnings
|
||||
|
||||
**Issue:**
|
||||
|
||||
```python
|
||||
# Deprecated
|
||||
session.dict()
|
||||
|
||||
# Should be
|
||||
session.model_dump()
|
||||
```
|
||||
|
||||
**Files to Update:**
|
||||
|
||||
- `src/server/middleware/auth.py`
|
||||
- `src/server/utils/dependencies.py`
|
||||
|
||||
---
|
||||
|
||||
## 📝 Task Checklist for AI Agent
|
||||
|
||||
### Phase 4: Frontend Integration 🔄 IN PROGRESS
|
||||
|
||||
- [ ] Fix frontend auth integration tests (42 total → 4 remaining failures)
|
||||
@ -440,7 +339,7 @@ session.model_dump()
|
||||
- TestFrontendRealTimeUpdates (3 failures): All real-time tests
|
||||
- TestFrontendDataFormats (3 failures): All format tests
|
||||
|
||||
### Phase 5: WebSocket Integration ✅ MOSTLY COMPLETE
|
||||
### Phase 5: WebSocket Integration
|
||||
|
||||
- [x] Fix websocket integration tests (48 failures → 2 remaining)
|
||||
- [x] Test connection management
|
||||
@ -452,7 +351,7 @@ session.model_dump()
|
||||
- `test_concurrent_broadcasts_to_different_rooms`
|
||||
- `test_multi_room_workflow`
|
||||
|
||||
### Phase 6: Download Flow ✅ MOSTLY COMPLETE
|
||||
### Phase 6: Download Flow
|
||||
|
||||
- [x] Fix download endpoint API tests (18 errors → All 20 tests passing!)
|
||||
- [x] Fix download flow integration tests (22+ errors → 11 remaining)
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
This module provides the base class that all ORM models inherit from,
|
||||
along with common functionality and mixins.
|
||||
"""
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
from sqlalchemy import DateTime, func
|
||||
@ -67,7 +67,7 @@ class SoftDeleteMixin:
|
||||
|
||||
def soft_delete(self) -> None:
|
||||
"""Mark record as deleted without removing from database."""
|
||||
self.deleted_at = datetime.utcnow()
|
||||
self.deleted_at = datetime.now(timezone.utc)
|
||||
|
||||
def restore(self) -> None:
|
||||
"""Restore a soft deleted record."""
|
||||
|
||||
@ -11,7 +11,7 @@ Models:
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from enum import Enum
|
||||
from typing import List, Optional
|
||||
|
||||
@ -422,7 +422,7 @@ class UserSession(Base, TimestampMixin):
|
||||
@property
|
||||
def is_expired(self) -> bool:
|
||||
"""Check if session has expired."""
|
||||
return datetime.utcnow() > self.expires_at
|
||||
return datetime.now(timezone.utc) > self.expires_at
|
||||
|
||||
def revoke(self) -> None:
|
||||
"""Revoke this session."""
|
||||
|
||||
@ -14,7 +14,7 @@ All services support both async and sync operations for flexibility.
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from sqlalchemy import delete, select, update
|
||||
@ -276,7 +276,7 @@ class EpisodeService:
|
||||
file_path=file_path,
|
||||
file_size=file_size,
|
||||
is_downloaded=is_downloaded,
|
||||
download_date=datetime.utcnow() if is_downloaded else None,
|
||||
download_date=datetime.now(timezone.utc) if is_downloaded else None,
|
||||
)
|
||||
db.add(episode)
|
||||
await db.flush()
|
||||
@ -380,7 +380,7 @@ class EpisodeService:
|
||||
episode.is_downloaded = True
|
||||
episode.file_path = file_path
|
||||
episode.file_size = file_size
|
||||
episode.download_date = datetime.utcnow()
|
||||
episode.download_date = datetime.now(timezone.utc)
|
||||
|
||||
await db.flush()
|
||||
await db.refresh(episode)
|
||||
@ -597,9 +597,9 @@ class DownloadQueueService:
|
||||
|
||||
# Update timestamps based on status
|
||||
if status == DownloadStatus.DOWNLOADING and not item.started_at:
|
||||
item.started_at = datetime.utcnow()
|
||||
item.started_at = datetime.now(timezone.utc)
|
||||
elif status in (DownloadStatus.COMPLETED, DownloadStatus.FAILED):
|
||||
item.completed_at = datetime.utcnow()
|
||||
item.completed_at = datetime.now(timezone.utc)
|
||||
|
||||
# Set error message for failed downloads
|
||||
if status == DownloadStatus.FAILED and error_message:
|
||||
@ -807,7 +807,7 @@ class UserSessionService:
|
||||
"""
|
||||
query = select(UserSession).where(
|
||||
UserSession.is_active == True,
|
||||
UserSession.expires_at > datetime.utcnow(),
|
||||
UserSession.expires_at > datetime.now(timezone.utc),
|
||||
)
|
||||
|
||||
if user_id:
|
||||
@ -834,7 +834,7 @@ class UserSessionService:
|
||||
if not session:
|
||||
return None
|
||||
|
||||
session.last_activity = datetime.utcnow()
|
||||
session.last_activity = datetime.now(timezone.utc)
|
||||
await db.flush()
|
||||
await db.refresh(session)
|
||||
return session
|
||||
@ -871,7 +871,7 @@ class UserSessionService:
|
||||
"""
|
||||
result = await db.execute(
|
||||
delete(UserSession).where(
|
||||
UserSession.expires_at < datetime.utcnow()
|
||||
UserSession.expires_at < datetime.now(timezone.utc)
|
||||
)
|
||||
)
|
||||
count = result.rowcount
|
||||
|
||||
@ -6,7 +6,7 @@ easy to validate and test.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field, constr
|
||||
@ -53,5 +53,5 @@ class SessionModel(BaseModel):
|
||||
|
||||
session_id: str = Field(..., description="Unique session identifier")
|
||||
user: Optional[str] = Field(None, description="Username or identifier")
|
||||
created_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
||||
expires_at: Optional[datetime] = Field(None)
|
||||
|
||||
@ -6,7 +6,7 @@ on serialization, validation, and OpenAPI documentation.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from enum import Enum
|
||||
from typing import List, Optional
|
||||
|
||||
@ -80,8 +80,8 @@ class DownloadItem(BaseModel):
|
||||
|
||||
# Timestamps
|
||||
added_at: datetime = Field(
|
||||
default_factory=datetime.utcnow,
|
||||
description="When item was added to queue"
|
||||
default_factory=lambda: datetime.now(timezone.utc),
|
||||
description="When item was added to queue",
|
||||
)
|
||||
started_at: Optional[datetime] = Field(
|
||||
None, description="When download started"
|
||||
|
||||
@ -6,7 +6,7 @@ for real-time updates.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
@ -56,7 +56,7 @@ class WebSocketMessage(BaseModel):
|
||||
..., description="Type of the message"
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
default_factory=lambda: datetime.now(timezone.utc).isoformat(),
|
||||
description="ISO 8601 timestamp when message was created",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
@ -72,7 +72,7 @@ class DownloadProgressMessage(BaseModel):
|
||||
description="Message type",
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
default_factory=lambda: datetime.now(timezone.utc).isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
@ -89,7 +89,7 @@ class DownloadCompleteMessage(BaseModel):
|
||||
description="Message type",
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
default_factory=lambda: datetime.now(timezone.utc).isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
@ -105,7 +105,7 @@ class DownloadFailedMessage(BaseModel):
|
||||
description="Message type",
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
default_factory=lambda: datetime.now(timezone.utc).isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
@ -121,7 +121,7 @@ class QueueStatusMessage(BaseModel):
|
||||
description="Message type",
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
default_factory=lambda: datetime.now(timezone.utc).isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
@ -137,7 +137,7 @@ class SystemMessage(BaseModel):
|
||||
..., description="System message type"
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
default_factory=lambda: datetime.now(timezone.utc).isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
@ -152,7 +152,7 @@ class ErrorMessage(BaseModel):
|
||||
default=WebSocketMessageType.ERROR, description="Message type"
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
default_factory=lambda: datetime.now(timezone.utc).isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
@ -167,7 +167,7 @@ class ConnectionMessage(BaseModel):
|
||||
..., description="Connection message type"
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
default_factory=lambda: datetime.now(timezone.utc).isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
@ -203,7 +203,7 @@ class ScanProgressMessage(BaseModel):
|
||||
description="Message type",
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
default_factory=lambda: datetime.now(timezone.utc).isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
@ -220,7 +220,7 @@ class ScanCompleteMessage(BaseModel):
|
||||
description="Message type",
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
default_factory=lambda: datetime.now(timezone.utc).isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
@ -237,7 +237,7 @@ class ScanFailedMessage(BaseModel):
|
||||
description="Message type",
|
||||
)
|
||||
timestamp: str = Field(
|
||||
default_factory=lambda: datetime.utcnow().isoformat(),
|
||||
default_factory=lambda: datetime.now(timezone.utc).isoformat(),
|
||||
description="ISO 8601 timestamp",
|
||||
)
|
||||
data: Dict[str, Any] = Field(
|
||||
|
||||
@ -12,7 +12,7 @@ can call it from async routes via threadpool if needed.
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Dict, Optional
|
||||
|
||||
from jose import JWTError, jwt # type: ignore
|
||||
@ -103,10 +103,10 @@ class AuthService:
|
||||
def _record_failure(self, identifier: str) -> None:
|
||||
rec = self._get_fail_record(identifier)
|
||||
rec["count"] += 1
|
||||
rec["last"] = datetime.utcnow()
|
||||
rec["last"] = datetime.now(timezone.utc)
|
||||
if rec["count"] >= self.max_attempts:
|
||||
rec["locked_until"] = (
|
||||
datetime.utcnow() + timedelta(seconds=self.lockout_seconds)
|
||||
datetime.now(timezone.utc) + timedelta(seconds=self.lockout_seconds)
|
||||
)
|
||||
|
||||
def _clear_failures(self, identifier: str) -> None:
|
||||
@ -116,11 +116,11 @@ class AuthService:
|
||||
def _check_locked(self, identifier: str) -> None:
|
||||
rec = self._get_fail_record(identifier)
|
||||
lu = rec.get("locked_until")
|
||||
if lu and datetime.utcnow() < lu:
|
||||
if lu and datetime.now(timezone.utc) < lu:
|
||||
raise LockedOutError(
|
||||
"Too many failed attempts - temporarily locked out"
|
||||
)
|
||||
if lu and datetime.utcnow() >= lu:
|
||||
if lu and datetime.now(timezone.utc) >= lu:
|
||||
# lock expired, reset
|
||||
self._failed[identifier] = {
|
||||
"count": 0,
|
||||
@ -155,13 +155,13 @@ class AuthService:
|
||||
def create_access_token(
|
||||
self, subject: str = "master", remember: bool = False
|
||||
) -> LoginResponse:
|
||||
expiry = datetime.utcnow() + timedelta(
|
||||
expiry = datetime.now(timezone.utc) + timedelta(
|
||||
hours=(168 if remember else self.token_expiry_hours)
|
||||
)
|
||||
payload = {
|
||||
"sub": subject,
|
||||
"exp": int(expiry.timestamp()),
|
||||
"iat": int(datetime.utcnow().timestamp()),
|
||||
"iat": int(datetime.now(timezone.utc).timestamp()),
|
||||
}
|
||||
token = jwt.encode(payload, self.secret, algorithm="HS256")
|
||||
|
||||
@ -180,7 +180,7 @@ class AuthService:
|
||||
data = self.decode_token(token)
|
||||
exp_val = data.get("exp")
|
||||
expires_at = (
|
||||
datetime.utcfromtimestamp(exp_val) if exp_val is not None else None
|
||||
datetime.fromtimestamp(exp_val, timezone.utc) if exp_val is not None else None
|
||||
)
|
||||
return SessionModel(
|
||||
session_id=hashlib.sha256(token.encode()).hexdigest(),
|
||||
|
||||
@ -11,7 +11,7 @@ import json
|
||||
import uuid
|
||||
from collections import deque
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Callable, Dict, List, Optional
|
||||
|
||||
@ -183,7 +183,7 @@ class DownloadService:
|
||||
item.model_dump(mode="json")
|
||||
for item in self._failed_items
|
||||
],
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
}
|
||||
|
||||
with open(self._persistence_path, "w", encoding="utf-8") as f:
|
||||
@ -225,7 +225,7 @@ class DownloadService:
|
||||
episode=episode,
|
||||
status=DownloadStatus.PENDING,
|
||||
priority=priority,
|
||||
added_at=datetime.utcnow(),
|
||||
added_at=datetime.now(timezone.utc),
|
||||
)
|
||||
|
||||
# Insert based on priority
|
||||
@ -284,7 +284,7 @@ class DownloadService:
|
||||
if item_id in self._active_downloads:
|
||||
item = self._active_downloads[item_id]
|
||||
item.status = DownloadStatus.CANCELLED
|
||||
item.completed_at = datetime.utcnow()
|
||||
item.completed_at = datetime.now(timezone.utc)
|
||||
self._failed_items.append(item)
|
||||
del self._active_downloads[item_id]
|
||||
removed_ids.append(item_id)
|
||||
@ -673,7 +673,7 @@ class DownloadService:
|
||||
try:
|
||||
# Update status
|
||||
item.status = DownloadStatus.DOWNLOADING
|
||||
item.started_at = datetime.utcnow()
|
||||
item.started_at = datetime.now(timezone.utc)
|
||||
self._active_downloads[item.id] = item
|
||||
|
||||
logger.info(
|
||||
@ -715,7 +715,7 @@ class DownloadService:
|
||||
# Handle result
|
||||
if success:
|
||||
item.status = DownloadStatus.COMPLETED
|
||||
item.completed_at = datetime.utcnow()
|
||||
item.completed_at = datetime.now(timezone.utc)
|
||||
|
||||
# Track downloaded size
|
||||
if item.progress and item.progress.downloaded_mb:
|
||||
@ -757,7 +757,7 @@ class DownloadService:
|
||||
except Exception as e:
|
||||
# Handle failure
|
||||
item.status = DownloadStatus.FAILED
|
||||
item.completed_at = datetime.utcnow()
|
||||
item.completed_at = datetime.now(timezone.utc)
|
||||
item.error = str(e)
|
||||
self._failed_items.append(item)
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from enum import Enum
|
||||
from typing import Any, Callable, Dict, Optional
|
||||
|
||||
@ -65,8 +65,8 @@ class ProgressUpdate:
|
||||
current: int = 0
|
||||
total: int = 0
|
||||
metadata: Dict[str, Any] = field(default_factory=dict)
|
||||
started_at: datetime = field(default_factory=datetime.utcnow)
|
||||
updated_at: datetime = field(default_factory=datetime.utcnow)
|
||||
started_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
||||
updated_at: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""Convert progress update to dictionary."""
|
||||
@ -254,7 +254,7 @@ class ProgressService:
|
||||
update.percent = 0.0
|
||||
|
||||
update.status = ProgressStatus.IN_PROGRESS
|
||||
update.updated_at = datetime.utcnow()
|
||||
update.updated_at = datetime.now(timezone.utc)
|
||||
|
||||
# Only broadcast if significant change or forced
|
||||
percent_change = abs(update.percent - old_percent)
|
||||
@ -296,7 +296,7 @@ class ProgressService:
|
||||
update.message = message
|
||||
update.percent = 100.0
|
||||
update.current = update.total
|
||||
update.updated_at = datetime.utcnow()
|
||||
update.updated_at = datetime.now(timezone.utc)
|
||||
|
||||
if metadata:
|
||||
update.metadata.update(metadata)
|
||||
@ -345,7 +345,7 @@ class ProgressService:
|
||||
update = self._active_progress[progress_id]
|
||||
update.status = ProgressStatus.FAILED
|
||||
update.message = error_message
|
||||
update.updated_at = datetime.utcnow()
|
||||
update.updated_at = datetime.now(timezone.utc)
|
||||
|
||||
if metadata:
|
||||
update.metadata.update(metadata)
|
||||
@ -393,7 +393,7 @@ class ProgressService:
|
||||
update = self._active_progress[progress_id]
|
||||
update.status = ProgressStatus.CANCELLED
|
||||
update.message = message
|
||||
update.updated_at = datetime.utcnow()
|
||||
update.updated_at = datetime.now(timezone.utc)
|
||||
|
||||
# Move to history
|
||||
del self._active_progress[progress_id]
|
||||
|
||||
@ -8,7 +8,7 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any, Dict, List, Optional, Set
|
||||
|
||||
import structlog
|
||||
@ -346,7 +346,7 @@ class WebSocketService:
|
||||
user_id: Optional user identifier for authentication
|
||||
"""
|
||||
metadata = {
|
||||
"connected_at": datetime.utcnow().isoformat(),
|
||||
"connected_at": datetime.now(timezone.utc).isoformat(),
|
||||
"user_id": user_id,
|
||||
}
|
||||
await self._manager.connect(websocket, connection_id, metadata)
|
||||
@ -366,7 +366,7 @@ class WebSocketService:
|
||||
"""
|
||||
message = {
|
||||
"type": "download_progress",
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"data": {
|
||||
"download_id": download_id,
|
||||
**progress_data,
|
||||
@ -385,7 +385,7 @@ class WebSocketService:
|
||||
"""
|
||||
message = {
|
||||
"type": "download_complete",
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"data": {
|
||||
"download_id": download_id,
|
||||
**result_data,
|
||||
@ -404,7 +404,7 @@ class WebSocketService:
|
||||
"""
|
||||
message = {
|
||||
"type": "download_failed",
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"data": {
|
||||
"download_id": download_id,
|
||||
**error_data,
|
||||
@ -420,7 +420,7 @@ class WebSocketService:
|
||||
"""
|
||||
message = {
|
||||
"type": "queue_status",
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"data": status_data,
|
||||
}
|
||||
await self._manager.broadcast_to_room(message, "downloads")
|
||||
@ -436,7 +436,7 @@ class WebSocketService:
|
||||
"""
|
||||
message = {
|
||||
"type": f"system_{message_type}",
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"data": data,
|
||||
}
|
||||
await self._manager.broadcast(message)
|
||||
@ -453,7 +453,7 @@ class WebSocketService:
|
||||
"""
|
||||
message = {
|
||||
"type": "error",
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||||
"data": {
|
||||
"code": error_code,
|
||||
"message": error_message,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user