<commit_before>require File.join(File.dirname(__FILE__), *%w[.. .. blather])

module Blather #:nodoc:

  class Client #:nodoc:
    attr_reader :jid,
                :roster

    def initialize
      @state = :initializing

      @status = Stanza::Presence::Status.new
      @handlers = {}
      @tmp_handlers = {}
      @roster = Roster.new self

      setup_initial_handlers
    end

    def jid=(new_jid)
      @jid = JID.new new_jid
    end

    def status
      @status.state
    end

    def status=(state)
      state, msg, to = state

      status = Stanza::Presence::Status.new state, msg
      status.to = to
      @status = status unless to

      write status
    end

    def setup?
      @setup.is_a? Array
    end

    def setup(jid, password, host = nil, port = nil)
      @jid = JID.new(jid)
      @setup = [@jid, password]
      @setup << host if host
      @setup << port if port
      self
    end

    def run
      raise 'not setup!' unless setup?
      klass = @setup[0].node ? Blather::Stream::Client : Blather::Stream::Component
      @stream = klass.start self, *@setup
    end

    def register_tmp_handler(id, &handler)
      @tmp_handlers[id] = handler
    end

    def register_handler(type, *guards, &handler)
      check_guards guards
      @handlers[type] ||= []
      @handlers[type] << [guards, handler]
    end

    def write(stanza)
      @stream.send(stanza) if @stream
    end

    def write_with_handler(stanza, &handler)
      register_tmp_handler stanza.id, &handler
      write stanza
    end

    def post_init
      self.jid.node ? client_post_init : ready!
    end

    def close
      @stream.close_connection_after_writing
    end

    def unbind
      EM.stop if EM.reactor_running?
    end

    def receive_data(stanza)
      if handler = @tmp_handlers.delete(stanza.id)
        handler.call stanza
      else
        stanza.handler_heirarchy.each do |type|
          break if call_handler_for(type, stanza) && (stanza.is_a?(BlatherError) || stanza.type == :iq)
        end
      end
    end

  protected
    def setup_initial_handlers
      register_handler :error do |err|
        raise err
      end

      register_handler :iq, :type => [:get, :set] do |iq|
        write(StanzaError.new(iq, 'service-unavailable', :cancel).to_node)
      end

      register_handler :status do |status|
        roster[status.from].status = status if roster[status.from]
      end

      register_handler :roster do |node|
        roster.process node
      end
    end

    def ready!
      @state = :ready
      call_handler_for :ready, nil
    end

    def client_post_init
      write_with_handler Stanza::Iq::Roster.new do |node|
        roster.process node
        write @status
        ready!
      end
    end

    def call_handler_for(type, stanza)
      if @handlers[type]
        @handlers[type].find do |guards, handler|
          if guards.first.is_a?(String)
            unless (result = stanza.find(*guards)).empty?
              handler.call(stanza, result)
            end
          elsif !guarded?(guards, stanza)
            handler.call(stanza)
          end
        end
        true
      end
    end

    ##
    # If any of the guards returns FALSE this returns true
    # the logic is reversed to allow short circuiting
    # (why would anyone want to loop over more values than necessary?)
    def guarded?(guards, stanza)
      guards.find do |guard|<commit_msg>never fall through if a handler is found (may need to re-visit this)<commit_after>require File.join(File.dirname(__FILE__), *%w[.. .. blather])

module Blather #:nodoc:

  class Client #:nodoc:
    attr_reader :jid,
                :roster

    def initialize
      @state = :initializing

      @status = Stanza::Presence::Status.new
      @handlers = {}
      @tmp_handlers = {}
      @roster = Roster.new self

      setup_initial_handlers
    end

    def jid=(new_jid)
      @jid = JID.new new_jid
    end

    def status
      @status.state
    end

    def status=(state)
      state, msg, to = state

      status = Stanza::Presence::Status.new state, msg
      status.to = to
      @status = status unless to

      write status
    end

    def setup?
      @setup.is_a? Array
    end

    def setup(jid, password, host = nil, port = nil)
      @jid = JID.new(jid)
      @setup = [@jid, password]
      @setup << host if host
      @setup << port if port
      self
    end

    def run
      raise 'not setup!' unless setup?
      klass = @setup[0].node ? Blather::Stream::Client : Blather::Stream::Component
      @stream = klass.start self, *@setup
    end

    def register_tmp_handler(id, &handler)
      @tmp_handlers[id] = handler
    end

    def register_handler(type, *guards, &handler)
      check_guards guards
      @handlers[type] ||= []
      @handlers[type] << [guards, handler]
    end

    def write(stanza)
      @stream.send(stanza) if @stream
    end

    def write_with_handler(stanza, &handler)
      register_tmp_handler stanza.id, &handler
      write stanza
    end

    def post_init
      self.jid.node ? client_post_init : ready!
    end

    def close
      @stream.close_connection_after_writing
    end

    def unbind
      EM.stop if EM.reactor_running?
    end

    def receive_data(stanza)
      if handler = @tmp_handlers.delete(stanza.id)
        handler.call stanza
      else
        stanza.handler_heirarchy.each do |type|
          break if call_handler_for(type, stanza)# && (stanza.is_a?(BlatherError) || stanza.type == :iq)
        end
      end
    end

  protected
    def setup_initial_handlers
      register_handler :error do |err|
        raise err
      end

      register_handler :iq, :type => [:get, :set] do |iq|
        write(StanzaError.new(iq, 'service-unavailable', :cancel).to_node)
      end

      register_handler :status do |status|
        roster[status.from].status = status if roster[status.from]
      end

      register_handler :roster do |node|
        roster.process node
      end
    end

    def ready!
      @state = :ready
      call_handler_for :ready, nil
    end

    def client_post_init
      write_with_handler Stanza::Iq::Roster.new do |node|
        roster.process node
        write @status
        ready!
      end
    end

    def call_handler_for(type, stanza)
      if @handlers[type]
        @handlers[type].find do |guards, handler|
          if guards.first.is_a?(String)
            unless (result = stanza.find(*guards)).empty?
              handler.call(stanza, result)
            end
          elsif !guarded?(guards, stanza)
            handler.call(stanza)
          end
        end
      end
    end

    ##
    # If any of the guards returns FALSE this returns true
    # the logic is reversed to allow short circuiting
    # (why would anyone want to loop over more values than necessary?)
    def guarded?(guards, stanza)
      guards.find do |guard|
{'fraction_non_alphanumeric': 0.09409031508639466, 'fraction_numerical': 0.0002904022070567736, 'mean_word_length': 2.143769968051118, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2857611', 'n_tokens_mistral': 2213, 'n_tokens_neox': 2140, 'n_words': 584}