From 2b96c32063661e9b71212106b9609eb94b4c1435 Mon Sep 17 00:00:00 2001 From: nemunaire Date: Sat, 24 Oct 2015 14:44:16 +0200 Subject: [PATCH] [ddg] Split the module in two: ddg for search and urbandict for urbandictionnary --- modules/ddg.py | 138 ++++++++++++++++++++++++++++++++ modules/ddg/DDGSearch.py | 71 ---------------- modules/ddg/UrbanDictionnary.py | 30 ------- modules/ddg/__init__.py | 70 ---------------- modules/urbandict.py | 37 +++++++++ 5 files changed, 175 insertions(+), 171 deletions(-) create mode 100644 modules/ddg.py delete mode 100644 modules/ddg/DDGSearch.py delete mode 100644 modules/ddg/UrbanDictionnary.py delete mode 100644 modules/ddg/__init__.py create mode 100644 modules/urbandict.py diff --git a/modules/ddg.py b/modules/ddg.py new file mode 100644 index 0000000..e11d501 --- /dev/null +++ b/modules/ddg.py @@ -0,0 +1,138 @@ +"""Search around DuckDuckGo search engine""" + +# PYTHON STUFFS ####################################################### + +from urllib.parse import quote + +from nemubot.exception import IRCException +from nemubot.hooks import hook +from nemubot.tools import web + +from more import Response + +# MODULE CORE ######################################################### + +def do_search(terms): + if "!safeoff" in terms: + terms.remove("!safeoff") + safeoff = True + else: + safeoff = False + + sterm = " ".join(terms) + return DDGResult(sterm, web.getJSON( + "https://api.duckduckgo.com/?q=%s&format=json&no_redirect=1%s" % + (quote(sterm), "&kp=-1" if safeoff else ""))) + + +class DDGResult: + + def __init__(self, terms, res): + if res is None: + raise IRCException("An error occurs during search") + + self.terms = terms + self.ddgres = res + + + @property + def type(self): + if not self.ddgres or "Type" not in self.ddgres: + return "" + return self.ddgres["Type"] + + + @property + def definition(self): + if "Definition" not in self.ddgres or not self.ddgres["Definition"]: + return "Sorry, no definition found for %s." % self.terms + return self.ddgres["Definition"] + " <" + self.ddgres["DefinitionURL"] + "> from " + self.ddgres["DefinitionSource"] + + + @property + def relatedTopics(self): + if "RelatedTopics" in self.ddgres: + for rt in self.ddgres["RelatedTopics"]: + if "Text" in rt: + yield rt["Text"] + " <" + rt["FirstURL"] + ">" + elif "Topics" in rt: + yield rt["Name"] + ": " + "; ".join([srt["Text"] + " <" + srt["FirstURL"] + ">" for srt in rt["Topics"]]) + + + @property + def redirect(self): + if "Redirect" not in self.ddgres or not self.ddgres["Redirect"]: + return None + return self.ddgres["Redirect"] + + + @property + def entity(self): + if "Entity" not in self.ddgres or not self.ddgres["Entity"]: + return None + return self.ddgres["Entity"] + + + @property + def heading(self): + if "Heading" not in self.ddgres or not self.ddgres["Heading"]: + return " ".join(self.terms) + return self.ddgres["Heading"] + + + @property + def result(self): + if "Results" in self.ddgres: + for res in self.ddgres["Results"]: + yield res["Text"] + " <" + res["FirstURL"] + ">" + + + @property + def answer(self): + if "Answer" not in self.ddgres or not self.ddgres["Answer"]: + return None + return web.striphtml(self.ddgres["Answer"]) + + + @property + def abstract(self): + if "Abstract" not in self.ddgres or not self.ddgres["Abstract"]: + return None + return self.ddgres["AbstractText"] + " <" + self.ddgres["AbstractURL"] + "> from " + self.ddgres["AbstractSource"] + + +# MODULE INTERFACE #################################################### + +@hook("cmd_hook", "define") +def define(msg): + if not len(msg.args): + raise IRCException("Indicate a term to define") + + s = do_search(msg.args) + + if not s.definition: + raise IRCException("no definition found for '%s'." % " ".join(msg.args)) + + return Response(s.definition, channel=msg.channel) + +@hook("cmd_hook", "search") +def search(msg): + if not len(msg.args): + raise IRCException("Indicate a term to search") + + s = do_search(msg.args) + + res = Response(channel=msg.channel, nomore="No more results", + count=" (%d more results)") + + res.append_message(s.redirect) + res.append_message(s.answer) + res.append_message(s.abstract) + res.append_message([res for res in s.result]) + + for rt in s.relatedTopics: + res.append_message(rt) + + res.append_message(s.definition) + + return res diff --git a/modules/ddg/DDGSearch.py b/modules/ddg/DDGSearch.py deleted file mode 100644 index 174e4a5..0000000 --- a/modules/ddg/DDGSearch.py +++ /dev/null @@ -1,71 +0,0 @@ -# coding=utf-8 - -from urllib.parse import quote - -from nemubot.tools import web -from nemubot.tools.xmlparser import parse_string - - -class DDGSearch: - - def __init__(self, terms, safeoff=False): - self.terms = terms - - self.ddgres = web.getXML( - "https://api.duckduckgo.com/?q=%s&format=xml&no_redirect=1%s" % - (quote(terms), "&kp=-1" if safeoff else ""), - timeout=10) - - @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 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 web.striphtml(self.ddgres.getFirstNode("Answer").getContent()) - except: - return None - - @property - def abstract(self): - try: - if self.ddgres.getNode("Abstract").getContent() != "": - return self.ddgres.getNode("Abstract").getContent() + " <" + self.ddgres.getNode("AbstractURL").getContent() + ">" - else: - return None - except: - return None diff --git a/modules/ddg/UrbanDictionnary.py b/modules/ddg/UrbanDictionnary.py deleted file mode 100644 index 25faf39..0000000 --- a/modules/ddg/UrbanDictionnary.py +++ /dev/null @@ -1,30 +0,0 @@ -# coding=utf-8 - -from urllib.parse import quote - -from nemubot.tools import web - - -class UrbanDictionnary: - - def __init__(self, terms): - self.terms = terms - - self.udres = web.getJSON( - "http://api.urbandictionary.com/v0/define?term=%s" % quote(terms), - timeout=10) - - @property - def result_type(self): - if self.udres and "result_type" in self.udres: - return self.udres["result_type"] - else: - return "" - - @property - def definitions(self): - if self.udres and "list" in self.udres: - for d in self.udres["list"]: - yield d["definition"] + "\n" + d["example"] - else: - yield "Sorry, no definition found for %s" % self.terms diff --git a/modules/ddg/__init__.py b/modules/ddg/__init__.py deleted file mode 100644 index e7cfe89..0000000 --- a/modules/ddg/__init__.py +++ /dev/null @@ -1,70 +0,0 @@ -# coding=utf-8 - -"""Search around various search engine or knowledges database""" - -import imp - -from nemubot import context -from nemubot.exception import IRCException -from nemubot.hooks import hook - -nemubotversion = 3.4 - -from more import Response - -from . import DDGSearch -from . import UrbanDictionnary - -@hook("cmd_hook", "define") -def define(msg): - if not len(msg.args): - raise IRCException("Indicate a term to define") - - s = DDGSearch.DDGSearch(' '.join(msg.args)) - - return Response(s.definition, channel=msg.channel) - - -@hook("cmd_hook", "search") -def search(msg): - if not len(msg.args): - raise IRCException("Indicate a term to search") - - if "!safeoff" in msg.args: - msg.args.remove("!safeoff") - safeoff = True - else: - safeoff = False - - s = DDGSearch.DDGSearch(' '.join(msg.args), safeoff) - - res = Response(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) - - res.append_message(s.definition) - - return res - - -@hook("cmd_hook", "urbandictionnary") -def udsearch(msg): - if not len(msg.args): - raise IRCException("Indicate a term to search") - - s = UrbanDictionnary.UrbanDictionnary(' '.join(msg.args)) - - res = Response(channel=msg.channel, nomore="No more results", - count=" (%d more definitions)") - - for d in s.definitions: - res.append_message(d.replace("\n", " ")) - - return res diff --git a/modules/urbandict.py b/modules/urbandict.py new file mode 100644 index 0000000..e7474eb --- /dev/null +++ b/modules/urbandict.py @@ -0,0 +1,37 @@ +"""Search definition from urbandictionnary""" + +# PYTHON STUFFS ####################################################### + +from urllib.parse import quote + +from nemubot.exception import IRCException +from nemubot.hooks import hook +from nemubot.tools import web + +from more import Response + +# MODULE CORE ######################################################### + +def search(terms): + return web.getJSON( + "http://api.urbandictionary.com/v0/define?term=%s" + % quote(' '.join(terms))) + + +# MODULE INTERFACE #################################################### + +@hook("cmd_hook", "urbandictionnary") +def udsearch(msg): + if not len(msg.args): + raise IRCException("Indicate a term to search") + + s = search(msg.args) + + res = Response(channel=msg.channel, nomore="No more results", + count=" (%d more definitions)") + + for i in s["list"]: + res.append_message(i["definition"].replace("\n", " "), + title=i["word"]) + + return res