UNPKG

neroxbailx

Version:

baileys whatsapp-api

123 lines 3.48 kB
"use strict" var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod } } Object.defineProperty(exports, "__esModule", { value: true }) const async_mutex_1 = __importDefault(require("async-mutex")) const promises_1 = require("fs/promises") const path_1 = require("path") const WAProto_1 = require("../../WAProto") const auth_utils_1 = require("./auth-utils") const generics_1 = require("./generics") // We need to lock files due to the fact that we are using async functions to read and write files // https://github.com/WhiskeySockets/Baileys/issues/794 // https://github.com/nodejs/node/issues/26338 // Use a Map to store mutexes for each file path const fileLocks = new Map() // Get or create a mutex for a specific file path const getFileLock = (path) => { let mutex = fileLocks.get(path) if (!mutex) { mutex = new async_mutex_1.Mutex() fileLocks.set(path, mutex) } return mutex } /** * stores the full authentication state in a single folder. * Far more efficient than singlefileauthstate * * Again, I wouldn't endorse this for any production level use other than perhaps a bot. * Would recommend writing an auth state for use with a proper SQL or No-SQL DB * */ const useMultiFileAuthState = async (folder) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const writeData = async (data, file) => { const filePath = path_1.join(folder, fixFileName(file)) const mutex = getFileLock(filePath) return mutex.acquire().then(async (release) => { try { await promises_1.writeFile(filePath, JSON.stringify(data, generics_1.BufferJSON.replacer)) } finally { release() } }) } const readData = async (file) => { try { const filePath = path_1.join(folder, fixFileName(file)) const mutex = getFileLock(filePath) const data = await mutex.acquire().then(async (release) => { try { return await promises_1.readFile(filePath, { encoding: 'utf-8' }) } finally { release() } }) return JSON.parse(data, generics_1.BufferJSON.reviver) } catch (error) { return null } } const removeData = async (file) => { try { const filePath = path_1.join(folder, fixFileName(file)) const mutex = getFileLock(filePath) await mutex.acquire().then(async (release) => { try { await promises_1.unlink(filePath) } finally { release() } }) } catch {} } const folderInfo = await promises_1.stat(folder).catch(() => { }) if (folderInfo) { if (!folderInfo.isDirectory()) { throw new Error(`found something that is not a directory at ${folder}, either delete it or specify a different location`) } } else { await promises_1.mkdir(folder, { recursive: true }) } const fixFileName = (file) => { return file?.replace(/\//g, '__')?.replace(/:/g, '-') } const creds = await readData('creds.json') || auth_utils_1.initAuthCreds() return { state: { creds, keys: { get: async (type, ids) => { const data = {} await Promise.all(ids.map(async (id) => { let value = await readData(`${type}-${id}.json`) if (type === 'app-state-sync-key' && value) { value = WAProto_1.proto.Message.AppStateSyncKeyData.fromObject(value) } 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 file = `${category}-${id}.json` tasks.push(value ? writeData(value, file) : removeData(file)) } } await Promise.all(tasks) } } }, saveCreds: async () => { return writeData(creds, 'creds.json') } } } module.exports = { useMultiFileAuthState }