discourse/plugins/chat/app/serializers/chat_message_serializer.rb

154 lines
3.8 KiB
Ruby

# frozen_string_literal: true
class ChatMessageSerializer < ApplicationSerializer
attributes :id,
:message,
:cooked,
:created_at,
:excerpt,
:deleted_at,
:deleted_by_id,
:reviewable_id,
:user_flag_status,
:edited,
:reactions,
:bookmark,
:available_flags,
:thread_id,
:chat_channel_id
has_one :user, serializer: BasicUserWithStatusSerializer, embed: :objects
has_one :chat_webhook_event, serializer: ChatWebhookEventSerializer, embed: :objects
has_one :in_reply_to, serializer: ChatInReplyToSerializer, embed: :objects
has_many :uploads, serializer: UploadSerializer, embed: :objects
def channel
@channel ||= @options.dig(:chat_channel) || object.chat_channel
end
def user
object.user || DeletedChatUser.new
end
def excerpt
WordWatcher.censor(object.excerpt)
end
def reactions
reactions_hash = {}
object
.reactions
.group_by(&:emoji)
.each do |emoji, reactions|
users = reactions[0..6].map(&:user).filter { |user| user.id != scope&.user&.id }[0..5]
next unless Emoji.exists?(emoji)
reactions_hash[emoji] = {
count: reactions.count,
users:
ActiveModel::ArraySerializer.new(users, each_serializer: BasicUserSerializer).as_json,
reacted: users_reactions.include?(emoji),
}
end
reactions_hash
end
def include_reactions?
object.reactions.any?
end
def users_reactions
@users_reactions ||=
object.reactions.select { |reaction| reaction.user_id == scope&.user&.id }.map(&:emoji)
end
def users_bookmark
@user_bookmark ||= object.bookmarks.find { |bookmark| bookmark.user_id == scope&.user&.id }
end
def include_bookmark?
users_bookmark.present?
end
def bookmark
{
id: users_bookmark.id,
reminder_at: users_bookmark.reminder_at,
name: users_bookmark.name,
auto_delete_preference: users_bookmark.auto_delete_preference,
bookmarkable_id: users_bookmark.bookmarkable_id,
bookmarkable_type: users_bookmark.bookmarkable_type,
}
end
def edited
true
end
def include_edited?
object.revisions.any?
end
def deleted_at
object.user ? object.deleted_at : Time.zone.now
end
def deleted_by_id
object.user ? object.deleted_by_id : Discourse.system_user.id
end
def include_deleted_at?
object.user ? !object.deleted_at.nil? : true
end
def include_deleted_by_id?
object.user ? !object.deleted_at.nil? : true
end
def include_in_reply_to?
object.in_reply_to_id.presence
end
def reviewable_id
return @reviewable_id if defined?(@reviewable_id)
return @reviewable_id = nil unless @options && @options[:reviewable_ids]
@reviewable_id = @options[:reviewable_ids][object.id]
end
def include_reviewable_id?
reviewable_id.present?
end
def user_flag_status
return @user_flag_status if defined?(@user_flag_status)
return @user_flag_status = nil unless @options&.dig(:user_flag_statuses)
@user_flag_status = @options[:user_flag_statuses][object.id]
end
def include_user_flag_status?
user_flag_status.present?
end
def available_flags
return [] if !scope.can_flag_chat_message?(object)
return [] if reviewable_id.present? && user_flag_status == ReviewableScore.statuses[:pending]
PostActionType.flag_types.map do |sym, id|
next if channel.direct_message_channel? && %i[notify_moderators notify_user].include?(sym)
if sym == :notify_user &&
(
scope.current_user == user || user.bot? ||
!scope.current_user.in_any_groups?(SiteSetting.personal_message_enabled_groups_map)
)
next
end
sym
end
end
end