fix: handle new contact without push name (#13)
* fix: resolve bug for contact name when user stats a new conversation with a new contact * chore: update specs to cover the bug resolution * chore: correct variable name * chore: simplify update contact name handling * chore: ensure pushName is always a string and leave a comment to keep an eye if always pushName will be present * fix: update contact name access * chore: identify and permit only direct users jid types (#14) * fix: add jid_type method to classify message sender types and prevent processing for non-user jids * chore: update jid parsing to correctly extract phone number and improve message type detection * chore: add spec to ensure no conversation is created for non-user messages * chore: update jid shape comment * chore: refactor jid_type method * chore: update message_type logic for classify text messages when is a extendedTextMessage * refactor: update spec that no conversation is created for non-user messages * fix: use update! method for contact name update * chore: add note on distinguishing broadcast and status JIDs in Baileys * chore: add note on Baileys internal function for JID classification
This commit is contained in:
parent
02732b3db6
commit
e0708ca6f8
@ -46,6 +46,7 @@ class Whatsapp::IncomingMessageBaileysService < Whatsapp::IncomingMessageBaseSer
|
||||
end
|
||||
|
||||
def handle_message
|
||||
return if jid_type != 'user'
|
||||
return if find_message_by_source_id(message_id) || message_under_process?
|
||||
|
||||
cache_message_source_id_in_redis
|
||||
@ -62,16 +63,23 @@ class Whatsapp::IncomingMessageBaileysService < Whatsapp::IncomingMessageBaseSer
|
||||
end
|
||||
|
||||
def set_contact
|
||||
phone_number_from_jid = @raw_message[:key][:remoteJid].split('@').first.split(':').first
|
||||
|
||||
# NOTE: jid shape is `<user>_<agent>:<device>@<server>`
|
||||
# https://github.com/WhiskeySockets/Baileys/blob/v6.7.16/src/WABinary/jid-utils.ts#L19
|
||||
phone_number_from_jid = @raw_message[:key][:remoteJid].split('@').first.split(':').first.split('_').first
|
||||
phone_number_formatted = "+#{phone_number_from_jid}"
|
||||
# NOTE: We're assuming `pushName` will always be present when `fromMe: false`.
|
||||
# This assumption might be incorrect, so let's keep an eye out for contacts being created with empty name.
|
||||
push_name = @raw_message[:key][:fromMe] ? phone_number_formatted : @raw_message[:pushName].to_s
|
||||
contact_inbox = ::ContactInboxWithContactBuilder.new(
|
||||
source_id: phone_number_from_jid,
|
||||
inbox: inbox,
|
||||
contact_attributes: { name: @raw_message[:pushName], phone_number: "+#{phone_number_from_jid}" }
|
||||
contact_attributes: { name: push_name, phone_number: phone_number_formatted }
|
||||
).perform
|
||||
|
||||
@contact_inbox = contact_inbox
|
||||
@contact = contact_inbox.contact
|
||||
|
||||
@contact.update!(name: push_name) if @contact.name == phone_number_formatted && !@raw_message[:key][:fromMe]
|
||||
end
|
||||
|
||||
def handle_create_message
|
||||
@ -83,9 +91,34 @@ class Whatsapp::IncomingMessageBaileysService < Whatsapp::IncomingMessageBaseSer
|
||||
end
|
||||
end
|
||||
|
||||
def jid_type # rubocop:disable Metrics/CyclomaticComplexity
|
||||
jid = @raw_message[:key][:remoteJid]
|
||||
server = jid.split('@').last
|
||||
|
||||
# NOTE: Based on Baileys internal functions
|
||||
# https://github.com/WhiskeySockets/Baileys/blob/v6.7.16/src/WABinary/jid-utils.ts#L48-L58
|
||||
case server
|
||||
when 's.whatsapp.net', 'c.us'
|
||||
'user'
|
||||
when 'g.us'
|
||||
'group'
|
||||
when 'lid'
|
||||
'lid'
|
||||
when 'broadcast'
|
||||
jid.start_with?('status@') ? 'status' : 'broadcast'
|
||||
when 'newsletter'
|
||||
'newsletter'
|
||||
when 'call'
|
||||
'call'
|
||||
else
|
||||
'unknown'
|
||||
end
|
||||
end
|
||||
|
||||
def message_type # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
||||
msg = @raw_message[:message]
|
||||
return 'text' if msg.key?(:conversation) || msg.dig(:extendedTextMessage, :text)
|
||||
|
||||
return 'text' if msg.key?(:conversation) || msg.dig(:extendedTextMessage, :text).present?
|
||||
return 'contacts' if msg.key?(:contactMessage)
|
||||
return 'image' if msg.key?(:imageMessage)
|
||||
return 'audio' if msg.key?(:audioMessage)
|
||||
|
||||
@ -173,6 +173,32 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
end
|
||||
|
||||
context 'when message is not from a user' do
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'msg_123', remoteJid: 'status@broadcast', participant: '5511912345678@s.whatsapp.net', fromMe: false },
|
||||
message: { extendedTextMessage: { text: 'message' } },
|
||||
pushName: 'John Doe'
|
||||
}
|
||||
end
|
||||
let(:params) do
|
||||
{
|
||||
webhookVerifyToken: webhook_verify_token,
|
||||
event: 'messages.upsert',
|
||||
data: {
|
||||
type: 'notify',
|
||||
messages: [raw_message]
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it 'does not create a conversation' do
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
expect(inbox.conversations).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when message type is text' do
|
||||
let(:raw_message) do
|
||||
{
|
||||
@ -206,8 +232,9 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
end
|
||||
|
||||
it 'creates an outgoing message' do
|
||||
number = '5511912345678'
|
||||
raw_message_outgoing = raw_message.merge(
|
||||
key: { id: 'msg_123', remoteJid: '5511912345678@s.whatsapp.net', fromMe: true }
|
||||
key: { id: 'msg_123', remoteJid: "#{number}@s.whatsapp.net", fromMe: true }
|
||||
)
|
||||
params_outgoing = params.merge(data: { type: 'notify', messages: [raw_message_outgoing] })
|
||||
create(:account_user, account: inbox.account)
|
||||
@ -219,6 +246,15 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
expect(message).to be_present
|
||||
expect(message.content).to eq('Hello from Baileys')
|
||||
expect(message.message_type).to eq('outgoing')
|
||||
expect(conversation.contact.name).to eq("+#{number}")
|
||||
end
|
||||
|
||||
it 'updates the contact name if the current name is a phone number when a incoming message is received' do
|
||||
create(:contact, account: inbox.account, name: '+5511912345678', phone_number: '+5511912345678')
|
||||
described_class.new(inbox: inbox, params: params).perform
|
||||
|
||||
conversation = inbox.conversations.last
|
||||
expect(conversation.contact.name).to eq('John Doe')
|
||||
end
|
||||
|
||||
it 'creates a message on an existing conversation' do
|
||||
@ -265,7 +301,7 @@ describe Whatsapp::IncomingMessageBaileysService do
|
||||
let(:raw_message) do
|
||||
{
|
||||
key: { id: 'msg_123', remoteJid: '5511912345678@s.whatsapp.net', fromMe: false },
|
||||
message: { 'extendedTextMessage': { text: 'Hello from Baileys' } },
|
||||
message: { extendedTextMessage: { text: 'Hello from Baileys' } },
|
||||
pushName: 'John Doe'
|
||||
}
|
||||
end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user