<commit_before>require "socket"
require "iconv"
require "lib/irc_history"

$script_name = "WebIRC client"
$script_version = "0.9"
$script_source  = "http://github.com/andyherbert/WebIRC/tree/master"

class IRC
  def initialize(connection)
    @connection = connection
    @history = IRCHistory.new(@connection["nickname"])
    @joined_channels = Hash.new
    @connection_count = 0
  end
  
  def connect
    loop do
      connection_thread = Thread.new {connection_loop}
      loop do
        sleep 300 # 5 minutes
        if @history.stoned?
          @connection_count += 1
          @history.reconnection(:STONEDCONNECTION, "Connection appears to be stoned, attempting reconnection")
          disconnect
          connection_thread.exit
          break
        end
      end
    end
  end
  
  def connection_loop(retries = 4, reconnect_wait = 90)
    begin
      @socket = TCPSocket::open(@connection["server_name"], (@connection["server_port"] or 6667))
      send("PASS #{@connection["password"]}") if @connection["password"] and !@connection["password"].empty?
      send("NICK #{@connection["nickname"]}")
      send("USER #{@connection["user_name"]} #{user_mask} * :#{@connection["real_name"]}")
      loop do
          ready = select([@socket, $stdin], nil, nil, nil)
          next unless ready
          for msg in ready[0]
              if msg == $stdin then
                  return if $stdin.eof
                  msg = $stdin.gets
                  send(msg)
              elsif msg == @socket then
                  return if @socket.eof
                  msg = @socket.gets
                  main_loop(strip_colours_and_encode_to_utf(msg))
              end
          end
      end
    rescue SocketError # Unable to connect
      @connection_count += 1
      retry if server_retry(:SOCKETERROR, "Unable to connect with #{@connection["server_name"]}", retries -= 1, reconnect_wait)
    rescue Errno::ECONNREFUSED # Connection refused
      @connection_count += 1
      retry if server_retry(:CONNREFUSED, "Connection refused with #{@connection["server_name"]}")
    rescue Errno::ECONNRESET # Connection reset
      @connection_count += 1
      retry if server_retry(:CONNRESET, "Connection reset with #{@connection["server_name"]}", retries -= 1, reconnect_wait)
    rescue Errno::ETIMEDOUT # Connection timed out
      @connection_count += 1
      retry if server_retry(:TIMEDOUT, "Connection timed out with #{@connection["server_name"]}", retries -= 1, reconnect_wait)
    rescue
      puts $!
    end
  end
  
  def disconnect
    send("QUIT")
  end
  
  def history(last_read)
    {
      :server_name => @connection["server_name"],
      :server_port => @connection["server_port"],
      :nickname => @history.nickname,
      :user_name => @connection["user_name"],
      :real_name => @connection["real_name"],
      :connection_count => @connection_count,
      :history => @history.history(last_read)
    }
  end
  
  def sync_channels(channels)
    close_channels = Array.new
    channels.each {|channel| close_channels << channel unless @history.joined_channel?(channel)}
    close_channels
  end
  
  def sync_privmsgs(privmsgs)
    close_privmsgs = Array.new
    privmsgs.each {|privmsg| close_privmsgs << privmsg unless @history.in_private_chat?(privmsg)}
    close_privmsgs
  end
  
  def close(target)
    @history.close(target)
  end
  
  def send(text)
    begin
      @socket.send "#{text}\n", 0
    rescue
      return nil
    end
    text
  end
  
  def join(raw)
    raw.scan(/^(\S+)(?:\s(\S+))?/) do |channel, key|
      send("JOIN #{channel} #{key}")
      @joined_channels[channel.downcase] = raw
    end
  end
  
  def part(raw)
    raw.scan(/^(\S+)(?:\s(.+))?/) do |channel, msg|
      send("PART #{channel} :#{msg}")
      @joined_channels.delete(channel.downcase)
    end
  end
  
  def privmsg(target, text, action)
    if action
      @history.self_action(target, text)
      send("PRIVMSG #{target} :\001ACTION #{text}\001")
    else
      @history.self_privmsg(target, text)
      send("PRIVMSG #{target} :#{text}")
    end
  end
  
  def notice(target, text)<commit_msg>Fixed a potential problem on /join with multiple channels.<commit_after>require "socket"
require "iconv"
require "lib/irc_history"

$script_name = "WebIRC client"
$script_version = "0.9"
$script_source  = "http://github.com/andyherbert/WebIRC/tree/master"

class IRC
  def initialize(connection)
    @connection = connection
    @history = IRCHistory.new(@connection["nickname"])
    @joined_channels = Hash.new
    @connection_count = 0
  end
  
  def connect
    loop do
      connection_thread = Thread.new {connection_loop}
      loop do
        sleep 300 # 5 minutes
        if @history.stoned?
          @connection_count += 1
          @history.reconnection(:STONEDCONNECTION, "Connection appears to be stoned, attempting reconnection")
          disconnect
          connection_thread.exit
          break
        end
      end
    end
  end
  
  def connection_loop(retries = 4, reconnect_wait = 90)
    begin
      @socket = TCPSocket::open(@connection["server_name"], (@connection["server_port"] or 6667))
      send("PASS #{@connection["password"]}") if @connection["password"] and !@connection["password"].empty?
      send("NICK #{@connection["nickname"]}")
      send("USER #{@connection["user_name"]} #{user_mask} * :#{@connection["real_name"]}")
      loop do
          ready = select([@socket, $stdin], nil, nil, nil)
          next unless ready
          for msg in ready[0]
              if msg == $stdin then
                  return if $stdin.eof
                  msg = $stdin.gets
                  send(msg)
              elsif msg == @socket then
                  return if @socket.eof
                  msg = @socket.gets
                  main_loop(strip_colours_and_encode_to_utf(msg))
              end
          end
      end
    rescue SocketError # Unable to connect
      @connection_count += 1
      retry if server_retry(:SOCKETERROR, "Unable to connect with #{@connection["server_name"]}", retries -= 1, reconnect_wait)
    rescue Errno::ECONNREFUSED # Connection refused
      @connection_count += 1
      retry if server_retry(:CONNREFUSED, "Connection refused with #{@connection["server_name"]}")
    rescue Errno::ECONNRESET # Connection reset
      @connection_count += 1
      retry if server_retry(:CONNRESET, "Connection reset with #{@connection["server_name"]}", retries -= 1, reconnect_wait)
    rescue Errno::ETIMEDOUT # Connection timed out
      @connection_count += 1
      retry if server_retry(:TIMEDOUT, "Connection timed out with #{@connection["server_name"]}", retries -= 1, reconnect_wait)
    rescue
      puts $!
    end
  end
  
  def disconnect
    send("QUIT")
  end
  
  def history(last_read)
    {
      :server_name => @connection["server_name"],
      :server_port => @connection["server_port"],
      :nickname => @history.nickname,
      :user_name => @connection["user_name"],
      :real_name => @connection["real_name"],
      :connection_count => @connection_count,
      :history => @history.history(last_read)
    }
  end
  
  def sync_channels(channels)
    close_channels = Array.new
    channels.each {|channel| close_channels << channel unless @history.joined_channel?(channel)}
    close_channels
  end
  
  def sync_privmsgs(privmsgs)
    close_privmsgs = Array.new
    privmsgs.each {|privmsg| close_privmsgs << privmsg unless @history.in_private_chat?(privmsg)}
    close_privmsgs
  end
  
  def close(target)
    @history.close(target)
  end
  
  def send(text)
    begin
      @socket.send "#{text}\n", 0
    rescue
      return nil
    end
    text
  end
  
  def join(raw)
    raw.scan(/^(\S+)(?:\s(\S+))?/) do |channel, key|
      join_command = "JOIN #{channel} #{key}"
      send(join_command)
      @joined_channels[channel.downcase] = join_command
    end
  end
  
  def part(raw)
    raw.scan(/^(\S+)(?:\s(.+))?/) do |channel, msg|
      send("PART #{channel} :#{msg}")
      @joined_channels.delete(channel.downcase)
    end
  end
  
  def privmsg(target, text, action)
    if action
      @history.self_action(target, text)
      send("PRIVMSG #{target} :\001ACTION #{text}\001")
    else
      @history.self_privmsg(target, text)
      send("PRIVMSG #{target} :#{text}")
    end
  end
  
  def notice(target, text)
{'fraction_non_alphanumeric': 0.12443004559635229, 'fraction_numerical': 0.007199424046076314, 'mean_word_length': 2.7783318223028104, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2514991', 'n_tokens_mistral': 2619, 'n_tokens_neox': 2600, 'n_words': 603}