<commit_before>require 'json'

class Call

  include ActiveModel::Serialization
  include Keynames

  attr_accessor :call_tag, :target_id, :language, :extension,
                :called_at, :queued_at, :hungup_at, :dispatched_at,
                :skill, :hungup, :caller_id, :mailbox


  def initialize(par=nil)
    if par
      @target_id     = par.fetch(:target_id)
      @skill         = par.fetch(:skill, nil)
      @hungup        = par.fetch(:hungup, nil)
      @mailbox       = par.fetch(:mailbox, nil)
      @call_tag      = par.fetch(:call_tag, nil)
      @language      = par.fetch(:language, nil)
      @called_at     = par.fetch(:called_at, nil)
      @caller_id     = par.fetch(:caller_id, nil)
      @hungup_at     = par.fetch(:hungup_at, nil)
      @queued_at     = par.fetch(:queued_at, nil)
      @extension     = par.fetch(:extension, nil)
      @dispatched_at = par.fetch(:dispatched_at, nil)
    end
  end


  def headers
    {
      'CallTag'  => call_tag,  'Language' => language,  'Skill'        => skill,     'Extension' => extension,
      'CallerId' => caller_id, 'Hungup'   => hungup,    'CalledAt'     => called_at, 'Mailbox'   => mailbox,
      'QueuedAt' => queued_at, 'HungupAt' => hungup_at, 'DispatchedAt' => dispatched_at
    }
  end


  def is_owned_by?(user)
    # TODO We have to restrict access here:
    #
    true
  end


  def hangup
    AmqpManager.ahn_publish(call_id: target_id, command: :hangup)
  end


  def transfer_to(to)
    AmqpManager.ahn_publish(call_id: target_id, to: to, command: :transfer)
  end


  def send_update_notification_to_clients
    AmqpManager.push_publish(
      user_ids: User.all_online_ids, data: CallSerializer.new(self)
    )
  end


  def create_history_entry_for_mailbox
    return if mailbox.blank?
    create_customer_history_entry(nil, mailbox)
  end


  def fetch_or_create_customer(caller_id)
    Customer.where(caller_ids: caller_id).last || Customer.create(caller_ids: [caller_id])
  end


  def create_customer_history_entry(agent, mailbox=nil)
    cust = fetch_or_create_customer(caller_id)
    entr = cust.history_entries

    entr.detect { |e|
      e.call_id == target_id
    } || entr.create(
      mailbox:   mailbox,   call_id:   target_id,
      caller_id: caller_id, agent_ext: agent
    )
  end


  # FIXME This may become expensive for high call counts:
  #
  def self.all
    Redis.current.keys(call_pattern).map { |key|
      call = find(key[/[^.]+$/])
      !call.hungup ? call : nil
    }.compact
  end


  def self.originate(params)
    AmqpManager.ahn_publish(
      from: params[:from], to: params[:to], command: :originate
    )
  end


  def self.find(tcid)
    return unless tcid
    entry  = Redis.current.get(call_keyname tcid) || new.headers.to_json
    fields = JSON.parse entry

    par = {
      target_id:     tcid,
      skill:         fields['Skill'],
      hungup:        fields['Hungup'],
      mailbox:       fields['Mailbox'],
      call_tag:      fields['CallTag'],
      language:      fields['Language'],
      called_at:     fields['CalledAt'],
      caller_id:     fields['CallerId'],
      hungup_at:     fields['HungupAt'],
      queued_at:     fields['QueuedAt'],
      extension:     fields['Extension'],
      dispatched_at: fields['DispatchedAt']
    }

    new(par)
  end
end
<commit_msg>cleanup call header handling<commit_after>require 'json'


class Call
  FORMAT = %w{target_id call_tag language skill extension caller_id hungup called_at mailbox queued_at hungup_at dispatched_at}
           .each_with_object({}) { |key, hash| hash[key.camelize] = key.to_sym }

  attr_accessor *FORMAT.values

  include ActiveModel::Serialization
  include Keynames


  def initialize(par=nil)
    Call::FORMAT.values.each do |sym|
      self.send "#{sym}=", par.fetch(sym, nil)
    end if par
  end


  def headers
    Call::FORMAT.keys.each_with_object({}) { |key, hash|
      hash[key] = self.send(Call::FORMAT[key])
    }
  end


  def is_owned_by?(user)
    # TODO We have to restrict access here:
    #
    true
  end


  def hangup
    AmqpManager.ahn_publish(call_id: target_id, command: :hangup)
  end


  def transfer_to(to)
    AmqpManager.ahn_publish(call_id: target_id, to: to, command: :transfer)
  end


  def send_update_notification_to_clients
    AmqpManager.push_publish(
      user_ids: User.all_online_ids, data: CallSerializer.new(self)
    )
  end


  def create_history_entry_for_mailbox
    return if mailbox.blank?
    create_customer_history_entry(nil, mailbox)
  end


  def fetch_or_create_customer(caller_id)
    Customer.where(caller_ids: caller_id).last || Customer.create(caller_ids: [caller_id])
  end


  def create_customer_history_entry(agent, mailbox=nil)
    cust = fetch_or_create_customer(caller_id)
    entr = cust.history_entries

    entr.detect { |e|
      e.call_id == target_id
    } || entr.create(
      mailbox:   mailbox,   call_id:   target_id,
      caller_id: caller_id, agent_ext: agent
    )
  end


  # FIXME This may become expensive for high call counts:
  #
  def self.all
    Redis.current.keys(call_pattern).map { |key|
      call = find(key[/[^.]+$/])
      !call.hungup ? call : nil
    }.compact
  end


  def self.originate(params)
    AmqpManager.ahn_publish(
      from: params[:from], to: params[:to], command: :originate
    )
  end


  def self.find(tcid)
    return unless tcid
    fields = JSON.parse(Redis.current.get(call_keyname tcid) || new.headers.to_json)
    fields['TargetId'] = tcid

    new Call::FORMAT.keys.each_with_object({}) { |key, hash|
      hash[Call::FORMAT[key]] = fields[key]
    }
  end
end

{'fraction_non_alphanumeric': 0.11342964151952915, 'fraction_numerical': 0.0, 'mean_word_length': 2.929922915206727, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 14, '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': '4966142', 'n_tokens_mistral': 1991, 'n_tokens_neox': 1940, 'n_words': 400}