2015-10-24 12:44:16 +00:00
|
|
|
"""Search around DuckDuckGo search engine"""
|
|
|
|
|
|
|
|
# PYTHON STUFFS #######################################################
|
|
|
|
|
|
|
|
from urllib.parse import quote
|
|
|
|
|
2015-10-30 20:57:45 +00:00
|
|
|
from nemubot.exception import IMException
|
2015-10-24 12:44:16 +00:00
|
|
|
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:
|
2015-10-30 20:57:45 +00:00
|
|
|
raise IMException("An error occurs during search")
|
2015-10-24 12:44:16 +00:00
|
|
|
|
|
|
|
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"]:
|
2015-11-04 06:31:09 +00:00
|
|
|
return None
|
2015-10-24 12:44:16 +00:00
|
|
|
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 ####################################################
|
|
|
|
|
2015-11-02 19:19:12 +00:00
|
|
|
@hook.command("define")
|
2015-10-24 12:44:16 +00:00
|
|
|
def define(msg):
|
|
|
|
if not len(msg.args):
|
2015-10-30 20:57:45 +00:00
|
|
|
raise IMException("Indicate a term to define")
|
2015-10-24 12:44:16 +00:00
|
|
|
|
|
|
|
s = do_search(msg.args)
|
|
|
|
|
|
|
|
if not s.definition:
|
2015-10-30 20:57:45 +00:00
|
|
|
raise IMException("no definition found for '%s'." % " ".join(msg.args))
|
2015-10-24 12:44:16 +00:00
|
|
|
|
|
|
|
return Response(s.definition, channel=msg.channel)
|
|
|
|
|
2015-11-02 19:19:12 +00:00
|
|
|
@hook.command("search")
|
2015-10-24 12:44:16 +00:00
|
|
|
def search(msg):
|
|
|
|
if not len(msg.args):
|
2015-10-30 20:57:45 +00:00
|
|
|
raise IMException("Indicate a term to search")
|
2015-10-24 12:44:16 +00:00
|
|
|
|
|
|
|
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)
|
2015-10-30 20:10:06 +00:00
|
|
|
res.append_message([r for r in s.result])
|
2015-10-24 12:44:16 +00:00
|
|
|
|
|
|
|
for rt in s.relatedTopics:
|
|
|
|
res.append_message(rt)
|
|
|
|
|
|
|
|
res.append_message(s.definition)
|
|
|
|
|
|
|
|
return res
|