redis-auth-baileys
Version:
A Redis-based authentication state management system for Baileys, similar to Baileys' useMultiFileAuth, providing scalable and production-ready session storage for WhatsApp bots.
116 lines (102 loc) • 3.09 kB
JavaScript
const { Mutex } = require('async-mutex');
const { createClient } = require('redis');
const { initAuthCreds } = require('baileys/lib/Utils/auth-utils');
const { BufferJSON } = require('baileys/lib/Utils/generics');
/**
* Stores the full authentication state in Redis.
* This is more suitable for production-level use compared to file storage.
*/
const useRedisAuthState = async (redisConfig, redisPrefix) => {
// const client = createClient(redisConfig);
const redisURI = `redis://:${redisConfig.password}@${redisConfig.host}:${redisConfig.port}`;
const client = createClient({
url: redisURI
});
client.on('error', (err) => {
console.error('Redis error:', err);
});
await client.connect();
// We need to lock data due to the fact that we are using async functions to access Redis
const fileLocks = new Map();
// Get or create a mutex for a specific Redis key
const getRedisLock = (key) => {
let mutex = fileLocks.get(key);
if (!mutex) {
mutex = new Mutex();
fileLocks.set(key, mutex);
}
return mutex;
};
// Menambahkan prefix pada kunci
const prefixKey = (key) => `${redisPrefix}:${key}`;
const readData = async (key) => {
try {
const mutex = getRedisLock(key);
return await mutex.acquire().then(async (release) => {
try {
const data = await client.get(prefixKey(key)); // Menambahkan prefix pada kunci
return data ? JSON.parse(data, BufferJSON.reviver) : null;
} finally {
release();
}
});
} catch (error) {
return null;
}
};
const writeData = async (data, key) => {
const mutex = getRedisLock(key);
return mutex.acquire().then(async (release) => {
try {
await client.set(prefixKey(key), JSON.stringify(data, BufferJSON.replacer)); // Menambahkan prefix pada kunci
} finally {
release();
}
});
};
const removeData = async (key) => {
const mutex = getRedisLock(key);
return mutex.acquire().then(async (release) => {
try {
await client.del(prefixKey(key)); // Menambahkan prefix pada kunci
} finally {
release();
}
});
};
const creds = await readData('creds') || initAuthCreds();
const state = {
creds,
keys: {
get: async (type, ids) => {
const data = {};
await Promise.all(
ids.map(async (id) => {
const value = await readData(`${type}-${id}`);
data[id] = value;
})
);
return data;
},
set: async (data) => {
const tasks = [];
for (const category in data) {
for (const id in data[category]) {
const value = data[category][id];
const key = `${category}-${id}`;
tasks.push(value ? writeData(value, key) : removeData(key));
}
}
await Promise.all(tasks);
}
}
};
const saveCreds = async () => {
await writeData(creds, 'creds');
};
return {
state,
saveCreds
};
};
module.exports = { useRedisAuthState };