multi-mongo
Version:
MongoDB-based auth store for Baileys with single-collection multi-session in one collection support.
149 lines (138 loc) • 6.06 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.useMongoDBAuthState = useMongoDBAuthState;
const { Binary } = require("mongodb");
const { proto } = require("@whiskeysockets/baileys/WAProto");
const { Curve, signedKeyPair } = require("@whiskeysockets/baileys/lib/Utils/crypto");
const { generateRegistrationId } = require("@whiskeysockets/baileys/lib/Utils/generics");
const { randomBytes } = require("crypto");
const { v4: uuidv4 } = require("uuid");
const initAuthCreds = () => {
const identityKey = Curve.generateKeyPair();
return {
noiseKey: Curve.generateKeyPair(),
signedIdentityKey: identityKey,
signedPreKey: signedKeyPair(identityKey, 1),
registrationId: generateRegistrationId(),
advSecretKey: randomBytes(32).toString('base64'),
processedHistoryMessages: [],
nextPreKeyId: 1,
firstUnuploadedPreKeyId: 1,
accountSyncCounter: 0,
accountSettings: {
unarchiveChats: false
},
deviceId: randomBytes(16).toString('base64'),
phoneId: uuidv4(),
identityId: randomBytes(20),
registered: false,
backupToken: randomBytes(20),
registration: {},
pairingEphemeralKeyPair: Curve.generateKeyPair(),
pairingCode: undefined,
lastPropHash: undefined,
routingInfo: undefined,
};
};
/**
* Multi-device Baileys Auth State using MongoDB
* @param {Collection} collection - MongoDB collection
* @param {string} deviceId - Unique ID for this device/session
*/
function useMongoDBAuthState(collection, deviceId) {
return __awaiter(this, void 0, void 0, function* () {
const namespacedId = (id) => `${deviceId}-${id}`;
const convertBinaryToBuffer = (obj) => {
if (obj instanceof Binary) {
return obj.buffer;
}
if (Array.isArray(obj)) {
return obj.map(convertBinaryToBuffer);
}
if (typeof obj === 'object' && obj !== null) {
const newObj = {};
for (const key in obj) {
newObj[key] = convertBinaryToBuffer(obj[key]);
}
return newObj;
}
return obj;
};
const writeData = (data, id) => __awaiter(this, void 0, void 0, function* () {
try {
yield collection.updateOne(
{ _id: id },
{ $set: Object.assign({}, data, { deviceId }) },
{ upsert: true }
);
} catch (error) {
console.error("Error writing data:", error);
}
});
const readData = (id) => __awaiter(this, void 0, void 0, function* () {
try {
const data = yield collection.findOne({ _id: id });
return data ? convertBinaryToBuffer(data) : null;
} catch (error) {
console.error("Error reading data:", error);
return null;
}
});
const removeData = (id) => __awaiter(this, void 0, void 0, function* () {
try {
yield collection.deleteOne({ _id: id });
} catch (error) {
console.error("Error removing data:", error);
}
});
// Load or initialize credentials
let creds;
const existingData = yield readData(namespacedId("auth_creds"));
creds = existingData ? existingData.creds : initAuthCreds();
const state = {
creds,
keys: {
get: (type, ids) => __awaiter(this, void 0, void 0, function* () {
const data = {};
yield Promise.all(ids.map((id) => __awaiter(this, void 0, void 0, function* () {
let value = yield readData(namespacedId(`${type}-${id}`));
if (type === "app-state-sync-key" && value) {
value = proto.Message.AppStateSyncKeyData.fromObject(value);
}
data[id] = value;
})));
return data;
}),
set: (data) => __awaiter(this, void 0, void 0, function* () {
const tasks = [];
for (const category in data) {
const categoryData = data[category];
if (categoryData) {
for (const id in categoryData) {
const value = categoryData[id];
const key = namespacedId(`${category}-${id}`);
tasks.push(value ? writeData(value, key) : removeData(key));
}
}
}
yield Promise.all(tasks);
}),
},
};
return {
state,
saveCreds: () => __awaiter(this, void 0, void 0, function* () {
yield writeData({ creds: state.creds }, namespacedId("auth_creds"));
}),
};
});
}