2013-02-05 13:16:51 -06:00
|
|
|
# Responsible for creating posts and topics
|
|
|
|
#
|
|
|
|
require_dependency 'rate_limiter'
|
2013-06-04 13:13:01 -05:00
|
|
|
require_dependency 'topic_creator'
|
2014-02-17 00:57:37 -06:00
|
|
|
require_dependency 'post_jobs_enqueuer'
|
2014-07-29 23:04:27 -05:00
|
|
|
require_dependency 'distributed_mutex'
|
2015-03-26 15:57:50 -05:00
|
|
|
require_dependency 'has_errors'
|
2013-02-05 13:16:51 -06:00
|
|
|
|
|
|
|
class PostCreator
|
2015-03-26 15:57:50 -05:00
|
|
|
include HasErrors
|
2013-02-05 13:16:51 -06:00
|
|
|
|
2015-03-26 15:57:50 -05:00
|
|
|
attr_reader :opts
|
2013-02-05 13:16:51 -06:00
|
|
|
|
|
|
|
# Acceptable options:
|
|
|
|
#
|
|
|
|
# raw - raw text of post
|
2013-02-25 10:42:20 -06:00
|
|
|
# image_sizes - We can pass a list of the sizes of images in the post as a shortcut.
|
2013-03-18 12:55:34 -05:00
|
|
|
# invalidate_oneboxes - Whether to force invalidation of oneboxes in this post
|
2013-05-13 13:06:16 -05:00
|
|
|
# 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.
|
2013-05-20 01:44:06 -05:00
|
|
|
# created_at - Post creation time (optional)
|
2013-07-21 20:40:39 -05:00
|
|
|
# auto_track - Automatically track this topic if needed (default true)
|
2014-05-17 20:33:34 -05:00
|
|
|
# custom_fields - Custom fields to be added to the post, Hash (default nil)
|
2015-01-05 09:52:33 -06:00
|
|
|
# post_type - Whether this is a regular post or moderator post.
|
|
|
|
# no_bump - Do not cause this post to bump the topic.
|
|
|
|
# cooking_options - Options for rendering the text
|
|
|
|
# cook_method - Method of cooking the post.
|
|
|
|
# :regular - Pass through Markdown parser and strip bad HTML
|
|
|
|
# :raw_html - Perform no processing
|
2015-06-05 10:46:21 -05:00
|
|
|
# :raw_email - Imported from an email
|
2015-01-05 09:52:33 -06:00
|
|
|
# via_email - Mark this post as arriving via email
|
|
|
|
# raw_email - Full text of arriving email (to store)
|
2015-07-24 15:39:03 -05:00
|
|
|
# action_code - Describes a small_action post (optional)
|
2013-02-05 13:16:51 -06:00
|
|
|
#
|
|
|
|
# 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
|
2014-09-08 10:11:56 -05:00
|
|
|
# is_warning - Is the topic a warning?
|
2013-02-05 13:16:51 -06:00
|
|
|
# category - Category to assign to topic
|
|
|
|
# target_usernames - comma delimited list of usernames for membership (private message)
|
2013-05-09 02:37:34 -05:00
|
|
|
# target_group_names - comma delimited list of groups for membership (private message)
|
2013-02-05 13:16:51 -06:00
|
|
|
# meta_data - Topic meta data hash
|
2015-01-19 08:00:55 -06:00
|
|
|
# created_at - Topic creation time (optional)
|
|
|
|
# pinned_at - Topic pinned time (optional)
|
2015-03-13 15:24:11 -05:00
|
|
|
# pinned_globally - Is the topic pinned globally (optional)
|
2013-06-21 10:36:33 -05:00
|
|
|
#
|
2013-02-05 13:16:51 -06:00
|
|
|
def initialize(user, opts)
|
2013-04-04 23:29:46 -05:00
|
|
|
# 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
|
2013-02-25 10:42:20 -06:00
|
|
|
@user = user
|
2013-06-21 10:36:33 -05:00
|
|
|
@opts = opts || {}
|
2015-08-18 21:30:18 -05:00
|
|
|
opts[:title] = pg_clean_up(opts[:title]) if opts[:title] && opts[:title].include?("\u0000")
|
|
|
|
opts[:raw] = pg_clean_up(opts[:raw]) if opts[:raw] && opts[:raw].include?("\u0000")
|
2015-09-22 12:32:19 -05:00
|
|
|
opts.delete(:reply_to_post_number) unless opts[:topic_id]
|
2015-10-14 21:25:10 -05:00
|
|
|
@guardian = opts[:guardian] if opts[:guardian]
|
2015-09-22 12:32:19 -05:00
|
|
|
|
2013-05-10 15:58:23 -05:00
|
|
|
@spam = false
|
2013-02-05 13:16:51 -06:00
|
|
|
end
|
|
|
|
|
2015-08-18 21:27:55 -05:00
|
|
|
def pg_clean_up(str)
|
|
|
|
str.gsub("\u0000", "")
|
2015-08-18 21:15:38 -05:00
|
|
|
end
|
|
|
|
|
2013-05-10 15:58:23 -05:00
|
|
|
# True if the post was considered spam
|
|
|
|
def spam?
|
|
|
|
@spam
|
|
|
|
end
|
|
|
|
|
2014-07-30 22:15:16 -05:00
|
|
|
def skip_validations?
|
|
|
|
@opts[:skip_validations]
|
|
|
|
end
|
|
|
|
|
2013-02-05 13:16:51 -06:00
|
|
|
def guardian
|
|
|
|
@guardian ||= Guardian.new(@user)
|
|
|
|
end
|
|
|
|
|
2015-03-26 15:57:50 -05:00
|
|
|
def valid?
|
2013-06-04 13:13:01 -05:00
|
|
|
@topic = nil
|
|
|
|
@post = nil
|
2013-02-05 13:16:51 -06:00
|
|
|
|
2014-07-30 22:15:16 -05:00
|
|
|
if @user.suspended? && !skip_validations?
|
2015-03-26 15:57:50 -05:00
|
|
|
errors[:base] << I18n.t(:user_is_suspended)
|
|
|
|
return false
|
2014-07-30 22:15:16 -05:00
|
|
|
end
|
|
|
|
|
2015-03-26 15:57:50 -05:00
|
|
|
if new_topic?
|
|
|
|
topic_creator = TopicCreator.new(@user, guardian, @opts)
|
|
|
|
return false unless skip_validations? || validate_child(topic_creator)
|
|
|
|
else
|
|
|
|
@topic = Topic.find_by(id: @opts[:topic_id])
|
|
|
|
if (@topic.blank? || !guardian.can_create?(Post, @topic))
|
|
|
|
errors[:base] << I18n.t(:topic_not_found)
|
|
|
|
return false
|
|
|
|
end
|
2013-02-05 13:16:51 -06:00
|
|
|
end
|
|
|
|
|
2015-03-26 15:57:50 -05:00
|
|
|
setup_post
|
|
|
|
|
|
|
|
return true if skip_validations?
|
2016-04-25 16:03:17 -05:00
|
|
|
|
2015-03-26 15:57:50 -05:00
|
|
|
if @post.has_host_spam?
|
|
|
|
@spam = true
|
|
|
|
errors[:base] << I18n.t(:spamming_host)
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
DiscourseEvent.trigger :before_create_post, @post
|
|
|
|
DiscourseEvent.trigger :validate_post, @post
|
|
|
|
|
|
|
|
post_validator = Validators::PostValidator.new(skip_topic: true)
|
|
|
|
post_validator.validate(@post)
|
|
|
|
|
|
|
|
valid = @post.errors.blank?
|
|
|
|
add_errors_from(@post) unless valid
|
|
|
|
valid
|
|
|
|
end
|
|
|
|
|
|
|
|
def create
|
|
|
|
if valid?
|
|
|
|
transaction do
|
2015-08-02 23:29:04 -05:00
|
|
|
build_post_stats
|
2015-03-26 15:57:50 -05:00
|
|
|
create_topic
|
|
|
|
save_post
|
|
|
|
extract_links
|
|
|
|
store_unique_post_key
|
|
|
|
track_topic
|
|
|
|
update_topic_stats
|
|
|
|
update_topic_auto_close
|
|
|
|
update_user_counts
|
|
|
|
create_embedded_topic
|
|
|
|
|
|
|
|
ensure_in_allowed_users if guardian.is_staff?
|
2015-12-22 18:09:17 -06:00
|
|
|
unarchive_message
|
2015-03-26 15:57:50 -05:00
|
|
|
@post.advance_draft_sequence
|
|
|
|
@post.save_reply_relationships
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if @post && errors.blank?
|
2014-07-29 23:04:27 -05:00
|
|
|
publish
|
2014-03-17 23:22:39 -05:00
|
|
|
|
|
|
|
track_latest_on_category
|
|
|
|
enqueue_jobs
|
2014-07-22 20:42:24 -05:00
|
|
|
BadgeGranter.queue_badge_grant(Badge::Trigger::PostRevision, post: @post)
|
2015-03-31 11:58:56 -05:00
|
|
|
|
|
|
|
trigger_after_events(@post)
|
2016-04-11 22:29:48 -05:00
|
|
|
|
2016-05-17 10:16:10 -05:00
|
|
|
auto_close unless @opts[:import_mode]
|
2014-03-17 23:22:39 -05:00
|
|
|
end
|
2014-02-10 13:29:31 -06:00
|
|
|
|
2014-07-29 23:24:20 -05:00
|
|
|
if @post || @spam
|
2014-07-29 23:04:27 -05:00
|
|
|
handle_spam unless @opts[:import_mode]
|
|
|
|
end
|
|
|
|
|
2013-06-04 13:13:01 -05:00
|
|
|
@post
|
2013-02-05 13:16:51 -06:00
|
|
|
end
|
|
|
|
|
2015-08-02 23:29:04 -05:00
|
|
|
def self.track_post_stats
|
|
|
|
Rails.env != "test".freeze || @track_post_stats
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.track_post_stats=(val)
|
|
|
|
@track_post_stats = val
|
|
|
|
end
|
|
|
|
|
2013-02-05 13:16:51 -06:00
|
|
|
def self.create(user, opts)
|
2013-02-25 10:42:20 -06:00
|
|
|
PostCreator.new(user, opts).create
|
2013-02-05 13:16:51 -06:00
|
|
|
end
|
|
|
|
|
2013-06-09 11:48:44 -05:00
|
|
|
def self.before_create_tasks(post)
|
2015-09-25 10:28:41 -05:00
|
|
|
set_reply_info(post)
|
2013-06-09 11:48:44 -05:00
|
|
|
|
2016-01-11 04:16:23 -06:00
|
|
|
post.word_count = post.raw.scan(/[[:word:]]+/).size
|
2013-06-09 11:48:44 -05:00
|
|
|
post.post_number ||= Topic.next_post_number(post.topic_id, post.reply_to_post_number.present?)
|
2013-06-21 10:36:33 -05:00
|
|
|
|
|
|
|
cooking_options = post.cooking_options || {}
|
|
|
|
cooking_options[:topic_id] = post.topic_id
|
|
|
|
|
2015-09-29 11:51:26 -05:00
|
|
|
post.cooked ||= post.cook(post.raw, cooking_options.symbolize_keys)
|
2013-06-09 11:48:44 -05:00
|
|
|
post.sort_order = post.post_number
|
|
|
|
post.last_version_at ||= Time.now
|
|
|
|
end
|
|
|
|
|
2015-09-25 10:28:41 -05:00
|
|
|
def self.set_reply_info(post)
|
2014-02-10 13:29:31 -06:00
|
|
|
return unless post.reply_to_post_number.present?
|
|
|
|
|
2015-09-25 10:28:41 -05:00
|
|
|
reply_info = Post.where(topic_id: post.topic_id, post_number: post.reply_to_post_number)
|
|
|
|
.select(:user_id, :post_type)
|
|
|
|
.first
|
|
|
|
|
|
|
|
if reply_info.present?
|
|
|
|
post.reply_to_user_id ||= reply_info.user_id
|
|
|
|
whisper_type = Post.types[:whisper]
|
|
|
|
post.post_type = whisper_type if reply_info.post_type == whisper_type
|
|
|
|
end
|
2014-02-10 13:29:31 -06:00
|
|
|
end
|
2013-06-09 11:48:44 -05:00
|
|
|
|
2013-05-02 00:15:17 -05:00
|
|
|
protected
|
|
|
|
|
2015-08-02 23:29:04 -05:00
|
|
|
def build_post_stats
|
|
|
|
if PostCreator.track_post_stats
|
|
|
|
draft_key = @topic ? "topic_#{@topic.id}" : "new_topic"
|
|
|
|
|
|
|
|
sequence = DraftSequence.current(@user, draft_key)
|
|
|
|
revisions = Draft.where(sequence: sequence,
|
|
|
|
user_id: @user.id,
|
|
|
|
draft_key: draft_key).pluck(:revisions).first || 0
|
|
|
|
|
|
|
|
@post.build_post_stat(
|
|
|
|
drafts_saved: revisions,
|
|
|
|
typing_duration_msecs: @opts[:typing_duration_msecs] || 0,
|
|
|
|
composer_open_duration_msecs: @opts[:composer_open_duration_msecs] || 0
|
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-03-31 11:58:56 -05:00
|
|
|
def trigger_after_events(post)
|
|
|
|
DiscourseEvent.trigger(:topic_created, post.topic, @opts, @user) unless @opts[:topic_id]
|
|
|
|
DiscourseEvent.trigger(:post_created, post, @opts, @user)
|
|
|
|
end
|
|
|
|
|
2016-04-11 22:29:48 -05:00
|
|
|
def auto_close
|
|
|
|
if @post.topic.private_message? &&
|
|
|
|
!@post.topic.closed &&
|
|
|
|
SiteSetting.auto_close_messages_post_count > 0 &&
|
|
|
|
SiteSetting.auto_close_messages_post_count <= @post.topic.posts_count
|
|
|
|
|
|
|
|
@post.topic.update_status(:closed, true, Discourse.system_user,
|
|
|
|
message: I18n.t('topic_statuses.autoclosed_message_max_posts', count: SiteSetting.auto_close_messages_post_count))
|
|
|
|
|
|
|
|
elsif !@post.topic.private_message? &&
|
|
|
|
!@post.topic.closed &&
|
|
|
|
SiteSetting.auto_close_topics_post_count > 0 &&
|
|
|
|
SiteSetting.auto_close_topics_post_count <= @post.topic.posts_count
|
|
|
|
|
|
|
|
@post.topic.update_status(:closed, true, Discourse.system_user,
|
2016-04-12 15:42:52 -05:00
|
|
|
message: I18n.t('topic_statuses.autoclosed_topic_max_posts', count: SiteSetting.auto_close_topics_post_count))
|
2016-04-11 22:29:48 -05:00
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-07-29 23:04:27 -05:00
|
|
|
def transaction(&blk)
|
|
|
|
Post.transaction do
|
|
|
|
if new_topic?
|
|
|
|
blk.call
|
|
|
|
else
|
|
|
|
# we need to ensure post_number is monotonically increasing with no gaps
|
|
|
|
# so we serialize creation to avoid needing rollbacks
|
|
|
|
DistributedMutex.synchronize("topic_id_#{@opts[:topic_id]}", &blk)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-04-03 13:42:26 -05:00
|
|
|
# You can supply an `embed_url` for a post to set up the embedded relationship.
|
|
|
|
# This is used by the wp-discourse plugin to associate a remote post with a
|
|
|
|
# discourse post.
|
|
|
|
def create_embedded_topic
|
|
|
|
return unless @opts[:embed_url].present?
|
2015-06-15 11:08:55 -05:00
|
|
|
embed = TopicEmbed.new(topic_id: @post.topic_id, post_id: @post.id, embed_url: @opts[:embed_url])
|
|
|
|
rollback_from_errors!(embed) unless embed.save
|
2014-04-03 13:42:26 -05:00
|
|
|
end
|
|
|
|
|
2014-02-10 13:29:31 -06:00
|
|
|
def handle_spam
|
|
|
|
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(', ')} } )
|
2015-03-26 15:57:50 -05:00
|
|
|
elsif @post && errors.blank? && !skip_validations?
|
2014-02-10 13:29:31 -06:00
|
|
|
SpamRulesEnforcer.enforce!(@post)
|
2013-10-17 01:44:56 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-02-10 13:29:31 -06:00
|
|
|
def track_latest_on_category
|
|
|
|
return unless @post && @post.errors.count == 0 && @topic && @topic.category_id
|
|
|
|
|
|
|
|
Category.where(id: @topic.category_id).update_all(latest_post_id: @post.id)
|
2015-04-23 12:33:29 -05:00
|
|
|
Category.where(id: @topic.category_id).update_all(latest_topic_id: @topic.id) if @post.is_first_post?
|
2014-02-10 13:29:31 -06:00
|
|
|
end
|
|
|
|
|
2013-09-05 23:07:23 -05:00
|
|
|
def ensure_in_allowed_users
|
2016-01-13 17:38:04 -06:00
|
|
|
return unless @topic.private_message? && @topic.id
|
2013-09-05 23:07:23 -05:00
|
|
|
|
|
|
|
unless @topic.topic_allowed_users.where(user_id: @user.id).exists?
|
2016-01-11 20:57:45 -06:00
|
|
|
unless @topic.topic_allowed_groups.where('group_id IN (
|
|
|
|
SELECT group_id FROM group_users where user_id = ?
|
|
|
|
)',@user.id).exists?
|
|
|
|
@topic.topic_allowed_users.create!(user_id: @user.id)
|
|
|
|
end
|
2013-09-05 23:07:23 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-12-22 18:09:17 -06:00
|
|
|
def unarchive_message
|
|
|
|
return unless @topic.private_message? && @topic.id
|
|
|
|
|
2016-02-07 06:39:07 -06:00
|
|
|
UserArchivedMessage.where(topic_id: @topic.id).pluck(:user_id).each do |user_id|
|
|
|
|
UserArchivedMessage.move_to_inbox!(user_id, @topic.id)
|
|
|
|
end
|
|
|
|
|
|
|
|
GroupArchivedMessage.where(topic_id: @topic.id).pluck(:group_id).each do |group_id|
|
|
|
|
GroupArchivedMessage.move_to_inbox!(group_id, @topic.id)
|
|
|
|
end
|
2015-12-22 18:09:17 -06:00
|
|
|
end
|
|
|
|
|
2013-06-04 13:13:01 -05:00
|
|
|
private
|
|
|
|
|
2015-03-26 15:57:50 -05:00
|
|
|
def create_topic
|
|
|
|
return if @topic
|
|
|
|
begin
|
2013-06-04 13:13:01 -05:00
|
|
|
topic_creator = TopicCreator.new(@user, guardian, @opts)
|
2015-03-26 15:57:50 -05:00
|
|
|
@topic = topic_creator.create
|
|
|
|
rescue ActiveRecord::Rollback
|
2016-05-05 07:58:25 -05:00
|
|
|
rollback_from_errors!(topic_creator)
|
2013-05-02 00:15:17 -05:00
|
|
|
end
|
2015-03-26 15:57:50 -05:00
|
|
|
@post.topic_id = @topic.id
|
|
|
|
@post.topic = @topic
|
2013-05-02 00:15:17 -05:00
|
|
|
end
|
|
|
|
|
2013-07-22 00:06:53 -05:00
|
|
|
def update_topic_stats
|
2015-09-22 11:19:02 -05:00
|
|
|
return if @post.post_type == Post.types[:whisper]
|
|
|
|
|
2015-08-12 08:54:51 -05:00
|
|
|
attrs = {
|
|
|
|
last_posted_at: @post.created_at,
|
|
|
|
last_post_user_id: @post.user_id,
|
|
|
|
word_count: (@topic.word_count || 0) + @post.word_count,
|
|
|
|
}
|
2014-03-18 12:40:40 -05:00
|
|
|
attrs[:excerpt] = @post.excerpt(220, strip_links: true) if new_topic?
|
2015-08-12 08:54:51 -05:00
|
|
|
attrs[:bumped_at] = @post.created_at unless @post.no_bump
|
2013-07-22 00:06:53 -05:00
|
|
|
@topic.update_attributes(attrs)
|
|
|
|
end
|
|
|
|
|
2014-10-10 11:21:44 -05:00
|
|
|
def update_topic_auto_close
|
|
|
|
if @topic.auto_close_based_on_last_post && @topic.auto_close_hours
|
|
|
|
@topic.set_auto_close(@topic.auto_close_hours).save
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-06-04 13:13:01 -05:00
|
|
|
def setup_post
|
2015-07-24 15:39:03 -05:00
|
|
|
@opts[:raw] = TextCleaner.normalize_whitespaces(@opts[:raw] || '').gsub(/\s+\z/, "")
|
2014-08-11 17:01:58 -05:00
|
|
|
|
2015-03-26 15:57:50 -05:00
|
|
|
post = Post.new(raw: @opts[:raw],
|
|
|
|
topic_id: @topic.try(:id),
|
|
|
|
user: @user,
|
|
|
|
reply_to_post_number: @opts[:reply_to_post_number])
|
2013-06-04 13:13:01 -05:00
|
|
|
|
2013-06-21 10:36:33 -05:00
|
|
|
# Attributes we pass through to the post instance if present
|
2015-07-24 15:39:03 -05:00
|
|
|
[:post_type, :no_bump, :cooking_options, :image_sizes, :acting_user, :invalidate_oneboxes, :cook_method, :via_email, :raw_email, :action_code].each do |a|
|
2013-06-21 10:36:33 -05:00
|
|
|
post.send("#{a}=", @opts[a]) if @opts[a].present?
|
|
|
|
end
|
|
|
|
|
2013-06-04 13:13:01 -05:00
|
|
|
post.extract_quoted_post_numbers
|
|
|
|
post.created_at = Time.zone.parse(@opts[:created_at].to_s) if @opts[:created_at].present?
|
2014-02-10 13:29:31 -06:00
|
|
|
|
2014-05-17 20:33:34 -05:00
|
|
|
if fields = @opts[:custom_fields]
|
|
|
|
post.custom_fields = fields
|
|
|
|
end
|
|
|
|
|
2013-06-04 13:13:01 -05:00
|
|
|
@post = post
|
|
|
|
end
|
|
|
|
|
|
|
|
def save_post
|
2015-04-21 12:16:05 -05:00
|
|
|
@post.disable_rate_limits! if skip_validations?
|
2015-03-26 15:57:50 -05:00
|
|
|
saved = @post.save(validate: !skip_validations?)
|
|
|
|
rollback_from_errors!(@post) unless saved
|
2013-05-02 00:15:17 -05:00
|
|
|
end
|
2013-06-04 13:13:01 -05:00
|
|
|
|
|
|
|
def store_unique_post_key
|
2013-09-09 15:17:31 -05:00
|
|
|
@post.store_unique_post_key
|
2013-06-04 13:13:01 -05:00
|
|
|
end
|
|
|
|
|
2014-07-28 12:17:37 -05:00
|
|
|
def update_user_counts
|
2016-05-17 12:22:19 -05:00
|
|
|
return if @opts[:import_mode]
|
|
|
|
|
2014-07-28 12:17:37 -05:00
|
|
|
@user.create_user_stat if @user.user_stat.nil?
|
2014-02-10 13:29:31 -06:00
|
|
|
|
2014-07-28 12:17:37 -05:00
|
|
|
if @user.user_stat.first_post_created_at.nil?
|
|
|
|
@user.user_stat.first_post_created_at = @post.created_at
|
|
|
|
end
|
|
|
|
|
2016-01-23 23:39:01 -06:00
|
|
|
unless @post.topic.private_message?
|
|
|
|
@user.user_stat.post_count += 1
|
|
|
|
@user.user_stat.topic_count += 1 if @post.is_first_post?
|
|
|
|
end
|
2013-06-04 13:13:01 -05:00
|
|
|
|
|
|
|
# We don't count replies to your own topics
|
2014-07-03 13:43:24 -05:00
|
|
|
if !@opts[:import_mode] && @user.id != @topic.user_id
|
2013-10-03 22:28:49 -05:00
|
|
|
@user.user_stat.update_topic_reply_count
|
2013-06-04 13:13:01 -05:00
|
|
|
end
|
|
|
|
|
2014-07-28 12:17:37 -05:00
|
|
|
@user.user_stat.save!
|
|
|
|
|
2015-08-12 08:54:51 -05:00
|
|
|
@user.update_attributes(last_posted_at: @post.created_at)
|
2013-06-04 13:13:01 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def publish
|
2014-07-03 13:43:24 -05:00
|
|
|
return if @opts[:import_mode]
|
2014-02-10 13:29:31 -06:00
|
|
|
return unless @post.post_number > 1
|
|
|
|
|
2014-08-28 22:34:32 -05:00
|
|
|
@post.publish_change_to_clients! :created
|
2013-06-04 13:13:01 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def extract_links
|
|
|
|
TopicLink.extract_from(@post)
|
2014-07-15 02:47:24 -05:00
|
|
|
QuotedPost.extract_from(@post)
|
2013-06-04 13:13:01 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def track_topic
|
2014-02-10 13:29:31 -06:00
|
|
|
return if @opts[:auto_track] == false
|
|
|
|
|
2014-08-29 00:07:40 -05:00
|
|
|
TopicUser.change(@post.user_id,
|
|
|
|
@topic.id,
|
2014-02-10 13:29:31 -06:00
|
|
|
posted: true,
|
|
|
|
last_read_post_number: @post.post_number,
|
2014-10-30 17:40:35 -05:00
|
|
|
highest_seen_post_number: @post.post_number)
|
2014-06-03 20:41:42 -05:00
|
|
|
|
|
|
|
|
|
|
|
# assume it took us 5 seconds of reading time to make a post
|
|
|
|
PostTiming.record_timing(topic_id: @post.topic_id,
|
|
|
|
user_id: @post.user_id,
|
|
|
|
post_number: @post.post_number,
|
|
|
|
msecs: 5000)
|
|
|
|
|
2015-11-18 15:24:46 -06:00
|
|
|
if @user.staged
|
|
|
|
TopicUser.auto_watch(@user.id, @topic.id)
|
|
|
|
else
|
|
|
|
TopicUser.auto_track(@user.id, @topic.id, TopicUser.notification_reasons[:created_post])
|
|
|
|
end
|
2013-06-04 13:13:01 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
def enqueue_jobs
|
2014-02-10 13:29:31 -06:00
|
|
|
return unless @post && !@post.errors.present?
|
2014-07-03 13:43:24 -05:00
|
|
|
PostJobsEnqueuer.new(@post, @topic, new_topic?, {import_mode: @opts[:import_mode]}).enqueue_jobs
|
2014-02-17 00:57:37 -06:00
|
|
|
end
|
2014-02-10 13:29:31 -06:00
|
|
|
|
2014-02-17 00:57:37 -06:00
|
|
|
def new_topic?
|
|
|
|
@opts[:topic_id].blank?
|
2013-06-04 13:13:01 -05:00
|
|
|
end
|
2014-02-17 00:57:37 -06:00
|
|
|
|
2013-02-05 13:16:51 -06:00
|
|
|
end
|