class Duck
Constants
- DDG_HTML_URL
- MIN_SNIPPET_LENGTH
Public Class Methods
Source
# File plugins/duck.rb, line 38 def self.clean_url(href) return "" if href.nil? || href.to_s.strip.empty? href = href.to_s.strip href = "https:#{href}" if href.start_with?("//") if href.include?("uddg=") decoded = URI.decode_www_form(URI.parse(href).query.to_s).to_h["uddg"] return decoded if decoded && !decoded.empty? end href rescue StandardError href.to_s end
Source
# File plugins/duck.rb, line 21 def self.format_result(snippet, url) snippet = snippet.to_s.strip url = url.to_s.strip return "No results found" if snippet.empty? && url.empty? return "#{snippet} (#{url})" unless url.empty? snippet end
Source
# File plugins/duck.rb, line 82 def self.parse_results(html) doc = Nokogiri::HTML(html.to_s) parse_zci(doc) || parse_web_results(doc) end
Source
# File plugins/duck.rb, line 67 def self.parse_web_results(doc) doc.css(".result").each do |result| link_el = result.at_css(".result__a") next unless link_el snippet = result.at_css(".result__snippet")&.text&.strip next if snippet.nil? || snippet.length < MIN_SNIPPET_LENGTH url = clean_url(link_el["href"]) return format_result(trim_snippet(snippet), url) end nil end
Source
# File plugins/duck.rb, line 54 def self.parse_zci(doc) abstract = doc.at_css("#zero_click_abstract") return nil unless abstract node = abstract.dup node.search("a").remove snippet = trim_snippet(node.text) return nil if snippet.length < MIN_SNIPPET_LENGTH link = doc.at_css(".zci__heading a")&.[]("href") format_result(snippet, link.to_s) end
Source
# File plugins/duck.rb, line 87 def self.search(query, fetch:) html = fetch.call(query) parse_results(html) || "No results found" rescue StandardError "No results found" end
Source
# File plugins/duck.rb, line 30 def self.trim_snippet(text, max_sentences: 2) text = text.to_s.strip.gsub(/\s+/, " ") return "" if text.empty? sentences = text.split(/(?<=[.!?])\s+/) sentences.first(max_sentences).join(" ").strip end
Public Instance Methods
Source
# File plugins/duck.rb, line 103 def execute(m, query) safe_reply(m, search(query)) end
Source
# File plugins/duck.rb, line 98 def fetch_html(query) url = "#{DDG_HTML_URL}?q=#{CGI.escape(query)}" URI.parse(url).open("User-Agent" => "Mozilla/5.0").read end
Source
# File plugins/duck.rb, line 94 def search(query, fetch: method(:fetch_html)) self.class.search(query, fetch: fetch) end