A Python robot that edits Wikipedia and interacts with people over IRC https://en.wikipedia.org/wiki/User:EarwigBot
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

96 righe
3.3 KiB

  1. # -*- coding: utf-8 -*-
  2. """
  3. EarwigBot's XML Config File Parser
  4. This handles all tasks involving reading and writing to our config file,
  5. including encrypting and decrypting passwords and making a new config file from
  6. scratch at the inital bot run.
  7. """
  8. from os import makedirs, path
  9. from xml.dom import minidom
  10. from xml.parsers.expat import ExpatError
  11. script_dir = path.dirname(path.abspath(__file__))
  12. root_dir = path.split(script_dir)[0]
  13. config_path = path.join(root_dir, "config.xml")
  14. _config = None
  15. class ConfigParseException(Exception):
  16. """Base exception for when we could not parse the config file."""
  17. class TypeMismatchException(ConfigParseException):
  18. """A field does not fit to its expected type; e.g., an aribrary string
  19. where we expected a boolean or integer."""
  20. def _load_config():
  21. """Load data from our XML config file (config.xml) into a DOM object."""
  22. global _config
  23. _config = minidom.parse(config_path)
  24. def verify_config():
  25. """Check to see if we have a valid config file, and if not, notify the
  26. user. If there is no config file at all, offer to make one; otherwise,
  27. exit."""
  28. if path.exists(config_path):
  29. try:
  30. _load_config()
  31. except ExpatError as error:
  32. print "Could not parse config file {0}:\n{1}".format(config_path,
  33. error)
  34. exit()
  35. else:
  36. return are_passwords_encrypted()
  37. else:
  38. print "You haven't configured the bot yet!"
  39. choice = raw_input("Would you like to do this now? [y/n] ")
  40. if choice.lower().startswith("y"):
  41. return make_new_config()
  42. else:
  43. exit()
  44. def make_new_config():
  45. """Make a new XML config file based on the user's input."""
  46. makedirs(config_dir)
  47. encrypt = raw_input("Would you like to encrypt passwords stored in " +
  48. "config.xml? [y/n] ")
  49. if encrypt.lower().startswith("y"):
  50. is_encrypted = True
  51. else:
  52. is_encrypted = False
  53. return is_encrypted
  54. def are_passwords_encrypted():
  55. """Determine if the passwords in our config file are encrypted, returning
  56. either True or False."""
  57. element = _config.getElementsByTagName("config")[0]
  58. return attribute_to_bool(element, "encrypt-passwords", default=False)
  59. def attribute_to_bool(element, attribute, default=None):
  60. """Return True if the value of element's attribute is 'true', '1', or 'on';
  61. return False if it is 'false', '0', or 'off' (regardless of
  62. capitalization); return default if it is empty; raise TypeMismatchException
  63. if it does match any of those."""
  64. value = element.getAttribute(attribute).lower()
  65. if value in ["true", "1", "on"]:
  66. return True
  67. elif value in ["false", "0", "off"]:
  68. return False
  69. elif value == '':
  70. return default
  71. else:
  72. e = ("Expected a bool in attribute '{0}' of element '{1}', but " +
  73. "got '{2}'.").format(attribute, element.tagName, value)
  74. raise TypeMismatchException(e)
  75. def parse_config(key):
  76. """Parse config data from a DOM object. The key is used to unencrypt
  77. passwords stored in the config file."""
  78. _load_config() # we might be re-loading unnecessarily here, but no harm in
  79. # that!
  80. data = _config.getElementsByTagName("config")[0]