feat: Instagram story replies will display the original story link (#6846)
This commit is contained in:
@@ -70,17 +70,28 @@ class Messages::Instagram::MessageBuilder < Messages::Messenger::MessageBuilder
|
||||
@messaging[:message][:text]
|
||||
end
|
||||
|
||||
def story_reply_attributes
|
||||
message[:reply_to][:story] if message[:reply_to].present? && message[:reply_to][:story].present?
|
||||
end
|
||||
|
||||
def build_message
|
||||
return if @outgoing_echo && already_sent_from_chatwoot?
|
||||
return if message_content.blank? && all_unsupported_files?
|
||||
|
||||
@message = conversation.messages.create!(message_params)
|
||||
save_story_id
|
||||
|
||||
attachments.each do |attachment|
|
||||
process_attachment(attachment)
|
||||
end
|
||||
end
|
||||
|
||||
def save_story_id
|
||||
return if story_reply_attributes.blank?
|
||||
|
||||
@message.save_story_info(story_reply_attributes)
|
||||
end
|
||||
|
||||
def build_conversation
|
||||
@contact_inbox ||= contact.contact_inboxes.find_by!(source_id: message_source_id)
|
||||
Conversation.create!(conversation_params.merge(
|
||||
|
||||
@@ -22,6 +22,14 @@
|
||||
:bcc="emailHeadAttributes.bcc"
|
||||
:is-incoming="isIncoming"
|
||||
/>
|
||||
<blockquote v-if="storyReply" class="story-reply-quote">
|
||||
<span>{{ $t('CONVERSATION.REPLIED_TO_STORY') }}</span>
|
||||
<bubble-image
|
||||
v-if="!hasStoryError"
|
||||
:url="storyUrl"
|
||||
@error="onStoryLoadError"
|
||||
/>
|
||||
</blockquote>
|
||||
<bubble-text
|
||||
v-if="data.content"
|
||||
:message="message"
|
||||
@@ -79,7 +87,7 @@
|
||||
:sender="data.sender"
|
||||
:story-sender="storySender"
|
||||
:external-error="externalError"
|
||||
:story-id="storyId"
|
||||
:story-id="`${storyId}`"
|
||||
:is-a-tweet="isATweet"
|
||||
:is-a-whatsapp-channel="isAWhatsAppChannel"
|
||||
:has-instagram-story="hasInstagramStory"
|
||||
@@ -192,6 +200,7 @@ export default {
|
||||
hasImageError: false,
|
||||
contextMenuPosition: {},
|
||||
showBackgroundHighlight: false,
|
||||
hasStoryError: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -277,6 +286,12 @@ export default {
|
||||
storyId() {
|
||||
return this.contentAttributes.story_id || null;
|
||||
},
|
||||
storyUrl() {
|
||||
return this.contentAttributes.story_url || null;
|
||||
},
|
||||
storyReply() {
|
||||
return this.storyUrl && this.hasInstagramStory;
|
||||
},
|
||||
contentType() {
|
||||
const {
|
||||
data: { content_type: contentType },
|
||||
@@ -414,10 +429,12 @@ export default {
|
||||
watch: {
|
||||
data() {
|
||||
this.hasImageError = false;
|
||||
this.hasStoryError = false;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.hasImageError = false;
|
||||
this.hasStoryError = false;
|
||||
bus.$on(BUS_EVENTS.ON_MESSAGE_LIST_SCROLL, this.closeContextMenu);
|
||||
this.setupHighlightTimer();
|
||||
},
|
||||
@@ -432,6 +449,9 @@ export default {
|
||||
const { file_type: fileType } = attachments[0];
|
||||
return fileType === type && !this.hasImageError;
|
||||
}
|
||||
if (this.storyReply) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
handleContextMenuClick() {
|
||||
@@ -443,6 +463,9 @@ export default {
|
||||
onImageLoadError() {
|
||||
this.hasImageError = true;
|
||||
},
|
||||
onStoryLoadError() {
|
||||
this.hasStoryError = true;
|
||||
},
|
||||
openContextMenu(e) {
|
||||
const shouldSkipContextMenu =
|
||||
e.target?.classList.contains('skip-context-menu') ||
|
||||
@@ -672,7 +695,6 @@ li.right {
|
||||
blockquote {
|
||||
border-left: var(--space-micro) solid var(--s-75);
|
||||
color: var(--s-800);
|
||||
padding: var(--space-smaller) var(--space-small);
|
||||
margin: var(--space-smaller) 0;
|
||||
padding: var(--space-small) var(--space-small) 0 var(--space-normal);
|
||||
}
|
||||
@@ -704,4 +726,11 @@ li.right {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.story-reply-quote {
|
||||
border-left: var(--space-micro) solid var(--s-75);
|
||||
color: var(--s-600);
|
||||
margin: var(--space-small) var(--space-normal) 0;
|
||||
padding: var(--space-small) var(--space-small) 0 var(--space-small);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -195,7 +195,7 @@ export default {
|
||||
return '';
|
||||
}
|
||||
const { storySender, storyId } = this;
|
||||
return `https://www.instagram.com/stories/${storySender}/${storyId}`;
|
||||
return `https://www.instagram.com/stories/direct/${storySender}_${storyId}`;
|
||||
},
|
||||
showStatusIndicators() {
|
||||
if ((this.isOutgoing || this.isTemplate) && !this.isPrivate) {
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
"UNKNOWN_FILE_TYPE": "Unknown File",
|
||||
"SAVE_CONTACT": "Save",
|
||||
"UPLOADING_ATTACHMENTS": "Uploading attachments...",
|
||||
"REPLIED_TO_STORY": "Replied to your story",
|
||||
"SUCCESS_DELETE_MESSAGE": "Message deleted successfully",
|
||||
"FAIL_DELETE_MESSSAGE": "Couldn't delete message! Try again",
|
||||
"NO_RESPONSE": "No response",
|
||||
|
||||
@@ -198,6 +198,17 @@ class Message < ApplicationRecord
|
||||
outgoing? && human_response? && not_created_by_automation? && !private?
|
||||
end
|
||||
|
||||
def save_story_info(story_info)
|
||||
self.content_attributes = content_attributes.merge(
|
||||
{
|
||||
story_id: story_info['id'],
|
||||
story_sender: inbox.channel.instagram_id,
|
||||
story_url: story_info['url']
|
||||
}
|
||||
)
|
||||
save!
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_content_type
|
||||
|
||||
@@ -13,6 +13,7 @@ describe ::Messages::Instagram::MessageBuilder do
|
||||
let!(:instagram_inbox) { create(:inbox, channel: instagram_channel, account: account, greeting_enabled: false) }
|
||||
let!(:dm_params) { build(:instagram_message_create_event).with_indifferent_access }
|
||||
let!(:story_mention_params) { build(:instagram_story_mention_event).with_indifferent_access }
|
||||
let!(:instagram_story_reply_event) { build(:instagram_story_reply_event).with_indifferent_access }
|
||||
let(:fb_object) { double }
|
||||
let(:contact) { create(:contact, id: 'Sender-id-1', name: 'Jane Dae') }
|
||||
let(:contact_inbox) { create(:contact_inbox, contact_id: contact.id, inbox_id: instagram_inbox.id, source_id: 'Sender-id-1') }
|
||||
@@ -44,6 +45,29 @@ describe ::Messages::Instagram::MessageBuilder do
|
||||
expect(message.content).to eq('This is the first message from the customer')
|
||||
end
|
||||
|
||||
it 'creates message with for reply with story id' do
|
||||
allow(Koala::Facebook::API).to receive(:new).and_return(fb_object)
|
||||
allow(fb_object).to receive(:get_object).and_return(
|
||||
{
|
||||
name: 'Jane',
|
||||
id: 'Sender-id-1',
|
||||
account_id: instagram_inbox.account_id,
|
||||
profile_pic: 'https://chatwoot-assets.local/sample.png'
|
||||
}.with_indifferent_access
|
||||
)
|
||||
messaging = instagram_story_reply_event[:entry][0]['messaging'][0]
|
||||
contact_inbox
|
||||
|
||||
described_class.new(messaging, instagram_inbox).perform
|
||||
|
||||
message = instagram_channel.inbox.messages.first
|
||||
|
||||
expect(message.content).to eq('This is the story reply')
|
||||
expect(message.content_attributes[:story_sender]).to eq(instagram_inbox.channel.instagram_id)
|
||||
expect(message.content_attributes[:story_id]).to eq('chatwoot-app-user-id-1')
|
||||
expect(message.content_attributes[:story_url]).to eq('https://chatwoot-assets.local/sample.png')
|
||||
end
|
||||
|
||||
it 'raises exception on deleted story' do
|
||||
allow(Koala::Facebook::API).to receive(:new).and_return(fb_object)
|
||||
allow(fb_object).to receive(:get_object).and_raise(Koala::Facebook::ClientError.new(
|
||||
|
||||
@@ -26,6 +26,39 @@ FactoryBot.define do
|
||||
initialize_with { attributes }
|
||||
end
|
||||
|
||||
factory :instagram_story_reply_event, class: Hash do
|
||||
entry do
|
||||
[
|
||||
{
|
||||
'id': 'instagram-message-id-123',
|
||||
'time': '2021-09-08T06:34:04+0000',
|
||||
'messaging': [
|
||||
{
|
||||
'sender': {
|
||||
'id': 'Sender-id-1'
|
||||
},
|
||||
'recipient': {
|
||||
'id': 'chatwoot-app-user-id-1'
|
||||
},
|
||||
'timestamp': '2021-09-08T06:34:04+0000',
|
||||
'message': {
|
||||
'mid': 'message-id-1',
|
||||
'text': 'This is the story reply',
|
||||
'reply_to': {
|
||||
'story': {
|
||||
'id': 'chatwoot-app-user-id-1',
|
||||
'url': 'https://chatwoot-assets.local/sample.png'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
end
|
||||
initialize_with { attributes }
|
||||
end
|
||||
|
||||
factory :instagram_test_text_event, class: Hash do
|
||||
entry do
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user