diff --git a/app/models/chat_message.rb b/app/models/chat_message.rb index 39dcbd2ad..d50ee7a99 100644 --- a/app/models/chat_message.rb +++ b/app/models/chat_message.rb @@ -3,6 +3,7 @@ class ChatMessage < ApplicationRecord include ChatServices::Spam include ChatServices::PrivateConversation include Deeplinkable + include Mentionable include Translatable include Reactionnable include Surveyable diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb new file mode 100644 index 000000000..0c4476440 --- /dev/null +++ b/app/models/concerns/mentionable.rb @@ -0,0 +1,56 @@ +module Mentionable + extend ActiveSupport::Concern + + included do + after_create :has_mentions!, if: :has_mentions? + end + + MentionsStruct = Struct.new(:instance) do + def initialize(instance: nil) + @instance = instance + end + + def no_html + document = Nokogiri::HTML(@instance.content) + document.css('img, a').each { |node| node.remove } + document.text.strip + end + + def fragments + @fragments ||= Nokogiri::HTML.fragment(@instance.content) + end + + def contains_html? + fragments.children.any? + end + + def contains_anchor_with_href? + fragments.css('a[href]').any? + end + + def contains_user_link? + fragments.css('a[href]').any? { |a| a['href'].include?('app/users') } + end + + def extract_user_uuid + user_links = fragments.css('a[href]').select { |a| a['href'].include?('app/users') } + + user_links.map do |a| + a['href'][%r{app/users/([^/]+)}, 1] + end + end + end + + def mentions + @mentions ||= MentionsStruct.new(instance: self) + end + + def has_mentions? + mentions.extract_user_uuid.any? + end + + def has_mentions! + # @todo perform in a job + PushNotificationTrigger.new(self, :mention, Hash.new).run + end +end diff --git a/app/services/push_notification_trigger.rb b/app/services/push_notification_trigger.rb index a08a057d7..246b33bb4 100644 --- a/app/services/push_notification_trigger.rb +++ b/app/services/push_notification_trigger.rb @@ -428,6 +428,33 @@ def comment_on_create end end + def chat_message_on_mention + return unless @record.respond_to?(:mentions) + return unless @record.mentions.respond_to?(:extract_user_uuid) + + user_ids = User.where(uuid: @record.mentions.extract_user_uuid).pluck(:id).uniq + + return unless user_ids.any? + + puts "-- push to: #{user_ids}" + + User.where(id: user_ids).find_in_batches(batch_size: 100) do |batches| + notify( + sender_id: @record.user_id, + referent: @record.messageable, + instance: @record.messageable, + users: batches, + params: { + object: I18nStruct.new(i18n: 'push_notifications.chat_message.mention', i18n_args: [username(@record.user)]), + content: I18nStruct.new(instance: @record, field: :content), + extra: { + tracking: :chat_message_on_mention + } + } + ) + end + end + def user_reaction_on_create return unless @record.respond_to?(:instance) return unless @record.instance.respond_to?(:user_id) diff --git a/config/locales/entourage.fr.yml b/config/locales/entourage.fr.yml index ebfe9a444..3fbc4d710 100644 --- a/config/locales/entourage.fr.yml +++ b/config/locales/entourage.fr.yml @@ -367,6 +367,8 @@ fr: day_before: title: "🔔 Rappel : «%s» a lieu demain !" content: "N'oubliez pas, cet événement est pour demain. Est-ce que vous venez toujours ?" + chat_message: + mention: "%s vous a mentionné dans son message" post: create: "%s vient de partager : \"%s\"" comment: