fix: store playback history per Discord server

This commit is contained in:
mmacierzanka committed 2026-08-21 16:21:57 +02:00
1 parent 32fd296d9e
commit cfe9a2fc31
5 files changed
+74 -14

No files matched your search

+1 -1
View File
@@ -43,7 +43,7 @@ class Application:
self.uploads = UploadsRepository(self.settings.uploads_dir)
self.tracks = TrackFactory(self.uploads, MediaProbe())
self.bot = MusicBot(self.settings, self.tracks, self.uploads, self.config)
self.bot = MusicBot(self.settings, self.tracks, self.uploads, self.config, self.history)
self.guilds = GuildResolver(self.bot)
self.player = MusicPlayer(
bot=self.bot,
+32 -13
View File
@@ -1,17 +1,40 @@
from __future__ import annotations
import os
from zyrarbot.music.history_entry import HistoryEntry
from zyrarbot.storage.json_file_store import JsonFileStore
class HistoryRepository:
"""Historia odtwarzania per serwer, buforowana i utrwalana w history.json."""
"""Historia odtwarzania w osobnym pliku dla każdego serwera."""
def __init__(self, store: JsonFileStore, limit: int = 50):
self._store = store
self._limit = limit
self._cache: dict[int, list[HistoryEntry]] = {}
self._legacy_guild_id: int | None = None
self._guild_stores: dict[int, JsonFileStore] = {}
self._legacy_migrated = False
def _guild_store(self, guild_id: int) -> JsonFileStore:
if guild_id not in self._guild_stores:
directory = os.path.join(os.path.dirname(self._store.path), "history")
path = os.path.join(directory, f"{guild_id}.json")
self._guild_stores[guild_id] = JsonFileStore(path)
return self._guild_stores[guild_id]
def migrate_legacy(self, first_guild_id: int) -> None:
"""Move the old shared history file into one file per guild."""
if self._legacy_migrated:
return
legacy_data = self._store.read()
for key, entries in legacy_data.items():
if key == "history" and isinstance(entries, list):
self._write_entries(first_guild_id, entries)
elif key.isdigit() and isinstance(entries, list):
self._write_entries(int(key), entries)
self._legacy_migrated = True
def list(self, guild_id: int) -> list[HistoryEntry]:
if guild_id not in self._cache:
@@ -30,16 +53,7 @@ class HistoryRepository:
return next((item for item in self.list(guild_id) if item.id == entry_id), None)
def _load(self, guild_id: int) -> list[HistoryEntry]:
raw_entries = self._store.get(str(guild_id))
if raw_entries is None and self._legacy_guild_id is None:
legacy = self._store.get("history", [])
if isinstance(legacy, list):
raw_entries = legacy
self._legacy_guild_id = guild_id
self._store.set(str(guild_id), legacy)
data = self._store.read()
data.pop("history", None)
self._store.write(data)
raw_entries = self._guild_store(guild_id).get("entries", [])
raw_entries = raw_entries or []
entries: list[HistoryEntry] = []
seen: set[tuple[str, str | None]] = set()
@@ -53,4 +67,9 @@ class HistoryRepository:
return entries
def _persist(self, guild_id: int) -> None:
self._store.set(str(guild_id), [entry.to_dict() for entry in self._cache.get(guild_id, [])])
self._guild_store(guild_id).set(
"entries", [entry.to_dict() for entry in self._cache.get(guild_id, [])]
)
def _write_entries(self, guild_id: int, entries: list[dict]) -> None:
self._guild_store(guild_id).set("entries", entries[: self._limit])
+4
View File
@@ -9,6 +9,7 @@ from zyrarbot.audio.track_factory import TrackFactory
from zyrarbot.music.music_player import MusicPlayer
from zyrarbot.settings import Settings
from zyrarbot.storage.guild_config_repository import GuildConfigRepository
from zyrarbot.storage.history_repository import HistoryRepository
from zyrarbot.storage.uploads_repository import UploadsRepository
from zyrarbot.ui.bot.cogs.control_cog import ControlCog
from zyrarbot.ui.bot.cogs.playback_cog import PlaybackCog
@@ -32,6 +33,7 @@ class MusicBot(commands.Bot):
tracks: TrackFactory,
uploads: UploadsRepository,
config: GuildConfigRepository,
history: HistoryRepository,
):
intents = discord.Intents.default()
intents.message_content = True
@@ -42,6 +44,7 @@ class MusicBot(commands.Bot):
self.tracks = tracks
self.uploads = uploads
self.config = config
self.history = history
self.player: MusicPlayer | None = None
def _create_music_cogs(self) -> tuple[commands.Cog, ...]:
@@ -77,5 +80,6 @@ class MusicBot(commands.Bot):
first_guild_id = self.guilds[0].id
self.uploads.migrate_legacy(first_guild_id)
self.config.migrate_legacy(first_guild_id)
self.history.migrate_legacy(first_guild_id)
if self.user:
logger.info("Zalogowano jako %s (%s)", self.user.name, self.user.id)