]> git.netwichtig.de Git - user/henk/code/ruby/rbot.git/blob - lib/rbot/utils.rb
Document the new language stuff
[user/henk/code/ruby/rbot.git] / lib / rbot / utils.rb
1 require 'net/http'
2 require 'uri'
3 begin
4   $we_have_html_entities_decoder = require 'htmlentities'
5 rescue LoadError
6   $we_have_html_entities_decoder = false
7   UNESCAPE_TABLE = {
8     'raquo' => '>>',
9     'quot' => '"',
10     'apos' => '\'',
11     'micro' => 'u',
12     'copy' => '(c)',
13     'trade' => '(tm)',
14     'reg' => '(R)',
15     '#174' => '(R)',
16     '#8220' => '"',
17     '#8221' => '"',
18     '#8212' => '--',
19     '#39' => '\'',
20 =begin
21     # extras codes, for future use...
22     'zwnj' => '‌',
23     'aring' => '\xe5',
24     'gt' => '>',
25     'yen' => '\xa5',
26     'ograve' => '\xf2',
27     'Chi' => 'Χ',
28     'bull' => '•',
29     'Egrave' => '\xc8',
30     'Ntilde' => '\xd1',
31     'upsih' => 'ϒ',
32     'Yacute' => '\xdd',
33     'asymp' => '≈',
34     'radic' => '√',
35     'otimes' => '⊗',
36     'nabla' => '∇',
37     'aelig' => '\xe6',
38     'oelig' => 'œ',
39     'equiv' => '≡',
40     'Psi' => 'Ψ',
41     'auml' => '\xe4',
42     'circ' => 'ˆ',
43     'Acirc' => '\xc2',
44     'Epsilon' => 'Ε',
45     'Yuml' => 'Ÿ',
46     'Eta' => 'Η',
47     'lt' => '<',
48     'Icirc' => '\xce',
49     'Upsilon' => '&#933;',
50     'ndash' => '&#8211;',
51     'there4' => '&#8756;',
52     'Prime' => '&#8243;',
53     'prime' => '&#8242;',
54     'psi' => '&#968;',
55     'Kappa' => '&#922;',
56     'rsaquo' => '&#8250;',
57     'Tau' => '&#932;',
58     'darr' => '&#8595;',
59     'ocirc' => '\xf4',
60     'lrm' => '&#8206;',
61     'zwj' => '&#8205;',
62     'cedil' => '\xb8',
63     'Ecirc' => '\xca',
64     'not' => '\xac',
65     'amp' => '&',
66     'AElig' => '\xc6',
67     'oslash' => '\xf8',
68     'acute' => '\xb4',
69     'lceil' => '&#8968;',
70     'laquo' => '\xab',
71     'shy' => '\xad',
72     'rdquo' => '&#8221;',
73     'ge' => '&#8805;',
74     'Igrave' => '\xcc',
75     'Ograve' => '\xd2',
76     'euro' => '&#8364;',
77     'dArr' => '&#8659;',
78     'sdot' => '&#8901;',
79     'nbsp' => '\xa0',
80     'lfloor' => '&#8970;',
81     'lArr' => '&#8656;',
82     'Auml' => '\xc4',
83     'larr' => '&#8592;',
84     'Atilde' => '\xc3',
85     'Otilde' => '\xd5',
86     'szlig' => '\xdf',
87     'clubs' => '&#9827;',
88     'diams' => '&#9830;',
89     'agrave' => '\xe0',
90     'Ocirc' => '\xd4',
91     'Iota' => '&#921;',
92     'Theta' => '&#920;',
93     'Pi' => '&#928;',
94     'OElig' => '&#338;',
95     'Scaron' => '&#352;',
96     'frac14' => '\xbc',
97     'egrave' => '\xe8',
98     'sub' => '&#8834;',
99     'iexcl' => '\xa1',
100     'frac12' => '\xbd',
101     'sbquo' => '&#8218;',
102     'ordf' => '\xaa',
103     'sum' => '&#8721;',
104     'prop' => '&#8733;',
105     'Uuml' => '\xdc',
106     'ntilde' => '\xf1',
107     'sup' => '&#8835;',
108     'theta' => '&#952;',
109     'prod' => '&#8719;',
110     'nsub' => '&#8836;',
111     'hArr' => '&#8660;',
112     'rlm' => '&#8207;',
113     'THORN' => '\xde',
114     'infin' => '&#8734;',
115     'yuml' => '\xff',
116     'Mu' => '&#924;',
117     'le' => '&#8804;',
118     'Eacute' => '\xc9',
119     'thinsp' => '&#8201;',
120     'ecirc' => '\xea',
121     'bdquo' => '&#8222;',
122     'Sigma' => '&#931;',
123     'fnof' => '&#402;',
124     'Aring' => '\xc5',
125     'tilde' => '&#732;',
126     'frac34' => '\xbe',
127     'emsp' => '&#8195;',
128     'mdash' => '&#8212;',
129     'uarr' => '&#8593;',
130     'permil' => '&#8240;',
131     'Ugrave' => '\xd9',
132     'rarr' => '&#8594;',
133     'Agrave' => '\xc0',
134     'chi' => '&#967;',
135     'forall' => '&#8704;',
136     'eth' => '\xf0',
137     'rceil' => '&#8969;',
138     'iuml' => '\xef',
139     'gamma' => '&#947;',
140     'lambda' => '&#955;',
141     'harr' => '&#8596;',
142     'rang' => '&#9002;',
143     'xi' => '&#958;',
144     'dagger' => '&#8224;',
145     'divide' => '\xf7',
146     'Ouml' => '\xd6',
147     'image' => '&#8465;',
148     'alefsym' => '&#8501;',
149     'igrave' => '\xec',
150     'otilde' => '\xf5',
151     'Oacute' => '\xd3',
152     'sube' => '&#8838;',
153     'alpha' => '&#945;',
154     'frasl' => '&#8260;',
155     'ETH' => '\xd0',
156     'lowast' => '&#8727;',
157     'Nu' => '&#925;',
158     'plusmn' => '\xb1',
159     'Euml' => '\xcb',
160     'real' => '&#8476;',
161     'sup1' => '\xb9',
162     'sup2' => '\xb2',
163     'sup3' => '\xb3',
164     'Oslash' => '\xd8',
165     'Aacute' => '\xc1',
166     'cent' => '\xa2',
167     'oline' => '&#8254;',
168     'Beta' => '&#914;',
169     'perp' => '&#8869;',
170     'Delta' => '&#916;',
171     'loz' => '&#9674;',
172     'pi' => '&#960;',
173     'iota' => '&#953;',
174     'empty' => '&#8709;',
175     'euml' => '\xeb',
176     'brvbar' => '\xa6',
177     'iacute' => '\xed',
178     'para' => '\xb6',
179     'micro' => '\xb5',
180     'cup' => '&#8746;',
181     'weierp' => '&#8472;',
182     'uuml' => '\xfc',
183     'part' => '&#8706;',
184     'icirc' => '\xee',
185     'delta' => '&#948;',
186     'omicron' => '&#959;',
187     'upsilon' => '&#965;',
188     'Iuml' => '\xcf',
189     'Lambda' => '&#923;',
190     'Xi' => '&#926;',
191     'kappa' => '&#954;',
192     'ccedil' => '\xe7',
193     'Ucirc' => '\xdb',
194     'cap' => '&#8745;',
195     'mu' => '&#956;',
196     'scaron' => '&#353;',
197     'lsquo' => '&#8216;',
198     'isin' => '&#8712;',
199     'Zeta' => '&#918;',
200     'supe' => '&#8839;',
201     'deg' => '\xb0',
202     'and' => '&#8743;',
203     'tau' => '&#964;',
204     'pound' => '\xa3',
205     'hellip' => '&#8230;',
206     'curren' => '\xa4',
207     'int' => '&#8747;',
208     'ucirc' => '\xfb',
209     'rfloor' => '&#8971;',
210     'ensp' => '&#8194;',
211     'crarr' => '&#8629;',
212     'ugrave' => '\xf9',
213     'notin' => '&#8713;',
214     'exist' => '&#8707;',
215     'uArr' => '&#8657;',
216     'cong' => '&#8773;',
217     'Dagger' => '&#8225;',
218     'oplus' => '&#8853;',
219     'times' => '\xd7',
220     'atilde' => '\xe3',
221     'piv' => '&#982;',
222     'ni' => '&#8715;',
223     'Phi' => '&#934;',
224     'lsaquo' => '&#8249;',
225     'Uacute' => '\xda',
226     'Omicron' => '&#927;',
227     'ang' => '&#8736;',
228     'ne' => '&#8800;',
229     'iquest' => '\xbf',
230     'eta' => '&#951;',
231     'yacute' => '\xfd',
232     'Rho' => '&#929;',
233     'uacute' => '\xfa',
234     'Alpha' => '&#913;',
235     'zeta' => '&#950;',
236     'Omega' => '&#937;',
237     'nu' => '&#957;',
238     'sim' => '&#8764;',
239     'sect' => '\xa7',
240     'phi' => '&#966;',
241     'sigmaf' => '&#962;',
242     'macr' => '\xaf',
243     'minus' => '&#8722;',
244     'Ccedil' => '\xc7',
245     'ordm' => '\xba',
246     'epsilon' => '&#949;',
247     'beta' => '&#946;',
248     'rArr' => '&#8658;',
249     'rho' => '&#961;',
250     'aacute' => '\xe1',
251     'eacute' => '\xe9',
252     'omega' => '&#969;',
253     'middot' => '\xb7',
254     'Gamma' => '&#915;',
255     'Iacute' => '\xcd',
256     'lang' => '&#9001;',
257     'spades' => '&#9824;',
258     'rsquo' => '&#8217;',
259     'uml' => '\xa8',
260     'thorn' => '\xfe',
261     'ouml' => '\xf6',
262     'thetasym' => '&#977;',
263     'or' => '&#8744;',
264     'raquo' => '\xbb',
265     'acirc' => '\xe2',
266     'ldquo' => '&#8220;',
267     'hearts' => '&#9829;',
268     'sigma' => '&#963;',
269     'oacute' => '\xf3',
270 =end
271   }
272 end
273
274 module Irc
275
276   # miscellaneous useful functions
277   module Utils
278
279     # turn a number of seconds into a human readable string, e.g
280     # 2 days, 3 hours, 18 minutes, 10 seconds
281     def Utils.secs_to_string(secs)
282       ret = ""
283       days = (secs / (60 * 60 * 24)).to_i
284       secs = secs % (60 * 60 * 24)
285       hours = (secs / (60 * 60)).to_i
286       secs = (secs % (60 * 60))
287       mins = (secs / 60).to_i
288       secs = (secs % 60).to_i
289       ret += "#{days} days, " if days > 0
290       ret += "#{hours} hours, " if hours > 0 || days > 0
291       ret += "#{mins} minutes and " if mins > 0 || hours > 0 || days > 0
292       ret += "#{secs} seconds"
293       return ret
294     end
295
296
297     def Utils.safe_exec(command, *args)
298       IO.popen("-") {|p|
299         if(p)
300           return p.readlines.join("\n")
301         else
302           begin
303             $stderr = $stdout
304             exec(command, *args)
305           rescue Exception => e
306             puts "exec of #{command} led to exception: #{e.inspect}"
307             Kernel::exit! 0
308           end
309           puts "exec of #{command} failed"
310           Kernel::exit! 0
311         end
312       }
313     end
314
315     # returns a string containing the result of an HTTP GET on the uri
316     def Utils.http_get(uristr, readtimeout=8, opentimeout=4)
317
318       # ruby 1.7 or better needed for this (or 1.6 and debian unstable)
319       Net::HTTP.version_1_2
320       # (so we support the 1_1 api anyway, avoids problems)
321
322       uri = URI.parse uristr
323       query = uri.path
324       if uri.query
325         query += "?#{uri.query}"
326       end
327
328       proxy_host = nil
329       proxy_port = nil
330       if(ENV['http_proxy'] && proxy_uri = URI.parse(ENV['http_proxy']))
331         proxy_host = proxy_uri.host
332         proxy_port = proxy_uri.port
333       end
334
335       begin
336         http = Net::HTTP.new(uri.host, uri.port, proxy_host, proxy_port)
337         http.open_timeout = opentimeout
338         http.read_timeout = readtimeout
339
340         http.start {|http|
341           resp = http.get(query)
342           if resp.code == "200"
343             return resp.body
344           end
345         }
346       rescue => e
347         # cheesy for now
348         error "Utils.http_get exception: #{e.inspect}, while trying to get #{uristr}"
349         return nil
350       end
351     end
352
353     def Utils.decode_html_entities(str)
354       if $we_have_html_entities_decoder
355         return HTMLEntities.decode_entities(str)
356       else
357         str.gsub(/(&(.+?);)/) {
358           symbol = $2
359           # remove the 0-paddng from unicode integers
360           if symbol =~ /#(.+)/
361             symbol = "##{$1.to_i.to_s}"
362           end
363
364           # output the symbol's irc-translated character, or a * if it's unknown
365           UNESCAPE_TABLE[symbol] || '*'
366         }
367       end
368     end
369   end
370 end