nadoka 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|