138 lines
4.3 KiB
Python
138 lines
4.3 KiB
Python
''' Data used throughout the application '''
|
|
|
|
'''
|
|
TODO: Save one properties pickle file per-guild, instead of saving all in one file at once
|
|
'''
|
|
|
|
import logging
|
|
import os
|
|
import pickle
|
|
|
|
from enum import Enum
|
|
from typing import Final
|
|
|
|
from subsonic import Song
|
|
from player import Player
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
# Guild data
|
|
_default_data: dict[str, any] = {
|
|
"player": None,
|
|
}
|
|
|
|
class GuildData():
|
|
''' Class that holds all Discodrome data specific to a guild (not saved to disk) '''
|
|
def __init__(self) -> None:
|
|
self._data = _default_data
|
|
self.player = Player()
|
|
if self.player.queue is None:
|
|
self.player.queue = []
|
|
|
|
@property
|
|
def player(self) -> Player:
|
|
'''The guild's player.'''
|
|
return self._data["player"]
|
|
|
|
@player.setter
|
|
def player(self, value: Player) -> None:
|
|
self._data["player"] = value
|
|
|
|
_guild_data_instances: dict[int, GuildData] = {} # Dictionary to store temporary data for each guild instance
|
|
|
|
def guild_data(guild_id: int) -> GuildData:
|
|
''' Returns the temporary data for the chosen guild '''
|
|
|
|
# Return property if guild exists
|
|
if guild_id in _guild_data_instances:
|
|
return _guild_data_instances[guild_id]
|
|
|
|
# Create & store new data object if guild does not already exist
|
|
data = GuildData()
|
|
|
|
# Load queue from disk if it exists
|
|
if guild_properties(guild_id).queue is not None:
|
|
data.player.queue = guild_properties(guild_id).queue
|
|
|
|
_guild_data_instances[guild_id] = data
|
|
return _guild_data_instances[guild_id]
|
|
|
|
|
|
# Guild properties
|
|
class AutoplayMode(Enum):
|
|
''' Enum representing an autoplay mode '''
|
|
NONE : Final[int] = 0
|
|
RANDOM : Final[int] = 1
|
|
SIMILAR : Final[int] = 2
|
|
|
|
_default_properties: dict[str, any] = {
|
|
"queue": None,
|
|
"autoplay-mode": AutoplayMode.NONE,
|
|
}
|
|
|
|
|
|
class GuildProperties():
|
|
''' Class that holds all Discodrome properties specific to a guild (saved to disk) '''
|
|
def __init__(self) -> None:
|
|
self._properties = _default_properties
|
|
|
|
@property
|
|
def autoplay_mode(self) -> AutoplayMode:
|
|
'''The autoplay mode in use by this guild'''
|
|
return self._properties["autoplay-mode"]
|
|
|
|
@autoplay_mode.setter
|
|
def autoplay_mode(self, value: AutoplayMode) -> None:
|
|
self._properties["autoplay-mode"] = value
|
|
|
|
@property
|
|
def queue(self) -> list[Song]:
|
|
return self._properties["queue"]
|
|
|
|
@queue.setter
|
|
def queue(self, value: list[Song]) -> None:
|
|
self._properties["queue"] = value
|
|
|
|
|
|
_guild_property_instances: dict[int, GuildProperties] = {} # Dictionary to store properties for each guild instance
|
|
|
|
def guild_properties(guild_id: int) -> GuildProperties:
|
|
''' Returns the properties for the chosen guild '''
|
|
|
|
# Return property if guild exists
|
|
if guild_id in _guild_property_instances:
|
|
return _guild_property_instances[guild_id]
|
|
|
|
# Create & store new properties object if guild does not already exist
|
|
properties = GuildProperties()
|
|
_guild_property_instances[guild_id] = properties
|
|
return _guild_property_instances[guild_id]
|
|
|
|
def save_guild_properties_to_disk() -> None:
|
|
''' Saves guild properties to disk. '''
|
|
|
|
# Copy the queues from each guild data into each guild property
|
|
for guild_id, properties in _guild_property_instances.items():
|
|
properties.queue = guild_data(guild_id).player.queue
|
|
|
|
with open("guild_properties.pickle", "wb") as file:
|
|
try:
|
|
pickle.dump(_guild_property_instances, file, protocol=pickle.HIGHEST_PROTOCOL)
|
|
logger.info("Guild properties saved successfully.")
|
|
except pickle.PicklingError as err:
|
|
logger.error("Failed to save guild properties to disk.", exc_info=err)
|
|
|
|
def load_guild_properties_from_disk() -> None:
|
|
''' Loads guild properties that have been saved to disk. '''
|
|
|
|
if not os.path.exists("guild_properties.pickle"):
|
|
logger.info("Unable to load guild properties from disk. File was not found.")
|
|
return
|
|
|
|
with open("guild_properties.pickle", "rb") as file:
|
|
try:
|
|
_guild_property_instances.update(pickle.load(file))
|
|
logger.info("Guild properties loaded successfully.")
|
|
except pickle.UnpicklingError as err:
|
|
logger.error("Failed to load guild properties from disk.", exc_info=err)
|