| @@ -20,13 +20,15 @@ | |||||
| # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
| # SOFTWARE. | # SOFTWARE. | ||||
| import re | |||||
| from earwigbot import exceptions | from earwigbot import exceptions | ||||
| from earwigbot.commands import Command | from earwigbot.commands import Command | ||||
| class Dictionary(Command): | class Dictionary(Command): | ||||
| """Define words and stuff.""" | """Define words and stuff.""" | ||||
| name = "dictionary" | name = "dictionary" | ||||
| commands = ["dict", "dictionary"] | |||||
| commands = ["dict", "dictionary", "define"] | |||||
| def process(self, data): | def process(self, data): | ||||
| if not data.args: | if not data.args: | ||||
| @@ -41,7 +43,7 @@ class Dictionary(Command): | |||||
| msg = "cannot find a {0}-language Wiktionary." | msg = "cannot find a {0}-language Wiktionary." | ||||
| self.reply(data, msg.format(lang)) | self.reply(data, msg.format(lang)) | ||||
| else: | else: | ||||
| self.reply(data, "{0}: {1}".format(term, defined.encode("utf8"))) | |||||
| self.reply(data, defined.encode("utf8")) | |||||
| def define(self, term, lang): | def define(self, term, lang): | ||||
| try: | try: | ||||
| @@ -55,4 +57,93 @@ class Dictionary(Command): | |||||
| except (exceptions.PageNotFoundError, exceptions.InvalidPageError): | except (exceptions.PageNotFoundError, exceptions.InvalidPageError): | ||||
| return "no definition found." | return "no definition found." | ||||
| return entry | |||||
| languages = self.get_languages(entry) | |||||
| if not languages: | |||||
| return u"couldn't parse {0}!".format(page.url) | |||||
| result = [] | |||||
| for lang, section in sorted(languages.items()): | |||||
| this = u"({0}) {1}".format(lang, self.get_definition(section)) | |||||
| result.append(this) | |||||
| return u"; ".join(result) | |||||
| def get_languages(self, entry): | |||||
| regex = r"(?:\A|\n)==\s*([a-zA-Z0-9_ ]*?)\s*==(?:\Z|\n)" | |||||
| split = re.split(regex, entry) | |||||
| if len(split) % 2 == 0: | |||||
| return None | |||||
| split.pop(0) | |||||
| languages = {} | |||||
| for i in xrange(0, len(split), 2): | |||||
| languages[split[i]] = split[i + 1] | |||||
| return languages | |||||
| def get_definition(self, section): | |||||
| parts_of_speech = { | |||||
| "v.": "Verb", | |||||
| "n.": "Noun", | |||||
| "pron.": "Pronoun", | |||||
| "adj.": "Adjective", | |||||
| "adv.": "Adverb", | |||||
| "prep.": "Preposition", | |||||
| "conj.": "Conjunction", | |||||
| "inter.": "Interjection", | |||||
| "symbol": "Symbol", | |||||
| "suffix": "Suffix", | |||||
| "initialism": "Initialism", | |||||
| "phrase": "Phrase", | |||||
| "proverb": "Proverb", | |||||
| } | |||||
| defs = [] | |||||
| for part, fullname in parts_of_speech.iteritems(): | |||||
| if re.search("===\s*" + fullname + "\s*===", section): | |||||
| regex = "===\s*" + fullname + "\s*===(.*?)(?:(?:===)|\Z)" | |||||
| body = re.findall(regex, section, re.DOTALL) | |||||
| if body: | |||||
| definition = self.parse_body(body[0]) | |||||
| if definition: | |||||
| defs.append("\x02{0}\x0F {1}".format(part, definition)) | |||||
| return "; ".join(defs) | |||||
| def parse_body(self, body): | |||||
| senses = [] | |||||
| for line in body.splitlines(): | |||||
| line = line.strip() | |||||
| if re.match("#\s*[^:*]", line): | |||||
| line = re.sub("\[\[(.*?)\|(.*?)\]\]", r"\2", line) | |||||
| line = self.strip_templates(line) | |||||
| line = line[1:].replace("'''", "").replace("''", "") | |||||
| line = line.replace("[[", "").replace("]]", "") | |||||
| senses.append(line.strip()) | |||||
| if not senses: | |||||
| return None | |||||
| if len(senses) == 1: | |||||
| return senses[0] | |||||
| result = [] # Number the senses incrementally | |||||
| for i, sense in enumerate(senses): | |||||
| result.append(u"{0}. {1}".format(i + 1, sense)) | |||||
| return " ".join(result) | |||||
| def strip_templates(self, line): | |||||
| line = list(line) | |||||
| stripped = "" | |||||
| depth = 0 | |||||
| while line: | |||||
| this = line.pop(0) | |||||
| if line: | |||||
| next = line[0] | |||||
| else: | |||||
| next = "" | |||||
| if this == "{" and next == "{": | |||||
| line.pop(0) | |||||
| depth += 1 | |||||
| elif this == "}" and next == "}": | |||||
| line.pop(0) | |||||
| depth -= 1 | |||||
| elif depth == 0: | |||||
| stripped += this | |||||
| return stripped | |||||