class Cinch::IRC

This class manages the connection to the IRC server. That includes processing incoming and outgoing messages, creating Ruby objects and invoking plugins.

Attributes

bot[R]

@return [Bot]

isupport[R]

@return [ISupport]

network[R]

@return [Network] The detected network

Public Class Methods

new(bot) click to toggle source
# File lib/cinch/irc.rb, line 21
def initialize(bot)
  @bot      = bot
  @isupport = ISupport.new
end

Public Instance Methods

connect() click to toggle source

@api private @return [Boolean] True if the connection could be established

# 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.message}")
    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) click to toggle source

@api private @return [void]

# 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
registered?() click to toggle source

@return [Boolean] true if we successfully registered yet

# File lib/cinch/irc.rb, line 270
def registered?
  (("001".."004").to_a - @registration).empty?
end
send(msg) click to toggle source

Send a message to the server. @param [String] msg @return [void]

# File lib/cinch/irc.rb, line 277
def send(msg)
  @queue.queue(msg)
end
send_cap_end() click to toggle source

@since 2.0.0 @api private @return [void]

# File lib/cinch/irc.rb, line 121
def send_cap_end
  send "CAP END"
end
send_cap_ls() click to toggle source

@api private @return [void] @since 2.0.0

# File lib/cinch/irc.rb, line 107
def send_cap_ls
  send "CAP LS"
end
send_cap_req() click to toggle source

@api private @return [void] @since 2.0.0

# 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() click to toggle source

@api private @return [void] @since 2.0.0

# 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
send_sasl() click to toggle source

@since 2.0.0

# 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() click to toggle source

@api private @return [void] @since 2.0.0

# 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) click to toggle source

@api private @return [void] @since 2.0.0

# 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
socket() click to toggle source

@return [TCPSocket] @api private @since 2.0.0

# File lib/cinch/irc.rb, line 29
def socket
  @socket.io
end
start() click to toggle source

Establish a connection.

@return [void] @since 2.0.0

# 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
start_ping_thread() click to toggle source

@api private @return [Thread] The ping thread. @since 2.0.0

# 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
start_reading_thread() click to toggle source

@api private @return [Thread] the reading thread @since 2.0.0

# 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
start_sending_thread() click to toggle source

@api private @return [Thread] the sending thread @since 2.0.0

# File lib/cinch/irc.rb, line 166
def start_sending_thread
  Thread.new do
    rescue_exception do
      @queue.process!
    end
  end
end

Private Instance Methods

detect_network(msg, event) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 287
def detect_network(msg, event)
  old_network = @network
  new_network = nil
  new_ircd    = nil
  case event
  when "002"
    if msg.params.last =~ /^Your host is .+?, running version (.+)$/
      case $1
      when /\+snircd\(/
        new_ircd = :snircd
      when /^u[\d\.]+$/
        new_ircd = :ircu
      when /^(.+?)-?\d+/
        new_ircd = $1.downcase.to_sym
      end
    elsif msg.params.last == "Your host is jtvchat"
      new_network = :jtv
      new_ircd    = :jtv
    end
  when "005"
    case @isupport["NETWORK"]
    when "NGameTV"
      new_network = :ngametv
      new_ircd    = :ngametv
    when nil
    else
      new_network = @isupport["NETWORK"].downcase.to_sym
    end
  end

  new_network ||= old_network.name
  new_ircd    ||= old_network.ircd

  if old_network.unknown_ircd? && new_ircd != :unknown
    @bot.loggers.info "Detected IRCd: #{new_ircd}"
  end
  if !old_network.unknown_ircd? && new_ircd != old_network.ircd
    @bot.loggers.info "Detected different IRCd: #{old_network.ircd} -> #{new_ircd}"
  end
  if old_network.unknown_network? && new_network != :unknown
    @bot.loggers.info "Detected network: #{new_network}"
  end
  if !old_network.unknown_network? && new_network != old_network.name
    @bot.loggers.info "Detected different network: #{old_network.name} -> #{new_network}"
  end

  @network.name = new_network
  @network.ircd = new_ircd
end
on_001(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 566
def on_001(msg, events)
  # Ensure that we know our real, possibly truncated or otherwise
  # modified nick.
  @bot.set_nick msg.params.first
end
on_002(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 573
def on_002(msg, events)
  detect_network(msg, "002")
end
on_005(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 577
def on_005(msg, events)
  # ISUPPORT
  @isupport.parse(*msg.params[1..-2].map {|v| v.split(" ")}.flatten)
  detect_network(msg, "005")
end
on_301(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 584
def on_301(msg, events)
  # RPL_AWAY
  user = User(msg.params.first)
  away = msg.message

  if @whois_updates[user]
    @whois_updates[user].merge!({:away => away})
  end
end
on_307(msg, events) click to toggle source

@since 1.1.0

# File lib/cinch/irc.rb, line 595
def on_307(msg, events)
  # RPL_WHOISREGNICK
  user = User(msg.params[1])
  @whois_updates[user].merge!({:authname => user.nick})
end
on_311(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 601
def on_311(msg, events)
  # RPL_WHOISUSER
  user = User(msg.params[1])
  @whois_updates[user].merge!({
                                :user => msg.params[2],
                                :host => msg.params[3],
                                :realname => msg.params[5],
                              })
end
on_317(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 611
def on_317(msg, events)
  # RPL_WHOISIDLE
  user = User(msg.params[1])
  @whois_updates[user].merge!({
                                :idle => msg.params[2].to_i,
                                :signed_on_at => Time.at(msg.params[3].to_i),
                              })
end
on_318(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 620
def on_318(msg, events)
  # RPL_ENDOFWHOIS
  user = User(msg.params[1])

  if @whois_updates[user].empty? && !user.attr(:unknown?, true, true)
    user.end_of_whois(nil)
  else
    user.end_of_whois(@whois_updates[user])
    @whois_updates.delete user
  end
end
on_319(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 632
def on_319(msg, events)
  # RPL_WHOISCHANNELS
  user     = User(msg.params[1])
  channels = msg.params[2].scan(/#{@isupport["CHANTYPES"].join}[^ ]+/).map {|c| Channel(c) }
  user.sync(:channels, channels, true)
end
on_324(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 639
def on_324(msg, events)
  # RPL_CHANNELMODEIS
  modes     = {}
  arguments = msg.params[3..-1]

  msg.params[2][1..-1].split("").each do |mode|
    if (@isupport["CHANMODES"]["B"] + @isupport["CHANMODES"]["C"]).include?(mode)
      modes[mode] = arguments.shift
    else
      modes[mode] = true
    end
  end

  msg.channel.sync(:modes, modes, false)
end
on_330(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 655
def on_330(msg, events)
  # RPL_WHOISACCOUNT
  user     = User(msg.params[1])
  authname = msg.params[2]

  @whois_updates[user].merge!({:authname => authname})
end
on_331(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 663
def on_331(msg, events)
  # RPL_NOTOPIC
  msg.channel.sync(:topic, "")
end
on_332(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 668
def on_332(msg, events)
  # RPL_TOPIC
  msg.channel.sync(:topic, msg.params[2])
end
on_352(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 673
def on_352(msg, events)
  # RPL_WHOREPLY
  # "<channel> <user> <host> <server> <nick> <H|G>[*][@|+] :<hopcount> <real name>"
  _, channel, user, host, _, nick, _, hopsrealname = msg.params
  _, realname = hopsrealname.split(" ", 2)
  channel     = Channel(channel)
  user_object = User(nick)
  user_object.sync(:user, user, true)
  user_object.sync(:host, host, true)
  user_object.sync(:realname, realname, true)
end
on_353(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 704
def on_353(msg, events)
  # RPL_NAMEREPLY
  unless @in_lists.include?(:names)
    msg.channel.clear_users
  end
  @in_lists << :names

  msg.params[3].split(" ").each do |user|
    m = user.match(/^([#{@isupport["PREFIX"].values.join}]+)/)
    if m
      prefixes = m[1].split("").map {|s| @isupport["PREFIX"].key(s)}
      nick   = user[prefixes.size..-1]
    else
      nick   = user
      prefixes = []
    end
    user        = User(nick)
    user.online = true
    msg.channel.add_user(user, prefixes)
    user.channels_unsynced << msg.channel unless user.channels_unsynced.include?(msg.channel)
  end
end
on_354(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 685
def on_354(msg, events)
  # RPL_WHOSPCRPL
  # We are using the following format: %acfhnru

  #                          _         user      host                                 nick      f account  realame
  # :leguin.freenode.net 354 dominikh_ ~a        ip-88-152-125-117.unitymediagroup.de dominikh_ H 0        :d
  # :leguin.freenode.net 354 dominikh_ ~FiXato   fixato.net                           FiXato    H FiXato   :FiXato, using WeeChat -- More? See: http://twitter
  # :leguin.freenode.net 354 dominikh_ ~dominikh cinch/developer/dominikh             dominikh  H DominikH :dominikh
  # :leguin.freenode.net 354 dominikh_ ~oddmunds s21-04214.dsl.no.powertech.net       oddmunds  H 0        :oddmunds

  _, channel, user, host, nick, _, account, realname = msg.params
  channel = Channel(channel)
  user_object = User(nick)
  user_object.sync(:user, user, true)
  user_object.sync(:host, host, true)
  user_object.sync(:realname, realname, true)
  user_object.sync(:authname, account == "0" ? nil : account, true)
end
on_366(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 727
def on_366(msg, events)
  # RPL_ENDOFNAMES
  @in_lists.delete :names
  msg.channel.mark_as_synced(:users)
end
on_367(msg, events) click to toggle source

@version 2.0.0

# File lib/cinch/irc.rb, line 734
def on_367(msg, events)
  # RPL_BANLIST
  unless @in_lists.include?(:bans)
    msg.channel.bans_unsynced.clear
  end
  @in_lists << :bans

  mask = msg.params[2]
  if @network.jtv?
    # on the justin tv network, ban "masks" only consist of the
    # nick/username
    mask = "%s!%s@%s" % [mask, mask, mask + ".irc.justin.tv"]
  end

  if msg.params[3]
    by = User(msg.params[3].split("!").first)
  else
    by = nil
  end

  at  = Time.at(msg.params[4].to_i)
  ban = Ban.new(mask, by, at)
  msg.channel.bans_unsynced << ban
end
on_368(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 759
def on_368(msg, events)
  # RPL_ENDOFBANLIST
  if @in_lists.include?(:bans)
    @in_lists.delete :bans
  else
    # we never received a ban, yet an end of list => no bans
    msg.channel.bans_unsynced.clear
  end

  msg.channel.mark_as_synced(:bans)
end
on_386(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 771
def on_386(msg, events)
  # RPL_QLIST
  unless @in_lists.include?(:owners)
    msg.channel.owners_unsynced.clear
  end
  @in_lists << :owners

  owner = User(msg.params[2])
  msg.channel.owners_unsynced << owner
end
on_387(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 782
def on_387(msg, events)
  # RPL_ENDOFQLIST
  if @in_lists.include?(:owners)
    @in_lists.delete :owners
  else
    #we never received an owner, yet an end of list -> no owners
    msg.channel.owners_unsynced.clear
  end

  msg.channel.mark_as_synced(:owners)
end
on_396(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 794
def on_396(msg, events)
  # RPL_HOSTHIDDEN
  # note: designed for freenode
  User(msg.params[0]).sync(:host, msg.params[1], true)
end
on_401(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 800
def on_401(msg, events)
  # ERR_NOSUCHNICK
  user = User(msg.params[1])
  user.sync(:unknown?, true, true)
  msg.user.online = false
  if @whois_updates.key?(user)
    user.end_of_whois(nil, true)
    @whois_updates.delete user
  end
end
on_402(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 811
def on_402(msg, events)
  # ERR_NOSUCHSERVER

  if user = @bot.user_list.find(msg.params[1]) # not _ensured, we only want a user that already exists
    user.end_of_whois(nil, true)
    @whois_updates.delete user
    # TODO freenode specific, test on other IRCd
  end
end
on_433(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 821
def on_433(msg, events)
  # ERR_NICKNAMEINUSE
  @bot.nick = @bot.generate_next_nick!(msg.params[1])
end
on_671(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 826
def on_671(msg, events)
  user = User(msg.params[1])
  @whois_updates[user].merge!({:secure? => true})
end
on_730(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 832
def on_730(msg, events)
  # RPL_MONONLINE
  msg.params.last.split(",").each do |mask|
    user = User(Mask.new(mask).nick)
    # User is responsible for emitting an event
    user.online = true
  end
end
on_731(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 842
def on_731(msg, events)
  # RPL_MONOFFLINE
  msg.params.last.split(",").each do |nick|
    user = User(nick)
    # User is responsible for emitting an event
    user.online = false
  end
end
on_734(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 852
def on_734(msg, events)
  # ERR_MONLISTFULL
  user = User(msg.params[2])
  user.monitored = false
end
on_903(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 859
def on_903(msg, events)
  # SASL authentication successful
  @bot.loggers.info "[SASL] SASL authentication with #{@sasl_current_method.mechanism_name} successful"
  send_cap_end
end
on_904(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 866
def on_904(msg, events)
  # SASL authentication failed
  @bot.loggers.info "[SASL] SASL authentication with #{@sasl_current_method.mechanism_name} failed"
  send_sasl
end
on_authenticate(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 873
def on_authenticate(msg, events)
  send "AUTHENTICATE " + @sasl_current_method.generate(@bot.config.sasl.username,
                                                       @bot.config.sasl.password,
                                                       msg.params.last)
end
on_away(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 362
def on_away(msg, events)
  if msg.message.to_s.empty?
    # unaway
    m.user.sync(:away, nil, true)
    events << [:unaway]
  else
    # away
    m.user.sync(:away, msg.message, true)
    events << [:away]
  end
end
on_cap(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 375
def on_cap(msg, events)
  case msg.params[1]
  when "LS"
    @network.capabilities.concat msg.message.split(" ").map(&:to_sym)
    send_cap_req
  when "ACK"
    if @network.capabilities.include?(:sasl)
      send_sasl
    else
      send_cap_end
    end
  when "NACK"
    send_cap_end
  end
end
on_connect(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 392
def on_connect(msg, events)
  @bot.modes = @bot.config.modes
end
on_join(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 396
def on_join(msg, events)
  if msg.user == @bot
    @bot.channels << msg.channel
    msg.channel.sync_modes
  end
  msg.channel.add_user(msg.user)
  msg.user.online = true
end
on_kick(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 405
def on_kick(msg, events)
  target = User(msg.params[1])
  if target == @bot
    @bot.channels.delete(msg.channel)
  end
  msg.channel.remove_user(target)

  set_leaving_user(msg, target, events)
end
on_kill(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 415
def on_kill(msg, events)
  user = User(msg.params[1])

  @bot.channel_list.each do |channel|
    channel.remove_user(user)
  end

  user.unsync_all
  user.online = false

  set_leaving_user(msg, user, events)
end
on_mode(msg, events) click to toggle source

@version 1.1.0

# File lib/cinch/irc.rb, line 429
def on_mode(msg, events)
  if msg.channel?
    add_and_remove = @bot.irc.isupport["CHANMODES"]["A"] + @bot.irc.isupport["CHANMODES"]["B"] + @bot.irc.isupport["PREFIX"].keys

    param_modes = {
      :add    => @bot.irc.isupport["CHANMODES"]["C"] + add_and_remove,
      :remove => add_and_remove
    }

    modes = ModeParser.parse_modes(msg.params[1], msg.params[2..-1], param_modes)
    modes.each do |direction, mode, param|
      if @bot.irc.isupport["PREFIX"].keys.include?(mode)
        target = User(param)

        # (un)set a user-mode
        if direction == :add
          msg.channel.users[target] << mode unless msg.channel.users[User(param)].include?(mode)
        else
          msg.channel.users[target].delete mode
        end

        user_events = {
          "o" => "op",
          "v" => "voice",
          "h" => "halfop"
        }
        if user_events.has_key?(mode)
          event = (direction == :add ? "" : "de") + user_events[mode]
          events << [event.to_sym, target]
        end
      elsif @bot.irc.isupport["CHANMODES"]["A"].include?(mode)
        case mode
        when "b"
          process_ban_mode(msg, events, param, direction)
        when "q"
          process_owner_mode(msg, events, param, direction) if @network.owner_list_mode
        else
          raise Exceptions::UnsupportedMode, mode
        end
      else
        # channel options
        if direction == :add
          msg.channel.modes_unsynced[mode] = param.nil? ? true : param
        else
          msg.channel.modes_unsynced.delete(mode)
        end
      end
    end

    events << [:mode_change, modes]
  elsif msg.params.first == bot.nick
    modes = ModeParser.parse_modes(msg.params[1], msg.params[2..-1])
    modes.each do |direction, mode, _|
      if direction == :add
        @bot.modes << mode
      else
        @bot.modes.delete(mode)
      end
    end
  end
end
on_nick(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 491
def on_nick(msg, events)
  if msg.user == @bot
    # @bot.set_nick msg.params.last
    target = @bot
  else
    target = msg.user
  end

  target.update_nick(msg.params.last)
  target.online = true
end
on_part(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 503
def on_part(msg, events)
  msg.channel.remove_user(msg.user)
  msg.user.channels_unsynced.delete msg.channel

  if msg.user == @bot
    @bot.channels.delete(msg.channel)
  end

  set_leaving_user(msg, msg.user, events)
end
on_ping(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 514
def on_ping(msg, events)
  send "PONG :#{msg.params.first}"
end
on_privmsg(msg, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 541
def on_privmsg(msg, events)
  if msg.user
    msg.user.online = true
  end


  if msg.message =~ /^\001DCC SEND (?:"([^"]+)"|(\S+)) (\d+) (\d+)(?: (\d+))?\001$/
    process_dcc_send($1 || $2, $3, $4, $5, msg, events)
  end
end
on_quit(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 522
def on_quit(msg, events)
  @bot.channel_list.each do |channel|
    channel.remove_user(msg.user)
  end
  msg.user.unsync_all
  msg.user.online = false

  set_leaving_user(msg, msg.user, events)

  if msg.message.downcase == "excess flood" && msg.user == @bot
    @bot.warn ["Looks like your bot has been kicked because of excess flood.",
                "If you haven't modified the throttling options manually, please file a bug report at https://github.com/cinchrb/cinch/issues and include the following information:",
                "- Server: #{@bot.config.server}",
                "- Messages per second: #{@bot.config.messages_per_second}",
                "- Server queue size: #{@bot.config.server_queue_size}"]
  end
end
on_topic(msg, events) click to toggle source
# File lib/cinch/irc.rb, line 518
def on_topic(msg, events)
  msg.channel.sync(:topic, msg.params[1])
end
process_ban_mode(msg, events, param, direction) click to toggle source
# File lib/cinch/irc.rb, line 337
def process_ban_mode(msg, events, param, direction)
  mask = param
  ban = Ban.new(mask, msg.user, Time.now)

  if direction == :add
    msg.channel.bans_unsynced << ban
    events << [:ban, ban]
  else
    msg.channel.bans_unsynced.delete_if {|b| b.mask == ban.mask}.first
    events << [:unban, ban]
  end
end
process_dcc_send(filename, ip, port, size, m, events) click to toggle source

@since 2.0.0

# File lib/cinch/irc.rb, line 553
def process_dcc_send(filename, ip, port, size, m, events)
  ip   = ip.to_i
  ip   = [24, 16, 8, 0].collect {|b| (ip >> b) & 255}.join('.')
  port = port.to_i
  size = size.to_i

  @bot.loggers.info "DCC: Incoming DCC SEND: File name: %s - Size: %dB - IP: %s - Port: %d" % [filename, size, ip, port]

  dcc = DCC::Incoming::Send.new(user: m.user, filename: filename, size: size, ip: ip, port: port)
  events << [:dcc_send, dcc]
end
process_owner_mode(msg, events, param, direction) click to toggle source
# File lib/cinch/irc.rb, line 350
def process_owner_mode(msg, events, param, direction)
  owner = User(param)
  if direction == :add
    msg.channel.owners_unsynced << owner unless msg.channel.owners_unsynced.include?(owner)
    events << [:owner, owner]
  else
    msg.channel.owners_unsynced.delete(owner)
    events << [:deowner, owner]
  end
end
set_leaving_user(message, user, events) click to toggle source
# File lib/cinch/irc.rb, line 282
def set_leaving_user(message, user, events)
  events << [:leaving, user]
end