/scripts/duckduckgo.rb

https://github.com/Terminus-Project/Terminus-Bot · Ruby · 136 lines · 83 code · 28 blank · 25 comment · 10 complexity · b219e6e6d10b6e4fcd15fc0dd0c9ef91 MD5 · raw file

  1. #
  2. # Terminus-Bot: An IRC bot to solve all of the problems with IRC bots.
  3. #
  4. # Copyright (C) 2015 Kyle Johnson <kyle@vacantminded.com>
  5. # (http://terminus-bot.net/)
  6. #
  7. # Permission is hereby granted, free of charge, to any person obtaining a copy
  8. # of this software and associated documentation files (the "Software"), to deal
  9. # in the Software without restriction, including without limitation the rights
  10. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. # copies of the Software, and to permit persons to whom the Software is
  12. # furnished to do so, subject to the following conditions:
  13. #
  14. # The above copyright notice and this permission notice shall be included in all
  15. # copies or substantial portions of the Software.
  16. #
  17. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. # SOFTWARE.
  24. #
  25. need_module! 'http'
  26. register 'Perform searches on duckduckgo.com.'
  27. command 'ddg', 'Search the Internet using duckduckgo.com.' do
  28. argc! 1
  29. bang 'ducky', @params.first
  30. end
  31. command 'define', 'Define a term with duckduckgo.com.' do
  32. argc! 1
  33. define @params.first
  34. end
  35. command 'ask', 'Ask duckduckgo.com to complete a complex query.' do
  36. argc! 1
  37. answer @params.first
  38. end
  39. helpers do
  40. def bang type, query
  41. api_call "!#{type} #{query}" do |json|
  42. if json['Redirect'].start_with? 'https://duckduckgo.com/?q='
  43. raise 'No results.'
  44. end
  45. reply json['Redirect']
  46. end
  47. end
  48. def answer query
  49. api_call query do |json|
  50. if json['Answer'].empty?
  51. raise 'No results.'
  52. end
  53. reply json['Answer']
  54. end
  55. end
  56. def define query
  57. api_call query do |json|
  58. buf = []
  59. unless json['Abstract'].empty?
  60. if json['AbstractSource'].empty?
  61. source = ''
  62. else
  63. source = " (Source: #{json['AbstractSource']})"
  64. end
  65. buf << "\002(#{buf.length + 1})\002 #{html_decode json['Abstract']}#{source}"
  66. end
  67. unless json['Definition'].empty?
  68. if json['DefinitionSource'].empty?
  69. source = ''
  70. else
  71. source = " (Source: #{json['DefinitionSource']})"
  72. end
  73. buf << "\002(#{buf.length + 1})\002 #{html_decode json['Definition']}#{source}"
  74. end
  75. unless json['RelatedTopics'].empty?
  76. json['RelatedTopics'].each do |related_topic|
  77. if related_topic['Topics']
  78. related_topic['Topics'].each do |topic|
  79. break if buf.length == 3
  80. buf << "\002(#{buf.length + 1})\002 #{html_decode topic['Text']}"
  81. end
  82. else
  83. break if buf.length == 3
  84. buf << "\002(#{buf.length + 1})\002 #{html_decode related_topic['Text']}"
  85. end
  86. end
  87. end
  88. if buf.empty?
  89. raise 'No results.'
  90. end
  91. reply_without_prefix query => buf.join(' ').tr_s(' ', ' ')
  92. end
  93. end
  94. def api_call query
  95. opts = {
  96. 'q' => query,
  97. 'format' => 'json',
  98. 'no_redirect' => '1',
  99. 'no_html' => '1',
  100. 'kp' => '-1'
  101. }
  102. uri = URI('https://api.duckduckgo.com/')
  103. json_get uri, opts do |json|
  104. yield json
  105. end
  106. end
  107. end
  108. # vim: set tabstop=2 expandtab: