Compare commits

...
20 Commits
Author SHA1 Message Date
devlikepro e5df21e165 [core] 2025.7.3
Release / WEBJS - chrome - amd64 - chrome (push) Waiting to run
Release / WEBJS - chromium - amd64 - latest (push) Waiting to run
Release / WEBJS - chromium - linux/arm64 - arm (push) Waiting to run
Release / GOWS - none - amd64 - gows (push) Waiting to run
Release / GOWS - none - linux/arm64 - gows-arm (push) Waiting to run
Release / NOWEB - none - amd64 - noweb (push) Waiting to run
Release / NOWEB - none - linux/arm64 - noweb-arm (push) Waiting to run
2025-07-03 17:13:06 +07:00
devlikepro 792029b13f [core] Up GOWS
fix #1043
fix #1068
fix #1094
2025-07-03 17:13:06 +07:00
devlikepro 0ef49d7116 [core] GOWS - fallback to storage in case of JSON errors
2 UNKNOWN: json: cannot unmarshal object into Go struct field InteractiveAnnotation.imageMessage.annotations. Action of type waE2
E.isInteractiveAnnotation_Action
2025-07-03 17:13:06 +07:00
devlikepro 600d3291eb [core] add dns in waha by default 2025-07-03 17:13:06 +07:00
devlikepro b78413190c [core] WEBJS - disable GPU 2025-07-03 17:13:06 +07:00
devlikepro c9729af139 [core] 2025.7.2
Release / WEBJS - chromium - amd64 - latest (push) Waiting to run
Release / WEBJS - chromium - linux/arm64 - arm (push) Waiting to run
Release / GOWS - none - amd64 - gows (push) Waiting to run
Release / WEBJS - chrome - amd64 - chrome (push) Waiting to run
Release / GOWS - none - linux/arm64 - gows-arm (push) Waiting to run
Release / NOWEB - none - amd64 - noweb (push) Waiting to run
Release / NOWEB - none - linux/arm64 - noweb-arm (push) Waiting to run
2025-07-02 14:47:05 +07:00
devlikepro 697f267fc3 [core] Add - in prefix 2025-07-02 14:47:05 +07:00
devlikepro ac49ce3cc5 [core] trace 2025-07-02 14:47:05 +07:00
devlikepro 555daf6888 [core] fix heap API 2025-07-02 14:47:05 +07:00
devlikepro 8f0c2994a6 [core] One build-all 2025-07-02 14:47:05 +07:00
devlikepro 873e66db19 [core] Add browser tracing debug API 2025-07-02 14:45:52 +07:00
devlikepro 38b542def4 [core] Add TmpDir (from PLUS) 2025-07-02 14:45:51 +07:00
devlikepro a646e5efc0 [core] remove healthcheck 2025-07-02 14:45:50 +07:00
devlikepro 31590c9229 [core] Add server.debug.controller.ts 2025-07-02 14:45:50 +07:00
devlikepro 98c2172908 [core] WEBJS - onTag handler
related #1092
2025-07-02 14:45:49 +07:00
devlikepro 314b02daf1 [core] WEBJS add waha arguments to chrome to identify it better 2025-07-02 14:45:49 +07:00
devlikepro d2ab78b65c [core] WEBJS Up user agent 2025-07-02 14:45:49 +07:00
devlikepro db2c352fd1 [core] WEBJS --renderer-process-limit=1 2025-07-02 14:45:49 +07:00
devlikepro 6e79ad2793 [core] WEBJS - rm --single-process at all 2025-07-02 14:45:49 +07:00
devlikepro 77eaa287fe [core] WEBJS - remove disable-background-networking, it's default puppeter flag 2025-07-02 14:45:49 +07:00
20 changed files with 315 additions and 93 deletions

No files matched your search

-5
View File
@@ -128,11 +128,6 @@ jobs:
run: |
docker run -d \
--name smoke \
--health-cmd "/bin/bash /ping-check.sh" \
--health-interval 1s \
--health-retries 60 \
--health-timeout 2s \
--health-start-period 2s \
--rm -p3000:3000 \
${{ vars.DOCKER_IMAGE }}:${{ matrix.tag }}
-4
View File
@@ -200,10 +200,6 @@ ENV WAHA_GOWS_SOCKET /tmp/gows.sock
COPY entrypoint.sh /entrypoint.sh
# Add healthcheck script
COPY ping-check.sh /ping-check.sh
RUN chmod +x /ping-check.sh
# Chokidar options to monitor file changes
ENV CHOKIDAR_USEPOLLING=1
ENV CHOKIDAR_INTERVAL=5000
+5 -7
View File
@@ -1,22 +1,20 @@
build-all: build-plus build-chrome build-gows build-noweb
build:
docker build . -t devlikeapro/waha
build-all: build-plus build-chrome build-gows build-noweb
build-plus:
docker build . -t devlikeapro/waha-plus
build-chrome:
docker build . -t devlikeapro/waha-plus:chrome --build-arg USE_BROWSER=chrome
build-noweb:
docker build . -t devlikeapro/waha:noweb --build-arg USE_BROWSER=none --build-arg WHATSAPP_DEFAULT_ENGINE=NOWEB
docker build . -t devlikeapro/waha-plus:noweb --build-arg USE_BROWSER=none --build-arg WHATSAPP_DEFAULT_ENGINE=NOWEB
build-gows:
docker build . -t devlikeapro/waha-plus:gows --build-arg USE_BROWSER=none --build-arg WHATSAPP_DEFAULT_ENGINE=GOWS
build-all: build build-chrome build-noweb
build-plus:
docker build . -t devlikeapro/waha-plus
build-ssh:
# check IMAGE provided
@[ "${IMAGE}" ] || ( echo "Add APP: make build-ssh image=devlikeapro/waha"; exit 1 );
+5 -6
View File
@@ -7,12 +7,11 @@ services:
image: devlikeapro/waha-plus
# WAHA Core
# image: devlikeapro/waha:latest
healthcheck:
test: ['CMD', '/bin/bash', '/ping-check.sh']
interval: 60s
timeout: 10s
retries: 3
start_period: 30s
# Add "dns" if you have a problem with resolving "web.whatsapp.com"
dns:
- 1.1.1.1
- 8.8.8.8
logging:
driver: 'json-file'
-14
View File
@@ -1,14 +0,0 @@
#!/bin/bash
# Try PORT first, then WHATSAPP_API_PORT, then default to 3000
PORT=${PORT:-${WHATSAPP_API_PORT:-3000}}
# Check if HTTPS is enabled
if [[ "${WAHA_HTTPS_ENABLED}" == "true" || "${WAHA_HTTPS_ENABLED}" == "1" ]]; then
PROTOCOL="https"
else
PROTOCOL="http"
fi
# Execute curl command with SSL verification disabled
curl -f -s -k "${PROTOCOL}://127.0.0.1:${PORT}/ping" || exit 1
-34
View File
@@ -1,15 +1,12 @@
import * as process from 'node:process';
import * as v8 from 'node:v8';
import {
Body,
Controller,
Get,
Logger,
NotFoundException,
Post,
Query,
StreamableFile,
UsePipes,
} from '@nestjs/common';
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
@@ -112,34 +109,3 @@ export class ServerController {
return { stopping: true };
}
}
@ApiSecurity('api_key')
@Controller('api/server/debug')
@ApiTags('🔍 Observability')
export class ServerDebugController {
private logger: Logger;
private readonly enabled: boolean;
constructor(protected config: WhatsappConfigService) {
this.logger = new Logger('ServerDebugController');
this.enabled = this.config.debugModeEnabled;
}
@Get('heapsnapshot')
@ApiOperation({
summary: 'Return a heapsnapshot',
description: "Return a heapsnapshot of the server's memory",
})
async heapsnapshot() {
if (!this.enabled) {
throw new NotFoundException('WAHA_DEBUG_MODE is disabled');
}
this.logger.log('Creating a heap snapshot...');
const heap = v8.getHeapSnapshot();
const fileName = `${Date.now()}.heapsnapshot`;
return new StreamableFile(heap, {
type: 'application/octet-stream',
disposition: `attachment; filename=${fileName}`,
});
}
}
+79
View File
@@ -0,0 +1,79 @@
import * as v8 from 'node:v8';
import {
Controller,
Get,
Logger,
NotFoundException,
Query,
StreamableFile,
UsePipes,
} from '@nestjs/common';
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
import { WhatsappConfigService } from '@waha/config.service';
import { SessionManager } from '@waha/core/abc/manager.abc';
import { WhatsappSession } from '@waha/core/abc/session.abc';
import {
SessionApiParam,
WorkingSessionParam,
} from '@waha/nestjs/params/SessionApiParam';
import { WAHAValidationPipe } from '@waha/nestjs/pipes/WAHAValidationPipe';
import { BrowserTraceQuery } from '@waha/structures/server.debug.dto';
import { createReadStream } from 'fs';
@ApiSecurity('api_key')
@Controller('api/server/debug')
@ApiTags('🔍 Observability')
export class ServerDebugController {
private logger: Logger;
private readonly enabled: boolean;
constructor(
private config: WhatsappConfigService,
private manager: SessionManager,
) {
this.logger = new Logger('ServerDebugController');
this.enabled = this.config.debugModeEnabled;
}
@Get('heapsnapshot')
@ApiOperation({
summary: 'Return a heapsnapshot for the current nodejs process',
description: "Return a heapsnapshot of the server's memory",
})
async heapsnapshot() {
if (!this.enabled) {
throw new NotFoundException('WAHA_DEBUG_MODE is disabled');
}
this.logger.log('Creating a heap snapshot...');
const heap = v8.getHeapSnapshot();
const fileName = `${Date.now()}.heapsnapshot`;
return new StreamableFile(heap, {
type: 'application/octet-stream',
disposition: `attachment; filename=${fileName}`,
});
}
@Get('browser/trace/:session')
@ApiOperation({
summary: 'Collect and get a trace.json for Chrome DevTools ',
description: 'Uses https://pptr.dev/api/puppeteer.tracing',
})
@SessionApiParam
@UsePipes(new WAHAValidationPipe())
async browserTrace(
@WorkingSessionParam session: WhatsappSession,
@Query() query: BrowserTraceQuery,
) {
if (!this.enabled) {
throw new NotFoundException('WAHA_DEBUG_MODE is disabled');
}
const filepath = await session.browserTrace(query);
const stream = createReadStream(filepath);
const filename = `trace - ${session.name} - ${new Date()}.json`;
return new StreamableFile(stream, {
type: 'application/octet-stream',
disposition: `attachment; filename=${filename}`,
});
}
}
+7 -4
View File
@@ -30,6 +30,7 @@ import { Label, LabelDTO, LabelID } from '@waha/structures/labels.dto';
import { LidToPhoneNumber } from '@waha/structures/lids.dto';
import { PaginationParams } from '@waha/structures/pagination.dto';
import { MessageSource, WAMessage } from '@waha/structures/responses.dto';
import { BrowserTraceQuery } from '@waha/structures/server.debug.dto';
import { DefaultMap } from '@waha/utils/DefaultMap';
import { generatePrefixedId } from '@waha/utils/ids';
import { LoggerBuilder } from '@waha/utils/logging';
@@ -285,7 +286,6 @@ export abstract class WhatsappSession {
'--aggressive-cache-discard',
'--disable-accelerated-2d-canvas',
'--disable-application-cache',
// '--disable-background-networking', // COMMENTED to test WEBJS stability
// DO NOT disable software rasterizer, it will break the video
// https://github.com/devlikeapro/waha/issues/629
// '--disable-software-rasterizer',
@@ -296,7 +296,7 @@ export abstract class WhatsappSession {
'--disable-dev-shm-usage',
'--disable-extensions',
// '--disable-features=site-per-process', // COMMENTED to test WEBJS stability
//'--disable-gpu', // COMMENTED to test WEBJS stability
'--disable-gpu', // COMMENTED to test WEBJS stability
'--disable-offer-store-unmasked-wallet-cards',
'--disable-offline-load-stale-cache',
'--disable-popup-blocking',
@@ -320,9 +320,8 @@ export abstract class WhatsappSession {
'--no-sandbox',
'--no-zygote',
'--password-store=basic',
// '--renderer-process-limit=2', // COMMENTED to test WEBJS stability
'--renderer-process-limit=1',
'--safebrowsing-disable-auto-update',
// '--single-process',
'--use-mock-keychain',
'--window-size=1280,720',
];
@@ -351,6 +350,10 @@ export abstract class WhatsappSession {
* START - Methods for API
*/
public browserTrace(query: BrowserTraceQuery): Promise<string> {
throw new NotImplementedByEngineError();
}
/**
* Auth methods
*/
+2 -4
View File
@@ -10,10 +10,8 @@ import { TerminusModule } from '@nestjs/terminus';
import { ChannelsController } from '@waha/api/channels.controller';
import { LidsController } from '@waha/api/lids.controller';
import { ProfileController } from '@waha/api/profile.controller';
import {
ServerController,
ServerDebugController,
} from '@waha/api/server.controller';
import { ServerController } from '@waha/api/server.controller';
import { ServerDebugController } from '@waha/api/server.debug.controller';
import { WebsocketGatewayCore } from '@waha/api/websocket.gateway.core';
import { ApiKeyStrategy } from '@waha/core/auth/apiKey.strategy';
import { IApiKeyAuth } from '@waha/core/auth/auth';
+46
View File
@@ -7031,6 +7031,8 @@ export namespace messages {
constructor(data?: any[] | {
session?: Session;
message?: string;
jid?: string;
messageId?: string;
}) {
super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
@@ -7041,6 +7043,12 @@ export namespace messages {
if ("message" in data && data.message != undefined) {
this.message = data.message;
}
if ("jid" in data && data.jid != undefined) {
this.jid = data.jid;
}
if ("messageId" in data && data.messageId != undefined) {
this.messageId = data.messageId;
}
}
}
get session() {
@@ -7058,9 +7066,23 @@ export namespace messages {
set message(value: string) {
pb_1.Message.setField(this, 2, value);
}
get jid() {
return pb_1.Message.getFieldWithDefault(this, 3, "") as string;
}
set jid(value: string) {
pb_1.Message.setField(this, 3, value);
}
get messageId() {
return pb_1.Message.getFieldWithDefault(this, 4, "") as string;
}
set messageId(value: string) {
pb_1.Message.setField(this, 4, value);
}
static fromObject(data: {
session?: ReturnType<typeof Session.prototype.toObject>;
message?: string;
jid?: string;
messageId?: string;
}): DownloadMediaRequest {
const message = new DownloadMediaRequest({});
if (data.session != null) {
@@ -7069,12 +7091,20 @@ export namespace messages {
if (data.message != null) {
message.message = data.message;
}
if (data.jid != null) {
message.jid = data.jid;
}
if (data.messageId != null) {
message.messageId = data.messageId;
}
return message;
}
toObject() {
const data: {
session?: ReturnType<typeof Session.prototype.toObject>;
message?: string;
jid?: string;
messageId?: string;
} = {};
if (this.session != null) {
data.session = this.session.toObject();
@@ -7082,6 +7112,12 @@ export namespace messages {
if (this.message != null) {
data.message = this.message;
}
if (this.jid != null) {
data.jid = this.jid;
}
if (this.messageId != null) {
data.messageId = this.messageId;
}
return data;
}
serialize(): Uint8Array;
@@ -7092,6 +7128,10 @@ export namespace messages {
writer.writeMessage(1, this.session, () => this.session.serialize(writer));
if (this.message.length)
writer.writeString(2, this.message);
if (this.jid.length)
writer.writeString(3, this.jid);
if (this.messageId.length)
writer.writeString(4, this.messageId);
if (!w)
return writer.getResultBuffer();
}
@@ -7107,6 +7147,12 @@ export namespace messages {
case 2:
message.message = reader.readString();
break;
case 3:
message.jid = reader.readString();
break;
case 4:
message.messageId = reader.readString();
break;
default: reader.skipField();
}
}
+61 -1
View File
@@ -14889,7 +14889,9 @@ proto.messages.DownloadMediaRequest.prototype.toObject = function(opt_includeIns
proto.messages.DownloadMediaRequest.toObject = function(includeInstance, msg) {
var f, obj = {
session: (f = msg.getSession()) && proto.messages.Session.toObject(includeInstance, f),
message: jspb.Message.getFieldWithDefault(msg, 2, "")
message: jspb.Message.getFieldWithDefault(msg, 2, ""),
jid: jspb.Message.getFieldWithDefault(msg, 3, ""),
messageid: jspb.Message.getFieldWithDefault(msg, 4, "")
};
if (includeInstance) {
@@ -14935,6 +14937,14 @@ proto.messages.DownloadMediaRequest.deserializeBinaryFromReader = function(msg,
var value = /** @type {string} */ (reader.readString());
msg.setMessage(value);
break;
case 3:
var value = /** @type {string} */ (reader.readString());
msg.setJid(value);
break;
case 4:
var value = /** @type {string} */ (reader.readString());
msg.setMessageid(value);
break;
default:
reader.skipField();
break;
@@ -14979,6 +14989,20 @@ proto.messages.DownloadMediaRequest.serializeBinaryToWriter = function(message,
f
);
}
f = message.getJid();
if (f.length > 0) {
writer.writeString(
3,
f
);
}
f = message.getMessageid();
if (f.length > 0) {
writer.writeString(
4,
f
);
}
};
@@ -15037,6 +15061,42 @@ proto.messages.DownloadMediaRequest.prototype.setMessage = function(value) {
};
/**
* optional string jid = 3;
* @return {string}
*/
proto.messages.DownloadMediaRequest.prototype.getJid = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, ""));
};
/**
* @param {string} value
* @return {!proto.messages.DownloadMediaRequest} returns this
*/
proto.messages.DownloadMediaRequest.prototype.setJid = function(value) {
return jspb.Message.setProto3StringField(this, 3, value);
};
/**
* optional string messageId = 4;
* @return {string}
*/
proto.messages.DownloadMediaRequest.prototype.getMessageid = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, ""));
};
/**
* @param {string} value
* @return {!proto.messages.DownloadMediaRequest} returns this
*/
proto.messages.DownloadMediaRequest.prototype.setMessageid = function(value) {
return jspb.Message.setProto3StringField(this, 4, value);
};
@@ -2152,6 +2152,8 @@ export class GOWSEngineMediaProcessor implements IMediaEngineProcessor<any> {
// double "session" it's not a mistake here
session: this.session.session,
message: data,
jid: message.Info.Chat,
messageId: message.Info.ID,
});
const response = await promisify(this.session.client.DownloadMedia)(
request,
+4
View File
@@ -119,4 +119,8 @@ export class WPage extends EventEmitter {
this.page.on(event, listener);
return this.page as any;
}
get tracing() {
return this.page.tracing;
}
}
+27 -1
View File
@@ -106,6 +106,7 @@ import {
WAHAPresenceData,
} from '@waha/structures/presence.dto';
import { WAMessage, WAMessageReaction } from '@waha/structures/responses.dto';
import { BrowserTraceQuery } from '@waha/structures/server.debug.dto';
import { MeInfo } from '@waha/structures/sessions.dto';
import { StatusRequest, TextStatus } from '@waha/structures/status.dto';
import {
@@ -117,7 +118,9 @@ import {
import { PaginatorInMemory } from '@waha/utils/Paginator';
import { sleep, waitUntil } from '@waha/utils/promiseTimeout';
import { SingleDelayedJobRunner } from '@waha/utils/SingleDelayedJobRunner';
import { TmpDir } from '@waha/utils/tmpdir';
import * as lodash from 'lodash';
import * as path from 'path';
import { ProtocolError } from 'puppeteer';
import { filter, fromEvent, merge, mergeMap, Observable, share } from 'rxjs';
import { map } from 'rxjs/operators';
@@ -194,13 +197,19 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
if (cacheType === 'local') {
this.logger.info(`Using web version: '${webVersion}'`);
}
const args = this.getBrowserArgsForPuppeteer();
// add at the start
args.unshift(`--a-waha-timestamp=${new Date()}`);
args.unshift(`--a-waha-session=${this.name}`);
return {
puppeteer: {
headless: true,
executablePath: this.getBrowserExecutablePath(),
args: this.getBrowserArgsForPuppeteer(),
args: args,
dumpio: this.isDebugEnabled(),
},
userAgent:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36',
webVersion: webVersion,
webVersionCache: {
type: cacheType,
@@ -513,6 +522,23 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
/**
* START - Methods for API
*/
public async browserTrace(query: BrowserTraceQuery): Promise<string> {
const tmpdir = new TmpDir(
this.logger,
`waha-browser-trace-${this.name}-`,
(10 * query.seconds + 120) * 1000,
);
const page = this.whatsapp.pupPage;
return await tmpdir.use(async (dir) => {
this.logger.info({ query }, `Starting browser tracing...`);
const filepath = path.join(dir, 'trace.json');
await page.tracing.start({ path: filepath });
await sleep(query.seconds * 1000);
await page.tracing.stop();
this.logger.info(`Browser tracing finished, saved to ${filepath}`);
return filepath;
});
}
/**
* Auth methods
+25
View File
@@ -0,0 +1,25 @@
import { ApiProperty } from '@nestjs/swagger';
import { Transform, Type } from 'class-transformer';
import { IsArray, IsNumber, IsOptional, IsString } from 'class-validator';
export class BrowserTraceQuery {
@Type(() => Number)
@IsNumber()
@ApiProperty({
description: 'How many seconds to trace',
example: 30,
required: true,
})
seconds: number = 30;
@IsArray()
@IsString({ each: true })
@Transform(({ value }) => (Array.isArray(value) ? value : [value]))
@IsOptional()
@ApiProperty({
description: 'Categories to trace (all by default)',
example: ['*'],
required: true,
})
categories: string[] = ['*'];
}
+47
View File
@@ -0,0 +1,47 @@
import * as fs from 'fs/promises';
import * as os from 'os';
import * as path from 'path';
import { Logger } from 'pino';
function sanitize(input: string) {
return input.replace(/[^a-zA-Z0-9-_]/g, '_');
}
export class TmpDir {
private readonly prefix: string;
constructor(
private logger: Logger,
prefix: string,
private cleanupTimeout = 10_000,
) {
this.prefix = sanitize(prefix);
if (this.prefix.length > 249) {
this.prefix = this.prefix.slice(0, 249);
}
}
/**
* Creates a temporary directory and passes it to the callback.
* The directory is automatically cleaned up after the callback returns.
* @param callback Function that receives the temporary directory path
* @returns The result of the callback
*/
public async use<T>(callback: (dir: string) => Promise<T>): Promise<T> {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), this.prefix));
try {
return await callback(dir);
} finally {
setTimeout(async () => {
fs.rm(dir, { recursive: true, force: true })
.then(() => {
this.logger.trace(`Cleaned up temporary directory '${dir}'`);
})
.catch((err) => {
this.logger.warn(
`Failed to clean up temporary directory '${dir}': ${err.message}`,
);
});
}, this.cleanupTimeout);
}
}
}
+1 -1
View File
@@ -33,7 +33,7 @@ export function getEngineName(): string {
}
export const VERSION: WAHAEnvironment = {
version: '2025.7.1',
version: '2025.7.3',
engine: getEngineName(),
tier: getWAHAVersion(),
browser:
+1 -9
View File
@@ -4,12 +4,4 @@ http:
allow-insecure: true
no-follow-redirects: true
timeout: 5000
body: ['version']
command:
docker smoke health:
exec: "docker inspect --format '{{`{{if .State.Health}}{{.State.Health.Status}}{{else}}no healthcheck{{end}}`}}' smoke"
exit-status: 0
stdout:
- 'healthy'
timeout: 5000
body: ['version']
+1 -1
View File
@@ -2,7 +2,7 @@
"waha": {
"gows": {
"repo": "devlikeapro/gows",
"ref": "v1.0.8"
"ref": "v1.0.9"
},
"dashboard": {
"repo": "devlikeapro/dashboard",
+2 -2
View File
@@ -13399,7 +13399,7 @@ __metadata:
"whatsapp-web.js@github:devlikeapro/whatsapp-web.js#fork-main-2025-06-09":
version: 1.30.1-alpha.2
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=48fcc59575b46386747673d1b01b8f89e8c49c2d"
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=c133ae4a347ba7b21b647c8c6811f58c55b21069"
dependencies:
"@pedroslopez/moduleraid": ^5.0.2
archiver: ^5.3.1
@@ -13417,7 +13417,7 @@ __metadata:
optional: true
unzipper:
optional: true
checksum: 7d867a4180321e85477e57b15f9ea85d2e26b6d1cf875f7e40131e4a047aaae1ad5e8b977c1ff9b3a64538276271fed06202ac6eb9168c7c5dd01eb155402f7f
checksum: e99e0c5172e4045098ef0cd027304b1f5d37b6ce1ae00f1b50f0ca59e5a0894faeca9972e7db88f1d0e6aebb3ca67c3d3cac333f594ab31ffeb166414e4eeb19
languageName: node
linkType: hard