TODO don’t write unchanged config to disk
[six.git] / plugins / web.rb
blob2009e83a8c68a73b7ada4eed9f523b1bd101b6d1
2 # Web services plugin. Google and more.
5 require 'net/http'
6 require 'uri'
7 require 'htmlentities'
9 class Web < PluginBase
11   def initialize
12     @brief_help = 'Performs various web services.'
13     @requests = 0
14     @max_requests = 4
15     super
16   end
18   def cmd_title(irc, line)
19     if !line or line.empty?
20       irc.reply 'USAGE: title <http-url>'
21     elsif @requests >= @max_requests
22       irc.reply 'My limit of outstanding web queries has been reached. Try again in a moment.'
23     else
24       line = "http://#{line}" unless line =~ /^http:\/\//
25       if !(uri = URI.parse(line)) or !uri.kind_of?(URI::HTTP)
26         irc.reply 'Error parsing URL.  For now, only HTTP URLs are accepted.'
27       else
28         Thread.new do
29           begin
30             @requests += 1
31             Net::HTTP.start(uri.host, uri.port) do |http|
32               buffer = ''
33               path = uri.path
34               res = http.get(path.empty? ? '/' : path) do |s|
35                 buffer << s
36                 if buffer =~ /<title>(.+?)<\/title>/
37                   irc.reply $1.decode_entities
38                   Thread.exit
39                 end
40               end
41               irc.reply 'No title found in document.'
42             end
43           rescue SocketError
44             irc.reply 'Error connecting to host.'
45           ensure
46             @requests -= 1
47           end
48         end
49       end
50     end
51   end
53   def cmd_google(irc, line)
55     # Argument checks.
56     if !line or line.empty?
57       irc.reply 'USAGE: google <search string>'
58       return
59     end
60     if @requests >= @max_requests
61       irc.reply 'My limit of outstanding web queries has been reached. Try again in a moment.'
62       return
63     end
65     # Let's google!
66     Thread.new do
67       begin
68         @requests += 1
69         Net::HTTP.start('www.google.com') do |http|
70           search = line.gsub(/[^a-zA-Z0-9_\.\-]/) { |s| sprintf('%%%02x', s[0]) }
71           re = http.get("/search?ie=utf8&oe=utf8&q=#{search}", 
72             { 'User-Agent' => 'CyBrowser' })
73           if re.code == '200'
74             if re.body =~ /<a href="([^"]+)" class=l>(.+?)<\/a>/
75               link = $1.decode_entities
76               desc = $2.gsub('<b>', "\x02").gsub('</b>', "\x0f").decode_entities
77               irc.reply "#{link} (#{desc})"
78             elsif re.body =~ /did not match any documents/
79               irc.reply 'Nothing found.'
80             else
81               irc.reply "Error parsing Google output."
82             end
83           else
84             irc.reply "Google returned an error: #{re.code} #{re.message}"
85           end
86         end
87       ensure
88         @requests -= 1
89       end
90     end
92   end
93   help :google, 'Searches the web with Google, returning the first result.'
94   alias_method :cmd_lucky, :cmd_google
95   help :lucky, "Alias for 'google'. Type 'google?' for more information."
97 end