wa-multi-mongodb 3.10.8 → 3.11.1
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 +5 -0
- package/dist/Socket/index.d.ts.map +1 -1
- package/dist/Socket/index.js +42 -3
- 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 +5 -0
- package/dist/cjs/Socket/index.d.ts.map +1 -1
- package/dist/cjs/Socket/index.js +43 -3
- 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/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/package.json +9 -8
- package/readme.md +1302 -1246
package/dist/cjs/Socket/index.js
CHANGED
|
@@ -45,7 +45,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
45
45
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.toLID = exports.toPhoneNumber = exports.isPNFormat = exports.isLIDFormat = exports.getAllLIDMappings = exports.getLIDForPN = exports.getPNForLID = exports.clearAllGroupMetadataCache = exports.clearSessionGroupMetadataCache = exports.clearGroupMetadataCache = exports.getGroupMetadata = exports.setGroupCacheConfig = exports.getSessionStatus = exports.getPairingCodeSessions = exports.reconnectAllPairingCodeSessions = exports.reconnect = exports.setCredentialsDir = exports.setMongoDBNames = exports.loadSessionsFromMongo = exports.onPairingCode = exports.onMessageUpdate = exports.onConnecting = exports.onDisconnected = exports.onConnected = exports.onQRUpdated = exports.onMessageReceived = exports.loadSessionsFromStorage = exports.getSession = exports.getAllSessionSync = exports.getAllSession = exports.deleteSession = exports.startWhatsapp = exports.startSessionWithPairingCode = exports.startSession = exports.setMongoURI = void 0;
|
|
48
|
+
exports.toLID = exports.toPhoneNumber = exports.isPNFormat = exports.isLIDFormat = exports.getAllLIDMappings = exports.getLIDForPN = exports.getPNForLID = exports.clearAllGroupMetadataCache = exports.clearSessionGroupMetadataCache = exports.clearGroupMetadataCache = exports.getGroupMetadata = exports.setGroupCacheConfig = exports.getSessionStatus = exports.getPairingCodeSessions = exports.reconnectAllPairingCodeSessions = exports.reconnect = exports.setCredentialsDir = exports.setMongoDBNames = exports.loadSessionsFromMongo = exports.onPairingCode = exports.onMessageUpdate = exports.onConnecting = exports.onDisconnected = exports.onConnected = exports.onQRUpdated = exports.onMessageReceived = exports.loadSessionsFromStorage = exports.downloadMediaMessage = exports.getSession = exports.getAllSessionSync = exports.getAllSession = exports.deleteSession = exports.startWhatsapp = exports.startSessionWithPairingCode = exports.startSession = exports.setMongoURI = void 0;
|
|
49
49
|
exports.setMongoCollection = setMongoCollection;
|
|
50
50
|
const baileys_1 = __importStar(require("baileys"));
|
|
51
51
|
const path_1 = __importDefault(require("path"));
|
|
@@ -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,9 +666,30 @@ 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;
|
|
671
|
+
const downloadMediaMessage = (_a) => __awaiter(void 0, [_a], void 0, function* ({ sessionId, message, key, }) {
|
|
672
|
+
const session = (0, exports.getSession)(sessionId);
|
|
673
|
+
if (!session) {
|
|
674
|
+
throw new Error_1.WhatsappError(Defaults_1.Messages.sessionNotFound(sessionId));
|
|
675
|
+
}
|
|
676
|
+
if (!message) {
|
|
677
|
+
throw new Error_1.WhatsappError("Message is required to download media");
|
|
678
|
+
}
|
|
679
|
+
try {
|
|
680
|
+
const buffer = yield (0, baileys_1.downloadMediaMessage)(message, "buffer", {}, {
|
|
681
|
+
logger: P,
|
|
682
|
+
reuploadRequest: session.updateMediaMessage,
|
|
683
|
+
});
|
|
684
|
+
return buffer;
|
|
685
|
+
}
|
|
686
|
+
catch (error) {
|
|
687
|
+
throw new Error_1.WhatsappError(`Failed to download media: ${error.message || String(error)}`);
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
exports.downloadMediaMessage = downloadMediaMessage;
|
|
666
691
|
const isSessionExistAndRunning = (sessionId) => {
|
|
692
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
667
693
|
// Cek jika session sudah berjalan di memory
|
|
668
694
|
if ((0, exports.getSession)(sessionId)) {
|
|
669
695
|
return true;
|
|
@@ -676,6 +702,7 @@ const isSessionExistAndRunning = (sessionId) => {
|
|
|
676
702
|
* @returns Boolean indicating if session should be loaded
|
|
677
703
|
*/
|
|
678
704
|
const shouldLoadSession = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
705
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
679
706
|
// Jika session sudah berjalan di memory, tidak perlu load lagi
|
|
680
707
|
if ((0, exports.getSession)(sessionId)) {
|
|
681
708
|
return false;
|
|
@@ -784,6 +811,7 @@ exports.setCredentialsDir = setCredentialsDir;
|
|
|
784
811
|
*/
|
|
785
812
|
const reconnect = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
786
813
|
try {
|
|
814
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
787
815
|
// Cek jika session masih ada di memory
|
|
788
816
|
const existingSession = sessions.get(sessionId);
|
|
789
817
|
// Hapus session terlebih dahulu untuk menghindari konflik
|
|
@@ -903,6 +931,7 @@ exports.getPairingCodeSessions = getPairingCodeSessions;
|
|
|
903
931
|
* @returns Object with session status information
|
|
904
932
|
*/
|
|
905
933
|
const getSessionStatus = (sessionId) => {
|
|
934
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
906
935
|
const isRunning = !!(0, exports.getSession)(sessionId);
|
|
907
936
|
const isPairingCodeSession = pairingCodeSessions.has(sessionId);
|
|
908
937
|
const retryAttempts = retryCount.get(sessionId) || 0;
|
|
@@ -922,6 +951,8 @@ const setGroupCacheConfig = (options) => {
|
|
|
922
951
|
exports.setGroupCacheConfig = setGroupCacheConfig;
|
|
923
952
|
// Fungsi baru untuk mendapatkan atau memuat data grup dengan multi-session support
|
|
924
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");
|
|
925
956
|
// Get the session socket
|
|
926
957
|
const sock = (0, exports.getSession)(sessionId);
|
|
927
958
|
if (!sock) {
|
|
@@ -951,11 +982,14 @@ const getGroupMetadata = (sessionId_1, jid_1, ...args_1) => __awaiter(void 0, [s
|
|
|
951
982
|
exports.getGroupMetadata = getGroupMetadata;
|
|
952
983
|
// Fungsi baru untuk menghapus cache grup tertentu
|
|
953
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");
|
|
954
987
|
yield Utils_1.groupCache.delete(sessionId, jid);
|
|
955
988
|
});
|
|
956
989
|
exports.clearGroupMetadataCache = clearGroupMetadataCache;
|
|
957
990
|
// Fungsi untuk membersihkan seluruh cache grup untuk session tertentu
|
|
958
991
|
const clearSessionGroupMetadataCache = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
992
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
959
993
|
yield Utils_1.groupCache.clearSessionCache(sessionId);
|
|
960
994
|
});
|
|
961
995
|
exports.clearSessionGroupMetadataCache = clearSessionGroupMetadataCache;
|
|
@@ -989,6 +1023,8 @@ exports.clearAllGroupMetadataCache = clearAllGroupMetadataCache;
|
|
|
989
1023
|
*/
|
|
990
1024
|
const getPNForLID = (sessionId, lid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
991
1025
|
var _a, _b;
|
|
1026
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
1027
|
+
lid = (0, security_1.assertValidJidIdentifier)(lid, "lid");
|
|
992
1028
|
const session = (0, exports.getSession)(sessionId);
|
|
993
1029
|
if (!session) {
|
|
994
1030
|
return {
|
|
@@ -1057,6 +1093,7 @@ exports.getPNForLID = getPNForLID;
|
|
|
1057
1093
|
*/
|
|
1058
1094
|
const getLIDForPN = (sessionId, pn) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1059
1095
|
var _a, _b;
|
|
1096
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
1060
1097
|
const session = (0, exports.getSession)(sessionId);
|
|
1061
1098
|
if (!session) {
|
|
1062
1099
|
return {
|
|
@@ -1123,6 +1160,7 @@ exports.getLIDForPN = getLIDForPN;
|
|
|
1123
1160
|
* @note This may return an empty array if no mappings are available yet.
|
|
1124
1161
|
*/
|
|
1125
1162
|
const getAllLIDMappings = (sessionId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1163
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
1126
1164
|
const session = (0, exports.getSession)(sessionId);
|
|
1127
1165
|
if (!session) {
|
|
1128
1166
|
throw new Error_1.WhatsappError(Defaults_1.Messages.sessionNotFound(sessionId));
|
|
@@ -1217,6 +1255,7 @@ exports.isPNFormat = isPNFormat;
|
|
|
1217
1255
|
* ```
|
|
1218
1256
|
*/
|
|
1219
1257
|
const toPhoneNumber = (sessionId, jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1258
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
1220
1259
|
// Handle null/undefined input
|
|
1221
1260
|
if (!jid) {
|
|
1222
1261
|
return null;
|
|
@@ -1268,6 +1307,7 @@ exports.toPhoneNumber = toPhoneNumber;
|
|
|
1268
1307
|
* ```
|
|
1269
1308
|
*/
|
|
1270
1309
|
const toLID = (sessionId, jid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1310
|
+
sessionId = (0, security_1.assertValidSessionId)(sessionId);
|
|
1271
1311
|
// If already in LID format, return as-is
|
|
1272
1312
|
if ((0, exports.isLIDFormat)(jid)) {
|
|
1273
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/dist/cjs/index.d.ts
CHANGED
package/dist/cjs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAE3B,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC"}
|
package/dist/cjs/index.js
CHANGED
|
@@ -43,4 +43,5 @@ __exportStar(require("./Utils"), exports);
|
|
|
43
43
|
__exportStar(require("./Types"), exports);
|
|
44
44
|
__exportStar(require("./Profile"), exports);
|
|
45
45
|
__exportStar(require("./Error"), exports);
|
|
46
|
+
__exportStar(require("./Defaults"), exports);
|
|
46
47
|
exports.baileys = __importStar(require("baileys"));
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAE3B,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wa-multi-mongodb",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.11.1",
|
|
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-rc11",
|
|
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",
|
|
@@ -54,4 +55,4 @@
|
|
|
54
55
|
"tslib": "^2.8.1",
|
|
55
56
|
"typescript": "^5.7.2"
|
|
56
57
|
}
|
|
57
|
-
}
|
|
58
|
+
}
|