DEV: Create and update chat message mentions earlier (#21388)

We need to create and update `chat_mentions` records for messages earlier. They should be created or updated before we  call `Chat::Publisher.publish_new!` `Chat::Publisher.publish_edit!` to send the message to message bus subscribers).

This logic is covered with tests in `message_creator_spec.rb`, `message_updater_spec.rb`, `notifier_spec.rb` and `notify_mentioned_spec.rb`.

See the commits history for steps of refactoring.
This commit is contained in:
Andrei Prigorshnev
2023-05-05 15:47:07 +04:00
committed by GitHub
parent 78616404ce
commit 35a414bb38
7 changed files with 104 additions and 65 deletions

View File

@ -52,9 +52,12 @@ module Chat
validate_message!(has_uploads: uploads.any?)
validate_reply_chain!
validate_existing_thread!
@chat_message.thread_id = @existing_thread&.id
@chat_message.cook
@chat_message.save!
@chat_message.create_mentions
create_chat_webhook_event
create_thread
@chat_message.attach_uploads(uploads)

View File

@ -31,8 +31,11 @@ module Chat
validate_message!(has_uploads: upload_info[:uploads].any?)
@chat_message.cook
@chat_message.save!
@chat_message.update_mentions
update_uploads(upload_info)
revision = save_revision!
@chat_message.reload
Chat::Publisher.publish_edit!(@chat_channel, @chat_message)
Jobs.enqueue(Jobs::Chat::ProcessMessage, { chat_message_id: @chat_message.id })

View File

@ -61,16 +61,11 @@ module Chat
@timestamp = timestamp
@chat_channel = @chat_message.chat_channel
@user = @chat_message.user
@mentions = Chat::MessageMentions.new(chat_message)
end
### Public API
def notify_new
if @mentions.all_mentioned_users_ids.present?
@chat_message.create_mentions(@mentions.all_mentioned_users_ids)
end
to_notify = list_users_to_notify
mentioned_user_ids = to_notify.extract!(:all_mentioned_user_ids)[:all_mentioned_user_ids]
@ -87,8 +82,6 @@ module Chat
end
def notify_edit
@chat_message.update_mentions(@mentions.all_mentioned_users_ids)
already_notified_user_ids =
Chat::Mention
.where(chat_message: @chat_message)
@ -108,7 +101,8 @@ module Chat
private
def list_users_to_notify
skip_notifications = @mentions.count > SiteSetting.max_mentions_per_chat_message
skip_notifications =
@chat_message.parsed_mentions.count > SiteSetting.max_mentions_per_chat_message
{}.tap do |to_notify|
# The order of these methods is the precedence
@ -130,10 +124,11 @@ module Chat
end
def expand_global_mention(to_notify, already_covered_ids)
has_all_mention = @mentions.has_global_mention
has_all_mention = @chat_message.parsed_mentions.has_global_mention
if has_all_mention && @chat_channel.allow_channel_wide_mentions
to_notify[:global_mentions] = @mentions
to_notify[:global_mentions] = @chat_message
.parsed_mentions
.global_mentions
.not_suspended
.where(user_options: { ignore_channel_wide_mention: [false, nil] })
@ -147,10 +142,11 @@ module Chat
end
def expand_here_mention(to_notify, already_covered_ids)
has_here_mention = @mentions.has_here_mention
has_here_mention = @chat_message.parsed_mentions.has_here_mention
if has_here_mention && @chat_channel.allow_channel_wide_mentions
to_notify[:here_mentions] = @mentions
to_notify[:here_mentions] = @chat_message
.parsed_mentions
.here_mentions
.not_suspended
.where(user_options: { ignore_channel_wide_mention: [false, nil] })
@ -190,7 +186,10 @@ module Chat
if skip
direct_mentions = []
else
direct_mentions = @mentions.direct_mentions.not_suspended.where.not(id: already_covered_ids)
direct_mentions =
@chat_message.parsed_mentions.direct_mentions.not_suspended.where.not(
id: already_covered_ids,
)
end
grouped = group_users_to_notify(direct_mentions)
@ -202,21 +201,24 @@ module Chat
end
def expand_group_mentions(to_notify, already_covered_ids)
return if @mentions.visible_groups.empty?
return if @chat_message.parsed_mentions.visible_groups.empty?
reached_by_group =
@mentions
@chat_message
.parsed_mentions
.group_mentions
.not_suspended
.where("user_count <= ?", SiteSetting.max_users_notified_per_group_mention)
.where.not(id: already_covered_ids)
too_many_members, mentionable =
@mentions.mentionable_groups.partition do |group|
@chat_message.parsed_mentions.mentionable_groups.partition do |group|
group.user_count > SiteSetting.max_users_notified_per_group_mention
end
mentions_disabled = @mentions.visible_groups - @mentions.mentionable_groups
mentions_disabled =
@chat_message.parsed_mentions.visible_groups -
@chat_message.parsed_mentions.mentionable_groups
to_notify[:group_mentions_disabled] = mentions_disabled
to_notify[:too_many_members] = too_many_members
mentionable.each { |g| to_notify[g.name.downcase] = [] }
@ -226,7 +228,8 @@ module Chat
# When a user is a member of multiple mentioned groups,
# the most far to the left should take precedence.
ordered_group_names =
@mentions.parsed_group_mentions & mentionable.map { |mg| mg.name.downcase }
@chat_message.parsed_mentions.parsed_group_mentions &
mentionable.map { |mg| mg.name.downcase }
user_group_names = user.groups.map { |ug| ug.name.downcase }
group_name = ordered_group_names.detect { |gn| user_group_names.include?(gn) }

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
module Chat
class MessageMentions
class ParsedMentions
def initialize(message)
@message = message