<commit_before>require 'activerecord/uuid'

class Conversation < ActiveRecord::Base
  include ActiveRecord::UUID

  belongs_to :account

  belongs_to :user

  has_many :account_people,
    through: :account,
    source: :user_people

  has_many :messages,
    after_add: :message_added_callback,
    dependent: :destroy

  has_one :first_message,
    -> { order('messages.updated_at ASC').limit(1) },
    class_name: 'Message'

  has_many :subsequent_messages,
    -> { order('messages.updated_at ASC').offset(1) },
    class_name: 'Message'

  has_one :most_recent_message,
    -> { order('messages.updated_at DESC').limit(1) },
    class_name: 'Message'

  has_many :participants,
    -> { uniq },
    through: :messages,
    source: :person

  has_many :respond_laters

  has_many :assignment_events

  has_many :tag_events

  validates :account, presence: true

  default_scope -> { paid }

  scope :archived, -> { where(archived: true) }

  scope :most_recent, -> { order('updated_at DESC') }

  scope :queue, -> { order('updated_at ASC') }

  scope :paid, -> { where(hidden: false) }

  scope :including_unpaid, -> { unscope(where: :hidden) }

  scope :this_month, -> { where("DATE_TRUNC('month', created_at) = ?", Time.now.utc.beginning_of_month) }

  scope :unresolved, -> { where(archived: false) }

  scope :with_messages_count, -> { select('conversations.*, (SELECT COUNT(messages.id) FROM messages WHERE messages.conversation_id = conversations.id) AS messages_count') }

  sequential column: :number,
    scope: :account_id

  before_create :check_conversations_limit

  after_commit :notify_account_people,
    on: :create

  def archive!
    update(archived: true)
  end

  def unarchive!
    update(archived: false)
  end

  def respond_later!(user)
    respond_later = respond_laters.find_or_create_by(user: user)
    respond_later.touch
  end

  def just_archived?
    _, new_archived = previous_changes[:archived]
    !!new_archived
  end

  def just_unarchived?
    _, new_archived = previous_changes[:archived]
    new_archived == false
  end

  def creator_person
    first_message.person
  end

  def messages_count
    ['messages_count'] || messages.count
  end

  # Public: Conversation specific email address for incoming email replies.
  #
  # Returns the Mail::Address customers should send email replies to.
  def mailbox_email
    email = Mail::Address.new("#{self.id}@#{Helpful.incoming_email_domain}")
    email.display_name = account.name
    email
  end

  # Public: Given an email address try to match to a conversation.
  #
  # Returns a Conversation or nil.
  def self.match_mailbox(email)
    address = Mail::Address.new(email)
    Conversation.find_by_id(address.local)
  end

  # Public: Given an email address try to match to a conversation or raise
  # ActiveRecord::RecordNotFound.
  #
  # Returns a Conversation or raises ActiveRecord::RecordNotFound.
  def self.match_mailbox!(email)
    self.match_mailbox(email) || raise(ActiveRecord::RecordNotFound)
  end

  def last_activity_at
    if most_recent_message
      most_recent_message.updated_at
    else
      updated_at
    end
  end

  def to_param
    number.to_param
  end

  def to_mailbox_hash
    {
      account_slug: self.account.slug,
      conversation_number: self.number
    }
  end

  def contains_message_id?(message_id)
    messages.detect { |message| message.id == message_id }
  end

  def notify_account_people
    return if messages.empty? || unpaid?
    MessageMailman.deliver(most_recent_message, account_people)
  end

  def unpaid?
    hidden
  end

  def stale?
    !archived? && last_activity_at < 3.days.ago
  end

  private

  def message_added_callback(message)
    unarchive!
  end

  def check_conversations_limit
    self.hidden = true if account.conversations_limit_reached?
  end
end
<commit_msg>Oops -- make that an accessor<commit_after>require 'activerecord/uuid'

class Conversation < ActiveRecord::Base
  include ActiveRecord::UUID

  belongs_to :account

  belongs_to :user

  has_many :account_people,
    through: :account,
    source: :user_people

  has_many :messages,
    after_add: :message_added_callback,
    dependent: :destroy

  has_one :first_message,
    -> { order('messages.updated_at ASC').limit(1) },
    class_name: 'Message'

  has_many :subsequent_messages,
    -> { order('messages.updated_at ASC').offset(1) },
    class_name: 'Message'

  has_one :most_recent_message,
    -> { order('messages.updated_at DESC').limit(1) },
    class_name: 'Message'

  has_many :participants,
    -> { uniq },
    through: :messages,
    source: :person

  has_many :respond_laters

  has_many :assignment_events

  has_many :tag_events

  validates :account, presence: true

  default_scope -> { paid }

  scope :archived, -> { where(archived: true) }

  scope :most_recent, -> { order('updated_at DESC') }

  scope :queue, -> { order('updated_at ASC') }

  scope :paid, -> { where(hidden: false) }

  scope :including_unpaid, -> { unscope(where: :hidden) }

  scope :this_month, -> { where("DATE_TRUNC('month', created_at) = ?", Time.now.utc.beginning_of_month) }

  scope :unresolved, -> { where(archived: false) }

  scope :with_messages_count, -> { select('conversations.*, (SELECT COUNT(messages.id) FROM messages WHERE messages.conversation_id = conversations.id) AS messages_count') }

  sequential column: :number,
    scope: :account_id

  before_create :check_conversations_limit

  after_commit :notify_account_people,
    on: :create

  def archive!
    update(archived: true)
  end

  def unarchive!
    update(archived: false)
  end

  def respond_later!(user)
    respond_later = respond_laters.find_or_create_by(user: user)
    respond_later.touch
  end

  def just_archived?
    _, new_archived = previous_changes[:archived]
    !!new_archived
  end

  def just_unarchived?
    _, new_archived = previous_changes[:archived]
    new_archived == false
  end

  def creator_person
    first_message.person
  end

  def messages_count
    self['messages_count'] || messages.count
  end

  # Public: Conversation specific email address for incoming email replies.
  #
  # Returns the Mail::Address customers should send email replies to.
  def mailbox_email
    email = Mail::Address.new("#{self.id}@#{Helpful.incoming_email_domain}")
    email.display_name = account.name
    email
  end

  # Public: Given an email address try to match to a conversation.
  #
  # Returns a Conversation or nil.
  def self.match_mailbox(email)
    address = Mail::Address.new(email)
    Conversation.find_by_id(address.local)
  end

  # Public: Given an email address try to match to a conversation or raise
  # ActiveRecord::RecordNotFound.
  #
  # Returns a Conversation or raises ActiveRecord::RecordNotFound.
  def self.match_mailbox!(email)
    self.match_mailbox(email) || raise(ActiveRecord::RecordNotFound)
  end

  def last_activity_at
    if most_recent_message
      most_recent_message.updated_at
    else
      updated_at
    end
  end

  def to_param
    number.to_param
  end

  def to_mailbox_hash
    {
      account_slug: self.account.slug,
      conversation_number: self.number
    }
  end

  def contains_message_id?(message_id)
    messages.detect { |message| message.id == message_id }
  end

  def notify_account_people
    return if messages.empty? || unpaid?
    MessageMailman.deliver(most_recent_message, account_people)
  end

  def unpaid?
    hidden
  end

  def stale?
    !archived? && last_activity_at < 3.days.ago
  end

  private

  def message_added_callback(message)
    unarchive!
  end

  def check_conversations_limit
    self.hidden = true if account.conversations_limit_reached?
  end
end

{'fraction_non_alphanumeric': 0.09669012249152985, 'fraction_numerical': 0.0010424811050299713, 'mean_word_length': 3.7143734643734643, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 29, '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': '1430767', 'n_tokens_mistral': 2561, 'n_tokens_neox': 2442, 'n_words': 570}