net-irc2 0.0.10

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/examples/ircd.rb ADDED
@@ -0,0 +1,358 @@
1
+ #!/usr/bin/env ruby
2
+ # vim:encoding=UTF-8:
3
+
4
+ require 'rubygems'
5
+ require 'net/irc'
6
+
7
+ class NetIrcServer < Net::IRC::Server::Session
8
+ def server_name
9
+ "net-irc"
10
+ end
11
+
12
+ def server_version
13
+ "0.0.0"
14
+ end
15
+
16
+ def available_user_modes
17
+ "iosw"
18
+ end
19
+
20
+ def default_user_modes
21
+ ""
22
+ end
23
+
24
+ def available_channel_modes
25
+ "om"
26
+ end
27
+
28
+ def default_channel_modes
29
+ ""
30
+ end
31
+
32
+ def initialize(*args)
33
+ super
34
+ @@channels ||= {}
35
+ @@users ||= {}
36
+ @ping = false
37
+ end
38
+
39
+ def on_pass(m)
40
+ end
41
+
42
+ def on_user(m)
43
+ @user, @real = m.params[0], m.params[3]
44
+ @host = @socket.peeraddr[2]
45
+ @prefix = Prefix.new("#{@nick}!#{@user}@#{@host}")
46
+ @joined_on = @updated_on = Time.now.to_i
47
+
48
+ post @socket, @prefix, NICK, nick
49
+ @nick = nick
50
+ @prefix = "#{@nick}!#{@user}@#{@host}"
51
+
52
+ time = Time.now.to_i
53
+ @@users[@nick.downcase] = {
54
+ :nick => @nick,
55
+ :user => @user,
56
+ :host => @host,
57
+ :real => @real,
58
+ :prefix => @prefix,
59
+ :socket => @socket,
60
+ :joined_on => time,
61
+ :updated_on => time
62
+ }
63
+
64
+ initial_message
65
+
66
+ start_ping
67
+ end
68
+
69
+ def on_join(m)
70
+ channels = m.params[0].split(/\s*,\s*/)
71
+ password = m.params[1]
72
+
73
+ channels.each do |channel|
74
+ unless channel.downcase =~ /^#/
75
+ post @socket, server_name, ERR_NOSUCHCHANNEL, @nick, channel, "No such channel"
76
+ next
77
+ end
78
+
79
+ unless @@channels.key?(channel.downcase)
80
+ channel_create(channel)
81
+ else
82
+ return if @@channels[channel.downcase][:users].key?(@nick.downcase)
83
+
84
+ @@channels[channel.downcase][:users][@nick.downcase] = []
85
+ end
86
+
87
+ mode = @@channels[channel.downcase][:mode].empty? ? "" : "+" + @@channels[channel.downcase][:mode]
88
+ post @socket, server_name, RPL_CHANNELMODEIS, @nick, @@channels[channel.downcase][:alias], mode
89
+
90
+ channel_users = ""
91
+ @@channels[channel.downcase][:users].each do |nick, m|
92
+ post @@users[nick][:socket], @prefix, JOIN, @@channels[channel.downcase][:alias]
93
+
94
+ case
95
+ when m.index("@")
96
+ f = "@"
97
+ when m.index("+")
98
+ f = "+"
99
+ else
100
+ f = ""
101
+ end
102
+ channel_users += "#{f}#{@@users[nick.downcase][:nick]} "
103
+ end
104
+ post @socket, server_name, RPL_NAMREPLY, @@users[nick][:nick], "=", @@channels[channel.downcase][:alias], "#{channel_users.strip}"
105
+ post @socket, server_name, RPL_ENDOFNAMES, @@users[nick][:nick], @@channels[channel.downcase][:alias], "End of /NAMES list"
106
+ end
107
+ end
108
+
109
+ def on_part(m)
110
+ channel, message = *m.params
111
+
112
+ @@channels[channel.downcase][:users].each do |nick, f|
113
+ post @@users[nick][:socket], @prefix, PART, @@channels[channel.downcase][:alias], message
114
+ end
115
+ channel_part(channel)
116
+ end
117
+
118
+ def on_quit(m)
119
+ message = m.params[0]
120
+ @@channels.each do |channel, f|
121
+ if f[:users].key?(@nick.downcase)
122
+ channel_part(channel)
123
+ f[:users].each do |nick, m|
124
+ post @@users[nick][:socket], @prefix, QUIT, message
125
+ end
126
+ end
127
+ end
128
+ finish
129
+ end
130
+
131
+ def on_disconnected
132
+ super
133
+ @@channels.each do |channel, f|
134
+ if f[:users].key?(@nick.downcase)
135
+ channel_part(channel)
136
+ f[:users].each do |nick, m|
137
+ post @@users[nick][:socket], @prefix, QUIT, "disconnect"
138
+ end
139
+ end
140
+ end
141
+ channel_part_all
142
+ @@users.delete(@nick.downcase)
143
+ end
144
+
145
+ def on_who(m)
146
+ channel = m.params[0]
147
+ return unless channel
148
+
149
+ c = channel.downcase
150
+ case
151
+ when @@channels.key?(c)
152
+ @@channels[c][:users].each do |nickname, m|
153
+ nick = @@users[nickname][:nick]
154
+ user = @@users[nickname][:user]
155
+ host = @@users[nickname][:host]
156
+ real = @@users[nickname][:real]
157
+ case
158
+ when m.index("@")
159
+ f = "@"
160
+ when m.index("+")
161
+ f = "+"
162
+ else
163
+ f = ""
164
+ end
165
+ post @socket, server_name, RPL_WHOREPLY, @nick, @@channels[c][:alias], user, host, server_name, nick, "H#{f}", "0 #{real}"
166
+ end
167
+ post @socket, server_name, RPL_ENDOFWHO, @nick, @@channels[c][:alias], "End of /WHO list"
168
+ end
169
+ end
170
+
171
+ def on_mode(m)
172
+ end
173
+
174
+ def on_privmsg(m)
175
+ while (Time.now.to_i - @updated_on < 2)
176
+ sleep 2
177
+ end
178
+ idle_update
179
+
180
+ return on_ctcp(m[0], ctcp_decoding(m[1])) if m.ctcp?
181
+
182
+ target, message = *m.params
183
+ t = target.downcase
184
+
185
+ case
186
+ when @@channels.key?(t)
187
+ if @@channels[t][:users].key?(@nick.downcase)
188
+ @@channels[t][:users].each do |nick, m|
189
+ post @@users[nick][:socket], @prefix, PRIVMSG, @@channels[t][:alias], message unless nick == @nick.downcase
190
+ end
191
+ else
192
+ post @socket, nil, ERR_CANNOTSENDTOCHAN, @nick, target, "Cannot send to channel"
193
+ end
194
+ when @@users.key?(t)
195
+ post @@users[nick][:socket], @prefix, PRIVMSG, @@users[t][:nick], message
196
+ else
197
+ post @socket, nil, ERR_NOSUCHNICK, @nick, target, "No such nick/channel"
198
+ end
199
+ end
200
+
201
+ def on_ping(m)
202
+ post @socket, server_name, PONG, m.params[0]
203
+ end
204
+
205
+ def on_pong(m)
206
+ @ping = true
207
+ end
208
+
209
+ def idle_update
210
+ @updated_on = Time.now.to_i
211
+ if logged_in?
212
+ @@users[@nick.downcase][:updated_on] = @updated_on
213
+ end
214
+ end
215
+
216
+ def channel_create(channel)
217
+ @@channels[channel.downcase] = {
218
+ :alias => channel,
219
+ :topic => "",
220
+ :mode => default_channel_modes,
221
+ :users => {@nick.downcase => ["@"]},
222
+ }
223
+ end
224
+
225
+ def channel_part(channel)
226
+ @@channels[channel.downcase][:users].delete(@nick.downcase)
227
+ channel_delete(channel.downcase) if @@channels[channel.downcase][:users].size == 0
228
+ end
229
+
230
+ def channel_part_all
231
+ @@channels.each do |c|
232
+ channel_part(c)
233
+ end
234
+ end
235
+
236
+ def channel_delete(channel)
237
+ @@channels.delete(channel.downcase)
238
+ end
239
+
240
+ def post(socket, prefix, command, *params)
241
+ m = Message.new(prefix, command, params.map{|s|
242
+ s.gsub(/[\r\n]/, "")
243
+ })
244
+ socket << m
245
+ rescue
246
+ finish
247
+ end
248
+
249
+ def start_ping
250
+ Thread.start do
251
+ loop do
252
+ @ping = false
253
+ time = Time.now.to_i
254
+ if @ping == false && (time - @updated_on > 60)
255
+ post @socket, server_name, PING, @prefix
256
+ loop do
257
+ sleep 1
258
+ if @ping
259
+ break
260
+ end
261
+ if 60 < Time.now.to_i - time
262
+ Thread.stop
263
+ finish
264
+ end
265
+ end
266
+ end
267
+ sleep 60
268
+ end
269
+ end
270
+ end
271
+
272
+ # Call when client connected.
273
+ # Send RPL_WELCOME sequence. If you want to customize, override this method at subclass.
274
+ def initial_message
275
+ post @socket, server_name, RPL_WELCOME, @nick, "Welcome to the Internet Relay Network #{@prefix}"
276
+ post @socket, server_name, RPL_YOURHOST, @nick, "Your host is #{server_name}, running version #{server_version}"
277
+ post @socket, server_name, RPL_CREATED, @nick, "This server was created #{Time.now}"
278
+ post @socket, server_name, RPL_MYINFO, @nick, "#{server_name} #{server_version} #{available_user_modes} #{available_channel_modes}"
279
+ end
280
+
281
+ end
282
+
283
+
284
+ if __FILE__ == $0
285
+ require "optparse"
286
+
287
+ opts = {
288
+ :port => 6969,
289
+ :host => "localhost",
290
+ :log => nil,
291
+ :debug => false,
292
+ :foreground => false,
293
+ }
294
+
295
+ OptionParser.new do |parser|
296
+ parser.instance_eval do
297
+ self.banner = <<-EOB.gsub(/^\t+/, "")
298
+ Usage: #{$0} [opts]
299
+
300
+ EOB
301
+
302
+ separator ""
303
+
304
+ separator "Options:"
305
+ on("-p", "--port [PORT=#{opts[:port]}]", "port number to listen") do |port|
306
+ opts[:port] = port
307
+ end
308
+
309
+ on("-h", "--host [HOST=#{opts[:host]}]", "host name or IP address to listen") do |host|
310
+ opts[:host] = host
311
+ end
312
+
313
+ on("-l", "--log LOG", "log file") do |log|
314
+ opts[:log] = log
315
+ end
316
+
317
+ on("--debug", "Enable debug mode") do |debug|
318
+ opts[:log] = $stdout
319
+ opts[:debug] = true
320
+ end
321
+
322
+ on("-f", "--foreground", "run foreground") do |foreground|
323
+ opts[:log] = $stdout
324
+ opts[:foreground] = true
325
+ end
326
+
327
+ on("-n", "--name [user name or email address]") do |name|
328
+ opts[:name] = name
329
+ end
330
+
331
+ parse!(ARGV)
332
+ end
333
+ end
334
+
335
+ opts[:logger] = Logger.new(opts[:log], "daily")
336
+ opts[:logger].level = opts[:debug] ? Logger::DEBUG : Logger::INFO
337
+
338
+ #def daemonize(foreground = false)
339
+ # [:INT, :TERM, :HUP].each do |sig|
340
+ # Signal.trap sig, "EXIT"
341
+ # end
342
+ # return yield if $DEBUG or foreground
343
+ # Process.fork do
344
+ # Process.setsid
345
+ # Dir.chdir "/"
346
+ # STDIN.reopen "/dev/null"
347
+ # STDOUT.reopen "/dev/null", "a"
348
+ # STDERR.reopen STDOUT
349
+ # yield
350
+ # end
351
+ # exit! 0
352
+ #end
353
+
354
+ #daemonize(opts[:debug] || opts[:foreground]) do
355
+ Net::IRC::Server.new(opts[:host], opts[:port], NetIrcServer, opts).start
356
+ #end
357
+ end
358
+