Experimental Discord bot written in Python
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

storage.py 2.3KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import json
  2. from os.path import exists
  3. from discord import Guild
  4. from config import CONFIG
  5. class StateKey:
  6. WARNING_CHANNEL_ID = 'warning_channel_id'
  7. class Storage:
  8. """
  9. Static class for managing persisted bot state.
  10. """
  11. # discord.Guild.id -> dict
  12. __guild_id_to_state = {}
  13. @classmethod
  14. def state_for_guild(cls, guild: Guild) -> dict:
  15. """
  16. Returns the state for the given guild, loading from disk if necessary.
  17. Always returns a dict.
  18. """
  19. state: dict = cls.__guild_id_to_state.get(guild.id)
  20. if state is not None:
  21. # Already in memory
  22. return state
  23. # Load from disk if possible
  24. cls.__trace(f'No loaded state for guild {guild.id}. Attempting to load from disk.')
  25. state = cls.__load_guild_state(guild)
  26. cls.__guild_id_to_state[guild.id] = state
  27. return state
  28. @classmethod
  29. def save_guild_state(cls, guild: Guild) -> None:
  30. """
  31. Saves state for the given guild to disk, if any exists.
  32. """
  33. state: dict = cls.__guild_id_to_state.get(guild.id)
  34. if state is None:
  35. # Nothing to save
  36. return
  37. cls.__save_guild_state(guild, state)
  38. @classmethod
  39. def __save_guild_state(cls, guild: Guild, state: dict) -> None:
  40. """
  41. Saves state for a guild to a JSON file on disk.
  42. """
  43. path: str = cls.__guild_path(guild)
  44. cls.__trace('Saving state for guild {guild.id} to {path}')
  45. with open(path, 'w') as file:
  46. # Pretty printing to make more legible for debugging
  47. # Sorting keys to help with diffs
  48. json.dump(state, file, indent='\t', sort_keys=True)
  49. cls.__trace('State saved')
  50. @classmethod
  51. def __load_guild_state(cls, guild: Guild) -> dict:
  52. """
  53. Loads state for a guild from a JSON file on disk.
  54. """
  55. path: str = cls.__guild_path(guild)
  56. if not exists(path):
  57. cls.__trace(f'No state on disk for guild {guild.id}. Returning {{}}.')
  58. return {}
  59. cls.__trace(f'Loading state from disk for guild {guild.id}')
  60. with open(path, 'r') as file:
  61. state = json.load(file)
  62. cls.__trace('State loaded')
  63. return state
  64. @classmethod
  65. def __guild_path(cls, guild: Guild) -> str:
  66. """
  67. Returns the JSON file path where guild state should be written.
  68. """
  69. config_value: str = CONFIG['statePath']
  70. path: str = config_value if config_value.endswith('/') else f'{config_value}/'
  71. return f'{path}guild_{guild.id}.json'
  72. @classmethod
  73. def __trace(cls, message: str) -> None:
  74. print(f'{Storage.__name__}: {message}')