Dostęp do danych trwałych schodzi za trzy repozytoria, zamiast być rozsmarowany po metodach coga i endpointach: - GuildConfigRepository - kanały powiadomień per serwer i domyślna liczba odtworzeń. - HistoryRepository - historia per serwer z buforem w pamięci i limitem wpisów. Zasada odsiewania duplikatów (zgodny tytuł albo adres) siedzi teraz w HistoryEntry.is_same_track_as zamiast w warunku wbudowanym w listę składaną. - UploadsRepository - katalog uploadów. Każda nazwa przechodzi przez os.path.basename w jednym miejscu, co zamyka temat ścieżek względnych przychodzących z API. Wpisy historii i pliki opisują struktury HistoryEntry oraz UploadFileInfo zamiast luźnych słowników z kluczami sprawdzanymi przez .get(). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
47 lines
1.4 KiB
Python
47 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from typing import Any
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class HistoryEntry:
|
|
"""Pojedynczy wpis historii odtwarzania zapisywany w history.json."""
|
|
|
|
id: str
|
|
title: str
|
|
url: str | None = None
|
|
duration: float | None = None
|
|
is_local: bool = False
|
|
filepath: str | None = None
|
|
|
|
def is_same_track_as(self, other: HistoryEntry) -> bool:
|
|
"""Wpisy uznajemy za ten sam utwór przy zgodnym tytule albo adresie."""
|
|
return self.title == other.title or bool(other.url and self.url == other.url)
|
|
|
|
@property
|
|
def replay_source(self) -> str | None:
|
|
"""Ścieżka lub adres, z którego wpis można odtworzyć ponownie."""
|
|
return (self.filepath or self.url) if self.is_local else self.url
|
|
|
|
def to_dict(self) -> dict[str, Any]:
|
|
return {
|
|
"id": self.id,
|
|
"title": self.title,
|
|
"url": self.url,
|
|
"duration": self.duration,
|
|
"is_local": self.is_local,
|
|
"filepath": self.filepath,
|
|
}
|
|
|
|
@classmethod
|
|
def from_dict(cls, data: dict[str, Any]) -> HistoryEntry:
|
|
return cls(
|
|
id=str(data.get("id", "")),
|
|
title=data.get("title", ""),
|
|
url=data.get("url"),
|
|
duration=data.get("duration"),
|
|
is_local=bool(data.get("is_local", False)),
|
|
filepath=data.get("filepath"),
|
|
)
|