<commit_before>require File.join(Rails.root, 'lib/hcard')
require File.join(Rails.root, 'lib/webfinger_profile')

class EMWebfinger
  TIMEOUT = 5
  REDIRECTS = 3
  OPTS = {:timeout => TIMEOUT, :redirects => REDIRECTS}
  def initialize(account)
    @account = account.strip.gsub('acct:','').to_s
    @callbacks = []
    @ssl = true 
    Rails.logger.info("event=EMWebfinger status=initialized target=#{account}")
    # Raise an error if identifier has a port number 
    #raise "Identifier is invalid" if(@account.strip.match(/\:\d+$/))
    # Raise an error if identifier is not a valid email (generous regexp)
    #raise "Identifier is invalid" if !(@account=~ /^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/)
  end 
  def fetch
    if @callbacks.empty?
      Rails.logger.info("event=EMWebfinger status=abort target=#{@account} callbacks=empty")
      raise 'you need to set a callback before calling fetch' 
    end
    person = Person.by_account_identifier(@account)
    if person
      Rails.logger.info("event=EMWebfinger status=local target=#{@account}")
      process_callbacks person
    else
      Rails.logger.info("event=EMWebfinger status=remote target=#{@account}")
      get_xrd
    end
  end

  def on_person(&block)
    @callbacks << block
    self.fetch
  end

  private

  def get_xrd
    http = EventMachine::HttpRequest.new(xrd_url).get OPTS
    http.callback { 
      profile_url = webfinger_profile_url(http.response)
      if profile_url 
        get_webfinger_profile(profile_url) 
      elsif @ssl
        @ssl = false
        get_xrd
      else
        process_callbacks  I18n.t('webfinger.not_enabled', :account => @account)
      end
    }

    http.errback {
      if @ssl
        @ssl = false
        get_xrd
      else
        process_callbacks I18n.t('webfinger.xrd_fetch_failed', :account => @account)
      end }
  end


  def get_webfinger_profile(profile_url)
     http = EventMachine::HttpRequest.new(profile_url).get OPTS
     http.callback{ make_person_from_webfinger(http.response) }
     http.errback{ process_callbacks I18n.t('webfinger.fetch_failed', :profile_url => profile_url) }
  end

  def make_person_from_webfinger(webfinger_profile)
    unless webfinger_profile.strip == ""
      
      begin
        wf_profile = WebfingerProfile.new(@account, webfinger_profile)
      rescue
        return process_callbacks "No person could be constructed from this webfinger profile."
      end
      
      http = EventMachine::HttpRequest.new(wf_profile.hcard).get OPTS
      http.callback{
        begin
          hcard = HCard.build http.response
          p = Person.build_from_webfinger(wf_profile, hcard)
          process_callbacks(p)
        rescue
          process_callbacks I18n.t 'webfinger.no_person_constructed'
        end
      }
      http.errback{process_callbacks I18n.t('webfinger.hcard_fetch_failed', :account => @account) }
    end
  end


  def process_callbacks(person)
    Rails.logger.info("event=EMWebfinger status=callbacks_started target=#{@account} response='#{person.is_a?(String) ? person : person.id}'")
    @callbacks.each { |c|
      begin
        c.call(person)
      rescue Exception => e
        Rails.logger.info("event=EMWebfinger status=error_on_callback error='#{e.inspect}'")
      end
    }
    Rails.logger.info("event=EMWebfinger status=complete target=#{@account}")
  end


  ##helpers
  private

  def webfinger_profile_url(xrd_response)
    doc = Nokogiri::XML::Document.parse(xrd_response)  
    return nil if doc.namespaces["xmlns"] != "http://docs.oasis-open.org/ns/xri/xrd-1.0" 
    swizzle doc.at('Link[rel=lrdd]').attribute('template').value
  end

  def xrd_url
    domain = @account.split('@')[1]
    "http#{'s' if @ssl}://#{domain}/.well-known/host-meta"
  end
  
  def swizzle(template)
    template.gsub '{uri}', @account
  end
end
<commit_msg>do no return in em-webfinger, causeing weird splunk errors<commit_after>require File.join(Rails.root, 'lib/hcard')
require File.join(Rails.root, 'lib/webfinger_profile')

class EMWebfinger
  TIMEOUT = 5
  REDIRECTS = 3
  OPTS = {:timeout => TIMEOUT, :redirects => REDIRECTS}
  def initialize(account)
    @account = account.strip.gsub('acct:','').to_s
    @callbacks = []
    @ssl = true 
    Rails.logger.info("event=EMWebfinger status=initialized target=#{account}")
    # Raise an error if identifier has a port number 
    #raise "Identifier is invalid" if(@account.strip.match(/\:\d+$/))
    # Raise an error if identifier is not a valid email (generous regexp)
    #raise "Identifier is invalid" if !(@account=~ /^[a-zA-Z][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$/)
  end 
  def fetch
    if @callbacks.empty?
      Rails.logger.info("event=EMWebfinger status=abort target=#{@account} callbacks=empty")
      raise 'you need to set a callback before calling fetch' 
    end
    person = Person.by_account_identifier(@account)
    if person
      Rails.logger.info("event=EMWebfinger status=local target=#{@account}")
      process_callbacks person
    else
      Rails.logger.info("event=EMWebfinger status=remote target=#{@account}")
      get_xrd
    end
  end

  def on_person(&block)
    @callbacks << block
    self.fetch
  end

  private

  def get_xrd
    http = EventMachine::HttpRequest.new(xrd_url).get OPTS
    http.callback { 
      profile_url = webfinger_profile_url(http.response)
      if profile_url 
        get_webfinger_profile(profile_url) 
      elsif @ssl
        @ssl = false
        get_xrd
      else
        process_callbacks  I18n.t('webfinger.not_enabled', :account => @account)
      end
    }

    http.errback {
      if @ssl
        @ssl = false
        get_xrd
      else
        process_callbacks I18n.t('webfinger.xrd_fetch_failed', :account => @account)
      end }
  end


  def get_webfinger_profile(profile_url)
     http = EventMachine::HttpRequest.new(profile_url).get OPTS
     http.callback{ make_person_from_webfinger(http.response) }
     http.errback{ process_callbacks I18n.t('webfinger.fetch_failed', :profile_url => profile_url) }
  end

  def make_person_from_webfinger(webfinger_profile)
    unless webfinger_profile.strip == ""
      
      begin
        wf_profile = WebfingerProfile.new(@account, webfinger_profile)

      
        http = EventMachine::HttpRequest.new(wf_profile.hcard).get OPTS
        http.callback{
          begin
            hcard = HCard.build http.response
            p = Person.build_from_webfinger(wf_profile, hcard)
            process_callbacks(p)
          rescue
            process_callbacks I18n.t 'webfinger.no_person_constructed'
          end
        }
        http.errback{
          process_callbacks I18n.t('webfinger.hcard_fetch_failed', :account => @account) }

      rescue
          process_callbacks "No person could be constructed from this webfinger profile."
      end
    end
  end


  def process_callbacks(person)
    Rails.logger.info("event=EMWebfinger status=callbacks_started target=#{@account} response='#{person.is_a?(String) ? person : person.id}'")
    @callbacks.each { |c|
      begin
        c.call(person)
      rescue Exception => e
        Rails.logger.info("event=EMWebfinger status=error_on_callback error='#{e.inspect}'")
      end
    }
    Rails.logger.info("event=EMWebfinger status=complete target=#{@account}")
  end


  ##helpers
  private

  def webfinger_profile_url(xrd_response)
    doc = Nokogiri::XML::Document.parse(xrd_response)  
    return nil if doc.namespaces["xmlns"] != "http://docs.oasis-open.org/ns/xri/xrd-1.0" 
    swizzle doc.at('Link[rel=lrdd]').attribute('template').value
  end

  def xrd_url
    domain = @account.split('@')[1]
    "http#{'s' if @ssl}://#{domain}/.well-known/host-meta"
  end
  
  def swizzle(template)
    template.gsub '{uri}', @account
  end
end

{'fraction_non_alphanumeric': 0.12434705057969168, 'fraction_numerical': 0.0053510001274047645, 'mean_word_length': 3.0463917525773194, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, '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': '5481316', 'n_tokens_mistral': 2731, 'n_tokens_neox': 2672, 'n_words': 502}