Skip to content

Commit aa22de8

Browse files
authored
Merge pull request #21 from canove/develop
merge development branch
2 parents 183e0a0 + dd28c1f commit aa22de8

11 files changed

Lines changed: 193 additions & 17 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "whaileys",
3-
"version": "6.2.4",
3+
"version": "6.2.5",
44
"description": "WhatsApp API",
55
"homepage": "https://github.com/canove/whaileys",
66
"main": "lib/index.js",

src/Socket/chats.ts

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@ import {
1515
WAMessage,
1616
WAPatchCreate,
1717
WAPatchName,
18-
WAPresence
18+
WAPresence,
19+
WAPrivacyCallValue,
20+
WAPrivacyGroupAddValue,
21+
WAPrivacyMessagesValue,
22+
WAPrivacyOnlineValue,
23+
WAPrivacyValue,
24+
WAReadReceiptsValue
1925
} from "../Types";
2026
import {
2127
chatModificationToAppPatch,
@@ -94,6 +100,62 @@ export const makeChatsSocket = (config: SocketConfig) => {
94100
return privacySettings;
95101
};
96102

103+
/** helper function to run a privacy IQ query */
104+
const privacyQuery = async (name: string, value: string) => {
105+
await query({
106+
tag: "iq",
107+
attrs: {
108+
xmlns: "privacy",
109+
to: S_WHATSAPP_NET,
110+
type: "set"
111+
},
112+
content: [
113+
{
114+
tag: "privacy",
115+
attrs: {},
116+
content: [
117+
{
118+
tag: "category",
119+
attrs: { name, value }
120+
}
121+
]
122+
}
123+
]
124+
});
125+
};
126+
127+
const updateMessagesPrivacy = async (value: WAPrivacyMessagesValue) => {
128+
await privacyQuery("messages", value);
129+
};
130+
131+
const updateCallPrivacy = async (value: WAPrivacyCallValue) => {
132+
await privacyQuery("calladd", value);
133+
};
134+
135+
const updateLastSeenPrivacy = async (value: WAPrivacyValue) => {
136+
await privacyQuery("last", value);
137+
};
138+
139+
const updateOnlinePrivacy = async (value: WAPrivacyOnlineValue) => {
140+
await privacyQuery("online", value);
141+
};
142+
143+
const updateProfilePicturePrivacy = async (value: WAPrivacyValue) => {
144+
await privacyQuery("profile", value);
145+
};
146+
147+
const updateStatusPrivacy = async (value: WAPrivacyValue) => {
148+
await privacyQuery("status", value);
149+
};
150+
151+
const updateReadReceiptsPrivacy = async (value: WAReadReceiptsValue) => {
152+
await privacyQuery("readreceipts", value);
153+
};
154+
155+
const updateGroupsAddPrivacy = async (value: WAPrivacyGroupAddValue) => {
156+
await privacyQuery("groupadd", value);
157+
};
158+
97159
/** helper function to run a generic IQ query */
98160
const interactiveQuery = async (
99161
userNodes: BinaryNode[],
@@ -884,6 +946,14 @@ export const makeChatsSocket = (config: SocketConfig) => {
884946
onWhatsApp,
885947
fetchBlocklist,
886948
fetchStatus,
949+
updateCallPrivacy,
950+
updateMessagesPrivacy,
951+
updateLastSeenPrivacy,
952+
updateOnlinePrivacy,
953+
updateProfilePicturePrivacy,
954+
updateStatusPrivacy,
955+
updateReadReceiptsPrivacy,
956+
updateGroupsAddPrivacy,
887957
updateProfilePicture,
888958
updateProfileStatus,
889959
updateProfileName,

src/Socket/groups.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,13 @@ export const extractGroupMetadata = (result: BinaryNode) => {
300300
: undefined,
301301
desc,
302302
descId,
303+
linkedParent:
304+
getBinaryNodeChild(group, "linked_parent")?.attrs.jid || undefined,
303305
restrict: !!getBinaryNodeChild(group, "locked"),
304306
announce: !!getBinaryNodeChild(group, "announcement"),
307+
isCommunity: !!getBinaryNodeChild(group, "parent"),
308+
isCommunityAnnounce: !!getBinaryNodeChild(group, "default_sub_group"),
309+
joinApprovalMode: !!getBinaryNodeChild(group, "membership_approval_mode"),
305310
participants: getBinaryNodeChildren(group, "participant").map(
306311
({ attrs }) => {
307312
return {

src/Socket/messages-recv.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -818,17 +818,6 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
818818

819819
cleanMessage(msg, authState.creds.me!.id);
820820

821-
if (
822-
msg.message?.protocolMessage?.type ===
823-
proto.Message.ProtocolMessage.Type.SHARE_PHONE_NUMBER &&
824-
node.attrs.sender_pn
825-
) {
826-
ev.emit("chats.phoneNumberShare", {
827-
lid: node.attrs.from,
828-
jid: node.attrs.sender_pn
829-
});
830-
}
831-
832821
await upsertMessage(msg, node.attrs.offline ? "append" : "notify");
833822
})
834823
]);

src/Types/Chat.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@ import type { AccountSettings } from "./Auth";
33
import type { BufferedEventData } from "./Events";
44
import type { MinimalMessage } from "./Message";
55

6+
/** privacy settings in WhatsApp Web */
7+
export type WAPrivacyValue = "all" | "contacts" | "contact_blacklist" | "none";
8+
9+
export type WAPrivacyOnlineValue = "all" | "match_last_seen";
10+
11+
export type WAPrivacyGroupAddValue = "all" | "contacts" | "contact_blacklist";
12+
13+
export type WAReadReceiptsValue = "all" | "none";
14+
15+
export type WAPrivacyCallValue = "all" | "known";
16+
17+
export type WAPrivacyMessagesValue = "all" | "contacts";
18+
619
/** set of statuses visible to other people; see updatePresence() in WhatsAppWeb.Send */
720
export type WAPresence =
821
| "unavailable"
@@ -67,6 +80,11 @@ export type LastMessageList =
6780
| MinimalMessage[]
6881
| proto.SyncActionValue.ISyncActionMessageRange;
6982

83+
export type VoteAggregation = {
84+
name: string;
85+
voters: string[];
86+
};
87+
7088
export type ChatModification =
7189
| {
7290
archive: boolean;

src/Types/Events.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export type BaileysEventMap = {
3232
"chats.upsert": Chat[];
3333
/** update the given chats */
3434
"chats.update": ChatUpdate[];
35+
/** @deprecated Use contacts.phone-number-share instead */
3536
"chats.phoneNumberShare": { lid: string; jid: string };
3637
/** delete chats with given ID */
3738
"chats.delete": string[];
@@ -43,6 +44,8 @@ export type BaileysEventMap = {
4344

4445
"contacts.upsert": Contact[];
4546
"contacts.update": Partial<Contact>[];
47+
/** contact decided to share his phone number that was hidden */
48+
"contacts.phone-number-share": { lid: string; jid: string };
4649

4750
"messages.delete": { keys: WAMessageKey[] } | { jid: string; all: true };
4851
"messages.update": WAMessageUpdate[];

src/Types/GroupMetadata.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ export interface GroupMetadata {
2222
desc?: string;
2323
descOwner?: string;
2424
descId?: string;
25+
/** Request approval to join the group */
26+
joinApprovalMode?: boolean;
27+
/** if this group is part of a community, it returns the jid of the community to which it belongs */
28+
linkedParent?: string;
29+
/** is this a community */
30+
isCommunity?: boolean;
31+
/** is this the announce of a community */
32+
isCommunityAnnounce?: boolean;
2533
/** is set when the group only allows admins to change group settings */
2634
restrict?: boolean;
2735
/** is set when the group only allows admins to write messages */

src/Utils/decode-wa-message.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export const decodeMessageStanza = (
108108

109109
const sender = msgType === "chat" ? author : chatId;
110110

111-
const fromMe = (isLidUser(from) ? isMeLid : isMe)(
111+
const fromMe = (isLidUser(from) || isLidUser(participant) ? isMeLid : isMe)(
112112
stanza.attrs.participant || stanza.attrs.from
113113
);
114114
const pushname = stanza.attrs.notify;

src/Utils/messages.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
MessageGenerationOptionsFromContent,
2121
MessageType,
2222
MessageUserReceipt,
23+
VoteAggregation,
2324
WAMediaUpload,
2425
WAMessage,
2526
WAMessageContent,
@@ -37,6 +38,7 @@ import {
3738
getAudioDuration,
3839
MediaDownloadOptions
3940
} from "./messages-media";
41+
import { sha256 } from "./crypto";
4042

4143
type MediaUploadData = {
4244
media: WAMediaUpload;
@@ -707,6 +709,74 @@ export const updateMessageWithReaction = (
707709
msg.reactions = reactions;
708710
};
709711

712+
/** Update the message with a new poll update */
713+
export const updateMessageWithPollUpdate = (
714+
msg: Pick<WAMessage, "pollUpdates">,
715+
update: proto.IPollUpdate
716+
) => {
717+
const authorID = getKeyAuthor(update.pollUpdateMessageKey);
718+
719+
const reactions = (msg.pollUpdates || []).filter(
720+
r => getKeyAuthor(r.pollUpdateMessageKey) !== authorID
721+
);
722+
if (update.vote?.selectedOptions?.length) {
723+
reactions.push(update);
724+
}
725+
726+
msg.pollUpdates = reactions;
727+
};
728+
729+
/**
730+
* Aggregates all poll updates in a poll.
731+
* @param msg the poll creation message
732+
* @param meId your jid
733+
* @returns A list of options & their voters
734+
*/
735+
export function getAggregateVotesInPollMessage({
736+
message,
737+
pollUpdates
738+
}: Pick<WAMessage, "pollUpdates" | "message">) {
739+
const opts =
740+
message?.pollCreationMessage?.options ||
741+
message?.pollCreationMessageV2?.options ||
742+
message?.pollCreationMessageV3?.options ||
743+
[];
744+
const voteHashMap = opts.reduce(
745+
(acc, opt) => {
746+
const hash = sha256(Buffer.from(opt.optionName || "")).toString();
747+
acc[hash] = {
748+
name: opt.optionName || "",
749+
voters: []
750+
};
751+
return acc;
752+
},
753+
{} as { [_: string]: VoteAggregation }
754+
);
755+
756+
for (const update of pollUpdates || []) {
757+
const { vote } = update;
758+
if (!vote) {
759+
continue;
760+
}
761+
762+
for (const option of vote.selectedOptions || []) {
763+
const hash = option.toString();
764+
let data = voteHashMap[hash];
765+
if (!data) {
766+
voteHashMap[hash] = {
767+
name: "Unknown",
768+
voters: []
769+
};
770+
data = voteHashMap[hash];
771+
}
772+
773+
voteHashMap[hash]!.voters.push(getKeyAuthor(update.pollUpdateMessageKey));
774+
}
775+
}
776+
777+
return Object.values(voteHashMap);
778+
}
779+
710780
/** Given a list of message keys, aggregates them by chat & sender. Useful for sending read receipts in bulk */
711781
export const aggregateMessageKeysNotFromMe = (keys: proto.IMessageKey[]) => {
712782
const keyMap: {

0 commit comments

Comments
 (0)