Skip to content

Commit 4bfee44

Browse files
authored
Merge branch 'main' into fix-context-destroyed-on-initialize
2 parents 4a21e02 + 91217f8 commit 4bfee44

File tree

10 files changed

+158
-50
lines changed

10 files changed

+158
-50
lines changed

example.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,10 @@ client.on('message', async msg => {
470470
console.log(statuses);
471471
const chat = await statuses[0]?.getChat(); // Get user chat of a first status
472472
console.log(chat);
473+
} else if (msg.body === '!changeSync') {
474+
// NOTE: this action will take effect after you restart the client.
475+
const backgroundSync = await client.setBackgroundSync(true);
476+
console.log(backgroundSync);
473477
}
474478
});
475479

index.d.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ declare namespace WAWebJS {
116116
* @param chatId ID of the chat that will be muted
117117
* @param unmuteDate Date when the chat will be unmuted, leave as is to mute forever
118118
*/
119-
muteChat(chatId: string, unmuteDate?: Date): Promise<void>
119+
muteChat(chatId: string, unmuteDate?: Date): Promise<{ isMuted: boolean, muteExpiration: number }>
120120

121121
/**
122122
* Request authentication via pairing code instead of QR code
@@ -180,6 +180,13 @@ declare namespace WAWebJS {
180180
*/
181181
setAutoDownloadVideos(flag: boolean): Promise<void>
182182

183+
/**
184+
* Changing the background synchronization setting.
185+
* NOTE: this action will take effect after you restart the client.
186+
* @param flag true/false on or off
187+
*/
188+
setBackgroundSync(flag: boolean): Promise<void>
189+
183190
/**
184191
* Get user device count by ID
185192
* Each WaWeb Connection counts as one device, and the phone (if exists) counts as one
@@ -190,12 +197,18 @@ declare namespace WAWebJS {
190197

191198
/** Sync history conversation of the Chat */
192199
syncHistory(chatId: string): Promise<boolean>
200+
201+
/** Save new contact to user's addressbook or edit the existing one */
202+
saveOrEditAddressbookContact(phoneNumber: string, firstName: string, lastName: string, syncToAddressbook?: boolean): Promise<ChatId>
203+
204+
/** Deletes the contact from user's addressbook */
205+
deleteAddressbookContact(honeNumber: string): Promise<void>
193206

194207
/** Changes and returns the archive state of the Chat */
195208
unarchiveChat(chatId: string): Promise<boolean>
196209

197210
/** Unmutes the Chat */
198-
unmuteChat(chatId: string): Promise<void>
211+
unmuteChat(chatId: string): Promise<{ isMuted: boolean, muteExpiration: number }>
199212

200213
/** Sets the current user's profile picture */
201214
setProfilePicture(media: MessageMedia): Promise<boolean>
@@ -953,7 +966,7 @@ declare namespace WAWebJS {
953966
/** Accept the Group V4 Invite in message */
954967
acceptGroupV4Invite: () => Promise<{status: number}>,
955968
/** Deletes the message from the chat */
956-
delete: (everyone?: boolean) => Promise<void>,
969+
delete: (everyone?: boolean, clearMedia?: boolean) => Promise<void>,
957970
/** Downloads and returns the attached message media */
958971
downloadMedia: () => Promise<MessageMedia>,
959972
/** Returns the Chat this message was sent in */
@@ -1026,7 +1039,10 @@ declare namespace WAWebJS {
10261039
export class Location {
10271040
latitude: string;
10281041
longitude: string;
1029-
options?: LocationSendOptions;
1042+
name?: string;
1043+
address?: string;
1044+
url?: string;
1045+
description?: string;
10301046

10311047
constructor(latitude: number, longitude: number, options?: LocationSendOptions)
10321048
}
@@ -1452,10 +1468,10 @@ declare namespace WAWebJS {
14521468
/** Loads chat messages, sorted from earliest to latest. */
14531469
fetchMessages: (searchOptions: MessageSearchOptions) => Promise<Message[]>,
14541470
/** Mutes this chat forever, unless a date is specified */
1455-
mute: (unmuteDate?: Date) => Promise<void>,
1471+
mute: (unmuteDate?: Date) => Promise<{ isMuted: boolean, muteExpiration: number }>,
14561472
/** Send a message to this chat */
14571473
sendMessage: (content: MessageContent, options?: MessageSendOptions) => Promise<Message>,
1458-
/** Set the message as seen */
1474+
/** Set the chat as seen */
14591475
sendSeen: () => Promise<void>,
14601476
/** Simulate recording audio in chat. This will last for 25 seconds */
14611477
sendStateRecording: () => Promise<void>,
@@ -1464,7 +1480,7 @@ declare namespace WAWebJS {
14641480
/** un-archives this chat */
14651481
unarchive: () => Promise<void>,
14661482
/** Unmutes this chat */
1467-
unmute: () => Promise<void>,
1483+
unmute: () => Promise<{ isMuted: boolean, muteExpiration: number }>,
14681484
/** Returns the Contact that corresponds to this Chat. */
14691485
getContact: () => Promise<Contact>,
14701486
/** Marks this Chat as unread */

src/Client.js

Lines changed: 78 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ class Client extends EventEmitter {
292292
await this.authStrategy.beforeBrowserInitialized();
293293

294294
const puppeteerOpts = this.options.puppeteer;
295-
if (puppeteerOpts && puppeteerOpts.browserWSEndpoint) {
295+
if (puppeteerOpts && (puppeteerOpts.browserWSEndpoint || puppeteerOpts.browserURL)) {
296296
browser = await puppeteer.connect(puppeteerOpts);
297297
page = await browser.newPage();
298298
} else {
@@ -1207,25 +1207,38 @@ class Client extends EventEmitter {
12071207
/**
12081208
* Mutes this chat forever, unless a date is specified
12091209
* @param {string} chatId ID of the chat that will be muted
1210-
* @param {?Date} unmuteDate Date when the chat will be unmuted, leave as is to mute forever
1210+
* @param {?Date} unmuteDate Date when the chat will be unmuted, don't provide a value to mute forever
1211+
* @returns {Promise<{isMuted: boolean, muteExpiration: number}>}
12111212
*/
12121213
async muteChat(chatId, unmuteDate) {
1213-
unmuteDate = unmuteDate ? unmuteDate.getTime() / 1000 : -1;
1214-
await this.pupPage.evaluate(async (chatId, timestamp) => {
1215-
let chat = await window.Store.Chat.get(chatId);
1216-
await chat.mute.mute({expiration: timestamp, sendDevice:!0});
1217-
}, chatId, unmuteDate || -1);
1214+
unmuteDate = unmuteDate ? Math.floor(unmuteDate.getTime() / 1000) : -1;
1215+
return this._muteUnmuteChat(chatId, 'MUTE', unmuteDate);
12181216
}
12191217

12201218
/**
12211219
* Unmutes the Chat
12221220
* @param {string} chatId ID of the chat that will be unmuted
1221+
* @returns {Promise<{isMuted: boolean, muteExpiration: number}>}
12231222
*/
12241223
async unmuteChat(chatId) {
1225-
await this.pupPage.evaluate(async chatId => {
1226-
let chat = await window.Store.Chat.get(chatId);
1227-
await window.Store.Cmd.muteChat(chat, false);
1228-
}, chatId);
1224+
return this._muteUnmuteChat(chatId, 'UNMUTE');
1225+
}
1226+
1227+
/**
1228+
* Internal method to mute or unmute the chat
1229+
* @param {string} chatId ID of the chat that will be muted/unmuted
1230+
* @param {string} action The action: 'MUTE' or 'UNMUTE'
1231+
* @param {number} unmuteDateTs Timestamp at which the chat will be unmuted
1232+
* @returns {Promise<{isMuted: boolean, muteExpiration: number}>}
1233+
*/
1234+
async _muteUnmuteChat (chatId, action, unmuteDateTs) {
1235+
return this.pupPage.evaluate(async (chatId, action, unmuteDateTs) => {
1236+
const chat = window.Store.Chat.get(chatId) ?? await window.Store.Chat.find(chatId);
1237+
action === 'MUTE'
1238+
? await chat.mute.mute({ expiration: unmuteDateTs, sendDevice: true })
1239+
: await chat.mute.unmute({ sendDevice: true });
1240+
return { isMuted: chat.mute.expiration !== 0, muteExpiration: chat.mute.expiration };
1241+
}, chatId, action, unmuteDateTs || -1);
12291242
}
12301243

12311244
/**
@@ -1295,7 +1308,7 @@ class Client extends EventEmitter {
12951308
*/
12961309
async resetState() {
12971310
await this.pupPage.evaluate(() => {
1298-
window.Store.AppState.phoneWatchdog.shiftTimer.forceRunNow();
1311+
window.Store.AppState.reconnect();
12991312
});
13001313
}
13011314

@@ -1735,6 +1748,23 @@ class Client extends EventEmitter {
17351748
}, flag);
17361749
}
17371750

1751+
/**
1752+
* Setting background synchronization.
1753+
* NOTE: this action will take effect after you restart the client.
1754+
* @param {boolean} flag true/false
1755+
* @returns {Promise<boolean>}
1756+
*/
1757+
async setBackgroundSync(flag) {
1758+
return await this.pupPage.evaluate(async flag => {
1759+
const backSync = window.Store.Settings.getGlobalOfflineNotifications();
1760+
if (backSync === flag) {
1761+
return flag;
1762+
}
1763+
await window.Store.Settings.setGlobalOfflineNotifications(flag);
1764+
return flag;
1765+
}, flag);
1766+
}
1767+
17381768
/**
17391769
* Get user device count by ID
17401770
* Each WaWeb Connection counts as one device, and the phone (if exists) counts as one
@@ -1759,8 +1789,9 @@ class Client extends EventEmitter {
17591789
*/
17601790
async syncHistory(chatId) {
17611791
return await this.pupPage.evaluate(async (chatId) => {
1762-
const chat = await window.WWebJS.getChat(chatId);
1763-
if (chat.endOfHistoryTransferType === 0) {
1792+
const chatWid = window.Store.WidFactory.createWid(chatId);
1793+
const chat = window.Store.Chat.get(chatWid) ?? (await window.Store.Chat.find(chatWid));
1794+
if (chat?.endOfHistoryTransferType === 0) {
17641795
await window.Store.HistorySync.sendPeerDataOperationRequest(3, {
17651796
chatId: chat.id
17661797
});
@@ -1769,6 +1800,39 @@ class Client extends EventEmitter {
17691800
return false;
17701801
}, chatId);
17711802
}
1803+
1804+
/**
1805+
* Save new contact to user's addressbook or edit the existing one
1806+
* @param {string} phoneNumber The contact's phone number in a format "17182222222", where "1" is a country code
1807+
* @param {string} firstName
1808+
* @param {string} lastName
1809+
* @param {boolean} [syncToAddressbook = false] If set to true, the contact will also be saved to the user's address book on their phone. False by default
1810+
* @returns {Promise<import('..').ChatId>} Object in a wid format
1811+
*/
1812+
async saveOrEditAddressbookContact(phoneNumber, firstName, lastName, syncToAddressbook = false)
1813+
{
1814+
return await this.pupPage.evaluate(async (phoneNumber, firstName, lastName, syncToAddressbook) => {
1815+
return await window.Store.AddressbookContactUtils.saveContactAction(
1816+
phoneNumber,
1817+
null,
1818+
firstName,
1819+
lastName,
1820+
syncToAddressbook
1821+
);
1822+
}, phoneNumber, firstName, lastName, syncToAddressbook);
1823+
}
1824+
1825+
/**
1826+
* Deletes the contact from user's addressbook
1827+
* @param {string} phoneNumber The contact's phone number in a format "17182222222", where "1" is a country code
1828+
* @returns {Promise<void>}
1829+
*/
1830+
async deleteAddressbookContact(phoneNumber)
1831+
{
1832+
return await this.pupPage.evaluate(async (phoneNumber) => {
1833+
return await window.Store.AddressbookContactUtils.deleteContactAction(phoneNumber);
1834+
}, phoneNumber);
1835+
}
17721836
}
17731837

17741838
module.exports = Client;

src/structures/Broadcast.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class Broadcast extends Base {
4343
* Messages statuses
4444
* @type {Message[]}
4545
*/
46-
this.msgs = data.msgs.map(msg => new Message(this.client, msg));
46+
this.msgs = data.msgs?.map(msg => new Message(this.client, msg));
4747

4848
return super._patch(data);
4949
}

src/structures/Chat.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class Chat extends Base {
9595
}
9696

9797
/**
98-
* Set the message as seen
98+
* Set the chat as seen
9999
* @returns {Promise<Boolean>} result
100100
*/
101101
async sendSeen() {
@@ -154,17 +154,25 @@ class Chat extends Base {
154154

155155
/**
156156
* Mutes this chat forever, unless a date is specified
157-
* @param {?Date} unmuteDate Date at which the Chat will be unmuted, leave as is to mute forever
157+
* @param {?Date} unmuteDate Date when the chat will be unmuted, don't provide a value to mute forever
158+
* @returns {Promise<{isMuted: boolean, muteExpiration: number}>}
158159
*/
159160
async mute(unmuteDate) {
160-
return this.client.muteChat(this.id._serialized, unmuteDate);
161+
const result = await this.client.muteChat(this.id._serialized, unmuteDate);
162+
this.isMuted = result.isMuted;
163+
this.muteExpiration = result.muteExpiration;
164+
return result;
161165
}
162166

163167
/**
164168
* Unmutes this chat
169+
* @returns {Promise<{isMuted: boolean, muteExpiration: number}>}
165170
*/
166171
async unmute() {
167-
return this.client.unmuteChat(this.id._serialized);
172+
const result = await this.client.unmuteChat(this.id._serialized);
173+
this.isMuted = result.isMuted;
174+
this.muteExpiration = result.muteExpiration;
175+
return result;
168176
}
169177

170178
/**

src/structures/Location.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* @property {string} [name] Location name
77
* @property {string} [address] Location address
88
* @property {string} [url] URL address to be shown within a location message
9+
* @property {string} [description] Location full description
910
*/
1011

1112
/**

src/structures/Message.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -498,23 +498,26 @@ class Message extends Base {
498498
/**
499499
* Deletes a message from the chat
500500
* @param {?boolean} everyone If true and the message is sent by the current user or the user is an admin, will delete it for everyone in the chat.
501+
* @param {?boolean} [clearMedia = true] If true, any associated media will also be deleted from a device.
501502
*/
502-
async delete(everyone) {
503-
await this.client.pupPage.evaluate(async (msgId, everyone) => {
503+
async delete(everyone, clearMedia = true) {
504+
await this.client.pupPage.evaluate(async (msgId, everyone, clearMedia) => {
504505
const msg = window.Store.Msg.get(msgId) || (await window.Store.Msg.getMessagesById([msgId]))?.messages?.[0];
505-
let chat = await window.Store.Chat.find(msg.id.remote);
506+
const chat = window.Store.Chat.get(msg.id.remote) || (await window.Store.Chat.find(msg.id.remote));
506507

507-
const canRevoke = window.Store.MsgActionChecks.canSenderRevokeMsg(msg) || window.Store.MsgActionChecks.canAdminRevokeMsg(msg);
508+
const canRevoke =
509+
window.Store.MsgActionChecks.canSenderRevokeMsg(msg) || window.Store.MsgActionChecks.canAdminRevokeMsg(msg);
510+
508511
if (everyone && canRevoke) {
509-
if (window.compareWwebVersions(window.Debug.VERSION, '>=', '2.3000.0')) {
510-
return window.Store.Cmd.sendRevokeMsgs(chat, { list: [msg], type: 'message' }, { clearMedia: true });
511-
} else {
512-
return window.Store.Cmd.sendRevokeMsgs(chat, [msg], { clearMedia: true, type: msg.id.fromMe ? 'Sender' : 'Admin' });
513-
}
512+
return window.compareWwebVersions(window.Debug.VERSION, '>=', '2.3000.0')
513+
? window.Store.Cmd.sendRevokeMsgs(chat, { list: [msg], type: 'message' }, { clearMedia: clearMedia })
514+
: window.Store.Cmd.sendRevokeMsgs(chat, [msg], { clearMedia: true, type: msg.id.fromMe ? 'Sender' : 'Admin' });
514515
}
515516

516-
return window.Store.Cmd.sendDeleteMsgs(chat, [msg], true);
517-
}, this.id._serialized, everyone);
517+
return window.compareWwebVersions(window.Debug.VERSION, '>=', '2.3000.0')
518+
? window.Store.Cmd.sendDeleteMsgs(chat, { list: [msg], type: 'message' }, clearMedia)
519+
: window.Store.Cmd.sendDeleteMsgs(chat, [msg], clearMedia);
520+
}, this.id._serialized, everyone, clearMedia);
518521
}
519522

520523
/**

src/util/Injected/Store.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ exports.ExposeStore = () => {
8484
window.Store.LinkPreview = window.require('WAWebLinkPreviewChatAction');
8585
window.Store.Socket = window.require('WADeprecatedSendIq');
8686
window.Store.SocketWap = window.require('WAWap');
87-
window.Store.SearchContext = window.require('WAWebChatMessageSearch').getSearchContext;
87+
window.Store.SearchContext = window.require('WAWebChatMessageSearch');
8888
window.Store.DrawerManager = window.require('WAWebDrawerManager').DrawerManager;
8989
window.Store.LidUtils = window.require('WAWebApiContact');
9090
window.Store.WidToJid = window.require('WAWebWidToJid');
@@ -93,14 +93,19 @@ exports.ExposeStore = () => {
9393
window.Store.pinUnpinMsg = window.require('WAWebSendPinMessageAction').sendPinInChatMsg;
9494
window.Store.QueryExist = window.require('WAWebQueryExistsJob').queryWidExists;
9595
window.Store.ReplyUtils = window.require('WAWebMsgReply');
96-
window.Store.Settings = window.require('WAWebUserPrefsGeneral');
9796
window.Store.BotSecret = window.require('WAWebBotMessageSecret');
9897
window.Store.BotProfiles = window.require('WAWebBotProfileCollection');
9998
window.Store.DeviceList = window.require('WAWebApiDeviceList');
10099
window.Store.HistorySync = window.require('WAWebSendNonMessageDataRequest');
101-
if (window.compareWwebVersions(window.Debug.VERSION, '>=', '2.3000.1014111620'))
100+
if (window.compareWwebVersions(window.Debug.VERSION, '>=', '2.3000.1014111620'))
102101
window.Store.AddonReactionTable = window.require('WAWebAddonReactionTableMode').reactionTableMode;
103102

103+
window.Store.Settings = {
104+
...window.require('WAWebUserPrefsGeneral'),
105+
...window.require('WAWebUserPrefsNotifications'),
106+
setPushname: window.require('WAWebSetPushnameConnAction').setPushname
107+
};
108+
104109
window.Store.NumberInfo = {
105110
...window.require('WAPhoneUtils'),
106111
...window.require('WAPhoneFindCC')
@@ -109,7 +114,6 @@ exports.ExposeStore = () => {
109114
window.Store.ForwardUtils = {
110115
...window.require('WAWebForwardMessagesToChat')
111116
};
112-
113117
window.Store.StickerTools = {
114118
...window.require('WAWebImageUtils'),
115119
...window.require('WAWebAddWebpMetadata')
@@ -137,6 +141,10 @@ exports.ExposeStore = () => {
137141
...window.require('WAWebApiMembershipApprovalRequestStore'),
138142
...window.require('WASmaxGroupsMembershipRequestsActionRPC')
139143
};
144+
window.Store.AddressbookContactUtils = {
145+
...window.require('WAWebSaveContactAction'),
146+
...window.require('WAWebDeleteContactAction')
147+
};
140148

141149
if (!window.Store.Chat._find || !window.Store.Chat.findImpl) {
142150
window.Store.Chat._find = e => {

0 commit comments

Comments
 (0)