Commit 52fd4bf3405b5780ea13b6c4662626f3b10447e3

Moved files to lib/irc
IRC.rb
(0 / 174)
  
1
2require 'socket'
3require 'IRCConnection'
4require 'IRCEvent'
5require 'IRCChannel'
6require 'IRCUser'
7require 'IRCUtil'
8
9# Class IRC is a master class that handles connection to the irc
10# server and pasring of IRC events, through the IRCEvent class.
11class IRC
12 attr_reader :nick, :server, :port
13
14 @channels = nil
15 # Create a new IRC Object instance
16 def initialize( nick, server, port, realname='RBot')
17 @nick = nick
18 @server = server
19 @port = port
20 @realname = realname
21 @channels = Array.new(0)
22 # Some good default Event handlers. These can and will be overridden by users.
23 # Thses make changes on the IRCbot object. So they need to be here.
24
25 # Topic events can come on two tags, so we create on proc to handle them.
26
27 topic_proc = Proc.new { |event|
28 self.channels.each { |chan|
29 if chan == event.channel
30 chan.topic = event.message
31 end
32 }
33 }
34
35 IRCEvent.add_handler('332', topic_proc)
36 IRCEvent.add_handler('topic', topic_proc)
37
38 unhandle_proc = Proc.new { |event|
39 method_id = "on_#{event.type}".to_sym
40 if respond_to?(method_id)
41 __send__(method_id, event)
42 elsif $DEBUG
43 $stderr.puts "=> Undefined method #{method_id}"
44 end
45 }
46
47 IRCEvent.add_handler("unhandled", unhandle_proc)
48 end
49
50 # Join a channel, adding it to the list of joined channels
51 def add_channel channel
52 join(channel)
53 self
54 end
55
56 # Returns a list of channels joined
57 def channels
58 @channels
59 end
60
61 # Open a connection to the server using the IRC Connect
62 # method. Events yielded from the IRCConnection handler are
63 # processed and then control is returned to IRCConnection
64 def connect
65 quithandler = lambda { send_quit(); IRCConnection.quit; exit 0 }
66 trap("INT", quithandler)
67 trap("TERM", quithandler)
68
69 IRCConnection.handle_connection(@server, @port, @nick, @realname) do
70 # Log in information moved to IRCConnection
71 @threads = []
72 IRCConnection.main do |event|
73 if event.kind_of?(Array)
74 event.each {|event|
75 thread_event(event)
76 }
77 else
78 thread_event(event)
79 end
80 end
81 @threads.each {|thr| thr.join }
82 end
83 end
84 alias start connect
85
86 # Joins a channel on a server.
87 def join(*channels)
88 channels.each { |channel|
89 if (IRCConnection.send_to_server("JOIN #{channel}"))
90 @channels.push(IRCChannel.new(channel));
91 end
92 }
93 end
94
95 # Leaves a channel on a server
96 def part(channel)
97 if (IRCConnection.send_to_server("PART #{channel}"))
98 @channels.delete_if {|chan| chan.name == channel }
99 end
100 end
101
102 # kicks a user from a channel (does not check for operator privledge)
103 def kick(channel, user, message)
104 IRCConnection.send_to_server("KICK #{channel} #{user} :#{message || user || 'kicked'}")
105 end
106
107 # sets the topic of the given channel
108 def set_topic(channel, topic)
109 IRCConnection.send_to_server("TOPIC #{channel} :#{topic}");
110 end
111
112 # Sends a private message, or channel message
113 def send_message(to, message)
114 IRCConnection.send_to_server("privmsg #{to} :#{message}");
115 end
116
117 # Sends a notice
118 def send_notice(to, message)
119 IRCConnection.send_to_server("NOTICE #{to} :#{message}");
120 end
121
122 # performs an action
123 def send_action(to, action)
124 send_ctcp(to, 'ACTION', action);
125 end
126
127 # send CTCP
128 def send_ctcp(to, type, message)
129 IRCConnection.send_to_server("privmsg #{to} :\001#{type} #{message}");
130 end
131
132 # Quits the IRC Server
133 def send_quit
134 IRCConnection.send_to_server("QUIT : Quit ordered by user")
135 end
136
137 # Ops selected user.
138 def op(channel, user)
139 IRCConnection.send_to_server("MODE #{channel} +o #{user}")
140 end
141
142 # Changes the current nickname
143 def ch_nick(nick)
144 IRCConnection.send_to_server("NICK #{nick}")
145 @nick = nick
146 end
147
148 # Removes operator status from a user
149 def deop(channel, user)
150 IRCConnection.send_to_server("MODE #{channel} -o #{user}")
151 end
152
153 # Changes target users mode
154 def mode(channel, user, mode)
155 IRCConnection.send_to_server("MODE #{channel} #{mode} #{user}")
156 end
157
158 # Retrievs user information from the server
159 def get_user_info(user)
160 IRCConnection.send_to_server("WHO #{user}")
161 end
162 private
163 def thread_event(event)
164 @threads << Thread.new(event) { |localevent|
165 begin
166 localevent.process
167 rescue => e
168 puts "Error: #{e.message}"
169 puts e.backtrace.map { |e| " from #{e}\n" }
170 exit -1
171 end
172 }
173 end
174end
IRCBot.rb
(0 / 27)
  
1
2require 'IRC'
3
4class IRCBot < IRC
5 attr_accessor :operator
6 def initialize(nick, server, port, realname='RBot')
7 super
8
9 @operator = "%"
10 end
11
12 def on_privmsg(event)
13 if event.message =~ /^#{@operator}(\w+)(\s|.+)*/
14 command = $1
15 args = $2.to_s.split(/\s+/)
16 method = "do_#{command}".to_sym
17
18 if respond_to?(method)
19 if respond_to?(method)
20 __send__(method, event, args)
21 end
22 else
23 $stderr.puts "Invalid action: #{command} from #{event.from} in #{event.channel}"
24 end
25 end
26 end
27end
  
1require "IRCUser"
2
3# Represents an IRC Channel
4class IRCChannel
5 def initialize(name)
6 @name = name
7 @users = Array.new(0)
8 end
9 attr_reader :name
10
11 # set the topic on this channel
12 def topic=(topic)
13 @topic = topic
14 end
15
16 # get the topic on this channel
17 def topic
18 if @topic
19 return @topic
20 end
21 return "No Topic set"
22 end
23
24 # add a user to this channel's userlist
25 def add_user(username)
26 @users.push(IRCUser.create_user(username))
27 end
28
29 # returns the current user list for this channel
30 def users
31 @users
32 end
33end
  
1
2# Handles connection to IRC Server
3class IRCConnection
4 @@quit = 0
5 @@readsockets = Array.new(0)
6 @@output_buffer = Array.new(0)
7 @@events = Hash.new()
8 @@last_send = Time.now.to_f
9 @@message_delay = 0.2 # Default delay to 1 fifth of a second.
10 # Creates a socket connection and then yields.
11 def IRCConnection.handle_connection(server, port, nick='ChangeMe', realname='MeToo' )
12 @server = server;
13 @port = port
14 @nick = nick
15 @realname = realname
16 socket = create_tcp_socket(server, port)
17 add_IO_socket(socket) {|sock|
18 begin
19 IRCEvent.new(sock.readline.chomp)
20 rescue Errno::ECONNRESET
21 # Catches connection reset by peer, attempts to reconnect
22 # after sleeping for 10 second.
23 remove_IO_socket(sock)
24 sleep 10
25 handle_connection(@server, @port, @nick, @realname)
26 end
27 }
28 send_to_server "NICK #{nick}"
29 send_to_server "USER #{nick} 8 * :#{realname}"
30 if block_given?
31 yield
32 @@socket.close
33 end
34 end
35
36 def IRCConnection.create_tcp_socket(server, port)
37 @@socket = TCPsocket.open(server, port)
38 if block_given?
39 yield
40 @@socket.close
41 return
42 end
43 return @@socket
44 end
45
46 # Sends a line of text to the server
47 def IRCConnection.send_to_server(line)
48 @@socket.write(line + "\n")
49 end
50
51 # Adds data an output buffer. This let's us keep a handle on how
52 # fast we send things. Yay.
53 def IRCConnection.output_push(line)
54 @@output_buffer.push(line)
55 end
56
57 # This loop monitors all IO_Sockets IRCConnection controls
58 # (including the IRC socket) and yields events to the IO_Sockets
59 # event handler.
60 def IRCConnection.main
61 while(@@quit == 0)
62 do_one_loop { |event|
63 yield event
64 }
65 end
66 end
67
68 # Makes one single loop pass, checking all sockets for data to read,
69 # and yields the data to the sockets event handler.
70 def IRCConnection.do_one_loop
71 read_sockets = select(@@readsockets, nil, nil, 0.1);
72 if !read_sockets.nil?
73 read_sockets[0].each {|sock|
74 if sock.eof? && sock == @@socket
75 p "Detected Socket Close"
76 remove_IO_socket(sock)
77 sleep 10
78 handle_connection(@server, @port, @nick, @realname)
79 else
80 yield @@events[sock.to_i].call(sock)
81 end
82 }
83 end
84 if @@output_buffer.length > 0
85 timer = Time.now.to_f
86 if (timer > @@last_send + @@message_delay)
87 message = @@output_buffer.shift();
88 if !message.nil?
89 IRCConnection.send_to_server(message);
90 @@last_send = timer
91 end
92 end
93 end
94 end
95
96 # Ends connection to the irc server
97 def IRCConnection.quit
98 @@quit = 1
99 end
100 def IRCConnection.delay=(delay)
101 @@message_delay = delay.to_f
102 end
103 # Retrieves user info from the server
104 def IRCConnection.get_user_info(user)
105 IRCConnection.send_to_server("WHOIS #{user}")
106 end
107
108 # Adds a new socket to the list of sockets to monitor for new data.
109 def IRCConnection.add_IO_socket(socket, &event_generator)
110 @@readsockets.push(socket)
111 @@events[socket.to_i] = event_generator
112 end
113
114 def IRCConnection.remove_IO_socket(sock)
115 sock.close
116 @@readsockets.delete_if {|item| item == sock }
117 end
118end
IRCEvent.rb
(0 / 115)
  
1require 'yaml'
2
3# This is a lookup class for IRC event name mapping
4class EventLookup
5 @@lookup = YAML.load_file("#{File.dirname(__FILE__)}/eventmap.yml")
6
7 # returns the event name, given a number
8 def EventLookup::find_by_number(num)
9 return @@lookup[num.to_i]
10 end
11end
12
13
14# Handles an IRC generated event.
15# Handlers are for the IRC framework to use
16# Callbacks are for users to add.
17# Both handlers and callbacks can be called for the same event.
18class IRCEvent
19 @@handlers = { 'ping' => lambda {|event| IRCConnection.send_to_server("PONG #{event.message}") } }
20 @@callbacks = Hash.new()
21 attr_reader :hostmask, :message, :type, :from, :channel, :target, :mode, :stats, :nick, :ident
22 def initialize (line)
23 puts "FROM SERVER: #{line}" if $DEBUG
24
25 line.sub!(/^:/, '')
26 mess_parts = line.split(':', 2);
27 # mess_parts[0] is server info
28 # mess_parts[1] is the message that was sent
29 @message = (mess_parts[1] ? mess_parts[1] : "" )
30 @from = ""
31 @channel = ""
32
33 @stats = mess_parts[0].split(" ")
34
35 puts @stats.join(" | ") if $DEBUG
36
37 if @stats[0].match(/^PING/)
38 @type = 'ping'
39 elsif @message.match(/^(\x1(\w+))/) # ctcp
40 @from = @stats[0]
41 ctcp = $2.downcase
42 @type = "ctcp_#{ctcp}"
43
44 @message.gsub!($1, "")
45 elsif @stats[1] && @stats[1].match(/^\d+/)
46 @type = EventLookup::find_by_number(@stats[1]);
47 @channel = @stats[2]
48 else
49 @type = @stats[1].downcase if @stats[1]
50 end
51
52 if @type != 'ping'
53 @from = @stats[0]
54 @user = IRCUser.create_user(@from)
55 end
56
57 @hostmask = @from.split("@").last
58 @nick = @from.split("!").first
59 @ident = ""
60
61 if @from =~ /!(.+)@/
62 @ident = $1
63 end
64
65 @channel = @stats[2] if @stats[2] and @channel.empty?
66 @target = @stats[3] if @stats[3]
67 @mode = @stats[4] if @stats[4]
68
69 # Unfortunatly, not all messages are created equal. This is our
70 # special exceptions section
71 if @type == 'join'
72 @channel = @message
73 end
74
75 puts "EVENT: #{@type}" if $DEBUG
76
77 end
78
79 # Adds a callback for the specified irc message.
80 def IRCEvent.add_callback(message_id, &callback)
81 @@callbacks[message_id] = callback
82 end
83
84 # Adds a handler to the handler function hash.
85 def IRCEvent.add_handler(message_id, proc=nil, &handler)
86 if block_given?
87 @@handlers[message_id] = handler
88 elsif proc
89 @@handlers[message_id] = proc
90 end
91 end
92
93 # Process this event, preforming which ever handler and callback is specified
94 # for this event.
95 def process
96 handled = false
97 if @@handlers[@type]
98 @@handlers[@type].call(self)
99 handled = true
100 end
101
102 if @@callbacks[@type]
103 @@callbacks[@type].call(self)
104 handled = true
105 end
106
107 if not handled
108 if @@handlers["unhandled"]
109 @@handlers["unhandled"].call(self)
110 else
111 $stderr.puts "No handler for event type #@type in #{self.class}" if $DEBUG
112 end
113 end
114 end
115end
IRCUser.rb
(0 / 23)
  
1# Represents IRC Users
2class IRCUser
3 @@users = Hash.new()
4 @modes = Hash.new()
5
6 def IRCUser.create_user(username)
7 username.sub!(/^[\@\%]/,'')
8
9 if @@users[username]
10 return @@users[username]
11 end
12 @@users[username] = self.new(username)
13 @@users[username]
14 end
15
16 attr_reader :username, :mask
17 attr_writer :mask
18
19 private
20 def initialize (username)
21 @username = username
22 end
23end
IRCUtil.rb
(0 / 49)
  
1#
2# IRCUtil is a module that contains utility functions for use with the
3# rest of Ruby-IRC. There is nothing required of the user to know or
4# even use these functions, but they are useful for certain tasks
5# regarding IRC connections.
6#
7
8module IRCUtil
9 #
10 # Matches hostmasks against hosts. Returns t/f on success/fail.
11 #
12 # A hostmask consists of a simple wildcard that describes a
13 # host or class of hosts.
14 #
15 # f.e., where the host is 'bar.example.com', a host mask
16 # of '*.example.com' would assert.
17 #
18
19 def assert_hostmask(host, hostmask)
20 return !!host.match(quote_regexp_for_mask(hostmask))
21 end
22
23 module_function :assert_hostmask
24
25 #
26 # A utility function used by assert_hostmask() to turn hostmasks
27 # into regular expressions.
28 #
29 # Rarely, if ever, should be used by outside code. It's public
30 # exposure is merely for those who are interested in it's
31 # functionality.
32 #
33
34 def quote_regexp_for_mask(hostmask)
35 # Big thanks to Jesse Williamson for his consultation while writing this.
36 #
37 # escape all other regexp specials except for . and *.
38 # properly escape . and place an unescaped . before *.
39 # confine the regexp to scan the whole line.
40 # return the edited hostmask as a string.
41 hostmask.gsub(/([\[\]\(\)\?\^\$])\\/, '\\1').
42 gsub(/\./, '\.').
43 gsub(/\*/, '.*').
44 sub(/^/, '^').
45 sub(/$/, '$')
46 end
47
48 module_function :quote_regexp_for_mask
49end
eventmap.yml
(0 / 247)
  
1# 001 ne 1 for the purpose of hash keying apparently.
2001 : welcome
3002 : yourhost
4003 : created
5004 : myinfo
6005 : map # Undernet Extension, Kajetan@Hinner.com, 17/11/98
7006 : mapmore # Undernet Extension, Kajetan@Hinner.com, 17/11/98
8007 : mapend # Undernet Extension, Kajetan@Hinner.com, 17/11/98
9008 : snomask # Undernet Extension, Kajetan@Hinner.com, 17/11/98
10009 : statmemtot # Undernet Extension, Kajetan@Hinner.com, 17/11/98
11010 : statmem # Undernet Extension, Kajetan@Hinner.com, 17/11/98
12200 : tracelink
13201 : traceconnecting
14202 : tracehandshake
15203 : traceunknown
16204 : traceoperator
17205 : traceuser
18206 : traceserver
19208 : tracenewtype
20209 : traceclass
21211 : statslinkinfo
22212 : statscommands
23213 : statscline
24214 : statsnline
25215 : statsiline
26216 : statskline
27217 : statsqline
28218 : statsyline
29219 : endofstats
30220 : statsbline # UnrealIrcd, Hendrik Frenzel
31221 : umodeis
32222 : sqline_nick # UnrealIrcd, Hendrik Frenzel
33223 : statsgline # UnrealIrcd, Hendrik Frenzel
34224 : statstline # UnrealIrcd, Hendrik Frenzel
35225 : statseline # UnrealIrcd, Hendrik Frenzel
36226 : statsnline # UnrealIrcd, Hendrik Frenzel
37227 : statsvline # UnrealIrcd, Hendrik Frenzel
38231 : serviceinfo
39232 : endofservices
40233 : service
41234 : servlist
42235 : servlistend
43241 : statslline
44242 : statsuptime
45243 : statsoline
46244 : statshline
47245 : statssline # Reserved, Kajetan@Hinner.com, 17/10/98
48246 : statstline # Undernet Extension, Kajetan@Hinner.com, 17/10/98
49247 : statsgline # Undernet Extension, Kajetan@Hinner.com, 17/10/98
50### TODO: need numerics to be able to map to multiple strings
51### 247 : statsxline # UnrealIrcd, Hendrik Frenzel
52248 : statsuline # Undernet Extension, Kajetan@Hinner.com, 17/10/98
53249 : statsdebug # Unspecific Extension, Kajetan@Hinner.com, 17/10/98
54250 : luserconns # 1998-03-15 -- tkil
55251 : luserclient
56252 : luserop
57253 : luserunknown
58254 : luserchannels
59255 : luserme
60256 : adminme
61257 : adminloc1
62258 : adminloc2
63259 : adminemail
64261 : tracelog
65262 : endoftrace # 1997-11-24 -- archon
66265 : n_local # 1997-10-16 -- tkil
67266 : n_global # 1997-10-16 -- tkil
68271 : silelist # Undernet Extension, Kajetan@Hinner.com, 17/10/98
69272 : endofsilelist # Undernet Extension, Kajetan@Hinner.com, 17/10/98
70275 : statsdline # Undernet Extension, Kajetan@Hinner.com, 17/10/98
71280 : glist # Undernet Extension, Kajetan@Hinner.com, 17/10/98
72281 : endofglist # Undernet Extension, Kajetan@Hinner.com, 17/10/98
73290 : helphdr # UnrealIrcd, Hendrik Frenzel
74291 : helpop # UnrealIrcd, Hendrik Frenzel
75292 : helptlr # UnrealIrcd, Hendrik Frenzel
76293 : helphlp # UnrealIrcd, Hendrik Frenzel
77294 : helpfwd # UnrealIrcd, Hendrik Frenzel
78295 : helpign # UnrealIrcd, Hendrik Frenzel
79300 : none
80301 : away
81302 : userhost
82303 : ison
83304 : rpl_text # Bahamut IRCD
84305 : unaway
85306 : nowaway
86307 : userip # Undernet Extension, Kajetan@Hinner.com, 17/10/98
87308 : rulesstart # UnrealIrcd, Hendrik Frenzel
88309 : endofrules # UnrealIrcd, Hendrik Frenzel
89310 : whoishelp # (July01-01)Austnet Extension, found by Andypoo <andypoo@secret.com.au>
90311 : whoisuser
91312 : whoisserver
92313 : whoisoperator
93314 : whowasuser
94315 : endofwho
95316 : whoischanop
96317 : whoisidle
97318 : endofwhois
98319 : whoischannels
99320 : whoisvworld # (July01-01)Austnet Extension, found by Andypoo <andypoo@secret.com.au>
100321 : liststart
101322 : list
102323 : listend
103324 : channelmodeis
104329 : channelcreate # 1997-11-24 -- archon
105331 : notopic
106332 : topic
107333 : topicinfo # 1997-11-24 -- archon
108334 : listusage # Undernet Extension, Kajetan@Hinner.com, 17/10/98
109335 : whoisbot # UnrealIrcd, Hendrik Frenzel
110341 : inviting
111342 : summoning
112346 : invitelist # UnrealIrcd, Hendrik Frenzel
113347 : endofinvitelist # UnrealIrcd, Hendrik Frenzel
114348 : exlist # UnrealIrcd, Hendrik Frenzel
115349 : endofexlist # UnrealIrcd, Hendrik Frenzel
116351 : version
117352 : whoreply
118353 : namreply
119354 : whospcrpl # Undernet Extension, Kajetan@Hinner.com, 17/10/98
120361 : killdone
121362 : closing
122363 : closeend
123364 : links
124365 : endoflinks
125366 : endofnames
126367 : banlist
127368 : endofbanlist
128369 : endofwhowas
129371 : info
130372 : motd
131373 : infostart
132374 : endofinfo
133375 : motdstart
134376 : endofmotd
135377 : motd2 # 1997-10-16 -- tkil
136378 : austmotd # (July01-01)Austnet Extension, found by Andypoo <andypoo@secret.com.au>
137379 : whoismodes # UnrealIrcd, Hendrik Frenzel
138381 : youreoper
139382 : rehashing
140383 : youreservice # UnrealIrcd, Hendrik Frenzel
141384 : myportis
142385 : notoperanymore # Unspecific Extension, Kajetan@Hinner.com, 17/10/98
143386 : qlist # UnrealIrcd, Hendrik Frenzel
144387 : endofqlist # UnrealIrcd, Hendrik Frenzel
145388 : alist # UnrealIrcd, Hendrik Frenzel
146389 : endofalist # UnrealIrcd, Hendrik Frenzel
147391 : time
148392 : usersstart
149393 : users
150394 : endofusers
151395 : nousers
152401 : nosuchnick
153402 : nosuchserver
154403 : nosuchchannel
155404 : cannotsendtochan
156405 : toomanychannels
157406 : wasnosuchnick
158407 : toomanytargets
159408 : nosuchservice # UnrealIrcd, Hendrik Frenzel
160409 : noorigin
161411 : norecipient
162412 : notexttosend
163413 : notoplevel
164414 : wildtoplevel
165416 : querytoolong # Undernet Extension, Kajetan@Hinner.com, 17/10/98
166421 : unknowncommand
167422 : nomotd
168423 : noadmininfo
169424 : fileerror
170425 : noopermotd # UnrealIrcd, Hendrik Frenzel
171431 : nonicknamegiven
172432 : erroneusnickname # This iz how its speld in thee RFC.
173433 : nicknameinuse
174434 : norules # UnrealIrcd, Hendrik Frenzel
175435 : serviceconfused # UnrealIrcd, Hendrik Frenzel
176436 : nickcollision
177437 : bannickchange # Undernet Extension, Kajetan@Hinner.com, 17/10/98
178438 : nicktoofast # Undernet Extension, Kajetan@Hinner.com, 17/10/98
179439 : targettoofast # Undernet Extension, Kajetan@Hinner.com, 17/10/98
180440 : servicesdown # Bahamut IRCD
181441 : usernotinchannel
182442 : notonchannel
183443 : useronchannel
184444 : nologin
185445 : summondisabled
186446 : usersdisabled
187447 : nonickchange # UnrealIrcd, Hendrik Frenzel
188451 : notregistered
189455 : hostilename # UnrealIrcd, Hendrik Frenzel
190459 : nohiding # UnrealIrcd, Hendrik Frenzel
191460 : notforhalfops # UnrealIrcd, Hendrik Frenzel
192461 : needmoreparams
193462 : alreadyregistered
194463 : nopermforhost
195464 : passwdmismatch
196465 : yourebannedcreep # I love this one...
197466 : youwillbebanned
198467 : keyset
199468 : invalidusername # Undernet Extension, Kajetan@Hinner.com, 17/10/98
200469 : linkset # UnrealIrcd, Hendrik Frenzel
201470 : linkchannel # UnrealIrcd, Hendrik Frenzel
202471 : channelisfull
203472 : unknownmode
204473 : inviteonlychan
205474 : bannedfromchan
206475 : badchannelkey
207476 : badchanmask
208477 : needreggednick # Bahamut IRCD
209478 : banlistfull # Undernet Extension, Kajetan@Hinner.com, 17/10/98
210479 : secureonlychannel # pircd
211### TODO: see above todo
212### 479 : linkfail # UnrealIrcd, Hendrik Frenzel
213480 : cannotknock # UnrealIrcd, Hendrik Frenzel
214481 : noprivileges
215482 : chanoprivsneeded
216483 : cantkillserver
217484 : ischanservice # Undernet Extension, Kajetan@Hinner.com, 17/10/98
218485 : killdeny # UnrealIrcd, Hendrik Frenzel
219486 : htmdisabled # UnrealIrcd, Hendrik Frenzel
220489 : secureonlychan # UnrealIrcd, Hendrik Frenzel
221491 : nooperhost
222492 : noservicehost
223501 : umodeunknownflag
224502 : usersdontmatch
225511 : silelistfull # Undernet Extension, Kajetan@Hinner.com, 17/10/98
226513 : nosuchgline # Undernet Extension, Kajetan@Hinner.com, 17/10/98
227513 : badping # Undernet Extension, Kajetan@Hinner.com, 17/10/98
228518 : noinvite # UnrealIrcd, Hendrik Frenzel
229519 : admonly # UnrealIrcd, Hendrik Frenzel
230520 : operonly # UnrealIrcd, Hendrik Frenzel
231521 : listsyntax # UnrealIrcd, Hendrik Frenzel
232524 : operspverify # UnrealIrcd, Hendrik Frenzel
233
234600 : rpl_logon # Bahamut IRCD
235601 : rpl_logoff # Bahamut IRCD
236602 : rpl_watchoff # UnrealIrcd, Hendrik Frenzel
237603 : rpl_watchstat # UnrealIrcd, Hendrik Frenzel
238604 : rpl_nowon # Bahamut IRCD
239605 : rpl_nowoff # Bahamut IRCD
240606 : rpl_watchlist # UnrealIrcd, Hendrik Frenzel
241607 : rpl_endofwatchlist # UnrealIrcd, Hendrik Frenzel
242610 : mapmore # UnrealIrcd, Hendrik Frenzel
243640 : rpl_dumping # UnrealIrcd, Hendrik Frenzel
244641 : rpl_dumprpl # UnrealIrcd, Hendrik Frenzel
245642 : rpl_eodump # UnrealIrcd, Hendrik Frenzel
246
247999 : numericerror # Bahamut IRCD
  
1
2require 'socket'
3require 'IRCConnection'
4require 'IRCEvent'
5require 'IRCChannel'
6require 'IRCUser'
7require 'IRCUtil'
8
9# Class IRC is a master class that handles connection to the irc
10# server and pasring of IRC events, through the IRCEvent class.
11class IRC
12 attr_reader :nick, :server, :port
13
14 @channels = nil
15 # Create a new IRC Object instance
16 def initialize( nick, server, port, realname='RBot')
17 @nick = nick
18 @server = server
19 @port = port
20 @realname = realname
21 @channels = Array.new(0)
22 # Some good default Event handlers. These can and will be overridden by users.
23 # Thses make changes on the IRCbot object. So they need to be here.
24
25 # Topic events can come on two tags, so we create on proc to handle them.
26
27 topic_proc = Proc.new { |event|
28 self.channels.each { |chan|
29 if chan == event.channel
30 chan.topic = event.message
31 end
32 }
33 }
34
35 IRCEvent.add_handler('332', topic_proc)
36 IRCEvent.add_handler('topic', topic_proc)
37
38 unhandle_proc = Proc.new { |event|
39 method_id = "on_#{event.type}".to_sym
40 if respond_to?(method_id)
41 __send__(method_id, event)
42 elsif $DEBUG
43 $stderr.puts "=> Undefined method #{method_id}"
44 end
45 }
46
47 IRCEvent.add_handler("unhandled", unhandle_proc)
48 end
49
50 # Join a channel, adding it to the list of joined channels
51 def add_channel channel
52 join(channel)
53 self
54 end
55
56 # Returns a list of channels joined
57 def channels
58 @channels
59 end
60
61 # Open a connection to the server using the IRC Connect
62 # method. Events yielded from the IRCConnection handler are
63 # processed and then control is returned to IRCConnection
64 def connect
65 quithandler = lambda { send_quit(); IRCConnection.quit; exit 0 }
66 trap("INT", quithandler)
67 trap("TERM", quithandler)
68
69 IRCConnection.handle_connection(@server, @port, @nick, @realname) do
70 # Log in information moved to IRCConnection
71 @threads = []
72 IRCConnection.main do |event|
73 if event.kind_of?(Array)
74 event.each {|event|
75 thread_event(event)
76 }
77 else
78 thread_event(event)
79 end
80 end
81 @threads.each {|thr| thr.join }
82 end
83 end
84 alias start connect
85
86 # Joins a channel on a server.
87 def join(*channels)
88 channels.each { |channel|
89 if (IRCConnection.send_to_server("JOIN #{channel}"))
90 @channels.push(IRCChannel.new(channel));
91 end
92 }
93 end
94
95 # Leaves a channel on a server
96 def part(channel)
97 if (IRCConnection.send_to_server("PART #{channel}"))
98 @channels.delete_if {|chan| chan.name == channel }
99 end
100 end
101
102 # kicks a user from a channel (does not check for operator privledge)
103 def kick(channel, user, message)
104 IRCConnection.send_to_server("KICK #{channel} #{user} :#{message || user || 'kicked'}")
105 end
106
107 # sets the topic of the given channel
108 def set_topic(channel, topic)
109 IRCConnection.send_to_server("TOPIC #{channel} :#{topic}");
110 end
111
112 # Sends a private message, or channel message
113 def send_message(to, message)
114 IRCConnection.send_to_server("privmsg #{to} :#{message}");
115 end
116
117 # Sends a notice
118 def send_notice(to, message)
119 IRCConnection.send_to_server("NOTICE #{to} :#{message}");
120 end
121
122 # performs an action
123 def send_action(to, action)
124 send_ctcp(to, 'ACTION', action);
125 end
126
127 # send CTCP
128 def send_ctcp(to, type, message)
129 IRCConnection.send_to_server("privmsg #{to} :\001#{type} #{message}");
130 end
131
132 # Quits the IRC Server
133 def send_quit
134 IRCConnection.send_to_server("QUIT : Quit ordered by user")
135 end
136
137 # Ops selected user.
138 def op(channel, user)
139 IRCConnection.send_to_server("MODE #{channel} +o #{user}")
140 end
141
142 # Changes the current nickname
143 def ch_nick(nick)
144 IRCConnection.send_to_server("NICK #{nick}")
145 @nick = nick
146 end
147
148 # Removes operator status from a user
149 def deop(channel, user)
150 IRCConnection.send_to_server("MODE #{channel} -o #{user}")
151 end
152
153 # Changes target users mode
154 def mode(channel, user, mode)
155 IRCConnection.send_to_server("MODE #{channel} #{mode} #{user}")
156 end
157
158 # Retrievs user information from the server
159 def get_user_info(user)
160 IRCConnection.send_to_server("WHO #{user}")
161 end
162 private
163 def thread_event(event)
164 @threads << Thread.new(event) { |localevent|
165 begin
166 localevent.process
167 rescue => e
168 puts "Error: #{e.message}"
169 puts e.backtrace.map { |e| " from #{e}\n" }
170 exit -1
171 end
172 }
173 end
174end
  
1
2require 'IRC'
3
4class IRCBot < IRC
5 attr_accessor :operator
6 def initialize(nick, server, port, realname='RBot')
7 super
8
9 @operator = "%"
10 end
11
12 def on_privmsg(event)
13 if event.message =~ /^#{@operator}(\w+)(\s|.+)*/
14 command = $1
15 args = $2.to_s.split(/\s+/)
16 method = "do_#{command}".to_sym
17
18 if respond_to?(method)
19 if respond_to?(method)
20 __send__(method, event, args)
21 end
22 else
23 $stderr.puts "Invalid action: #{command} from #{event.from} in #{event.channel}"
24 end
25 end
26 end
27end
  
1require "IRCUser"
2
3# Represents an IRC Channel
4class IRCChannel
5 def initialize(name)
6 @name = name
7 @users = Array.new(0)
8 end
9 attr_reader :name
10
11 # set the topic on this channel
12 def topic=(topic)
13 @topic = topic
14 end
15
16 # get the topic on this channel
17 def topic
18 if @topic
19 return @topic
20 end
21 return "No Topic set"
22 end
23
24 # add a user to this channel's userlist
25 def add_user(username)
26 @users.push(IRCUser.create_user(username))
27 end
28
29 # returns the current user list for this channel
30 def users
31 @users
32 end
33end
  
1
2# Handles connection to IRC Server
3class IRCConnection
4 @@quit = 0
5 @@readsockets = Array.new(0)
6 @@output_buffer = Array.new(0)
7 @@events = Hash.new()
8 @@last_send = Time.now.to_f
9 @@message_delay = 0.2 # Default delay to 1 fifth of a second.
10 # Creates a socket connection and then yields.
11 def IRCConnection.handle_connection(server, port, nick='ChangeMe', realname='MeToo' )
12 @server = server;
13 @port = port
14 @nick = nick
15 @realname = realname
16 socket = create_tcp_socket(server, port)
17 add_IO_socket(socket) {|sock|
18 begin
19 IRCEvent.new(sock.readline.chomp)
20 rescue Errno::ECONNRESET
21 # Catches connection reset by peer, attempts to reconnect
22 # after sleeping for 10 second.
23 remove_IO_socket(sock)
24 sleep 10
25 handle_connection(@server, @port, @nick, @realname)
26 end
27 }
28 send_to_server "NICK #{nick}"
29 send_to_server "USER #{nick} 8 * :#{realname}"
30 if block_given?
31 yield
32 @@socket.close
33 end
34 end
35
36 def IRCConnection.create_tcp_socket(server, port)
37 @@socket = TCPsocket.open(server, port)
38 if block_given?
39 yield
40 @@socket.close
41 return
42 end
43 return @@socket
44 end
45
46 # Sends a line of text to the server
47 def IRCConnection.send_to_server(line)
48 @@socket.write(line + "\n")
49 end
50
51 # Adds data an output buffer. This let's us keep a handle on how
52 # fast we send things. Yay.
53 def IRCConnection.output_push(line)
54 @@output_buffer.push(line)
55 end
56
57 # This loop monitors all IO_Sockets IRCConnection controls
58 # (including the IRC socket) and yields events to the IO_Sockets
59 # event handler.
60 def IRCConnection.main
61 while(@@quit == 0)
62 do_one_loop { |event|
63 yield event
64 }
65 end
66 end
67
68 # Makes one single loop pass, checking all sockets for data to read,
69 # and yields the data to the sockets event handler.
70 def IRCConnection.do_one_loop
71 read_sockets = select(@@readsockets, nil, nil, 0.1);
72 if !read_sockets.nil?
73 read_sockets[0].each {|sock|
74 if sock.eof? && sock == @@socket
75 p "Detected Socket Close"
76 remove_IO_socket(sock)
77 sleep 10
78 handle_connection(@server, @port, @nick, @realname)
79 else
80 yield @@events[sock.to_i].call(sock)
81 end
82 }
83 end
84 if @@output_buffer.length > 0
85 timer = Time.now.to_f
86 if (timer > @@last_send + @@message_delay)
87 message = @@output_buffer.shift();
88 if !message.nil?
89 IRCConnection.send_to_server(message);
90 @@last_send = timer
91 end
92 end
93 end
94 end
95
96 # Ends connection to the irc server
97 def IRCConnection.quit
98 @@quit = 1
99 end
100 def IRCConnection.delay=(delay)
101 @@message_delay = delay.to_f
102 end
103 # Retrieves user info from the server
104 def IRCConnection.get_user_info(user)
105 IRCConnection.send_to_server("WHOIS #{user}")
106 end
107
108 # Adds a new socket to the list of sockets to monitor for new data.
109 def IRCConnection.add_IO_socket(socket, &event_generator)
110 @@readsockets.push(socket)
111 @@events[socket.to_i] = event_generator
112 end
113
114 def IRCConnection.remove_IO_socket(sock)
115 sock.close
116 @@readsockets.delete_if {|item| item == sock }
117 end
118end
  
1require 'yaml'
2
3# This is a lookup class for IRC event name mapping
4class EventLookup
5 @@lookup = YAML.load_file("#{File.dirname(__FILE__)}/eventmap.yml")
6
7 # returns the event name, given a number
8 def EventLookup::find_by_number(num)
9 return @@lookup[num.to_i]
10 end
11end
12
13
14# Handles an IRC generated event.
15# Handlers are for the IRC framework to use
16# Callbacks are for users to add.
17# Both handlers and callbacks can be called for the same event.
18class IRCEvent
19 @@handlers = { 'ping' => lambda {|event| IRCConnection.send_to_server("PONG #{event.message}") } }
20 @@callbacks = Hash.new()
21 attr_reader :hostmask, :message, :type, :from, :channel, :target, :mode, :stats, :nick, :ident
22 def initialize (line)
23 puts "FROM SERVER: #{line}" if $DEBUG
24
25 line.sub!(/^:/, '')
26 mess_parts = line.split(':', 2);
27 # mess_parts[0] is server info
28 # mess_parts[1] is the message that was sent
29 @message = (mess_parts[1] ? mess_parts[1] : "" )
30 @from = ""
31 @channel = ""
32
33 @stats = mess_parts[0].split(" ")
34
35 puts @stats.join(" | ") if $DEBUG
36
37 if @stats[0].match(/^PING/)
38 @type = 'ping'
39 elsif @message.match(/^(\x1(\w+))/) # ctcp
40 @from = @stats[0]
41 ctcp = $2.downcase
42 @type = "ctcp_#{ctcp}"
43
44 @message.gsub!($1, "")
45 elsif @stats[1] && @stats[1].match(/^\d+/)
46 @type = EventLookup::find_by_number(@stats[1]);
47 @channel = @stats[2]
48 else
49 @type = @stats[1].downcase if @stats[1]
50 end
51
52 if @type != 'ping'
53 @from = @stats[0]
54 @user = IRCUser.create_user(@from)
55 end
56
57 @hostmask = @from.split("@").last
58 @nick = @from.split("!").first
59 @ident = ""
60
61 if @from =~ /!(.+)@/
62 @ident = $1
63 end
64
65 @channel = @stats[2] if @stats[2] and @channel.empty?
66 @target = @stats[3] if @stats[3]
67 @mode = @stats[4] if @stats[4]
68
69 # Unfortunatly, not all messages are created equal. This is our
70 # special exceptions section
71 if @type == 'join'
72 @channel = @message
73 end
74
75 puts "EVENT: #{@type}" if $DEBUG
76
77 end
78
79 # Adds a callback for the specified irc message.
80 def IRCEvent.add_callback(message_id, &callback)
81 @@callbacks[message_id] = callback
82 end
83
84 # Adds a handler to the handler function hash.
85 def IRCEvent.add_handler(message_id, proc=nil, &handler)
86 if block_given?
87 @@handlers[message_id] = handler
88 elsif proc
89 @@handlers[message_id] = proc
90 end
91 end
92
93 # Process this event, preforming which ever handler and callback is specified
94 # for this event.
95 def process
96 handled = false
97 if @@handlers[@type]
98 @@handlers[@type].call(self)
99 handled = true
100 end
101
102 if @@callbacks[@type]
103 @@callbacks[@type].call(self)
104 handled = true
105 end
106
107 if not handled
108 if @@handlers["unhandled"]
109 @@handlers["unhandled"].call(self)
110 else
111 $stderr.puts "No handler for event type #@type in #{self.class}" if $DEBUG
112 end
113 end
114 end
115end
  
1# Represents IRC Users
2class IRCUser
3 @@users = Hash.new()
4 @modes = Hash.new()
5
6 def IRCUser.create_user(username)
7 username.sub!(/^[\@\%]/,'')
8
9 if @@users[username]
10 return @@users[username]
11 end
12 @@users[username] = self.new(username)
13 @@users[username]
14 end
15
16 attr_reader :username, :mask
17 attr_writer :mask
18
19 private
20 def initialize (username)
21 @username = username
22 end
23end
  
1#
2# IRCUtil is a module that contains utility functions for use with the
3# rest of Ruby-IRC. There is nothing required of the user to know or
4# even use these functions, but they are useful for certain tasks
5# regarding IRC connections.
6#
7
8module IRCUtil
9 #
10 # Matches hostmasks against hosts. Returns t/f on success/fail.
11 #
12 # A hostmask consists of a simple wildcard that describes a
13 # host or class of hosts.
14 #
15 # f.e., where the host is 'bar.example.com', a host mask
16 # of '*.example.com' would assert.
17 #
18
19 def assert_hostmask(host, hostmask)
20 return !!host.match(quote_regexp_for_mask(hostmask))
21 end
22
23 module_function :assert_hostmask
24
25 #
26 # A utility function used by assert_hostmask() to turn hostmasks
27 # into regular expressions.
28 #
29 # Rarely, if ever, should be used by outside code. It's public
30 # exposure is merely for those who are interested in it's
31 # functionality.
32 #
33
34 def quote_regexp_for_mask(hostmask)
35 # Big thanks to Jesse Williamson for his consultation while writing this.
36 #
37 # escape all other regexp specials except for . and *.
38 # properly escape . and place an unescaped . before *.
39 # confine the regexp to scan the whole line.
40 # return the edited hostmask as a string.
41 hostmask.gsub(/([\[\]\(\)\?\^\$])\\/, '\\1').
42 gsub(/\./, '\.').
43 gsub(/\*/, '.*').
44 sub(/^/, '^').
45 sub(/$/, '$')
46 end
47
48 module_function :quote_regexp_for_mask
49end
  
1# 001 ne 1 for the purpose of hash keying apparently.
2001 : welcome
3002 : yourhost
4003 : created
5004 : myinfo
6005 : map # Undernet Extension, Kajetan@Hinner.com, 17/11/98
7006 : mapmore # Undernet Extension, Kajetan@Hinner.com, 17/11/98
8007 : mapend # Undernet Extension, Kajetan@Hinner.com, 17/11/98
9008 : snomask # Undernet Extension, Kajetan@Hinner.com, 17/11/98
10009 : statmemtot # Undernet Extension, Kajetan@Hinner.com, 17/11/98
11010 : statmem # Undernet Extension, Kajetan@Hinner.com, 17/11/98
12200 : tracelink
13201 : traceconnecting
14202 : tracehandshake
15203 : traceunknown
16204 : traceoperator
17205 : traceuser
18206 : traceserver
19208 : tracenewtype
20209 : traceclass
21211 : statslinkinfo
22212 : statscommands
23213 : statscline
24214 : statsnline
25215 : statsiline
26216 : statskline
27217 : statsqline
28218 : statsyline
29219 : endofstats
30220 : statsbline # UnrealIrcd, Hendrik Frenzel
31221 : umodeis
32222 : sqline_nick # UnrealIrcd, Hendrik Frenzel
33223 : statsgline # UnrealIrcd, Hendrik Frenzel
34224 : statstline # UnrealIrcd, Hendrik Frenzel
35225 : statseline # UnrealIrcd, Hendrik Frenzel
36226 : statsnline # UnrealIrcd, Hendrik Frenzel
37227 : statsvline # UnrealIrcd, Hendrik Frenzel
38231 : serviceinfo
39232 : endofservices
40233 : service
41234 : servlist
42235 : servlistend
43241 : statslline
44242 : statsuptime
45243 : statsoline
46244 : statshline
47245 : statssline # Reserved, Kajetan@Hinner.com, 17/10/98
48246 : statstline # Undernet Extension, Kajetan@Hinner.com, 17/10/98
49247 : statsgline # Undernet Extension, Kajetan@Hinner.com, 17/10/98
50### TODO: need numerics to be able to map to multiple strings
51### 247 : statsxline # UnrealIrcd, Hendrik Frenzel
52248 : statsuline # Undernet Extension, Kajetan@Hinner.com, 17/10/98
53249 : statsdebug # Unspecific Extension, Kajetan@Hinner.com, 17/10/98
54250 : luserconns # 1998-03-15 -- tkil
55251 : luserclient
56252 : luserop
57253 : luserunknown
58254 : luserchannels
59255 : luserme
60256 : adminme
61257 : adminloc1
62258 : adminloc2
63259 : adminemail
64261 : tracelog
65262 : endoftrace # 1997-11-24 -- archon
66265 : n_local # 1997-10-16 -- tkil
67266 : n_global # 1997-10-16 -- tkil
68271 : silelist # Undernet Extension, Kajetan@Hinner.com, 17/10/98
69272 : endofsilelist # Undernet Extension, Kajetan@Hinner.com, 17/10/98
70275 : statsdline # Undernet Extension, Kajetan@Hinner.com, 17/10/98
71280 : glist # Undernet Extension, Kajetan@Hinner.com, 17/10/98
72281 : endofglist # Undernet Extension, Kajetan@Hinner.com, 17/10/98
73290 : helphdr # UnrealIrcd, Hendrik Frenzel
74291 : helpop # UnrealIrcd, Hendrik Frenzel
75292 : helptlr # UnrealIrcd, Hendrik Frenzel
76293 : helphlp # UnrealIrcd, Hendrik Frenzel
77294 : helpfwd # UnrealIrcd, Hendrik Frenzel
78295 : helpign # UnrealIrcd, Hendrik Frenzel
79300 : none
80301 : away
81302 : userhost
82303 : ison
83304 : rpl_text # Bahamut IRCD
84305 : unaway
85306 : nowaway
86307 : userip # Undernet Extension, Kajetan@Hinner.com, 17/10/98
87308 : rulesstart # UnrealIrcd, Hendrik Frenzel
88309 : endofrules # UnrealIrcd, Hendrik Frenzel
89310 : whoishelp # (July01-01)Austnet Extension, found by Andypoo <andypoo@secret.com.au>
90311 : whoisuser
91312 : whoisserver
92313 : whoisoperator
93314 : whowasuser
94315 : endofwho
95316 : whoischanop
96317 : whoisidle
97318 : endofwhois
98319 : whoischannels
99320 : whoisvworld # (July01-01)Austnet Extension, found by Andypoo <andypoo@secret.com.au>
100321 : liststart
101322 : list
102323 : listend
103324 : channelmodeis
104329 : channelcreate # 1997-11-24 -- archon
105331 : notopic
106332 : topic
107333 : topicinfo # 1997-11-24 -- archon
108334 : listusage # Undernet Extension, Kajetan@Hinner.com, 17/10/98
109335 : whoisbot # UnrealIrcd, Hendrik Frenzel
110341 : inviting
111342 : summoning
112346 : invitelist # UnrealIrcd, Hendrik Frenzel
113347 : endofinvitelist # UnrealIrcd, Hendrik Frenzel
114348 : exlist # UnrealIrcd, Hendrik Frenzel
115349 : endofexlist # UnrealIrcd, Hendrik Frenzel
116351 : version
117352 : whoreply
118353 : namreply
119354 : whospcrpl # Undernet Extension, Kajetan@Hinner.com, 17/10/98
120361 : killdone
121362 : closing
122363 : closeend
123364 : links
124365 : endoflinks
125366 : endofnames
126367 : banlist
127368 : endofbanlist
128369 : endofwhowas
129371 : info
130372 : motd
131373 : infostart
132374 : endofinfo
133375 : motdstart
134376 : endofmotd
135377 : motd2 # 1997-10-16 -- tkil
136378 : austmotd # (July01-01)Austnet Extension, found by Andypoo <andypoo@secret.com.au>
137379 : whoismodes # UnrealIrcd, Hendrik Frenzel
138381 : youreoper
139382 : rehashing
140383 : youreservice # UnrealIrcd, Hendrik Frenzel
141384 : myportis
142385 : notoperanymore # Unspecific Extension, Kajetan@Hinner.com, 17/10/98
143386 : qlist # UnrealIrcd, Hendrik Frenzel
144387 : endofqlist # UnrealIrcd, Hendrik Frenzel
145388 : alist # UnrealIrcd, Hendrik Frenzel
146389 : endofalist # UnrealIrcd, Hendrik Frenzel
147391 : time
148392 : usersstart
149393 : users
150394 : endofusers
151395 : nousers
152401 : nosuchnick
153402 : nosuchserver
154403 : nosuchchannel
155404 : cannotsendtochan
156405 : toomanychannels
157406 : wasnosuchnick
158407 : toomanytargets
159408 : nosuchservice # UnrealIrcd, Hendrik Frenzel
160409 : noorigin
161411 : norecipient
162412 : notexttosend
163413 : notoplevel
164414 : wildtoplevel
165416 : querytoolong # Undernet Extension, Kajetan@Hinner.com, 17/10/98
166421 : unknowncommand
167422 : nomotd
168423 : noadmininfo
169424 : fileerror
170425 : noopermotd # UnrealIrcd, Hendrik Frenzel
171431 : nonicknamegiven
172432 : erroneusnickname # This iz how its speld in thee RFC.
173433 : nicknameinuse
174434 : norules # UnrealIrcd, Hendrik Frenzel
175435 : serviceconfused # UnrealIrcd, Hendrik Frenzel
176436 : nickcollision
177437 : bannickchange # Undernet Extension, Kajetan@Hinner.com, 17/10/98
178438 : nicktoofast # Undernet Extension, Kajetan@Hinner.com, 17/10/98
179439 : targettoofast # Undernet Extension, Kajetan@Hinner.com, 17/10/98
180440 : servicesdown # Bahamut IRCD
181441 : usernotinchannel
182442 : notonchannel
183443 : useronchannel
184444 : nologin
185445 : summondisabled
186446 : usersdisabled
187447 : nonickchange # UnrealIrcd, Hendrik Frenzel
188451 : notregistered
189455 : hostilename # UnrealIrcd, Hendrik Frenzel
190459 : nohiding # UnrealIrcd, Hendrik Frenzel
191460 : notforhalfops # UnrealIrcd, Hendrik Frenzel
192461 : needmoreparams
193462 : alreadyregistered
194463 : nopermforhost
195464 : passwdmismatch
196465 : yourebannedcreep # I love this one...
197466 : youwillbebanned
198467 : keyset
199468 : invalidusername # Undernet Extension, Kajetan@Hinner.com, 17/10/98
200469 : linkset # UnrealIrcd, Hendrik Frenzel
201470 : linkchannel # UnrealIrcd, Hendrik Frenzel
202471 : channelisfull
203472 : unknownmode
204473 : inviteonlychan
205474 : bannedfromchan
206475 : badchannelkey
207476 : badchanmask
208477 : needreggednick # Bahamut IRCD
209478 : banlistfull # Undernet Extension, Kajetan@Hinner.com, 17/10/98
210479 : secureonlychannel # pircd
211### TODO: see above todo
212### 479 : linkfail # UnrealIrcd, Hendrik Frenzel
213480 : cannotknock # UnrealIrcd, Hendrik Frenzel
214481 : noprivileges
215482 : chanoprivsneeded
216483 : cantkillserver
217484 : ischanservice # Undernet Extension, Kajetan@Hinner.com, 17/10/98
218485 : killdeny # UnrealIrcd, Hendrik Frenzel
219486 : htmdisabled # UnrealIrcd, Hendrik Frenzel
220489 : secureonlychan # UnrealIrcd, Hendrik Frenzel
221491 : nooperhost
222492 : noservicehost
223501 : umodeunknownflag
224502 : usersdontmatch
225511 : silelistfull # Undernet Extension, Kajetan@Hinner.com, 17/10/98
226513 : nosuchgline # Undernet Extension, Kajetan@Hinner.com, 17/10/98
227513 : badping # Undernet Extension, Kajetan@Hinner.com, 17/10/98
228518 : noinvite # UnrealIrcd, Hendrik Frenzel
229519 : admonly # UnrealIrcd, Hendrik Frenzel
230520 : operonly # UnrealIrcd, Hendrik Frenzel
231521 : listsyntax # UnrealIrcd, Hendrik Frenzel
232524 : operspverify # UnrealIrcd, Hendrik Frenzel
233
234600 : rpl_logon # Bahamut IRCD
235601 : rpl_logoff # Bahamut IRCD
236602 : rpl_watchoff # UnrealIrcd, Hendrik Frenzel
237603 : rpl_watchstat # UnrealIrcd, Hendrik Frenzel
238604 : rpl_nowon # Bahamut IRCD
239605 : rpl_nowoff # Bahamut IRCD
240606 : rpl_watchlist # UnrealIrcd, Hendrik Frenzel
241607 : rpl_endofwatchlist # UnrealIrcd, Hendrik Frenzel
242610 : mapmore # UnrealIrcd, Hendrik Frenzel
243640 : rpl_dumping # UnrealIrcd, Hendrik Frenzel
244641 : rpl_dumprpl # UnrealIrcd, Hendrik Frenzel
245642 : rpl_eodump # UnrealIrcd, Hendrik Frenzel
246
247999 : numericerror # Bahamut IRCD