wa-multi-mongodb 3.11.0 → 3.11.2
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.
- package/dist/Socket/index.d.ts.map +1 -1
- package/dist/Socket/index.js +22 -2
- package/dist/Utils/group-cache.d.ts.map +1 -1
- package/dist/Utils/group-cache.js +20 -12
- package/dist/Utils/index.d.ts +1 -0
- package/dist/Utils/index.d.ts.map +1 -1
- package/dist/Utils/index.js +1 -0
- package/dist/Utils/mongo-auth-state.d.ts.map +1 -1
- package/dist/Utils/mongo-auth-state.js +5 -3
- package/dist/Utils/save-media.d.ts.map +1 -1
- package/dist/Utils/save-media.js +6 -4
- package/dist/Utils/security.d.ts +7 -0
- package/dist/Utils/security.d.ts.map +1 -0
- package/dist/Utils/security.js +44 -0
- package/dist/cjs/Socket/index.d.ts.map +1 -1
- package/dist/cjs/Socket/index.js +22 -2
- package/dist/cjs/Utils/group-cache.d.ts.map +1 -1
- package/dist/cjs/Utils/group-cache.js +20 -12
- package/dist/cjs/Utils/index.d.ts +1 -0
- package/dist/cjs/Utils/index.d.ts.map +1 -1
- package/dist/cjs/Utils/index.js +1 -0
- package/dist/cjs/Utils/mongo-auth-state.d.ts.map +1 -1
- package/dist/cjs/Utils/mongo-auth-state.js +5 -3
- package/dist/cjs/Utils/save-media.d.ts.map +1 -1
- package/dist/cjs/Utils/save-media.js +6 -4
- package/dist/cjs/Utils/security.d.ts +7 -0
- package/dist/cjs/Utils/security.d.ts.map +1 -0
- package/dist/cjs/Utils/security.js +56 -0
- package/package.json +8 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Socket/index.ts"],"names":[],"mappings":"AAAA,OAAqB,EAInB,QAAQ,EAGT,MAAM,SAAS,CAAC;AAMjB,OAAO,KAAK,EAEV,eAAe,EACf,cAAc,EACd,kBAAkB,EAEnB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Socket/index.ts"],"names":[],"mappings":"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"}
|
package/dist/Socket/index.js
CHANGED
|
@@ -20,6 +20,7 @@ import { parseMessageStatusCodeToReadable } from "../Utils/message-status.js";
|
|
|
20
20
|
import { MongoClient } from "mongodb";
|
|
21
21
|
import { useMongoAuthState } from "../Utils/mongo-auth-state.js";
|
|
22
22
|
import { createDelay } from "../Utils/create-delay.js";
|
|
23
|
+
import { assertValidJidIdentifier, assertValidSessionId, maskSensitiveValue } from "../Utils/security.js";
|
|
23
24
|
const sessions = new Map();
|
|
24
25
|
/**
|
|
25
26
|
* Valid PlatformType values that WhatsApp recognizes
|
|
@@ -143,6 +144,7 @@ function initMongo() {
|
|
|
143
144
|
});
|
|
144
145
|
}
|
|
145
146
|
export const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (sessionId = "mysession", options = { printQR: true }) {
|
|
147
|
+
sessionId = assertValidSessionId(sessionId);
|
|
146
148
|
if (isSessionExistAndRunning(sessionId))
|
|
147
149
|
throw new WhatsappError(Messages.sessionAlreadyExist(sessionId));
|
|
148
150
|
yield initMongo();
|
|
@@ -310,6 +312,7 @@ export const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0
|
|
|
310
312
|
* @returns Promise<WASocket> The WhatsApp socket instance
|
|
311
313
|
*/
|
|
312
314
|
export const startSessionWithPairingCode = (sessionId_1, phoneNumber_1, ...args_1) => __awaiter(void 0, [sessionId_1, phoneNumber_1, ...args_1], void 0, function* (sessionId, phoneNumber, options = {}) {
|
|
315
|
+
sessionId = assertValidSessionId(sessionId);
|
|
313
316
|
if (isSessionExistAndRunning(sessionId))
|
|
314
317
|
throw new WhatsappError(Messages.sessionAlreadyExist(sessionId));
|
|
315
318
|
// Simpan informasi session pairing code untuk auto-reconnect
|
|
@@ -353,7 +356,7 @@ export const startSessionWithPairingCode = (sessionId_1, phoneNumber_1, ...args_
|
|
|
353
356
|
const code = yield sock.requestPairingCode(phoneNumberFormatted);
|
|
354
357
|
// Pastikan kode ada dan merupakan string
|
|
355
358
|
if (code && typeof code === 'string') {
|
|
356
|
-
console.log(`Pairing code untuk session ${sessionId}: ${code}`);
|
|
359
|
+
console.log(`Pairing code untuk session ${sessionId}: ${maskSensitiveValue(code)}`);
|
|
357
360
|
// Panggil callback yang terdaftar
|
|
358
361
|
(_a = callback.get(CALLBACK_KEY.ON_PAIRING_CODE)) === null || _a === void 0 ? void 0 : _a(sessionId, code);
|
|
359
362
|
(_b = options.onPairingCode) === null || _b === void 0 ? void 0 : _b.call(options, code);
|
|
@@ -522,6 +525,7 @@ export const startWhatsapp = startSession;
|
|
|
522
525
|
* @param sessionId Session ID to soft delete
|
|
523
526
|
*/
|
|
524
527
|
const softDeleteSession = (sessionId_1, ...args_1) => __awaiter(void 0, [sessionId_1, ...args_1], void 0, function* (sessionId, preserveData = false) {
|
|
528
|
+
sessionId = assertValidSessionId(sessionId);
|
|
525
529
|
const session = getSession(sessionId);
|
|
526
530
|
try {
|
|
527
531
|
yield (session === null || session === void 0 ? void 0 : session.logout());
|
|
@@ -557,6 +561,7 @@ const softDeleteSession = (sessionId_1, ...args_1) => __awaiter(void 0, [session
|
|
|
557
561
|
}
|
|
558
562
|
});
|
|
559
563
|
export const deleteSession = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
564
|
+
sessionId = assertValidSessionId(sessionId);
|
|
560
565
|
const session = getSession(sessionId);
|
|
561
566
|
try {
|
|
562
567
|
yield (session === null || session === void 0 ? void 0 : session.logout());
|
|
@@ -615,7 +620,7 @@ export const getAllSession = () => __awaiter(void 0, void 0, void 0, function* (
|
|
|
615
620
|
});
|
|
616
621
|
// Untuk backward compatibility
|
|
617
622
|
export const getAllSessionSync = () => Array.from(sessions.keys());
|
|
618
|
-
export const getSession = (key) => sessions.get(key);
|
|
623
|
+
export const getSession = (key) => sessions.get(assertValidSessionId(key));
|
|
619
624
|
export const downloadMediaMessage = (_a) => __awaiter(void 0, [_a], void 0, function* ({ sessionId, message, key, }) {
|
|
620
625
|
const session = getSession(sessionId);
|
|
621
626
|
if (!session) {
|
|
@@ -636,6 +641,7 @@ export const downloadMediaMessage = (_a) => __awaiter(void 0, [_a], void 0, func
|
|
|
636
641
|
}
|
|
637
642
|
});
|
|
638
643
|
const isSessionExistAndRunning = (sessionId) => {
|
|
644
|
+
sessionId = assertValidSessionId(sessionId);
|
|
639
645
|
// Cek jika session sudah berjalan di memory
|
|
640
646
|
if (getSession(sessionId)) {
|
|
641
647
|
return true;
|
|
@@ -648,6 +654,7 @@ const isSessionExistAndRunning = (sessionId) => {
|
|
|
648
654
|
* @returns Boolean indicating if session should be loaded
|
|
649
655
|
*/
|
|
650
656
|
const shouldLoadSession = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
657
|
+
sessionId = assertValidSessionId(sessionId);
|
|
651
658
|
// Jika session sudah berjalan di memory, tidak perlu load lagi
|
|
652
659
|
if (getSession(sessionId)) {
|
|
653
660
|
return false;
|
|
@@ -745,6 +752,7 @@ export const setCredentialsDir = (dirname = "wa_credentials") => {
|
|
|
745
752
|
*/
|
|
746
753
|
export const reconnect = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
747
754
|
try {
|
|
755
|
+
sessionId = assertValidSessionId(sessionId);
|
|
748
756
|
// Cek jika session masih ada di memory
|
|
749
757
|
const existingSession = sessions.get(sessionId);
|
|
750
758
|
// Hapus session terlebih dahulu untuk menghindari konflik
|
|
@@ -861,6 +869,7 @@ export const getPairingCodeSessions = () => {
|
|
|
861
869
|
* @returns Object with session status information
|
|
862
870
|
*/
|
|
863
871
|
export const getSessionStatus = (sessionId) => {
|
|
872
|
+
sessionId = assertValidSessionId(sessionId);
|
|
864
873
|
const isRunning = !!getSession(sessionId);
|
|
865
874
|
const isPairingCodeSession = pairingCodeSessions.has(sessionId);
|
|
866
875
|
const retryAttempts = retryCount.get(sessionId) || 0;
|
|
@@ -878,6 +887,8 @@ export const setGroupCacheConfig = (options) => {
|
|
|
878
887
|
};
|
|
879
888
|
// Fungsi baru untuk mendapatkan atau memuat data grup dengan multi-session support
|
|
880
889
|
export const getGroupMetadata = (sessionId_1, jid_1, ...args_1) => __awaiter(void 0, [sessionId_1, jid_1, ...args_1], void 0, function* (sessionId, jid, forceFetch = false) {
|
|
890
|
+
sessionId = assertValidSessionId(sessionId);
|
|
891
|
+
jid = assertValidJidIdentifier(jid, "jid");
|
|
881
892
|
// Get the session socket
|
|
882
893
|
const sock = getSession(sessionId);
|
|
883
894
|
if (!sock) {
|
|
@@ -906,10 +917,13 @@ export const getGroupMetadata = (sessionId_1, jid_1, ...args_1) => __awaiter(voi
|
|
|
906
917
|
});
|
|
907
918
|
// Fungsi baru untuk menghapus cache grup tertentu
|
|
908
919
|
export const clearGroupMetadataCache = (sessionId, jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
920
|
+
sessionId = assertValidSessionId(sessionId);
|
|
921
|
+
jid = assertValidJidIdentifier(jid, "jid");
|
|
909
922
|
yield groupCache.delete(sessionId, jid);
|
|
910
923
|
});
|
|
911
924
|
// Fungsi untuk membersihkan seluruh cache grup untuk session tertentu
|
|
912
925
|
export const clearSessionGroupMetadataCache = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
926
|
+
sessionId = assertValidSessionId(sessionId);
|
|
913
927
|
yield groupCache.clearSessionCache(sessionId);
|
|
914
928
|
});
|
|
915
929
|
// Fungsi untuk membersihkan seluruh cache grup untuk semua session
|
|
@@ -941,6 +955,8 @@ export const clearAllGroupMetadataCache = () => {
|
|
|
941
955
|
*/
|
|
942
956
|
export const getPNForLID = (sessionId, lid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
943
957
|
var _a, _b;
|
|
958
|
+
sessionId = assertValidSessionId(sessionId);
|
|
959
|
+
lid = assertValidJidIdentifier(lid, "lid");
|
|
944
960
|
const session = getSession(sessionId);
|
|
945
961
|
if (!session) {
|
|
946
962
|
return {
|
|
@@ -1008,6 +1024,7 @@ export const getPNForLID = (sessionId, lid) => __awaiter(void 0, void 0, void 0,
|
|
|
1008
1024
|
*/
|
|
1009
1025
|
export const getLIDForPN = (sessionId, pn) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1010
1026
|
var _a, _b;
|
|
1027
|
+
sessionId = assertValidSessionId(sessionId);
|
|
1011
1028
|
const session = getSession(sessionId);
|
|
1012
1029
|
if (!session) {
|
|
1013
1030
|
return {
|
|
@@ -1073,6 +1090,7 @@ export const getLIDForPN = (sessionId, pn) => __awaiter(void 0, void 0, void 0,
|
|
|
1073
1090
|
* @note This may return an empty array if no mappings are available yet.
|
|
1074
1091
|
*/
|
|
1075
1092
|
export const getAllLIDMappings = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1093
|
+
sessionId = assertValidSessionId(sessionId);
|
|
1076
1094
|
const session = getSession(sessionId);
|
|
1077
1095
|
if (!session) {
|
|
1078
1096
|
throw new WhatsappError(Messages.sessionNotFound(sessionId));
|
|
@@ -1164,6 +1182,7 @@ export const isPNFormat = (jid) => {
|
|
|
1164
1182
|
* ```
|
|
1165
1183
|
*/
|
|
1166
1184
|
export const toPhoneNumber = (sessionId, jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1185
|
+
sessionId = assertValidSessionId(sessionId);
|
|
1167
1186
|
// Handle null/undefined input
|
|
1168
1187
|
if (!jid) {
|
|
1169
1188
|
return null;
|
|
@@ -1214,6 +1233,7 @@ export const toPhoneNumber = (sessionId, jid) => __awaiter(void 0, void 0, void
|
|
|
1214
1233
|
* ```
|
|
1215
1234
|
*/
|
|
1216
1235
|
export const toLID = (sessionId, jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1236
|
+
sessionId = assertValidSessionId(sessionId);
|
|
1217
1237
|
// If already in LID format, return as-is
|
|
1218
1238
|
if (isLIDFormat(jid)) {
|
|
1219
1239
|
return jid;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group-cache.d.ts","sourceRoot":"","sources":["../../src/Utils/group-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"group-cache.d.ts","sourceRoot":"","sources":["../../src/Utils/group-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAMxC,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAqB;IAC5C,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAuB;IAGvC,OAAO;WAUO,WAAW,IAAI,kBAAkB;IAQlC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBpD,OAAO,CAAC,cAAc;IAKT,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAsCtE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B/E,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBzD,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBzD,SAAS,CAAC,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE;IAU5D,KAAK,IAAI,IAAI;CAGrB;AAGD,eAAO,MAAM,UAAU,oBAAmC,CAAC"}
|
|
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import NodeCache from "node-cache";
|
|
11
11
|
import { MongoClient } from "mongodb";
|
|
12
12
|
import { CREDENTIALS } from "../Defaults/index.js";
|
|
13
|
+
import { assertValidJidIdentifier, assertValidSessionId } from "./security.js";
|
|
13
14
|
// Class untuk mengelola cache group metadata dengan pendekatan hybrid (NodeCache + MongoDB)
|
|
14
15
|
export class GroupMetadataCache {
|
|
15
16
|
// Konstruktor private untuk singleton pattern
|
|
@@ -58,8 +59,10 @@ export class GroupMetadataCache {
|
|
|
58
59
|
// Mendapatkan metadata grup dari cache atau MongoDB
|
|
59
60
|
get(sessionId, groupId) {
|
|
60
61
|
return __awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
const safeSessionId = assertValidSessionId(sessionId);
|
|
63
|
+
const safeGroupId = assertValidJidIdentifier(groupId, "groupId");
|
|
61
64
|
// Buat kunci cache dengan kombinasi sessionId dan groupId
|
|
62
|
-
const cacheKey = this.createCacheKey(
|
|
65
|
+
const cacheKey = this.createCacheKey(safeSessionId, safeGroupId);
|
|
63
66
|
// Coba ambil dari cache memory dulu
|
|
64
67
|
const cachedData = this.cache.get(cacheKey);
|
|
65
68
|
if (cachedData) {
|
|
@@ -69,8 +72,8 @@ export class GroupMetadataCache {
|
|
|
69
72
|
if (this.mongoCollection) {
|
|
70
73
|
try {
|
|
71
74
|
const data = yield this.mongoCollection.findOne({
|
|
72
|
-
id:
|
|
73
|
-
sessionId:
|
|
75
|
+
id: safeGroupId,
|
|
76
|
+
sessionId: safeSessionId
|
|
74
77
|
});
|
|
75
78
|
if (data) {
|
|
76
79
|
// Hapus _id dari MongoDB yang tidak diperlukan
|
|
@@ -91,18 +94,20 @@ export class GroupMetadataCache {
|
|
|
91
94
|
// Menyimpan metadata grup ke cache dan MongoDB
|
|
92
95
|
set(sessionId, groupId, metadata) {
|
|
93
96
|
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
+
const safeSessionId = assertValidSessionId(sessionId);
|
|
98
|
+
const safeGroupId = assertValidJidIdentifier(groupId, "groupId");
|
|
94
99
|
// Buat kunci cache dengan kombinasi sessionId dan groupId
|
|
95
|
-
const cacheKey = this.createCacheKey(
|
|
100
|
+
const cacheKey = this.createCacheKey(safeSessionId, safeGroupId);
|
|
96
101
|
// Simpan ke cache memory
|
|
97
102
|
this.cache.set(cacheKey, metadata);
|
|
98
103
|
// Jika MongoDB tersedia, simpan juga ke MongoDB
|
|
99
104
|
if (this.mongoCollection) {
|
|
100
105
|
try {
|
|
101
106
|
// Tambahkan sessionId ke data yang disimpan
|
|
102
|
-
const dataToStore = Object.assign(Object.assign({}, metadata), { sessionId });
|
|
107
|
+
const dataToStore = Object.assign(Object.assign({}, metadata), { sessionId: safeSessionId });
|
|
103
108
|
yield this.mongoCollection.updateOne({
|
|
104
|
-
id:
|
|
105
|
-
sessionId:
|
|
109
|
+
id: safeGroupId,
|
|
110
|
+
sessionId: safeSessionId
|
|
106
111
|
}, { $set: dataToStore }, { upsert: true });
|
|
107
112
|
}
|
|
108
113
|
catch (error) {
|
|
@@ -114,16 +119,18 @@ export class GroupMetadataCache {
|
|
|
114
119
|
// Menghapus metadata grup dari cache dan MongoDB
|
|
115
120
|
delete(sessionId, groupId) {
|
|
116
121
|
return __awaiter(this, void 0, void 0, function* () {
|
|
122
|
+
const safeSessionId = assertValidSessionId(sessionId);
|
|
123
|
+
const safeGroupId = assertValidJidIdentifier(groupId, "groupId");
|
|
117
124
|
// Buat kunci cache dengan kombinasi sessionId dan groupId
|
|
118
|
-
const cacheKey = this.createCacheKey(
|
|
125
|
+
const cacheKey = this.createCacheKey(safeSessionId, safeGroupId);
|
|
119
126
|
// Hapus dari cache memory
|
|
120
127
|
this.cache.del(cacheKey);
|
|
121
128
|
// Jika MongoDB tersedia, hapus juga dari MongoDB
|
|
122
129
|
if (this.mongoCollection) {
|
|
123
130
|
try {
|
|
124
131
|
yield this.mongoCollection.deleteOne({
|
|
125
|
-
id:
|
|
126
|
-
sessionId:
|
|
132
|
+
id: safeGroupId,
|
|
133
|
+
sessionId: safeSessionId
|
|
127
134
|
});
|
|
128
135
|
}
|
|
129
136
|
catch (error) {
|
|
@@ -135,10 +142,11 @@ export class GroupMetadataCache {
|
|
|
135
142
|
// Menghapus semua cache untuk session tertentu
|
|
136
143
|
clearSessionCache(sessionId) {
|
|
137
144
|
return __awaiter(this, void 0, void 0, function* () {
|
|
145
|
+
const safeSessionId = assertValidSessionId(sessionId);
|
|
138
146
|
// Hapus dari MongoDB
|
|
139
147
|
if (this.mongoCollection) {
|
|
140
148
|
try {
|
|
141
|
-
yield this.mongoCollection.deleteMany({ sessionId:
|
|
149
|
+
yield this.mongoCollection.deleteMany({ sessionId: safeSessionId });
|
|
142
150
|
}
|
|
143
151
|
catch (error) {
|
|
144
152
|
console.error(`Error clearing session ${sessionId} cache from MongoDB:`, error);
|
|
@@ -147,7 +155,7 @@ export class GroupMetadataCache {
|
|
|
147
155
|
// Hapus dari memory cache
|
|
148
156
|
// Karena NodeCache tidak mendukung wildcard delete, kita harus mendapatkan semua kunci dulu
|
|
149
157
|
const allKeys = this.cache.keys();
|
|
150
|
-
const sessionKeys = allKeys.filter(key => key.startsWith(`${
|
|
158
|
+
const sessionKeys = allKeys.filter(key => key.startsWith(`${safeSessionId}:`));
|
|
151
159
|
sessionKeys.forEach(key => this.cache.del(key));
|
|
152
160
|
});
|
|
153
161
|
}
|
package/dist/Utils/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/Utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
|
package/dist/Utils/index.js
CHANGED
|
@@ -3,5 +3,6 @@ export * from "./is-exist.js";
|
|
|
3
3
|
export * from "./create-delay.js";
|
|
4
4
|
export * from "./group-cache.js";
|
|
5
5
|
export * from "./lid-utils.js";
|
|
6
|
+
export * from "./security.js";
|
|
6
7
|
// Note: setCredentialsDir & setMongoDBNames have been moved to src/Socket/index.ts
|
|
7
8
|
// Please import them directly from there instead
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongo-auth-state.d.ts","sourceRoot":"","sources":["../../src/Utils/mongo-auth-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAuB,MAAM,SAAS,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"mongo-auth-state.d.ts","sourceRoot":"","sources":["../../src/Utils/mongo-auth-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAuB,MAAM,SAAS,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAwC1C,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU;;;;kBAkC7D,CAAC,SAAS,MAAM,iBAAiB,QAAQ,CAAC,OAAO,MAAM,EAAE;;;2BAWhD,GAAG;;;;GAqB/B"}
|
|
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { proto } from "baileys/WAProto/index.js";
|
|
11
11
|
import { Curve, signedKeyPair } from "baileys/lib/Utils/crypto.js";
|
|
12
12
|
import { generateRegistrationId } from "baileys/lib/Utils/generics.js";
|
|
13
|
+
import { assertValidSessionId } from "./security.js";
|
|
13
14
|
const BufferJSON = {
|
|
14
15
|
replacer: (_, value) => {
|
|
15
16
|
if (Buffer.isBuffer(value) || value instanceof Uint8Array || (value === null || value === void 0 ? void 0 : value.type) === "Buffer") {
|
|
@@ -47,17 +48,18 @@ const initAuthCreds = () => {
|
|
|
47
48
|
};
|
|
48
49
|
export function useMongoAuthState(sessionId, collection) {
|
|
49
50
|
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
const safeSessionId = assertValidSessionId(sessionId);
|
|
50
52
|
const readState = () => __awaiter(this, void 0, void 0, function* () {
|
|
51
|
-
const doc = yield collection.findOne({ sessionId });
|
|
53
|
+
const doc = yield collection.findOne({ sessionId: safeSessionId });
|
|
52
54
|
return (doc === null || doc === void 0 ? void 0 : doc.state)
|
|
53
55
|
? JSON.parse(JSON.stringify(doc.state), BufferJSON.reviver)
|
|
54
56
|
: null;
|
|
55
57
|
});
|
|
56
58
|
const writeState = (state) => __awaiter(this, void 0, void 0, function* () {
|
|
57
|
-
yield collection.updateOne({ sessionId }, { $set: { state: JSON.parse(JSON.stringify(state, BufferJSON.replacer)) } }, { upsert: true });
|
|
59
|
+
yield collection.updateOne({ sessionId: safeSessionId }, { $set: { state: JSON.parse(JSON.stringify(state, BufferJSON.replacer)) } }, { upsert: true });
|
|
58
60
|
});
|
|
59
61
|
const removeKey = (key) => __awaiter(this, void 0, void 0, function* () {
|
|
60
|
-
yield collection.updateOne({ sessionId }, { $unset: { [`state.keys.${key}`]: "" } });
|
|
62
|
+
yield collection.updateOne({ sessionId: safeSessionId }, { $unset: { [`state.keys.${key}`]: "" } });
|
|
61
63
|
});
|
|
62
64
|
const savedState = (yield readState()) || {};
|
|
63
65
|
const creds = savedState.creds || initAuthCreds();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"save-media.d.ts","sourceRoot":"","sources":["../../src/Utils/save-media.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"save-media.d.ts","sourceRoot":"","sources":["../../src/Utils/save-media.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAU3C,eAAO,MAAM,gBAAgB,GAAU,KAAK,eAAe,EAAE,MAAM,MAAM,kBAOxE,CAAC;AACF,eAAO,MAAM,gBAAgB,GAAU,KAAK,eAAe,EAAE,MAAM,MAAM,kBAOxE,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,KAAK,eAAe,EACpB,MAAM,MAAM,kBAUb,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAU,KAAK,eAAe,EAAE,MAAM,MAAM,kBAOxE,CAAC"}
|
package/dist/Utils/save-media.js
CHANGED
|
@@ -10,8 +10,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { downloadMediaMessage } from "baileys";
|
|
11
11
|
import ValidationError from "./error.js";
|
|
12
12
|
import fs from "fs/promises";
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
import { assertSafeFilePath, sanitizeFileExtension } from "./security.js";
|
|
14
|
+
const saveMedia = (filePath, data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
|
+
const safePath = assertSafeFilePath(filePath);
|
|
16
|
+
yield fs.writeFile(safePath, data.toString("base64"), "base64");
|
|
15
17
|
});
|
|
16
18
|
export const saveImageHandler = (msg, path) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
19
|
var _a;
|
|
@@ -32,8 +34,8 @@ export const saveDocumentHandler = (msg, path) => __awaiter(void 0, void 0, void
|
|
|
32
34
|
if (!((_a = msg.message) === null || _a === void 0 ? void 0 : _a.documentMessage))
|
|
33
35
|
throw new ValidationError("Message is not contain Document");
|
|
34
36
|
const buf = yield downloadMediaMessage(msg, "buffer", {});
|
|
35
|
-
const ext = (_b = msg.message.documentMessage.fileName) === null || _b === void 0 ? void 0 : _b.split(".").pop();
|
|
36
|
-
path
|
|
37
|
+
const ext = sanitizeFileExtension((_b = msg.message.documentMessage.fileName) === null || _b === void 0 ? void 0 : _b.split(".").pop());
|
|
38
|
+
path = `${assertSafeFilePath(path)}.${ext}`;
|
|
37
39
|
return saveMedia(path, buf);
|
|
38
40
|
});
|
|
39
41
|
export const saveAudioHandler = (msg, path) => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const assertValidIdentifier: (value: string, fieldName: string) => string;
|
|
2
|
+
export declare const assertValidSessionId: (sessionId: string) => string;
|
|
3
|
+
export declare const assertValidJidIdentifier: (value: string, fieldName: string) => string;
|
|
4
|
+
export declare const assertSafeFilePath: (filePath: string) => string;
|
|
5
|
+
export declare const sanitizeFileExtension: (extension?: string) => string;
|
|
6
|
+
export declare const maskSensitiveValue: (value: string, visibleChars?: number) => string;
|
|
7
|
+
//# sourceMappingURL=security.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/Utils/security.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,qBAAqB,GAAI,OAAO,MAAM,EAAE,WAAW,MAAM,KAAG,MAQxE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,KAAG,MACV,CAAC;AAEhD,eAAO,MAAM,wBAAwB,GAAI,OAAO,MAAM,EAAE,WAAW,MAAM,KAAG,MAQ3E,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,KAAG,MAiBrD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,YAAY,MAAM,KAAG,MAK1D,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,EAAE,qBAAgB,KAAG,MAKpE,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { WhatsappError } from "../Error/index.js";
|
|
3
|
+
const SAFE_IDENTIFIER_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
|
|
4
|
+
const SAFE_JID_IDENTIFIER_PATTERN = /^[A-Za-z0-9_@.:-]{1,192}$/;
|
|
5
|
+
export const assertValidIdentifier = (value, fieldName) => {
|
|
6
|
+
if (typeof value !== "string" || !SAFE_IDENTIFIER_PATTERN.test(value)) {
|
|
7
|
+
throw new WhatsappError(`${fieldName} hanya boleh berisi huruf, angka, underscore, atau dash dengan panjang 1-128 karakter`);
|
|
8
|
+
}
|
|
9
|
+
return value;
|
|
10
|
+
};
|
|
11
|
+
export const assertValidSessionId = (sessionId) => assertValidIdentifier(sessionId, "sessionId");
|
|
12
|
+
export const assertValidJidIdentifier = (value, fieldName) => {
|
|
13
|
+
if (typeof value !== "string" || !SAFE_JID_IDENTIFIER_PATTERN.test(value)) {
|
|
14
|
+
throw new WhatsappError(`${fieldName} berisi karakter tidak valid atau melebihi 192 karakter`);
|
|
15
|
+
}
|
|
16
|
+
return value;
|
|
17
|
+
};
|
|
18
|
+
export const assertSafeFilePath = (filePath) => {
|
|
19
|
+
if (typeof filePath !== "string" || filePath.trim().length === 0) {
|
|
20
|
+
throw new WhatsappError("File path is required");
|
|
21
|
+
}
|
|
22
|
+
if (filePath.includes("\0")) {
|
|
23
|
+
throw new WhatsappError("File path contains invalid characters");
|
|
24
|
+
}
|
|
25
|
+
const normalized = path.normalize(filePath);
|
|
26
|
+
const baseName = path.basename(normalized);
|
|
27
|
+
if (!baseName || baseName === "." || baseName === "..") {
|
|
28
|
+
throw new WhatsappError("File path must include a valid file name");
|
|
29
|
+
}
|
|
30
|
+
return normalized;
|
|
31
|
+
};
|
|
32
|
+
export const sanitizeFileExtension = (extension) => {
|
|
33
|
+
if (!extension)
|
|
34
|
+
return "bin";
|
|
35
|
+
const cleanExtension = extension.replace(/[^A-Za-z0-9]/g, "").slice(0, 16);
|
|
36
|
+
return cleanExtension || "bin";
|
|
37
|
+
};
|
|
38
|
+
export const maskSensitiveValue = (value, visibleChars = 2) => {
|
|
39
|
+
if (!value)
|
|
40
|
+
return "";
|
|
41
|
+
if (value.length <= visibleChars * 2)
|
|
42
|
+
return "*".repeat(value.length);
|
|
43
|
+
return `${value.slice(0, visibleChars)}${"*".repeat(value.length - visibleChars * 2)}${value.slice(-visibleChars)}`;
|
|
44
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Socket/index.ts"],"names":[],"mappings":"AAAA,OAAqB,EAInB,QAAQ,EAGT,MAAM,SAAS,CAAC;AAMjB,OAAO,KAAK,EAEV,eAAe,EACf,cAAc,EACd,kBAAkB,EAEnB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Socket/index.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/Socket/index.js
CHANGED
|
@@ -60,6 +60,7 @@ const message_status_1 = require("../Utils/message-status");
|
|
|
60
60
|
const mongodb_1 = require("mongodb");
|
|
61
61
|
const mongo_auth_state_1 = require("../Utils/mongo-auth-state");
|
|
62
62
|
const create_delay_1 = require("../Utils/create-delay");
|
|
63
|
+
const security_1 = require("../Utils/security");
|
|
63
64
|
const sessions = new Map();
|
|
64
65
|
/**
|
|
65
66
|
* Valid PlatformType values that WhatsApp recognizes
|
|
@@ -184,6 +185,7 @@ function initMongo() {
|
|
|
184
185
|
});
|
|
185
186
|
}
|
|
186
187
|
const startSession = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (sessionId = "mysession", options = { printQR: true }) {
|
|
188
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
187
189
|
if (isSessionExistAndRunning(sessionId))
|
|
188
190
|
throw new Error_1.WhatsappError(Defaults_1.Messages.sessionAlreadyExist(sessionId));
|
|
189
191
|
yield initMongo();
|
|
@@ -352,6 +354,7 @@ exports.startSession = startSession;
|
|
|
352
354
|
* @returns Promise<WASocket> The WhatsApp socket instance
|
|
353
355
|
*/
|
|
354
356
|
const startSessionWithPairingCode = (sessionId_1, phoneNumber_1, ...args_1) => __awaiter(void 0, [sessionId_1, phoneNumber_1, ...args_1], void 0, function* (sessionId, phoneNumber, options = {}) {
|
|
357
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
355
358
|
if (isSessionExistAndRunning(sessionId))
|
|
356
359
|
throw new Error_1.WhatsappError(Defaults_1.Messages.sessionAlreadyExist(sessionId));
|
|
357
360
|
// Simpan informasi session pairing code untuk auto-reconnect
|
|
@@ -395,7 +398,7 @@ const startSessionWithPairingCode = (sessionId_1, phoneNumber_1, ...args_1) => _
|
|
|
395
398
|
const code = yield sock.requestPairingCode(phoneNumberFormatted);
|
|
396
399
|
// Pastikan kode ada dan merupakan string
|
|
397
400
|
if (code && typeof code === 'string') {
|
|
398
|
-
console.log(`Pairing code untuk session ${sessionId}: ${code}`);
|
|
401
|
+
console.log(`Pairing code untuk session ${sessionId}: ${(0, security_1.maskSensitiveValue)(code)}`);
|
|
399
402
|
// Panggil callback yang terdaftar
|
|
400
403
|
(_a = callback.get(Defaults_1.CALLBACK_KEY.ON_PAIRING_CODE)) === null || _a === void 0 ? void 0 : _a(sessionId, code);
|
|
401
404
|
(_b = options.onPairingCode) === null || _b === void 0 ? void 0 : _b.call(options, code);
|
|
@@ -565,6 +568,7 @@ exports.startWhatsapp = exports.startSession;
|
|
|
565
568
|
* @param sessionId Session ID to soft delete
|
|
566
569
|
*/
|
|
567
570
|
const softDeleteSession = (sessionId_1, ...args_1) => __awaiter(void 0, [sessionId_1, ...args_1], void 0, function* (sessionId, preserveData = false) {
|
|
571
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
568
572
|
const session = (0, exports.getSession)(sessionId);
|
|
569
573
|
try {
|
|
570
574
|
yield (session === null || session === void 0 ? void 0 : session.logout());
|
|
@@ -600,6 +604,7 @@ const softDeleteSession = (sessionId_1, ...args_1) => __awaiter(void 0, [session
|
|
|
600
604
|
}
|
|
601
605
|
});
|
|
602
606
|
const deleteSession = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
607
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
603
608
|
const session = (0, exports.getSession)(sessionId);
|
|
604
609
|
try {
|
|
605
610
|
yield (session === null || session === void 0 ? void 0 : session.logout());
|
|
@@ -661,7 +666,7 @@ exports.getAllSession = getAllSession;
|
|
|
661
666
|
// Untuk backward compatibility
|
|
662
667
|
const getAllSessionSync = () => Array.from(sessions.keys());
|
|
663
668
|
exports.getAllSessionSync = getAllSessionSync;
|
|
664
|
-
const getSession = (key) => sessions.get(key);
|
|
669
|
+
const getSession = (key) => sessions.get((0, security_1.assertValidSessionId)(key));
|
|
665
670
|
exports.getSession = getSession;
|
|
666
671
|
const downloadMediaMessage = (_a) => __awaiter(void 0, [_a], void 0, function* ({ sessionId, message, key, }) {
|
|
667
672
|
const session = (0, exports.getSession)(sessionId);
|
|
@@ -684,6 +689,7 @@ const downloadMediaMessage = (_a) => __awaiter(void 0, [_a], void 0, function* (
|
|
|
684
689
|
});
|
|
685
690
|
exports.downloadMediaMessage = downloadMediaMessage;
|
|
686
691
|
const isSessionExistAndRunning = (sessionId) => {
|
|
692
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
687
693
|
// Cek jika session sudah berjalan di memory
|
|
688
694
|
if ((0, exports.getSession)(sessionId)) {
|
|
689
695
|
return true;
|
|
@@ -696,6 +702,7 @@ const isSessionExistAndRunning = (sessionId) => {
|
|
|
696
702
|
* @returns Boolean indicating if session should be loaded
|
|
697
703
|
*/
|
|
698
704
|
const shouldLoadSession = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
705
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
699
706
|
// Jika session sudah berjalan di memory, tidak perlu load lagi
|
|
700
707
|
if ((0, exports.getSession)(sessionId)) {
|
|
701
708
|
return false;
|
|
@@ -804,6 +811,7 @@ exports.setCredentialsDir = setCredentialsDir;
|
|
|
804
811
|
*/
|
|
805
812
|
const reconnect = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
806
813
|
try {
|
|
814
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
807
815
|
// Cek jika session masih ada di memory
|
|
808
816
|
const existingSession = sessions.get(sessionId);
|
|
809
817
|
// Hapus session terlebih dahulu untuk menghindari konflik
|
|
@@ -923,6 +931,7 @@ exports.getPairingCodeSessions = getPairingCodeSessions;
|
|
|
923
931
|
* @returns Object with session status information
|
|
924
932
|
*/
|
|
925
933
|
const getSessionStatus = (sessionId) => {
|
|
934
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
926
935
|
const isRunning = !!(0, exports.getSession)(sessionId);
|
|
927
936
|
const isPairingCodeSession = pairingCodeSessions.has(sessionId);
|
|
928
937
|
const retryAttempts = retryCount.get(sessionId) || 0;
|
|
@@ -942,6 +951,8 @@ const setGroupCacheConfig = (options) => {
|
|
|
942
951
|
exports.setGroupCacheConfig = setGroupCacheConfig;
|
|
943
952
|
// Fungsi baru untuk mendapatkan atau memuat data grup dengan multi-session support
|
|
944
953
|
const getGroupMetadata = (sessionId_1, jid_1, ...args_1) => __awaiter(void 0, [sessionId_1, jid_1, ...args_1], void 0, function* (sessionId, jid, forceFetch = false) {
|
|
954
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
955
|
+
jid = (0, security_1.assertValidJidIdentifier)(jid, "jid");
|
|
945
956
|
// Get the session socket
|
|
946
957
|
const sock = (0, exports.getSession)(sessionId);
|
|
947
958
|
if (!sock) {
|
|
@@ -971,11 +982,14 @@ const getGroupMetadata = (sessionId_1, jid_1, ...args_1) => __awaiter(void 0, [s
|
|
|
971
982
|
exports.getGroupMetadata = getGroupMetadata;
|
|
972
983
|
// Fungsi baru untuk menghapus cache grup tertentu
|
|
973
984
|
const clearGroupMetadataCache = (sessionId, jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
985
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
986
|
+
jid = (0, security_1.assertValidJidIdentifier)(jid, "jid");
|
|
974
987
|
yield Utils_1.groupCache.delete(sessionId, jid);
|
|
975
988
|
});
|
|
976
989
|
exports.clearGroupMetadataCache = clearGroupMetadataCache;
|
|
977
990
|
// Fungsi untuk membersihkan seluruh cache grup untuk session tertentu
|
|
978
991
|
const clearSessionGroupMetadataCache = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
992
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
979
993
|
yield Utils_1.groupCache.clearSessionCache(sessionId);
|
|
980
994
|
});
|
|
981
995
|
exports.clearSessionGroupMetadataCache = clearSessionGroupMetadataCache;
|
|
@@ -1009,6 +1023,8 @@ exports.clearAllGroupMetadataCache = clearAllGroupMetadataCache;
|
|
|
1009
1023
|
*/
|
|
1010
1024
|
const getPNForLID = (sessionId, lid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1011
1025
|
var _a, _b;
|
|
1026
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
1027
|
+
lid = (0, security_1.assertValidJidIdentifier)(lid, "lid");
|
|
1012
1028
|
const session = (0, exports.getSession)(sessionId);
|
|
1013
1029
|
if (!session) {
|
|
1014
1030
|
return {
|
|
@@ -1077,6 +1093,7 @@ exports.getPNForLID = getPNForLID;
|
|
|
1077
1093
|
*/
|
|
1078
1094
|
const getLIDForPN = (sessionId, pn) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1079
1095
|
var _a, _b;
|
|
1096
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
1080
1097
|
const session = (0, exports.getSession)(sessionId);
|
|
1081
1098
|
if (!session) {
|
|
1082
1099
|
return {
|
|
@@ -1143,6 +1160,7 @@ exports.getLIDForPN = getLIDForPN;
|
|
|
1143
1160
|
* @note This may return an empty array if no mappings are available yet.
|
|
1144
1161
|
*/
|
|
1145
1162
|
const getAllLIDMappings = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1163
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
1146
1164
|
const session = (0, exports.getSession)(sessionId);
|
|
1147
1165
|
if (!session) {
|
|
1148
1166
|
throw new Error_1.WhatsappError(Defaults_1.Messages.sessionNotFound(sessionId));
|
|
@@ -1237,6 +1255,7 @@ exports.isPNFormat = isPNFormat;
|
|
|
1237
1255
|
* ```
|
|
1238
1256
|
*/
|
|
1239
1257
|
const toPhoneNumber = (sessionId, jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1258
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
1240
1259
|
// Handle null/undefined input
|
|
1241
1260
|
if (!jid) {
|
|
1242
1261
|
return null;
|
|
@@ -1288,6 +1307,7 @@ exports.toPhoneNumber = toPhoneNumber;
|
|
|
1288
1307
|
* ```
|
|
1289
1308
|
*/
|
|
1290
1309
|
const toLID = (sessionId, jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1310
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
1291
1311
|
// If already in LID format, return as-is
|
|
1292
1312
|
if ((0, exports.isLIDFormat)(jid)) {
|
|
1293
1313
|
return jid;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group-cache.d.ts","sourceRoot":"","sources":["../../../src/Utils/group-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"group-cache.d.ts","sourceRoot":"","sources":["../../../src/Utils/group-cache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAMxC,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAqB;IAC5C,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAuB;IAGvC,OAAO;WAUO,WAAW,IAAI,kBAAkB;IAQlC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBpD,OAAO,CAAC,cAAc;IAKT,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAsCtE,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B/E,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBzD,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBzD,SAAS,CAAC,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE;IAU5D,KAAK,IAAI,IAAI;CAGrB;AAGD,eAAO,MAAM,UAAU,oBAAmC,CAAC"}
|
|
@@ -16,6 +16,7 @@ exports.groupCache = exports.GroupMetadataCache = void 0;
|
|
|
16
16
|
const node_cache_1 = __importDefault(require("node-cache"));
|
|
17
17
|
const mongodb_1 = require("mongodb");
|
|
18
18
|
const Defaults_1 = require("../Defaults");
|
|
19
|
+
const security_1 = require("./security");
|
|
19
20
|
// Class untuk mengelola cache group metadata dengan pendekatan hybrid (NodeCache + MongoDB)
|
|
20
21
|
class GroupMetadataCache {
|
|
21
22
|
// Konstruktor private untuk singleton pattern
|
|
@@ -64,8 +65,10 @@ class GroupMetadataCache {
|
|
|
64
65
|
// Mendapatkan metadata grup dari cache atau MongoDB
|
|
65
66
|
get(sessionId, groupId) {
|
|
66
67
|
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
const safeSessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
69
|
+
const safeGroupId = (0, security_1.assertValidJidIdentifier)(groupId, "groupId");
|
|
67
70
|
// Buat kunci cache dengan kombinasi sessionId dan groupId
|
|
68
|
-
const cacheKey = this.createCacheKey(
|
|
71
|
+
const cacheKey = this.createCacheKey(safeSessionId, safeGroupId);
|
|
69
72
|
// Coba ambil dari cache memory dulu
|
|
70
73
|
const cachedData = this.cache.get(cacheKey);
|
|
71
74
|
if (cachedData) {
|
|
@@ -75,8 +78,8 @@ class GroupMetadataCache {
|
|
|
75
78
|
if (this.mongoCollection) {
|
|
76
79
|
try {
|
|
77
80
|
const data = yield this.mongoCollection.findOne({
|
|
78
|
-
id:
|
|
79
|
-
sessionId:
|
|
81
|
+
id: safeGroupId,
|
|
82
|
+
sessionId: safeSessionId
|
|
80
83
|
});
|
|
81
84
|
if (data) {
|
|
82
85
|
// Hapus _id dari MongoDB yang tidak diperlukan
|
|
@@ -97,18 +100,20 @@ class GroupMetadataCache {
|
|
|
97
100
|
// Menyimpan metadata grup ke cache dan MongoDB
|
|
98
101
|
set(sessionId, groupId, metadata) {
|
|
99
102
|
return __awaiter(this, void 0, void 0, function* () {
|
|
103
|
+
const safeSessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
104
|
+
const safeGroupId = (0, security_1.assertValidJidIdentifier)(groupId, "groupId");
|
|
100
105
|
// Buat kunci cache dengan kombinasi sessionId dan groupId
|
|
101
|
-
const cacheKey = this.createCacheKey(
|
|
106
|
+
const cacheKey = this.createCacheKey(safeSessionId, safeGroupId);
|
|
102
107
|
// Simpan ke cache memory
|
|
103
108
|
this.cache.set(cacheKey, metadata);
|
|
104
109
|
// Jika MongoDB tersedia, simpan juga ke MongoDB
|
|
105
110
|
if (this.mongoCollection) {
|
|
106
111
|
try {
|
|
107
112
|
// Tambahkan sessionId ke data yang disimpan
|
|
108
|
-
const dataToStore = Object.assign(Object.assign({}, metadata), { sessionId });
|
|
113
|
+
const dataToStore = Object.assign(Object.assign({}, metadata), { sessionId: safeSessionId });
|
|
109
114
|
yield this.mongoCollection.updateOne({
|
|
110
|
-
id:
|
|
111
|
-
sessionId:
|
|
115
|
+
id: safeGroupId,
|
|
116
|
+
sessionId: safeSessionId
|
|
112
117
|
}, { $set: dataToStore }, { upsert: true });
|
|
113
118
|
}
|
|
114
119
|
catch (error) {
|
|
@@ -120,16 +125,18 @@ class GroupMetadataCache {
|
|
|
120
125
|
// Menghapus metadata grup dari cache dan MongoDB
|
|
121
126
|
delete(sessionId, groupId) {
|
|
122
127
|
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
+
const safeSessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
129
|
+
const safeGroupId = (0, security_1.assertValidJidIdentifier)(groupId, "groupId");
|
|
123
130
|
// Buat kunci cache dengan kombinasi sessionId dan groupId
|
|
124
|
-
const cacheKey = this.createCacheKey(
|
|
131
|
+
const cacheKey = this.createCacheKey(safeSessionId, safeGroupId);
|
|
125
132
|
// Hapus dari cache memory
|
|
126
133
|
this.cache.del(cacheKey);
|
|
127
134
|
// Jika MongoDB tersedia, hapus juga dari MongoDB
|
|
128
135
|
if (this.mongoCollection) {
|
|
129
136
|
try {
|
|
130
137
|
yield this.mongoCollection.deleteOne({
|
|
131
|
-
id:
|
|
132
|
-
sessionId:
|
|
138
|
+
id: safeGroupId,
|
|
139
|
+
sessionId: safeSessionId
|
|
133
140
|
});
|
|
134
141
|
}
|
|
135
142
|
catch (error) {
|
|
@@ -141,10 +148,11 @@ class GroupMetadataCache {
|
|
|
141
148
|
// Menghapus semua cache untuk session tertentu
|
|
142
149
|
clearSessionCache(sessionId) {
|
|
143
150
|
return __awaiter(this, void 0, void 0, function* () {
|
|
151
|
+
const safeSessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
144
152
|
// Hapus dari MongoDB
|
|
145
153
|
if (this.mongoCollection) {
|
|
146
154
|
try {
|
|
147
|
-
yield this.mongoCollection.deleteMany({ sessionId:
|
|
155
|
+
yield this.mongoCollection.deleteMany({ sessionId: safeSessionId });
|
|
148
156
|
}
|
|
149
157
|
catch (error) {
|
|
150
158
|
console.error(`Error clearing session ${sessionId} cache from MongoDB:`, error);
|
|
@@ -153,7 +161,7 @@ class GroupMetadataCache {
|
|
|
153
161
|
// Hapus dari memory cache
|
|
154
162
|
// Karena NodeCache tidak mendukung wildcard delete, kita harus mendapatkan semua kunci dulu
|
|
155
163
|
const allKeys = this.cache.keys();
|
|
156
|
-
const sessionKeys = allKeys.filter(key => key.startsWith(`${
|
|
164
|
+
const sessionKeys = allKeys.filter(key => key.startsWith(`${safeSessionId}:`));
|
|
157
165
|
sessionKeys.forEach(key => this.cache.del(key));
|
|
158
166
|
});
|
|
159
167
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/Utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
|
package/dist/cjs/Utils/index.js
CHANGED
|
@@ -19,5 +19,6 @@ __exportStar(require("./is-exist"), exports);
|
|
|
19
19
|
__exportStar(require("./create-delay"), exports);
|
|
20
20
|
__exportStar(require("./group-cache"), exports);
|
|
21
21
|
__exportStar(require("./lid-utils"), exports);
|
|
22
|
+
__exportStar(require("./security"), exports);
|
|
22
23
|
// Note: setCredentialsDir & setMongoDBNames have been moved to src/Socket/index.ts
|
|
23
24
|
// Please import them directly from there instead
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongo-auth-state.d.ts","sourceRoot":"","sources":["../../../src/Utils/mongo-auth-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAuB,MAAM,SAAS,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"mongo-auth-state.d.ts","sourceRoot":"","sources":["../../../src/Utils/mongo-auth-state.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAuB,MAAM,SAAS,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAwC1C,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU;;;;kBAkC7D,CAAC,SAAS,MAAM,iBAAiB,QAAQ,CAAC,OAAO,MAAM,EAAE;;;2BAWhD,GAAG;;;;GAqB/B"}
|
|
@@ -13,6 +13,7 @@ exports.useMongoAuthState = useMongoAuthState;
|
|
|
13
13
|
const WAProto_1 = require("baileys/WAProto");
|
|
14
14
|
const crypto_1 = require("baileys/lib/Utils/crypto");
|
|
15
15
|
const generics_1 = require("baileys/lib/Utils/generics");
|
|
16
|
+
const security_1 = require("./security");
|
|
16
17
|
const BufferJSON = {
|
|
17
18
|
replacer: (_, value) => {
|
|
18
19
|
if (Buffer.isBuffer(value) || value instanceof Uint8Array || (value === null || value === void 0 ? void 0 : value.type) === "Buffer") {
|
|
@@ -50,17 +51,18 @@ const initAuthCreds = () => {
|
|
|
50
51
|
};
|
|
51
52
|
function useMongoAuthState(sessionId, collection) {
|
|
52
53
|
return __awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
const safeSessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
53
55
|
const readState = () => __awaiter(this, void 0, void 0, function* () {
|
|
54
|
-
const doc = yield collection.findOne({ sessionId });
|
|
56
|
+
const doc = yield collection.findOne({ sessionId: safeSessionId });
|
|
55
57
|
return (doc === null || doc === void 0 ? void 0 : doc.state)
|
|
56
58
|
? JSON.parse(JSON.stringify(doc.state), BufferJSON.reviver)
|
|
57
59
|
: null;
|
|
58
60
|
});
|
|
59
61
|
const writeState = (state) => __awaiter(this, void 0, void 0, function* () {
|
|
60
|
-
yield collection.updateOne({ sessionId }, { $set: { state: JSON.parse(JSON.stringify(state, BufferJSON.replacer)) } }, { upsert: true });
|
|
62
|
+
yield collection.updateOne({ sessionId: safeSessionId }, { $set: { state: JSON.parse(JSON.stringify(state, BufferJSON.replacer)) } }, { upsert: true });
|
|
61
63
|
});
|
|
62
64
|
const removeKey = (key) => __awaiter(this, void 0, void 0, function* () {
|
|
63
|
-
yield collection.updateOne({ sessionId }, { $unset: { [`state.keys.${key}`]: "" } });
|
|
65
|
+
yield collection.updateOne({ sessionId: safeSessionId }, { $unset: { [`state.keys.${key}`]: "" } });
|
|
64
66
|
});
|
|
65
67
|
const savedState = (yield readState()) || {};
|
|
66
68
|
const creds = savedState.creds || initAuthCreds();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"save-media.d.ts","sourceRoot":"","sources":["../../../src/Utils/save-media.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"save-media.d.ts","sourceRoot":"","sources":["../../../src/Utils/save-media.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAU3C,eAAO,MAAM,gBAAgB,GAAU,KAAK,eAAe,EAAE,MAAM,MAAM,kBAOxE,CAAC;AACF,eAAO,MAAM,gBAAgB,GAAU,KAAK,eAAe,EAAE,MAAM,MAAM,kBAOxE,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC9B,KAAK,eAAe,EACpB,MAAM,MAAM,kBAUb,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAU,KAAK,eAAe,EAAE,MAAM,MAAM,kBAOxE,CAAC"}
|
|
@@ -16,8 +16,10 @@ exports.saveAudioHandler = exports.saveDocumentHandler = exports.saveVideoHandle
|
|
|
16
16
|
const baileys_1 = require("baileys");
|
|
17
17
|
const error_1 = __importDefault(require("./error"));
|
|
18
18
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
19
|
-
const
|
|
20
|
-
|
|
19
|
+
const security_1 = require("./security");
|
|
20
|
+
const saveMedia = (filePath, data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
|
+
const safePath = (0, security_1.assertSafeFilePath)(filePath);
|
|
22
|
+
yield promises_1.default.writeFile(safePath, data.toString("base64"), "base64");
|
|
21
23
|
});
|
|
22
24
|
const saveImageHandler = (msg, path) => __awaiter(void 0, void 0, void 0, function* () {
|
|
23
25
|
var _a;
|
|
@@ -40,8 +42,8 @@ const saveDocumentHandler = (msg, path) => __awaiter(void 0, void 0, void 0, fun
|
|
|
40
42
|
if (!((_a = msg.message) === null || _a === void 0 ? void 0 : _a.documentMessage))
|
|
41
43
|
throw new error_1.default("Message is not contain Document");
|
|
42
44
|
const buf = yield (0, baileys_1.downloadMediaMessage)(msg, "buffer", {});
|
|
43
|
-
const ext = (_b = msg.message.documentMessage.fileName) === null || _b === void 0 ? void 0 : _b.split(".").pop();
|
|
44
|
-
path
|
|
45
|
+
const ext = (0, security_1.sanitizeFileExtension)((_b = msg.message.documentMessage.fileName) === null || _b === void 0 ? void 0 : _b.split(".").pop());
|
|
46
|
+
path = `${(0, security_1.assertSafeFilePath)(path)}.${ext}`;
|
|
45
47
|
return saveMedia(path, buf);
|
|
46
48
|
});
|
|
47
49
|
exports.saveDocumentHandler = saveDocumentHandler;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const assertValidIdentifier: (value: string, fieldName: string) => string;
|
|
2
|
+
export declare const assertValidSessionId: (sessionId: string) => string;
|
|
3
|
+
export declare const assertValidJidIdentifier: (value: string, fieldName: string) => string;
|
|
4
|
+
export declare const assertSafeFilePath: (filePath: string) => string;
|
|
5
|
+
export declare const sanitizeFileExtension: (extension?: string) => string;
|
|
6
|
+
export declare const maskSensitiveValue: (value: string, visibleChars?: number) => string;
|
|
7
|
+
//# sourceMappingURL=security.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../src/Utils/security.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,qBAAqB,GAAI,OAAO,MAAM,EAAE,WAAW,MAAM,KAAG,MAQxE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,KAAG,MACV,CAAC;AAEhD,eAAO,MAAM,wBAAwB,GAAI,OAAO,MAAM,EAAE,WAAW,MAAM,KAAG,MAQ3E,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,KAAG,MAiBrD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,YAAY,MAAM,KAAG,MAK1D,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO,MAAM,EAAE,qBAAgB,KAAG,MAKpE,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.maskSensitiveValue = exports.sanitizeFileExtension = exports.assertSafeFilePath = exports.assertValidJidIdentifier = exports.assertValidSessionId = exports.assertValidIdentifier = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const Error_1 = require("../Error");
|
|
9
|
+
const SAFE_IDENTIFIER_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
|
|
10
|
+
const SAFE_JID_IDENTIFIER_PATTERN = /^[A-Za-z0-9_@.:-]{1,192}$/;
|
|
11
|
+
const assertValidIdentifier = (value, fieldName) => {
|
|
12
|
+
if (typeof value !== "string" || !SAFE_IDENTIFIER_PATTERN.test(value)) {
|
|
13
|
+
throw new Error_1.WhatsappError(`${fieldName} hanya boleh berisi huruf, angka, underscore, atau dash dengan panjang 1-128 karakter`);
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
};
|
|
17
|
+
exports.assertValidIdentifier = assertValidIdentifier;
|
|
18
|
+
const assertValidSessionId = (sessionId) => (0, exports.assertValidIdentifier)(sessionId, "sessionId");
|
|
19
|
+
exports.assertValidSessionId = assertValidSessionId;
|
|
20
|
+
const assertValidJidIdentifier = (value, fieldName) => {
|
|
21
|
+
if (typeof value !== "string" || !SAFE_JID_IDENTIFIER_PATTERN.test(value)) {
|
|
22
|
+
throw new Error_1.WhatsappError(`${fieldName} berisi karakter tidak valid atau melebihi 192 karakter`);
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
};
|
|
26
|
+
exports.assertValidJidIdentifier = assertValidJidIdentifier;
|
|
27
|
+
const assertSafeFilePath = (filePath) => {
|
|
28
|
+
if (typeof filePath !== "string" || filePath.trim().length === 0) {
|
|
29
|
+
throw new Error_1.WhatsappError("File path is required");
|
|
30
|
+
}
|
|
31
|
+
if (filePath.includes("\0")) {
|
|
32
|
+
throw new Error_1.WhatsappError("File path contains invalid characters");
|
|
33
|
+
}
|
|
34
|
+
const normalized = path_1.default.normalize(filePath);
|
|
35
|
+
const baseName = path_1.default.basename(normalized);
|
|
36
|
+
if (!baseName || baseName === "." || baseName === "..") {
|
|
37
|
+
throw new Error_1.WhatsappError("File path must include a valid file name");
|
|
38
|
+
}
|
|
39
|
+
return normalized;
|
|
40
|
+
};
|
|
41
|
+
exports.assertSafeFilePath = assertSafeFilePath;
|
|
42
|
+
const sanitizeFileExtension = (extension) => {
|
|
43
|
+
if (!extension)
|
|
44
|
+
return "bin";
|
|
45
|
+
const cleanExtension = extension.replace(/[^A-Za-z0-9]/g, "").slice(0, 16);
|
|
46
|
+
return cleanExtension || "bin";
|
|
47
|
+
};
|
|
48
|
+
exports.sanitizeFileExtension = sanitizeFileExtension;
|
|
49
|
+
const maskSensitiveValue = (value, visibleChars = 2) => {
|
|
50
|
+
if (!value)
|
|
51
|
+
return "";
|
|
52
|
+
if (value.length <= visibleChars * 2)
|
|
53
|
+
return "*".repeat(value.length);
|
|
54
|
+
return `${value.slice(0, visibleChars)}${"*".repeat(value.length - visibleChars * 2)}${value.slice(-visibleChars)}`;
|
|
55
|
+
};
|
|
56
|
+
exports.maskSensitiveValue = maskSensitiveValue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wa-multi-mongodb",
|
|
3
|
-
"version": "3.11.
|
|
3
|
+
"version": "3.11.2",
|
|
4
4
|
"description": "Multi Session Whatsapp Library with MongoDB Integration",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -21,7 +21,9 @@
|
|
|
21
21
|
"build:esm": "tsc && tsc-esm-fix --source=dist --target=dist",
|
|
22
22
|
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
23
23
|
"start": "npm run build && node ./dist/index.js",
|
|
24
|
-
"test": "
|
|
24
|
+
"test": "npm run build",
|
|
25
|
+
"audit:security": "npm audit --audit-level=high || true",
|
|
26
|
+
"ci": "npm test"
|
|
25
27
|
},
|
|
26
28
|
"author": "wahdalo",
|
|
27
29
|
"license": "ISC",
|
|
@@ -31,15 +33,14 @@
|
|
|
31
33
|
"@types/node-cache": "^4.1.3",
|
|
32
34
|
"@types/qrcode": "^1.5.5",
|
|
33
35
|
"aws4": "^1.13.2",
|
|
34
|
-
"baileys": "^7.0.0-
|
|
36
|
+
"baileys": "^7.0.0-rc13",
|
|
35
37
|
"dotenv": "^16.5.0",
|
|
36
38
|
"link-preview-js": "^3.0.14",
|
|
37
|
-
"mime": "^
|
|
39
|
+
"mime": "^4.1.0",
|
|
38
40
|
"mongodb": "^5.7.0",
|
|
39
41
|
"node-cache": "^5.1.2",
|
|
40
|
-
"pino": "^
|
|
41
|
-
"qrcode": "^1.5.4"
|
|
42
|
-
"qrcode-terminal": "^0.12.0"
|
|
42
|
+
"pino": "^10.3.1",
|
|
43
|
+
"qrcode": "^1.5.4"
|
|
43
44
|
},
|
|
44
45
|
"repository": {
|
|
45
46
|
"type": "git",
|