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.
Files changed (54) hide show
  1. data/.gitignore +5 -0
  2. data/ChangeLog.old +1553 -0
  3. data/Gemfile +4 -0
  4. data/README.org +31 -0
  5. data/Rakefile +1 -0
  6. data/bin/nadoka +13 -0
  7. data/lib/rss_check.rb +206 -0
  8. data/lib/tagparts.rb +206 -0
  9. data/nadoka.gemspec +29 -0
  10. data/nadoka.rb +123 -0
  11. data/nadokarc +267 -0
  12. data/ndk/bot.rb +241 -0
  13. data/ndk/client.rb +288 -0
  14. data/ndk/config.rb +571 -0
  15. data/ndk/error.rb +61 -0
  16. data/ndk/logger.rb +311 -0
  17. data/ndk/server.rb +784 -0
  18. data/ndk/server_state.rb +324 -0
  19. data/ndk/version.rb +44 -0
  20. data/plugins/autoawaybot.nb +66 -0
  21. data/plugins/autodumpbot.nb +227 -0
  22. data/plugins/autoop.nb +56 -0
  23. data/plugins/backlogbot.nb +88 -0
  24. data/plugins/checkbot.nb +64 -0
  25. data/plugins/cronbot.nb +20 -0
  26. data/plugins/dictbot.nb +53 -0
  27. data/plugins/drbcl.rb +39 -0
  28. data/plugins/drbot.nb +93 -0
  29. data/plugins/evalbot.nb +49 -0
  30. data/plugins/gonzuibot.nb +41 -0
  31. data/plugins/googlebot.nb +345 -0
  32. data/plugins/identifynickserv.nb +43 -0
  33. data/plugins/mailcheckbot.nb +0 -0
  34. data/plugins/marldiabot.nb +99 -0
  35. data/plugins/messagebot.nb +96 -0
  36. data/plugins/modemanager.nb +150 -0
  37. data/plugins/opensearchbot.nb +156 -0
  38. data/plugins/opshop.nb +23 -0
  39. data/plugins/pastebot.nb +46 -0
  40. data/plugins/roulettebot.nb +33 -0
  41. data/plugins/rss_checkbot.nb +121 -0
  42. data/plugins/samplebot.nb +24 -0
  43. data/plugins/sendpingbot.nb +17 -0
  44. data/plugins/shellbot.nb +59 -0
  45. data/plugins/sixamobot.nb +77 -0
  46. data/plugins/tenkibot.nb +111 -0
  47. data/plugins/timestampbot.nb +62 -0
  48. data/plugins/titlebot.nb +226 -0
  49. data/plugins/translatebot.nb +301 -0
  50. data/plugins/twitterbot.nb +138 -0
  51. data/plugins/weba.nb +209 -0
  52. data/plugins/xibot.nb +113 -0
  53. data/rice/irc.rb +780 -0
  54. metadata +102 -0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in nadoka.gemspec
4
+ gemspec
@@ -0,0 +1,31 @@
1
+ #######################################################
2
+ # Nadoka: IRC Client server program.
3
+ #
4
+ # Written by SASADA Koichi <ko1 at atdot.net>
5
+ #
6
+ #
7
+ # $Id$
8
+ #
9
+
10
+ * What's this?
11
+
12
+ Nadoka is IRC Client Server program.
13
+ It's same concept as [[http://www.madoka.org/][madoka]].
14
+
15
+ You can do with this software:
16
+
17
+ - connect to IRC usually
18
+ - easy to make a bot with ruby
19
+
20
+
21
+ * more about
22
+
23
+ See Web pages:
24
+ - https://github.com/nadoka/nadoka
25
+ - http://rubyforge.org/projects/nadoka/
26
+ - http://www.atdot.net/nadoka/
27
+
28
+
29
+ : Thank you,
30
+ : --
31
+ : SASADA Koichi at atdot dot net
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/ruby
2
+ require 'rbconfig'
3
+ ruby = nil
4
+ begin
5
+ ruby = RbConfig.ruby
6
+ rescue
7
+ ruby = File.join(
8
+ Config::CONFIG["bindir"],
9
+ Config::CONFIG["ruby_install_name"] + Config::CONFIG["EXEEXT"]
10
+ )
11
+ end
12
+ top_dir = File.expand_path('../..', __FILE__)
13
+ exec(ruby, "-I#{top_dir}", File.join(top_dir, 'nadoka.rb'), *ARGV)
@@ -0,0 +1,206 @@
1
+ #
2
+ # Copyright (c) 2004-2005 SASADA Koichi <ko1 at atdot.net>
3
+ #
4
+ # This program is free software with ABSOLUTELY NO WARRANTY.
5
+ # You can re-distribute and/or modify this program under
6
+ # the same terms of the Ruby's license.
7
+ #
8
+ #
9
+ # $Id$
10
+ # Create : K.S. Sat, 24 Apr 2004 12:10:31 +0900
11
+ #
12
+
13
+ require "rss/parser"
14
+ require "rss/1.0"
15
+ require "rss/2.0"
16
+ require "rss/syndication"
17
+ require "rss/dublincore"
18
+ require "open-uri"
19
+ require 'uri'
20
+ require 'yaml/store'
21
+ require 'csv'
22
+ require 'stringio'
23
+ require 'zlib'
24
+
25
+
26
+ class RSS_Check
27
+ class RSS_File
28
+ def initialize path, init_now
29
+ @uri = URI.parse(path)
30
+ @entry_time = @file_time = (init_now ? Time.now : Time.at(0))
31
+ end
32
+
33
+ def check
34
+ begin
35
+ if (mt=mtime) > @file_time
36
+ @file_time = mt
37
+ check_entries
38
+ else
39
+ []
40
+ end
41
+ rescue => e
42
+ [{
43
+ :about => e.message,
44
+ :title => "RSS Check Error (#{@uri})",
45
+ :ccode => 'UTF-8'
46
+ }]
47
+ end
48
+ end
49
+
50
+ def date_of e
51
+ if e.respond_to? :dc_date
52
+ e.dc_date || Time.at(0)
53
+ else
54
+ e.pubDate || Time.at(0)
55
+ end
56
+ end
57
+
58
+ def check_entries
59
+ rss = RSS::Parser.parse(read_content, false)
60
+ et = @entry_time
61
+ items = rss.items.sort_by{|e|
62
+ date_of(e)
63
+ }.map{|e|
64
+ e_date = date_of(e)
65
+ if e_date > @entry_time
66
+ if e_date > et
67
+ et = e_date
68
+ end
69
+ {
70
+ :about => e.about,
71
+ :title => e.title,
72
+ :ccode => 'UTF-8'
73
+ }
74
+ end
75
+ }.compact
76
+ @entry_time = et
77
+ items
78
+ end
79
+
80
+ def read_content
81
+ case @uri.scheme
82
+ when 'http'
83
+ open(@uri){|f|
84
+ if f.content_encoding.any?{|e| /gzip/ =~ e}
85
+ Zlib::GzipReader.new(StringIO.new(f.read)).read || ''
86
+ else
87
+ f.read
88
+ end
89
+ }
90
+ else
91
+ open(@uri.to_s){|f|
92
+ f.read
93
+ }
94
+ end
95
+ end
96
+
97
+ def mtime
98
+ case @uri.scheme
99
+ when 'http'
100
+ open(@uri){|f|
101
+ f.last_modified || Time.now
102
+ }
103
+ else
104
+ File.mtime(@rss_file)
105
+ end
106
+ end
107
+ end
108
+
109
+ class LIRS_File < RSS_File
110
+ def check_entries
111
+ et = @entry_time
112
+ res = []
113
+ CSV::Reader.parse(read_content){|row|
114
+ last_detected = Time.at(row[2].data.to_i)
115
+ if last_detected > @entry_time && row[1].data != row[2].data
116
+ if last_detected > et
117
+ et = last_detected
118
+ end
119
+ res << {
120
+ :about => row[5].data,
121
+ :title => row[6].data,
122
+ :ccode => 'EUC-JP'
123
+ }
124
+ end
125
+ }
126
+ @entry_time = et
127
+ res
128
+ end
129
+ end
130
+
131
+ def initialize paths, cache_file=nil, init_now=false
132
+ @paths = paths
133
+ @db = YAML::Store.new(cache_file) if cache_file
134
+ @rss_files = paths.map{|uri|
135
+ load_file(uri) ||
136
+ if /LIRS:(.+)/ =~ uri
137
+ LIRS_File.new($1, init_now)
138
+ else
139
+ RSS_File.new(uri, init_now)
140
+ end
141
+ }
142
+ end
143
+
144
+ def check
145
+ @rss_files.map{|rf|
146
+ rf.check
147
+ }.flatten
148
+ end
149
+
150
+ def save
151
+ @db.transaction{
152
+ @paths.each_with_index{|path, i|
153
+ @db[path] = @rss_files[i]
154
+ }
155
+ } if @db
156
+ end
157
+
158
+ def load_file file
159
+ @db.transaction{
160
+ @db[file]
161
+ } if @db
162
+ end
163
+
164
+ def clear
165
+ if @db
166
+ @db.transaction{
167
+ @db.keys.each{|k|
168
+ @db.delete k
169
+ }
170
+ }
171
+ end
172
+ end
173
+ end
174
+
175
+
176
+ if $0 == __FILE__
177
+ rss_uri = %w(
178
+ http://www.ruby-lang.org/ja/index.rdf
179
+ http://slashdot.jp/slashdotjp.rss
180
+ http://www3.asahi.com/rss/index.rdf
181
+ http://pcweb.mycom.co.jp/haishin/rss/index.rdf
182
+ http://japan.cnet.com/rss/index.rdf
183
+ http://blog.japan.cnet.com/umeda/index.rdf
184
+ http://jvn.doi.ics.keio.ac.jp/rss/jvnRSS.rdf
185
+ )
186
+ lirs_uri = [
187
+ 'LIRS:http://www.rubyist.net/~kazu/samidare/sites.lirs.gz'
188
+ ]
189
+
190
+ rssc = RSS_Check.new(
191
+ rss_uri + lirs_uri,
192
+ ARGV.shift || './rss_cache',
193
+ false # false
194
+ )
195
+ require 'iconv'
196
+ require 'kconv'
197
+ ic = Iconv.open("EUC-JP", "UTF-8")
198
+
199
+ rssc.check.each{|e|
200
+ puts e[:about]
201
+ title = (e[:ccode] == 'UTF-8') ? ic.iconv(e[:title]) : e[:title]
202
+ puts title
203
+ }
204
+ rssc.dump
205
+ end
206
+
@@ -0,0 +1,206 @@
1
+ #
2
+ # Copyright (c) 2004-2005 SASADA Koichi <ko1 at atdot.net>
3
+ #
4
+ # This program is free software with ABSOLUTELY NO WARRANTY.
5
+ # You can re-distribute and/or modify this program under
6
+ # the same terms of the Ruby's license.
7
+ #
8
+ #
9
+ # $Id:$
10
+ #
11
+
12
+ require 'cgi'
13
+ module TagParts
14
+ class TagItem
15
+ include Enumerable
16
+ def initialize tag, body, ignore_empty = false
17
+ @tag = tag.to_s
18
+ @attr = {}
19
+ @body = []
20
+ @ignore_empty = ignore_empty
21
+ body.each{|e|
22
+ add! e
23
+ }
24
+ end
25
+ attr_reader :body, :tag, :attr
26
+
27
+ def make_attr_str
28
+ @attr.map{|k,v|
29
+ " #{CGI.escapeHTML(k.to_s)}='#{CGI.escapeHTML(v)}'"
30
+ }.join
31
+ end
32
+
33
+ def to_s
34
+ if @body.size > 0 || @ignore_empty
35
+ body = @body.flatten.map{|e|
36
+ if e.kind_of? String
37
+ CGI.escapeHTML(e.to_s)
38
+ else
39
+ e.to_s
40
+ end
41
+ }
42
+ "<#{@tag}#{make_attr_str}\n>#{body}</#{@tag}>\n"
43
+ else
44
+ "<#{@tag}#{make_attr_str} /\n>"
45
+ end
46
+ end
47
+
48
+ def inspect
49
+ "<TagItem: <#{@tag}#{make_attr_str}>>"
50
+ end
51
+
52
+ def add!(elem)
53
+ if elem.kind_of? Hash
54
+ @attr.update elem
55
+ else
56
+ @body << elem
57
+ end
58
+ end
59
+
60
+ def [](k)
61
+ @attr[k]
62
+ end
63
+
64
+ def []=(k, v)
65
+ @attr[k] = v
66
+ end
67
+
68
+ def each
69
+ @body.flatten.each{|e|
70
+ yield e
71
+ }
72
+ end
73
+
74
+ def each_leaf
75
+ @body.each{|e|
76
+ if e.kind_of? TagItem
77
+ e.each_leaf(&Proc.new)
78
+ else
79
+ yield e
80
+ end
81
+ }
82
+ end
83
+
84
+ def each_node
85
+ yield(self)
86
+ @body.each{|e|
87
+ if e.kind_of? TagItem
88
+ e.each_node(&Proc.new)
89
+ else
90
+ yield e
91
+ end
92
+ }
93
+ end
94
+
95
+ alias << add!
96
+ end
97
+
98
+ def ignore_empty_tag?
99
+ false
100
+ end
101
+
102
+ # do nothing. please override
103
+ def tag_encoding str
104
+ str
105
+ end
106
+
107
+ def tree2string tag
108
+ tag_encoding(tree2string_(tag))
109
+ end
110
+
111
+ def tree2string_ tag
112
+ bs = tag.map{|body|
113
+ if body.kind_of? TagItem
114
+ tree2string_(body)
115
+ else
116
+ CGI.escapeHTML(body.to_s)
117
+ end
118
+ }
119
+ tagname = tag.tag
120
+ attr = tag.make_attr_str
121
+ if bs.size > 0 || ignore_empty_tag?
122
+ "<#{tagname}#{attr}\n>#{bs}</#{tagname}>\n"
123
+ else
124
+ "<#{tagname}#{attr}\n/>"
125
+ end
126
+ end
127
+
128
+ @@method_prefix = '_'
129
+
130
+ def self.newtag sym, ignore_empty, klass = TagParts
131
+ klass.module_eval <<-EOS
132
+ def #{@@method_prefix}#{sym}(*args)
133
+ TagItem.new(:#{sym}, args, #{ignore_empty})
134
+ end
135
+ EOS
136
+ end
137
+
138
+ TagParts.module_eval <<-EOS
139
+ def #{@@method_prefix}(tag, *args)
140
+ TagItem.new(tag, args, false)
141
+ end
142
+ EOS
143
+
144
+ def method_missing m, *args
145
+ if make_unknown_tag? && (/^#{@@method_prefix}(.+)/ =~ m.to_s)
146
+ TagItem.new($1, args)
147
+ else
148
+ super
149
+ end
150
+ end
151
+
152
+ def make_unknown_tag?
153
+ true
154
+ end
155
+
156
+ end
157
+
158
+ module HTMLParts
159
+ include TagParts
160
+
161
+ def make_unknown_tag?
162
+ false
163
+ end
164
+
165
+ def ignore_empty_tag?
166
+ true
167
+ end
168
+
169
+
170
+ # copy from cgi.rb
171
+ PARTS_1 = %w{
172
+ TT I B BIG SMALL EM STRONG DFN CODE SAMP KBD
173
+ VAR CITE ABBR ACRONYM SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT
174
+ H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT OPTGROUP
175
+ FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT
176
+ TEXTAREA FORM A BLOCKQUOTE CAPTION
177
+ }
178
+ PARTS_2 = %w{
179
+ IMG BASE BR AREA LINK PARAM HR INPUT COL META
180
+ }
181
+ PARTS_3 = %w{
182
+ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY COLGROUP TR TH TD HEAD
183
+ }
184
+ (PARTS_1 + PARTS_2 + PARTS_3).each{|e|
185
+ elem = e.downcase
186
+ TagParts.newtag elem, true
187
+ }
188
+ end
189
+
190
+ __END__
191
+
192
+ include HTMLParts
193
+ tags = _html(
194
+ _head(
195
+ _title('hogehoge')),
196
+ _body(
197
+ _br(),
198
+ _h1('huga-'),
199
+ _p('hogehoge', _a('hogehoge', 'href' => 'dokka'), 'huga'),
200
+ _p('hogehoge', 'huga', ['ho-', 'hu'])
201
+ ))
202
+
203
+ puts tags.to_s
204
+ puts tree2string(tags)
205
+ p( tags.to_s == tree2string(tags) )
206
+