Add missing Metamigo changes
This commit is contained in:
parent
27810142b3
commit
161f3fcee2
6 changed files with 12 additions and 200 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -8,4 +8,5 @@ docker/zammad/auto_install/**
|
|||
.npmrc
|
||||
coverage/
|
||||
build/
|
||||
junit.xml
|
||||
junit.xml
|
||||
.next
|
||||
|
|
|
|||
|
|
@ -1,191 +0,0 @@
|
|||
import { Boom } from "@hapi/boom";
|
||||
import { Server } from "@hapi/hapi";
|
||||
import { randomBytes } from "node: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 "@digiresilience/metamigo-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 > 0) {
|
||||
const result = await state.get(type, idsRequiringFetch);
|
||||
|
||||
transactionCache[type] = transactionCache[type] || {};
|
||||
Object.assign(transactionCache[type], result);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
async get(type, ids) {
|
||||
if (inTransaction) {
|
||||
await prefetch(type, ids);
|
||||
return ids.reduce((dict, id) => {
|
||||
const value = transactionCache[type]?.[id];
|
||||
if (value) {
|
||||
dict[id] = value;
|
||||
}
|
||||
|
||||
return dict;
|
||||
}, {});
|
||||
}
|
||||
|
||||
return state.get(type, ids);
|
||||
},
|
||||
set(data) {
|
||||
if (inTransaction) {
|
||||
logger.trace({ types: Object.keys(data) }, "caching in transaction");
|
||||
for (const key in data) {
|
||||
transactionCache[key] = transactionCache[key] || {};
|
||||
Object.assign(transactionCache[key], data[key]);
|
||||
mutations[key] = mutations[key] || {};
|
||||
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);
|
||||
},
|
||||
async transaction(work) {
|
||||
if (inTransaction) {
|
||||
await work();
|
||||
} else {
|
||||
logger.debug("entering transaction");
|
||||
inTransaction = true;
|
||||
try {
|
||||
await work();
|
||||
if (Object.keys(mutations).length > 0) {
|
||||
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 } => {
|
||||
const { 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);
|
||||
}
|
||||
|
||||
dict[id] = value;
|
||||
}
|
||||
|
||||
return dict;
|
||||
}, {});
|
||||
},
|
||||
set(data) {
|
||||
for (const _key in data) {
|
||||
const key = KEY_MAP[_key as keyof SignalDataTypeMap];
|
||||
keys[key] = keys[key] || {};
|
||||
Object.assign(keys[key], data[_key]);
|
||||
}
|
||||
|
||||
saveState();
|
||||
},
|
||||
},
|
||||
},
|
||||
saveState,
|
||||
};
|
||||
};
|
||||
|
|
@ -146,7 +146,7 @@ export const UnverifyBotRoute = Helpers.withDefaults({
|
|||
path: "/api/whatsapp/bots/{id}/unverify",
|
||||
options: {
|
||||
description: "Unverify bot",
|
||||
async handler: (request: Hapi.Request, _h: Hapi.ResponseToolkit) {
|
||||
async handler(request: Hapi.Request, _h: Hapi.ResponseToolkit) {
|
||||
const { id } = request.params;
|
||||
const { whatsappService } = request.services();
|
||||
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ const Sidebar = ({ record }) => {
|
|||
</IconButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
{receivedMessages.map((receivedMessage) => (
|
||||
<Grid item container direction="column" spacing={1}>
|
||||
{receivedMessages.map((receivedMessage, index) => (
|
||||
<Grid key={index} item container direction="column" spacing={1}>
|
||||
<Grid item style={{ fontWeight: "bold", color: "#999" }}>
|
||||
{receivedMessage.key.remoteJid.replace("@s.whatsapp.net", "")}
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@
|
|||
"author": "Abel Luck <abel@guardianproject.info>",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@digiresilience/montar": "*"
|
||||
"@digiresilience/montar": "*",
|
||||
"@digiresilience/metamigo-common": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.20.12",
|
||||
|
|
|
|||
|
|
@ -41,13 +41,14 @@ export class WhatsappBotRecordRepository extends RepositoryBase(
|
|||
);
|
||||
}
|
||||
|
||||
async updateAuthInfo(
|
||||
async updateVerified(
|
||||
bot: SavedWhatsappBot,
|
||||
authInfo: string | undefined
|
||||
verified: boolean
|
||||
): Promise<SavedWhatsappBot> {
|
||||
return this.db.one(
|
||||
"UPDATE $1 SET (auth_info, is_verified) = ROW($2, true) WHERE id = $3 RETURNING *",
|
||||
[this.schemaTable, authInfo, bot.id]
|
||||
"UPDATE $1 SET (is_verified) = ROW($2) WHERE id = $3 RETURNING *",
|
||||
[this.schemaTable, verified, bot.id]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue