From 2f7592091be3e0b104f159b6e6e39b8acaa6176d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9munaire?= Date: Fri, 31 Aug 2012 02:58:28 +0200 Subject: [PATCH] Convert DDG/WFA/Wiki module to nemubot 3.2 --- modules/ddg/DDGSearch.py | 125 ++++++++++++++++++---------------- modules/ddg/WFASearch.py | 117 +++++++++++++++----------------- modules/ddg/Wikipedia.py | 42 ++++++------ modules/ddg/__init__.py | 141 ++++++++++++++++++++++++++------------- 4 files changed, 236 insertions(+), 189 deletions(-) diff --git a/modules/ddg/DDGSearch.py b/modules/ddg/DDGSearch.py index 04e3b56..1ff3358 100644 --- a/modules/ddg/DDGSearch.py +++ b/modules/ddg/DDGSearch.py @@ -4,72 +4,83 @@ import http.client import re from urllib.parse import quote -import module_states_file as xmlparser +import xmlparser class DDGSearch: - def __init__(self, terms): - self.terms = terms - self.curRT = -1 - (res, page) = getPage(terms) - if res == http.client.OK or res == http.client.SEE_OTHER: - self.ddgres = xmlparser.parse_string(page) - else: - self.ddgres = None + def __init__(self, terms): + self.terms = terms + (res, page) = getPage(terms) + if res == http.client.OK or res == http.client.SEE_OTHER: + self.ddgres = xmlparser.parse_string(page) + else: + self.ddgres = None - @property - def type(self): - if self.ddgres and self.ddgres.hasNode("Type"): - return self.ddgres.getFirstNode("Type").getContent() - else: - return "" + @property + def type(self): + if self.ddgres and self.ddgres.hasNode("Type"): + return self.ddgres.getFirstNode("Type").getContent() + else: + return "" - @property - def definition(self): - if self.ddgres.hasNode("Definition"): - return self.ddgres.getFirstNode("Definition").getContent() - else: - return "Sorry, no definition found for %s" % self.terms + @property + def definition(self): + if self.ddgres.hasNode("Definition"): + return self.ddgres.getFirstNode("Definition").getContent() + else: + return "Sorry, no definition found for %s" % self.terms - @property - def nextRes(self): - if (self.type == "D" or self.type == "C") and len(self.ddgres.getFirstNode("RelatedTopics").getNodes("RelatedTopic")) > self.curRT + 1: - self.curRT += 1 - node = self.ddgres.getFirstNode("RelatedTopics").getNodes("RelatedTopic")[self.curRT] - return node.getFirstNode("Text").getContent() - elif self.ddgres.hasNode("Redirect") and self.ddgres.getFirstNode("Redirect").getContent() != "": - return self.ddgres.getFirstNode("Redirect").getContent() - elif self.ddgres.hasNode("Results") and self.ddgres.getFirstNode("Results").hasNode("Result") and self.curRT < 0: - self.curRT = 0 - node = self.ddgres.getFirstNode("Results").getFirstNode("Result") - return node.getFirstNode("Text").getContent() + ": " + node.getFirstNode("FirstURL").getContent() - elif self.ddgres.hasNode("Answer") and self.curRT < 0: - self.curRT = 0 - return striphtml(self.ddgres.getFirstNode("Answer").getContent()) - elif self.ddgres.hasNode("Abstract") and len (self.ddgres.getNode("Abstract").getContent()) > 0: - if self.curRT < 0: - self.curRT = 0 - return self.ddgres.getNode("Abstract").getContent() + " <" + self.ddgres.getNode("AbstractURL").getContent() + ">" - elif len(self.ddgres.getFirstNode("RelatedTopics").getNodes("RelatedTopic")) > self.curRT: - node = self.ddgres.getFirstNode("RelatedTopics").getNodes("RelatedTopic")[self.curRT] - self.curRT += 1 - return node.getFirstNode("Text").getContent() - return "No more results" + @property + def relatedTopics(self): + try: + for rt in self.ddgres.getFirstNode("RelatedTopics").getNodes("RelatedTopic"): + yield rt.getFirstNode("Text").getContent() + except: + pass + + @property + def redirect(self): + try: + return self.ddgres.getFirstNode("Redirect").getContent() + except: + return None + + @property + def result(self): + try: + node = self.ddgres.getFirstNode("Results").getFirstNode("Result") + return node.getFirstNode("Text").getContent() + ": " + node.getFirstNode("FirstURL").getContent() + except: + return None + + @property + def answer(self): + try: + return striphtml(self.ddgres.getFirstNode("Answer").getContent()) + except: + return None + + @property + def abstract(self): + try: + return self.ddgres.getNode("Abstract").getContent() + " <" + self.ddgres.getNode("AbstractURL").getContent() + ">" + except: + return None def striphtml(data): - p = re.compile(r'<.*?>') - return p.sub('', data).replace("(", "/(").replace(")", ")/").replace(""", "\"") + p = re.compile(r'<.*?>') + return p.sub('', data).replace("(", "/(").replace(")", ")/").replace(""", "\"") def getPage(terms): - conn = http.client.HTTPConnection("api.duckduckgo.com", timeout=5) - try: - conn.request("GET", "/?q=%s&format=xml" % quote(terms)) - except socket.gaierror: - print ("impossible de récupérer la page %s."%(p)) - return (http.client.INTERNAL_SERVER_ERROR, None) + conn = http.client.HTTPConnection("api.duckduckgo.com", timeout=5) + try: + conn.request("GET", "/?q=%s&format=xml" % quote(terms)) + except socket.gaierror: + print ("impossible de récupérer la page %s."%(p)) + return (http.client.INTERNAL_SERVER_ERROR, None) - res = conn.getresponse() - data = res.read() + res = conn.getresponse() + data = res.read() - conn.close() - return (res.status, data) + conn.close() + return (res.status, data) diff --git a/modules/ddg/WFASearch.py b/modules/ddg/WFASearch.py index 458c947..c2efca7 100644 --- a/modules/ddg/WFASearch.py +++ b/modules/ddg/WFASearch.py @@ -5,76 +5,63 @@ import re import socket from urllib.parse import quote -import module_states_file as xmlparser +import xmlparser class WFASearch: - def __init__(self, terms): - self.terms = terms - self.curPod = 1 - self.curSubPod = 0 - (res, page) = getPage(terms) - if res == http.client.OK: - self.wfares = xmlparser.parse_string(page) - else: - self.wfares = None + def __init__(self, terms): + self.terms = terms + (res, page) = getPage(terms) + if res == http.client.OK: + self.wfares = xmlparser.parse_string(page) + else: + self.wfares = None - @property - def success(self): - try: - return self.wfares["success"] == "true" - except: - return False + @property + def success(self): + try: + return self.wfares["success"] == "true" + except: + return False - @property - def error(self): - if self.wfares["error"] == "true": - return "An error occurs during computation: " + self.wfares.getNode("error").getNode("msg").getContent() - elif self.wfares.hasNode("didyoumeans"): - start = "Did you mean: " - tag = "didyoumean" - end = "?" - elif self.wfares.hasNode("tips"): - start = "Tips: " - tag = "tip" - end = "" - elif self.wfares.hasNode("relatedexamples"): - start = "Related examples: " - tag = "relatedexample" - end = "" - elif self.wfares.hasNode("futuretopic"): - return self.wfares.getNode("futuretopic")["msg"] - else: - return "An error occurs during computation" - proposal = list() - for dym in self.wfares.getNode(tag + "s").getNodes(tag): - if tag == "tip": - proposal.append(dym["text"]) - elif tag == "relatedexample": - proposal.append(dym["desc"]) - else: - proposal.append(dym.getContent()) - return start + ', '.join(proposal) + end + @property + def error(self): + if self.wfares["error"] == "true": + return "An error occurs during computation: " + self.wfares.getNode("error").getNode("msg").getContent() + elif self.wfares.hasNode("didyoumeans"): + start = "Did you mean: " + tag = "didyoumean" + end = "?" + elif self.wfares.hasNode("tips"): + start = "Tips: " + tag = "tip" + end = "" + elif self.wfares.hasNode("relatedexamples"): + start = "Related examples: " + tag = "relatedexample" + end = "" + elif self.wfares.hasNode("futuretopic"): + return self.wfares.getNode("futuretopic")["msg"] + else: + return "An error occurs during computation" + proposal = list() + for dym in self.wfares.getNode(tag + "s").getNodes(tag): + if tag == "tip": + proposal.append(dym["text"]) + elif tag == "relatedexample": + proposal.append(dym["desc"]) + else: + proposal.append(dym.getContent()) + return start + ', '.join(proposal) + end - @property - def nextRes(self): - try: - if len(self.wfares.getNodes("pod")) > self.curPod: - txt = "" - while txt == "" or subnode.getFirstNode("plaintext").getContent() == "": - node = self.wfares.getNodes("pod")[self.curPod] - subnode = node.getNodes("subpod")[self.curSubPod] - - self.curSubPod += 1 - if len(node.getNodes("subpod")) <= self.curSubPod: - self.curPod += 1 - self.curSubPod = 0 - - txt = node["title"] + " " + subnode["title"] + ": " + subnode.getFirstNode("plaintext").getContent() - return txt - except IndexError: - pass - self.curPod = 1 - return "No more results" + @property + def nextRes(self): + try: + for node in self.wfares.getNodes("pod"): + for subnode in node.getNodes("subpod"): + if subnode.getFirstNode("plaintext").getContent() != "": + yield node["title"] + " " + subnode["title"] + ": " + subnode.getFirstNode("plaintext").getContent() + except IndexError: + pass def getPage(terms): diff --git a/modules/ddg/Wikipedia.py b/modules/ddg/Wikipedia.py index 76ebfe3..f7cb9a1 100644 --- a/modules/ddg/Wikipedia.py +++ b/modules/ddg/Wikipedia.py @@ -4,31 +4,29 @@ import http.client import re from urllib.parse import quote -import module_states_file as xmlparser +import xmlparser class Wikipedia: - def __init__(self, terms, lang="fr"): - self.terms = terms - self.lang = lang - self.curRT = -1 - (res, page) = getPage(terms, self.lang) - if res == http.client.OK or res == http.client.SEE_OTHER: - self.wres = xmlparser.parse_string(page) - else: - self.wres = None + def __init__(self, terms, lang="fr"): + self.terms = terms + self.lang = lang + self.curRT = -1 + (res, page) = getPage(terms, self.lang) + if res == http.client.OK or res == http.client.SEE_OTHER: + self.wres = xmlparser.parse_string(page) + else: + self.wres = None - @property - def nextRes(self): - if self.wres is not None and self.wres.hasNode("query"): - if self.wres.getFirstNode("query").hasNode("pages"): - if self.wres.getFirstNode("query").getFirstNode("pages").hasNode("page"): - if self.wres.getFirstNode("query").getFirstNode("pages").getFirstNode("page").hasNode("revisions"): - self.curRT += 1 - content = self.wres.getFirstNode("query").getFirstNode("pages").getFirstNode("page").getFirstNode("revisions").getFirstNode("rev").getContent().split("\n") - while self.curRT < len(content) and striplink(content[self.curRT]).strip() == "": - self.curRT += 1 - return striplink(content[self.curRT]) - return "No more results" + @property + def nextRes(self): + if self.wres is not None and self.wres.hasNode("query"): + if self.wres.getFirstNode("query").hasNode("pages"): + if self.wres.getFirstNode("query").getFirstNode("pages").hasNode("page"): + if self.wres.getFirstNode("query").getFirstNode("pages").getFirstNode("page").hasNode("revisions"): + for cnt in self.wres.getFirstNode("query").getFirstNode("pages").getFirstNode("page").getFirstNode("revisions").getFirstNode("rev").getContent().split("\n"): + c = striplink(cnt).strip() + if c != "": + yield c def striplink(data): diff --git a/modules/ddg/__init__.py b/modules/ddg/__init__.py index 2a5385f..ba1e967 100644 --- a/modules/ddg/__init__.py +++ b/modules/ddg/__init__.py @@ -2,64 +2,115 @@ import imp -nemubotversion = 3.0 +nemubotversion = 3.2 from . import DDGSearch from . import WFASearch from . import Wikipedia -lastSearch = dict() +def load(context): + global CONF + WFASearch.CONF = CONF -def load(): - global CONF - WFASearch.CONF = CONF + from hooks import Hook + context.hooks.add_hook(context.hooks.cmd_hook, Hook(define, "d")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(define, "def")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(define, "defini")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(define, "definit")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(define, "define")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(define, "definition")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(search, "search")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(search, "ddg")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(search, "g")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(calculate, "wa")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(calculate, "wfa")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(calculate, "calc")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(wiki, "w")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(wiki, "wf")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(wiki, "wfr")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(wiki, "we")) + context.hooks.add_hook(context.hooks.cmd_hook, Hook(wiki, "wen")) def reload(): - imp.reload(DDGSearch) - imp.reload(WFASearch) - imp.reload(Wikipedia) + imp.reload(DDGSearch) + imp.reload(WFASearch) + imp.reload(Wikipedia) -def parseanswer(msg): - global lastSearch - req = None - if msg.cmd[0] == "def" or msg.cmd[0] == "d" or msg.cmd[0] == "define" or msg.cmd[0] == "defini" or msg.cmd[0] == "definit" or msg.cmd[0] == "definition": - req = "def" - elif msg.cmd[0] == "g" or msg.cmd[0] == "ddg" or msg.cmd[0] == "d": - req = "link" - elif msg.cmd[0] == "w" or msg.cmd[0] == "wf" or msg.cmd[0] == "wfr": - req = "fr" - elif msg.cmd[0] == "we" or msg.cmd[0] == "wen": - req = "en" - elif msg.cmd[0] == "wfa" or msg.cmd[0] == "calc" or msg.cmd[0] == "wa": - req = "wfa" - if msg.cmd[0] == "more" or msg.cmd[0] == "plus": - if msg.channel in lastSearch and lastSearch[msg.channel] is not None: - msg.send_chn(lastSearch[msg.channel].nextRes) +def define(msg): + if len(msg.cmd) <= 1: + return Response(msg.sender, + "Indicate a term to define", + msg.channel, nick=msg.nick) + + s = DDGSearch.DDGSearch(' '.join(msg.cmd[1:])) + + res = Response(msg.sender, channel=msg.channel) + + res.append_message(s.definition) + + return res + + +def search(msg): + if len(msg.cmd) <= 1: + return Response(msg.sender, + "Indicate a term to search", + msg.channel, nick=msg.nick) + + s = DDGSearch.DDGSearch(' '.join(msg.cmd[1:])) + + res = Response(msg.sender, channel=msg.channel, nomore="No more results", + count=" (%d more results)") + + res.append_message(s.redirect) + res.append_message(s.abstract) + res.append_message(s.result) + res.append_message(s.answer) + + for rt in s.relatedTopics: + res.append_message(rt) + + return res + + +def calculate(msg): + if len(msg.cmd) <= 1: + return Response(msg.sender, + "Indicate a calcul to compute", + msg.channel, nick=msg.nick) + + s = WFASearch.WFASearch(' '.join(msg.cmd[1:])) + + if s.success: + res = Response(msg.sender, channel=msg.channel, nomore="No more results") + for result in s.nextRes: + res.append_message(result) + res.messages.pop(0) + return res else: - msg.send_chn("There is no ongoing research.") - elif req is not None: - if len(msg.cmd) > 1: - if req == "wfa": - s = WFASearch.WFASearch(' '.join(msg.cmd[1:])) - #print (s.wfares) - if not s.success: - msg.send_chn(s.error) - return True - elif req == "link" or req == "def": - s = DDGSearch.DDGSearch(' '.join(msg.cmd[1:])) - else: - s = Wikipedia.Wikipedia(' '.join(msg.cmd[1:]), req) + return Response(msg.sender, s.error, msg.channel) - if req == "def": - msg.send_chn(s.definition) - else: - msg.send_chn(s.nextRes) - lastSearch[msg.channel] = s + +def wiki(msg): + if len(msg.cmd) <= 1: + return Response(msg.sender, + "Indicate a term to search", + msg.channel, nick=msg.nick) + if msg.cmd[0] == "w" or msg.cmd[0] == "wf" or msg.cmd[0] == "wfr": + lang = "fr" else: - msg.send_chn("What are you looking for?") - return True + lang = "en" - return False + s = Wikipedia.Wikipedia(msg.cmd[1], lang) + res = Response(msg.sender, channel=msg.channel, nomore="No more results") + for result in s.nextRes: + res.append_message(result) + if len(res.messages) > 0: + return res + else: + return Response(msg.sender, + "No information about " + msg.cmd[1], + msg.channel)