Compare commits

..

1 Commits

Author SHA1 Message Date
Matheus Filype 6afde71691 feat: groups mention all (#2396)
* fix: improve message resend logic by adding checks for message IDs

* Revert "fix: improve message resend logic by adding checks for message IDs"

This reverts commit c03f9d8e6fc6cbfbb9d1f8f67c169700e704213d.

* feat: add mentionAll support to message context for group mentions

* fix: improve readability of condition for mentions and mentionAll in generateWAMessageContent

* Apply suggestions from code review

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>

---------

Co-authored-by: Rajeh Taher <rajeh@reforward.dev>
2026-03-13 19:49:16 +02:00
6 changed files with 20 additions and 54 deletions
+3 -12
View File
@@ -36,7 +36,7 @@ import {
signedKeyPair,
xmppSignedPreKey
} from '../Utils'
import { getPlatformId, isAndroidBrowser } from '../Utils/browser-utils'
import { getPlatformId } from '../Utils/browser-utils'
import {
assertNodeErrorFree,
type BinaryNode,
@@ -758,15 +758,6 @@ export const makeSocket = (config: SocketConfig) => {
id: jidEncode(phoneNumber, 's.whatsapp.net'),
name: '~'
}
// Pair code companion_platform_id must be Chrome (1) when using Android
// browser preset. ANDROID_PHONE (16) causes silent timeout, UWP (21)
// causes rejection. Only Chrome (1) works for pair code via web protocol.
// The device still appears as "Android" in linked devices because
// DeviceProps.platformType=ANDROID_PHONE is set in the registration node.
const isAndroid = isAndroidBrowser(browser)
const pairPlatformId = isAndroid ? getPlatformId('Chrome') : getPlatformId(browser[1])
const pairPlatformDisplay = isAndroid ? 'Chrome (Mac OS)' : `${browser[1]} (${browser[0]})`
ev.emit('creds.update', authState.creds)
await sendNode({
tag: 'iq',
@@ -799,12 +790,12 @@ export const makeSocket = (config: SocketConfig) => {
{
tag: 'companion_platform_id',
attrs: {},
content: pairPlatformId
content: getPlatformId(browser[1])
},
{
tag: 'companion_platform_display',
attrs: {},
content: pairPlatformDisplay
content: `${browser[1]} (${browser[0]})`
},
{
tag: 'link_code_pairing_nonce',
+2
View File
@@ -113,6 +113,8 @@ export interface WAUrlInfo {
type Mentionable = {
/** list of jids that are mentioned in the accompanying text */
mentions?: string[]
/** mention all */
mentionAll?: boolean
}
type Contextable = {
/** add contextInfo to the message */
-1
View File
@@ -22,7 +22,6 @@ export type BrowsersMap = {
baileys(browser: string): [string, string, string]
windows(browser: string): [string, string, string]
appropriate(browser: string): [string, string, string]
android(apiLevel: string): [string, string, string]
}
export enum DisconnectReason {
+2 -25
View File
@@ -22,33 +22,10 @@ export const Browsers: BrowsersMap = {
baileys: browser => ['Baileys', browser, '6.5.0'],
windows: browser => ['Windows', browser, '10.0.22631'],
/** The appropriate browser based on your OS & release */
appropriate: browser => [PLATFORM_MAP[platform()] || 'Ubuntu', browser, release()],
/** Android companion device. apiLevel is the Android API level (e.g. '14') */
android: (apiLevel: string) => [apiLevel, 'Android', '']
}
/**
* Checks if the browser tuple represents an Android companion device.
* @param browser - Browser tuple [os, platform, version]
* @returns True if platform is 'Android' (case-insensitive)
*/
export const isAndroidBrowser = (browser: [string, string, string]): boolean => {
return browser[1]?.toUpperCase() === 'ANDROID'
appropriate: browser => [PLATFORM_MAP[platform()] || 'Ubuntu', browser, release()]
}
export const getPlatformId = (browser: string) => {
const platformType = proto.DeviceProps.PlatformType[browser.toUpperCase() as any]
if (platformType !== undefined) {
return platformType.toString()
}
// 'ANDROID' is not in the PlatformType enum — map to ANDROID_PHONE
if (browser.toUpperCase() === 'ANDROID') {
const androidPhone = proto.DeviceProps.PlatformType['ANDROID_PHONE' as any]
if (androidPhone !== undefined) {
return androidPhone.toString()
}
}
return '1' // Chrome
return platformType ? platformType.toString() : '1' //chrome
}
+12 -6
View File
@@ -609,14 +609,20 @@ export const generateWAMessageContent = async (
m = { viewOnceMessage: { message: m } }
}
if (hasOptionalProperty(message, 'mentions') && message.mentions?.length) {
if (
(hasOptionalProperty(message, 'mentions') && message.mentions?.length) ||
(hasOptionalProperty(message, 'mentionAll') && message.mentionAll)
) {
const messageType = Object.keys(m)[0]! as Extract<keyof proto.IMessage, MessageWithContextInfo>
const key = m[messageType]
if ('contextInfo' in key! && !!key.contextInfo) {
key.contextInfo.mentionedJid = message.mentions
} else if (key!) {
key.contextInfo = {
mentionedJid: message.mentions
if (key && 'contextInfo' in key) {
key.contextInfo = key.contextInfo || {}
if (message.mentions?.length) {
key.contextInfo.mentionedJid = message.mentions
}
if (message.mentionAll) {
key.contextInfo.nonJidMentions = 1
}
}
}
+1 -10
View File
@@ -14,17 +14,13 @@ import { encodeBigEndian } from './generics'
import { createSignalIdentity } from './signal'
const getUserAgent = (config: SocketConfig): proto.ClientPayload.IUserAgent => {
// Always use MACOS platform for UserAgent — we connect via web protocol
// (WA\x06\x03) so the server expects a web-compatible identity.
// Using WEB causes 405 errors; using SMB_ANDROID breaks pair code.
// Android identity is only set in DeviceProps (registration node).
return {
appVersion: {
primary: config.version[0],
secondary: config.version[1],
tertiary: config.version[2]
},
platform: proto.ClientPayload.UserAgent.Platform.MACOS,
platform: proto.ClientPayload.UserAgent.Platform.WEB,
releaseChannel: proto.ClientPayload.UserAgent.ReleaseChannel.RELEASE,
osVersion: '0.1',
device: 'Desktop',
@@ -83,11 +79,6 @@ export const generateLoginNode = (userJid: string, config: SocketConfig): proto.
const getPlatformType = (platform: string): proto.DeviceProps.PlatformType => {
const platformType = platform.toUpperCase()
// 'ANDROID' is not in PlatformType enum — map to ANDROID_PHONE
if (platformType === 'ANDROID') {
return proto.DeviceProps.PlatformType.ANDROID_PHONE
}
return (
proto.DeviceProps.PlatformType[platformType as keyof typeof proto.DeviceProps.PlatformType] ||
proto.DeviceProps.PlatformType.CHROME