Experimental Discord bot written in Python
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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}')