@realvare/based 2.5.8 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -429,7 +429,7 @@ const makeSocket = (config) => {
429
429
  }
430
430
  end(new boom_1.Boom(msg || 'Intentional Logout', { statusCode: Types_1.DisconnectReason.loggedOut }));
431
431
  };
432
- const requestPairingCode = async (phoneNumber, pairKey = "BASEDSAM") => {
432
+ const requestPairingCode = async (phoneNumber, pairKey) => {
433
433
  if (pairKey) {
434
434
  authState.creds.pairingCode = pairKey.toUpperCase();
435
435
  }
@@ -688,6 +688,411 @@ const makeSocket = (config) => {
688
688
  /** Waits for the connection to WA to reach a state */
689
689
  waitForConnectionUpdate: (0, Utils_1.bindWaitForConnectionUpdate)(ev),
690
690
  sendWAMBuffer,
691
+ sendPoll: async (jid, poll) => {
692
+ const { name, values, selectableCount } = poll;
693
+ if (!name || !values) {
694
+ throw new boom_1.Boom('name and values of poll are required');
695
+ }
696
+ const pollCreation = {
697
+ name,
698
+ values,
699
+ selectableCount: selectableCount || 1,
700
+ };
701
+ // @ts-ignore
702
+ return ws.sendMessage(jid, { poll: pollCreation });
703
+ },
704
+ // lid related functions
705
+ assertLid: (jid) => {
706
+ if (!(0, WABinary_1.isLid)(jid)) {
707
+ throw new boom_1.Boom(`JID "${jid}" is not a LID`, {
708
+ statusCode: 400
709
+ });
710
+ }
711
+ },
712
+ getLIDById: async (jid) => {
713
+ if ((0, WABinary_1.isLid)(jid)) {
714
+ return jid;
715
+ }
716
+ const lid = await signalRepository.lidMapping.get(jid);
717
+ if (lid) {
718
+ return lid;
719
+ }
720
+ },
721
+ getPNById: async (jid) => {
722
+ if (!(0, WABinary_1.isLid)(jid)) {
723
+ return jid;
724
+ }
725
+ const pn = await signalRepository.lidMapping.get(jid);
726
+ if (pn) {
727
+ return pn;
728
+ }
729
+ },
730
+ storeLidPnMapping: (lid, pn) => {
731
+ return signalRepository.lidMapping.set(lid, pn);
732
+ },
733
+ // newsletter functions
734
+ newsletterCreate: async (name, description) => {
735
+ const result = await query({
736
+ tag: 'iq',
737
+ attrs: {
738
+ to: WABinary_1.S_WHATSAPP_NET,
739
+ type: 'set',
740
+ xmlns: 'newsletter'
741
+ },
742
+ content: [
743
+ {
744
+ tag: 'create',
745
+ attrs: {},
746
+ content: [
747
+ {
748
+ tag: 'name',
749
+ attrs: {},
750
+ content: name
751
+ },
752
+ {
753
+ tag: 'description',
754
+ attrs: {},
755
+ content: description
756
+ }
757
+ ]
758
+ }
759
+ ]
760
+ });
761
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, 'newsletter');
762
+ const metadata = (0, Utils_1.parseNewsletterMetadata)(node);
763
+ return metadata;
764
+ },
765
+ getNewsletterInfo: async (jid) => {
766
+ const result = await query({
767
+ tag: 'iq',
768
+ attrs: {
769
+ to: WABinary_1.S_WHATSAPP_NET,
770
+ type: 'get',
771
+ xmlns: 'newsletter'
772
+ },
773
+ content: [
774
+ {
775
+ tag: 'newsletter',
776
+ attrs: {
777
+ id: jid,
778
+ type: 'invite'
779
+ }
780
+ }
781
+ ]
782
+ });
783
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, 'newsletter');
784
+ const metadata = (0, Utils_1.parseNewsletterMetadata)(node);
785
+ return metadata;
786
+ },
787
+ getNewsletterMessage: async (jid, serverId) => {
788
+ const result = await query({
789
+ tag: 'iq',
790
+ attrs: {
791
+ to: WABinary_1.S_WHATSAPP_NET,
792
+ type: 'get',
793
+ xmlns: 'newsletter'
794
+ },
795
+ content: [
796
+ {
797
+ tag: 'messages',
798
+ attrs: {
799
+ id: jid,
800
+ 'server-id': serverId
801
+ }
802
+ }
803
+ ]
804
+ });
805
+ const messages = (0, WABinary_1.getBinaryNodeChild)(result, 'messages');
806
+ const message = (0, WABinary_1.getBinaryNodeChild)(messages, 'message');
807
+ return (0, Utils_1.parseNewsletterMessage)(message);
808
+ },
809
+ updateNewsletterMute: async (jid, mute) => {
810
+ const result = await query({
811
+ tag: 'iq',
812
+ attrs: {
813
+ to: WABinary_1.S_WHATSAPP_NET,
814
+ type: 'set',
815
+ xmlns: 'newsletter'
816
+ },
817
+ content: [
818
+ {
819
+ tag: 'mute',
820
+ attrs: {
821
+ id: jid,
822
+ value: mute ? 'true' : 'false'
823
+ }
824
+ }
825
+ ]
826
+ });
827
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, 'newsletter');
828
+ const metadata = (0, Utils_1.parseNewsletterMetadata)(node);
829
+ return metadata;
830
+ },
831
+ toggleNewsletterSubscribe: async (jid, subscribe) => {
832
+ const result = await query({
833
+ tag: 'iq',
834
+ attrs: {
835
+ to: WABinary_1.S_WHATSAPP_NET,
836
+ type: 'set',
837
+ xmlns: 'newsletter'
838
+ },
839
+ content: [
840
+ {
841
+ tag: subscribe ? 'subscribe' : 'unsubscribe',
842
+ attrs: {
843
+ id: jid
844
+ }
845
+ }
846
+ ]
847
+ });
848
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, 'newsletter');
849
+ const metadata = (0, Utils_1.parseNewsletterMetadata)(node);
850
+ return metadata;
851
+ },
852
+ sendNewsletterMessage: async (jid, content) => {
853
+ const result = await ws.sendMessage(jid, content);
854
+ return result;
855
+ },
856
+ getNewsletterMessages: async (jid, count, after) => {
857
+ const attrs = {
858
+ id: jid,
859
+ count: count.toString(),
860
+ };
861
+ if (after) {
862
+ attrs.after = after.toString();
863
+ }
864
+ const result = await query({
865
+ tag: 'iq',
866
+ attrs: {
867
+ to: WABinary_1.S_WHATSAPP_NET,
868
+ type: 'get',
869
+ xmlns: 'newsletter'
870
+ },
871
+ content: [
872
+ {
873
+ tag: 'messages',
874
+ attrs
875
+ }
876
+ ]
877
+ });
878
+ const messages = (0, WABinary_1.getBinaryNodeChild)(result, 'messages');
879
+ const messageNodes = (0, WABinary_1.getBinaryNodeChildren)(messages, 'message');
880
+ return messageNodes.map(Utils_1.parseNewsletterMessage);
881
+ },
882
+ // contact functions
883
+ addOrEditContact: async (jid, action) => {
884
+ const result = await query({
885
+ tag: 'iq',
886
+ attrs: {
887
+ to: WABinary_1.S_WHATSAPP_NET,
888
+ type: 'set',
889
+ xmlns: 'contact'
890
+ },
891
+ content: [
892
+ {
893
+ tag: 'contact',
894
+ attrs: {
895
+ jid,
896
+ ...action
897
+ }
898
+ }
899
+ ]
900
+ });
901
+ return result;
902
+ },
903
+ removeContact: async (jid) => {
904
+ const result = await query({
905
+ tag: 'iq',
906
+ attrs: {
907
+ to: WABinary_1.S_WHATSAPP_NET,
908
+ type: 'set',
909
+ xmlns: 'contact'
910
+ },
911
+ content: [
912
+ {
913
+ tag: 'contact',
914
+ attrs: {
915
+ jid,
916
+ type: 'remove'
917
+ }
918
+ }
919
+ ]
920
+ });
921
+ return result;
922
+ },
923
+ // profile functions
924
+ updateProfilePicture: async (jid, content, options) => {
925
+ const { img } = await (0, Utils_1.generateProfilePicture)(content);
926
+ const result = await query({
927
+ tag: 'iq',
928
+ attrs: {
929
+ to: jid,
930
+ type: 'set',
931
+ xmlns: 'w:profile:picture'
932
+ },
933
+ content: [
934
+ {
935
+ tag: 'picture',
936
+ attrs: {
937
+ type: 'image',
938
+ ...options
939
+ },
940
+ content: img
941
+ }
942
+ ]
943
+ });
944
+ return result;
945
+ },
946
+ updateProfileName: async (name) => {
947
+ const result = await sendNode({
948
+ tag: 'presence',
949
+ attrs: {
950
+ name,
951
+ type: 'available'
952
+ }
953
+ });
954
+ return result;
955
+ },
956
+ updateProfileStatus: async (status) => {
957
+ const result = await query({
958
+ tag: 'iq',
959
+ attrs: {
960
+ to: WABinary_1.S_WHATSAPP_NET,
961
+ type: 'set',
962
+ xmlns: 'status'
963
+ },
964
+ content: [
965
+ {
966
+ tag: 'status',
967
+ attrs: {},
968
+ content: Buffer.from(status, 'utf-8')
969
+ }
970
+ ]
971
+ });
972
+ return result;
973
+ },
974
+ updateLastSeenPrivacy: async (value) => {
975
+ const result = await query({
976
+ tag: 'iq',
977
+ attrs: {
978
+ to: WABinary_1.S_WHATSAPP_NET,
979
+ type: 'set',
980
+ xmlns: 'privacy'
981
+ },
982
+ content: [
983
+ {
984
+ tag: 'privacy',
985
+ attrs: {},
986
+ content: [
987
+ {
988
+ tag: 'last',
989
+ attrs: {
990
+ value
991
+ }
992
+ }
993
+ ]
994
+ }
995
+ ]
996
+ });
997
+ return result;
998
+ },
999
+ updateOnlinePrivacy: async (value) => {
1000
+ const result = await query({
1001
+ tag: 'iq',
1002
+ attrs: {
1003
+ to: WABinary_1.S_WHATSAPP_NET,
1004
+ type: 'set',
1005
+ xmlns: 'privacy'
1006
+ },
1007
+ content: [
1008
+ {
1009
+ tag: 'privacy',
1010
+ attrs: {},
1011
+ content: [
1012
+ {
1013
+ tag: 'online',
1014
+ attrs: {
1015
+ value
1016
+ }
1017
+ }
1018
+ ]
1019
+ }
1020
+ ]
1021
+ });
1022
+ return result;
1023
+ },
1024
+ updateProfilePicturePrivacy: async (value) => {
1025
+ const result = await query({
1026
+ tag: 'iq',
1027
+ attrs: {
1028
+ to: WABinary_1.S_WHATSAPP_NET,
1029
+ type: 'set',
1030
+ xmlns: 'privacy'
1031
+ },
1032
+ content: [
1033
+ {
1034
+ tag: 'privacy',
1035
+ attrs: {},
1036
+ content: [
1037
+ {
1038
+ tag: 'profile',
1039
+ attrs: {
1040
+ value
1041
+ }
1042
+ }
1043
+ ]
1044
+ }
1045
+ ]
1046
+ });
1047
+ return result;
1048
+ },
1049
+ fetchStatus: async (jid) => {
1050
+ const result = await query({
1051
+ tag: 'iq',
1052
+ attrs: {
1053
+ to: jid,
1054
+ type: 'get',
1055
+ xmlns: 'status'
1056
+ }
1057
+ });
1058
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, 'status');
1059
+ return {
1060
+ status: node === null || node === void 0 ? void 0 : node.content.toString(),
1061
+ setAt: new Date(+(node === null || node === void 0 ? void 0 : node.attrs.t) * 1000)
1062
+ };
1063
+ },
1064
+ fetchBlocklist: async () => {
1065
+ const result = await query({
1066
+ tag: 'iq',
1067
+ attrs: {
1068
+ to: WABinary_1.S_WHATSAPP_NET,
1069
+ type: 'get',
1070
+ xmlns: 'blocklist'
1071
+ }
1072
+ });
1073
+ const node = (0, WABinary_1.getBinaryNodeChild)(result, 'list');
1074
+ return (0, WABinary_1.getBinaryNodeChildren)(node, 'item').map(i => i.attrs.jid);
1075
+ },
1076
+ blocklistUpdate: async (jid, action) => {
1077
+ const result = await query({
1078
+ tag: 'iq',
1079
+ attrs: {
1080
+ to: WABinary_1.S_WHATSAPP_NET,
1081
+ type: 'set',
1082
+ xmlns: 'blocklist'
1083
+ },
1084
+ content: [
1085
+ {
1086
+ tag: 'item',
1087
+ attrs: {
1088
+ jid,
1089
+ action
1090
+ }
1091
+ }
1092
+ ]
1093
+ });
1094
+ return result;
1095
+ }
691
1096
  };
692
1097
  };
693
1098
  exports.makeSocket = makeSocket;
@@ -43,7 +43,9 @@ export type AuthenticationCreds = SignalCreds & {
43
43
  readonly noiseKey: KeyPair;
44
44
  readonly pairingEphemeralKeyPair: KeyPair;
45
45
  advSecretKey: string;
46
- me?: Contact;
46
+ me?: Omit<Contact, 'imgUrl'> & {
47
+ lid?: string;
48
+ };
47
49
  account?: proto.IADVSignedDeviceIdentity;
48
50
  signalIdentities?: SignalIdentity[];
49
51
  myAppStateKeyId?: string;
@@ -51,6 +53,8 @@ export type AuthenticationCreds = SignalCreds & {
51
53
  nextPreKeyId: number;
52
54
  lastAccountSyncTimestamp?: number;
53
55
  platform?: string;
56
+ deviceIndex?: number;
57
+ historySyncConfig?: proto.IHistorySyncConfig;
54
58
  processedHistoryMessages: MinimalMessage[];
55
59
  /** number of times history & app state has been synced */
56
60
  accountSyncCounter: number;
@@ -69,6 +73,9 @@ export type SignalDataTypeMap = {
69
73
  };
70
74
  'app-state-sync-key': proto.Message.IAppStateSyncKeyData;
71
75
  'app-state-sync-version': LTHashState;
76
+ 'lid-mapping': {
77
+ [lid: string]: string;
78
+ };
72
79
  };
73
80
  export type SignalDataSet = {
74
81
  [T in keyof SignalDataTypeMap]?: {
@@ -21,3 +21,9 @@ export interface Contact {
21
21
  imgUrl?: string | null;
22
22
  status?: string;
23
23
  }
24
+ export interface ContactAction {
25
+ firstName?: string;
26
+ fullName?: string;
27
+ lidJid?: string;
28
+ saveOnPrimaryAddressbook?: boolean;
29
+ }
@@ -1,79 +1,22 @@
1
- import { proto } from '../../WAProto';
2
- export type NewsletterReactionMode = 'ALL' | 'BASIC' | 'NONE';
3
- export type NewsletterState = 'ACTIVE' | 'GEOSUSPENDED' | 'SUSPENDED';
4
- export type NewsletterVerification = 'VERIFIED' | 'UNVERIFIED';
5
- export type NewsletterMute = 'ON' | 'OFF' | 'UNDEFINED';
6
- export type NewsletterViewRole = 'ADMIN' | 'GUEST' | 'OWNER' | 'SUBSCRIBER';
7
- export type NewsletterViewerMetadata = {
8
- mute: NewsletterMute;
9
- view_role: NewsletterViewRole;
10
- };
1
+ import type { proto } from '../../WAProto';
11
2
  export type NewsletterMetadata = {
12
- /**jid of newsletter */
13
3
  id: string;
14
- /**state of newsletter */
15
- state: NewsletterState;
16
- /**creation timestamp of newsletter */
17
- creation_time: number;
18
- /**name of newsletter */
19
4
  name: string;
20
- /**timestamp of last name modification of newsletter */
21
- nameTime: number;
22
- /**description of newsletter */
23
5
  description: string;
24
- /**timestamp of last description modification of newsletter */
25
- descriptionTime: number;
26
- /**invite code of newsletter */
27
- invite: string;
28
- /**i dont know */
29
- handle: null;
30
- /**direct path of picture */
31
- picture: string | null;
32
- /**direct path of picture preview (lower quality) */
33
- preview: string | null;
34
- /**reaction mode of newsletter */
35
- reaction_codes?: NewsletterReactionMode;
36
- /**subscribers count of newsletter */
37
- subscribers: number;
38
- /**verification state of newsletter */
39
- verification: NewsletterVerification;
40
- /**viewer metadata */
41
- viewer_metadata: NewsletterViewerMetadata;
42
- };
43
- export type SubscriberAction = 'promote' | 'demote';
44
- export type ReactionModeUpdate = {
45
- reaction_codes: {
46
- blocked_codes: null;
47
- enabled_ts_sec: null;
48
- value: NewsletterReactionMode;
49
- };
50
- };
51
- /**only exists reaction mode update */
52
- export type NewsletterSettingsUpdate = ReactionModeUpdate;
53
- export type NewsletterReaction = {
54
- count: number;
55
- code: string;
56
- };
57
- export type NewsletterFetchedUpdate = {
58
- /**id of message in newsletter, starts from 100 */
59
- server_id: string;
60
- /**count of views in this message */
61
- views?: number;
62
- /**reactions in this message */
63
- reactions: NewsletterReaction[];
64
- /**the message, if you requested only updates, you will not receive message */
65
- message?: proto.IWebMessageInfo;
6
+ inviteCode: string;
7
+ handle: string;
8
+ subscriberCount: number;
9
+ verification: 'VERIFIED' | 'UNVERIFIED';
10
+ picture?: string;
11
+ preview?: string;
12
+ creationTime: number;
13
+ muted: boolean;
14
+ state: 'ACTIVE' | 'SUSPENDED' | 'GEOSUSPENDED';
15
+ viewRole: 'ADMIN' | 'GUEST' | 'SUBSCRIBER';
16
+ subscribe: 'SUBSCRIBED' | 'UNSUBSCRIBED';
66
17
  };
67
- export declare enum MexOperations {
68
- PROMOTE = "NotificationNewsletterAdminPromote",
69
- DEMOTE = "NotificationNewsletterAdminDemote",
70
- UPDATE = "NotificationNewsletterUpdate"
71
- }
72
- export declare enum XWAPaths {
73
- PROMOTE = "xwa2_notify_newsletter_admin_promote",
74
- DEMOTE = "xwa2_notify_newsletter_admin_demote",
75
- ADMIN_COUNT = "xwa2_newsletter_admin",
76
- CREATE = "xwa2_newsletter_create",
77
- NEWSLETTER = "xwa2_newsletter",
78
- METADATA_UPDATE = "xwa2_notify_newsletter_on_metadata_update"
79
- }
18
+ export type NewsletterMessage = {
19
+ serverMsgId: number;
20
+ views: number;
21
+ message: proto.IWebMessageInfo;
22
+ };
@@ -40,6 +40,10 @@ type E2ESessionOpts = {
40
40
  session: E2ESession;
41
41
  };
42
42
  export type SignalRepository = {
43
+ lidMapping: {
44
+ get: (lid: string) => Promise<string | undefined>;
45
+ set: (lid: string, pn: string) => Promise<void>;
46
+ };
43
47
  decryptGroupMessage(opts: DecryptGroupSignalOpts): Promise<Uint8Array>;
44
48
  processSenderKeyDistributionMessage(opts: ProcessSenderKeyDistributionMessageOpts): Promise<void>;
45
49
  decryptMessage(opts: DecryptSignalProtoOpts): Promise<Uint8Array>;
@@ -53,5 +57,7 @@ export type SignalRepository = {
53
57
  }>;
54
58
  injectE2ESession(opts: E2ESessionOpts): Promise<void>;
55
59
  jidToSignalProtocolAddress(jid: string): string;
60
+ getLidAddress(jid: string): any;
61
+ getDeviceCanHandleLid(): boolean;
56
62
  };
57
63
  export {};
@@ -115,5 +115,14 @@ export type SocketConfig = {
115
115
  getMessage: (key: proto.IMessageKey) => Promise<proto.IMessage | undefined>;
116
116
  /** cached group metadata, use to prevent redundant requests to WA & speed up msg sending */
117
117
  cachedGroupMetadata: (jid: string) => Promise<GroupMetadata | undefined>;
118
+ /** makeSignalRepository */
118
119
  makeSignalRepository: (auth: SignalAuthState) => SignalRepository;
120
+ /**
121
+ * Meta-coexistence on WhatsApp Web
122
+ */
123
+ coexistence?: boolean;
124
+ /**
125
+ * The number of messages to fetch at a time when interacting with newsletters
126
+ */
127
+ newsletterPageSize?: number;
119
128
  };
@@ -190,6 +190,16 @@ const initAuthCreds = () => {
190
190
  accountSettings: {
191
191
  unarchiveChats: false
192
192
  },
193
+ // ADVSignedDeviceIdentity
194
+ account: undefined,
195
+ // me: Omit<Contact, 'imgUrl'> & { lid?: string }
196
+ me: undefined,
197
+ // signalIdentities: SignalIdentity[]
198
+ signalIdentities: undefined,
199
+ platform: undefined,
200
+ myAppStateKeyId: undefined,
201
+ lastAccountSyncTimestamp: undefined,
202
+ historySyncConfig: undefined,
193
203
  registered: false,
194
204
  pairingCode: undefined,
195
205
  lastPropHash: undefined,
@@ -54,6 +54,11 @@ class CacheManager {
54
54
  return this.caches[cacheName]?.set(key, value, ttl);
55
55
  }
56
56
 
57
+ async setAsync(cacheName, key, fetchData, ttl = undefined) {
58
+ const value = await fetchData();
59
+ return this.set(cacheName, key, value, ttl);
60
+ }
61
+
57
62
  del(cacheName, key) {
58
63
  return this.caches[cacheName]?.del(key);
59
64
  }
@@ -62,6 +67,21 @@ class CacheManager {
62
67
  return this.caches[cacheName]?.getStats();
63
68
  }
64
69
 
70
+ // Enhanced cleanup for bad ACK entries
71
+ on(event, callback) {
72
+ if (event === 'bad_ack') {
73
+ // Setup cleanup listener for bad ACKs
74
+ this.badAckCallback = callback;
75
+ }
76
+ }
77
+
78
+ // Method to trigger bad ACK cleanup
79
+ cleanupBadAck(key) {
80
+ if (this.badAckCallback) {
81
+ this.badAckCallback(key);
82
+ }
83
+ }
84
+
65
85
  shutdown() {
66
86
  if (this.memoryCheckInterval) {
67
87
  clearInterval(this.memoryCheckInterval);
@@ -70,4 +90,4 @@ class CacheManager {
70
90
  }
71
91
  }
72
92
 
73
- module.exports = new CacheManager();
93
+ module.exports = new CacheManager();
@@ -32,3 +32,4 @@ __exportStar(require("./link-preview"), exports);
32
32
  __exportStar(require("./event-buffer"), exports);
33
33
  __exportStar(require("./process-message"), exports);
34
34
  __exportStar(require("./performance-config"), exports);
35
+ __exportStar(require("./newsletter-utils"), exports);
@@ -479,8 +479,21 @@ async function generateThumbnail(file, mediaType, options) {
479
479
  };
480
480
  }
481
481
  const getHttpStream = async (url, options = {}) => {
482
- const fetched = await axios_1.default.get(url.toString(), { ...options, responseType: 'stream' });
483
- return fetched.data;
482
+ const { retryRequestDelayMs, maxMsgRetryCount } = options;
483
+ let retries = 0;
484
+ while (retries < maxMsgRetryCount) {
485
+ try {
486
+ const fetched = await axios_1.default.get(url.toString(), { ...options, responseType: 'stream' });
487
+ return fetched.data;
488
+ }
489
+ catch (error) {
490
+ retries++;
491
+ if (retries >= maxMsgRetryCount) {
492
+ throw error;
493
+ }
494
+ await (0, generics_1.delay)(retryRequestDelayMs || 1000);
495
+ }
496
+ }
484
497
  };
485
498
  exports.getHttpStream = getHttpStream;
486
499
  const prepareStream = async (media, mediaType, { logger, saveOriginalFileIfRequired, opts } = {}) => {