# frozen_string_literal: true module Jobs class ChatNotifyMentioned < ::Jobs::Base def execute(args = {}) @chat_message = ChatMessage.includes(:user, :revisions, chat_channel: :chatable).find_by( id: args[:chat_message_id], ) if @chat_message.nil? || @chat_message.revisions.where("created_at > ?", args[:timestamp]).any? return end @creator = @chat_message.user @chat_channel = @chat_message.chat_channel @already_notified_user_ids = args[:already_notified_user_ids] || [] user_ids_to_notify = args[:to_notify_ids_map] || {} user_ids_to_notify.each { |mention_type, ids| process_mentions(ids, mention_type.to_sym) } end private def get_memberships(user_ids) query = UserChatChannelMembership.includes(:user).where( user_id: (user_ids - @already_notified_user_ids), chat_channel_id: @chat_message.chat_channel_id, ) query = query.where(following: true) if @chat_channel.public_channel? query end def build_data_for(membership, identifier_type:) data = { chat_message_id: @chat_message.id, chat_channel_id: @chat_channel.id, mentioned_by_username: @creator.username, is_direct_message_channel: @chat_channel.direct_message_channel?, } if !@is_direct_message_channel data[:chat_channel_title] = @chat_channel.title(membership.user) data[:chat_channel_slug] = @chat_channel.slug end return data if identifier_type == :direct_mentions case identifier_type when :here_mentions data[:identifier] = "here" when :global_mentions data[:identifier] = "all" else data[:identifier] = identifier_type if identifier_type data[:is_group_mention] = true end data end def build_payload_for(membership, identifier_type:) payload = { notification_type: Notification.types[:chat_mention], username: @creator.username, tag: Chat::ChatNotifier.push_notification_tag(:mention, @chat_channel.id), excerpt: @chat_message.push_notification_excerpt, post_url: "#{@chat_channel.relative_url}?messageId=#{@chat_message.id}", } translation_prefix = ( if @chat_channel.direct_message_channel? "discourse_push_notifications.popup.direct_message_chat_mention" else "discourse_push_notifications.popup.chat_mention" end ) translation_suffix = identifier_type == :direct_mentions ? "direct" : "other_type" identifier_text = case identifier_type when :here_mentions "@here" when :global_mentions "@all" when :direct_mentions "" else "@#{identifier_type}" end payload[:translated_title] = I18n.t( "#{translation_prefix}.#{translation_suffix}", username: @creator.username, identifier: identifier_text, channel: @chat_channel.title(membership.user), ) payload end def create_notification!(membership, notification_data) is_read = Chat::ChatNotifier.user_has_seen_message?(membership, @chat_message.id) notification = Notification.create!( notification_type: Notification.types[:chat_mention], user_id: membership.user_id, high_priority: true, data: notification_data.to_json, read: is_read, ) ChatMention.create!( notification: notification, user: membership.user, chat_message: @chat_message, ) end def send_notifications(membership, notification_data, os_payload) create_notification!(membership, notification_data) if !membership.desktop_notifications_never? && !membership.muted? MessageBus.publish( "/chat/notification-alert/#{membership.user_id}", os_payload, user_ids: [membership.user_id], ) end if !membership.mobile_notifications_never? && !membership.muted? PostAlerter.push_notification(membership.user, os_payload) end end def process_mentions(user_ids, mention_type) memberships = get_memberships(user_ids) memberships.each do |membership| notification_data = build_data_for(membership, identifier_type: mention_type) payload = build_payload_for(membership, identifier_type: mention_type) send_notifications(membership, notification_data, payload) end end end end