Move in progress apps temporarily

This commit is contained in:
Darren Clarke 2023-03-07 14:09:49 +00:00
parent ba04aa108c
commit 6eaaf8e9be
360 changed files with 6171 additions and 55 deletions

View file

@ -1,198 +0,0 @@
import { Boom } from "@hapi/boom";
import { Server } from "@hapi/hapi";
import { randomBytes } from "crypto";
import type { Logger } from "pino";
import {
proto,
BufferJSON,
generateRegistrationId,
Curve,
signedKeyPair,
AuthenticationCreds,
AuthenticationState,
AccountSettings,
SignalDataSet,
SignalDataTypeMap,
SignalKeyStore,
SignalKeyStoreWithTransaction,
} from "@adiwajshing/baileys";
import { SavedWhatsappBot as Bot } from "db";
const KEY_MAP: { [T in keyof SignalDataTypeMap]: string } = {
"pre-key": "preKeys",
session: "sessions",
"sender-key": "senderKeys",
"app-state-sync-key": "appStateSyncKeys",
"app-state-sync-version": "appStateVersions",
"sender-key-memory": "senderKeyMemory",
};
export const addTransactionCapability = (
state: SignalKeyStore,
logger: Logger
): SignalKeyStoreWithTransaction => {
let inTransaction = false;
let transactionCache: SignalDataSet = {};
let mutations: SignalDataSet = {};
const prefetch = async (type: keyof SignalDataTypeMap, ids: string[]) => {
if (!inTransaction) {
throw new Boom("Cannot prefetch without transaction");
}
const dict = transactionCache[type];
const idsRequiringFetch = dict
? ids.filter((item) => !(item in dict))
: ids;
// only fetch if there are any items to fetch
if (idsRequiringFetch.length) {
const result = await state.get(type, idsRequiringFetch);
transactionCache[type] = transactionCache[type] || {};
// @ts-expect-error
Object.assign(transactionCache[type], result);
}
};
return {
get: async (type, ids) => {
if (inTransaction) {
await prefetch(type, ids);
return ids.reduce((dict, id) => {
const value = transactionCache[type]?.[id];
if (value) {
// @ts-expect-error
dict[id] = value;
}
return dict;
}, {});
} else {
return state.get(type, ids);
}
},
set: (data) => {
if (inTransaction) {
logger.trace({ types: Object.keys(data) }, "caching in transaction");
for (const key in data) {
// @ts-expect-error
transactionCache[key] = transactionCache[key] || {};
// @ts-expect-error
Object.assign(transactionCache[key], data[key]);
// @ts-expect-error
mutations[key] = mutations[key] || {};
// @ts-expect-error
Object.assign(mutations[key], data[key]);
}
} else {
return state.set(data);
}
},
isInTransaction: () => inTransaction,
// @ts-expect-error
prefetch: (type, ids) => {
logger.trace({ type, ids }, "prefetching");
return prefetch(type, ids);
},
transaction: async (work) => {
if (inTransaction) {
await work();
} else {
logger.debug("entering transaction");
inTransaction = true;
try {
await work();
if (Object.keys(mutations).length) {
logger.debug("committing transaction");
await state.set(mutations);
} else {
logger.debug("no mutations in transaction");
}
} finally {
inTransaction = false;
transactionCache = {};
mutations = {};
}
}
},
};
};
export const initAuthCreds = (): AuthenticationCreds => {
const identityKey = Curve.generateKeyPair();
return {
noiseKey: Curve.generateKeyPair(),
signedIdentityKey: identityKey,
signedPreKey: signedKeyPair(identityKey, 1),
registrationId: generateRegistrationId(),
advSecretKey: randomBytes(32).toString("base64"),
nextPreKeyId: 1,
firstUnuploadedPreKeyId: 1,
processedHistoryMessages: [],
accountSettings: {
unarchiveChats: false,
},
} as any;
};
export const useDatabaseAuthState = (
bot: Bot,
server: Server
): { state: AuthenticationState; saveState: () => void } => {
let { logger }: any = server;
let creds: AuthenticationCreds;
let keys: any = {};
const saveState = async () => {
logger && logger.trace("saving auth state");
const authInfo = JSON.stringify({ creds, keys }, BufferJSON.replacer, 2);
await server.db().whatsappBots.updateAuthInfo(bot, authInfo);
};
if (bot.authInfo) {
console.log("Auth info exists");
const result = JSON.parse(bot.authInfo, BufferJSON.reviver);
creds = result.creds;
keys = result.keys;
} else {
console.log("Auth info does not exist");
creds = initAuthCreds();
keys = {};
}
return {
state: {
creds,
keys: {
get: (type, ids) => {
const key = KEY_MAP[type];
return ids.reduce((dict, id) => {
let value = keys[key]?.[id];
if (value) {
if (type === "app-state-sync-key") {
// @ts-expect-error
value = proto.AppStateSyncKeyData.fromObject(value);
}
// @ts-expect-error
dict[id] = value;
}
return dict;
}, {});
},
set: (data) => {
for (const _key in data) {
const key = KEY_MAP[_key as keyof SignalDataTypeMap];
keys[key] = keys[key] || {};
// @ts-expect-error
Object.assign(keys[key], data[_key]);
}
saveState();
},
},
},
saveState,
};
};