class Syndi::IRC::Server
A class which maintains a connection to an IRC
server and provides a highly usable interface for the IRC
server.
@api IRC
@since 4.0.0 @author noxgirl
@!attribute [r] socket
@return [TCPSocket] The TCP socket being used for the connection.
@!attribute [r] in
@return [Integer] The number of bytes received from the socket.
@!attribute [r] out
@return [Integer] The number of bytes sent to the socket.
@!attribute [r] type
@return [Symbol] +:irc+
@!attribute [r] supp
@return [Syndi::IRC::State::Support] The IRCd capabilities.
@!attribute name
@return [String] The name of the server as specified by configuration.
@!attribute address
@return [String] The address used to connect to the server.
@!attribute port
@return [Integer] The port used to connect to the server
@!attribute nick
@return [String] The nickname of the bot on the server.
@!attribute user
@return [String] The username of the bot on the server.
@!attribute real
@return [String] The real name or GECOS of the bot on the server.
@!attribute password
@return [String] If needed, the password used to connect to the server @return [nil] If not needed.
@!attribute bind
@return [String] If desired, the address to which to bind for this socket @return [nil] If not desired. @note This appears to be unused at the moment.
@!attribute ssl
@return [true, false] If SSL should [not] be used for the connection.
@!attribute sasl_id
@return [String] If SASL is desired, the username with which to authenticate. @return [nil] If not used. @note This is seemingly deprecated?
@!attribute connected
@return [true, false] Whether or not we are connected to the server.
@!attribute mask
@return [String] The bot's own hostname or mask on the IRC server.
@!attribute recvq
@return [Array<String>] The socket's receive queue, which is comprised of an array of strings which are pending processing. @!attribute prefixes @return [Hash{String => String}] The IRC server's supported prefixes, with the key being the channel mode which represents the prefix, and the value being the prefix.
@!attribute channel_modes
@return [Hash{Symbol => Array<String>}] The IRC server's supported channel modes, divided as thus: - +:list+ = A list of modes which add/remove a nickname or mask from a channel list, such as ops and bans. - +:always+ = A llst of modes which change a channel setting, and always have a parameter. - +:set+ = A list of modes which change a channel setting, and which have a parameter only when set. - +:never+ = A list of modes which change a channel setting, and which never have a parameter.
@!attribute max_modes
@return [Integer] The maximum number of mode changes which may be specified in a /MODE query.
@!attribute await_self_who
@return [true, false] Whether or not we are awaiting for a response to a /WHO on ourselves.
@!attribute channels
@return [Hash{String => IRC::Object::Channel}] A list of channels in which we reside, with each key being the channel's name in all-lowercase, and the respective values being of {IRC::Object::Channel IRC::Object::Channel}.
@!attribute users
@return [Hash{String => IRC::Object::User}] A list of users who are known to us, with each key being the user's nickname in all-lowercase, and the respective values being of {IRC::Object::User IRC::Object::User}.
Attributes
Public Class Methods
Produce a new instance of {Syndi::IRC::Server}.
@param [String] name The name of the server to which we should connect.
@yieldparam [Syndi::IRC::Server] c This instance, intended for configuration of the
attributes.
Configuration attributes are address
, port
, nick
, user
, real
, password
, bind
, and ssl
.
@example
irc = Syndi::IRC::Server.new('Freenode') do |c| c.address = 'irc.freenode.net' c.port = 7000 c.nick = 'cowmoon' c.user = 'foo1' c.real = "The night is lovely." c.bind = 'localhost' c.ssl = true end
# File lib/syndi/irc/server.rb, line 141 def initialize(name) # Prepare attributes. @name = name @address = nil @port = nil @nick = nil @user = nil @real = nil @password = nil @bind = nil @ssl = false # Yield for configuration. yield(self) if block_given? or raise ArgumentError, "Server #{name} unable to initialize because it was not configured." # Additional instance attributes. @in = 0 @out = 0 @socket = nil @connected = false @type = :irc # Pull in commands. extend Syndi::IRC::Std::Commands # State managers. @supp = Syndi::IRC::State::Support.new @chans = nil @users = nil # Our receive queue remainder. @recv_rem = nil # Mutual exclusion for thread safety. @lock = Mutex.new end
Public Instance Methods
Establish (or attempt to) a connection with the server.
# File lib/syndi/irc/server.rb, line 180 def connect # Check for missing attributes. begin attribute_check rescue => e $m.error("Cannot connect to server #@name: #{e}", false, e.backtrace) end $m.info("Connecting to #@name @ #@address:#@port...") # Create a new socket. begin socket = TCPSocket.new(@address, @port, @bind) rescue => e $m.error("Failed to connect to server #@name: #{e}", false, e.backtrace) raise end # Wrap it in SSL if told to. if ssl begin socket = OpenSSL::SSL::SSLSocket.new(socket) socket.connect rescue => e $m.error("Failed to connect to server #@name: #{e}", false, e.backtrace) raise end end @socket = socket # Register. emit :irc, :preconnect, self pass @password if @password snd 'CAP LS' self.nickname = @nick user @user, Socket.gethostname, @address, @real end
# File lib/syndi/irc/server.rb, line 270 def inspect; "#<Syndi::IRC::Server: name='#@name'>"; end
Receive data from the socket, and push it into the recvQ.
# File lib/syndi/irc/server.rb, line 231 def recv # Thread safety. @lock.synchronize do if @socket.nil? or @socket.eof? return end # Read the data. data = @socket.sysread(1024) # Increase in. @in += data.length # Split the data. recv = [] until data !~ /\r\n/ line, data = data.split(/(?<=\r\n)/, 2) recv.push line.chomp "\r\n" end # Check if there's a remainder in the recvQ. if @recv_rem != '' recv[0] = "#@recv_rem#{recv[0]}" @recv_rem = '' end @recv_rem = data if data != '' # Lastly, sent the data out recv.each do |dline| $m.foreground("{irc-recv} #@name >> #{dline}") emit :irc, :receive, self, dline # send it out to :receive end end end
Send data to the socket.
@param [String] data The string of data, which should not exceed 512 in length.
# File lib/syndi/irc/server.rb, line 224 def snd data $m.foreground("{irc-send} #@name << #{data}") @socket.write("#{data}\r\n") @out += "#{data}\r\n".length end
# File lib/syndi/irc/server.rb, line 269 def to_s; @name; end
Private Instance Methods
Check the presence of all attributes.
# File lib/syndi/irc/server.rb, line 278 def attribute_check raise(ConfigError, "Missing server address") unless @address raise(ConfigError, "Missing server port") unless @port raise(ConfigError, "Missing nickname to use") unless @nick raise(ConfigError, "Missing username to use") unless @user raise(ConfigError, "Missing realname to use") unless @real end
Check if we are connected.
@return [true, false]
# File lib/syndi/irc/server.rb, line 289 def connected? return false unless @socket return false unless @connected true end