nadoka 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/ChangeLog.old +1553 -0
- data/Gemfile +4 -0
- data/README.org +31 -0
- data/Rakefile +1 -0
- data/bin/nadoka +13 -0
- data/lib/rss_check.rb +206 -0
- data/lib/tagparts.rb +206 -0
- data/nadoka.gemspec +29 -0
- data/nadoka.rb +123 -0
- data/nadokarc +267 -0
- data/ndk/bot.rb +241 -0
- data/ndk/client.rb +288 -0
- data/ndk/config.rb +571 -0
- data/ndk/error.rb +61 -0
- data/ndk/logger.rb +311 -0
- data/ndk/server.rb +784 -0
- data/ndk/server_state.rb +324 -0
- data/ndk/version.rb +44 -0
- data/plugins/autoawaybot.nb +66 -0
- data/plugins/autodumpbot.nb +227 -0
- data/plugins/autoop.nb +56 -0
- data/plugins/backlogbot.nb +88 -0
- data/plugins/checkbot.nb +64 -0
- data/plugins/cronbot.nb +20 -0
- data/plugins/dictbot.nb +53 -0
- data/plugins/drbcl.rb +39 -0
- data/plugins/drbot.nb +93 -0
- data/plugins/evalbot.nb +49 -0
- data/plugins/gonzuibot.nb +41 -0
- data/plugins/googlebot.nb +345 -0
- data/plugins/identifynickserv.nb +43 -0
- data/plugins/mailcheckbot.nb +0 -0
- data/plugins/marldiabot.nb +99 -0
- data/plugins/messagebot.nb +96 -0
- data/plugins/modemanager.nb +150 -0
- data/plugins/opensearchbot.nb +156 -0
- data/plugins/opshop.nb +23 -0
- data/plugins/pastebot.nb +46 -0
- data/plugins/roulettebot.nb +33 -0
- data/plugins/rss_checkbot.nb +121 -0
- data/plugins/samplebot.nb +24 -0
- data/plugins/sendpingbot.nb +17 -0
- data/plugins/shellbot.nb +59 -0
- data/plugins/sixamobot.nb +77 -0
- data/plugins/tenkibot.nb +111 -0
- data/plugins/timestampbot.nb +62 -0
- data/plugins/titlebot.nb +226 -0
- data/plugins/translatebot.nb +301 -0
- data/plugins/twitterbot.nb +138 -0
- data/plugins/weba.nb +209 -0
- data/plugins/xibot.nb +113 -0
- data/rice/irc.rb +780 -0
- metadata +102 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
# gonzui bot
|
2
|
+
#
|
3
|
+
|
4
|
+
require 'open-uri'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
class GonzuiBot < Nadoka::NDK_Bot
|
8
|
+
ResultRegexp = %r(>Results <strong\n>(\d+)</strong\n> - <strong\n>(\d+)</strong\n> of <strong\n>(\d+)</strong)
|
9
|
+
|
10
|
+
def on_privmsg prefix, ch, msg
|
11
|
+
if /\Agonzui(?:\:([\w\-\+]+))?>\s*(.+)/ =~ msg
|
12
|
+
send_notice ch, "gonzui bot: #{gonzui_result($1, $2)}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
EngineURI = {
|
17
|
+
'raa' => 'http://raa.ruby-lang.org/gonzui/',
|
18
|
+
'gnome' => 'http://gonzui.tagonome.org/',
|
19
|
+
'cpan' => 'http://cpansearch.bulknews.net/',
|
20
|
+
'b-src' => 'http://b-src.cbrc.jp/',
|
21
|
+
}
|
22
|
+
|
23
|
+
def gonzui_result engine, key
|
24
|
+
engine ||= 'raa'
|
25
|
+
key_uri = URI.encode(key)
|
26
|
+
engine_uri = EngineURI[engine.downcase]
|
27
|
+
return "unknown engine: #{engine}" unless engine_uri
|
28
|
+
|
29
|
+
url = "#{engine_uri}search?q=#{key_uri}"
|
30
|
+
open(url){|f|
|
31
|
+
result = f.read
|
32
|
+
if ResultRegexp =~ result
|
33
|
+
"#{$3} for #{key} - #{url}"
|
34
|
+
else
|
35
|
+
"#{key} - not found in #{engine}"
|
36
|
+
end
|
37
|
+
}
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,345 @@
|
|
1
|
+
# -*-ruby-*-
|
2
|
+
#
|
3
|
+
# Copyright (c) 2004-2005 SASADA Koichi <ko1 at atdot.net>
|
4
|
+
# Copyright (c) 2009, 2010 Kazuhiro NISHIYAMA
|
5
|
+
#
|
6
|
+
# This program is free software with ABSOLUTELY NO WARRANTY.
|
7
|
+
# You can re-distribute and/or modify this program under
|
8
|
+
# the same terms of the Ruby's license.
|
9
|
+
#
|
10
|
+
#
|
11
|
+
# $Id$
|
12
|
+
#
|
13
|
+
|
14
|
+
=begin
|
15
|
+
|
16
|
+
== Usage with irc client
|
17
|
+
|
18
|
+
google> keyword
|
19
|
+
-> search keyword by google with default search langage
|
20
|
+
|
21
|
+
google:[lang]> keyword
|
22
|
+
-> search keyword by google with [lang] langage
|
23
|
+
|
24
|
+
googlec> k1 k2 k3 k4 k5(max 5 words)
|
25
|
+
-> search and show each hit count
|
26
|
+
|
27
|
+
googlec> k1 k2 k3 k4 k5(max 5 words)
|
28
|
+
-> search and show each hit count with default count language
|
29
|
+
|
30
|
+
googlec:[lang]> k1 k2 k3 k4 k5(max 5 words)
|
31
|
+
-> search and show each hit count with [lang] langage
|
32
|
+
|
33
|
+
|
34
|
+
== Configuration:
|
35
|
+
|
36
|
+
BotConfig = [
|
37
|
+
{
|
38
|
+
:name => :GoogleBot,
|
39
|
+
:ch => /.*/,
|
40
|
+
:headers => {
|
41
|
+
#"User-Agent" => "Ruby/#{RUBY_VERSION}",
|
42
|
+
'Referer' => 'https://github.com/nadoka/nadoka',
|
43
|
+
},
|
44
|
+
# Register URL at http://code.google.com/intl/ja/apis/ajaxsearch/signup.html
|
45
|
+
# and set your URL to :referer and your API key to :api_key if you want.
|
46
|
+
:api_key => nil,
|
47
|
+
:googlec_maxwords => 5,
|
48
|
+
:search_default_lang => 'ja',
|
49
|
+
:count_default_lang => '',
|
50
|
+
:ch_kcode => :tojis,
|
51
|
+
},
|
52
|
+
]
|
53
|
+
|
54
|
+
=end
|
55
|
+
|
56
|
+
|
57
|
+
require 'iconv'
|
58
|
+
require 'kconv'
|
59
|
+
require 'shellwords'
|
60
|
+
require 'cgi'
|
61
|
+
require 'open-uri'
|
62
|
+
begin
|
63
|
+
require 'json'
|
64
|
+
rescue LoadError
|
65
|
+
require 'rubygems'
|
66
|
+
require 'json'
|
67
|
+
end
|
68
|
+
|
69
|
+
class GoogleBot < Nadoka::NDK_Bot
|
70
|
+
def bot_initialize
|
71
|
+
bot_init_utils
|
72
|
+
|
73
|
+
@search_default_lang = (@bot_config[:search_default_lang] || 'ja').sub(/^lang_/, '')
|
74
|
+
@googlec_maxwords = @bot_config[:googlec_maxwords] || 5
|
75
|
+
@count_default_lang = (@bot_config[:count_default_lang] || '').sub(/^lang_/, '')
|
76
|
+
@headers = @bot_config.fetch(:headers, {})
|
77
|
+
@api_key = @bot_config[:api_key]
|
78
|
+
@uri_slog = @bot_config.fetch(:uri_slog, false)
|
79
|
+
@ch_kcode = @bot_config.fetch(:ch_kcode, :tojis)
|
80
|
+
end
|
81
|
+
|
82
|
+
def on_privmsg prefix, ch, msg
|
83
|
+
return unless @available_channel === ch
|
84
|
+
return if same_bot?(ch)
|
85
|
+
if response = dispatch_command(msg)
|
86
|
+
send_notice(ch, response)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
SEARCHER = %w!web calc code local video blogs news books images ime imed patent suggest!.freeze
|
91
|
+
SEARCHER_RE = Regexp.new("(?:" + SEARCHER.join('|') + ")").freeze
|
92
|
+
|
93
|
+
def search_searcher key
|
94
|
+
SEARCHER.each{|searcher|
|
95
|
+
if /\A#{key}/ =~ searcher
|
96
|
+
return searcher
|
97
|
+
end
|
98
|
+
}; nil
|
99
|
+
end
|
100
|
+
|
101
|
+
def dispatch_command msg
|
102
|
+
begin
|
103
|
+
case msg
|
104
|
+
when /^goo(o*)gle( #{SEARCHER_RE})?(:.*?)?>\s*(.+)/o, /^gu(u*)guru(#{SEARCHER_RE})?(:.+)?>\s*(.+)/o
|
105
|
+
"goo#{$1}gle#{$2} bot#{$3}: #{search($1.length, $3, $4, $2)}"
|
106
|
+
when /^googlec( #{SEARCHER_RE})?(:.*?)?>\s*(.+)/o
|
107
|
+
"googlec#{$1} bot#{$2}: #{googlec($1, $3, $2)}"
|
108
|
+
when /^g(\w+)?(:.*?)?>\s*(.+)/
|
109
|
+
searcher = $1 ? search_searcher($1) : 'web'
|
110
|
+
"google #{searcher} bot#{$2}: #{search(0, $2, $3, searcher)}" if searcher
|
111
|
+
end
|
112
|
+
rescue Exception => e
|
113
|
+
@manager.ndk_error e
|
114
|
+
"google bot: #{e.class} (#{e.message} @ #{e.backtrace[0]})"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def do_search word, cnt, lang, searcher='web'
|
119
|
+
i = 0
|
120
|
+
begin
|
121
|
+
uri = "http://ajax.googleapis.com/ajax/services/search/"
|
122
|
+
uri << searcher
|
123
|
+
uri << "?v=1.0&q="
|
124
|
+
uri << CGI.escape(word)
|
125
|
+
if @api_key
|
126
|
+
uri << "&key=#{CGI.escape(@api_key)}"
|
127
|
+
end
|
128
|
+
cnt = cnt.to_i
|
129
|
+
if cnt > 0
|
130
|
+
uri << "&start=#{cnt.to_i}"
|
131
|
+
end
|
132
|
+
if lang
|
133
|
+
uri << "&hl=#{CGI.escape(lang)}"
|
134
|
+
if searcher == 'web'
|
135
|
+
uri << "&lr=lang_#{CGI.escape(lang)}"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
@logger.slog "GoogleBot: #{uri}" if @uri_slog
|
139
|
+
|
140
|
+
result = open(uri, @headers) do |f|
|
141
|
+
JSON.parse(f.read)
|
142
|
+
end
|
143
|
+
def result.estimatedTotalResultsCount
|
144
|
+
self["responseData"]["cursor"]["estimatedResultCount"]
|
145
|
+
end
|
146
|
+
result
|
147
|
+
rescue Exception => e
|
148
|
+
retry if (i+=1) < 5
|
149
|
+
raise
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def api_search word, cnt, lang, searcher
|
154
|
+
result = do_search word, cnt, lang, searcher
|
155
|
+
|
156
|
+
count = result.estimatedTotalResultsCount.to_i
|
157
|
+
|
158
|
+
if count > 0
|
159
|
+
count = count.to_s.gsub(/(\d)(?=\d{3}+$)/, '\\1,')
|
160
|
+
url = title = ''
|
161
|
+
|
162
|
+
e = result["responseData"]["results"][0]
|
163
|
+
url = e['unescapedUrl'] || e['url'] || e['postUrl']
|
164
|
+
title = show_char_code_and_erase_tag(e['titleNoFormatting'])
|
165
|
+
"#{title} - #{url} (and #{count} hit#{(count.to_i > 1) ? 's' : ''})"
|
166
|
+
else
|
167
|
+
"no match"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def google_calc exp
|
172
|
+
@logger.slog("google_calc<#{exp.dump}")
|
173
|
+
uri = "http://www.google.co.jp/search?ie=UTF8&oe=UTF-8&q=#{CGI.escape(exp)}"
|
174
|
+
html = open(uri, @headers) do |f|
|
175
|
+
f.read
|
176
|
+
end
|
177
|
+
if /class=r [^<>]+><b>(.+?)<\/b>/u =~ html
|
178
|
+
result = $1
|
179
|
+
# @logger.slog("google_calc>#{result.dump}")
|
180
|
+
result.gsub!(/<sup>(.+?)<\/sup>/u) { "^(#{$1})" }
|
181
|
+
result.gsub!(/<.+?>/u, '')
|
182
|
+
result.gsub!(/&\#215;/u, "\303\227")
|
183
|
+
result.send(@ch_kcode) # NKF.nkf('-j', result)
|
184
|
+
else
|
185
|
+
"response error"
|
186
|
+
end
|
187
|
+
rescue Exception
|
188
|
+
$!.to_s
|
189
|
+
end
|
190
|
+
|
191
|
+
def google_suggest(word, lang)
|
192
|
+
uri = "http://suggestqueries.google.com/complete/search?output=firefox"
|
193
|
+
uri << "&q="
|
194
|
+
uri << CGI.escape(word)
|
195
|
+
if lang
|
196
|
+
uri << "&hl=#{CGI.escape(lang)}"
|
197
|
+
end
|
198
|
+
@logger.slog "GoogleBot: #{uri}" if @uri_slog
|
199
|
+
|
200
|
+
result = open(uri, @headers) do |f|
|
201
|
+
JSON.parse(f.read)
|
202
|
+
end
|
203
|
+
result[1].join(", ").send(@ch_kcode)
|
204
|
+
end
|
205
|
+
|
206
|
+
def google_code key
|
207
|
+
return "http://google.com/codesearch#search/&q=#{CGI.escape(key)}&ct=os"
|
208
|
+
end
|
209
|
+
|
210
|
+
if defined?(URI.encode_www_form)
|
211
|
+
def encode_www_form(enum)
|
212
|
+
URI.encode_www_form(enum)
|
213
|
+
end
|
214
|
+
else
|
215
|
+
def encode_www_form(enum)
|
216
|
+
enum.map do |k, v|
|
217
|
+
"#{URI.encode(k)}=#{URI.encode(v)}"
|
218
|
+
end.join('&')
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# see http://www.google.com/intl/ja/ime/cgiapi.html
|
223
|
+
def google_ime text, d=false
|
224
|
+
url = 'http://www.google.com/transliterate?'
|
225
|
+
url << encode_www_form('langpair' => 'ja-Hira|ja', 'text' => text)
|
226
|
+
data = open(url,@headers){|f|
|
227
|
+
# TODO: gsub fix invalid JSON, should remove after fix response
|
228
|
+
# see http://www.google.com/support/forum/p/ime/thread?tid=06501c8b7a16add3&hl=ja
|
229
|
+
JSON.parse(f.read.gsub(/,(?=\n\])/,''))
|
230
|
+
}
|
231
|
+
if d
|
232
|
+
result = data.map do |org, candidates|
|
233
|
+
"#{org}=#{candidates.join('/')}"
|
234
|
+
end.join(' ')
|
235
|
+
else
|
236
|
+
result = data.map do |org, candidates|
|
237
|
+
candidates[0]
|
238
|
+
end.join('')
|
239
|
+
end
|
240
|
+
show_char_code_and_erase_tag(result)
|
241
|
+
rescue Exception
|
242
|
+
$!.to_s[/.+/] # first line
|
243
|
+
end
|
244
|
+
|
245
|
+
def search cnt, lang, word, searcher=nil
|
246
|
+
lang = lang_check(lang)
|
247
|
+
searcher = searcher_check(searcher)
|
248
|
+
word = search_char_code(word)
|
249
|
+
|
250
|
+
case searcher
|
251
|
+
when 'code'
|
252
|
+
google_code word
|
253
|
+
when 'calc'
|
254
|
+
google_calc word
|
255
|
+
when 'ime'
|
256
|
+
google_ime word
|
257
|
+
when 'imed'
|
258
|
+
google_ime word, true
|
259
|
+
when 'suggest'
|
260
|
+
google_suggest word, lang
|
261
|
+
else
|
262
|
+
api_search word, cnt, lang, searcher
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def googlec lang, word, searcher=nil
|
267
|
+
lang = lang_check(lang, @count_default_lang)
|
268
|
+
searcher = searcher_check(searcher)
|
269
|
+
words = Shellwords.shellwords(word).map{|e| "\"#{e}\""}
|
270
|
+
return 'too many options' if words.size > @googlec_maxwords
|
271
|
+
|
272
|
+
words.map{|rw|
|
273
|
+
w = search_char_code(rw)
|
274
|
+
result = do_search "'#{w}'", 0, lang, searcher
|
275
|
+
"#{rw}(#{result.estimatedTotalResultsCount.to_s.gsub(/(\d)(?=\d{3}+$)/, '\\1,')})"
|
276
|
+
}.join(', ')
|
277
|
+
end
|
278
|
+
|
279
|
+
def erase_tag str
|
280
|
+
CGI.unescapeHTML(str.gsub(/\<.+?\>/, ''))
|
281
|
+
end
|
282
|
+
|
283
|
+
def lang_check lang, default = @search_default_lang
|
284
|
+
if !lang
|
285
|
+
@search_default_lang
|
286
|
+
else
|
287
|
+
lang = lang[1..-1]
|
288
|
+
if lang.empty?
|
289
|
+
nil
|
290
|
+
elsif /^lang_/ =~ lang
|
291
|
+
lang.sub(/^lang_/, '')
|
292
|
+
else
|
293
|
+
lang
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
def searcher_check searcher
|
299
|
+
if !searcher
|
300
|
+
'web'
|
301
|
+
else
|
302
|
+
searcher = searcher.strip
|
303
|
+
if SEARCHER.include?(searcher)
|
304
|
+
searcher
|
305
|
+
else
|
306
|
+
'web'
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def show_char_code_and_erase_tag str
|
312
|
+
return CGI.unescapeHTML(erase_tag(str.toeuc)).send(@ch_kcode)
|
313
|
+
|
314
|
+
case $KCODE
|
315
|
+
when 'EUC', 'SJIS'
|
316
|
+
CGI.unescapeHTML(str.gsub(/\<.+?\>/, '')).send(@ch_kcode)
|
317
|
+
when 'NONE', 'UTF-8'
|
318
|
+
begin
|
319
|
+
str = Iconv.conv("EUC-JP", "UTF-8", str)
|
320
|
+
CGI.unescapeHTML(str.gsub(/\<.+?\>/, '')).send(@ch_kcode)
|
321
|
+
rescue => e
|
322
|
+
"(char code problem: #{e.class}[#{e.message.dump}])"
|
323
|
+
end
|
324
|
+
else
|
325
|
+
str
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
def search_char_code str
|
330
|
+
case $KCODE
|
331
|
+
when 'EUC', 'SJIS'
|
332
|
+
str.toeuc
|
333
|
+
when 'NONE'
|
334
|
+
begin
|
335
|
+
Iconv.conv("UTF-8", "EUC-JP", str.toeuc)
|
336
|
+
rescue => e
|
337
|
+
raise "(char code problem: #{e.class})"
|
338
|
+
end
|
339
|
+
when 'UTF-8'
|
340
|
+
str
|
341
|
+
else
|
342
|
+
raise
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*-ruby-*-
|
2
|
+
#
|
3
|
+
# Copyright (c) 2009 Kazuhiro NISHIYAMA
|
4
|
+
#
|
5
|
+
# This program is free software with ABSOLUTELY NO WARRANTY.
|
6
|
+
# You can re-distribute and/or modify this program under
|
7
|
+
# the same terms of the Ruby's license.
|
8
|
+
#
|
9
|
+
|
10
|
+
=begin
|
11
|
+
|
12
|
+
== Abstract
|
13
|
+
|
14
|
+
send IDENTIFY to NickServ.
|
15
|
+
|
16
|
+
== Configuration
|
17
|
+
|
18
|
+
BotConfig << {
|
19
|
+
:name => :IdentifyNickServ,
|
20
|
+
#:nickserv => "NickServ",
|
21
|
+
:nick => "nadoka",
|
22
|
+
:pass => "hoge",
|
23
|
+
}
|
24
|
+
|
25
|
+
=end
|
26
|
+
|
27
|
+
class IdentifyNickServ < Nadoka::NDK_Bot
|
28
|
+
def bot_initialize
|
29
|
+
@nickserv = @bot_config.fetch(:nickserv, "NickServ")
|
30
|
+
@nick = @bot_config.fetch(:nick, false)
|
31
|
+
@pass = @bot_config.fetch(:pass, false)
|
32
|
+
end
|
33
|
+
|
34
|
+
def on_server_connected(*args)
|
35
|
+
if @pass
|
36
|
+
if @nick
|
37
|
+
send_privmsg @nickserv, "IDENTIFY #{@nick} #{@pass}"
|
38
|
+
else
|
39
|
+
send_privmsg @nickserv, "IDENTIFY #{@pass}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
Binary file
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# -*-ruby-*-
|
2
|
+
require 'cgi'
|
3
|
+
require 'net/http'
|
4
|
+
require 'rexml/document'
|
5
|
+
require 'uri'
|
6
|
+
require 'time'
|
7
|
+
require 'json'
|
8
|
+
|
9
|
+
class MarldiaBot < Nadoka::NDK_Bot
|
10
|
+
def bot_initialize
|
11
|
+
@chats = @bot_config.fetch(:chats, nil)
|
12
|
+
@proxy_addr = @bot_config.fetch(:proxy_addr, nil)
|
13
|
+
@proxy_port = @bot_config.fetch(:proxy_port, 80)
|
14
|
+
|
15
|
+
@chs = @chats.keys
|
16
|
+
@chats.each_value do |chat|
|
17
|
+
chat[:uri] = URI(chat[:url])
|
18
|
+
chat[:query] = 'type=xml&' + chat[:data].
|
19
|
+
map{|k,v|"#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"}.join('&')
|
20
|
+
req = Net::HTTP::Get.new(chat[:uri].path+ '?' + chat[:query])
|
21
|
+
chat[:req] = req
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def bot_state
|
26
|
+
"<#{self.class.to_s}>"
|
27
|
+
end
|
28
|
+
|
29
|
+
def slog(msg, nostamp = false)
|
30
|
+
current_method = caller.first[/:in \`(.*?)\'/, 1].to_s
|
31
|
+
msg.each_line do |line|
|
32
|
+
@logger.slog "#{self.class.to_s}##{current_method} #{line}", nostamp
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_timer(t)
|
37
|
+
@chats.each_pair do |ch, chat|
|
38
|
+
uri = chat[:uri]
|
39
|
+
current_id = chat[:current_id]
|
40
|
+
body = nil
|
41
|
+
messages = []
|
42
|
+
Net::HTTP::Proxy(@proxy_addr, @proxy_port).start(uri.host, uri.port) do |http|
|
43
|
+
body = http.request(chat[:req]).body
|
44
|
+
end
|
45
|
+
doc = REXML::Document.new(body)
|
46
|
+
doc.each_element('feed/entry/log/article') do |art|
|
47
|
+
id = art.text('id')
|
48
|
+
break if current_id == id
|
49
|
+
time = Time.parse(art.text('updated'))
|
50
|
+
next if time + 10 * 60 < Time.now
|
51
|
+
user = art.text('author/name')
|
52
|
+
text = CGI.unescapeHTML(art.text('body')).gsub(/\n|<.*?>/," ")
|
53
|
+
text = text[/^[\w\W]{0,100}/u]
|
54
|
+
text.gsub!(/([\w\W])/u){|c|c == "\xA0" ? " " : c}
|
55
|
+
messages << "#{time.strftime('%H:%M')} #{user}: #{text}"
|
56
|
+
end
|
57
|
+
messages.reverse_each do |message|
|
58
|
+
send_notice ch, message
|
59
|
+
sleep 0.5
|
60
|
+
end
|
61
|
+
chat[:current_id] = doc.text('/feed/entry/log/article/id')
|
62
|
+
end
|
63
|
+
rescue Errno::ETIMEDOUT, Timeout::Error, SocketError
|
64
|
+
rescue Errno::ECONNRESET => err
|
65
|
+
slog "%s: %s (%s)" % [err.backtrace[0], err.message, err.class]
|
66
|
+
rescue Exception => err
|
67
|
+
detail = ("%s: %s (%s)\n" % [err.backtrace[0], err.message, err.class]) + err.backtrace[1..-1].join("\n")
|
68
|
+
slog "Exception\n#{detail}"
|
69
|
+
end
|
70
|
+
|
71
|
+
def send_marldia(ch, message)
|
72
|
+
chat = @chats[ch]
|
73
|
+
uri = chat[:uri]
|
74
|
+
req = Net::HTTP::Post.new(uri.path)
|
75
|
+
req.body = chat[:query] + '&type=xml&body=' + CGI.escape(message)
|
76
|
+
|
77
|
+
Net::HTTP::Proxy(@proxy_addr, @proxy_port).start(uri.host, uri.port) {|http|
|
78
|
+
http.read_timeout = @timeout
|
79
|
+
res = http.request(req)
|
80
|
+
@logger.dlog res.code
|
81
|
+
}
|
82
|
+
return true
|
83
|
+
rescue Errno::ECONNRESET => err
|
84
|
+
slog "%s: %s (%s)" % [err.backtrace[0], err.message, err.class]
|
85
|
+
rescue Exception => err
|
86
|
+
detail = ("%s: %s (%s)\n" % [err.backtrace[0], err.message, err.class]) +
|
87
|
+
err.backtrace[1..-1].join("\n")
|
88
|
+
slog "Exception\n#{detail}"
|
89
|
+
return false
|
90
|
+
end
|
91
|
+
|
92
|
+
def on_client_privmsg(client, ch, message)
|
93
|
+
ch.downcase!
|
94
|
+
return unless @chs.include?(ch)
|
95
|
+
msg = send_marldia(ch, message) ? 'sent to marldia: ' : 'marldia send faild: '
|
96
|
+
msg << message
|
97
|
+
slog msg
|
98
|
+
end
|
99
|
+
end
|