UNPKG

@baileys-md/baileys

Version:

Baileys WhatsApp API

112 lines (108 loc) 3.19 kB
//========================================// import { mkdir, readFile, stat, unlink, writeFile } from "fs/promises"; import { initAuthCreds } from "./auth-utils.js"; import { proto } from "../../WAProto/index.js"; import { BufferJSON } from "./generics.js"; import { Mutex } from "async-mutex"; import { join } from "path"; const fileLocks = new Map(); const getFileLock = (path) => { let mutex = fileLocks.get(path); if (!mutex) { mutex = new Mutex(); fileLocks.set(path, mutex); } return mutex; }; export const useMultiFileAuthState = async (folder) => { const writeData = async (data, file) => { const filePath = join(folder, fixFileName(file)); const mutex = getFileLock(filePath); return mutex.acquire().then(async (release) => { try { await writeFile(filePath, JSON.stringify(data, BufferJSON.replacer)); } finally { release(); } }); }; const readData = async (file) => { try { const filePath = join(folder, fixFileName(file)); const mutex = getFileLock(filePath); return await mutex.acquire().then(async (release) => { try { const data = await readFile(filePath, { encoding: "utf-8" }); return JSON.parse(data, BufferJSON.reviver); } finally { release(); } }); } catch (error) { return null; } }; const removeData = async (file) => { try { const filePath = join(folder, fixFileName(file)); const mutex = getFileLock(filePath); return mutex.acquire().then(async (release) => { try { await unlink(filePath); } catch { } finally { release(); } }); } catch { } }; const folderInfo = await 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 mkdir(folder, { recursive: true }); } const fixFileName = (file) => file?.replace(/\//g, "__")?.replace(/:/g, "-"); const creds = (await readData("creds.json")) || 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 = 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 await writeData(creds, "creds.json"); } }; };