net-irc2 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
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
+