<commit_before>class Post < ApplicationRecord
  has_and_belongs_to_many :reasons
  has_many :feedbacks, :dependent => :destroy
  has_many :deletion_logs, :dependent => :destroy
  belongs_to :site
  belongs_to :stack_exchange_user
  has_many :flag_logs, :dependent => :destroy

  scope :includes_for_post_row, -> { includes(:reasons).includes(:feedbacks => [:user, :api_key]) }
  scope :without_feedback, -> { left_joins(:feedbacks).where( :feedbacks => { :post_id => nil }) }

  after_create do
    ActionCable.server.broadcast "posts_realtime", { row: PostsController.render(locals: {post: Post.last}, partial: 'post').html_safe }
    ActionCable.server.broadcast "topbar", { review: Post.without_feedback.count }
  end

  after_create :autoflag

  def autoflag
    return unless Post.where(:link => link).count == 1
    return unless FlagSetting['flagging_enabled'] == '1'

    dry_run = FlagSetting['dry_run'] == '1'
    post = self

    Thread.new do
      begin
        conditions = post.site.flag_conditions.where(:flags_enabled => true)
        available_user_ids = {}
        conditions.each do |condition|
          if condition.validate!(post)
            available_user_ids[condition.user.id] = condition
          end
        end

        uids = post.site.user_site_settings.where(:user_id => available_user_ids.keys).map(&:user_id)
        users = User.where(:id => uids, :flags_enabled => true).where.not(:encrypted_api_token => nil)
        unless users.present?
          post.send_not_autoflagged
          Thread.exit
        end

        post.fetch_revision_count
        unless post.revision_count == 1
          post.send_not_autoflagged
          Thread.exit
        end

        max_flags = [post.site.max_flags_per_post, (FlagSetting['max_flags'] || '3').to_i].min
        core_count = (max_flags / 2.0).ceil
        other_count = max_flags - core_count

        users.with_role(:core).shuffle.each do |user|
          if core_count <= 0
            break
          end
          core_count -= post.send_autoflag(user, dry_run, available_user_ids[user.id])
        end

        users.without_role(:core).shuffle.each do |user|
          if other_count <= 0
            break
          end
          other_count -= post.send_autoflag(user, dry_run, available_user_ids[user.id])
        end
      rescue => e
        FlagLog.create(:success => false, :error_message => "#{e}: #{e.message} | #{e.backtrace.join("\n")}",
                       :is_dry_run => dry_run, :flag_condition => nil, :post => post,
                       :site_id => post.site_id)
      end

      post.send_not_autoflagged if post.flag_logs.where(:success => true).empty?
    end
  end

  def send_autoflag(user, dry_run, condition)
    user_site_flag_count = user.flag_logs.where(:site => self.site, :success => true, :is_dry_run => false).where(:created_at => Date.today..Time.now).count
    return 0 if user_site_flag_count >= user.user_site_settings.includes(:sites).where(:sites => { :id => self.site.id } ).minimum(:max_flags)

    last_log = FlagLog.auto.where(:user => user).last
    if last_log.try(:backoff).present? && (last_log.created_at + last_log.backoff.seconds > Time.now)
      sleep((last_log.created_at + last_log.backoff.seconds) - Time.now)
    end

    success, message = user.spam_flag(self, dry_run)
    backoff = 0
    if success
      backoff = message
    end

    unless ["Flag options not present", "Spam flag option not present", "You do not have permission to flag this post"].include? message
      flag_log = FlagLog.create(:success => success, :error_message => message,
                                :is_dry_run => dry_run, :flag_condition => condition,
                                :user => user, :post => self, :backoff => backoff,
                                :site_id => self.site_id)

      if success
        ActionCable.server.broadcast "api_flag_logs", { flag_log: JSON.parse(FlagLogController.render(locals: {flag_log: flag_log}, partial: 'flag_log.json')) }
        ActionCable.server.broadcast "flag_logs", { row: FlagLogController.render(locals: {log: flag_log}, partial: 'flag_log') }
      end
    end

    return success ? 1 : 0
  end

  def send_not_autoflagged
    ActionCable.server.broadcast "api_flag_logs", { not_flagged: { post_link: self.link, post: JSON.parse(PostsController.render(locals: {post: self}, partial: 'post.json')) } }
  end

  def update_feedback_cache
    self.is_tp = false
    self.is_fp = false

    feedbacks = self.feedbacks.to_a

    self.is_tp = true if feedbacks.index { |f| f.is_positive? }<commit_msg>Stop no-account creating failures<commit_after>class Post < ApplicationRecord
  has_and_belongs_to_many :reasons
  has_many :feedbacks, :dependent => :destroy
  has_many :deletion_logs, :dependent => :destroy
  belongs_to :site
  belongs_to :stack_exchange_user
  has_many :flag_logs, :dependent => :destroy

  scope :includes_for_post_row, -> { includes(:reasons).includes(:feedbacks => [:user, :api_key]) }
  scope :without_feedback, -> { left_joins(:feedbacks).where( :feedbacks => { :post_id => nil }) }

  after_create do
    ActionCable.server.broadcast "posts_realtime", { row: PostsController.render(locals: {post: Post.last}, partial: 'post').html_safe }
    ActionCable.server.broadcast "topbar", { review: Post.without_feedback.count }
  end

  after_create :autoflag

  def autoflag
    return unless Post.where(:link => link).count == 1
    return unless FlagSetting['flagging_enabled'] == '1'

    dry_run = FlagSetting['dry_run'] == '1'
    post = self

    Thread.new do
      begin
        conditions = post.site.flag_conditions.where(:flags_enabled => true)
        available_user_ids = {}
        conditions.each do |condition|
          if condition.validate!(post)
            available_user_ids[condition.user.id] = condition
          end
        end

        uids = post.site.user_site_settings.where(:user_id => available_user_ids.keys).map(&:user_id)
        users = User.where(:id => uids, :flags_enabled => true).where.not(:encrypted_api_token => nil)
        unless users.present?
          post.send_not_autoflagged
          Thread.exit
        end

        post.fetch_revision_count
        unless post.revision_count == 1
          post.send_not_autoflagged
          Thread.exit
        end

        max_flags = [post.site.max_flags_per_post, (FlagSetting['max_flags'] || '3').to_i].min
        core_count = (max_flags / 2.0).ceil
        other_count = max_flags - core_count

        users.with_role(:core).shuffle.each do |user|
          if core_count <= 0
            break
          end
          core_count -= post.send_autoflag(user, dry_run, available_user_ids[user.id])
        end

        users.without_role(:core).shuffle.each do |user|
          if other_count <= 0
            break
          end
          other_count -= post.send_autoflag(user, dry_run, available_user_ids[user.id])
        end
      rescue => e
        FlagLog.create(:success => false, :error_message => "#{e}: #{e.message} | #{e.backtrace.join("\n")}",
                       :is_dry_run => dry_run, :flag_condition => nil, :post => post,
                       :site_id => post.site_id)
      end

      post.send_not_autoflagged if post.flag_logs.where(:success => true).empty?
    end
  end

  def send_autoflag(user, dry_run, condition)
    user_site_flag_count = user.flag_logs.where(:site => self.site, :success => true, :is_dry_run => false).where(:created_at => Date.today..Time.now).count
    return 0 if user_site_flag_count >= user.user_site_settings.includes(:sites).where(:sites => { :id => self.site.id } ).minimum(:max_flags)

    last_log = FlagLog.auto.where(:user => user).last
    if last_log.try(:backoff).present? && (last_log.created_at + last_log.backoff.seconds > Time.now)
      sleep((last_log.created_at + last_log.backoff.seconds) - Time.now)
    end

    success, message = user.spam_flag(self, dry_run)
    backoff = 0
    if success
      backoff = message
    end

    unless ["Flag options not present", "Spam flag option not present", "You do not have permission to flag this post", "No account on this site."].include? message
      flag_log = FlagLog.create(:success => success, :error_message => message,
                                :is_dry_run => dry_run, :flag_condition => condition,
                                :user => user, :post => self, :backoff => backoff,
                                :site_id => self.site_id)

      if success
        ActionCable.server.broadcast "api_flag_logs", { flag_log: JSON.parse(FlagLogController.render(locals: {flag_log: flag_log}, partial: 'flag_log.json')) }
        ActionCable.server.broadcast "flag_logs", { row: FlagLogController.render(locals: {log: flag_log}, partial: 'flag_log') }
      end
    end

    return success ? 1 : 0
  end

  def send_not_autoflagged
    ActionCable.server.broadcast "api_flag_logs", { not_flagged: { post_link: self.link, post: JSON.parse(PostsController.render(locals: {post: self}, partial: 'post.json')) } }
  end

  def update_feedback_cache
    self.is_tp = false
    self.is_fp = false

    feedbacks = self.feedbacks.to_a

    self.is_tp = true if feedbacks.index { |f| f.is_positive? }
{'fraction_non_alphanumeric': 0.12061118335500651, 'fraction_numerical': 0.0028175119202427396, 'mean_word_length': 2.8470195914964567, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 81, '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': '6673608', 'n_tokens_mistral': 2978, 'n_tokens_neox': 2879, 'n_words': 596}