discourse/plugins/chat/lib/extensions/user_notifications_extension.rb
Joffrey JAFFEUX 06ad13b517
DEV: makes test more deterministic (#20078)
`last_message_sent_at` could be equal and as a result the order would be random causing random spec failures in plugins/chat/spec/mailers/user_notifications_spec.rb:182
2023-01-30 22:02:32 +01:00

141 lines
4.8 KiB
Ruby

# frozen_string_literal: true
module Chat::UserNotificationsExtension
def chat_summary(user, opts)
guardian = Guardian.new(user)
return unless guardian.can_chat?
@messages =
ChatMessage
.joins(:user, :chat_channel)
.where.not(user: user)
.where("chat_messages.created_at > ?", 1.week.ago)
.joins("LEFT OUTER JOIN chat_mentions cm ON cm.chat_message_id = chat_messages.id")
.joins(
"INNER JOIN user_chat_channel_memberships uccm ON uccm.chat_channel_id = chat_channels.id",
)
.where(<<~SQL, user_id: user.id)
uccm.user_id = :user_id AND
(uccm.last_read_message_id IS NULL OR chat_messages.id > uccm.last_read_message_id) AND
(uccm.last_unread_mention_when_emailed_id IS NULL OR chat_messages.id > uccm.last_unread_mention_when_emailed_id) AND
(
(cm.user_id = :user_id AND uccm.following IS true AND chat_channels.chatable_type = 'Category') OR
(chat_channels.chatable_type = 'DirectMessage')
)
SQL
.to_a
return if @messages.empty?
@grouped_messages = @messages.group_by { |message| message.chat_channel }
@grouped_messages =
@grouped_messages.select { |channel, _| guardian.can_join_chat_channel?(channel) }
return if @grouped_messages.empty?
@grouped_messages.each do |chat_channel, messages|
@grouped_messages[chat_channel] = messages.sort_by(&:created_at)
end
@user = user
@user_tz = UserOption.user_tzinfo(user.id)
@display_usernames = SiteSetting.prioritize_username_in_ux || !SiteSetting.enable_names
build_summary_for(user)
@preferences_path = "#{Discourse.base_url}/my/preferences/chat"
# TODO(roman): Remove after the 2.9 release
add_unsubscribe_link = UnsubscribeKey.respond_to?(:get_unsubscribe_strategy_for)
if add_unsubscribe_link
unsubscribe_key = UnsubscribeKey.create_key_for(@user, "chat_summary")
@unsubscribe_link = "#{Discourse.base_url}/email/unsubscribe/#{unsubscribe_key}"
opts[:unsubscribe_url] = @unsubscribe_link
end
opts = {
from_alias: I18n.t("user_notifications.chat_summary.from", site_name: Email.site_title),
subject: summary_subject(user, @grouped_messages),
add_unsubscribe_link: add_unsubscribe_link,
}
build_email(user.email, opts)
end
def summary_subject(user, grouped_messages)
all_channels = grouped_messages.keys
grouped_channels = all_channels.partition { |c| !c.direct_message_channel? }
channels = grouped_channels.first
dm_messages = grouped_channels.last.flat_map { |c| grouped_messages[c] }
dm_users = dm_messages.sort_by(&:created_at).uniq { |m| m.user_id }.map(&:user)
# Prioritize messages from regular channels over direct messages
if channels.any?
channel_notification_text(
channels.sort_by { |channel| [channel.last_message_sent_at, channel.created_at] },
dm_users,
)
else
direct_message_notification_text(dm_users)
end
end
private
def channel_notification_text(channels, dm_users)
total_count = channels.size + dm_users.size
if total_count > 2
I18n.t(
"user_notifications.chat_summary.subject.chat_channel_more",
email_prefix: @email_prefix,
channel: channels.first.title,
count: total_count - 1,
)
elsif channels.size == 1 && dm_users.size == 0
I18n.t(
"user_notifications.chat_summary.subject.chat_channel_1",
email_prefix: @email_prefix,
channel: channels.first.title,
)
elsif channels.size == 1 && dm_users.size == 1
I18n.t(
"user_notifications.chat_summary.subject.chat_channel_and_direct_message",
email_prefix: @email_prefix,
channel: channels.first.title,
username: dm_users.first.username,
)
elsif channels.size == 2
I18n.t(
"user_notifications.chat_summary.subject.chat_channel_2",
email_prefix: @email_prefix,
channel1: channels.first.title,
channel2: channels.second.title,
)
end
end
def direct_message_notification_text(dm_users)
case dm_users.size
when 1
I18n.t(
"user_notifications.chat_summary.subject.direct_message_from_1",
email_prefix: @email_prefix,
username: dm_users.first.username,
)
when 2
I18n.t(
"user_notifications.chat_summary.subject.direct_message_from_2",
email_prefix: @email_prefix,
username1: dm_users.first.username,
username2: dm_users.second.username,
)
else
I18n.t(
"user_notifications.chat_summary.subject.direct_message_from_more",
email_prefix: @email_prefix,
username: dm_users.first.username,
count: dm_users.size - 1,
)
end
end
end