Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41b669a35c | ||
|
|
7b5ca3bc57 | ||
|
|
bb0c7fd22b | ||
|
|
c79958541e | ||
|
|
94ee8863d6 | ||
|
|
011477262d | ||
|
|
2e8e4cefb0 | ||
|
|
5e2802c098 | ||
|
|
9a6250a055 | ||
|
|
f8cb56525a | ||
|
|
b5b491cb7b | ||
|
|
7eb6be70f9 | ||
|
|
0de8a5fabc | ||
|
|
9fbc18fb70 | ||
|
|
e7ce3368b0 | ||
|
|
729600e9c6 | ||
|
|
54886f385b | ||
|
|
81854ad7ec | ||
|
|
5261d4f281 | ||
|
|
72d9d94342 | ||
|
|
b782ad27a2 | ||
|
|
d7dad5e6c2 | ||
|
|
8765bb4412 | ||
|
|
984be25d51 | ||
|
|
70620207dd | ||
|
|
a96200f981 | ||
|
|
4978abf3d8 | ||
|
|
a67d84f21e | ||
|
|
91f59b38fd | ||
|
|
d0ec351910 | ||
|
|
a7b12874fb | ||
|
|
cd2c7bdd86 | ||
|
|
045077143f | ||
|
|
bcd2199687 | ||
|
|
af108eede4 | ||
|
|
ee1cf838b8 | ||
|
|
0fc74895da |
No files matched your search
+16
-13
@@ -3,9 +3,25 @@
|
||||
# https://waha.devlike.pro/docs/how-to/config/
|
||||
#
|
||||
|
||||
# ====================
|
||||
# ===== SECURITY =====
|
||||
# ====================
|
||||
WAHA_API_KEY=00000000000000000000000000000000
|
||||
WAHA_DASHBOARD_USERNAME=admin
|
||||
WAHA_DASHBOARD_PASSWORD=11111111111111111111111111111111
|
||||
WHATSAPP_SWAGGER_USERNAME=admin
|
||||
WHATSAPP_SWAGGER_PASSWORD=11111111111111111111111111111111
|
||||
|
||||
# Disable Dashboard or Swagger
|
||||
WAHA_DASHBOARD_ENABLED=True
|
||||
WHATSAPP_SWAGGER_ENABLED=True
|
||||
|
||||
# ==================
|
||||
# ===== COMMON =====
|
||||
# ==================
|
||||
# WhatsApp engine (WEBJS is default, GOWS or NOWEB for better performance)
|
||||
WHATSAPP_DEFAULT_ENGINE=WEBJS
|
||||
|
||||
# Base URL for the API (used for webhooks, file URLs, etc.)
|
||||
WAHA_BASE_URL=http://localhost:3000
|
||||
# WAHA_PUBLIC_URL=http://localhost:3000
|
||||
@@ -15,20 +31,7 @@ WAHA_BASE_URL=http://localhost:3000
|
||||
# WHATSAPP_API_PORT=3000
|
||||
# WHATSAPP_API_HOSTNAME=localhost
|
||||
|
||||
# ====================
|
||||
# ===== SECURITY =====
|
||||
# ====================
|
||||
# "sha512:{SHA}" format - below is "admin" api key
|
||||
WAHA_API_KEY=sha512:c7ad44cbad762a5da0a452f9e854fdc1e0e7a52a38015f23f3eab1d80b931dd472634dfac71cd34ebc35d16ab7fb8a90c81f975113d6c7538dc69dd8de9077ec
|
||||
WAHA_DASHBOARD_ENABLED=True
|
||||
WAHA_DASHBOARD_USERNAME=admin
|
||||
WAHA_DASHBOARD_PASSWORD=admin
|
||||
WHATSAPP_SWAGGER_ENABLED=True
|
||||
WHATSAPP_SWAGGER_USERNAME=admin
|
||||
WHATSAPP_SWAGGER_PASSWORD=admin
|
||||
|
||||
# WhatsApp engine (WEBJS is default, GOWS or NOWEB for better performance)
|
||||
WHATSAPP_DEFAULT_ENGINE=WEBJS
|
||||
|
||||
# ===================
|
||||
# ===== LOGGING =====
|
||||
|
||||
@@ -129,6 +129,7 @@ jobs:
|
||||
docker run -d \
|
||||
--name smoke \
|
||||
--rm -p3000:3000 \
|
||||
-e WAHA_API_KEY=test \
|
||||
${{ vars.DOCKER_IMAGE }}:${{ matrix.tag }}
|
||||
|
||||
sleep 3
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
name: Dev
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
docker-build:
|
||||
if: github.repository == 'devlikeapro/waha-plus'
|
||||
runs-on: ${{ matrix.runner }}
|
||||
name:
|
||||
${{ matrix.engine }} - ${{ matrix.browser }} - ${{ matrix.platform }} -
|
||||
${{ matrix.tag }}
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- runner: 'buildjet-4vcpu-ubuntu-2204'
|
||||
tag: 'dev'
|
||||
platform: 'amd64'
|
||||
browser: 'chromium'
|
||||
engine: 'WEBJS'
|
||||
goss: 'goss-linux-amd64'
|
||||
- runner: 'buildjet-4vcpu-ubuntu-2204-arm'
|
||||
tag: 'dev-arm'
|
||||
platform: 'linux/arm64'
|
||||
browser: 'chromium'
|
||||
engine: 'WEBJS'
|
||||
goss: 'goss-linux-arm'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check recent changes
|
||||
id: recent
|
||||
run: |
|
||||
count=$(git rev-list --after="24 hours ago" --count HEAD || true)
|
||||
if [ "$count" -gt 0 ]; then
|
||||
echo "has_recent=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "has_recent=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: No recent changes summary
|
||||
if: ${{ steps.recent.outputs.has_recent != 'true' }}
|
||||
run:
|
||||
echo "No commits in the last 24 hours; skipping build." >>
|
||||
"$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
if: ${{ steps.recent.outputs.has_recent == 'true' }}
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Docker meta
|
||||
if: ${{ steps.recent.outputs.has_recent == 'true' }}
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ vars.DOCKER_IMAGE }}
|
||||
flavor: latest=false
|
||||
tags: |
|
||||
type=raw,value=${{ matrix.tag }}
|
||||
|
||||
- name: Login to image repository
|
||||
if: ${{ steps.recent.outputs.has_recent == 'true' }}
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USER }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
||||
- name: Build
|
||||
if: ${{ steps.recent.outputs.has_recent == 'true' }}
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile
|
||||
platforms: ${{ matrix.platform }}
|
||||
build-args: |
|
||||
USE_BROWSER=${{ matrix.browser }}
|
||||
WHATSAPP_DEFAULT_ENGINE=${{ matrix.engine }}
|
||||
push: false
|
||||
load: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
- name: Install goss
|
||||
if: ${{ steps.recent.outputs.has_recent == 'true' }}
|
||||
env:
|
||||
GOSS_DOWNLOAD: 'https://github.com/goss-org/goss/releases/download'
|
||||
GOSS_VERSION: 'v0.4.8'
|
||||
run: |
|
||||
curl -L https://github.com/goss-org/goss/releases/download/${{ env.GOSS_VERSION }}/${{ matrix.goss }} -o /usr/local/bin/goss
|
||||
chmod +rx /usr/local/bin/goss
|
||||
|
||||
- name: Run smoke tests
|
||||
if: ${{ steps.recent.outputs.has_recent == 'true' }}
|
||||
working-directory: tests/smoke
|
||||
timeout-minutes: 2
|
||||
run: |
|
||||
docker run -d \
|
||||
--name smoke \
|
||||
--rm -p3000:3000 \
|
||||
-e WAHA_API_KEY=test \
|
||||
${{ vars.DOCKER_IMAGE }}:${{ matrix.tag }}
|
||||
|
||||
sleep 3
|
||||
docker logs smoke
|
||||
goss validate --retry-timeout 30s --sleep 1s
|
||||
docker rm --force smoke
|
||||
|
||||
- name: Push
|
||||
if: ${{ steps.recent.outputs.has_recent == 'true' }}
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile
|
||||
platforms: ${{ matrix.platform }}
|
||||
build-args: |
|
||||
USE_BROWSER=${{ matrix.browser }}
|
||||
WHATSAPP_DEFAULT_ENGINE=${{ matrix.engine }}
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
@@ -15,6 +15,7 @@ on:
|
||||
|
||||
jobs:
|
||||
en:
|
||||
if: github.repository == 'devlikeapro/waha'
|
||||
permissions:
|
||||
issues: write
|
||||
discussions: write
|
||||
@@ -31,21 +32,20 @@ jobs:
|
||||
CUSTOM_BOT_NOTE: 'English'
|
||||
TARGET_LANGUAGE: 'eng'
|
||||
TRANSLATED_LANGUAGE: 'en'
|
||||
|
||||
pt:
|
||||
permissions:
|
||||
issues: write
|
||||
discussions: write
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: devlikeapro/github-translate-action@main
|
||||
env:
|
||||
# GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
IS_MODIFY_TITLE: false
|
||||
CUSTOM_BOT_NOTE: 'Portuguese'
|
||||
TARGET_LANGUAGE: 'por'
|
||||
TRANSLATED_LANGUAGE: 'pt'
|
||||
# pt:
|
||||
# permissions:
|
||||
# issues: write
|
||||
# discussions: write
|
||||
# pull-requests: write
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v4
|
||||
# - uses: devlikeapro/github-translate-action@main
|
||||
# env:
|
||||
# # GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# with:
|
||||
# IS_MODIFY_TITLE: false
|
||||
# CUSTOM_BOT_NOTE: 'Portuguese'
|
||||
# TARGET_LANGUAGE: 'por'
|
||||
# TRANSLATED_LANGUAGE: 'pt'
|
||||
@@ -73,4 +73,5 @@ repos:
|
||||
^src/core/engines/webjs/_lodash.js|
|
||||
^tests/perf/.*|
|
||||
^scripts/.*|
|
||||
^scripts/init-waha.js|
|
||||
)$
|
||||
@@ -195,6 +195,11 @@ COPY --from=build /git/node_modules ./node_modules
|
||||
COPY --from=build /git/dist ./dist
|
||||
COPY --from=dashboard /dashboard ./dist/dashboard
|
||||
COPY --from=gows /go/gows/bin/gows /app/gows
|
||||
COPY .env.example ./.env.example
|
||||
COPY scripts/init-waha.js ./scripts/init-waha.js
|
||||
RUN chmod +x ./scripts/init-waha.js \
|
||||
&& printf '%s\n' '#!/bin/sh' 'exec node /app/scripts/init-waha.js "$@"' > /usr/local/bin/init-waha \
|
||||
&& chmod +x /usr/local/bin/init-waha
|
||||
ENV WAHA_GOWS_PATH=/app/gows
|
||||
ENV WAHA_GOWS_SOCKET=/tmp/gows.sock
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ for-swagger:
|
||||
WHATSAPP_SWAGGER_CONFIG_ADVANCED=true . ${NVM_DIR}/nvm.sh && nvm exec yarn start
|
||||
|
||||
up-noweb:
|
||||
yarn up @adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-2025-10-10
|
||||
yarn up @adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-2025-10-19
|
||||
|
||||
up-noweb-libsignal:
|
||||
yarn up libsignal@github:devlikeapro/libsignal-node#fork-master
|
||||
|
||||
@@ -3,6 +3,20 @@
|
||||
# https://waha.devlike.pro/docs/how-to/config/
|
||||
#
|
||||
|
||||
# ====================
|
||||
# ===== SECURITY =====
|
||||
# ====================
|
||||
WAHA_API_KEY_PLAIN=00000000000000000000000000000000
|
||||
WAHA_API_KEY=00000000000000000000000000000000
|
||||
WAHA_DASHBOARD_USERNAME=admin
|
||||
WAHA_DASHBOARD_PASSWORD=11111111111111111111111111111111
|
||||
WHATSAPP_SWAGGER_USERNAME=admin
|
||||
WHATSAPP_SWAGGER_PASSWORD=11111111111111111111111111111111
|
||||
|
||||
# Disable Dashboard or Swagger
|
||||
WAHA_DASHBOARD_ENABLED=True
|
||||
WHATSAPP_SWAGGER_ENABLED=True
|
||||
|
||||
# ==================
|
||||
# ===== COMMON =====
|
||||
# ==================
|
||||
@@ -15,20 +29,6 @@ WAHA_PUBLIC_URL=http://localhost:3000
|
||||
# WHATSAPP_API_PORT=3000
|
||||
# WHATSAPP_API_HOSTNAME=localhost
|
||||
|
||||
# ====================
|
||||
# ===== SECURITY =====
|
||||
# ====================
|
||||
# WAHA Apps requires both sha and plain version
|
||||
WAHA_API_KEY_PLAIN=00000000000000000000000000000000
|
||||
WAHA_API_KEY=sha512:98b6d128682e280b74b324ca82a6bae6e8a3f7174e0605bfd52eb9948fad8984854ec08f7652f32055c4a9f12b69add4850481d9503a7f2225501671d6124648
|
||||
WAHA_DASHBOARD_USERNAME=admin
|
||||
WAHA_DASHBOARD_PASSWORD=11111111111111111111111111111111
|
||||
WHATSAPP_SWAGGER_USERNAME=admin
|
||||
WHATSAPP_SWAGGER_PASSWORD=11111111111111111111111111111111
|
||||
|
||||
WAHA_DASHBOARD_ENABLED=True
|
||||
WHATSAPP_SWAGGER_ENABLED=True
|
||||
|
||||
# WhatsApp engine (WEBJS is default, GOWS or NOWEB for better performance)
|
||||
WHATSAPP_DEFAULT_ENGINE=GOWS
|
||||
|
||||
|
||||
@@ -41,11 +41,6 @@ if [ -n "$key" ]; then
|
||||
# If already hashed, use it as is
|
||||
export WAHA_API_KEY="$key"
|
||||
else
|
||||
# Display warning about using plain text API key
|
||||
echo "⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️"
|
||||
echo "WARNING: Plain text API key detected. Converting to hashed format for security."
|
||||
echo "For better security, use WAHA_API_KEY=sha512:{SHA512_HASH_FOR_YOUR_API_KEY}"
|
||||
echo "⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️"
|
||||
# Hash the key using sha512sum
|
||||
HASHED_KEY=$(echo -n "$key" | sha512sum | awk '{print $1}')
|
||||
export WAHA_API_KEY="sha512:$HASHED_KEY"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+3
-3
@@ -26,7 +26,7 @@
|
||||
"gows:proto": "yarn gows:proto:fetch && yarn gows:proto:build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@adiwajshing/baileys": "github:devlikeapro/Baileys#fork-master-2025-10-10",
|
||||
"@adiwajshing/baileys": "github:devlikeapro/Baileys#fork-master-2025-10-19",
|
||||
"@adiwajshing/keyed-db": "^0.2.4",
|
||||
"@aws-sdk/client-s3": "^3.633.0",
|
||||
"@aws-sdk/s3-request-presigner": "^3.633.0",
|
||||
@@ -76,7 +76,7 @@
|
||||
"joi": "^17.13.3",
|
||||
"knex": "^3.1.0",
|
||||
"libphonenumber-js": "^1.10.36",
|
||||
"libsignal": "github:devlikeapro/libsignal-node#fork-master",
|
||||
"libsignal": "github:WhiskeySockets/libsignal-node#master",
|
||||
"link-preview-js": "^3.0.4",
|
||||
"lodash": "^4.17.21",
|
||||
"long": "^5.3.2",
|
||||
@@ -102,6 +102,7 @@
|
||||
"sqlite3": "^5.1.7",
|
||||
"swagger-ui-express": "^4.1.4",
|
||||
"ulid": "^2.3.0",
|
||||
"undici": "^7.16.0",
|
||||
"whatsapp-web.js": "github:devlikeapro/whatsapp-web.js#fork-main-2025-09-10",
|
||||
"write-file-atomic": "^6.0.0",
|
||||
"yaml": "^2.7.1"
|
||||
@@ -114,7 +115,6 @@
|
||||
"ws": "^8.18.0",
|
||||
"puppeteer": "^24.19.0",
|
||||
"whatwg-url": "13.0.0",
|
||||
"libsignal": "github:devlikeapro/libsignal-node#fork-master",
|
||||
"axios": "^1.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
Executable
+92
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const projectRoot = path.resolve(__dirname, '..');
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
const forceIndex = args.indexOf('--force');
|
||||
const forceOverwrite = forceIndex !== -1;
|
||||
|
||||
if (forceOverwrite) {
|
||||
args.splice(forceIndex, 1);
|
||||
}
|
||||
|
||||
const folderArg = args[0] || '.';
|
||||
const sourceArgRaw = args[1];
|
||||
const targetArg = args[2] || '.env';
|
||||
|
||||
const envDir = path.resolve(process.cwd(), folderArg);
|
||||
const sourceArg = sourceArgRaw || '.env.example';
|
||||
const templateBaseDir = sourceArgRaw ? envDir : projectRoot;
|
||||
const templatePath = path.isAbsolute(sourceArg)
|
||||
? sourceArg
|
||||
: path.resolve(templateBaseDir, sourceArg);
|
||||
const targetPath = path.isAbsolute(targetArg)
|
||||
? targetArg
|
||||
: path.resolve(envDir, targetArg);
|
||||
|
||||
function exitWithMessage(message, code = 1) {
|
||||
console.error(message);
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
if (!fs.existsSync(envDir)) {
|
||||
exitWithMessage(`Target directory does not exist: ${envDir}`);
|
||||
}
|
||||
|
||||
if (!fs.existsSync(templatePath)) {
|
||||
exitWithMessage(`Missing template file: ${templatePath}`);
|
||||
}
|
||||
|
||||
if (!forceOverwrite && fs.existsSync(targetPath)) {
|
||||
const stats = fs.statSync(targetPath);
|
||||
if (stats.size > 0) {
|
||||
exitWithMessage(
|
||||
`${targetPath} already exists and is not empty. Remove it manually or rerun with --force to overwrite.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const exampleContent = fs.readFileSync(templatePath, 'utf8');
|
||||
|
||||
function generateSecret() {
|
||||
return crypto.randomUUID({ disableEntropyCache: true }).replace(/-/g, '');
|
||||
}
|
||||
|
||||
const apiKey = generateSecret();
|
||||
const adminPassword = generateSecret();
|
||||
|
||||
const updatedContent = exampleContent
|
||||
.replace(/^WAHA_API_KEY=.*/m, `WAHA_API_KEY=${apiKey}`)
|
||||
.replace(/^WAHA_API_KEY_PLAIN=.*/m, `WAHA_API_KEY_PLAIN=${apiKey}`)
|
||||
.replace(/^WAHA_DASHBOARD_USERNAME=.*/m, 'WAHA_DASHBOARD_USERNAME=admin')
|
||||
.replace(
|
||||
/^WAHA_DASHBOARD_PASSWORD=.*/m,
|
||||
`WAHA_DASHBOARD_PASSWORD=${adminPassword}`,
|
||||
)
|
||||
.replace(/^WHATSAPP_SWAGGER_USERNAME=.*/m, 'WHATSAPP_SWAGGER_USERNAME=admin')
|
||||
.replace(
|
||||
/^WHATSAPP_SWAGGER_PASSWORD=.*/m,
|
||||
`WHATSAPP_SWAGGER_PASSWORD=${adminPassword}`,
|
||||
);
|
||||
|
||||
fs.writeFileSync(targetPath, updatedContent, { encoding: 'utf8' });
|
||||
|
||||
const lines = [
|
||||
'Credentials generated.',
|
||||
'',
|
||||
'Dashboard and Swagger:',
|
||||
' - Username: admin',
|
||||
` - Password: ${adminPassword}`,
|
||||
'',
|
||||
'API key: ',
|
||||
` - ${apiKey}`,
|
||||
'',
|
||||
'Use it in the Dashboard connection flow: https://waha.devlike.pro/docs/how-to/dashboard/#api-key',
|
||||
];
|
||||
|
||||
console.log(lines.join('\n'));
|
||||
@@ -2,10 +2,11 @@ import * as process from 'node:process';
|
||||
|
||||
import { parseBool } from '@waha/helpers';
|
||||
import * as basicAuth from 'express-basic-auth';
|
||||
import { Auth } from '@waha/core/auth/config';
|
||||
|
||||
export function BullAuthMiddleware() {
|
||||
let username = process.env.WAHA_DASHBOARD_USERNAME || '';
|
||||
let password = process.env.WAHA_DASHBOARD_PASSWORD || '';
|
||||
let username = Auth.dashboard.username.value || '';
|
||||
let password = Auth.dashboard.password.value || '';
|
||||
if (process.env.WAHA_DASHBOARD_ENABLED) {
|
||||
const enabled = parseBool(process.env.WAHA_DASHBOARD_ENABLED);
|
||||
if (!enabled) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import { ChatwootLocalesController } from '@waha/apps/chatwoot/api/chatwoot.loca
|
||||
import { ChatWootExports } from '@waha/apps/chatwoot/chatwoot.module';
|
||||
import { parseBool } from '@waha/helpers';
|
||||
import { RMutexModule } from '@waha/modules/rmutex';
|
||||
import { Auth } from '@waha/core/auth/config';
|
||||
|
||||
const IMPORTS = [
|
||||
BullModule.forRoot({
|
||||
@@ -93,11 +94,11 @@ const AppsDisabled = {
|
||||
};
|
||||
|
||||
function checkApiKey() {
|
||||
const key = process.env.WHATSAPP_API_KEY || process.env.WAHA_API_KEY;
|
||||
const key = Auth.key.value;
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
const plain = process.env.WAHA_API_KEY_PLAIN;
|
||||
const plain = Auth.keyplain.value;
|
||||
if (!plain) {
|
||||
throw Error(
|
||||
'WAHA_API_KEY set, please provide WAHA_API_KEY_PLAIN when WAHA_APPS_ENABLED',
|
||||
|
||||
@@ -13,12 +13,11 @@ import { Locale } from '@waha/apps/chatwoot/i18n/locale';
|
||||
import { WAHASessionAPI } from '@waha/apps/chatwoot/session/WAHASelf';
|
||||
import { SessionManager } from '@waha/core/abc/manager.abc';
|
||||
import { RMutexService } from '@waha/modules/rmutex/rmutex.service';
|
||||
import { WAHAEvents, WAMessageAck } from '@waha/structures/enums.dto';
|
||||
import { WAHAEvents } from '@waha/structures/enums.dto';
|
||||
import { WAHAWebhookMessageAck } from '@waha/structures/webhooks.dto';
|
||||
import { Job } from 'bullmq';
|
||||
import { PinoLogger } from 'nestjs-pino';
|
||||
import { isJidCusFormat } from '@waha/utils/wa';
|
||||
import { isLidUser } from '@adiwajshing/baileys/lib/WABinary/jid-utils';
|
||||
import { ShouldMarkAsReadInChatWoot } from '@waha/apps/chatwoot/consumers/waha/message.ack.utils';
|
||||
|
||||
@Processor(QueueName.WAHA_MESSAGE_ACK, { concurrency: JOB_CONCURRENCY })
|
||||
export class WAHAMessageAckConsumer extends ChatWootWAHABaseConsumer {
|
||||
@@ -30,22 +29,8 @@ export class WAHAMessageAckConsumer extends ChatWootWAHABaseConsumer {
|
||||
super(manager, log, rmutex, 'WAHAMessageAckConsumer');
|
||||
}
|
||||
|
||||
ShouldProcess(event: WAHAWebhookMessageAck): boolean {
|
||||
// Mark as seen only if it's DM
|
||||
// Ignore groups and other multiple participants chats
|
||||
const chatId = this.GetChatId(event);
|
||||
if (!isJidCusFormat(chatId) && !isLidUser(chatId)) {
|
||||
return false;
|
||||
}
|
||||
const payload = event.payload;
|
||||
if (payload.fromMe) {
|
||||
// Ignore from me
|
||||
return;
|
||||
}
|
||||
// Only READ and PLAYED
|
||||
return (
|
||||
payload.ack === WAMessageAck.READ || payload.ack == WAMessageAck.PLAYED
|
||||
);
|
||||
ShouldProcess(event: any): boolean {
|
||||
return ShouldMarkAsReadInChatWoot(event);
|
||||
}
|
||||
|
||||
GetChatId(event: WAHAWebhookMessageAck): string {
|
||||
|
||||
@@ -0,0 +1,466 @@
|
||||
import type { WAHAEngine, WAHAEvents } from '@waha/structures/enums.dto';
|
||||
import { ShouldMarkAsReadInChatWoot } from '@waha/apps/chatwoot/consumers/waha/message.ack.utils';
|
||||
|
||||
interface TestParam {
|
||||
name: string;
|
||||
expected: boolean;
|
||||
GOWS: any;
|
||||
NOWEB: any;
|
||||
WEBJS: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* Me - 444444444444 (lid - 144444444444444)
|
||||
* Participant - 11111111111 (lid - 011111111111111)
|
||||
* Group - 222222222222222222
|
||||
*/
|
||||
const ShouldMarkAsReadCases: TestParam[] = [
|
||||
{
|
||||
name: 'Participant read My message (READ ack)',
|
||||
expected: true,
|
||||
GOWS: {
|
||||
id: 'evt_00000000000000000000000000',
|
||||
session: 'default',
|
||||
event: 'message.ack' as WAHAEvents,
|
||||
payload: {
|
||||
id: 'true_11111111111@c.us_3333333333333333333333',
|
||||
from: '11111111111@c.us',
|
||||
to: null,
|
||||
participant: null,
|
||||
fromMe: true,
|
||||
ack: 3,
|
||||
ackName: 'READ',
|
||||
_data: {
|
||||
Chat: '11111111111@s.whatsapp.net',
|
||||
Sender: '11111111111@s.whatsapp.net',
|
||||
IsFromMe: false,
|
||||
IsGroup: false,
|
||||
AddressingMode: '',
|
||||
SenderAlt: '',
|
||||
RecipientAlt: '',
|
||||
BroadcastListOwner: '',
|
||||
BroadcastRecipients: null,
|
||||
MessageIDs: ['3333333333333333333333'],
|
||||
Type: 'read',
|
||||
MessageSender: '',
|
||||
},
|
||||
},
|
||||
metadata: {},
|
||||
me: {
|
||||
id: '444444444444@c.us',
|
||||
lid: '144444444444444@lid',
|
||||
jid: '444444444444:42@s.whatsapp.net',
|
||||
pushName: '',
|
||||
},
|
||||
environment: {
|
||||
version: '2025.10.4',
|
||||
engine: 'GOWS',
|
||||
tier: 'PLUS',
|
||||
browser: null,
|
||||
},
|
||||
engine: 'GOWS' as WAHAEngine,
|
||||
},
|
||||
NOWEB: {
|
||||
id: 'evt_00000000000000000000000000',
|
||||
session: 'default',
|
||||
event: 'message.ack',
|
||||
payload: {
|
||||
id: 'true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
||||
from: '11111111111@c.us',
|
||||
fromMe: true,
|
||||
ack: 3,
|
||||
ackName: 'READ',
|
||||
},
|
||||
metadata: {},
|
||||
me: {
|
||||
id: '444444444444@c.us',
|
||||
pushName: '',
|
||||
lid: '144444444444444@lid',
|
||||
},
|
||||
engine: 'NOWEB',
|
||||
environment: {
|
||||
version: '2025.10.4',
|
||||
engine: 'NOWEB',
|
||||
tier: 'PLUS',
|
||||
browser: null,
|
||||
},
|
||||
},
|
||||
WEBJS: {
|
||||
id: 'evt_00000000000000000000000000',
|
||||
session: 'default',
|
||||
event: 'message.ack',
|
||||
payload: {
|
||||
id: 'true_11111111111@c.us_AAA',
|
||||
from: '444444444444@c.us',
|
||||
fromMe: true,
|
||||
source: 'app',
|
||||
to: '11111111111@c.us',
|
||||
body: 'Nn',
|
||||
hasMedia: false,
|
||||
media: null,
|
||||
ack: 3,
|
||||
ackName: 'READ',
|
||||
vCards: [],
|
||||
_data: {
|
||||
id: {
|
||||
fromMe: true,
|
||||
remote: '11111111111@c.us',
|
||||
id: 'AAA',
|
||||
_serialized: 'true_11111111111@c.us_AAA',
|
||||
},
|
||||
viewed: false,
|
||||
from: '444444444444@c.us',
|
||||
to: '11111111111@c.us',
|
||||
author: '444444444444@c.us',
|
||||
ack: 3,
|
||||
},
|
||||
},
|
||||
metadata: {},
|
||||
me: {
|
||||
id: '444444444444@c.us',
|
||||
pushName: '',
|
||||
},
|
||||
engine: 'WEBJS',
|
||||
environment: {
|
||||
version: '2025.10.4',
|
||||
engine: 'WEBJS',
|
||||
tier: 'PLUS',
|
||||
browser: '/usr/bin/google-chrome-stable',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Participant received My message (DEVICE ack)',
|
||||
expected: false,
|
||||
GOWS: {
|
||||
id: 'evt_00000000000000000000000000',
|
||||
session: 'default',
|
||||
event: 'message.ack' as WAHAEvents,
|
||||
payload: {
|
||||
id: 'true_11111111111@c.us_3333333333333333333333',
|
||||
from: '11111111111@c.us',
|
||||
to: null,
|
||||
participant: null,
|
||||
fromMe: true,
|
||||
ack: 2,
|
||||
ackName: 'DEVICE',
|
||||
_data: {
|
||||
Chat: '11111111111@s.whatsapp.net',
|
||||
Sender: '11111111111:3@s.whatsapp.net',
|
||||
IsFromMe: false,
|
||||
IsGroup: false,
|
||||
AddressingMode: '',
|
||||
SenderAlt: '',
|
||||
RecipientAlt: '',
|
||||
BroadcastListOwner: '',
|
||||
BroadcastRecipients: null,
|
||||
MessageIDs: ['3333333333333333333333'],
|
||||
Type: '',
|
||||
MessageSender: '',
|
||||
},
|
||||
},
|
||||
me: {
|
||||
id: '444444444444@c.us',
|
||||
lid: '144444444444444@lid',
|
||||
jid: '444444444444:42@s.whatsapp.net',
|
||||
pushName: '',
|
||||
},
|
||||
environment: {
|
||||
version: '2025.10.4',
|
||||
engine: 'GOWS',
|
||||
tier: 'PLUS',
|
||||
browser: null,
|
||||
},
|
||||
engine: 'GOWS' as WAHAEngine,
|
||||
},
|
||||
NOWEB: {
|
||||
id: 'evt_00000000000000000000000000',
|
||||
session: 'default',
|
||||
event: 'message.ack',
|
||||
payload: {
|
||||
id: 'true_11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
||||
from: '11111111111@c.us',
|
||||
fromMe: true,
|
||||
ack: 2,
|
||||
ackName: 'DEVICE',
|
||||
},
|
||||
metadata: {},
|
||||
me: {
|
||||
id: '444444444444@c.us',
|
||||
pushName: '',
|
||||
lid: '1144444444444444@lid',
|
||||
},
|
||||
engine: 'NOWEB',
|
||||
environment: {
|
||||
version: '2025.10.4',
|
||||
engine: 'NOWEB',
|
||||
tier: 'PLUS',
|
||||
browser: null,
|
||||
},
|
||||
},
|
||||
WEBJS: {
|
||||
id: 'evt_00000000000000000000000000',
|
||||
session: 'default',
|
||||
event: 'message.ack',
|
||||
payload: {
|
||||
id: 'true_11111111111@c.us_AAA',
|
||||
from: '444444444444@c.us',
|
||||
fromMe: true,
|
||||
source: 'app',
|
||||
to: '11111111111@c.us',
|
||||
body: 'Nn',
|
||||
hasMedia: false,
|
||||
media: null,
|
||||
ack: 2,
|
||||
ackName: 'DEVICE',
|
||||
vCards: [],
|
||||
_data: {
|
||||
id: {
|
||||
fromMe: true,
|
||||
remote: '11111111111@c.us',
|
||||
id: 'AAA',
|
||||
_serialized: 'true_11111111111@c.us_AAA',
|
||||
},
|
||||
from: '444444444444@c.us',
|
||||
to: '11111111111@c.us',
|
||||
author: '444444444444@c.us',
|
||||
ack: 2,
|
||||
},
|
||||
},
|
||||
metadata: {},
|
||||
me: {
|
||||
id: '444444444444@c.us',
|
||||
pushName: '',
|
||||
},
|
||||
engine: 'WEBJS',
|
||||
environment: {
|
||||
version: '2025.10.4',
|
||||
engine: 'WEBJS',
|
||||
tier: 'PLUS',
|
||||
browser: '/usr/bin/google-chrome-stable',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Me read Participant message on another device (READ ack)',
|
||||
expected: false,
|
||||
GOWS: {
|
||||
id: 'evt_00000000000000000000000000',
|
||||
session: 'default',
|
||||
event: 'message.ack' as WAHAEvents,
|
||||
payload: {
|
||||
id: 'false_11111111111@c.us_3333333333333333333333',
|
||||
from: '11111111111@c.us',
|
||||
to: null,
|
||||
participant: null,
|
||||
fromMe: false,
|
||||
ack: 3,
|
||||
ackName: 'READ',
|
||||
_data: {
|
||||
Chat: '11111111111@s.whatsapp.net',
|
||||
Sender: '444444444444@s.whatsapp.net',
|
||||
IsFromMe: true,
|
||||
IsGroup: false,
|
||||
AddressingMode: '',
|
||||
SenderAlt: '',
|
||||
RecipientAlt: '',
|
||||
BroadcastListOwner: '',
|
||||
BroadcastRecipients: null,
|
||||
MessageIDs: ['3333333333333333333333'],
|
||||
Type: 'read',
|
||||
MessageSender: '11111111111@s.whatsapp.net',
|
||||
},
|
||||
},
|
||||
metadata: {},
|
||||
me: {
|
||||
id: '444444444444@c.us',
|
||||
lid: '144444444444444@lid',
|
||||
jid: '444444444444:42@s.whatsapp.net',
|
||||
pushName: '',
|
||||
},
|
||||
environment: {
|
||||
version: '2025.10.4',
|
||||
engine: 'GOWS',
|
||||
tier: 'PLUS',
|
||||
browser: null,
|
||||
},
|
||||
engine: 'GOWS' as WAHAEngine,
|
||||
},
|
||||
NOWEB: {
|
||||
id: 'evt_00000000000000000000000000',
|
||||
session: 'default',
|
||||
event: 'message.ack',
|
||||
payload: {
|
||||
id: '11111111111@c.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
||||
from: '11111111111@c.us',
|
||||
fromMe: false,
|
||||
ack: 3,
|
||||
ackName: 'READ',
|
||||
},
|
||||
metadata: {},
|
||||
me: {
|
||||
id: '444444444444@c.us',
|
||||
pushName: '',
|
||||
lid: '1144444444444444@lid',
|
||||
},
|
||||
engine: 'NOWEB',
|
||||
environment: {
|
||||
version: '2025.10.4',
|
||||
engine: 'NOWEB',
|
||||
tier: 'PLUS',
|
||||
browser: null,
|
||||
},
|
||||
},
|
||||
WEBJS: null,
|
||||
},
|
||||
{
|
||||
name: 'Participant read My Group Message (READ ack)',
|
||||
expected: false,
|
||||
GOWS: {
|
||||
id: 'evt_00000000000000000000000000',
|
||||
session: 'default',
|
||||
payload: {
|
||||
id: 'true_222222222222222222@g.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_444444444444@c.us',
|
||||
from: '222222222222222222@g.us',
|
||||
to: '011111111111111@lid',
|
||||
participant: '011111111111111@lid',
|
||||
fromMe: true,
|
||||
ack: 3,
|
||||
ackName: 'READ',
|
||||
_data: {
|
||||
Chat: '222222222222222222@g.us',
|
||||
Sender: '011111111111111@lid',
|
||||
IsFromMe: false,
|
||||
IsGroup: true,
|
||||
AddressingMode: '',
|
||||
SenderAlt: '',
|
||||
RecipientAlt: '',
|
||||
BroadcastListOwner: '',
|
||||
BroadcastRecipients: null,
|
||||
MessageIDs: ['AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'],
|
||||
Type: 'read',
|
||||
MessageSender: '',
|
||||
},
|
||||
},
|
||||
metadata: {},
|
||||
me: {
|
||||
id: '444444444444@c.us',
|
||||
lid: '144444444444444@lid',
|
||||
jid: '444444444444:42@s.whatsapp.net',
|
||||
pushName: '',
|
||||
},
|
||||
environment: {
|
||||
version: '2025.10.4',
|
||||
engine: 'GOWS',
|
||||
tier: 'PLUS',
|
||||
browser: null,
|
||||
},
|
||||
},
|
||||
NOWEB: {
|
||||
id: 'evt_00000000000000000000000000',
|
||||
session: 'default',
|
||||
event: 'message.ack',
|
||||
payload: {
|
||||
id: 'true_222222222222222222@g.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_444444444444@c.us',
|
||||
from: '222222222222222222@g.us',
|
||||
to: '222222222222222222@g.us',
|
||||
participant: '011111111111111@lid',
|
||||
fromMe: true,
|
||||
ack: 3,
|
||||
ackName: 'READ',
|
||||
_data: {
|
||||
key: {
|
||||
remoteJid: '222222222222222222@g.us',
|
||||
id: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
||||
fromMe: true,
|
||||
participant: '011111111111111@lid',
|
||||
},
|
||||
receipt: {
|
||||
userJid: '011111111111111@lid',
|
||||
},
|
||||
},
|
||||
},
|
||||
metadata: {},
|
||||
me: {
|
||||
id: '444444444444@c.us',
|
||||
pushName: '',
|
||||
lid: '1144444444444444@lid',
|
||||
},
|
||||
engine: 'NOWEB',
|
||||
environment: {
|
||||
version: '2025.10.4',
|
||||
engine: 'NOWEB',
|
||||
tier: 'PLUS',
|
||||
browser: null,
|
||||
},
|
||||
},
|
||||
WEBJS: {
|
||||
id: 'evt_00000000000000000000000000',
|
||||
session: 'default',
|
||||
event: 'message.ack',
|
||||
payload: {
|
||||
id: 'true_222222222222222222@g.us_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA_444444444444@c.us',
|
||||
from: '222222222222222222@g.us',
|
||||
to: '222222222222222222@g.us',
|
||||
participant: '011111111111111@lid',
|
||||
fromMe: false,
|
||||
ack: 3,
|
||||
ackName: 'READ',
|
||||
_data: {
|
||||
tag: 'receipt',
|
||||
attrs: {
|
||||
from: {
|
||||
$1: {
|
||||
type: 0,
|
||||
user: '222222222222222222',
|
||||
server: 'g.us',
|
||||
},
|
||||
},
|
||||
type: 'read',
|
||||
id: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
||||
participant: {
|
||||
$1: {
|
||||
type: 1,
|
||||
user: '011111111111111',
|
||||
device: 0,
|
||||
domainType: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
content: null,
|
||||
},
|
||||
},
|
||||
metadata: {},
|
||||
me: {
|
||||
id: '444444444444@c.us',
|
||||
pushName: '',
|
||||
},
|
||||
engine: 'WEBJS',
|
||||
environment: {
|
||||
version: '2025.10.4',
|
||||
engine: 'WEBJS',
|
||||
tier: 'PLUS',
|
||||
browser: '/usr/bin/google-chrome-stable',
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
describe('ShouldMarkAsReadInChatWoot', () => {
|
||||
const engines = ['GOWS', 'NOWEB', 'WEBJS'];
|
||||
for (const engine of engines) {
|
||||
describe(engine, () => {
|
||||
for (const param of ShouldMarkAsReadCases) {
|
||||
const name = `[${param.expected}] ${param.name}`;
|
||||
const event = param[engine];
|
||||
const testfn = event ? test : test.skip;
|
||||
const expected = param.expected;
|
||||
testfn(name, () => {
|
||||
// Test
|
||||
const result = ShouldMarkAsReadInChatWoot(event);
|
||||
expect(result).toBe(expected);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { WAHAWebhookMessageAck } from '@waha/structures/webhooks.dto';
|
||||
import { isJidCusFormat } from '@waha/utils/wa';
|
||||
import { WAMessageAck } from '@waha/structures/enums.dto';
|
||||
import { isLidUser, toCusFormat } from '@waha/core/utils/jids';
|
||||
|
||||
export function ShouldMarkAsReadInChatWoot(
|
||||
event: WAHAWebhookMessageAck,
|
||||
): boolean {
|
||||
// Mark as seen only if it's DM
|
||||
// Ignore groups and other multiple participants chats
|
||||
const chatId = event.payload.from;
|
||||
if (!isJidCusFormat(chatId) && !isLidUser(chatId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const payload = event.payload;
|
||||
// Only READ and PLAYED
|
||||
const read = payload.ack === WAMessageAck.READ;
|
||||
const played = payload.ack == WAMessageAck.PLAYED;
|
||||
if (!read && !played) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only process when OUR message (fromMe: true) was read by recipient
|
||||
if (!payload.fromMe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mark ChatWoot conversation as read when recipient reads our message
|
||||
return true;
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
LocationMessage,
|
||||
MessageToChatWootConverter,
|
||||
PollMessage,
|
||||
ListMessage,
|
||||
ShareContactMessage,
|
||||
TextMessage,
|
||||
UnsupportedMessage,
|
||||
@@ -104,6 +105,12 @@ class MessageAnyHandler extends MessageBaseHandler<WAMessage> {
|
||||
return msg;
|
||||
}
|
||||
|
||||
converter = new ListMessage(this.l);
|
||||
msg = await converter.convert(payload, protoMessage);
|
||||
if (msg) {
|
||||
return msg;
|
||||
}
|
||||
|
||||
converter = new EventMessage(this.l);
|
||||
msg = await converter.convert(payload, protoMessage);
|
||||
if (msg) {
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇦🇪 العربية (Arabic)'
|
||||
# تستخدمه WAHA لعرض الأرقام والعملات والتاريخ/الوقت
|
||||
locale.base: 'ar-AE'
|
||||
|
||||
app.inbox.contact.name: 'تكامل واتساب (WAHA)'
|
||||
app.inbox.contact.name: 'تكامل واتساب'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# "options" من date.toLocaleString
|
||||
@@ -283,6 +283,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇧🇩 বাংলা (Bengali)'
|
||||
# WAHA এটি সংখ্যা, মুদ্রা এবং তারিখ/সময়ের ফরম্যাটিংয়ে ব্যবহার করে।
|
||||
locale.base: 'bn-BD'
|
||||
|
||||
app.inbox.contact.name: 'হোয়াটসঅ্যাপ ইন্টিগ্রেশন (WAHA)'
|
||||
app.inbox.contact.name: 'হোয়াটসঅ্যাপ ইন্টিগ্রেশন'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# date.toLocaleString এর "options"
|
||||
@@ -283,6 +283,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇩🇪 Deutsch (German)'
|
||||
# WAHA nutzt ihn zur Darstellung von Zahlen, Währungen sowie Datum und Uhrzeit
|
||||
locale.base: 'de-DE'
|
||||
|
||||
app.inbox.contact.name: 'WhatsApp Integration (WAHA)'
|
||||
app.inbox.contact.name: 'WhatsApp Integration'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# "Optionen" von date.toLocaleString
|
||||
@@ -286,6 +286,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇺🇸 English (English)'
|
||||
# WAHA uses it for number, currency and datetime representation
|
||||
locale.base: 'en-US'
|
||||
|
||||
app.inbox.contact.name: 'WhatsApp Integration (WAHA)'
|
||||
app.inbox.contact.name: 'WhatsApp Integration'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# "options" from date.toLocaleString
|
||||
@@ -160,6 +160,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇪🇸 Español (Spanish)'
|
||||
# WAHA lo utiliza para formatear números, moneda y fecha/hora
|
||||
locale.base: 'es-ES'
|
||||
|
||||
app.inbox.contact.name: 'Integración de WhatsApp (WAHA)'
|
||||
app.inbox.contact.name: 'Integración de WhatsApp'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# "opciones" de date.toLocaleString
|
||||
@@ -286,6 +286,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇮🇷 فارسی (Persian)'
|
||||
# WAHA از آن برای نمایش اعداد، ارز و تاریخ/زمان استفاده میکند
|
||||
locale.base: 'fa-IR'
|
||||
|
||||
app.inbox.contact.name: 'ادغام واتساپ (WAHA)'
|
||||
app.inbox.contact.name: 'ادغام واتساپ'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# گزینههای "options" از date.toLocaleString
|
||||
@@ -283,6 +283,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇫🇷 Français (French)'
|
||||
# WAHA l'utilise pour le formatage des nombres, devises et dates/heures
|
||||
locale.base: 'fr-FR'
|
||||
|
||||
app.inbox.contact.name: 'Intégration WhatsApp (WAHA)'
|
||||
app.inbox.contact.name: 'Intégration WhatsApp'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# "options" de date.toLocaleString
|
||||
@@ -283,6 +283,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇮🇱 עברית (Hebrew)'
|
||||
# WAHA משתמש בכך להצגת מספרים, מטבע ותאריך/שעה
|
||||
locale.base: 'he-IL'
|
||||
|
||||
app.inbox.contact.name: 'אינטגרציית וואטסאפ (WAHA)'
|
||||
app.inbox.contact.name: 'אינטגרציית וואטסאפ'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# "אפשרויות" של date.toLocaleString
|
||||
@@ -283,6 +283,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇮🇳 हिंदी (Hindi)'
|
||||
# WAHA इसे संख्याएँ, मुद्रा और दिनांक/समय प्रदर्शित करने के लिए उपयोग करता है।
|
||||
locale.base: 'hi-IN'
|
||||
|
||||
app.inbox.contact.name: 'व्हाट्सएप इंटीग्रेशन (WAHA)'
|
||||
app.inbox.contact.name: 'व्हाट्सएप इंटीग्रेशन'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# date.toLocaleString की "options"
|
||||
@@ -283,6 +283,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇮🇩 Bahasa Indonesia (Indonesian)'
|
||||
# WAHA menggunakannya untuk format angka, mata uang, dan tanggal/waktu
|
||||
locale.base: 'id-ID'
|
||||
|
||||
app.inbox.contact.name: 'Integrasi WhatsApp (WAHA)'
|
||||
app.inbox.contact.name: 'Integrasi WhatsApp'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# "opsi" dari date.toLocaleString
|
||||
@@ -283,6 +283,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇵🇰 ਪੰਜਾਬੀ (Punjabi)'
|
||||
# WAHA ਇਸਨੂੰ ਅੰਕ, ਕਰੰਸੀ ਅਤੇ ਤਾਰੀਖ/ਸਮੇਂ ਦੀ ਨਮਾਇਸ਼ ਲਈ ਵਰਤਦਾ ਹੈ
|
||||
locale.base: 'pa-PK'
|
||||
|
||||
app.inbox.contact.name: 'ਵਟਸਐਪ ਇੰਟੀਗ੍ਰੇਸ਼ਨ (WAHA)'
|
||||
app.inbox.contact.name: 'ਵਟਸਐਪ ਇੰਟੀਗ੍ਰੇਸ਼ਨ'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# date.toLocaleString ਦੀਆਂ "options"
|
||||
@@ -283,6 +283,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇧🇷🇵🇹 Português (Portuguese)'
|
||||
# A WAHA usa isso para formatar números, moeda e data/hora
|
||||
locale.base: 'pt-BR'
|
||||
|
||||
app.inbox.contact.name: 'Integração WhatsApp (WAHA)'
|
||||
app.inbox.contact.name: 'Integração WhatsApp'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# "opções" de date.toLocaleString
|
||||
@@ -286,6 +286,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇷🇺 Русский (Russian)'
|
||||
# WAHA использует его для форматирования чисел, валют и даты/времени
|
||||
locale.base: 'ru-RU'
|
||||
|
||||
app.inbox.contact.name: 'WhatsApp Интеграция (WAHA)'
|
||||
app.inbox.contact.name: 'WhatsApp Интеграция'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# "параметры" из date.toLocaleString
|
||||
@@ -283,6 +283,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇹🇷 Türkçe (Turkish)'
|
||||
# WAHA bunu sayı, para birimi ve tarih/saat gösterimi için kullanır
|
||||
locale.base: 'tr-TR'
|
||||
|
||||
app.inbox.contact.name: 'WhatsApp Entegrasyonu (WAHA)'
|
||||
app.inbox.contact.name: 'WhatsApp Entegrasyonu'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# date.toLocaleString için "options"
|
||||
@@ -283,6 +283,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇺🇦 Українська (Ukrainian)'
|
||||
# WAHA використовує його для форматування чисел, валют і дати/часу
|
||||
locale.base: 'uk-UA'
|
||||
|
||||
app.inbox.contact.name: 'Інтеграція WhatsApp (WAHA)'
|
||||
app.inbox.contact.name: 'Інтеграція WhatsApp'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# "параметри" з date.toLocaleString
|
||||
@@ -283,6 +283,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -6,7 +6,7 @@ locale.name: '🇵🇰 اردو (Urdu)'
|
||||
# WAHA اسے نمبرز، کرنسی اور تاریخ/وقت کی نمائندگی کے لیے استعمال کرتا ہے۔
|
||||
locale.base: 'ur-PK'
|
||||
|
||||
app.inbox.contact.name: 'واٹس ایپ انٹیگریشن (WAHA)'
|
||||
app.inbox.contact.name: 'واٹس ایپ انٹیگریشن'
|
||||
app.inbox.contact.avatar.url: 'https://raw.githubusercontent.com/devlikeapro/waha/core/logo.png'
|
||||
|
||||
# date.toLocaleString کی "options"
|
||||
@@ -283,6 +283,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -285,6 +285,34 @@ whatsapp.to.chatwoot.message.poll: |-
|
||||
{{/options}}
|
||||
{{/poll}}
|
||||
|
||||
whatsapp.to.chatwoot.message.list: |-
|
||||
{{#message.listMessage}}
|
||||
{{#title}}
|
||||
*{{{title}}}*
|
||||
{{/title}}
|
||||
{{#description}}
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{{#footerText}}
|
||||
{{{footerText}}}
|
||||
{{/footerText}}
|
||||
|
||||
{{#buttonText}}
|
||||
{{{buttonText}}}
|
||||
{{/buttonText}}
|
||||
{{#sections}}
|
||||
{{#title}}
|
||||
{{{title}}}:
|
||||
{{/title}}
|
||||
{{#rows}}
|
||||
{{#title}}
|
||||
- {{{title}}}
|
||||
{{/title}}
|
||||
{{/rows}}
|
||||
|
||||
{{/sections}}
|
||||
{{/message.listMessage}}
|
||||
|
||||
whatsapp.to.chatwoot.message.event: |-
|
||||
{{#message}}
|
||||
{{#eventMessage}}
|
||||
|
||||
@@ -56,6 +56,7 @@ export enum TKey {
|
||||
WA_TO_CW_MESSAGE_PIX = 'whatsapp.to.chatwoot.message.pix',
|
||||
WA_TO_CW_MESSAGE_UNSUPPORTED = 'whatsapp.to.chatwoot.message.unsupported',
|
||||
WA_TO_CW_MESSAGE_FACEBOOK_AD = 'whatsapp.to.chatwoot.message.facebook.ad',
|
||||
WA_TO_CW_MESSAGE_LIST = 'whatsapp.to.chatwoot.message.list',
|
||||
|
||||
//
|
||||
// App Inbox
|
||||
@@ -174,6 +175,10 @@ export type TemplatePayloads = {
|
||||
eventMessage: Record<string, unknown>;
|
||||
};
|
||||
};
|
||||
[TKey.WA_TO_CW_MESSAGE_LIST]: {
|
||||
payload: WAMessage;
|
||||
message: proto.Message;
|
||||
};
|
||||
[TKey.WA_TO_CW_MESSAGE_PIX]: {
|
||||
payload: WAMessage;
|
||||
message: proto.Message | null;
|
||||
|
||||
@@ -11,7 +11,8 @@ import { WhatsappToMarkdown } from '@waha/apps/chatwoot/messages/to/chatwoot/uti
|
||||
import { WAMessage } from '@waha/structures/responses.dto';
|
||||
import type { proto } from '@adiwajshing/baileys';
|
||||
import * as lodash from 'lodash';
|
||||
import { fetchBuffer } from '@waha/core/abc/session.abc';
|
||||
|
||||
import { fetchBuffer } from '@waha/utils/fetch';
|
||||
|
||||
export class FacebookAdMessage implements MessageToChatWootConverter {
|
||||
constructor(
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import { ChatWootMessagePartial } from '@waha/apps/chatwoot/consumers/waha/base';
|
||||
import { Locale } from '@waha/apps/chatwoot/i18n/locale';
|
||||
import { TKey } from '@waha/apps/chatwoot/i18n/templates';
|
||||
import { MessageToChatWootConverter } from '@waha/apps/chatwoot/messages/to/chatwoot';
|
||||
import { isEmptyString } from '@waha/apps/chatwoot/messages/to/chatwoot/utils/proto';
|
||||
import { WhatsappToMarkdown } from '@waha/apps/chatwoot/messages/to/chatwoot/utils/markdown';
|
||||
import * as lodash from 'lodash';
|
||||
import type { proto } from '@adiwajshing/baileys';
|
||||
import { WAMessage } from '@waha/structures/responses.dto';
|
||||
|
||||
export class ListMessage implements MessageToChatWootConverter {
|
||||
constructor(private readonly locale: Locale) {}
|
||||
|
||||
convert(
|
||||
payload: WAMessage,
|
||||
protoMessage: proto.Message | null,
|
||||
): ChatWootMessagePartial | null {
|
||||
const listMessage = protoMessage?.listMessage;
|
||||
if (lodash.isEmpty(listMessage)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const content = this.locale
|
||||
.key(TKey.WA_TO_CW_MESSAGE_LIST)
|
||||
.r({ payload, message: protoMessage as proto.Message });
|
||||
|
||||
if (isEmptyString(content)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
content: WhatsappToMarkdown(content),
|
||||
attachments: [],
|
||||
private: undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -116,8 +116,7 @@ describe('PixMessage - pt-BR', () => {
|
||||
****Tipo:**** PHONE
|
||||
****Referência:**** 4TB11111111
|
||||
|
||||
💳 ****PIX Copia e Cola enviado****
|
||||
`;
|
||||
💳 ****PIX Copia e Cola enviado****`;
|
||||
|
||||
expect(protoMessage).not.toBeNull();
|
||||
expect(result).not.toBeNull();
|
||||
@@ -237,8 +236,7 @@ describe('PixMessage - pt-BR', () => {
|
||||
****Valor:**** R$\u00A025,12
|
||||
****Referência:**** 4TB11111111
|
||||
|
||||
💳 ****PIX Copia e Cola enviado****
|
||||
`;
|
||||
💳 ****PIX Copia e Cola enviado****`;
|
||||
|
||||
expect(protoMessage).not.toBeNull();
|
||||
expect(result).not.toBeNull();
|
||||
|
||||
@@ -12,6 +12,7 @@ export { FacebookAdMessage } from './FacebookAdMessage';
|
||||
export { PollMessage } from './PollMessage';
|
||||
export { EventMessage } from './EventMessage';
|
||||
export { PixMessage } from './PixMessage';
|
||||
export { ListMessage } from './ListMessage';
|
||||
|
||||
export type Awaitable<T> = T | Promise<T>;
|
||||
|
||||
|
||||
@@ -14,4 +14,43 @@ describe('WhatsappToMarkdown', () => {
|
||||
const expected = `**bold** | *italic* | ~~strike~~ | \`one line code\` | \`\`\`\nmultiple lines\`\`\` `;
|
||||
expect(WhatsappToMarkdown(input)).toBe(expected);
|
||||
});
|
||||
|
||||
// Tests for URL protection
|
||||
it('preserves URLs with single underscore', () => {
|
||||
const input = 'https://example.com/page_name';
|
||||
expect(WhatsappToMarkdown(input)).toBe('https://example.com/page_name');
|
||||
});
|
||||
|
||||
it('preserves URLs with double underscores', () => {
|
||||
const input = 'https://en.wikipedia.org/wiki/Sarah_Jessica_Parker';
|
||||
expect(WhatsappToMarkdown(input)).toBe(
|
||||
'https://en.wikipedia.org/wiki/Sarah_Jessica_Parker',
|
||||
);
|
||||
});
|
||||
|
||||
it('preserves URLs with multiple underscores', () => {
|
||||
const input = 'https://example.com/a_b_c_test';
|
||||
expect(WhatsappToMarkdown(input)).toBe('https://example.com/a_b_c_test');
|
||||
});
|
||||
|
||||
it('handles mixed text with URLs and formatting', () => {
|
||||
const input = 'Veja *isso* em https://example.com/test_link e _aquilo_';
|
||||
const expected =
|
||||
'Veja **isso** em https://example.com/test_link e *aquilo*';
|
||||
expect(WhatsappToMarkdown(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it('handles multiple URLs in same text', () => {
|
||||
const input =
|
||||
'Links: https://example.com/page_1 e https://example.com/page_2';
|
||||
expect(WhatsappToMarkdown(input)).toBe(
|
||||
'Links: https://example.com/page_1 e https://example.com/page_2',
|
||||
);
|
||||
});
|
||||
|
||||
it('handles URLs with underscores and regular italic formatting', () => {
|
||||
const input = 'URL: https://example.com/test_page e texto _em itálico_';
|
||||
const expected = 'URL: https://example.com/test_page e texto *em itálico*';
|
||||
expect(WhatsappToMarkdown(input)).toBe(expected);
|
||||
});
|
||||
});
|
||||
@@ -1,3 +1,5 @@
|
||||
import { UrlProtection } from '@waha/apps/chatwoot/messages/to/markdown';
|
||||
|
||||
export function WhatsappToMarkdown(text: string): string {
|
||||
if (!text) {
|
||||
return text;
|
||||
@@ -5,13 +7,22 @@ export function WhatsappToMarkdown(text: string): string {
|
||||
if (text == '') {
|
||||
return '';
|
||||
}
|
||||
return (
|
||||
text
|
||||
// Bold: *bold* → **bold**
|
||||
.replace(/\*(.*?)\*/g, '**$1**')
|
||||
// Strikethrough: ~strike~ → ~~strike~~
|
||||
.replace(/~(.*?)~/g, '~~$1~~')
|
||||
// Italic: _italic_ → *italic*
|
||||
.replace(/_(.*?)_/g, '*$1*')
|
||||
);
|
||||
|
||||
// Extract and protect URLs before formatting transformations
|
||||
const protection = new UrlProtection();
|
||||
const urls = protection.protect(text);
|
||||
text = urls.text;
|
||||
|
||||
// Apply markdown transformations to "clean" text
|
||||
let result = text
|
||||
// Bold: *bold* → **bold**
|
||||
.replace(/\*(.*?)\*/g, '**$1**')
|
||||
// Strikethrough: ~strike~ → ~~strike~~
|
||||
.replace(/~(.*?)~/g, '~~$1~~')
|
||||
// Italic: _italic_ → *italic*
|
||||
.replace(/_(.*?)_/g, '*$1*');
|
||||
|
||||
// Restore original URLs after all transformations
|
||||
result = urls.restore(result);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
const DEFAULT_PLACEHOLDER_PREFIX = 'URLPLACEHOLDER';
|
||||
const URL_REGEX = /https?:\/\/[^\s]+/g;
|
||||
|
||||
export class UrlProtection {
|
||||
/** Replaces URLs with placeholders so downstream formatters don't touch them. */
|
||||
constructor(
|
||||
private readonly placeholder: string = DEFAULT_PLACEHOLDER_PREFIX,
|
||||
) {}
|
||||
|
||||
protect(text: string): ProtectedUrlText {
|
||||
const urls: string[] = [];
|
||||
const result = text.replace(URL_REGEX, (url) => {
|
||||
const index = urls.length;
|
||||
urls.push(url);
|
||||
return `${this.placeholder}${index}`;
|
||||
});
|
||||
|
||||
return new ProtectedUrlText(result, urls, this.placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
export class ProtectedUrlText {
|
||||
/** Carries protected text and restores URLs back into place. */
|
||||
constructor(
|
||||
public text: string,
|
||||
private readonly urls: string[],
|
||||
private readonly placeholder: string,
|
||||
) {}
|
||||
|
||||
restore(text: string = this.text): string {
|
||||
return this.urls.reduce((acc, url, index) => {
|
||||
const placeholder = `${this.placeholder}${index}`;
|
||||
return acc.replace(placeholder, url);
|
||||
}, text);
|
||||
}
|
||||
}
|
||||
@@ -14,4 +14,41 @@ describe('MarkdownToWhatsApp', () => {
|
||||
const expected = `Here is a code block:\n\`\`\`some code\`\`\`\n*bold* _italic_ ~strike~ example (http://example.com)\n* item`;
|
||||
expect(MarkdownToWhatsApp(input)).toBe(expected);
|
||||
});
|
||||
|
||||
// Tests for URL protection
|
||||
it('preserves URLs with multiple underscores', () => {
|
||||
const input = 'https://example.com/page__name__test';
|
||||
expect(MarkdownToWhatsApp(input)).toBe(
|
||||
'https://example.com/page__name__test',
|
||||
);
|
||||
});
|
||||
|
||||
it('preserves URLs with double underscores', () => {
|
||||
const input = 'https://en.wikipedia.org/wiki/Sarah_Jessica_Parker';
|
||||
expect(MarkdownToWhatsApp(input)).toBe(
|
||||
'https://en.wikipedia.org/wiki/Sarah_Jessica_Parker',
|
||||
);
|
||||
});
|
||||
|
||||
it('preserves URLs inside markdown links', () => {
|
||||
const input =
|
||||
'Veja [perfil](https://en.wikipedia.org/wiki/Sarah_Jessica_Parker)';
|
||||
const expected =
|
||||
'Veja perfil (https://en.wikipedia.org/wiki/Sarah_Jessica_Parker)';
|
||||
expect(MarkdownToWhatsApp(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it('handles mixed text with URLs and formatting', () => {
|
||||
const input = 'Veja **isso** em https://example.com/test_link e _aquilo_';
|
||||
const expected = 'Veja *isso* em https://example.com/test_link e _aquilo_';
|
||||
expect(MarkdownToWhatsApp(input)).toBe(expected);
|
||||
});
|
||||
|
||||
it('handles multiple URLs in the same text', () => {
|
||||
const input =
|
||||
'Links: https://example.com/page_1 e https://example.com/page_2';
|
||||
expect(MarkdownToWhatsApp(input)).toBe(
|
||||
'Links: https://example.com/page_1 e https://example.com/page_2',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -11,13 +11,14 @@ import {
|
||||
} from '@waha/structures/chatting.dto';
|
||||
import { SessionInfo } from '@waha/structures/sessions.dto';
|
||||
import axios, { AxiosInstance } from 'axios';
|
||||
import { Auth } from '@waha/core/auth/config';
|
||||
|
||||
export class WAHASelf {
|
||||
public client: AxiosInstance;
|
||||
|
||||
constructor() {
|
||||
// Set 'X-Api-Key'
|
||||
const key = process.env.WAHA_API_KEY_PLAIN;
|
||||
const key = Auth.keyplain.value;
|
||||
const port =
|
||||
parseInt(process.env.PORT) ||
|
||||
parseInt(process.env.WHATSAPP_API_PORT) ||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { IgnoreJidConfig } from '@waha/core/utils/jids';
|
||||
|
||||
import { parseBool } from './helpers';
|
||||
import { WebhookConfig } from './structures/webhooks.config.dto';
|
||||
import { Auth } from '@waha/core/auth/config';
|
||||
|
||||
@Injectable()
|
||||
export class WhatsappConfigService implements OnApplicationBootstrap {
|
||||
@@ -139,10 +140,7 @@ export class WhatsappConfigService implements OnApplicationBootstrap {
|
||||
}
|
||||
|
||||
getApiKey(): string | undefined {
|
||||
return (
|
||||
this.configService.get('WHATSAPP_API_KEY', '') ||
|
||||
this.configService.get('WAHA_API_KEY', '')
|
||||
);
|
||||
return Auth.key.value;
|
||||
}
|
||||
|
||||
getExcludedPaths(): string[] {
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
import { MessagesForRead } from '@waha/core/utils/convertors';
|
||||
import {
|
||||
IgnoreJidConfig,
|
||||
isJidNewsletter,
|
||||
isJidBroadcast,
|
||||
isJidNewsletter,
|
||||
JidFilter,
|
||||
} from '@waha/core/utils/jids';
|
||||
import {
|
||||
@@ -43,7 +43,6 @@ import { complete } from '@waha/utils/reactive/complete';
|
||||
import { SwitchObservable } from '@waha/utils/reactive/SwitchObservable';
|
||||
import axios from 'axios';
|
||||
import axiosRetry from 'axios-retry';
|
||||
import { Agent as HttpsAgent } from 'https';
|
||||
import * as fs from 'fs';
|
||||
import * as lodash from 'lodash';
|
||||
import * as NodeCache from 'node-cache';
|
||||
@@ -129,6 +128,7 @@ import {
|
||||
import { IMediaManager } from '../media/IMediaManager';
|
||||
import { QR } from '../QR';
|
||||
import { DataStore } from './DataStore';
|
||||
import { fetchBuffer } from '@waha/utils/fetch';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const qrcode = require('qrcode-terminal');
|
||||
@@ -1081,21 +1081,6 @@ export abstract class WhatsappSession {
|
||||
}
|
||||
}
|
||||
|
||||
const InsecureHttpsAgent = new HttpsAgent({
|
||||
rejectUnauthorized: false,
|
||||
});
|
||||
|
||||
export async function fetchBuffer(url: string): Promise<Buffer> {
|
||||
return axios
|
||||
.get(url, {
|
||||
responseType: 'arraybuffer',
|
||||
httpsAgent: InsecureHttpsAgent,
|
||||
})
|
||||
.then((res) => {
|
||||
return Buffer.from(res.data);
|
||||
});
|
||||
}
|
||||
|
||||
export function getGroupInviteLink(code: string) {
|
||||
if (code.startsWith('https://')) {
|
||||
return code;
|
||||
|
||||
@@ -6,11 +6,15 @@ import {
|
||||
NoAuth,
|
||||
PlainApiKeyAuth,
|
||||
} from '@waha/core/auth/auth';
|
||||
import { ReportGeneratedValue } from '@waha/core/auth/config';
|
||||
|
||||
export function ApiKeyAuthFactory(
|
||||
config: WhatsappConfigService,
|
||||
logger: LoggerService,
|
||||
): IApiKeyAuth {
|
||||
setTimeout(() => {
|
||||
ReportGeneratedValue();
|
||||
}, 4000);
|
||||
const apiKey = config.getApiKey();
|
||||
if (!apiKey) {
|
||||
setTimeout(() => {
|
||||
@@ -36,18 +40,5 @@ export function ApiKeyAuthFactory(
|
||||
}
|
||||
|
||||
// Fallback to plain text
|
||||
setTimeout(() => {
|
||||
logger.warn('⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️');
|
||||
logger.warn(
|
||||
'WARNING: Plain text API key detected. This is a security risk.',
|
||||
);
|
||||
logger.warn(
|
||||
'Your API key can be exposed in environment variables or process lists.',
|
||||
);
|
||||
logger.warn(
|
||||
'For better security, use WAHA_API_KEY=sha512:{SHA512_HASH_FOR_YOUR_API_KEY}',
|
||||
);
|
||||
logger.warn('⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️');
|
||||
}, 2000);
|
||||
return new PlainApiKeyAuth(apiKey);
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
import { parseBool } from '@waha/helpers';
|
||||
|
||||
export interface SValue {
|
||||
param: string;
|
||||
value: string | null;
|
||||
generated: boolean;
|
||||
}
|
||||
|
||||
function rand() {
|
||||
return crypto.randomUUID().toString().replace(/-/g, '');
|
||||
}
|
||||
|
||||
function FromEnv(
|
||||
param: string,
|
||||
skip: boolean,
|
||||
adefault: string,
|
||||
search: any[],
|
||||
): SValue {
|
||||
let value = process.env[param];
|
||||
const common = search.includes(value);
|
||||
if (common && !skip) {
|
||||
// Use generated value for the setting
|
||||
return {
|
||||
param: param,
|
||||
value: adefault,
|
||||
generated: true,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
param: param,
|
||||
value: value,
|
||||
generated: false,
|
||||
};
|
||||
}
|
||||
|
||||
const keys = [
|
||||
'',
|
||||
null,
|
||||
undefined,
|
||||
'123',
|
||||
'321',
|
||||
'waha',
|
||||
'admin',
|
||||
'00000000000000000000000000000000',
|
||||
'11111111111111111111111111111111',
|
||||
'sha512:98b6d128682e280b74b324ca82a6bae6e8a3f7174e0605bfd52eb9948fad8984854ec08f7652f32055c4a9f12b69add4850481d9503a7f2225501671d6124648',
|
||||
];
|
||||
|
||||
const nulls = ['', null, undefined];
|
||||
|
||||
interface UserPassword {
|
||||
username: SValue;
|
||||
password: SValue;
|
||||
}
|
||||
|
||||
export class AuthConfig {
|
||||
public key: SValue;
|
||||
public keyplain: SValue;
|
||||
public dashboard: UserPassword;
|
||||
public swagger: UserPassword;
|
||||
|
||||
constructor() {
|
||||
if (process.env.WHATSAPP_API_KEY) {
|
||||
process.env.WAHA_API_KEY = process.env.WHATSAPP_API_KEY;
|
||||
}
|
||||
this.key = FromEnv(
|
||||
'WAHA_API_KEY',
|
||||
parseBool(process.env.WAHA_NO_API_KEY),
|
||||
rand(),
|
||||
keys,
|
||||
);
|
||||
|
||||
this.keyplain = FromEnv(
|
||||
'WAHA_API_KEY_PLAIN',
|
||||
false,
|
||||
this.key.value?.startsWith('sha512:') ? null : this.key.value,
|
||||
[],
|
||||
);
|
||||
|
||||
this.dashboard = this.getDashboard();
|
||||
this.swagger = this.getSwagger();
|
||||
}
|
||||
|
||||
private getDashboard(): UserPassword {
|
||||
const password = FromEnv(
|
||||
'WAHA_DASHBOARD_PASSWORD',
|
||||
parseBool(process.env.WAHA_DASHBOARD_NO_PASSWORD),
|
||||
rand(),
|
||||
keys,
|
||||
);
|
||||
const username = FromEnv(
|
||||
'WAHA_DASHBOARD_USERNAME',
|
||||
false,
|
||||
'admin',
|
||||
password.value ? nulls : [],
|
||||
);
|
||||
return {
|
||||
username: username,
|
||||
password: password,
|
||||
};
|
||||
}
|
||||
|
||||
private getSwagger(): UserPassword {
|
||||
const password = FromEnv(
|
||||
'WHATSAPP_SWAGGER_PASSWORD',
|
||||
parseBool(process.env.WHATSAPP_SWAGGER_NO_PASSWORD),
|
||||
this.dashboard.password.value,
|
||||
keys,
|
||||
);
|
||||
const username = FromEnv(
|
||||
'WHATSAPP_SWAGGER_USERNAME',
|
||||
false,
|
||||
'admin',
|
||||
password.value ? nulls : [],
|
||||
);
|
||||
return {
|
||||
username: username,
|
||||
password: password,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const Auth = new AuthConfig();
|
||||
|
||||
export function ReportGeneratedValue() {
|
||||
let values = [
|
||||
Auth.key,
|
||||
Auth.dashboard.username,
|
||||
Auth.dashboard.password,
|
||||
Auth.swagger.username,
|
||||
Auth.swagger.password,
|
||||
];
|
||||
values = values.filter((key) => key.generated);
|
||||
if (values.length === 0) {
|
||||
return;
|
||||
}
|
||||
console.warn('');
|
||||
console.warn('⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️');
|
||||
console.warn('Generated credentials (persist to .env or WAHA_* env vars)');
|
||||
console.warn(
|
||||
'Save these values to your environment (.env or WAHA_*) to reuse them; new keys are generated on every start otherwise.',
|
||||
);
|
||||
console.warn('');
|
||||
console.warn("cat <<'EOF' > .env");
|
||||
console.warn('');
|
||||
for (const key of values) {
|
||||
console.warn(`${key.param}=${key.value}`);
|
||||
}
|
||||
console.warn('EOF');
|
||||
console.warn('');
|
||||
console.warn('Generated credentials ready to copy');
|
||||
console.warn('⬆️ ⬆️ ⬆️ ⬆️ ⬆️ ⬆️ ⬆️ ⬆️ ⬆️ ⬆️ ⬆️ ⬆️');
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { ConfigService } from '@nestjs/config';
|
||||
import { InjectPinoLogger, PinoLogger } from 'nestjs-pino';
|
||||
|
||||
import { parseBool } from '../../helpers';
|
||||
import { Auth } from '@waha/core/auth/config';
|
||||
|
||||
@Injectable()
|
||||
export class DashboardConfigServiceCore {
|
||||
@@ -20,8 +21,8 @@ export class DashboardConfigServiceCore {
|
||||
}
|
||||
|
||||
get credentials(): [string, string] | null {
|
||||
const user = this.configService.get('WAHA_DASHBOARD_USERNAME', '');
|
||||
const password = this.configService.get('WAHA_DASHBOARD_PASSWORD', '');
|
||||
const user = Auth.dashboard.username.value || '';
|
||||
const password = Auth.dashboard.password.value || '';
|
||||
if (!user && !password) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ConfigService } from '@nestjs/config';
|
||||
import { InjectPinoLogger, PinoLogger } from 'nestjs-pino';
|
||||
|
||||
import { parseBool } from '../../helpers';
|
||||
import { Auth } from '@waha/core/auth/config';
|
||||
|
||||
@Injectable()
|
||||
export class SwaggerConfigServiceCore {
|
||||
@@ -26,14 +27,8 @@ export class SwaggerConfigServiceCore {
|
||||
}
|
||||
|
||||
get credentials(): [string, string] | undefined {
|
||||
const user = this.configService.get<string>(
|
||||
'WHATSAPP_SWAGGER_USERNAME',
|
||||
undefined,
|
||||
);
|
||||
const password = this.configService.get<string>(
|
||||
'WHATSAPP_SWAGGER_PASSWORD',
|
||||
undefined,
|
||||
);
|
||||
const user = Auth.swagger.username.value;
|
||||
const password = Auth.swagger.password.value;
|
||||
if (!user && !password) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { proto, WAMessageKey } from '@adiwajshing/baileys';
|
||||
import { normalizeMessageContent, WAMessageKey } from '@adiwajshing/baileys';
|
||||
import { proto } from '@adiwajshing/baileys';
|
||||
import * as grpc from '@grpc/grpc-js';
|
||||
import { connectivityState } from '@grpc/grpc-js';
|
||||
import { UnprocessableEntityException } from '@nestjs/common';
|
||||
@@ -166,6 +167,7 @@ import {
|
||||
isLabelUpsertEvent,
|
||||
} from './labels.gows';
|
||||
import esm from '@waha/vendor/esm';
|
||||
import { IsEditedMessage } from '@waha/core/utils/pwa';
|
||||
|
||||
enum WhatsMeowEvent {
|
||||
CONNECTED = 'gows.ConnectedEventData',
|
||||
@@ -491,19 +493,15 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
|
||||
// Handle edited messages
|
||||
const messagesEdited$ = messages$.pipe(
|
||||
filter((msg) => {
|
||||
return (
|
||||
msg?.Message?.protocolMessage?.type === 14 &&
|
||||
msg?.Message?.protocolMessage?.editedMessage !== undefined
|
||||
);
|
||||
}),
|
||||
filter((message) => IsEditedMessage(message.Message)),
|
||||
mergeMap(async (message): Promise<WAMessageEditedBody> => {
|
||||
const waMessage = await this.toWAMessage(message);
|
||||
const content = normalizeMessageContent(message.Message);
|
||||
// Extract the body from editedMessage using extractBody function
|
||||
const body =
|
||||
extractBody(message.Message.protocolMessage.editedMessage) || '';
|
||||
const body = extractBody(content.protocolMessage.editedMessage) || '';
|
||||
// Extract the original message ID from protocolMessage.key
|
||||
const editedMessageId = message.Message.protocolMessage.key?.ID;
|
||||
// @ts-ignore
|
||||
const editedMessageId = content.protocolMessage.key?.ID;
|
||||
return {
|
||||
...waMessage,
|
||||
body: body,
|
||||
@@ -1948,17 +1946,18 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
|
||||
// if there is no text or media message
|
||||
if (!message) return;
|
||||
if (!message.Message) return;
|
||||
// Ignore reactions, we have a dedicated handler for that
|
||||
if (message.Message.reactionMessage) return;
|
||||
// Ignore poll votes, we have a dedicated handler for that
|
||||
if (message.Message.pollUpdateMessage) return;
|
||||
// Ignore event response, we have a dedicated handler for that
|
||||
if (message.Message.encEventResponseMessage) return;
|
||||
// Ignore protocol messages
|
||||
if (message.Message.protocolMessage) return;
|
||||
|
||||
const normalizedContent = esm.b.normalizeMessageContent(message.Message);
|
||||
const contentType = esm.b.getContentType(normalizedContent);
|
||||
const content = esm.b.normalizeMessageContent(message.Message);
|
||||
// Ignore reactions, we have a dedicated handler for that
|
||||
if (content.reactionMessage) return;
|
||||
// Ignore poll votes, we have a dedicated handler for that
|
||||
if (content.pollUpdateMessage) return;
|
||||
// Ignore event response, we have a dedicated handler for that
|
||||
if (content.encEventResponseMessage) return;
|
||||
// Ignore protocol messages
|
||||
if (content.protocolMessage) return;
|
||||
|
||||
const contentType = esm.b.getContentType(content);
|
||||
// Ignore device sent message
|
||||
if (contentType == 'deviceSentMessage') {
|
||||
return;
|
||||
|
||||
@@ -68,12 +68,13 @@ import {
|
||||
} from '@waha/core/exceptions';
|
||||
import { toVcardV3 } from '@waha/core/vcard';
|
||||
import { createAgentProxy } from '@waha/core/helpers.proxy';
|
||||
import type { Agent } from 'https';
|
||||
import { IMediaEngineProcessor } from '@waha/core/media/IMediaEngineProcessor';
|
||||
import { QR } from '@waha/core/QR';
|
||||
import { AckToStatus, StatusToAck } from '@waha/core/utils/acks';
|
||||
import { ExtractMessageKeysForRead } from '@waha/core/utils/convertors';
|
||||
import { parseMessageIdSerialized } from '@waha/core/utils/ids';
|
||||
import { isJidNewsletter, toJID } from '@waha/core/utils/jids';
|
||||
import { isJidNewsletter, toCusFormat, toJID } from '@waha/core/utils/jids';
|
||||
import { DistinctAck } from '@waha/core/utils/reactive';
|
||||
import { flipObject, splitAt } from '@waha/helpers';
|
||||
import { PairingCodeResponse } from '@waha/structures/auth.dto';
|
||||
@@ -178,8 +179,6 @@ import { exclude } from '@waha/utils/reactive/ops/exclude';
|
||||
import { SingleDelayedJobRunner } from '@waha/utils/SingleDelayedJobRunner';
|
||||
import { SinglePeriodicJobRunner } from '@waha/utils/SinglePeriodicJobRunner';
|
||||
import { StatusTracker } from '@waha/utils/StatusTracker';
|
||||
import * as Buffer from 'buffer';
|
||||
import { Agent } from 'https';
|
||||
import * as lodash from 'lodash';
|
||||
import * as NodeCache from 'node-cache';
|
||||
import {
|
||||
@@ -199,6 +198,8 @@ import { INowebStore } from './store/INowebStore';
|
||||
import { NowebPersistentStore } from './store/NowebPersistentStore';
|
||||
import { NowebStorageFactoryCore } from './store/NowebStorageFactoryCore';
|
||||
import { ensureNumber, extractMediaContent } from './utils';
|
||||
import { Agents } from '@waha/core/engines/noweb/types';
|
||||
import { IsEditedMessage } from '@waha/core/utils/pwa';
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const promiseRetry = require('promise-retry');
|
||||
|
||||
@@ -307,7 +308,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
await this.sock?.logout();
|
||||
}
|
||||
|
||||
getSocketConfig(agent, state): Partial<SocketConfig> {
|
||||
getSocketConfig(agents: Agents | undefined, state): Partial<SocketConfig> {
|
||||
const fullSyncEnabled = this.sessionConfig?.noweb?.store?.fullSync || false;
|
||||
const browser = ['Ubuntu', 'Chrome', '20.0.04'] as WABrowserDescription;
|
||||
let markOnlineOnConnect = this.sessionConfig?.noweb?.markOnline;
|
||||
@@ -315,8 +316,11 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
markOnlineOnConnect = true;
|
||||
}
|
||||
return {
|
||||
agent: agent,
|
||||
fetchAgent: agent,
|
||||
agent: agents?.socket,
|
||||
// Baileys types still expect a Node https.Agent here,
|
||||
// but 'undici' fetch requires a Dispatcher.
|
||||
// Cast keeps the compiler satisfied while we pass the ProxyAgent at runtime.
|
||||
fetchAgent: agents?.fetch as unknown as Agent,
|
||||
auth: state,
|
||||
printQRInTerminal: false,
|
||||
browser: browser,
|
||||
@@ -346,9 +350,9 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
this.authNOWEBStore = store;
|
||||
}
|
||||
const { state, saveCreds } = this.authNOWEBStore;
|
||||
const agent = this.makeAgent();
|
||||
const agents = this.makeProxyAgents();
|
||||
const socketConfig: SocketConfig = this.getSocketConfig(
|
||||
agent,
|
||||
agents,
|
||||
state,
|
||||
) as SocketConfig;
|
||||
const sock = makeWASocket(socketConfig);
|
||||
@@ -356,7 +360,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
return sock;
|
||||
}
|
||||
|
||||
protected makeAgent(): Agent {
|
||||
protected makeProxyAgents(): Agents | undefined {
|
||||
if (!this.proxyConfig) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -605,14 +609,9 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
// https://github.com/WhiskeySockets/Baileys/pull/855/
|
||||
this.sock.ev.on('messages.upsert', ({ messages }) => {
|
||||
for (const message of messages) {
|
||||
const content = normalizeMessageContent(message.message);
|
||||
const protocolMsg = content?.protocolMessage;
|
||||
if (
|
||||
protocolMsg !== null &&
|
||||
protocolMsg !== undefined &&
|
||||
protocolMsg.editedMessage &&
|
||||
protocolMsg.key
|
||||
) {
|
||||
if (IsEditedMessage(message.message)) {
|
||||
const content = normalizeMessageContent(message.message);
|
||||
const protocolMsg = content?.protocolMessage;
|
||||
this.sock?.ev.emit('messages.update', [
|
||||
{
|
||||
key: {
|
||||
@@ -1894,22 +1893,15 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
this.events2.get(WAHAEvents.MESSAGE_REVOKED).switch(messagesRevoked$);
|
||||
|
||||
// Handle edited messages
|
||||
// @ts-ignore
|
||||
const messagesEdited$ = messagesUpsert$.pipe(
|
||||
filter(
|
||||
(message) =>
|
||||
// @ts-ignore
|
||||
message.message?.protocolMessage?.type ===
|
||||
proto.Message.ProtocolMessage.Type.MESSAGE_EDIT &&
|
||||
message.message?.protocolMessage?.editedMessage !== undefined,
|
||||
),
|
||||
filter((message) => IsEditedMessage(message.message)),
|
||||
mergeMap(async (message): Promise<WAMessageEditedBody> => {
|
||||
const waMessage = this.toWAMessage(message);
|
||||
// Extract the body from editedMessage using extractBody function
|
||||
const body =
|
||||
extractBody(message.message.protocolMessage.editedMessage) || '';
|
||||
const content = normalizeMessageContent(message.message);
|
||||
const body = extractBody(content.protocolMessage.editedMessage) || '';
|
||||
// Extract the original message ID from protocolMessage.key
|
||||
const editedMessageId = message.message.protocolMessage.key?.id;
|
||||
const editedMessageId = content.protocolMessage.key?.id;
|
||||
return {
|
||||
...waMessage,
|
||||
body: body,
|
||||
@@ -2205,11 +2197,7 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
|
||||
)
|
||||
return;
|
||||
// Ignore edit, we have a dedicated event for that
|
||||
if (
|
||||
message.message?.protocolMessage?.type ===
|
||||
proto.Message.ProtocolMessage.Type.MESSAGE_EDIT
|
||||
)
|
||||
return;
|
||||
if (IsEditedMessage(message.message)) return;
|
||||
if (
|
||||
message.message?.protocolMessage?.type ===
|
||||
proto.Message.ProtocolMessage.Type.EPHEMERAL_SYNC_RESPONSE
|
||||
@@ -2633,37 +2621,6 @@ export class NOWEBEngineMediaProcessor implements IMediaEngineProcessor<any> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from 11111111111@s.whatsapp.net to 11111111111@c.us
|
||||
*/
|
||||
export function toCusFormat(remoteJid) {
|
||||
if (!remoteJid) {
|
||||
return remoteJid;
|
||||
}
|
||||
if (isJidGroup(remoteJid)) {
|
||||
return remoteJid;
|
||||
}
|
||||
if (isJidBroadcast(remoteJid)) {
|
||||
return remoteJid;
|
||||
}
|
||||
if (isLidUser(remoteJid)) {
|
||||
return remoteJid;
|
||||
}
|
||||
if (isJidNewsletter(remoteJid)) {
|
||||
return remoteJid;
|
||||
}
|
||||
if (!remoteJid) {
|
||||
return;
|
||||
}
|
||||
if (remoteJid == 'me') {
|
||||
return remoteJid;
|
||||
}
|
||||
let number = remoteJid.split('@')[0];
|
||||
// remove :{device} part
|
||||
number = number.split(':')[0];
|
||||
return ensureSuffix(number);
|
||||
}
|
||||
|
||||
export const ALL_JID = 'all@s.whatsapp.net';
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { Agent } from 'https';
|
||||
import type { Dispatcher } from 'undici';
|
||||
|
||||
export interface Agents {
|
||||
socket: Agent;
|
||||
fetch: Dispatcher;
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Agent } from 'https';
|
||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||
import { URL } from 'url';
|
||||
import { ProxyAgent } from 'undici';
|
||||
|
||||
import { WhatsappConfigService } from '../config.service';
|
||||
import { ProxyConfig } from '../structures/sessions.dto';
|
||||
import { WhatsappSession } from './abc/session.abc';
|
||||
import { Agents } from '@waha/core/engines/noweb/types';
|
||||
|
||||
export function getProxyConfig(
|
||||
config: WhatsappConfigService,
|
||||
@@ -63,11 +64,15 @@ function getAuthenticatedUrl(
|
||||
* Return https Agent proxy for the config
|
||||
* @param proxyConfig
|
||||
*/
|
||||
export function createAgentProxy(proxyConfig: ProxyConfig): Agent | undefined {
|
||||
export function createAgentProxy(proxyConfig: ProxyConfig): Agents | undefined {
|
||||
const url = getAuthenticatedUrl(
|
||||
proxyConfig.server,
|
||||
proxyConfig.username || '',
|
||||
proxyConfig.password || '',
|
||||
);
|
||||
return new HttpsProxyAgent(url);
|
||||
|
||||
const socketAgent = new HttpsProxyAgent(url);
|
||||
const fetchAgent = new ProxyAgent({ uri: url });
|
||||
|
||||
return { socket: socketAgent, fetch: fetchAgent };
|
||||
}
|
||||
@@ -36,6 +36,10 @@ export function isPnUser(jid: string) {
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeJid(jid: string): string {
|
||||
return jid.replace(/:\d+(?=@)/, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from 11111111111@c.us to 11111111111@s.whatsapp.net
|
||||
* @param chatId
|
||||
@@ -135,14 +139,11 @@ export function toCusFormat(remoteJid) {
|
||||
return remoteJid;
|
||||
}
|
||||
if (isLidUser(remoteJid)) {
|
||||
return remoteJid;
|
||||
return normalizeJid(remoteJid);
|
||||
}
|
||||
if (isJidNewsletter(remoteJid)) {
|
||||
return remoteJid;
|
||||
}
|
||||
if (!remoteJid) {
|
||||
return;
|
||||
}
|
||||
if (remoteJid == 'me') {
|
||||
return remoteJid;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Proto WhatsApp Utils
|
||||
*/
|
||||
|
||||
import { normalizeMessageContent, proto } from '@adiwajshing/baileys';
|
||||
|
||||
export function IsEditedMessage(message: proto.IMessage): boolean {
|
||||
message = normalizeMessageContent(message);
|
||||
if (!message) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
message?.protocolMessage?.type !==
|
||||
proto.Message.ProtocolMessage.Type.MESSAGE_EDIT
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (message?.protocolMessage?.editedMessage == null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -18,6 +18,9 @@ import { SwaggerConfiguratorCore } from './core/SwaggerConfiguratorCore';
|
||||
import { AllExceptionsFilter } from './nestjs/AllExceptionsFilter';
|
||||
import { getWAHAVersion, VERSION, WAHAVersion } from './version';
|
||||
import { loadESMModules } from '@waha/vendor/esm';
|
||||
import { setGlobalDispatcher, Agent } from 'undici';
|
||||
|
||||
setGlobalDispatcher(new Agent({ connect: { family: 4 } }));
|
||||
|
||||
const logger: Logger = pino({
|
||||
level: getPinoLogLevel(),
|
||||
|
||||
@@ -150,7 +150,7 @@ export class SessionConfig {
|
||||
})
|
||||
@IsDynamicObject()
|
||||
@IsOptional()
|
||||
metadata?: Map<string, string>;
|
||||
metadata?: Record<string, string>;
|
||||
|
||||
@ApiProperty({
|
||||
example: null,
|
||||
@@ -225,6 +225,12 @@ export class MeInfo {
|
||||
})
|
||||
lid?: string;
|
||||
|
||||
@ApiProperty({
|
||||
example: '123123:123@s.whatsapp.net',
|
||||
description: 'Your id with device number',
|
||||
})
|
||||
jid?: string;
|
||||
|
||||
pushName: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ export class WAHAWebhook<Payload = any> {
|
||||
},
|
||||
description: 'Metadata for the session.',
|
||||
})
|
||||
metadata?: Map<string, string>;
|
||||
metadata?: Record<string, string>;
|
||||
|
||||
@ApiProperty({
|
||||
example: WAHAEngine.WEBJS,
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import axios from 'axios';
|
||||
import { Agent as HttpsAgent } from 'https';
|
||||
|
||||
const InsecureHttpsAgent = new HttpsAgent({
|
||||
rejectUnauthorized: false,
|
||||
});
|
||||
|
||||
export async function fetchBuffer(url: string): Promise<Buffer> {
|
||||
return axios
|
||||
.get(url, {
|
||||
responseType: 'arraybuffer',
|
||||
httpsAgent: InsecureHttpsAgent,
|
||||
})
|
||||
.then((res) => {
|
||||
return Buffer.from(res.data);
|
||||
});
|
||||
}
|
||||
+1
-1
@@ -30,7 +30,7 @@ export function getWAHAVersion(): WAHAVersion {
|
||||
}
|
||||
|
||||
export const VERSION: WAHAEnvironment = {
|
||||
version: '2025.10.2',
|
||||
version: '2025.10.4',
|
||||
engine: getEngineName(),
|
||||
tier: getWAHAVersion(),
|
||||
browser:
|
||||
|
||||
@@ -4,4 +4,6 @@ http:
|
||||
allow-insecure: true
|
||||
no-follow-redirects: true
|
||||
timeout: 5000
|
||||
request-headers:
|
||||
- "X-Api-Key: test"
|
||||
body: ['version']
|
||||
+2
-2
@@ -2,11 +2,11 @@
|
||||
"waha": {
|
||||
"gows": {
|
||||
"repo": "devlikeapro/gows",
|
||||
"ref": "v1.0.17"
|
||||
"ref": "v1.0.18"
|
||||
},
|
||||
"dashboard": {
|
||||
"repo": "devlikeapro/dashboard",
|
||||
"ref": "0d3523523e9d0e9d8aece8dec8a38b5fee23caad"
|
||||
"ref": "8345fb8594a9f8f51fc0a593d5cc1a2e4e786960"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,9 @@ __metadata:
|
||||
version: 6
|
||||
cacheKey: 8
|
||||
|
||||
"@adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-2025-10-10":
|
||||
"@adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-2025-10-19":
|
||||
version: 7.0.0-rc.5
|
||||
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=dad2730017ab6a24a48d3010796e8338928d0f43"
|
||||
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=df07435e41a5b6062c51a4a74393558cecf8fc50"
|
||||
dependencies:
|
||||
"@cacheable/node-cache": ^1.4.0
|
||||
"@hapi/boom": ^9.1.3
|
||||
@@ -31,7 +31,7 @@ __metadata:
|
||||
optional: true
|
||||
link-preview-js:
|
||||
optional: true
|
||||
checksum: 453dc477eee6c8df1d9aaaddcebfc5ce8b1cca72e958c6d7b742d0ef4afa3fcf1c6db06aba331d7a99596e64499af8e6ade81de0feadb4369fc567e74ddf7fa9
|
||||
checksum: 065a0a3e086e307ef805321355914c97282d279e7cbe2350118562373c0d36aaf877b0789d7e339f45f9c24e31a425f699b2f905411500522d0dc95a31c8986a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8536,13 +8536,23 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"libsignal@github:devlikeapro/libsignal-node#fork-master":
|
||||
"libsignal@git+https://github.com/whiskeysockets/libsignal-node":
|
||||
version: 2.0.1
|
||||
resolution: "libsignal@https://github.com/devlikeapro/libsignal-node.git#commit=83bc9236ee3d96ae1747cf3ca2e505b10cf97250"
|
||||
resolution: "libsignal@https://github.com/whiskeysockets/libsignal-node.git#commit=e81ecfc32eb74951d789ab37f7e341ab66d5fff1"
|
||||
dependencies:
|
||||
curve25519-js: ^0.0.4
|
||||
protobufjs: 6.8.8
|
||||
checksum: 3ee39bc7cbd123fa2c1f84ff53ab4e3dacfb5a00d10944960fd72156b24a5eb5af1fa5ca31b9f25b26aab107c712d8c295c85b0bed26ad6eba6d0e3f26f38927
|
||||
checksum: bf7a7b93000c826958d3ba6de72545675d39579a7befff56e3db561d985267e402fdf485127f6f4b1c12855a99966867f28517123fbb4b882d7ef39e83057c3d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"libsignal@github:WhiskeySockets/libsignal-node#master":
|
||||
version: 2.0.1
|
||||
resolution: "libsignal@https://github.com/WhiskeySockets/libsignal-node.git#commit=e81ecfc32eb74951d789ab37f7e341ab66d5fff1"
|
||||
dependencies:
|
||||
curve25519-js: ^0.0.4
|
||||
protobufjs: 6.8.8
|
||||
checksum: bf7a7b93000c826958d3ba6de72545675d39579a7befff56e3db561d985267e402fdf485127f6f4b1c12855a99966867f28517123fbb4b882d7ef39e83057c3d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -12327,6 +12337,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"undici@npm:^7.16.0":
|
||||
version: 7.16.0
|
||||
resolution: "undici@npm:7.16.0"
|
||||
checksum: dca60e323e44c2d408e0d1f5eb540632ad4e75631d5b6fcd7791876bab54e0e263a66e5606eaa717d436b2db5988c2f4af912dfa221ce53e3fc7fcb7d224c9cd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unicorn-magic@npm:^0.3.0":
|
||||
version: 0.3.0
|
||||
resolution: "unicorn-magic@npm:0.3.0"
|
||||
@@ -12494,7 +12511,7 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "waha@workspace:."
|
||||
dependencies:
|
||||
"@adiwajshing/baileys": "github:devlikeapro/Baileys#fork-master-2025-10-10"
|
||||
"@adiwajshing/baileys": "github:devlikeapro/Baileys#fork-master-2025-10-19"
|
||||
"@adiwajshing/keyed-db": ^0.2.4
|
||||
"@aws-sdk/client-s3": ^3.633.0
|
||||
"@aws-sdk/s3-request-presigner": ^3.633.0
|
||||
@@ -12558,7 +12575,7 @@ __metadata:
|
||||
joi: ^17.13.3
|
||||
knex: ^3.1.0
|
||||
libphonenumber-js: ^1.10.36
|
||||
libsignal: "github:devlikeapro/libsignal-node#fork-master"
|
||||
libsignal: "github:WhiskeySockets/libsignal-node#master"
|
||||
link-preview-js: ^3.0.4
|
||||
lodash: ^4.17.21
|
||||
long: ^5.3.2
|
||||
@@ -12593,6 +12610,7 @@ __metadata:
|
||||
tsconfig-paths: ^4.1.0
|
||||
typescript: 5.9.2
|
||||
ulid: ^2.3.0
|
||||
undici: ^7.16.0
|
||||
whatsapp-web.js: "github:devlikeapro/whatsapp-web.js#fork-main-2025-09-10"
|
||||
write-file-atomic: ^6.0.0
|
||||
yaml: ^2.7.1
|
||||
|
||||
Reference in new issue
Block a user