Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ WORKDIR /app
COPY package*.json ./

# Install production dependencies only
RUN npm ci --omit=dev && npm cache clean --force
COPY scripts/patch-wwebjs-lid-last-received-key.js ./scripts/patch-wwebjs-lid-last-received-key.js
RUN npm ci --omit=dev && node scripts/patch-wwebjs-lid-last-received-key.js && npm cache clean --force

# amd64: download Chrome for Testing via Puppeteer and symlink it.
# arm64: use Debian's chromium installed above (CfT has no linux-arm64 build).
Expand All @@ -114,7 +115,7 @@ COPY --from=builder /app/dashboard/dist ./dashboard/dist

# Create data directories with correct ownership
RUN mkdir -p ./data/sessions ./data/media && \
chown -R openwa:openwa /app
chown -R openwa:openwa ./data

# The non-root openwa user has no home of its own (`useradd -r`, no -m). Chromium resolves the home
# dir from the passwd entry via glib's getpwuid() — it IGNORES $HOME — so it tries to read/write
Expand Down
57 changes: 57 additions & 0 deletions scripts/patch-wwebjs-lid-last-received-key.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const fs = require('fs');
const path = require('path');

const DEFAULT_TARGET = path.join(
__dirname,
'..',
'node_modules',
'whatsapp-web.js',
'src',
'util',
'Injected',
'Utils.js',
);

const OLD_BLOCK = ` const lastMessage = chat.lastReceivedKey
? window
.require('WAWebCollections')
.Msg.get(chat.lastReceivedKey._serialized) ||
(
await window
.require('WAWebCollections')
.Msg.getMessagesById([
chat.lastReceivedKey._serialized,
])
)?.messages?.[0]
: null;`;

const NEW_BLOCK = ` const lastReceivedKey = chat.lastReceivedKey?._serialized || chat.lastReceivedKey?.toString?.();
const lastMessage = lastReceivedKey
? window
.require('WAWebCollections')
.Msg.get(lastReceivedKey) ||
(
await window
.require('WAWebCollections')
.Msg.getMessagesById([
lastReceivedKey,
])
)?.messages?.[0]
: null;`;

function applyPatch(target = DEFAULT_TARGET) {
const source = fs.readFileSync(target, 'utf8');
if (source.includes(NEW_BLOCK)) return 'already-patched';
if (!source.includes(OLD_BLOCK)) {
throw new Error(`Unsupported whatsapp-web.js Utils.js shape: ${target}`);
}
fs.writeFileSync(target, source.replace(OLD_BLOCK, NEW_BLOCK));
return 'patched';
}

if (require.main === module) {
const result = applyPatch(process.argv[2] || DEFAULT_TARGET);
console.log(`patch-wwebjs-lid-last-received-key: ${result}`);
}

module.exports = { applyPatch };
34 changes: 34 additions & 0 deletions src/engine/adapters/wwebjs-patch.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';

describe('patch-wwebjs-lid-last-received-key', () => {
it('adds a string fallback for WhatsApp MsgKey objects without _serialized', () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { applyPatch } = require('../../../scripts/patch-wwebjs-lid-last-received-key');
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'wwebjs-patch-'));
const target = path.join(dir, 'Utils.js');
fs.writeFileSync(
target,
` const lastMessage = chat.lastReceivedKey
? window
.require('WAWebCollections')
.Msg.get(chat.lastReceivedKey._serialized) ||
(
await window
.require('WAWebCollections')
.Msg.getMessagesById([
chat.lastReceivedKey._serialized,
])
)?.messages?.[0]
: null;`,
);

expect(applyPatch(target)).toBe('patched');
const patched = fs.readFileSync(target, 'utf8');

expect(patched).toContain('chat.lastReceivedKey?._serialized || chat.lastReceivedKey?.toString?.()');
expect(patched).toContain('Msg.get(lastReceivedKey)');
expect(patched).toContain('Msg.getMessagesById([\n lastReceivedKey,');
});
});