Compare commits

...
21 Commits
Author SHA1 Message Date
devlikepro ad10ea4e96 [core] 2025.7.9
Release / WEBJS - chrome - amd64 - chrome (push) Waiting to run
Release / WEBJS - chromium - amd64 - latest (push) Waiting to run
Release / WEBJS - chromium - linux/arm64 - arm (push) Waiting to run
Release / GOWS - none - amd64 - gows (push) Waiting to run
Release / GOWS - none - linux/arm64 - gows-arm (push) Waiting to run
Release / NOWEB - none - amd64 - noweb (push) Waiting to run
Release / NOWEB - none - linux/arm64 - noweb-arm (push) Waiting to run
2025-07-25 12:46:33 +07:00
devlikepro 9de53a972a [core] Up NOWEB
fix #1143
2025-07-25 12:46:33 +07:00
devlikepro 4043efbb9a [core] Up Dashboard 2025-07-25 12:46:33 +07:00
devlikepro 42019644f0 [core] cpus*2 for UV_THREADPOOL_SIZE 2025-07-25 12:46:33 +07:00
devlikepro bcc25ef42f [core] Adjust UV_THREADPOOL_SIZE logic 2025-07-25 12:46:33 +07:00
devlikepro 602bbf3b60 [core] WEBJS - WAHA_RUN_XVFB
fix #1151
2025-07-25 12:46:32 +07:00
devlikeaproandsnyk-bot 585ac6074f [core] fix: package.json to reduce vulnerabilities (#16)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-MULTER-10773732

Co-authored-by: snyk-bot <snyk-bot@snyk.io>
2025-07-24 10:37:37 +07:00
devlikepro 5bd1a43df6 [core] 2025.7.8
Release / WEBJS - chrome - amd64 - chrome (push) Waiting to run
Release / WEBJS - chromium - amd64 - latest (push) Waiting to run
Release / WEBJS - chromium - linux/arm64 - arm (push) Waiting to run
Release / GOWS - none - amd64 - gows (push) Waiting to run
Release / GOWS - none - linux/arm64 - gows-arm (push) Waiting to run
Release / NOWEB - none - amd64 - noweb (push) Waiting to run
Release / NOWEB - none - linux/arm64 - noweb-arm (push) Waiting to run
2025-07-23 15:02:05 +07:00
devlikepro c9279a4b59 [core] ChatWoot - send png as images 2025-07-23 15:02:04 +07:00
devlikepro 9ff8eed6ba [core] Add, edit, and remove contact API
fix #1124
2025-07-23 15:02:03 +07:00
devlikepro 96ffdd251f [core] Up GOWS 2025-07-23 15:01:53 +07:00
devlikepro 35b8b7d01c [core] 2025.7.7
Release / WEBJS - chrome - amd64 - chrome (push) Waiting to run
Release / WEBJS - chromium - amd64 - latest (push) Waiting to run
Release / WEBJS - chromium - linux/arm64 - arm (push) Waiting to run
Release / GOWS - none - amd64 - gows (push) Waiting to run
Release / GOWS - none - linux/arm64 - gows-arm (push) Waiting to run
Release / NOWEB - none - amd64 - noweb (push) Waiting to run
Release / NOWEB - none - linux/arm64 - noweb-arm (push) Waiting to run
2025-07-22 14:53:35 +07:00
devlikepro 4e2e2b2b3c [core] WEBJS - add 1GB cache back
fix #1131 fix #1140
2025-07-22 14:53:35 +07:00
devlikepro bfff0c8cf4 [core] 2025.7.6
Release / WEBJS - chrome - amd64 - chrome (push) Waiting to run
Release / WEBJS - chromium - amd64 - latest (push) Waiting to run
Release / WEBJS - chromium - linux/arm64 - arm (push) Waiting to run
Release / GOWS - none - amd64 - gows (push) Waiting to run
Release / GOWS - none - linux/arm64 - gows-arm (push) Waiting to run
Release / NOWEB - none - amd64 - noweb (push) Waiting to run
Release / NOWEB - none - linux/arm64 - noweb-arm (push) Waiting to run
2025-07-20 14:06:59 +07:00
devlikepro e253f445b9 [core] WEBJS - fix sendSeen
fix #1117
2025-07-20 14:06:58 +07:00
devlikepro 73ed663c9c [core] Dashboard - show tier 2025-07-20 14:06:58 +07:00
devlikepro 2236150b83 [core] ChatWoot - adjust commands list text 2025-07-20 14:06:58 +07:00
devlikepro da24feb390 [core] Fix "Not implemented by engine" in status
fix #1115
2025-07-20 14:06:58 +07:00
devlikepro 44a5ada162 [core] Fix "You provided 'null' where a stream was expected" 2025-07-20 14:06:58 +07:00
devlikepro e57cc2587c [core] WEBJS - share media properly 2025-07-20 14:06:58 +07:00
Alan Frigo 38bfb9baa5 Added WHATSAPP_HOOK_CUSTOM_HEADERS to env example 2025-07-20 13:57:46 +07:00
33 changed files with 741 additions and 119 deletions

No files matched your search

+1
View File
@@ -102,6 +102,7 @@ WHATSAPP_FILES_FOLDER=/app/.media
# Webhooks
# WHATSAPP_HOOK_URL=https://webhook.site/11111111-1111-1111-1111-11111111
# WHATSAPP_HOOK_CUSTOM_HEADERS=custom_header_key:custom_header_value
# WHATSAPP_HOOK_EVENTS=session.status,message,message.reaction
# Proxy configuration
+30 -9
View File
@@ -4,8 +4,18 @@
#
# Calculate UV_THREADPOOL_SIZE based on number of CPUs
#
cpus=$(node -e "const os = require('os'); console.log(os.cpus().length);")
uv_threadpool_size=$(($cpus * 1))
# Try to get CPU count using Node.js, fallback to 1 if it fails
cpus=$(node -e "const os = require('os'); console.log(os.cpus().length);" 2>/dev/null) || cpus=1
# Make sure cpus is a number, default to 1 if not
case $cpus in
''|*[!0-9]*) cpus=1 ;;
esac
uv_threadpool_size=$(($cpus * 2))
# Check if uv_threadpool_size is less than 4 (default), set it to 4 if it is
if [ "$uv_threadpool_size" -lt 4 ]; then
uv_threadpool_size=4
fi
# Set UV_THREADPOOL_SIZE as an environment variable
export UV_THREADPOOL_SIZE="${UV_THREADPOOL_SIZE:-$uv_threadpool_size}"
@@ -46,13 +56,22 @@ fi
# xvfb-run
#
USE_XVFB=false
if [ -z "$WHATSAPP_DEFAULT_ENGINE" ] || [ "$WHATSAPP_DEFAULT_ENGINE" = "WEBJS" ]; then
# Try to run xvfb-run with a test command
if xvfb-run --auto-servernum echo "xvfb-run is working!"; then
USE_XVFB=true
else
echo "xvfb-run test failed, do not run it"
USE_XVFB=false
# Check WAHA_RUN_XVFB parameter - only test for "false" case, treat all others as True
if [ "$WAHA_RUN_XVFB" = "false" ] || [ "$WAHA_RUN_XVFB" = "False" ] || [ "$WAHA_RUN_XVFB" = "0" ]; then
# Explicitly disabled by user
echo "WAHA_RUN_XVFB value: $WAHA_RUN_XVFB - xvfb is disabled"
USE_XVFB=false
else
# Check engine and run test if it's WEBJS or not specified
if [ -z "$WHATSAPP_DEFAULT_ENGINE" ] || [ "$WHATSAPP_DEFAULT_ENGINE" = "WEBJS" ]; then
# Try to run xvfb-run with a test command
if xvfb-run --auto-servernum echo "xvfb-run is working!"; then
USE_XVFB=true
else
echo "xvfb-run test failed, do not run it"
USE_XVFB=false
fi
fi
fi
@@ -60,7 +79,9 @@ fi
# Start your application using node with exec to ensure proper signal handling
#
if [ "$USE_XVFB" = "true" ]; then
echo "Executing node with xvfb-run..."
exec xvfb-run --auto-servernum node dist/main
else
echo "Executing node without xvfb-run..."
exec node dist/main
fi
+1 -1
View File
@@ -41,7 +41,7 @@
"@nestjs/config": "^3.2.3",
"@nestjs/core": "^11.0.0",
"@nestjs/passport": "^11.0.0",
"@nestjs/platform-express": "^11.0.0",
"@nestjs/platform-express": "^11.1.5",
"@nestjs/platform-ws": "^11.0.0",
"@nestjs/serve-static": "^5.0.0",
"@nestjs/swagger": "^7.1.11",
@@ -180,7 +180,7 @@ export class MessageHandler {
switch (file.file_type) {
case 'image':
if (mimetype != 'image/jpeg') {
if (mimetype != 'image/jpeg' && mimetype != 'image/png') {
// Send it as a file
break;
}
+4 -2
View File
@@ -95,7 +95,9 @@ APP_UPDATED_MESSAGE: |
✅ تم تحديث إعدادات جلسة واتساب **{{{name}}}**.
APP_COMMANDS_LIST: |
يمكنك إدارة **جلسة واتساب** عن طريق إرسال أحد الأوامر التالية:
يمكنك إدارة **تكامل واتساب** عن طريق إرسال أحد الأوامر التالية:
🖥️ الجلسات:
1. **status** - الحصول على حالة الجلسة الحالية.
2. **restart** - إعادة تشغيل الجلسة - سيحاول هذا إعادة توصيل حساب واتساب الخاص بك.
3. **start** - بدء الجلسة.
@@ -105,7 +107,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - الحصول على لقطة شاشة للجلسة (متاح فقط في محرك **WEBJS**).
8. **help** - الأوامر المتاحة.
أوامر الخادم:
⚙️ الخادم:
- **server status** - الحصول على معلومات إصدار الخادم وحالته.
- **server reboot** - إعادة تشغيل الخادم بسلاسة.
- **server reboot force** - إعادة تشغيل الخادم بالقوة.
+4 -2
View File
@@ -95,7 +95,9 @@ APP_UPDATED_MESSAGE: |
✅ হোয়াটসঅ্যাপ সেশন **{{{name}}}** এর সেটিংস আপডেট করা হয়েছে।
APP_COMMANDS_LIST: |
আপনি নিম্নলিখিত কমান্ডগুলির একটি পাঠিয়ে **হোয়াটসঅ্যাপ সেশন** পরিচালনা করতে পারেন:
আপনি নিম্নলিখিত কমান্ডগুলির একটি পাঠিয়ে **হোয়াটসঅ্যাপ ইন্টিগ্রেশন** পরিচালনা করতে পারেন:
🖥️ সেশন:
1. **status** - বর্তমান সেশনের স্ট্যাটাস পান।
2. **restart** - সেশন পুনরায় চালু করুন - এটি আপনার হোয়াটসঅ্যাপ অ্যাকাউন্ট পুনরায় সংযোগ করার চেষ্টা করবে।
3. **start** - সেশন শুরু করুন।
@@ -105,7 +107,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - সেশনের স্ক্রিনশট পান (শুধুমাত্র **WEBJS** ইঞ্জিনে উপলব্ধ)।
8. **help** - উপলব্ধ কমান্ডগুলি।
সার্ভার কমান্ডগুলি:
⚙️ সার্ভার:
- **server status** - সার্ভারের সংস্করণ এবং স্ট্যাটাস তথ্য পান।
- **server reboot** - সার্ভার সুন্দরভাবে পুনরায় চালু করুন।
- **server reboot force** - সার্ভার জোর করে পুনরায় চালু করুন।
+4 -2
View File
@@ -98,7 +98,9 @@ APP_UPDATED_MESSAGE: |
✅ Einstellungen für WhatsApp-Sitzung **{{{name}}}** wurden aktualisiert.
APP_COMMANDS_LIST: |
Sie können die **WhatsApp-Sitzung** verwalten, indem Sie einen der folgenden Befehle senden:
Sie können die **WhatsApp Integration** verwalten, indem Sie einen der folgenden Befehle senden:
🖥️ Sitzungen:
1. **status** - den aktuellen Sitzungsstatus abrufen.
2. **restart** - die Sitzung neu starten - dies versucht, Ihr WhatsApp-Konto neu zu verbinden.
3. **start** - die Sitzung starten.
@@ -108,7 +110,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - einen Screenshot der Sitzung erhalten (nur in der **WEBJS**-Engine verfügbar).
8. **help** - verfügbare Befehle.
Server-Befehle:
⚙️ Server:
- **server status** - Serverversion und Statusinformationen abrufen.
- **server reboot** - Server ordnungsgemäß neu starten.
- **server reboot force** - Server erzwungen neu starten.
+4 -2
View File
@@ -96,7 +96,9 @@ APP_UPDATED_MESSAGE: |
✅ Settings for WhatsApp session **{{{name}}}** have been updated.
APP_COMMANDS_LIST: |
You can manage **WhatsApp session** by sending one of the following commands:
You can manage **WhatsApp Integration** by sending one of the following commands:
🖥️ Sessions:
1. **status** - get the current session status.
2. **restart** - restart the session - this will try to reconnect your WhatsApp account.
3. **start** - start the session.
@@ -106,7 +108,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - get a screenshot of the session (only available in **WEBJS** engine).
8. **help** - available commands.
Server commands:
⚙️ Server:
- **server status** - get the server version and status information.
- **server reboot** - reboot the server gracefully.
- **server reboot force** - force reboot the server.
+4 -2
View File
@@ -95,7 +95,9 @@ APP_UPDATED_MESSAGE: |
✅ La configuración para la sesión de WhatsApp **{{{name}}}** ha sido actualizada.
APP_COMMANDS_LIST: |
Puedes gestionar la **sesión de WhatsApp** enviando uno de los siguientes comandos:
Puedes gestionar la **Integración de WhatsApp** enviando uno de los siguientes comandos:
🖥️ Sesiones:
1. **status** - obtener el estado actual de la sesión.
2. **restart** - reiniciar la sesión - esto intentará reconectar tu cuenta de WhatsApp.
3. **start** - iniciar la sesión.
@@ -105,7 +107,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - obtener una captura de pantalla de la sesión (solo disponible en el motor **WEBJS**).
8. **help** - comandos disponibles.
Comandos del servidor:
⚙️ Servidor:
- **server status** - obtener información de versión y estado del servidor.
- **server reboot** - reiniciar el servidor de forma segura.
- **server reboot force** - forzar el reinicio del servidor.
+4 -2
View File
@@ -95,7 +95,9 @@ APP_UPDATED_MESSAGE: |
✅ تنظیمات جلسه واتساپ **{{{name}}}** به‌روزرسانی شده است.
APP_COMMANDS_LIST: |
شما می‌توانید **جلسه واتساپ** را با ارسال یکی از دستورات زیر مدیریت کنید:
شما می‌توانید **ادغام واتساپ** را با ارسال یکی از دستورات زیر مدیریت کنید:
🖥️ جلسات:
1. **status** - دریافت وضعیت فعلی جلسه.
2. **restart** - راه‌اندازی مجدد جلسه - این تلاش خواهد کرد حساب واتساپ شما را مجدداً متصل کند.
3. **start** - شروع جلسه.
@@ -105,7 +107,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - دریافت اسکرین‌شات از جلسه (فقط در موتور **WEBJS** در دسترس است).
8. **help** - دستورات موجود.
دستورات سرور:
⚙️ سرور:
- **server status** - دریافت اطلاعات نسخه و وضعیت سرور.
- **server reboot** - راه‌اندازی مجدد سرور به صورت نرم.
- **server reboot force** - راه‌اندازی مجدد اجباری سرور.
+4 -2
View File
@@ -95,7 +95,9 @@ APP_UPDATED_MESSAGE: |
✅ Les paramètres de la session WhatsApp **{{{name}}}** ont été mis à jour.
APP_COMMANDS_LIST: |
Vous pouvez gérer la **session WhatsApp** en envoyant l'une des commandes suivantes :
Vous pouvez gérer l'**Intégration WhatsApp** en envoyant l'une des commandes suivantes :
🖥️ Sessions :
1. **status** - obtenir l'état actuel de la session.
2. **restart** - redémarrer la session - cela tentera de reconnecter votre compte WhatsApp.
3. **start** - démarrer la session.
@@ -105,7 +107,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - obtenir une capture d'écran de la session (disponible uniquement dans le moteur **WEBJS**).
8. **help** - commandes disponibles.
Commandes du serveur :
⚙️ Serveur :
- **server status** - obtenir les informations de version et d'état du serveur.
- **server reboot** - redémarrer le serveur en douceur.
- **server reboot force** - forcer le redémarrage du serveur.
+4 -2
View File
@@ -95,7 +95,9 @@ APP_UPDATED_MESSAGE: |
✅ ההגדרות עבור הפעלת וואטסאפ **{{{name}}}** עודכנו.
APP_COMMANDS_LIST: |
אתה יכול לנהל **הפעלת וואטסאפ** על ידי שליחת אחת מהפקודות הבאות:
אתה יכול לנהל **אינטגרציית וואטסאפ** על ידי שליחת אחת מהפקודות הבאות:
🖥️ הפעלות:
1. **status** - קבל את סטטוס ההפעלה הנוכחי.
2. **restart** - הפעל מחדש את ההפעלה - זה ינסה לחבר מחדש את חשבון הוואטסאפ שלך.
3. **start** - התחל את ההפעלה.
@@ -105,7 +107,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - קבל צילום מסך של ההפעלה (זמין רק במנוע **WEBJS**).
8. **help** - פקודות זמינות.
פקודות שרת:
⚙️ שרת:
- **server status** - קבל מידע על גרסת השרת והסטטוס.
- **server reboot** - הפעל מחדש את השרת בצורה חלקה.
- **server reboot force** - אלץ הפעלה מחדש של השרת.
+4 -2
View File
@@ -95,7 +95,9 @@ APP_UPDATED_MESSAGE: |
✅ व्हाट्सएप सत्र **{{{name}}}** की सेटिंग्स अपडेट की गई हैं।
APP_COMMANDS_LIST: |
आप निम्न कमांड में से एक भेजकर **व्हाट्सएप सत्र** का प्रबंधन कर सकते हैं:
आप निम्न कमांड में से एक भेजकर **व्हाट्सएप इंटीग्रेशन** का प्रबंधन कर सकते हैं:
🖥️ सत्र:
1. **status** - वर्तमान सत्र स्थिति प्राप्त करें।
2. **restart** - सत्र को पुनरारंभ करें - यह आपके व्हाट्सएप खाते को फिर से कनेक्ट करने का प्रयास करेगा।
3. **start** - सत्र शुरू करें।
@@ -105,7 +107,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - सत्र का स्क्रीनशॉट प्राप्त करें (केवल **WEBJS** इंजन में उपलब्ध)।
8. **help** - उपलब्ध कमांड।
सर्वर कमांड:
⚙️ सर्वर:
- **server status** - सर्वर संस्करण और स्थिति जानकारी प्राप्त करें।
- **server reboot** - सर्वर को सुचारू रूप से पुनरारंभ करें।
- **server reboot force** - सर्वर को जबरदस्ती पुनरारंभ करें।
+4 -2
View File
@@ -95,7 +95,9 @@ APP_UPDATED_MESSAGE: |
✅ Pengaturan untuk sesi WhatsApp **{{{name}}}** telah diperbarui.
APP_COMMANDS_LIST: |
Anda dapat mengelola **sesi WhatsApp** dengan mengirimkan salah satu perintah berikut:
Anda dapat mengelola **Integrasi WhatsApp** dengan mengirimkan salah satu perintah berikut:
🖥️ Sesi:
1. **status** - dapatkan status sesi saat ini.
2. **restart** - mulai ulang sesi - ini akan mencoba menghubungkan kembali akun WhatsApp Anda.
3. **start** - mulai sesi.
@@ -105,7 +107,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - dapatkan tangkapan layar sesi (hanya tersedia di mesin **WEBJS**).
8. **help** - perintah yang tersedia.
Perintah server:
⚙️ Server:
- **server status** - dapatkan informasi versi dan status server.
- **server reboot** - mulai ulang server dengan anggun.
- **server reboot force** - paksa mulai ulang server.
+4 -2
View File
@@ -95,7 +95,9 @@ APP_UPDATED_MESSAGE: |
✅ ਵਟਸਐਪ ਸੈਸ਼ਨ **{{{name}}}** ਲਈ ਸੈਟਿੰਗਾਂ ਅਪਡੇਟ ਕੀਤੀਆਂ ਗਈਆਂ ਹਨ।
APP_COMMANDS_LIST: |
ਤੁਸੀਂ ਹੇਠਾਂ ਦਿੱਤੇ ਕਮਾਂਡਾਂ ਵਿੱਚੋਂ ਇੱਕ ਭੇਜ ਕੇ **ਵਟਸਐਪ ਸੈਸ਼ਨ** ਦਾ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦੇ ਹੋ:
ਤੁਸੀਂ ਹੇਠਾਂ ਦਿੱਤੇ ਕਮਾਂਡਾਂ ਵਿੱਚੋਂ ਇੱਕ ਭੇਜ ਕੇ **ਵਟਸਐਪ ਇੰਟੀਗ੍ਰੇਸ਼ਨ** ਦਾ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦੇ ਹੋ:
🖥️ ਸੈਸ਼ਨ:
1. **status** - ਮੌਜੂਦਾ ਸੈਸ਼ਨ ਸਥਿਤੀ ਪ੍ਰਾਪਤ ਕਰੋ।
2. **restart** - ਸੈਸ਼ਨ ਮੁੜ ਚਾਲੂ ਕਰੋ - ਇਹ ਤੁਹਾਡੇ ਵਟਸਐਪ ਖਾਤੇ ਨੂੰ ਮੁੜ ਕਨੈਕਟ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੇਗਾ।
3. **start** - ਸੈਸ਼ਨ ਸ਼ੁਰੂ ਕਰੋ।
@@ -105,7 +107,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - ਸੈਸ਼ਨ ਦਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਪ੍ਰਾਪਤ ਕਰੋ (ਸਿਰਫ **WEBJS** ਇੰਜਣ ਵਿੱਚ ਉਪਲਬਧ)।
8. **help** - ਉਪਲਬਧ ਕਮਾਂਡਾਂ।
ਸਰਵਰ ਕਮਾਂਡਾਂ:
⚙️ ਸਰਵਰ:
- **server status** - ਸਰਵਰ ਵਰਜਨ ਅਤੇ ਸਥਿਤੀ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰੋ।
- **server reboot** - ਸਰਵਰ ਨੂੰ ਸੁਚਾਰੂ ਢੰਗ ਨਾਲ ਮੁੜ ਚਾਲੂ ਕਰੋ।
- **server reboot force** - ਸਰਵਰ ਨੂੰ ਜ਼ਬਰਦਸਤੀ ਮੁੜ ਚਾਲੂ ਕਰੋ।
+4 -2
View File
@@ -98,7 +98,9 @@ APP_UPDATED_MESSAGE: |
✅ As configurações para a sessão do WhatsApp **{{{name}}}** foram atualizadas.
APP_COMMANDS_LIST: |
Você pode gerenciar a **sessão do WhatsApp** enviando um dos seguintes comandos:
Você pode gerenciar a **Integração WhatsApp** enviando um dos seguintes comandos:
🖥️ Sessões:
1. **status** - obter o status atual da sessão.
2. **restart** - reiniciar a sessão - isso tentará reconectar sua conta do WhatsApp.
3. **start** - iniciar a sessão.
@@ -108,7 +110,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - obter uma captura de tela da sessão (disponível apenas no motor **WEBJS**).
8. **help** - comandos disponíveis.
Comandos do servidor:
⚙️ Servidor:
- **server status** - obter informações sobre a versão e status do servidor.
- **server reboot** - reiniciar o servidor suavemente.
- **server reboot force** - forçar a reinicialização do servidor.
+4 -2
View File
@@ -95,7 +95,9 @@ APP_UPDATED_MESSAGE: |
✅ Настройки для сессии WhatsApp **{{{name}}}** были обновлены.
APP_COMMANDS_LIST: |
Вы можете управлять **сессией WhatsApp**, отправив одну из следующих команд:
Вы можете управлять **WhatsApp Интеграцией**, отправив одну из следующих команд:
🖥️ Сессии:
1. **status** - получить текущий статус сессии.
2. **restart** - перезапустить сессию - это попытается переподключить ваш аккаунт WhatsApp.
3. **start** - запустить сессию.
@@ -105,7 +107,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - получить скриншот сессии (доступно только в движке **WEBJS**).
8. **help** - доступные команды.
Серверные команды:
⚙️ Сервер:
- **server status** - получить информацию о версии и статусе сервера.
- **server reboot** - корректно перезагрузить сервер.
- **server reboot force** - принудительно перезагрузить сервер.
+4 -2
View File
@@ -95,7 +95,9 @@ APP_UPDATED_MESSAGE: |
✅ WhatsApp oturumu **{{{name}}}** için ayarlar güncellendi.
APP_COMMANDS_LIST: |
Aşağıdaki komutlardan birini göndererek **WhatsApp oturumunu** yönetebilirsiniz:
Aşağıdaki komutlardan birini göndererek **WhatsApp Entegrasyonu**nu yönetebilirsiniz:
🖥️ Oturumlar:
1. **status** - mevcut oturum durumunu alın.
2. **restart** - oturumu yeniden başlatın - bu, WhatsApp hesabınızı yeniden bağlamaya çalışacaktır.
3. **start** - oturumu başlatın.
@@ -105,7 +107,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - oturumun ekran görüntüsünü alın (yalnızca **WEBJS** motorunda kullanılabilir).
8. **help** - kullanılabilir komutlar.
Sunucu komutları:
⚙️ Sunucu:
- **server status** - sunucu sürümü ve durum bilgilerini alın.
- **server reboot** - sunucuyu nazikçe yeniden başlatın.
- **server reboot force** - sunucuyu zorla yeniden başlatın.
+4 -2
View File
@@ -95,7 +95,9 @@ APP_UPDATED_MESSAGE: |
✅ Налаштування для сесії WhatsApp **{{{name}}}** були оновлені.
APP_COMMANDS_LIST: |
Ви можете керувати **сесією WhatsApp**, надіславши одну з наступних команд:
Ви можете керувати **Інтеграцією WhatsApp**, надіславши одну з наступних команд:
🖥️ Сесії:
1. **status** - отримати поточний статус сесії.
2. **restart** - перезапустити сесію - це спробує повторно підключити ваш обліковий запис WhatsApp.
3. **start** - запустити сесію.
@@ -105,7 +107,7 @@ APP_COMMANDS_LIST: |
7. **screenshot** - отримати знімок екрану сесії (доступно лише в двигуні **WEBJS**).
8. **help** - доступні команди.
Команди сервера:
⚙️ Сервер:
- **server status** - отримати інформацію про версію та статус сервера.
- **server reboot** - перезавантажити сервер плавно.
- **server reboot force** - примусово перезавантажити сервер.
+38
View File
@@ -0,0 +1,38 @@
import { Body, Controller, Delete, Param, Put, UsePipes } from '@nestjs/common';
import { ApiOperation, ApiSecurity, ApiTags } from '@nestjs/swagger';
import { WhatsappSession } from '@waha/core/abc/session.abc';
import { ChatIdApiParam } from '@waha/nestjs/params/ChatIdApiParam';
import {
SessionApiParam,
WorkingSessionParam,
} from '@waha/nestjs/params/SessionApiParam';
import { WAHAValidationPipe } from '@waha/nestjs/pipes/WAHAValidationPipe';
import { SessionManager } from './core/abc/manager.abc';
import { Result } from './structures/base.dto';
import { ContactUpdateBody } from './structures/contacts.dto';
@ApiSecurity('api_key')
@Controller('api/:session/contacts')
@ApiTags('👤 Contacts')
export class ContactsSessionController {
constructor(private manager: SessionManager) {}
@Put('/:chatId')
@SessionApiParam
@ChatIdApiParam
@ApiOperation({
summary: 'Create or update contact',
description:
'Create or update contact on the phone address book. May not work if you have installed many WhatsApp apps on the same phone',
})
@UsePipes(new WAHAValidationPipe())
async put(
@WorkingSessionParam session: WhatsappSession,
@Param('chatId') chatId: string,
@Body() body: ContactUpdateBody,
): Promise<Result> {
await session.upsertContact(chatId, body);
return { success: true };
}
}
+23 -8
View File
@@ -77,7 +77,11 @@ import {
MessageVoiceRequest,
SendSeenRequest,
} from '../../structures/chatting.dto';
import { ContactQuery, ContactRequest } from '../../structures/contacts.dto';
import {
ContactQuery,
ContactRequest,
ContactUpdateBody,
} from '../../structures/contacts.dto';
import {
WAHAEngine,
WAHAEvents,
@@ -109,7 +113,10 @@ import {
VoiceStatus,
} from '../../structures/status.dto';
import { WASessionStatusBody } from '../../structures/webhooks.dto';
import { NotImplementedByEngineError } from '../exceptions';
import {
AvailableInPlusVersion,
NotImplementedByEngineError,
} from '../exceptions';
import { IMediaManager } from '../media/IMediaManager';
import { QR } from '../QR';
import { DataStore } from './DataStore';
@@ -283,13 +290,11 @@ export abstract class WhatsappSession {
// https://superuser.com/questions/654565/how-to-run-google-chrome-in-a-single-process
// https://www.bannerbear.com/blog/ways-to-speed-up-puppeteer-screenshots/
return [
'--aggressive-cache-discard',
'--disable-accelerated-2d-canvas',
'--disable-application-cache',
// DO NOT disable software rasterizer, it will break the video
// https://github.com/devlikeapro/waha/issues/629
// '--disable-software-rasterizer',
'--disable-cache',
'--disable-client-side-phishing-detection',
'--disable-component-update',
'--disable-default-apps',
@@ -306,7 +311,6 @@ export abstract class WhatsappSession {
'--disable-sync',
'--disable-translate',
'--disable-web-security',
'--disk-cache-size=0',
'--hide-scrollbars',
'--ignore-certificate-errors',
'--ignore-ssl-errors',
@@ -324,6 +328,13 @@ export abstract class WhatsappSession {
'--safebrowsing-disable-auto-update',
'--use-mock-keychain',
'--window-size=1280,720',
//
// Cache options
//
'--disk-cache-size=1073741824', // 1GB
// '--disk-cache-size=0',
// '--disable-cache',
// '--aggressive-cache-discard',
];
}
@@ -632,6 +643,10 @@ export abstract class WhatsappSession {
/**
* Contacts methods
*/
public upsertContact(chatId: string, body: ContactUpdateBody): Promise<void> {
throw new NotImplementedByEngineError();
}
public getContact(query: ContactQuery) {
throw new NotImplementedByEngineError();
}
@@ -940,15 +955,15 @@ export abstract class WhatsappSession {
}
public sendImageStatus(status: ImageStatus) {
throw new NotImplementedByEngineError();
throw new AvailableInPlusVersion();
}
public sendVoiceStatus(status: VoiceStatus) {
throw new NotImplementedByEngineError();
throw new AvailableInPlusVersion();
}
public sendVideoStatus(status: VideoStatus) {
throw new NotImplementedByEngineError();
throw new AvailableInPlusVersion();
}
public deleteStatus(request: DeleteStatusRequest) {
+2
View File
@@ -14,6 +14,7 @@ import { ServerController } from '@waha/api/server.controller';
import { ServerDebugController } from '@waha/api/server.debug.controller';
import { WebsocketGatewayCore } from '@waha/api/websocket.gateway.core';
import { AppsModuleExports } from '@waha/apps/apps.module';
import { ContactsSessionController } from '@waha/contacts.session.controller';
import { ApiKeyStrategy } from '@waha/core/auth/apiKey.strategy';
import { IApiKeyAuth } from '@waha/core/auth/auth';
import { AuthMiddleware } from '@waha/core/auth/auth.middleware';
@@ -146,6 +147,7 @@ export const CONTROLLERS = [
StatusController,
LabelsController,
ContactsController,
ContactsSessionController,
LidsController,
GroupsController,
PresenceController,
+178 -26
View File
@@ -7941,6 +7941,145 @@ export namespace messages {
return GetMessagesRequest.deserialize(bytes);
}
}
export class UpdateContactRequest extends pb_1.Message {
#one_of_decls: number[][] = [];
constructor(data?: any[] | {
session?: Session;
jid?: string;
firstName?: string;
lastName?: string;
}) {
super();
pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls);
if (!Array.isArray(data) && typeof data == "object") {
if ("session" in data && data.session != undefined) {
this.session = data.session;
}
if ("jid" in data && data.jid != undefined) {
this.jid = data.jid;
}
if ("firstName" in data && data.firstName != undefined) {
this.firstName = data.firstName;
}
if ("lastName" in data && data.lastName != undefined) {
this.lastName = data.lastName;
}
}
}
get session() {
return pb_1.Message.getWrapperField(this, Session, 1) as Session;
}
set session(value: Session) {
pb_1.Message.setWrapperField(this, 1, value);
}
get has_session() {
return pb_1.Message.getField(this, 1) != null;
}
get jid() {
return pb_1.Message.getFieldWithDefault(this, 2, "") as string;
}
set jid(value: string) {
pb_1.Message.setField(this, 2, value);
}
get firstName() {
return pb_1.Message.getFieldWithDefault(this, 3, "") as string;
}
set firstName(value: string) {
pb_1.Message.setField(this, 3, value);
}
get lastName() {
return pb_1.Message.getFieldWithDefault(this, 4, "") as string;
}
set lastName(value: string) {
pb_1.Message.setField(this, 4, value);
}
static fromObject(data: {
session?: ReturnType<typeof Session.prototype.toObject>;
jid?: string;
firstName?: string;
lastName?: string;
}): UpdateContactRequest {
const message = new UpdateContactRequest({});
if (data.session != null) {
message.session = Session.fromObject(data.session);
}
if (data.jid != null) {
message.jid = data.jid;
}
if (data.firstName != null) {
message.firstName = data.firstName;
}
if (data.lastName != null) {
message.lastName = data.lastName;
}
return message;
}
toObject() {
const data: {
session?: ReturnType<typeof Session.prototype.toObject>;
jid?: string;
firstName?: string;
lastName?: string;
} = {};
if (this.session != null) {
data.session = this.session.toObject();
}
if (this.jid != null) {
data.jid = this.jid;
}
if (this.firstName != null) {
data.firstName = this.firstName;
}
if (this.lastName != null) {
data.lastName = this.lastName;
}
return data;
}
serialize(): Uint8Array;
serialize(w: pb_1.BinaryWriter): void;
serialize(w?: pb_1.BinaryWriter): Uint8Array | void {
const writer = w || new pb_1.BinaryWriter();
if (this.has_session)
writer.writeMessage(1, this.session, () => this.session.serialize(writer));
if (this.jid.length)
writer.writeString(2, this.jid);
if (this.firstName.length)
writer.writeString(3, this.firstName);
if (this.lastName.length)
writer.writeString(4, this.lastName);
if (!w)
return writer.getResultBuffer();
}
static deserialize(bytes: Uint8Array | pb_1.BinaryReader): UpdateContactRequest {
const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new UpdateContactRequest();
while (reader.nextField()) {
if (reader.isEndGroup())
break;
switch (reader.getFieldNumber()) {
case 1:
reader.readMessage(message.session, () => message.session = Session.deserialize(reader));
break;
case 2:
message.jid = reader.readString();
break;
case 3:
message.firstName = reader.readString();
break;
case 4:
message.lastName = reader.readString();
break;
default: reader.skipField();
}
}
return message;
}
serializeBinary(): Uint8Array {
return this.serialize();
}
static deserializeBinary(bytes: Uint8Array): UpdateContactRequest {
return UpdateContactRequest.deserialize(bytes);
}
}
export class GetContactsRequest extends pb_1.Message {
#one_of_decls: number[][] = [];
constructor(data?: any[] | {
@@ -9603,6 +9742,33 @@ export namespace messages {
responseSerialize: (message: JsonList) => Buffer.from(message.serialize()),
responseDeserialize: (bytes: Buffer) => JsonList.deserialize(new Uint8Array(bytes))
},
UpdateContact: {
path: "/messages.MessageService/UpdateContact",
requestStream: false,
responseStream: false,
requestSerialize: (message: UpdateContactRequest) => Buffer.from(message.serialize()),
requestDeserialize: (bytes: Buffer) => UpdateContactRequest.deserialize(new Uint8Array(bytes)),
responseSerialize: (message: Empty) => Buffer.from(message.serialize()),
responseDeserialize: (bytes: Buffer) => Empty.deserialize(new Uint8Array(bytes))
},
GetContacts: {
path: "/messages.MessageService/GetContacts",
requestStream: false,
responseStream: false,
requestSerialize: (message: GetContactsRequest) => Buffer.from(message.serialize()),
requestDeserialize: (bytes: Buffer) => GetContactsRequest.deserialize(new Uint8Array(bytes)),
responseSerialize: (message: JsonList) => Buffer.from(message.serialize()),
responseDeserialize: (bytes: Buffer) => JsonList.deserialize(new Uint8Array(bytes))
},
GetContactById: {
path: "/messages.MessageService/GetContactById",
requestStream: false,
responseStream: false,
requestSerialize: (message: EntityByIdRequest) => Buffer.from(message.serialize()),
requestDeserialize: (bytes: Buffer) => EntityByIdRequest.deserialize(new Uint8Array(bytes)),
responseSerialize: (message: Json) => Buffer.from(message.serialize()),
responseDeserialize: (bytes: Buffer) => Json.deserialize(new Uint8Array(bytes))
},
CancelEventMessage: {
path: "/messages.MessageService/CancelEventMessage",
requestStream: false,
@@ -9639,24 +9805,6 @@ export namespace messages {
responseSerialize: (message: JsonList) => Buffer.from(message.serialize()),
responseDeserialize: (bytes: Buffer) => JsonList.deserialize(new Uint8Array(bytes))
},
GetContacts: {
path: "/messages.MessageService/GetContacts",
requestStream: false,
responseStream: false,
requestSerialize: (message: GetContactsRequest) => Buffer.from(message.serialize()),
requestDeserialize: (bytes: Buffer) => GetContactsRequest.deserialize(new Uint8Array(bytes)),
responseSerialize: (message: JsonList) => Buffer.from(message.serialize()),
responseDeserialize: (bytes: Buffer) => JsonList.deserialize(new Uint8Array(bytes))
},
GetContactById: {
path: "/messages.MessageService/GetContactById",
requestStream: false,
responseStream: false,
requestSerialize: (message: EntityByIdRequest) => Buffer.from(message.serialize()),
requestDeserialize: (bytes: Buffer) => EntityByIdRequest.deserialize(new Uint8Array(bytes)),
responseSerialize: (message: Json) => Buffer.from(message.serialize()),
responseDeserialize: (bytes: Buffer) => Json.deserialize(new Uint8Array(bytes))
},
GetChats: {
path: "/messages.MessageService/GetChats",
requestStream: false,
@@ -9722,12 +9870,13 @@ export namespace messages {
abstract RemoveChatLabel(call: grpc_1.ServerUnaryCall<ChatLabelRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
abstract GetLabelsByJid(call: grpc_1.ServerUnaryCall<EntityByIdRequest, JsonList>, callback: grpc_1.sendUnaryData<JsonList>): void;
abstract GetChatsByLabelId(call: grpc_1.ServerUnaryCall<EntityByIdRequest, JsonList>, callback: grpc_1.sendUnaryData<JsonList>): void;
abstract UpdateContact(call: grpc_1.ServerUnaryCall<UpdateContactRequest, Empty>, callback: grpc_1.sendUnaryData<Empty>): void;
abstract GetContacts(call: grpc_1.ServerUnaryCall<GetContactsRequest, JsonList>, callback: grpc_1.sendUnaryData<JsonList>): void;
abstract GetContactById(call: grpc_1.ServerUnaryCall<EntityByIdRequest, Json>, callback: grpc_1.sendUnaryData<Json>): void;
abstract CancelEventMessage(call: grpc_1.ServerUnaryCall<CancelEventMessageRequest, MessageResponse>, callback: grpc_1.sendUnaryData<MessageResponse>): void;
abstract DownloadMedia(call: grpc_1.ServerUnaryCall<DownloadMediaRequest, DownloadMediaResponse>, callback: grpc_1.sendUnaryData<DownloadMediaResponse>): void;
abstract GetMessageById(call: grpc_1.ServerUnaryCall<EntityByIdRequest, Json>, callback: grpc_1.sendUnaryData<Json>): void;
abstract GetMessages(call: grpc_1.ServerUnaryCall<GetMessagesRequest, JsonList>, callback: grpc_1.sendUnaryData<JsonList>): void;
abstract GetContacts(call: grpc_1.ServerUnaryCall<GetContactsRequest, JsonList>, callback: grpc_1.sendUnaryData<JsonList>): void;
abstract GetContactById(call: grpc_1.ServerUnaryCall<EntityByIdRequest, Json>, callback: grpc_1.sendUnaryData<Json>): void;
abstract GetChats(call: grpc_1.ServerUnaryCall<GetChatsRequest, JsonList>, callback: grpc_1.sendUnaryData<JsonList>): void;
}
export class MessageServiceClient extends grpc_1.makeGenericClientConstructor(UnimplementedMessageServiceService.definition, "MessageService", {}) {
@@ -9896,6 +10045,15 @@ export namespace messages {
GetChatsByLabelId: GrpcUnaryServiceInterface<EntityByIdRequest, JsonList> = (message: EntityByIdRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, options?: grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, callback?: grpc_1.requestCallback<JsonList>): grpc_1.ClientUnaryCall => {
return super.GetChatsByLabelId(message, metadata, options, callback);
};
UpdateContact: GrpcUnaryServiceInterface<UpdateContactRequest, Empty> = (message: UpdateContactRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<Empty>, options?: grpc_1.CallOptions | grpc_1.requestCallback<Empty>, callback?: grpc_1.requestCallback<Empty>): grpc_1.ClientUnaryCall => {
return super.UpdateContact(message, metadata, options, callback);
};
GetContacts: GrpcUnaryServiceInterface<GetContactsRequest, JsonList> = (message: GetContactsRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, options?: grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, callback?: grpc_1.requestCallback<JsonList>): grpc_1.ClientUnaryCall => {
return super.GetContacts(message, metadata, options, callback);
};
GetContactById: GrpcUnaryServiceInterface<EntityByIdRequest, Json> = (message: EntityByIdRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<Json>, options?: grpc_1.CallOptions | grpc_1.requestCallback<Json>, callback?: grpc_1.requestCallback<Json>): grpc_1.ClientUnaryCall => {
return super.GetContactById(message, metadata, options, callback);
};
CancelEventMessage: GrpcUnaryServiceInterface<CancelEventMessageRequest, MessageResponse> = (message: CancelEventMessageRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<MessageResponse>, options?: grpc_1.CallOptions | grpc_1.requestCallback<MessageResponse>, callback?: grpc_1.requestCallback<MessageResponse>): grpc_1.ClientUnaryCall => {
return super.CancelEventMessage(message, metadata, options, callback);
};
@@ -9908,12 +10066,6 @@ export namespace messages {
GetMessages: GrpcUnaryServiceInterface<GetMessagesRequest, JsonList> = (message: GetMessagesRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, options?: grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, callback?: grpc_1.requestCallback<JsonList>): grpc_1.ClientUnaryCall => {
return super.GetMessages(message, metadata, options, callback);
};
GetContacts: GrpcUnaryServiceInterface<GetContactsRequest, JsonList> = (message: GetContactsRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, options?: grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, callback?: grpc_1.requestCallback<JsonList>): grpc_1.ClientUnaryCall => {
return super.GetContacts(message, metadata, options, callback);
};
GetContactById: GrpcUnaryServiceInterface<EntityByIdRequest, Json> = (message: EntityByIdRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<Json>, options?: grpc_1.CallOptions | grpc_1.requestCallback<Json>, callback?: grpc_1.requestCallback<Json>): grpc_1.ClientUnaryCall => {
return super.GetContactById(message, metadata, options, callback);
};
GetChats: GrpcUnaryServiceInterface<GetChatsRequest, JsonList> = (message: GetChatsRequest, metadata: grpc_1.Metadata | grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, options?: grpc_1.CallOptions | grpc_1.requestCallback<JsonList>, callback?: grpc_1.requestCallback<JsonList>): grpc_1.ClientUnaryCall => {
return super.GetChats(message, metadata, options, callback);
};
+47 -22
View File
@@ -631,6 +631,17 @@ function deserialize_messages_SubscribePresenceRequest(buffer_arg) {
return gows_pb.SubscribePresenceRequest.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_messages_UpdateContactRequest(arg) {
if (!(arg instanceof gows_pb.UpdateContactRequest)) {
throw new Error('Expected argument of type messages.UpdateContactRequest');
}
return Buffer.from(arg.serializeBinary());
}
function deserialize_messages_UpdateContactRequest(buffer_arg) {
return gows_pb.UpdateContactRequest.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_messages_UpdateParticipantsRequest(arg) {
if (!(arg instanceof gows_pb.UpdateParticipantsRequest)) {
throw new Error('Expected argument of type messages.UpdateParticipantsRequest');
@@ -1294,6 +1305,42 @@ getLabels: {
responseDeserialize: deserialize_messages_JsonList,
},
//
// Contacts
//
updateContact: {
path: '/messages.MessageService/UpdateContact',
requestStream: false,
responseStream: false,
requestType: gows_pb.UpdateContactRequest,
responseType: gows_pb.Empty,
requestSerialize: serialize_messages_UpdateContactRequest,
requestDeserialize: deserialize_messages_UpdateContactRequest,
responseSerialize: serialize_messages_Empty,
responseDeserialize: deserialize_messages_Empty,
},
getContacts: {
path: '/messages.MessageService/GetContacts',
requestStream: false,
responseStream: false,
requestType: gows_pb.GetContactsRequest,
responseType: gows_pb.JsonList,
requestSerialize: serialize_messages_GetContactsRequest,
requestDeserialize: deserialize_messages_GetContactsRequest,
responseSerialize: serialize_messages_JsonList,
responseDeserialize: deserialize_messages_JsonList,
},
getContactById: {
path: '/messages.MessageService/GetContactById',
requestStream: false,
responseStream: false,
requestType: gows_pb.EntityByIdRequest,
responseType: gows_pb.Json,
requestSerialize: serialize_messages_EntityByIdRequest,
requestDeserialize: deserialize_messages_EntityByIdRequest,
responseSerialize: serialize_messages_Json,
responseDeserialize: deserialize_messages_Json,
},
//
// Events
//
cancelEventMessage: {
@@ -1346,28 +1393,6 @@ getMessageById: {
responseSerialize: serialize_messages_JsonList,
responseDeserialize: deserialize_messages_JsonList,
},
getContacts: {
path: '/messages.MessageService/GetContacts',
requestStream: false,
responseStream: false,
requestType: gows_pb.GetContactsRequest,
responseType: gows_pb.JsonList,
requestSerialize: serialize_messages_GetContactsRequest,
requestDeserialize: deserialize_messages_GetContactsRequest,
responseSerialize: serialize_messages_JsonList,
responseDeserialize: deserialize_messages_JsonList,
},
getContactById: {
path: '/messages.MessageService/GetContactById',
requestStream: false,
responseStream: false,
requestType: gows_pb.EntityByIdRequest,
responseType: gows_pb.Json,
requestSerialize: serialize_messages_EntityByIdRequest,
requestDeserialize: deserialize_messages_EntityByIdRequest,
responseSerialize: serialize_messages_Json,
responseDeserialize: deserialize_messages_Json,
},
getChats: {
path: '/messages.MessageService/GetChats',
requestStream: false,
+263
View File
@@ -107,6 +107,7 @@ goog.exportSymbol('proto.messages.SortBy', null, global);
goog.exportSymbol('proto.messages.SortBy.Order', null, global);
goog.exportSymbol('proto.messages.StartSessionRequest', null, global);
goog.exportSymbol('proto.messages.SubscribePresenceRequest', null, global);
goog.exportSymbol('proto.messages.UpdateContactRequest', null, global);
goog.exportSymbol('proto.messages.UpdateParticipantsRequest', null, global);
goog.exportSymbol('proto.messages.UpsertLabelRequest', null, global);
goog.exportSymbol('proto.messages.vCardContact', null, global);
@@ -1601,6 +1602,27 @@ if (goog.DEBUG && !COMPILED) {
*/
proto.messages.GetMessagesRequest.displayName = 'proto.messages.GetMessagesRequest';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.messages.UpdateContactRequest = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.messages.UpdateContactRequest, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* @public
* @override
*/
proto.messages.UpdateContactRequest.displayName = 'proto.messages.UpdateContactRequest';
}
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
@@ -16661,6 +16683,247 @@ proto.messages.GetMessagesRequest.prototype.hasPagination = function() {
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* @param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @return {!Object}
*/
proto.messages.UpdateContactRequest.prototype.toObject = function(opt_includeInstance) {
return proto.messages.UpdateContactRequest.toObject(opt_includeInstance, this);
};
/**
* Static version of the {@see toObject} method.
* @param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* @param {!proto.messages.UpdateContactRequest} msg The msg instance to transform.
* @return {!Object}
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.messages.UpdateContactRequest.toObject = function(includeInstance, msg) {
var f, obj = {
session: (f = msg.getSession()) && proto.messages.Session.toObject(includeInstance, f),
jid: jspb.Message.getFieldWithDefault(msg, 2, ""),
firstname: jspb.Message.getFieldWithDefault(msg, 3, ""),
lastname: jspb.Message.getFieldWithDefault(msg, 4, "")
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* @param {jspb.ByteSource} bytes The bytes to deserialize.
* @return {!proto.messages.UpdateContactRequest}
*/
proto.messages.UpdateContactRequest.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.messages.UpdateContactRequest;
return proto.messages.UpdateContactRequest.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* @param {!proto.messages.UpdateContactRequest} msg The message object to deserialize into.
* @param {!jspb.BinaryReader} reader The BinaryReader to use.
* @return {!proto.messages.UpdateContactRequest}
*/
proto.messages.UpdateContactRequest.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = new proto.messages.Session;
reader.readMessage(value,proto.messages.Session.deserializeBinaryFromReader);
msg.setSession(value);
break;
case 2:
var value = /** @type {string} */ (reader.readString());
msg.setJid(value);
break;
case 3:
var value = /** @type {string} */ (reader.readString());
msg.setFirstname(value);
break;
case 4:
var value = /** @type {string} */ (reader.readString());
msg.setLastname(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* @return {!Uint8Array}
*/
proto.messages.UpdateContactRequest.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.messages.UpdateContactRequest.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* @param {!proto.messages.UpdateContactRequest} message
* @param {!jspb.BinaryWriter} writer
* @suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.messages.UpdateContactRequest.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getSession();
if (f != null) {
writer.writeMessage(
1,
f,
proto.messages.Session.serializeBinaryToWriter
);
}
f = message.getJid();
if (f.length > 0) {
writer.writeString(
2,
f
);
}
f = message.getFirstname();
if (f.length > 0) {
writer.writeString(
3,
f
);
}
f = message.getLastname();
if (f.length > 0) {
writer.writeString(
4,
f
);
}
};
/**
* optional Session session = 1;
* @return {?proto.messages.Session}
*/
proto.messages.UpdateContactRequest.prototype.getSession = function() {
return /** @type{?proto.messages.Session} */ (
jspb.Message.getWrapperField(this, proto.messages.Session, 1));
};
/**
* @param {?proto.messages.Session|undefined} value
* @return {!proto.messages.UpdateContactRequest} returns this
*/
proto.messages.UpdateContactRequest.prototype.setSession = function(value) {
return jspb.Message.setWrapperField(this, 1, value);
};
/**
* Clears the message field making it undefined.
* @return {!proto.messages.UpdateContactRequest} returns this
*/
proto.messages.UpdateContactRequest.prototype.clearSession = function() {
return this.setSession(undefined);
};
/**
* Returns whether this field is set.
* @return {boolean}
*/
proto.messages.UpdateContactRequest.prototype.hasSession = function() {
return jspb.Message.getField(this, 1) != null;
};
/**
* optional string jid = 2;
* @return {string}
*/
proto.messages.UpdateContactRequest.prototype.getJid = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, ""));
};
/**
* @param {string} value
* @return {!proto.messages.UpdateContactRequest} returns this
*/
proto.messages.UpdateContactRequest.prototype.setJid = function(value) {
return jspb.Message.setProto3StringField(this, 2, value);
};
/**
* optional string firstName = 3;
* @return {string}
*/
proto.messages.UpdateContactRequest.prototype.getFirstname = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, ""));
};
/**
* @param {string} value
* @return {!proto.messages.UpdateContactRequest} returns this
*/
proto.messages.UpdateContactRequest.prototype.setFirstname = function(value) {
return jspb.Message.setProto3StringField(this, 3, value);
};
/**
* optional string lastName = 4;
* @return {string}
*/
proto.messages.UpdateContactRequest.prototype.getLastname = function() {
return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, ""));
};
/**
* @param {string} value
* @return {!proto.messages.UpdateContactRequest} returns this
*/
proto.messages.UpdateContactRequest.prototype.setLastname = function(value) {
return jspb.Message.setProto3StringField(this, 4, value);
};
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
+14 -1
View File
@@ -1,5 +1,6 @@
import {
aggregateMessageKeysNotFromMe,
Contact,
getContentType,
getUrlFromDirectPath,
isJidGroup,
@@ -86,7 +87,7 @@ import {
SendSeenRequest,
WANumberExistResult,
} from '@waha/structures/chatting.dto';
import { ContactQuery } from '@waha/structures/contacts.dto';
import { ContactQuery, ContactUpdateBody } from '@waha/structures/contacts.dto';
import {
ACK_UNKNOWN,
WAHAEvents,
@@ -1464,6 +1465,18 @@ export class WhatsappSessionGoWSCore extends WhatsappSession {
* Contacts methods
*/
public async upsertContact(chatId: string, body: ContactUpdateBody) {
const jid = toJID(chatId);
const request = new messages.UpdateContactRequest({
session: this.session,
jid: jid,
firstName: body.firstName || '',
lastName: body.lastName || '',
});
const response = await promisify(this.client.UpdateContact)(request);
response.toObject();
}
protected toWAContact(contact) {
return {
id: toCusFormat(contact.Jid),
+27 -1
View File
@@ -121,7 +121,11 @@ import {
SendSeenRequest,
WANumberExistResult,
} from '@waha/structures/chatting.dto';
import { ContactQuery, ContactRequest } from '@waha/structures/contacts.dto';
import {
ContactQuery,
ContactRequest,
ContactUpdateBody,
} from '@waha/structures/contacts.dto';
import {
ACK_UNKNOWN,
SECOND,
@@ -1322,6 +1326,28 @@ export class WhatsappSessionNoWebCore extends WhatsappSession {
/**
* Contacts methods
*/
public async upsertContact(chatId: string, body: ContactUpdateBody) {
const jid = toJID(chatId);
let fullName = body.firstName;
if (body.lastName) {
fullName = `${body.firstName} ${body.lastName}`;
}
const action = {
fullName: fullName,
firstName: body.firstName,
saveOnPrimaryAddressbook: true,
};
await this.sock.addOrEditContact(jid, action);
const updates: Partial<Contact>[] = [
{
id: jid,
name: fullName,
},
];
this.sock.ev.emit('contacts.update', updates);
}
async getContact(query: ContactQuery) {
const jid = toJID(query.contactId);
const contact = await this.store.getContactById(jid);
+19 -2
View File
@@ -80,7 +80,11 @@ import {
SendSeenRequest,
WANumberExistResult,
} from '@waha/structures/chatting.dto';
import { ContactQuery, ContactRequest } from '@waha/structures/contacts.dto';
import {
ContactQuery,
ContactRequest,
ContactUpdateBody,
} from '@waha/structures/contacts.dto';
import {
ACK_UNKNOWN,
SECOND,
@@ -953,6 +957,16 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
/**
* Contacts methods
*/
public async upsertContact(chatId: string, body: ContactUpdateBody) {
const phoneNumber = chatId.split('@')[0];
await this.whatsapp.saveOrEditAddressbookContact(
phoneNumber,
body.firstName,
body.lastName,
true,
);
}
getContact(query: ContactQuery) {
return this.whatsapp
.getContactById(this.ensureSuffix(query.contactId))
@@ -1426,12 +1440,14 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
const messageReceived$ = fromEvent(this.whatsapp, Events.MESSAGE_RECEIVED);
const messagesFromOthers$ = messageReceived$.pipe(
mergeMap((msg: any) => this.processIncomingMessage(msg, true)),
share(),
);
this.events2.get(WAHAEvents.MESSAGE).switch(messagesFromOthers$);
const messageCreate$ = fromEvent(this.whatsapp, Events.MESSAGE_CREATE);
const messagesFromAll$ = messageCreate$.pipe(
mergeMap((msg: any) => this.processIncomingMessage(msg, true)),
share(),
);
this.events2.get(WAHAEvents.MESSAGE_ANY).switch(messagesFromAll$);
@@ -1440,7 +1456,8 @@ export class WhatsappSessionWebJSCore extends WhatsappSession {
Events.MESSAGE_CIPHERTEXT,
);
const messagesWaiting$ = messageCiphertext$.pipe(
mergeMap((msg: any) => this.processIncomingMessage(msg, true)),
mergeMap((msg: any) => this.processIncomingMessage(msg, false)),
share(),
);
this.events2.get(WAHAEvents.MESSAGE_WAITING).switch(messagesWaiting$);
+18
View File
@@ -54,3 +54,21 @@ export class ContactRequest extends SessionBaseRequest {
@IsString()
contactId: string;
}
export class ContactUpdateBody {
@ApiProperty({
description: 'Contact First Name',
example: 'John',
required: true,
})
@IsString()
firstName: string = 'John';
@ApiProperty({
description: 'Contact Last Name',
example: 'Doe',
required: true,
})
@IsString()
lastName: string = 'Doe';
}
+2 -1
View File
@@ -24,7 +24,8 @@ export class SwitchObservable<T> extends Observable<T> {
}
switch(newObservable$: Observable<T>) {
this.subject$.next(newObservable$);
// If newObservable$ is null or undefined, use EMPTY instead
this.subject$.next(newObservable$ || EMPTY);
}
complete() {
+1 -1
View File
@@ -33,7 +33,7 @@ export function getEngineName(): string {
}
export const VERSION: WAHAEnvironment = {
version: '2025.7.5',
version: '2025.7.9',
engine: getEngineName(),
tier: getWAHAVersion(),
browser:
+2 -2
View File
@@ -2,11 +2,11 @@
"waha": {
"gows": {
"repo": "devlikeapro/gows",
"ref": "v1.0.9"
"ref": "v1.0.10"
},
"dashboard": {
"repo": "devlikeapro/dashboard",
"ref": "991857a40b9f745a0c7725031c486bad59370d38"
"ref": "0000e1ffee9bc40b4d3e0ee6eff825ab5bc19f30"
}
}
}
+14 -14
View File
@@ -7,7 +7,7 @@ __metadata:
"@adiwajshing/baileys@github:devlikeapro/Baileys#fork-master-2025-07-04":
version: 6.7.18
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=599231e9f18be6ebe6e8eb48a5c57ec9f587ee5e"
resolution: "@adiwajshing/baileys@https://github.com/devlikeapro/Baileys.git#commit=bca2147eee9de863f5fd58673027a7286e559bed"
dependencies:
"@cacheable/node-cache": ^1.4.0
"@hapi/boom": ^9.1.3
@@ -33,7 +33,7 @@ __metadata:
optional: true
sharp:
optional: true
checksum: 4a0d0221ea30efbbe50dd3c639c45bed677da6688d550787b7c4fa2b3a1bb3992e3d3ebb920be2429113996c02e87a0801f94e6d6609f4ceaf8637b7490691ee
checksum: b20db4943ed6b228e5ec10a6916f4be0f68aee150337c94267e623ab0c6c396191b0d7c82c83bf8efd55f17d8a57c2e339d12fc47c0a8152b45e4c9aaf8f996f
languageName: node
linkType: hard
@@ -2392,19 +2392,19 @@ __metadata:
languageName: node
linkType: hard
"@nestjs/platform-express@npm:^11.0.0":
version: 11.1.3
resolution: "@nestjs/platform-express@npm:11.1.3"
"@nestjs/platform-express@npm:^11.1.5":
version: 11.1.5
resolution: "@nestjs/platform-express@npm:11.1.5"
dependencies:
cors: 2.8.5
express: 5.1.0
multer: 2.0.1
multer: 2.0.2
path-to-regexp: 8.2.0
tslib: 2.8.1
peerDependencies:
"@nestjs/common": ^11.0.0
"@nestjs/core": ^11.0.0
checksum: df28ad07b992b368e83e9b8d0215dd9115ec7e32106a72181843fa0db7ca6b724208bddf4f06505ceae97dc86e27367a109f676b3910d44feb6d771633845005
checksum: de4720511a4a7ac84002b9c778a8698ef80a95c4e925a9edd1f0d46a04dae0c8b0ad3b3c274881ac27aa29da9bde3df789fdb85a5e1d290a1a4c81b6c09ea273
languageName: node
linkType: hard
@@ -9935,9 +9935,9 @@ __metadata:
languageName: node
linkType: hard
"multer@npm:2.0.1":
version: 2.0.1
resolution: "multer@npm:2.0.1"
"multer@npm:2.0.2":
version: 2.0.2
resolution: "multer@npm:2.0.2"
dependencies:
append-field: ^1.0.0
busboy: ^1.6.0
@@ -9946,7 +9946,7 @@ __metadata:
object-assign: ^4.1.1
type-is: ^1.6.18
xtend: ^4.0.2
checksum: bcbc523108c337cdb0a3f2610fd743a8ad0b7ce773f1970c69e9a338ba3d4389ce3a6339a6bf66b80b96a7aa82442ae505121a2eaa07f3e843b342b84ce8bc2f
checksum: 187f3539b3d5b7f80a289288fc21d3e4116ab9ed21ac9b9ceb25272c7344d215e9572f7e7ed01edb876afddf24661b06578f2c0fc67f36655ebb51a13ccf83dc
languageName: node
linkType: hard
@@ -13348,7 +13348,7 @@ __metadata:
"@nestjs/config": ^3.2.3
"@nestjs/core": ^11.0.0
"@nestjs/passport": ^11.0.0
"@nestjs/platform-express": ^11.0.0
"@nestjs/platform-express": ^11.1.5
"@nestjs/platform-ws": ^11.0.0
"@nestjs/schematics": ^11.0.0
"@nestjs/serve-static": ^5.0.0
@@ -13525,7 +13525,7 @@ __metadata:
"whatsapp-web.js@github:devlikeapro/whatsapp-web.js#fork-main-2025-06-09":
version: 1.30.1-alpha.2
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=c133ae4a347ba7b21b647c8c6811f58c55b21069"
resolution: "whatsapp-web.js@https://github.com/devlikeapro/whatsapp-web.js.git#commit=3db9c9d867a0cb5be8525552ad2dc7de9ba42580"
dependencies:
"@pedroslopez/moduleraid": ^5.0.2
archiver: ^5.3.1
@@ -13543,7 +13543,7 @@ __metadata:
optional: true
unzipper:
optional: true
checksum: e99e0c5172e4045098ef0cd027304b1f5d37b6ce1ae00f1b50f0ca59e5a0894faeca9972e7db88f1d0e6aebb3ca67c3d3cac333f594ab31ffeb166414e4eeb19
checksum: 6aeee54f021f48fcd73df7b3b26f785fe9ae376715b76de53d7a491dec60ff281b149754fab20be01192ff9bf7aa246a18475b14a69fb6e006ae23985b95ebcb
languageName: node
linkType: hard