PageRenderTime 51ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/search.py

https://gitlab.com/garheade/garbot
Python | 222 lines | 207 code | 5 blank | 10 comment | 10 complexity | dcebe55f53d8b857ad055d9f1e4580c2 MD5 | raw file
  1. """
  2. search.py - Willie Web Search Module
  3. Copyright 2008-9, Sean B. Palmer, inamidst.com
  4. Copyright 2012, Edward Powell, embolalia.net
  5. Licensed under the Eiffel Forum License 2.
  6. http://willie.dftba.net
  7. """
  8. import re
  9. import willie.web as web
  10. import json
  11. def google_ajax(query):
  12. """Search using AjaxSearch, and return its JSON."""
  13. if isinstance(query, unicode):
  14. query = query.encode('utf-8')
  15. uri = 'http://ajax.googleapis.com/ajax/services/search/web'
  16. args = '?v=1.0&safe=off&q=' + web.quote(query)
  17. bytes = web.get(uri + args)
  18. return json.loads(bytes)
  19. def google_search(query):
  20. results = google_ajax(query)
  21. try: return results['responseData']['results'][0]['unescapedUrl']
  22. except IndexError: return None
  23. except TypeError:
  24. return False
  25. def google_count(query):
  26. results = google_ajax(query)
  27. if not results.has_key('responseData'): return '0'
  28. if not results['responseData'].has_key('cursor'): return '0'
  29. if not results['responseData']['cursor'].has_key('estimatedResultCount'):
  30. return '0'
  31. return results['responseData']['cursor']['estimatedResultCount']
  32. def formatnumber(n):
  33. """Format a number with beautiful commas."""
  34. parts = list(str(n))
  35. for i in range((len(parts) - 3), 0, -3):
  36. parts.insert(i, ',')
  37. return ''.join(parts)
  38. def g(willie, trigger):
  39. """Queries Google for the specified input."""
  40. query = trigger.group(2)
  41. if not query:
  42. return willie.reply('.g what?')
  43. try:
  44. query = query.encode('utf-8')
  45. except:
  46. pass
  47. uri = google_search(query)
  48. if uri:
  49. willie.reply(uri)
  50. if not hasattr(willie.bot, 'last_seen_uri'):
  51. willie.bot.last_seen_uri = {}
  52. willie.bot.last_seen_uri[trigger.sender] = uri
  53. elif uri is False: willie.reply("Problem getting data from Google.")
  54. else: willie.reply("No results found for '%s'." % query)
  55. g.commands = ['g','google']
  56. g.priority = 'high'
  57. g.example = '.g swhack'
  58. def gc(willie, trigger):
  59. """Returns the number of Google results for the specified input."""
  60. query = trigger.group(2)
  61. if not query:
  62. return willie.reply('.gc what?')
  63. query = query.encode('utf-8')
  64. num = formatnumber(google_count(query))
  65. willie.say(query + ': ' + num)
  66. gc.commands = ['gc']
  67. gc.priority = 'high'
  68. gc.example = '.gc extrapolate'
  69. r_query = re.compile(
  70. r'\+?"[^"\\]*(?:\\.[^"\\]*)*"|\[[^]\\]*(?:\\.[^]\\]*)*\]|\S+'
  71. )
  72. def gcs(willie, trigger):
  73. """Compare the number of Google search results"""
  74. if not trigger.group(2):
  75. return willie.reply("Nothing to compare.")
  76. queries = r_query.findall(trigger.group(2))
  77. if len(queries) > 6:
  78. return willie.reply('Sorry, can only compare up to six things.')
  79. results = []
  80. for i, query in enumerate(queries):
  81. query = query.strip('[]')
  82. query = query.encode('utf-8')
  83. n = int((formatnumber(google_count(query)) or '0').replace(',', ''))
  84. results.append((n, query))
  85. if i >= 2: __import__('time').sleep(0.25)
  86. if i >= 4: __import__('time').sleep(0.25)
  87. results = [(term, n) for (n, term) in reversed(sorted(results))]
  88. reply = ', '.join('%s (%s)' % (t, formatnumber(n)) for (t, n) in results)
  89. willie.say(reply)
  90. gcs.commands = ['gcs', 'comp']
  91. gcs.example = '.gcs foo bar'
  92. r_bing = re.compile(r'<h3><a href="([^"]+)"')
  93. def bing_search(query, lang='en-GB'):
  94. query = web.quote(query)
  95. base = 'http://www.bing.com/search?mkt=%s&q=' % lang
  96. bytes = web.get(base + query)
  97. m = r_bing.search(bytes)
  98. if m: return m.group(1)
  99. def bing(willie, trigger):
  100. """Queries Bing for the specified input."""
  101. query = trigger.group(2)
  102. if query.startswith(':'):
  103. lang, query = query.split(' ', 1)
  104. lang = lang[1:]
  105. else: lang = 'en-GB'
  106. if not query:
  107. return willie.reply('.bing what?')
  108. query = query.encode('utf-8')
  109. uri = bing_search(query, lang)
  110. if uri:
  111. willie.reply(uri)
  112. if not hasattr(willie.bot, 'last_seen_uri'):
  113. willie.bot.last_seen_uri = {}
  114. willie.bot.last_seen_uri[trigger.sender] = uri
  115. else: willie.reply("No results found for '%s'." % query)
  116. bing.commands = ['bing']
  117. bing.example = '.bing swhack'
  118. r_duck = re.compile(r'nofollow" class="[^"]+" href="(.*?)">')
  119. def duck_search(query):
  120. query = query.replace('!', '')
  121. query = web.quote(query)
  122. uri = 'http://duckduckgo.com/html/?q=%s&kl=uk-en' % query
  123. bytes = web.get(uri)
  124. m = r_duck.search(bytes)
  125. if m: return web.decode(m.group(1))
  126. def duck_api(query):
  127. if '!bang' in query.lower():
  128. return 'https://duckduckgo.com/bang.html'
  129. uri = web.quote(query)
  130. uri = 'http://api.duckduckgo.com/?q=%s&format=json&no_html=1&no_redirect=1'%query
  131. results = json.loads(web.get(uri))
  132. print results
  133. if results['Redirect']:
  134. return results['Redirect']
  135. else:
  136. return None
  137. def duck(willie, trigger):
  138. """Queries Duck Duck Go for the specified input."""
  139. query = trigger.group(2)
  140. if not query:
  141. return willie.reply('.ddg what?')
  142. query = query.encode('utf-8')
  143. #If the API gives us something, say it and stop
  144. result = duck_api(query)
  145. if result:
  146. willie.reply(result)
  147. return
  148. #Otherwise, look it up on the HTMl version
  149. uri= duck_search(query)
  150. if uri:
  151. willie.reply(uri)
  152. if not hasattr(willie.bot, 'last_seen_uri'):
  153. willie.bot.last_seen_uri = {}
  154. willie.bot.last_seen_uri[trigger.sender] = uri
  155. else: willie.reply("No results found for '%s'." % query)
  156. duck.commands = ['duck', 'ddg']
  157. def search(willie, trigger):
  158. """Searches Google, Bing, and Duck Duck Go."""
  159. if not trigger.group(2):
  160. return willie.reply('.search for what?')
  161. query = trigger.group(2).encode('utf-8')
  162. gu = google_search(query) or '-'
  163. bu = bing_search(query) or '-'
  164. du = duck_search(query) or '-'
  165. if (gu == bu) and (bu == du):
  166. result = '%s (g, b, d)' % gu
  167. elif (gu == bu):
  168. result = '%s (g, b), %s (d)' % (gu, du)
  169. elif (bu == du):
  170. result = '%s (b, d), %s (g)' % (bu, gu)
  171. elif (gu == du):
  172. result = '%s (g, d), %s (b)' % (gu, bu)
  173. else:
  174. if len(gu) > 250: gu = '(extremely long link)'
  175. if len(bu) > 150: bu = '(extremely long link)'
  176. if len(du) > 150: du = '(extremely long link)'
  177. result = '%s (g), %s (b), %s (d)' % (gu, bu, du)
  178. willie.reply(result)
  179. search.commands = ['search']
  180. search.example = '.search nerdfighter'
  181. def suggest(willie, trigger):
  182. """Suggest terms starting with given input"""
  183. if not trigger.group(2):
  184. return willie.reply("No query term.")
  185. query = trigger.group(2).encode('utf-8')
  186. uri = 'http://websitedev.de/temp-bin/suggest.pl?q='
  187. answer = web.get(uri + web.quote(query).replace('+', '%2B'))
  188. if answer:
  189. willie.say(answer)
  190. else: willie.reply('Sorry, no result.')
  191. suggest.commands = ['suggest']
  192. if __name__ == '__main__':
  193. print __doc__.strip()