fix: Handle Instagram text and attachments as separate messages (#11315)
When we send text with attachments on Instagram, Instagram treats text and attachments as separate messages. However, Chatwoot keeps them as a single message. Since Instagram sends echo events for each message, this can create duplicate messages in Chatwoot. To prevent this, we will send text and attachments as separate messages. --------- Co-authored-by: Pranav <pranav@chatwoot.com>
This commit is contained in:
@@ -65,6 +65,7 @@ class DashboardController < ActionController::Base
|
||||
VAPID_PUBLIC_KEY: VapidService.public_key,
|
||||
ENABLE_ACCOUNT_SIGNUP: GlobalConfigService.load('ENABLE_ACCOUNT_SIGNUP', 'false'),
|
||||
FB_APP_ID: GlobalConfigService.load('FB_APP_ID', ''),
|
||||
INSTAGRAM_APP_ID: GlobalConfigService.load('INSTAGRAM_APP_ID', ''),
|
||||
FACEBOOK_API_VERSION: GlobalConfigService.load('FACEBOOK_API_VERSION', 'v17.0'),
|
||||
IS_ENTERPRISE: ChatwootApp.enterprise?,
|
||||
AZURE_APP_ID: GlobalConfigService.load('AZURE_APP_ID', ''),
|
||||
|
||||
@@ -17,6 +17,9 @@ export default {
|
||||
hasFbConfigured() {
|
||||
return window.chatwootConfig?.fbAppId;
|
||||
},
|
||||
hasInstagramConfigured() {
|
||||
return window.chatwootConfig?.instagramAppId;
|
||||
},
|
||||
isActive() {
|
||||
const { key } = this.channel;
|
||||
if (Object.keys(this.enabledFeatures).length === 0) {
|
||||
@@ -33,7 +36,9 @@ export default {
|
||||
}
|
||||
|
||||
if (key === 'instagram') {
|
||||
return this.enabledFeatures.channel_instagram;
|
||||
return (
|
||||
this.enabledFeatures.channel_instagram && this.hasInstagramConfigured
|
||||
);
|
||||
}
|
||||
|
||||
return [
|
||||
|
||||
@@ -686,7 +686,11 @@ export default {
|
||||
this.isATwilioWhatsAppChannel ||
|
||||
this.isAWhatsAppCloudChannel ||
|
||||
this.is360DialogWhatsAppChannel;
|
||||
if (isOnWhatsApp && !this.isPrivate) {
|
||||
// When users send messages containing both text and attachments on Instagram, Instagram treats them as separate messages.
|
||||
// Although Chatwoot combines these into a single message, Instagram sends separate echo events for each component.
|
||||
// This can create duplicate messages in Chatwoot. To prevent this issue, we'll handle text and attachments as separate messages.
|
||||
const isOnInstagram = this.isAInstagramChannel;
|
||||
if ((isOnWhatsApp || isOnInstagram) && !this.isPrivate) {
|
||||
this.sendMessageAsMultipleMessages(this.message);
|
||||
} else {
|
||||
const messagePayload = this.getMessagePayload(this.message);
|
||||
@@ -703,7 +707,7 @@ export default {
|
||||
}
|
||||
},
|
||||
sendMessageAsMultipleMessages(message) {
|
||||
const messages = this.getMessagePayloadForWhatsapp(message);
|
||||
const messages = this.getMultipleMessagesPayload(message);
|
||||
messages.forEach(messagePayload => {
|
||||
this.sendMessage(messagePayload);
|
||||
});
|
||||
@@ -935,11 +939,11 @@ export default {
|
||||
|
||||
return payload;
|
||||
},
|
||||
getMessagePayloadForWhatsapp(message) {
|
||||
getMultipleMessagesPayload(message) {
|
||||
const multipleMessagePayload = [];
|
||||
|
||||
if (this.attachedFiles && this.attachedFiles.length) {
|
||||
let caption = message;
|
||||
let caption = this.isAInstagramChannel ? '' : message;
|
||||
this.attachedFiles.forEach(attachment => {
|
||||
const attachedFile = this.globalConfig.directUploadsEnabled
|
||||
? attachment.blobSignedId
|
||||
@@ -954,9 +958,19 @@ export default {
|
||||
|
||||
attachmentPayload = this.setReplyToInPayload(attachmentPayload);
|
||||
multipleMessagePayload.push(attachmentPayload);
|
||||
caption = '';
|
||||
// For WhatsApp, only the first attachment gets a caption
|
||||
if (!this.isAInstagramChannel) caption = '';
|
||||
});
|
||||
} else {
|
||||
}
|
||||
|
||||
const hasNoAttachments =
|
||||
!this.attachedFiles || !this.attachedFiles.length;
|
||||
// For Instagram, we need a separate text message
|
||||
// For WhatsApp, we only need a text message if there are no attachments
|
||||
if (
|
||||
(this.isAInstagramChannel && this.message) ||
|
||||
(!this.isAInstagramChannel && hasNoAttachments)
|
||||
) {
|
||||
let messagePayload = {
|
||||
conversationId: this.currentChat.id,
|
||||
message,
|
||||
@@ -1136,7 +1150,7 @@ export default {
|
||||
v-else-if="!showRichContentEditor"
|
||||
ref="messageInput"
|
||||
v-model="message"
|
||||
class="input rounded-none"
|
||||
class="rounded-none input"
|
||||
:placeholder="messagePlaceHolder"
|
||||
:min-height="4"
|
||||
:signature="signatureToApply"
|
||||
|
||||
@@ -35,8 +35,7 @@ export default {
|
||||
},
|
||||
{ key: 'telegram', name: 'Telegram' },
|
||||
{ key: 'line', name: 'Line' },
|
||||
// TODO: Add Instagram to the channel list after the feature is ready to use.
|
||||
// { key: 'instagram', name: 'Instagram' },
|
||||
{ key: 'instagram', name: 'Instagram' },
|
||||
];
|
||||
},
|
||||
...mapGetters({
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
hostURL: '<%= ENV.fetch('FRONTEND_URL', '') %>',
|
||||
helpCenterURL: '<%= ENV.fetch('HELPCENTER_URL', '') %>',
|
||||
fbAppId: '<%= @global_config['FB_APP_ID'] %>',
|
||||
instagramAppId: '<%= @global_config['INSTAGRAM_APP_ID'] %>',
|
||||
googleOAuthClientId: '<%= ENV.fetch('GOOGLE_OAUTH_CLIENT_ID', nil) %>',
|
||||
googleOAuthCallbackUrl: '<%= ENV.fetch('GOOGLE_OAUTH_CALLBACK_URL', nil) %>',
|
||||
fbApiVersion: '<%= @global_config['FACEBOOK_API_VERSION'] %>',
|
||||
|
||||
@@ -163,5 +163,5 @@
|
||||
enabled: false
|
||||
- name: channel_instagram
|
||||
display_name: Instagram Channel
|
||||
enabled: false
|
||||
enabled: true
|
||||
chatwoot_internal: true
|
||||
|
||||
Reference in New Issue
Block a user