better time usings

This commit is contained in:
2025-10-22 08:14:42 +02:00
parent 04b516a52d
commit 4eede0c8c0
11 changed files with 62 additions and 163 deletions

View File

@@ -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(),

View File

@@ -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)

View File

@@ -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]

View File

@@ -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,