Commit 52fd4bf3405b5780ea13b6c4662626f3b10447e3
- Diff rendering mode:
- inline
- side by side
IRC.rb
(0 / 174)
|   | |||
| 1 | |||
| 2 | require 'socket' | ||
| 3 | require 'IRCConnection' | ||
| 4 | require 'IRCEvent' | ||
| 5 | require 'IRCChannel' | ||
| 6 | require 'IRCUser' | ||
| 7 | require '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. | ||
| 11 | class 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 | ||
| 174 | end |
IRCBot.rb
(0 / 27)
|   | |||
| 1 | |||
| 2 | require 'IRC' | ||
| 3 | |||
| 4 | class 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 | ||
| 27 | end |
IRCChannel.rb
(0 / 33)
|   | |||
| 1 | require "IRCUser" | ||
| 2 | |||
| 3 | # Represents an IRC Channel | ||
| 4 | class 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 | ||
| 33 | end |
IRCConnection.rb
(0 / 118)
|   | |||
| 1 | |||
| 2 | # Handles connection to IRC Server | ||
| 3 | class 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 | ||
| 118 | end |
IRCEvent.rb
(0 / 115)
|   | |||
| 1 | require 'yaml' | ||
| 2 | |||
| 3 | # This is a lookup class for IRC event name mapping | ||
| 4 | class 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 | ||
| 11 | end | ||
| 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. | ||
| 18 | class 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 | ||
| 115 | end |
IRCUser.rb
(0 / 23)
|   | |||
| 1 | # Represents IRC Users | ||
| 2 | class 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 | ||
| 23 | end |
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 | |||
| 8 | module 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 | ||
| 49 | end |
eventmap.yml
(0 / 247)
|   | |||
| 1 | # 001 ne 1 for the purpose of hash keying apparently. | ||
| 2 | 001 : welcome | ||
| 3 | 002 : yourhost | ||
| 4 | 003 : created | ||
| 5 | 004 : myinfo | ||
| 6 | 005 : map # Undernet Extension, Kajetan@Hinner.com, 17/11/98 | ||
| 7 | 006 : mapmore # Undernet Extension, Kajetan@Hinner.com, 17/11/98 | ||
| 8 | 007 : mapend # Undernet Extension, Kajetan@Hinner.com, 17/11/98 | ||
| 9 | 008 : snomask # Undernet Extension, Kajetan@Hinner.com, 17/11/98 | ||
| 10 | 009 : statmemtot # Undernet Extension, Kajetan@Hinner.com, 17/11/98 | ||
| 11 | 010 : statmem # Undernet Extension, Kajetan@Hinner.com, 17/11/98 | ||
| 12 | 200 : tracelink | ||
| 13 | 201 : traceconnecting | ||
| 14 | 202 : tracehandshake | ||
| 15 | 203 : traceunknown | ||
| 16 | 204 : traceoperator | ||
| 17 | 205 : traceuser | ||
| 18 | 206 : traceserver | ||
| 19 | 208 : tracenewtype | ||
| 20 | 209 : traceclass | ||
| 21 | 211 : statslinkinfo | ||
| 22 | 212 : statscommands | ||
| 23 | 213 : statscline | ||
| 24 | 214 : statsnline | ||
| 25 | 215 : statsiline | ||
| 26 | 216 : statskline | ||
| 27 | 217 : statsqline | ||
| 28 | 218 : statsyline | ||
| 29 | 219 : endofstats | ||
| 30 | 220 : statsbline # UnrealIrcd, Hendrik Frenzel | ||
| 31 | 221 : umodeis | ||
| 32 | 222 : sqline_nick # UnrealIrcd, Hendrik Frenzel | ||
| 33 | 223 : statsgline # UnrealIrcd, Hendrik Frenzel | ||
| 34 | 224 : statstline # UnrealIrcd, Hendrik Frenzel | ||
| 35 | 225 : statseline # UnrealIrcd, Hendrik Frenzel | ||
| 36 | 226 : statsnline # UnrealIrcd, Hendrik Frenzel | ||
| 37 | 227 : statsvline # UnrealIrcd, Hendrik Frenzel | ||
| 38 | 231 : serviceinfo | ||
| 39 | 232 : endofservices | ||
| 40 | 233 : service | ||
| 41 | 234 : servlist | ||
| 42 | 235 : servlistend | ||
| 43 | 241 : statslline | ||
| 44 | 242 : statsuptime | ||
| 45 | 243 : statsoline | ||
| 46 | 244 : statshline | ||
| 47 | 245 : statssline # Reserved, Kajetan@Hinner.com, 17/10/98 | ||
| 48 | 246 : statstline # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 49 | 247 : 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 | ||
| 52 | 248 : statsuline # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 53 | 249 : statsdebug # Unspecific Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 54 | 250 : luserconns # 1998-03-15 -- tkil | ||
| 55 | 251 : luserclient | ||
| 56 | 252 : luserop | ||
| 57 | 253 : luserunknown | ||
| 58 | 254 : luserchannels | ||
| 59 | 255 : luserme | ||
| 60 | 256 : adminme | ||
| 61 | 257 : adminloc1 | ||
| 62 | 258 : adminloc2 | ||
| 63 | 259 : adminemail | ||
| 64 | 261 : tracelog | ||
| 65 | 262 : endoftrace # 1997-11-24 -- archon | ||
| 66 | 265 : n_local # 1997-10-16 -- tkil | ||
| 67 | 266 : n_global # 1997-10-16 -- tkil | ||
| 68 | 271 : silelist # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 69 | 272 : endofsilelist # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 70 | 275 : statsdline # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 71 | 280 : glist # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 72 | 281 : endofglist # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 73 | 290 : helphdr # UnrealIrcd, Hendrik Frenzel | ||
| 74 | 291 : helpop # UnrealIrcd, Hendrik Frenzel | ||
| 75 | 292 : helptlr # UnrealIrcd, Hendrik Frenzel | ||
| 76 | 293 : helphlp # UnrealIrcd, Hendrik Frenzel | ||
| 77 | 294 : helpfwd # UnrealIrcd, Hendrik Frenzel | ||
| 78 | 295 : helpign # UnrealIrcd, Hendrik Frenzel | ||
| 79 | 300 : none | ||
| 80 | 301 : away | ||
| 81 | 302 : userhost | ||
| 82 | 303 : ison | ||
| 83 | 304 : rpl_text # Bahamut IRCD | ||
| 84 | 305 : unaway | ||
| 85 | 306 : nowaway | ||
| 86 | 307 : userip # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 87 | 308 : rulesstart # UnrealIrcd, Hendrik Frenzel | ||
| 88 | 309 : endofrules # UnrealIrcd, Hendrik Frenzel | ||
| 89 | 310 : whoishelp # (July01-01)Austnet Extension, found by Andypoo <andypoo@secret.com.au> | ||
| 90 | 311 : whoisuser | ||
| 91 | 312 : whoisserver | ||
| 92 | 313 : whoisoperator | ||
| 93 | 314 : whowasuser | ||
| 94 | 315 : endofwho | ||
| 95 | 316 : whoischanop | ||
| 96 | 317 : whoisidle | ||
| 97 | 318 : endofwhois | ||
| 98 | 319 : whoischannels | ||
| 99 | 320 : whoisvworld # (July01-01)Austnet Extension, found by Andypoo <andypoo@secret.com.au> | ||
| 100 | 321 : liststart | ||
| 101 | 322 : list | ||
| 102 | 323 : listend | ||
| 103 | 324 : channelmodeis | ||
| 104 | 329 : channelcreate # 1997-11-24 -- archon | ||
| 105 | 331 : notopic | ||
| 106 | 332 : topic | ||
| 107 | 333 : topicinfo # 1997-11-24 -- archon | ||
| 108 | 334 : listusage # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 109 | 335 : whoisbot # UnrealIrcd, Hendrik Frenzel | ||
| 110 | 341 : inviting | ||
| 111 | 342 : summoning | ||
| 112 | 346 : invitelist # UnrealIrcd, Hendrik Frenzel | ||
| 113 | 347 : endofinvitelist # UnrealIrcd, Hendrik Frenzel | ||
| 114 | 348 : exlist # UnrealIrcd, Hendrik Frenzel | ||
| 115 | 349 : endofexlist # UnrealIrcd, Hendrik Frenzel | ||
| 116 | 351 : version | ||
| 117 | 352 : whoreply | ||
| 118 | 353 : namreply | ||
| 119 | 354 : whospcrpl # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 120 | 361 : killdone | ||
| 121 | 362 : closing | ||
| 122 | 363 : closeend | ||
| 123 | 364 : links | ||
| 124 | 365 : endoflinks | ||
| 125 | 366 : endofnames | ||
| 126 | 367 : banlist | ||
| 127 | 368 : endofbanlist | ||
| 128 | 369 : endofwhowas | ||
| 129 | 371 : info | ||
| 130 | 372 : motd | ||
| 131 | 373 : infostart | ||
| 132 | 374 : endofinfo | ||
| 133 | 375 : motdstart | ||
| 134 | 376 : endofmotd | ||
| 135 | 377 : motd2 # 1997-10-16 -- tkil | ||
| 136 | 378 : austmotd # (July01-01)Austnet Extension, found by Andypoo <andypoo@secret.com.au> | ||
| 137 | 379 : whoismodes # UnrealIrcd, Hendrik Frenzel | ||
| 138 | 381 : youreoper | ||
| 139 | 382 : rehashing | ||
| 140 | 383 : youreservice # UnrealIrcd, Hendrik Frenzel | ||
| 141 | 384 : myportis | ||
| 142 | 385 : notoperanymore # Unspecific Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 143 | 386 : qlist # UnrealIrcd, Hendrik Frenzel | ||
| 144 | 387 : endofqlist # UnrealIrcd, Hendrik Frenzel | ||
| 145 | 388 : alist # UnrealIrcd, Hendrik Frenzel | ||
| 146 | 389 : endofalist # UnrealIrcd, Hendrik Frenzel | ||
| 147 | 391 : time | ||
| 148 | 392 : usersstart | ||
| 149 | 393 : users | ||
| 150 | 394 : endofusers | ||
| 151 | 395 : nousers | ||
| 152 | 401 : nosuchnick | ||
| 153 | 402 : nosuchserver | ||
| 154 | 403 : nosuchchannel | ||
| 155 | 404 : cannotsendtochan | ||
| 156 | 405 : toomanychannels | ||
| 157 | 406 : wasnosuchnick | ||
| 158 | 407 : toomanytargets | ||
| 159 | 408 : nosuchservice # UnrealIrcd, Hendrik Frenzel | ||
| 160 | 409 : noorigin | ||
| 161 | 411 : norecipient | ||
| 162 | 412 : notexttosend | ||
| 163 | 413 : notoplevel | ||
| 164 | 414 : wildtoplevel | ||
| 165 | 416 : querytoolong # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 166 | 421 : unknowncommand | ||
| 167 | 422 : nomotd | ||
| 168 | 423 : noadmininfo | ||
| 169 | 424 : fileerror | ||
| 170 | 425 : noopermotd # UnrealIrcd, Hendrik Frenzel | ||
| 171 | 431 : nonicknamegiven | ||
| 172 | 432 : erroneusnickname # This iz how its speld in thee RFC. | ||
| 173 | 433 : nicknameinuse | ||
| 174 | 434 : norules # UnrealIrcd, Hendrik Frenzel | ||
| 175 | 435 : serviceconfused # UnrealIrcd, Hendrik Frenzel | ||
| 176 | 436 : nickcollision | ||
| 177 | 437 : bannickchange # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 178 | 438 : nicktoofast # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 179 | 439 : targettoofast # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 180 | 440 : servicesdown # Bahamut IRCD | ||
| 181 | 441 : usernotinchannel | ||
| 182 | 442 : notonchannel | ||
| 183 | 443 : useronchannel | ||
| 184 | 444 : nologin | ||
| 185 | 445 : summondisabled | ||
| 186 | 446 : usersdisabled | ||
| 187 | 447 : nonickchange # UnrealIrcd, Hendrik Frenzel | ||
| 188 | 451 : notregistered | ||
| 189 | 455 : hostilename # UnrealIrcd, Hendrik Frenzel | ||
| 190 | 459 : nohiding # UnrealIrcd, Hendrik Frenzel | ||
| 191 | 460 : notforhalfops # UnrealIrcd, Hendrik Frenzel | ||
| 192 | 461 : needmoreparams | ||
| 193 | 462 : alreadyregistered | ||
| 194 | 463 : nopermforhost | ||
| 195 | 464 : passwdmismatch | ||
| 196 | 465 : yourebannedcreep # I love this one... | ||
| 197 | 466 : youwillbebanned | ||
| 198 | 467 : keyset | ||
| 199 | 468 : invalidusername # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 200 | 469 : linkset # UnrealIrcd, Hendrik Frenzel | ||
| 201 | 470 : linkchannel # UnrealIrcd, Hendrik Frenzel | ||
| 202 | 471 : channelisfull | ||
| 203 | 472 : unknownmode | ||
| 204 | 473 : inviteonlychan | ||
| 205 | 474 : bannedfromchan | ||
| 206 | 475 : badchannelkey | ||
| 207 | 476 : badchanmask | ||
| 208 | 477 : needreggednick # Bahamut IRCD | ||
| 209 | 478 : banlistfull # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 210 | 479 : secureonlychannel # pircd | ||
| 211 | ### TODO: see above todo | ||
| 212 | ### 479 : linkfail # UnrealIrcd, Hendrik Frenzel | ||
| 213 | 480 : cannotknock # UnrealIrcd, Hendrik Frenzel | ||
| 214 | 481 : noprivileges | ||
| 215 | 482 : chanoprivsneeded | ||
| 216 | 483 : cantkillserver | ||
| 217 | 484 : ischanservice # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 218 | 485 : killdeny # UnrealIrcd, Hendrik Frenzel | ||
| 219 | 486 : htmdisabled # UnrealIrcd, Hendrik Frenzel | ||
| 220 | 489 : secureonlychan # UnrealIrcd, Hendrik Frenzel | ||
| 221 | 491 : nooperhost | ||
| 222 | 492 : noservicehost | ||
| 223 | 501 : umodeunknownflag | ||
| 224 | 502 : usersdontmatch | ||
| 225 | 511 : silelistfull # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 226 | 513 : nosuchgline # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 227 | 513 : badping # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 228 | 518 : noinvite # UnrealIrcd, Hendrik Frenzel | ||
| 229 | 519 : admonly # UnrealIrcd, Hendrik Frenzel | ||
| 230 | 520 : operonly # UnrealIrcd, Hendrik Frenzel | ||
| 231 | 521 : listsyntax # UnrealIrcd, Hendrik Frenzel | ||
| 232 | 524 : operspverify # UnrealIrcd, Hendrik Frenzel | ||
| 233 | |||
| 234 | 600 : rpl_logon # Bahamut IRCD | ||
| 235 | 601 : rpl_logoff # Bahamut IRCD | ||
| 236 | 602 : rpl_watchoff # UnrealIrcd, Hendrik Frenzel | ||
| 237 | 603 : rpl_watchstat # UnrealIrcd, Hendrik Frenzel | ||
| 238 | 604 : rpl_nowon # Bahamut IRCD | ||
| 239 | 605 : rpl_nowoff # Bahamut IRCD | ||
| 240 | 606 : rpl_watchlist # UnrealIrcd, Hendrik Frenzel | ||
| 241 | 607 : rpl_endofwatchlist # UnrealIrcd, Hendrik Frenzel | ||
| 242 | 610 : mapmore # UnrealIrcd, Hendrik Frenzel | ||
| 243 | 640 : rpl_dumping # UnrealIrcd, Hendrik Frenzel | ||
| 244 | 641 : rpl_dumprpl # UnrealIrcd, Hendrik Frenzel | ||
| 245 | 642 : rpl_eodump # UnrealIrcd, Hendrik Frenzel | ||
| 246 | |||
| 247 | 999 : numericerror # Bahamut IRCD |
lib/irc/IRC.rb
(174 / 0)
|   | |||
| 1 | |||
| 2 | require 'socket' | ||
| 3 | require 'IRCConnection' | ||
| 4 | require 'IRCEvent' | ||
| 5 | require 'IRCChannel' | ||
| 6 | require 'IRCUser' | ||
| 7 | require '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. | ||
| 11 | class 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 | ||
| 174 | end |
lib/irc/IRCBot.rb
(27 / 0)
|   | |||
| 1 | |||
| 2 | require 'IRC' | ||
| 3 | |||
| 4 | class 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 | ||
| 27 | end |
lib/irc/IRCChannel.rb
(33 / 0)
|   | |||
| 1 | require "IRCUser" | ||
| 2 | |||
| 3 | # Represents an IRC Channel | ||
| 4 | class 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 | ||
| 33 | end |
lib/irc/IRCConnection.rb
(118 / 0)
|   | |||
| 1 | |||
| 2 | # Handles connection to IRC Server | ||
| 3 | class 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 | ||
| 118 | end |
lib/irc/IRCEvent.rb
(115 / 0)
|   | |||
| 1 | require 'yaml' | ||
| 2 | |||
| 3 | # This is a lookup class for IRC event name mapping | ||
| 4 | class 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 | ||
| 11 | end | ||
| 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. | ||
| 18 | class 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 | ||
| 115 | end |
lib/irc/IRCUser.rb
(23 / 0)
|   | |||
| 1 | # Represents IRC Users | ||
| 2 | class 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 | ||
| 23 | end |
lib/irc/IRCUtil.rb
(49 / 0)
|   | |||
| 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 | |||
| 8 | module 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 | ||
| 49 | end |
lib/irc/eventmap.yml
(247 / 0)
|   | |||
| 1 | # 001 ne 1 for the purpose of hash keying apparently. | ||
| 2 | 001 : welcome | ||
| 3 | 002 : yourhost | ||
| 4 | 003 : created | ||
| 5 | 004 : myinfo | ||
| 6 | 005 : map # Undernet Extension, Kajetan@Hinner.com, 17/11/98 | ||
| 7 | 006 : mapmore # Undernet Extension, Kajetan@Hinner.com, 17/11/98 | ||
| 8 | 007 : mapend # Undernet Extension, Kajetan@Hinner.com, 17/11/98 | ||
| 9 | 008 : snomask # Undernet Extension, Kajetan@Hinner.com, 17/11/98 | ||
| 10 | 009 : statmemtot # Undernet Extension, Kajetan@Hinner.com, 17/11/98 | ||
| 11 | 010 : statmem # Undernet Extension, Kajetan@Hinner.com, 17/11/98 | ||
| 12 | 200 : tracelink | ||
| 13 | 201 : traceconnecting | ||
| 14 | 202 : tracehandshake | ||
| 15 | 203 : traceunknown | ||
| 16 | 204 : traceoperator | ||
| 17 | 205 : traceuser | ||
| 18 | 206 : traceserver | ||
| 19 | 208 : tracenewtype | ||
| 20 | 209 : traceclass | ||
| 21 | 211 : statslinkinfo | ||
| 22 | 212 : statscommands | ||
| 23 | 213 : statscline | ||
| 24 | 214 : statsnline | ||
| 25 | 215 : statsiline | ||
| 26 | 216 : statskline | ||
| 27 | 217 : statsqline | ||
| 28 | 218 : statsyline | ||
| 29 | 219 : endofstats | ||
| 30 | 220 : statsbline # UnrealIrcd, Hendrik Frenzel | ||
| 31 | 221 : umodeis | ||
| 32 | 222 : sqline_nick # UnrealIrcd, Hendrik Frenzel | ||
| 33 | 223 : statsgline # UnrealIrcd, Hendrik Frenzel | ||
| 34 | 224 : statstline # UnrealIrcd, Hendrik Frenzel | ||
| 35 | 225 : statseline # UnrealIrcd, Hendrik Frenzel | ||
| 36 | 226 : statsnline # UnrealIrcd, Hendrik Frenzel | ||
| 37 | 227 : statsvline # UnrealIrcd, Hendrik Frenzel | ||
| 38 | 231 : serviceinfo | ||
| 39 | 232 : endofservices | ||
| 40 | 233 : service | ||
| 41 | 234 : servlist | ||
| 42 | 235 : servlistend | ||
| 43 | 241 : statslline | ||
| 44 | 242 : statsuptime | ||
| 45 | 243 : statsoline | ||
| 46 | 244 : statshline | ||
| 47 | 245 : statssline # Reserved, Kajetan@Hinner.com, 17/10/98 | ||
| 48 | 246 : statstline # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 49 | 247 : 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 | ||
| 52 | 248 : statsuline # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 53 | 249 : statsdebug # Unspecific Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 54 | 250 : luserconns # 1998-03-15 -- tkil | ||
| 55 | 251 : luserclient | ||
| 56 | 252 : luserop | ||
| 57 | 253 : luserunknown | ||
| 58 | 254 : luserchannels | ||
| 59 | 255 : luserme | ||
| 60 | 256 : adminme | ||
| 61 | 257 : adminloc1 | ||
| 62 | 258 : adminloc2 | ||
| 63 | 259 : adminemail | ||
| 64 | 261 : tracelog | ||
| 65 | 262 : endoftrace # 1997-11-24 -- archon | ||
| 66 | 265 : n_local # 1997-10-16 -- tkil | ||
| 67 | 266 : n_global # 1997-10-16 -- tkil | ||
| 68 | 271 : silelist # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 69 | 272 : endofsilelist # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 70 | 275 : statsdline # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 71 | 280 : glist # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 72 | 281 : endofglist # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 73 | 290 : helphdr # UnrealIrcd, Hendrik Frenzel | ||
| 74 | 291 : helpop # UnrealIrcd, Hendrik Frenzel | ||
| 75 | 292 : helptlr # UnrealIrcd, Hendrik Frenzel | ||
| 76 | 293 : helphlp # UnrealIrcd, Hendrik Frenzel | ||
| 77 | 294 : helpfwd # UnrealIrcd, Hendrik Frenzel | ||
| 78 | 295 : helpign # UnrealIrcd, Hendrik Frenzel | ||
| 79 | 300 : none | ||
| 80 | 301 : away | ||
| 81 | 302 : userhost | ||
| 82 | 303 : ison | ||
| 83 | 304 : rpl_text # Bahamut IRCD | ||
| 84 | 305 : unaway | ||
| 85 | 306 : nowaway | ||
| 86 | 307 : userip # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 87 | 308 : rulesstart # UnrealIrcd, Hendrik Frenzel | ||
| 88 | 309 : endofrules # UnrealIrcd, Hendrik Frenzel | ||
| 89 | 310 : whoishelp # (July01-01)Austnet Extension, found by Andypoo <andypoo@secret.com.au> | ||
| 90 | 311 : whoisuser | ||
| 91 | 312 : whoisserver | ||
| 92 | 313 : whoisoperator | ||
| 93 | 314 : whowasuser | ||
| 94 | 315 : endofwho | ||
| 95 | 316 : whoischanop | ||
| 96 | 317 : whoisidle | ||
| 97 | 318 : endofwhois | ||
| 98 | 319 : whoischannels | ||
| 99 | 320 : whoisvworld # (July01-01)Austnet Extension, found by Andypoo <andypoo@secret.com.au> | ||
| 100 | 321 : liststart | ||
| 101 | 322 : list | ||
| 102 | 323 : listend | ||
| 103 | 324 : channelmodeis | ||
| 104 | 329 : channelcreate # 1997-11-24 -- archon | ||
| 105 | 331 : notopic | ||
| 106 | 332 : topic | ||
| 107 | 333 : topicinfo # 1997-11-24 -- archon | ||
| 108 | 334 : listusage # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 109 | 335 : whoisbot # UnrealIrcd, Hendrik Frenzel | ||
| 110 | 341 : inviting | ||
| 111 | 342 : summoning | ||
| 112 | 346 : invitelist # UnrealIrcd, Hendrik Frenzel | ||
| 113 | 347 : endofinvitelist # UnrealIrcd, Hendrik Frenzel | ||
| 114 | 348 : exlist # UnrealIrcd, Hendrik Frenzel | ||
| 115 | 349 : endofexlist # UnrealIrcd, Hendrik Frenzel | ||
| 116 | 351 : version | ||
| 117 | 352 : whoreply | ||
| 118 | 353 : namreply | ||
| 119 | 354 : whospcrpl # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 120 | 361 : killdone | ||
| 121 | 362 : closing | ||
| 122 | 363 : closeend | ||
| 123 | 364 : links | ||
| 124 | 365 : endoflinks | ||
| 125 | 366 : endofnames | ||
| 126 | 367 : banlist | ||
| 127 | 368 : endofbanlist | ||
| 128 | 369 : endofwhowas | ||
| 129 | 371 : info | ||
| 130 | 372 : motd | ||
| 131 | 373 : infostart | ||
| 132 | 374 : endofinfo | ||
| 133 | 375 : motdstart | ||
| 134 | 376 : endofmotd | ||
| 135 | 377 : motd2 # 1997-10-16 -- tkil | ||
| 136 | 378 : austmotd # (July01-01)Austnet Extension, found by Andypoo <andypoo@secret.com.au> | ||
| 137 | 379 : whoismodes # UnrealIrcd, Hendrik Frenzel | ||
| 138 | 381 : youreoper | ||
| 139 | 382 : rehashing | ||
| 140 | 383 : youreservice # UnrealIrcd, Hendrik Frenzel | ||
| 141 | 384 : myportis | ||
| 142 | 385 : notoperanymore # Unspecific Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 143 | 386 : qlist # UnrealIrcd, Hendrik Frenzel | ||
| 144 | 387 : endofqlist # UnrealIrcd, Hendrik Frenzel | ||
| 145 | 388 : alist # UnrealIrcd, Hendrik Frenzel | ||
| 146 | 389 : endofalist # UnrealIrcd, Hendrik Frenzel | ||
| 147 | 391 : time | ||
| 148 | 392 : usersstart | ||
| 149 | 393 : users | ||
| 150 | 394 : endofusers | ||
| 151 | 395 : nousers | ||
| 152 | 401 : nosuchnick | ||
| 153 | 402 : nosuchserver | ||
| 154 | 403 : nosuchchannel | ||
| 155 | 404 : cannotsendtochan | ||
| 156 | 405 : toomanychannels | ||
| 157 | 406 : wasnosuchnick | ||
| 158 | 407 : toomanytargets | ||
| 159 | 408 : nosuchservice # UnrealIrcd, Hendrik Frenzel | ||
| 160 | 409 : noorigin | ||
| 161 | 411 : norecipient | ||
| 162 | 412 : notexttosend | ||
| 163 | 413 : notoplevel | ||
| 164 | 414 : wildtoplevel | ||
| 165 | 416 : querytoolong # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 166 | 421 : unknowncommand | ||
| 167 | 422 : nomotd | ||
| 168 | 423 : noadmininfo | ||
| 169 | 424 : fileerror | ||
| 170 | 425 : noopermotd # UnrealIrcd, Hendrik Frenzel | ||
| 171 | 431 : nonicknamegiven | ||
| 172 | 432 : erroneusnickname # This iz how its speld in thee RFC. | ||
| 173 | 433 : nicknameinuse | ||
| 174 | 434 : norules # UnrealIrcd, Hendrik Frenzel | ||
| 175 | 435 : serviceconfused # UnrealIrcd, Hendrik Frenzel | ||
| 176 | 436 : nickcollision | ||
| 177 | 437 : bannickchange # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 178 | 438 : nicktoofast # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 179 | 439 : targettoofast # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 180 | 440 : servicesdown # Bahamut IRCD | ||
| 181 | 441 : usernotinchannel | ||
| 182 | 442 : notonchannel | ||
| 183 | 443 : useronchannel | ||
| 184 | 444 : nologin | ||
| 185 | 445 : summondisabled | ||
| 186 | 446 : usersdisabled | ||
| 187 | 447 : nonickchange # UnrealIrcd, Hendrik Frenzel | ||
| 188 | 451 : notregistered | ||
| 189 | 455 : hostilename # UnrealIrcd, Hendrik Frenzel | ||
| 190 | 459 : nohiding # UnrealIrcd, Hendrik Frenzel | ||
| 191 | 460 : notforhalfops # UnrealIrcd, Hendrik Frenzel | ||
| 192 | 461 : needmoreparams | ||
| 193 | 462 : alreadyregistered | ||
| 194 | 463 : nopermforhost | ||
| 195 | 464 : passwdmismatch | ||
| 196 | 465 : yourebannedcreep # I love this one... | ||
| 197 | 466 : youwillbebanned | ||
| 198 | 467 : keyset | ||
| 199 | 468 : invalidusername # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 200 | 469 : linkset # UnrealIrcd, Hendrik Frenzel | ||
| 201 | 470 : linkchannel # UnrealIrcd, Hendrik Frenzel | ||
| 202 | 471 : channelisfull | ||
| 203 | 472 : unknownmode | ||
| 204 | 473 : inviteonlychan | ||
| 205 | 474 : bannedfromchan | ||
| 206 | 475 : badchannelkey | ||
| 207 | 476 : badchanmask | ||
| 208 | 477 : needreggednick # Bahamut IRCD | ||
| 209 | 478 : banlistfull # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 210 | 479 : secureonlychannel # pircd | ||
| 211 | ### TODO: see above todo | ||
| 212 | ### 479 : linkfail # UnrealIrcd, Hendrik Frenzel | ||
| 213 | 480 : cannotknock # UnrealIrcd, Hendrik Frenzel | ||
| 214 | 481 : noprivileges | ||
| 215 | 482 : chanoprivsneeded | ||
| 216 | 483 : cantkillserver | ||
| 217 | 484 : ischanservice # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 218 | 485 : killdeny # UnrealIrcd, Hendrik Frenzel | ||
| 219 | 486 : htmdisabled # UnrealIrcd, Hendrik Frenzel | ||
| 220 | 489 : secureonlychan # UnrealIrcd, Hendrik Frenzel | ||
| 221 | 491 : nooperhost | ||
| 222 | 492 : noservicehost | ||
| 223 | 501 : umodeunknownflag | ||
| 224 | 502 : usersdontmatch | ||
| 225 | 511 : silelistfull # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 226 | 513 : nosuchgline # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 227 | 513 : badping # Undernet Extension, Kajetan@Hinner.com, 17/10/98 | ||
| 228 | 518 : noinvite # UnrealIrcd, Hendrik Frenzel | ||
| 229 | 519 : admonly # UnrealIrcd, Hendrik Frenzel | ||
| 230 | 520 : operonly # UnrealIrcd, Hendrik Frenzel | ||
| 231 | 521 : listsyntax # UnrealIrcd, Hendrik Frenzel | ||
| 232 | 524 : operspverify # UnrealIrcd, Hendrik Frenzel | ||
| 233 | |||
| 234 | 600 : rpl_logon # Bahamut IRCD | ||
| 235 | 601 : rpl_logoff # Bahamut IRCD | ||
| 236 | 602 : rpl_watchoff # UnrealIrcd, Hendrik Frenzel | ||
| 237 | 603 : rpl_watchstat # UnrealIrcd, Hendrik Frenzel | ||
| 238 | 604 : rpl_nowon # Bahamut IRCD | ||
| 239 | 605 : rpl_nowoff # Bahamut IRCD | ||
| 240 | 606 : rpl_watchlist # UnrealIrcd, Hendrik Frenzel | ||
| 241 | 607 : rpl_endofwatchlist # UnrealIrcd, Hendrik Frenzel | ||
| 242 | 610 : mapmore # UnrealIrcd, Hendrik Frenzel | ||
| 243 | 640 : rpl_dumping # UnrealIrcd, Hendrik Frenzel | ||
| 244 | 641 : rpl_dumprpl # UnrealIrcd, Hendrik Frenzel | ||
| 245 | 642 : rpl_eodump # UnrealIrcd, Hendrik Frenzel | ||
| 246 | |||
| 247 | 999 : numericerror # Bahamut IRCD |

