@baileys-md/baileys
Version:
Baileys WhatsApp API
112 lines (108 loc) • 3.19 kB
JavaScript
//========================================//
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");
}
};
};