root/lang/ruby/chokan/trunk/plugins/uri_information.rb @ 283

Revision 283, 5.1 kB (checked in by cho45, 6 years ago)

lang/ruby/chokan,

Move from http://svn.lab.lowreal.net/lowreal/chokan/

Line 
1
2require 'chokan/plugin_base'
3require 'net/https'
4require 'net/ftp'
5require "cgi"
6require "image_size"
7require "digest/md5"
8
9class UriInformation < Chokan::PluginBase
10        MAX_REDIRECT = 10
11        HEADER       = {
12                "User-Agent" => "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0",
13                "Accept"     => "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
14        }
15
16        def initialize(config, chokan)
17                super
18                @uri = /(#{URI.regexp(@config['accept_scheme']).to_s})/
19        end
20
21        def on_privmsg(prefix, channel, message)
22                @channel = channel
23                message.scan(@uri) do |uri|
24                        begin
25                                uri = uri[0]
26                                uri = URI(uri)
27                                mes = chaining_try(uri)
28                                log mes
29                                notice(channel, mes) if mes
30                        rescue Exception => e
31                                notice(channel, e.inspect)
32                        end
33                end
34        end
35
36
37        def chaining_try(uri)
38                ret = nil
39                @config['modules'].each do |mod|
40                        begin
41                                if mod.kind_of? Hash
42                                        name = mod.keys[0]
43                                        config = mod[name]
44                                else
45                                        name = mod
46                                        config = {}
47                                end
48                                ret = send("handler_#{name}", config, uri)
49                                break if ret
50                        rescue Exception => e
51                                log e
52                                log name
53                                log e.message
54                                log *e.backtrace
55                        end
56                end
57                ret
58        end
59
60
61        def handler_gigazine(config, uri)
62                return unless uri.scheme =~ /^https?/
63                require "bdb"
64                c  = config.find {|h| h["channel"] == @channel }
65                log c.inspect
66                return unless c
67
68                db = BDB::Hash.open(c["db"], nil, 0, 0644)
69                db.each do |k,v|
70                        _, url, datetime, = */^(.+?):(\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d)$/.match(k)
71                        if url == uri.to_s
72                                notice(@channel, "GIGAZINE にものってるわ")
73                                break
74                        end
75                end
76                db.close
77                nil # continue chain
78        end
79
80
81        def handler_mixi(config, uri)
82                return unless uri.host == 'mixi.jp'
83                cookie = {}
84                login_uri = URI("http://mixi.jp/login.pl")
85                Net::HTTP.start(login_uri.host, login_uri.port) do |http|
86                        data = {
87                                "next_url" => "/home.pl",
88                                "email"    => config['user'],
89                                "password" => config['pass'],
90                                "sticky"   => ""
91                        }
92                        data = data.collect {|k,v| "#{k}=#{URI.escape(v)}" }.join("&")
93                        res = http.post(login_uri.request_uri, data, HEADER)
94                        if res.key?("set-cookie")
95                                res["set-cookie"].split(/\s*,\s*/).each do |c|
96                                        k, v =c.sub(/;.*/, "").split(/=/)
97                                        cookie[k] = v
98                                end
99                                #http.get("/check.pl?n=/home.pl", {"User-Agent" => UA} )
100                        else
101                                raise LoginError, "Invalid e-mail or password"
102                        end
103                end
104
105                http(uri, {
106                        "Cookie" => cookie.collect {|c| c.join("=") }.join(";")
107                })
108        end
109       
110        def handler_http(config, uri)
111                return unless uri.scheme =~ /^https?/
112                http(uri)
113        end
114
115        def handler_urn(config, uri)
116                return unless uri.scheme == 'urn'
117                nid, *nss = uri.opaque.split(/:/)
118                case nid
119                when 'ietf'
120                        subclass, *rest = nss
121                        case subclass
122                        when "rfc"
123                                "http://www.ietf.org/rfc/rfc#{rest[0]}.txt"
124                        end
125                when 'isbn'
126                        "http://www.amazon.co.jp/gp/product/#{nss[0]}/"
127                end
128        end
129
130        def handler_ftp(config, uri)
131                return unless uri.scheme == 'ftp'
132                ftp = Net::FTP.open(uri.host, uri.user || "anonymous", uri.password || "foobar@example.com")
133                begin
134                        size = ftp.size(uri.path)
135                        time = ftp.mtime(uri.path)
136                        "[size: #{size} mtime:#{time}]"
137                rescue Net::FTPPermError => e
138                        e.message
139                ensure
140                        ftp.close
141                end
142        end
143
144        def http(uri, header=HEADER, limit=MAX_REDIRECT)
145                return "Redirect loop?: last:#{uri}" if limit <= 0
146
147                log uri
148                ret = ''
149                http = Net::HTTP.new(uri.host, uri.port)
150                http.use_ssl = (uri.scheme == "https")
151                http.start do |http|
152                        r = http.head(uri.request_uri, header)
153                        log r.code.inspect
154                        case r.code
155                        when '200'
156                                case r["Content-Type"]
157                                when /html/
158                                        ret = html(http.get(uri.request_uri, header))
159                                when /image/
160                                        ret = image(http.get(uri.request_uri, header))
161                                else
162                                        if r["Content-Length"]
163                                                size = r["Content-Length"].to_i / 1024
164                                                ret = "[#{r["Content-Type"]}] #{size}KB"
165                                        else
166                                                ret = "[#{r["Content-Type"]}]"
167                                        end
168                                end
169                        when '401'
170                                realm = r["WWW-Authenticate"][/Basic realm="([^"]+)"/, 1]
171                                auth  =  @config["http_auth"].find {|e| e["host"] == uri.host and e["realm"] == realm }
172                                if auth
173                                        auth = "Basic " + ["#{auth["user"]}:#{auth["pass"]}"].pack("m")
174                                        ret = http(uri, header.update({'Authorization' => auth}), limit-1)
175                                else
176                                        ret = realm
177                                end
178                        when /^3/
179                                loc = URI(r["Location"])
180                                loc = uri + loc if loc.relative?
181                                ret = http(loc, header, limit-1)
182                        else
183                                ret = "[#{r.code} #{r.message}]"
184                        end
185                end
186
187        rescue Exception => e
188                log e.message
189                log *e.backtrace
190                e.inspect
191        end
192
193        def image(res)
194                size = res.body.length / 1024
195                img = ImageSize.new(res.body)
196                ret =  "#{img.get_type} Image, "
197                ret << "#{img.get_width || "?"}x#{img.get_height || "?"} "
198                ret << "#{size.to_i}KB"
199        end
200
201        def html(res)
202                title = res.body[/<title.*?>(.*?)<\/title>/imn, 1]
203                title = "タイトル無し " if !title || title.empty?
204                title = title.gsub(/\s+/, " ").gsub(/<.*?>/, "").to_u8
205                title.gsub!(/&#(x)?([0-9a-f]+);/i) do |m|
206                        [$1 ? $2.hex : $2.to_i].pack("U")
207                end
208                if title.size > 70
209                        title = title[/.{0,60}/] + "..."
210                end
211               
212                title = title.gsub(/&gt;/, ">").gsub(/&lt;/, "<").gsub(/&amp;/, "&")
213
214                "#{title} [#{res["Content-Type"]}]"
215        end
216end
217
218
Note: See TracBrowser for help on using the browser.