A Python robot that edits Wikipedia and interacts with people over IRC https://en.wikipedia.org/wiki/User:EarwigBot
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

152 líneas
5.3 KiB

  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright (C) 2009-2012 Ben Kurtovic <ben.kurtovic@verizon.net>
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a copy
  6. # of this software and associated documentation files (the "Software"), to deal
  7. # in the Software without restriction, including without limitation the rights
  8. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. # copies of the Software, and to permit persons to whom the Software is
  10. # furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. # SOFTWARE.
  22. import re
  23. from earwigbot import exceptions
  24. from earwigbot.commands import Command
  25. class Dictionary(Command):
  26. """Define words and stuff."""
  27. name = "dictionary"
  28. commands = ["dict", "dictionary", "define"]
  29. def process(self, data):
  30. if not data.args:
  31. self.reply(data, "what do you want me to define?")
  32. return
  33. term = " ".join(data.args)
  34. lang = self.bot.wiki.get_site().lang
  35. try:
  36. defined = self.define(term, lang)
  37. except exceptions.APIError:
  38. msg = "cannot find a {0}-language Wiktionary."
  39. self.reply(data, msg.format(lang))
  40. else:
  41. self.reply(data, defined.encode("utf8"))
  42. def define(self, term, lang):
  43. try:
  44. site = self.bot.wiki.get_site(project="wiktionary", lang=lang)
  45. except exceptions.SiteNotFoundError:
  46. site = self.bot.wiki.add_site(project="wiktionary", lang=lang)
  47. page = site.get_page(term)
  48. try:
  49. entry = page.get()
  50. except (exceptions.PageNotFoundError, exceptions.InvalidPageError):
  51. return "no definition found."
  52. languages = self.get_languages(entry)
  53. if not languages:
  54. return u"couldn't parse {0}!".format(page.url)
  55. result = []
  56. for lang, section in sorted(languages.items()):
  57. this = u"({0}) {1}".format(lang, self.get_definition(section))
  58. result.append(this)
  59. return u"; ".join(result)
  60. def get_languages(self, entry):
  61. regex = r"(?:\A|\n)==\s*([a-zA-Z0-9_ ]*?)\s*==(?:\Z|\n)"
  62. split = re.split(regex, entry)
  63. if len(split) % 2 == 0:
  64. return None
  65. split.pop(0)
  66. languages = {}
  67. for i in xrange(0, len(split), 2):
  68. languages[split[i]] = split[i + 1]
  69. return languages
  70. def get_definition(self, section):
  71. parts_of_speech = {
  72. "v.": "Verb",
  73. "n.": "Noun",
  74. "pron.": "Pronoun",
  75. "adj.": "Adjective",
  76. "adv.": "Adverb",
  77. "prep.": "Preposition",
  78. "conj.": "Conjunction",
  79. "inter.": "Interjection",
  80. "symbol": "Symbol",
  81. "suffix": "Suffix",
  82. "initialism": "Initialism",
  83. "phrase": "Phrase",
  84. "proverb": "Proverb",
  85. "prop. n.": "Proper noun",
  86. }
  87. defs = []
  88. for part, fullname in parts_of_speech.iteritems():
  89. if re.search("===\s*" + fullname + "\s*===", section):
  90. regex = "===\s*" + fullname + "\s*===(.*?)(?:(?:===)|\Z)"
  91. body = re.findall(regex, section, re.DOTALL)
  92. if body:
  93. definition = self.parse_body(body[0])
  94. if definition:
  95. msg = u"\x02{0}\x0F {1}"
  96. defs.append(msg.format(part, definition))
  97. return "; ".join(defs)
  98. def parse_body(self, body):
  99. senses = []
  100. for line in body.splitlines():
  101. line = line.strip()
  102. if re.match("#\s*[^:*]", line):
  103. line = re.sub("\[\[(.*?)\|(.*?)\]\]", r"\2", line)
  104. line = self.strip_templates(line)
  105. line = line[1:].replace("'''", "").replace("''", "")
  106. line = line.replace("[[", "").replace("]]", "")
  107. senses.append(line.strip())
  108. if not senses:
  109. return None
  110. if len(senses) == 1:
  111. return senses[0]
  112. result = [] # Number the senses incrementally
  113. for i, sense in enumerate(senses):
  114. result.append(u"{0}. {1}".format(i + 1, sense))
  115. return " ".join(result)
  116. def strip_templates(self, line):
  117. line = list(line)
  118. stripped = ""
  119. depth = 0
  120. while line:
  121. this = line.pop(0)
  122. if line:
  123. next = line[0]
  124. else:
  125. next = ""
  126. if this == "{" and next == "{":
  127. line.pop(0)
  128. depth += 1
  129. elif this == "}" and next == "}":
  130. line.pop(0)
  131. depth -= 1
  132. elif depth == 0:
  133. stripped += this
  134. return stripped