diff --git a/Gemfile b/Gemfile index c4989c538..8c0bb82a5 100644 --- a/Gemfile +++ b/Gemfile @@ -22,6 +22,7 @@ gem 'time_diff' gem 'tzinfo-data' gem 'valid_email2' gem 'email-provider-info' +gem 'gemoji' # compress javascript config.assets.js_compressor gem 'uglifier' ##-- used for single column multiple binary flags in notification settings/feature flagging --## diff --git a/Gemfile.lock b/Gemfile.lock index 5912172f5..d85999b57 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -349,6 +349,7 @@ GEM googleapis-common-protos-types (>= 1.3.1, < 2.a) googleauth (~> 1.0) grpc (~> 1.36) + gemoji (4.1.0) geocoder (1.8.1) gli (2.22.2) ostruct @@ -1075,6 +1076,7 @@ DEPENDENCIES fcm flag_shih_tzu foreman + gemoji geocoder gmail_xoauth google-cloud-dialogflow-v2 (>= 0.24.0) diff --git a/lib/integrations/slack/emoji_formatter.rb b/lib/integrations/slack/emoji_formatter.rb new file mode 100644 index 000000000..727c14784 --- /dev/null +++ b/lib/integrations/slack/emoji_formatter.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class Integrations::Slack::EmojiFormatter + def self.format(text) + return text if text.blank? + + text.gsub(/:([a-zA-Z0-9_+-]+):/) do |match| + short_code = Regexp.last_match(1) + # gemoji exposes find_by_alias; Rails/DynamicFindBy is a false positive because Emoji is not an ActiveRecord model. + # rubocop:disable Rails/DynamicFindBy + emoji = Emoji.find_by_alias(short_code) + # rubocop:enable Rails/DynamicFindBy + emoji ? emoji.raw : match + end + end +end diff --git a/lib/integrations/slack/slack_message_helper.rb b/lib/integrations/slack/slack_message_helper.rb index 3af57a4c3..110156b06 100644 --- a/lib/integrations/slack/slack_message_helper.rb +++ b/lib/integrations/slack/slack_message_helper.rb @@ -35,7 +35,7 @@ module Integrations::Slack::SlackMessageHelper message_type: :outgoing, account_id: conversation.account_id, inbox_id: conversation.inbox_id, - content: Slack::Messages::Formatting.unescape(params[:event][:text] || ''), + content: formatted_message_content, external_source_id_slack: params[:event][:ts], private: private_note?, sender: resolved_sender, @@ -104,6 +104,11 @@ module Integrations::Slack::SlackMessageHelper [nil, nil, nil] end + def formatted_message_content + text = Slack::Messages::Formatting.unescape(params[:event][:text] || '') + Integrations::Slack::EmojiFormatter.format(text) + end + def private_note? params[:event][:text].strip.downcase.starts_with?('note:', 'private:') end diff --git a/spec/lib/integrations/slack/emoji_formatter_spec.rb b/spec/lib/integrations/slack/emoji_formatter_spec.rb new file mode 100644 index 000000000..d34706e43 --- /dev/null +++ b/spec/lib/integrations/slack/emoji_formatter_spec.rb @@ -0,0 +1,20 @@ +require 'rails_helper' + +describe Integrations::Slack::EmojiFormatter do + describe '.format' do + it 'replaces emoji shortcodes with unicode characters' do + expect(described_class.format('Hello :smile:')).to eq('Hello 😄') + expect(described_class.format('Good job :+1:')).to eq('Good job 👍') + expect(described_class.format('Unknown :unknown_emoji:')).to eq('Unknown :unknown_emoji:') + end + + it 'handles nil or empty text' do + expect(described_class.format(nil)).to be_nil + expect(described_class.format('')).to eq('') + end + + it 'replaces multiple emojis' do + expect(described_class.format(':smile: :+1:')).to eq('😄 👍') + end + end +end