Class: Cinch::IRC
Overview
This class manages the connection to the IRC server. That includes processing incoming and outgoing messages, creating Ruby objects and invoking plugins.
Instance Attribute Summary (collapse)
-
- (Bot) bot
readonly
-
- (ISupport) isupport
readonly
-
- (Network) network
readonly
The detected network.
Instance Method Summary (collapse)
-
- (Boolean) connect
private
True if the connection could be established.
-
- (IRC) initialize(bot)
constructor
A new instance of IRC.
-
- parse(input)
private
-
- (Boolean) registered?
True if we successfully registered yet.
-
- send(msg)
Send a message to the server.
-
- send_cap_end
private
-
- send_cap_ls
private
-
- send_cap_req
private
-
- send_login
private
-
- (Object) send_sasl
-
- setup
private
-
- setup_ssl(socket)
private
-
- (TCPSocket) socket
private
-
- start
Establish a connection.
-
- (Thread) start_ping_thread
private
The ping thread.
-
- (Thread) start_reading_thread
private
The reading thread.
-
- (Thread) start_sending_thread
private
The sending thread.
Methods included from Helpers
#Channel, #Format, #Target, #Timer, #User, #debug, #error, #exception, #fatal, #incoming, #info, #log, #outgoing, #rescue_exception, #warn
Constructor Details
- (IRC) initialize(bot)
A new instance of IRC
21 22 23 24 |
# File 'lib/cinch/irc.rb', line 21 def initialize(bot) @bot = bot @isupport = ISupport.new end |
Instance Attribute Details
- (ISupport) isupport (readonly)
13 14 15 |
# File 'lib/cinch/irc.rb', line 13 def isupport @isupport end |
- (Network) network (readonly)
The detected network
19 20 21 |
# File 'lib/cinch/irc.rb', line 19 def network @network end |
Instance Method Details
- (Boolean) connect
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
True if the connection could be established
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/cinch/irc.rb', line 45 def connect tcp_socket = nil begin Timeout::timeout(@bot.config.timeouts.connect) do tcp_socket = TCPSocket.new(@bot.config.server, @bot.config.port, @bot.config.local_host) end rescue Timeout::Error @bot.loggers.warn("Timed out while connecting") return false rescue SocketError => e @bot.loggers.warn("Could not connect to the IRC server. Please check your network: #{e.}") return false rescue => e @bot.loggers.exception(e) return false end if @bot.config.ssl.use setup_ssl(tcp_socket) else @socket = tcp_socket end @socket = Net::BufferedIO.new(@socket) @socket.read_timeout = @bot.config.timeouts.read @queue = MessageQueue.new(@socket, @bot) return true end |
- parse(input)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/cinch/irc.rb', line 221 def parse(input) return if input.chomp.empty? @bot.loggers.incoming(input) msg = Message.new(input, @bot) events = [[:catchall]] if ("001".."004").include? msg.command @registration << msg.command if registered? events << [:connect] @bot.last_connection_was_successful = true on_connect(msg, events) end end if ["PRIVMSG", "NOTICE"].include?(msg.command) events << [:ctcp] if msg.ctcp? if msg.channel? events << [:channel] else events << [:private] end if msg.command == "PRIVMSG" events << [:message] end if msg.action? events << [:action] end end meth = "on_#{msg.command.downcase}" __send__(meth, msg, events) if respond_to?(meth, true) if msg.error? events << [:error] end events << [msg.command.downcase.to_sym] msg.events = events.map(&:first) events.each do |event, *args| @bot.handlers.dispatch(event, msg, *args) end end |
- (Boolean) registered?
True if we successfully registered yet
270 271 272 |
# File 'lib/cinch/irc.rb', line 270 def registered? (("001".."004").to_a - @registration).empty? end |
- send(msg)
This method returns an undefined value.
Send a message to the server.
277 278 279 |
# File 'lib/cinch/irc.rb', line 277 def send(msg) @queue.queue(msg) end |
- send_cap_end
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
121 122 123 |
# File 'lib/cinch/irc.rb', line 121 def send_cap_end send "CAP END" end |
- send_cap_ls
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
107 108 109 |
# File 'lib/cinch/irc.rb', line 107 def send_cap_ls send "CAP LS" end |
- send_cap_req
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
114 115 116 |
# File 'lib/cinch/irc.rb', line 114 def send_cap_req send "CAP REQ :" + ([:away-notify", :multi-prefix", :sasl] & @network.capabilities).join(" ") end |
- send_login
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
128 129 130 131 132 |
# File 'lib/cinch/irc.rb', line 128 def send_login send "PASS #{@bot.config.password}" if @bot.config.password send "NICK #{@bot.generate_next_nick!}" send "USER #{@bot.config.user} 0 * :#{@bot.config.realname}" end |
- (Object) send_sasl
189 190 191 192 193 194 195 196 |
# File 'lib/cinch/irc.rb', line 189 def send_sasl if @bot.config.sasl.username && @sasl_current_method = @sasl_remaining_methods.pop @bot.loggers.info "[SASL] Trying to authenticate with #{@sasl_current_method.mechanism_name}" send "AUTHENTICATE #{@sasl_current_method.mechanism_name}" else send_cap_end end end |
- setup
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
36 37 38 39 40 41 |
# File 'lib/cinch/irc.rb', line 36 def setup @registration = [] @network = Network.new(:unknown, :unknown) @whois_updates = Hash.new {|h, k| h[k] = {}} @in_lists = Set.new end |
- setup_ssl(socket)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/cinch/irc.rb', line 79 def setup_ssl(socket) # require openssl in this method so the bot doesn't break for # people who don't have SSL but don't want to use SSL anyway. require 'openssl' ssl_context = OpenSSL::SSL::SSLContext.new if @bot.config.ssl.is_a?(Configuration::SSL) if @bot.config.ssl.client_cert ssl_context.cert = OpenSSL::X509::Certificate.new(File.read(@bot.config.ssl.client_cert)) ssl_context.key = OpenSSL::PKey::RSA.new(File.read(@bot.config.ssl.client_cert)) end ssl_context.ca_path = @bot.config.ssl.ca_path ssl_context.verify_mode = @bot.config.ssl.verify ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE else ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE end @bot.loggers.info "Using SSL with #{@bot.config.server}:#{@bot.config.port}" @socket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context) @socket.sync = true @socket.connect end |
- (TCPSocket) socket
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
29 30 31 |
# File 'lib/cinch/irc.rb', line 29 def socket @socket.io end |
- start
This method returns an undefined value.
Establish a connection.
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/cinch/irc.rb', line 202 def start setup if connect @sasl_remaining_methods = [SASL::Plain, SASL::DH_Blowfish] send_cap_ls send_login reading_thread = start_reading_thread sending_thread = start_sending_thread ping_thread = start_ping_thread reading_thread.join sending_thread.kill ping_thread.kill end end |
- (Thread) start_ping_thread
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The ping thread.
177 178 179 180 181 182 183 184 185 186 |
# File 'lib/cinch/irc.rb', line 177 def start_ping_thread Thread.new do while true sleep @bot.config.ping_interval # PING requires a single argument. In our case the value # doesn't matter though. send("PING 0") end end end |
- (Thread) start_reading_thread
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The reading thread
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/cinch/irc.rb', line 137 def start_reading_thread Thread.new do begin while line = @socket.readline rescue_exception do line = Cinch::Utilities::Encoding.encode_incoming(line, @bot.config.encoding) parse line end end rescue Timeout::Error @bot.loggers.warn "Connection timed out." rescue EOFError @bot.loggers.warn "Lost connection." rescue => e @bot.loggers.exception(e) end @socket.close @bot.handlers.dispatch(:disconnect) # FIXME won't we kill all :disconnect handlers here? prolly # not, as they have 10 seconds to finish. that should be # plenty of time @bot.handlers.stop_all end end |
- (Thread) start_sending_thread
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
The sending thread
166 167 168 169 170 171 172 |
# File 'lib/cinch/irc.rb', line 166 def start_sending_thread Thread.new do rescue_exception do @queue.process! end end end |