96 lines
2.9 KiB
Ruby
96 lines
2.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Chat::ChatMessageUpdater
|
|
attr_reader :error
|
|
|
|
def self.update(opts)
|
|
instance = new(**opts)
|
|
instance.update
|
|
instance
|
|
end
|
|
|
|
def initialize(guardian:, chat_message:, new_content:, upload_ids: nil)
|
|
@guardian = guardian
|
|
@user = guardian.user
|
|
@chat_message = chat_message
|
|
@old_message_content = chat_message.message
|
|
@chat_channel = @chat_message.chat_channel
|
|
@new_content = new_content
|
|
@upload_ids = upload_ids
|
|
@error = nil
|
|
end
|
|
|
|
def update
|
|
begin
|
|
validate_channel_status!
|
|
@guardian.ensure_can_edit_chat!(@chat_message)
|
|
@chat_message.message = @new_content
|
|
@chat_message.last_editor_id = @user.id
|
|
upload_info = get_upload_info
|
|
validate_message!(has_uploads: upload_info[:uploads].any?)
|
|
@chat_message.cook
|
|
@chat_message.save!
|
|
update_uploads(upload_info)
|
|
revision = save_revision!
|
|
@chat_message.reload
|
|
ChatPublisher.publish_edit!(@chat_channel, @chat_message)
|
|
Jobs.enqueue(:process_chat_message, { chat_message_id: @chat_message.id })
|
|
Chat::ChatNotifier.notify_edit(chat_message: @chat_message, timestamp: revision.created_at)
|
|
DiscourseEvent.trigger(:chat_message_edited, @chat_message, @chat_channel, @user)
|
|
rescue => error
|
|
@error = error
|
|
end
|
|
end
|
|
|
|
def failed?
|
|
@error.present?
|
|
end
|
|
|
|
private
|
|
|
|
def validate_channel_status!
|
|
return if @guardian.can_modify_channel_message?(@chat_channel)
|
|
raise StandardError.new(
|
|
I18n.t("chat.errors.channel_modify_message_disallowed.#{@chat_channel.status}"),
|
|
)
|
|
end
|
|
|
|
def validate_message!(has_uploads:)
|
|
@chat_message.validate_message(has_uploads: has_uploads)
|
|
if @chat_message.errors.present?
|
|
raise StandardError.new(@chat_message.errors.map(&:full_message).join(", "))
|
|
end
|
|
end
|
|
|
|
def get_upload_info
|
|
return { uploads: [] } if @upload_ids.nil? || !SiteSetting.chat_allow_uploads
|
|
|
|
uploads = Upload.where(id: @upload_ids, user_id: @user.id)
|
|
if uploads.count != @upload_ids.count
|
|
# User is passing upload_ids for uploads that they don't own. Don't change anything.
|
|
return { uploads: @chat_message.uploads, changed: false }
|
|
end
|
|
|
|
new_upload_ids = uploads.map(&:id)
|
|
existing_upload_ids = @chat_message.upload_ids
|
|
difference = (existing_upload_ids + new_upload_ids) - (existing_upload_ids & new_upload_ids)
|
|
{ uploads: uploads, changed: difference.any? }
|
|
end
|
|
|
|
def update_uploads(upload_info)
|
|
return unless upload_info[:changed]
|
|
|
|
DB.exec("DELETE FROM chat_uploads WHERE chat_message_id = #{@chat_message.id}")
|
|
UploadReference.where(target: @chat_message).destroy_all
|
|
@chat_message.attach_uploads(upload_info[:uploads])
|
|
end
|
|
|
|
def save_revision!
|
|
@chat_message.revisions.create!(
|
|
old_message: @old_message_content,
|
|
new_message: @chat_message.message,
|
|
user_id: @user.id,
|
|
)
|
|
end
|
|
end
|