<commit_before># Responsible for creating posts and topics
#
require_dependency 'rate_limiter'
require_dependency 'topic_creator'

class PostCreator

  attr_reader :errors, :opts

  # Acceptable options:
  #
  #   raw                     - raw text of post
  #   image_sizes             - We can pass a list of the sizes of images in the post as a shortcut.
  #   invalidate_oneboxes     - Whether to force invalidation of oneboxes in this post
  #   acting_user             - The user performing the action might be different than the user
  #                             who is the post "author." For example when copying posts to a new
  #                             topic.
  #   created_at              - Post creation time (optional)
  #   auto_track              - Automatically track this topic if needed (default true)
  #
  #   When replying to a topic:
  #     topic_id              - topic we're replying to
  #     reply_to_post_number  - post number we're replying to
  #
  #   When creating a topic:
  #     title                 - New topic title
  #     archetype             - Topic archetype
  #     category              - Category to assign to topic
  #     target_usernames      - comma delimited list of usernames for membership (private message)
  #     target_group_names    - comma delimited list of groups for membership (private message)
  #     meta_data             - Topic meta data hash
  #     cooking_options       - Options for rendering the text
  #
  def initialize(user, opts)
    # TODO: we should reload user in case it is tainted, should take in a user_id as opposed to user
    # If we don't do this we introduce a rather risky dependency
    @user = user
    @opts = opts || {}
    @spam = false
  end

  # True if the post was considered spam
  def spam?
    @spam
  end

  def guardian
    @guardian ||= Guardian.new(@user)
  end

  def create
    @topic = nil
    @post = nil
    @new_topic = false

    Post.transaction do
      setup_topic
      setup_post
      rollback_if_host_spam_detected
      save_post
      extract_links
      store_unique_post_key
      consider_clearing_flags
      track_topic
      update_topic_stats
      update_user_counts
      publish
      ensure_in_allowed_users if guardian.is_staff?
      @post.advance_draft_sequence
      @post.save_reply_relationships
    end

    if @spam
      GroupMessage.create( Group[:moderators].name,
                           :spam_post_blocked,
                           { user: @user,
                             limit_once_per: 24.hours,
                             message_params: {domains: @post.linked_hosts.keys.join(', ')} } )
    elsif @post && !@post.errors.present?
      SpamRulesEnforcer.enforce!(@post)
    end

    track_latest_on_category

    enqueue_jobs
    @post
  end


  def self.create(user, opts)
    PostCreator.new(user, opts).create
  end

  def self.before_create_tasks(post)<commit_msg>skip validations for Spam Rules when needed<commit_after># Responsible for creating posts and topics
#
require_dependency 'rate_limiter'
require_dependency 'topic_creator'

class PostCreator

  attr_reader :errors, :opts

  # Acceptable options:
  #
  #   raw                     - raw text of post
  #   image_sizes             - We can pass a list of the sizes of images in the post as a shortcut.
  #   invalidate_oneboxes     - Whether to force invalidation of oneboxes in this post
  #   acting_user             - The user performing the action might be different than the user
  #                             who is the post "author." For example when copying posts to a new
  #                             topic.
  #   created_at              - Post creation time (optional)
  #   auto_track              - Automatically track this topic if needed (default true)
  #
  #   When replying to a topic:
  #     topic_id              - topic we're replying to
  #     reply_to_post_number  - post number we're replying to
  #
  #   When creating a topic:
  #     title                 - New topic title
  #     archetype             - Topic archetype
  #     category              - Category to assign to topic
  #     target_usernames      - comma delimited list of usernames for membership (private message)
  #     target_group_names    - comma delimited list of groups for membership (private message)
  #     meta_data             - Topic meta data hash
  #     cooking_options       - Options for rendering the text
  #
  def initialize(user, opts)
    # TODO: we should reload user in case it is tainted, should take in a user_id as opposed to user
    # If we don't do this we introduce a rather risky dependency
    @user = user
    @opts = opts || {}
    @spam = false
  end

  # True if the post was considered spam
  def spam?
    @spam
  end

  def guardian
    @guardian ||= Guardian.new(@user)
  end

  def create
    @topic = nil
    @post = nil
    @new_topic = false

    Post.transaction do
      setup_topic
      setup_post
      rollback_if_host_spam_detected
      save_post
      extract_links
      store_unique_post_key
      consider_clearing_flags
      track_topic
      update_topic_stats
      update_user_counts
      publish
      ensure_in_allowed_users if guardian.is_staff?
      @post.advance_draft_sequence
      @post.save_reply_relationships
    end

    if @spam
      GroupMessage.create( Group[:moderators].name,
                           :spam_post_blocked,
                           { user: @user,
                             limit_once_per: 24.hours,
                             message_params: {domains: @post.linked_hosts.keys.join(', ')} } )
    elsif @post && !@post.errors.present? && !@opts[:skip_validations]
      SpamRulesEnforcer.enforce!(@post)
    end

    track_latest_on_category

    enqueue_jobs
    @post
  end


  def self.create(user, opts)
    PostCreator.new(user, opts).create
  end

  def self.before_create_tasks(post)
{'fraction_non_alphanumeric': 0.058188564682071175, 'fraction_numerical': 0.0006746500252993759, 'mean_word_length': 1.975413948820873, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2838527', 'n_tokens_mistral': 1737, 'n_tokens_neox': 1659, 'n_words': 538}