[ddg] Split the module in two: ddg for search and urbandict for urbandictionnary

This commit is contained in:
nemunaire 2015-10-24 14:44:16 +02:00
parent aca073faff
commit 2b96c32063
5 changed files with 175 additions and 171 deletions

138
modules/ddg.py Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

37
modules/urbandict.py Normal file
View File

@ -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