mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-09-04 05:28:25 -06:00
Compare commits
No commits in common. "main" and "2.3.1" have entirely different histories.
15
CHANGELOG.md
15
CHANGELOG.md
@ -1,17 +1,4 @@
|
|||||||
# 2.3.2 (2025-09-02)
|
# 2.3.1 (develop)
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* Add support to socks proxy
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
* Added key id into webhook payload in n8n service
|
|
||||||
* Enhance RabbitMQ controller with improved connection management and shutdown procedures
|
|
||||||
* Convert outgoing images to JPEG before sending with Chatwoot
|
|
||||||
* Update baileys dependency to version 6.7.19
|
|
||||||
|
|
||||||
# 2.3.1 (2025-07-29)
|
|
||||||
|
|
||||||
### Feature
|
### Feature
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
[](https://hub.docker.com/r/evoapicloud/evolution-api)
|
[]
|
||||||
[](https://evolution-api.com/whatsapp)
|
[](https://evolution-api.com/whatsapp)
|
||||||
[](https://evolution-api.com/discord)
|
[](https://evolution-api.com/discord)
|
||||||
[](https://evolution-api.com/postman)
|
[](https://evolution-api.com/postman)
|
||||||
|
@ -1,75 +1,83 @@
|
|||||||
version: "3.8"
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
api:
|
api:
|
||||||
container_name: evolution_api
|
container_name: evolution_api
|
||||||
image: evoapicloud/evolution-api:latest
|
image: evoapicloud/evolution-api:latest
|
||||||
restart: always
|
restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- redis
|
||||||
- evolution-postgres
|
- postgres
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:8080:8080"
|
- 8080:8080
|
||||||
volumes:
|
volumes:
|
||||||
- evolution_instances:/evolution/instances
|
- evolution_instances:/evolution/instances
|
||||||
networks:
|
networks:
|
||||||
- evolution-net
|
- evolution-net
|
||||||
- dokploy-network
|
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
expose:
|
expose:
|
||||||
- "8080"
|
- 8080
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
container_name: evolution_redis
|
|
||||||
image: redis:latest
|
image: redis:latest
|
||||||
restart: always
|
networks:
|
||||||
|
- evolution-net
|
||||||
|
container_name: redis
|
||||||
command: >
|
command: >
|
||||||
redis-server --port 6379 --appendonly yes
|
redis-server --port 6379 --appendonly yes
|
||||||
volumes:
|
volumes:
|
||||||
- evolution_redis:/data
|
- evolution_redis:/data
|
||||||
networks:
|
ports:
|
||||||
evolution-net:
|
- 6379:6379
|
||||||
aliases:
|
|
||||||
- evolution-redis
|
|
||||||
dokploy-network:
|
|
||||||
aliases:
|
|
||||||
- evolution-redis
|
|
||||||
expose:
|
|
||||||
- "6379"
|
|
||||||
|
|
||||||
evolution-postgres:
|
postgres:
|
||||||
container_name: evolution_postgres
|
container_name: postgres
|
||||||
image: postgres:15
|
image: postgres:15
|
||||||
restart: always
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
command:
|
|
||||||
- postgres
|
|
||||||
- -c
|
|
||||||
- max_connections=1000
|
|
||||||
- -c
|
|
||||||
- listen_addresses=*
|
|
||||||
environment:
|
|
||||||
- POSTGRES_DB=${POSTGRES_DATABASE}
|
|
||||||
- POSTGRES_USER=${POSTGRES_USERNAME}
|
|
||||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
|
||||||
volumes:
|
|
||||||
- postgres_data:/var/lib/postgresql/data
|
|
||||||
networks:
|
networks:
|
||||||
- evolution-net
|
- evolution-net
|
||||||
- dokploy-network
|
command: [
|
||||||
expose:
|
"postgres",
|
||||||
- "5432"
|
"-c", "max_connections=200",
|
||||||
|
"-c", "listen_addresses=*",
|
||||||
|
"-c", "shared_buffers=256MB",
|
||||||
|
"-c", "effective_cache_size=1GB",
|
||||||
|
"-c", "work_mem=4MB"
|
||||||
|
]
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=user
|
||||||
|
- POSTGRES_PASSWORD=pass
|
||||||
|
- POSTGRES_DB=evolution_db
|
||||||
|
- POSTGRES_HOST_AUTH_METHOD=trust
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
|
||||||
|
# pgbouncer:
|
||||||
|
# image: edoburu/pgbouncer:latest
|
||||||
|
# environment:
|
||||||
|
# DB_HOST: postgres
|
||||||
|
# DB_USER: user
|
||||||
|
# DB_PASSWORD: pass
|
||||||
|
# POOL_MODE: transaction
|
||||||
|
# AUTH_TYPE: trust
|
||||||
|
# MAX_CLIENT_CONN: 1000
|
||||||
|
# DEFAULT_POOL_SIZE: 25
|
||||||
|
# depends_on:
|
||||||
|
# - postgres
|
||||||
|
# ports:
|
||||||
|
# - "6543:5432"
|
||||||
|
# networks:
|
||||||
|
# - evolution-net
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
evolution_instances:
|
evolution_instances:
|
||||||
evolution_redis:
|
evolution_redis:
|
||||||
postgres_data:
|
postgres_data:
|
||||||
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
evolution-net:
|
evolution-net:
|
||||||
name: evolution-net
|
name: evolution-net
|
||||||
driver: bridge
|
driver: bridge
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
72
package-lock.json
generated
72
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "evolution-api",
|
"name": "evolution-api",
|
||||||
"version": "2.3.2",
|
"version": "2.3.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "evolution-api",
|
"name": "evolution-api",
|
||||||
"version": "2.3.2",
|
"version": "2.3.1",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adiwajshing/keyed-db": "^0.2.4",
|
"@adiwajshing/keyed-db": "^0.2.4",
|
||||||
@ -60,7 +60,6 @@
|
|||||||
"sharp": "^0.34.2",
|
"sharp": "^0.34.2",
|
||||||
"socket.io": "^4.8.1",
|
"socket.io": "^4.8.1",
|
||||||
"socket.io-client": "^4.8.1",
|
"socket.io-client": "^4.8.1",
|
||||||
"socks-proxy-agent": "^8.0.5",
|
|
||||||
"swagger-ui-express": "^5.0.1",
|
"swagger-ui-express": "^5.0.1",
|
||||||
"tsup": "^8.3.5"
|
"tsup": "^8.3.5"
|
||||||
},
|
},
|
||||||
@ -4986,8 +4985,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/baileys": {
|
"node_modules/baileys": {
|
||||||
"version": "6.7.19",
|
"version": "6.7.18",
|
||||||
"resolved": "git+ssh://git@github.com/WhiskeySockets/Baileys.git#9e04cce8d3eeb16025283a57849cc83aa26c6dd1",
|
"resolved": "git+ssh://git@github.com/WhiskeySockets/Baileys.git#b7876da2e5d8d4d4b391e215b48b668517b86f3e",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -7740,19 +7739,6 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ip-address": {
|
|
||||||
"version": "9.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
|
|
||||||
"integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"jsbn": "1.1.0",
|
|
||||||
"sprintf-js": "^1.1.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ipaddr.js": {
|
"node_modules/ipaddr.js": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
|
||||||
@ -8263,12 +8249,6 @@
|
|||||||
"js-yaml": "bin/js-yaml.js"
|
"js-yaml": "bin/js-yaml.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jsbn": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/json-buffer": {
|
"node_modules/json-buffer": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
||||||
@ -10781,16 +10761,6 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/smart-buffer": {
|
|
||||||
"version": "4.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
|
|
||||||
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 6.0.0",
|
|
||||||
"npm": ">= 3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/socket.io": {
|
"node_modules/socket.io": {
|
||||||
"version": "4.8.1",
|
"version": "4.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz",
|
||||||
@ -10927,34 +10897,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/socks": {
|
|
||||||
"version": "2.8.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.6.tgz",
|
|
||||||
"integrity": "sha512-pe4Y2yzru68lXCb38aAqRf5gvN8YdjP1lok5o0J7BOHljkyCGKVz7H3vpVIXKD27rj2giOJ7DwVyk/GWrPHDWA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"ip-address": "^9.0.5",
|
|
||||||
"smart-buffer": "^4.2.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10.0.0",
|
|
||||||
"npm": ">= 3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/socks-proxy-agent": {
|
|
||||||
"version": "8.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
|
|
||||||
"integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"agent-base": "^7.1.2",
|
|
||||||
"debug": "^4.3.4",
|
|
||||||
"socks": "^2.8.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/sonic-boom": {
|
"node_modules/sonic-boom": {
|
||||||
"version": "3.8.1",
|
"version": "3.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz",
|
||||||
@ -10979,12 +10921,6 @@
|
|||||||
"node": ">= 10.x"
|
"node": ">= 10.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/sprintf-js": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
|
|
||||||
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/statuses": {
|
"node_modules/statuses": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "evolution-api",
|
"name": "evolution-api",
|
||||||
"version": "2.3.2",
|
"version": "2.3.1",
|
||||||
"description": "Rest api for communication with WhatsApp",
|
"description": "Rest api for communication with WhatsApp",
|
||||||
"main": "./dist/main.js",
|
"main": "./dist/main.js",
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
@ -100,7 +100,6 @@
|
|||||||
"sharp": "^0.34.2",
|
"sharp": "^0.34.2",
|
||||||
"socket.io": "^4.8.1",
|
"socket.io": "^4.8.1",
|
||||||
"socket.io-client": "^4.8.1",
|
"socket.io-client": "^4.8.1",
|
||||||
"socks-proxy-agent": "^8.0.5",
|
|
||||||
"swagger-ui-express": "^5.0.1",
|
"swagger-ui-express": "^5.0.1",
|
||||||
"tsup": "^8.3.5"
|
"tsup": "^8.3.5"
|
||||||
},
|
},
|
||||||
|
@ -647,22 +647,22 @@ model IsOnWhatsapp {
|
|||||||
|
|
||||||
model N8n {
|
model N8n {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
enabled Boolean @default(true) @db.TinyInt(1)
|
enabled Boolean @default(true) @db.Boolean
|
||||||
description String? @db.VarChar(255)
|
description String? @db.VarChar(255)
|
||||||
webhookUrl String? @db.VarChar(255)
|
webhookUrl String? @db.VarChar(255)
|
||||||
basicAuthUser String? @db.VarChar(255)
|
basicAuthUser String? @db.VarChar(255)
|
||||||
basicAuthPass String? @db.VarChar(255)
|
basicAuthPass String? @db.VarChar(255)
|
||||||
expire Int? @default(0) @db.Int
|
expire Int? @default(0) @db.Int
|
||||||
keywordFinish String? @db.VarChar(100)
|
keywordFinish String? @db.VarChar(100)
|
||||||
delayMessage Int? @db.Int
|
delayMessage Int? @db.Integer
|
||||||
unknownMessage String? @db.VarChar(100)
|
unknownMessage String? @db.VarChar(100)
|
||||||
listeningFromMe Boolean? @default(false)
|
listeningFromMe Boolean? @default(false)
|
||||||
stopBotFromMe Boolean? @default(false)
|
stopBotFromMe Boolean? @default(false)
|
||||||
keepOpen Boolean? @default(false)
|
keepOpen Boolean? @default(false)
|
||||||
debounceTime Int? @db.Int
|
debounceTime Int? @db.Integer
|
||||||
ignoreJids Json?
|
ignoreJids Json?
|
||||||
splitMessages Boolean? @default(false)
|
splitMessages Boolean? @default(false)
|
||||||
timePerChar Int? @default(50) @db.Int
|
timePerChar Int? @default(50) @db.Integer
|
||||||
triggerType TriggerType?
|
triggerType TriggerType?
|
||||||
triggerOperator TriggerOperator?
|
triggerOperator TriggerOperator?
|
||||||
triggerValue String?
|
triggerValue String?
|
||||||
@ -677,15 +677,15 @@ model N8nSetting {
|
|||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
expire Int? @default(0) @db.Int
|
expire Int? @default(0) @db.Int
|
||||||
keywordFinish String? @db.VarChar(100)
|
keywordFinish String? @db.VarChar(100)
|
||||||
delayMessage Int? @db.Int
|
delayMessage Int? @db.Integer
|
||||||
unknownMessage String? @db.VarChar(100)
|
unknownMessage String? @db.VarChar(100)
|
||||||
listeningFromMe Boolean? @default(false)
|
listeningFromMe Boolean? @default(false)
|
||||||
stopBotFromMe Boolean? @default(false)
|
stopBotFromMe Boolean? @default(false)
|
||||||
keepOpen Boolean? @default(false)
|
keepOpen Boolean? @default(false)
|
||||||
debounceTime Int? @db.Int
|
debounceTime Int? @db.Integer
|
||||||
ignoreJids Json?
|
ignoreJids Json?
|
||||||
splitMessages Boolean? @default(false)
|
splitMessages Boolean? @default(false)
|
||||||
timePerChar Int? @default(50) @db.Int
|
timePerChar Int? @default(50) @db.Integer
|
||||||
createdAt DateTime? @default(now()) @db.Timestamp
|
createdAt DateTime? @default(now()) @db.Timestamp
|
||||||
updatedAt DateTime @updatedAt @db.Timestamp
|
updatedAt DateTime @updatedAt @db.Timestamp
|
||||||
Fallback N8n? @relation(fields: [n8nIdFallback], references: [id])
|
Fallback N8n? @relation(fields: [n8nIdFallback], references: [id])
|
||||||
@ -696,21 +696,21 @@ model N8nSetting {
|
|||||||
|
|
||||||
model Evoai {
|
model Evoai {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
enabled Boolean @default(true) @db.TinyInt(1)
|
enabled Boolean @default(true) @db.Boolean
|
||||||
description String? @db.VarChar(255)
|
description String? @db.VarChar(255)
|
||||||
agentUrl String? @db.VarChar(255)
|
agentUrl String? @db.VarChar(255)
|
||||||
apiKey String? @db.VarChar(255)
|
apiKey String? @db.VarChar(255)
|
||||||
expire Int? @default(0) @db.Int
|
expire Int? @default(0) @db.Int
|
||||||
keywordFinish String? @db.VarChar(100)
|
keywordFinish String? @db.VarChar(100)
|
||||||
delayMessage Int? @db.Int
|
delayMessage Int? @db.Integer
|
||||||
unknownMessage String? @db.VarChar(100)
|
unknownMessage String? @db.VarChar(100)
|
||||||
listeningFromMe Boolean? @default(false)
|
listeningFromMe Boolean? @default(false)
|
||||||
stopBotFromMe Boolean? @default(false)
|
stopBotFromMe Boolean? @default(false)
|
||||||
keepOpen Boolean? @default(false)
|
keepOpen Boolean? @default(false)
|
||||||
debounceTime Int? @db.Int
|
debounceTime Int? @db.Integer
|
||||||
ignoreJids Json?
|
ignoreJids Json?
|
||||||
splitMessages Boolean? @default(false)
|
splitMessages Boolean? @default(false)
|
||||||
timePerChar Int? @default(50) @db.Int
|
timePerChar Int? @default(50) @db.Integer
|
||||||
triggerType TriggerType?
|
triggerType TriggerType?
|
||||||
triggerOperator TriggerOperator?
|
triggerOperator TriggerOperator?
|
||||||
triggerValue String?
|
triggerValue String?
|
||||||
@ -725,15 +725,15 @@ model EvoaiSetting {
|
|||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
expire Int? @default(0) @db.Int
|
expire Int? @default(0) @db.Int
|
||||||
keywordFinish String? @db.VarChar(100)
|
keywordFinish String? @db.VarChar(100)
|
||||||
delayMessage Int? @db.Int
|
delayMessage Int? @db.Integer
|
||||||
unknownMessage String? @db.VarChar(100)
|
unknownMessage String? @db.VarChar(100)
|
||||||
listeningFromMe Boolean? @default(false)
|
listeningFromMe Boolean? @default(false)
|
||||||
stopBotFromMe Boolean? @default(false)
|
stopBotFromMe Boolean? @default(false)
|
||||||
keepOpen Boolean? @default(false)
|
keepOpen Boolean? @default(false)
|
||||||
debounceTime Int? @db.Int
|
debounceTime Int? @db.Integer
|
||||||
ignoreJids Json?
|
ignoreJids Json?
|
||||||
splitMessages Boolean? @default(false)
|
splitMessages Boolean? @default(false)
|
||||||
timePerChar Int? @default(50) @db.Int
|
timePerChar Int? @default(50) @db.Integer
|
||||||
createdAt DateTime? @default(now()) @db.Timestamp
|
createdAt DateTime? @default(now()) @db.Timestamp
|
||||||
updatedAt DateTime @updatedAt @db.Timestamp
|
updatedAt DateTime @updatedAt @db.Timestamp
|
||||||
Fallback Evoai? @relation(fields: [evoaiIdFallback], references: [id])
|
Fallback Evoai? @relation(fields: [evoaiIdFallback], references: [id])
|
||||||
|
@ -6,4 +6,14 @@ Warnings:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
-- AlterTable
|
-- AlterTable
|
||||||
ALTER TABLE "Setting" ADD COLUMN IF NOT EXISTS "wavoipToken" VARCHAR(100);
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_name = 'Setting'
|
||||||
|
AND column_name = 'wavoipToken'
|
||||||
|
) THEN
|
||||||
|
ALTER TABLE "Setting" ADD COLUMN "wavoipToken" VARCHAR(100);
|
||||||
|
END IF;
|
||||||
|
END $$;
|
@ -53,21 +53,15 @@ export class ProxyController {
|
|||||||
httpsAgent: makeProxyAgent(proxy),
|
httpsAgent: makeProxyAgent(proxy),
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = response?.data !== serverIp?.data;
|
return response?.data !== serverIp?.data;
|
||||||
if (result) {
|
|
||||||
logger.info('testProxy: proxy connection successful');
|
|
||||||
} else {
|
|
||||||
logger.warn("testProxy: proxy connection doesn't change the origin IP");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (axios.isAxiosError(error)) {
|
if (axios.isAxiosError(error) && error.response?.data) {
|
||||||
logger.error('testProxy error: axios error: ' + error.message);
|
logger.error('testProxy error: ' + error.response.data);
|
||||||
|
} else if (axios.isAxiosError(error)) {
|
||||||
|
logger.error('testProxy error: ');
|
||||||
} else {
|
} else {
|
||||||
logger.error('testProxy error: unexpected error: ' + error);
|
logger.error('testProxy error: ');
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1446,7 +1446,16 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const findMessage = await this.prismaRepository.message.findFirst({
|
||||||
|
where: { instanceId: this.instanceId, key: { path: ['id'], equals: key.id } },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!findMessage) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const message: any = {
|
const message: any = {
|
||||||
|
messageId: findMessage.id,
|
||||||
keyId: key.id,
|
keyId: key.id,
|
||||||
remoteJid: key?.remoteJid,
|
remoteJid: key?.remoteJid,
|
||||||
fromMe: key.fromMe,
|
fromMe: key.fromMe,
|
||||||
@ -1456,16 +1465,6 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
instanceId: this.instanceId,
|
instanceId: this.instanceId,
|
||||||
};
|
};
|
||||||
|
|
||||||
let findMessage: any;
|
|
||||||
const configDatabaseData = this.configService.get<Database>('DATABASE').SAVE_DATA;
|
|
||||||
if (configDatabaseData.HISTORIC || configDatabaseData.NEW_MESSAGE) {
|
|
||||||
findMessage = await this.prismaRepository.message.findFirst({
|
|
||||||
where: { instanceId: this.instanceId, key: { path: ['id'], equals: key.id } },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (findMessage) message.messageId = findMessage.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (update.message === null && update.status === undefined) {
|
if (update.message === null && update.status === undefined) {
|
||||||
this.sendDataWebhook(Events.MESSAGES_DELETE, key);
|
this.sendDataWebhook(Events.MESSAGES_DELETE, key);
|
||||||
|
|
||||||
@ -1481,9 +1480,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
} else if (update.status !== undefined && status[update.status] !== findMessage.status) {
|
||||||
|
|
||||||
if (findMessage && update.status !== undefined && status[update.status] !== findMessage.status) {
|
|
||||||
if (!key.fromMe && key.remoteJid) {
|
if (!key.fromMe && key.remoteJid) {
|
||||||
readChatToUpdate[key.remoteJid] = true;
|
readChatToUpdate[key.remoteJid] = true;
|
||||||
|
|
||||||
@ -2448,43 +2445,9 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
try {
|
try {
|
||||||
const type = mediaMessage.mediatype === 'ptv' ? 'video' : mediaMessage.mediatype;
|
const type = mediaMessage.mediatype === 'ptv' ? 'video' : mediaMessage.mediatype;
|
||||||
|
|
||||||
let mediaInput: any;
|
|
||||||
if (mediaMessage.mediatype === 'image') {
|
|
||||||
let imageBuffer: Buffer;
|
|
||||||
if (isURL(mediaMessage.media)) {
|
|
||||||
let config: any = { responseType: 'arraybuffer' };
|
|
||||||
|
|
||||||
if (this.localProxy?.enabled) {
|
|
||||||
config = {
|
|
||||||
...config,
|
|
||||||
httpsAgent: makeProxyAgent({
|
|
||||||
host: this.localProxy.host,
|
|
||||||
port: this.localProxy.port,
|
|
||||||
protocol: this.localProxy.protocol,
|
|
||||||
username: this.localProxy.username,
|
|
||||||
password: this.localProxy.password,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await axios.get(mediaMessage.media, config);
|
|
||||||
imageBuffer = Buffer.from(response.data, 'binary');
|
|
||||||
} else {
|
|
||||||
imageBuffer = Buffer.from(mediaMessage.media, 'base64');
|
|
||||||
}
|
|
||||||
|
|
||||||
mediaInput = await sharp(imageBuffer).jpeg().toBuffer();
|
|
||||||
mediaMessage.fileName ??= 'image.jpg';
|
|
||||||
mediaMessage.mimetype = 'image/jpeg';
|
|
||||||
} else {
|
|
||||||
mediaInput = isURL(mediaMessage.media)
|
|
||||||
? { url: mediaMessage.media }
|
|
||||||
: Buffer.from(mediaMessage.media, 'base64');
|
|
||||||
}
|
|
||||||
|
|
||||||
const prepareMedia = await prepareWAMessageMedia(
|
const prepareMedia = await prepareWAMessageMedia(
|
||||||
{
|
{
|
||||||
[type]: mediaInput,
|
[type]: isURL(mediaMessage.media) ? { url: mediaMessage.media } : Buffer.from(mediaMessage.media, 'base64'),
|
||||||
} as any,
|
} as any,
|
||||||
{ upload: this.client.waUploadToServer },
|
{ upload: this.client.waUploadToServer },
|
||||||
);
|
);
|
||||||
@ -2498,7 +2461,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mediaMessage.mediatype === 'image' && !mediaMessage.fileName) {
|
if (mediaMessage.mediatype === 'image' && !mediaMessage.fileName) {
|
||||||
mediaMessage.fileName = 'image.jpg';
|
mediaMessage.fileName = 'image.png';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mediaMessage.mediatype === 'video' && !mediaMessage.fileName) {
|
if (mediaMessage.mediatype === 'video' && !mediaMessage.fileName) {
|
||||||
@ -3475,20 +3438,17 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
where: { id: message.id },
|
where: { id: message.id },
|
||||||
data: { key: { ...existingKey, deleted: true }, status: 'DELETED' },
|
data: { key: { ...existingKey, deleted: true }, status: 'DELETED' },
|
||||||
});
|
});
|
||||||
if (this.configService.get<Database>('DATABASE').SAVE_DATA.MESSAGE_UPDATE) {
|
const messageUpdate: any = {
|
||||||
const messageUpdate: any = {
|
messageId: message.id,
|
||||||
messageId: message.id,
|
keyId: messageId,
|
||||||
keyId: messageId,
|
remoteJid: response.key.remoteJid,
|
||||||
remoteJid: response.key.remoteJid,
|
fromMe: response.key.fromMe,
|
||||||
fromMe: response.key.fromMe,
|
participant: response.key?.remoteJid,
|
||||||
participant: response.key?.remoteJid,
|
status: 'DELETED',
|
||||||
status: 'DELETED',
|
instanceId: this.instanceId,
|
||||||
instanceId: this.instanceId,
|
};
|
||||||
};
|
await this.prismaRepository.messageUpdate.create({ data: messageUpdate });
|
||||||
await this.prismaRepository.messageUpdate.create({ data: messageUpdate });
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (!message) return response;
|
|
||||||
await this.prismaRepository.message.deleteMany({ where: { id: message.id } });
|
await this.prismaRepository.message.deleteMany({ where: { id: message.id } });
|
||||||
}
|
}
|
||||||
this.sendDataWebhook(Events.MESSAGES_DELETE, {
|
this.sendDataWebhook(Events.MESSAGES_DELETE, {
|
||||||
@ -3820,10 +3780,6 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
|
|
||||||
private async formatUpdateMessage(data: UpdateMessageDto) {
|
private async formatUpdateMessage(data: UpdateMessageDto) {
|
||||||
try {
|
try {
|
||||||
if (!this.configService.get<Database>('DATABASE').SAVE_DATA.NEW_MESSAGE) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
const msg: any = await this.getMessage(data.key, true);
|
const msg: any = await this.getMessage(data.key, true);
|
||||||
|
|
||||||
if (msg?.messageType === 'conversation' || msg?.messageType === 'extendedTextMessage') {
|
if (msg?.messageType === 'conversation' || msg?.messageType === 'extendedTextMessage') {
|
||||||
@ -3857,15 +3813,13 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const oldMessage: any = await this.getMessage(data.key, true);
|
const oldMessage: any = await this.getMessage(data.key, true);
|
||||||
if (this.configService.get<Database>('DATABASE').SAVE_DATA.NEW_MESSAGE) {
|
if (!oldMessage) throw new NotFoundException('Message not found');
|
||||||
if (!oldMessage) throw new NotFoundException('Message not found');
|
if (oldMessage?.key?.remoteJid !== jid) {
|
||||||
if (oldMessage?.key?.remoteJid !== jid) {
|
throw new BadRequestException('RemoteJid does not match');
|
||||||
throw new BadRequestException('RemoteJid does not match');
|
}
|
||||||
}
|
if (oldMessage?.messageTimestamp > Date.now() + 900000) {
|
||||||
if (oldMessage?.messageTimestamp > Date.now() + 900000) {
|
// 15 minutes in milliseconds
|
||||||
// 15 minutes in milliseconds
|
throw new BadRequestException('Message is older than 15 minutes');
|
||||||
throw new BadRequestException('Message is older than 15 minutes');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageSent = await this.client.sendMessage(jid, { ...(options as any), edit: data.key });
|
const messageSent = await this.client.sendMessage(jid, { ...(options as any), edit: data.key });
|
||||||
@ -3883,7 +3837,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const messageId = messageSent.message?.protocolMessage?.key?.id;
|
const messageId = messageSent.message?.protocolMessage?.key?.id;
|
||||||
if (messageId && this.configService.get<Database>('DATABASE').SAVE_DATA.NEW_MESSAGE) {
|
if (messageId) {
|
||||||
let message = await this.prismaRepository.message.findFirst({
|
let message = await this.prismaRepository.message.findFirst({
|
||||||
where: { key: { path: ['id'], equals: messageId } },
|
where: { key: { path: ['id'], equals: messageId } },
|
||||||
});
|
});
|
||||||
@ -3895,7 +3849,6 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
if ((message.key.valueOf() as any)?.deleted) {
|
if ((message.key.valueOf() as any)?.deleted) {
|
||||||
new BadRequestException('You cannot edit deleted messages');
|
new BadRequestException('You cannot edit deleted messages');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldMessage.messageType === 'conversation' || oldMessage.messageType === 'extendedTextMessage') {
|
if (oldMessage.messageType === 'conversation' || oldMessage.messageType === 'extendedTextMessage') {
|
||||||
oldMessage.message.conversation = data.text;
|
oldMessage.message.conversation = data.text;
|
||||||
} else {
|
} else {
|
||||||
@ -3909,19 +3862,16 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
messageTimestamp: Math.floor(Date.now() / 1000), // Convert to int32 by dividing by 1000 to get seconds
|
messageTimestamp: Math.floor(Date.now() / 1000), // Convert to int32 by dividing by 1000 to get seconds
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const messageUpdate: any = {
|
||||||
if (this.configService.get<Database>('DATABASE').SAVE_DATA.MESSAGE_UPDATE) {
|
messageId: message.id,
|
||||||
const messageUpdate: any = {
|
keyId: messageId,
|
||||||
messageId: message.id,
|
remoteJid: messageSent.key.remoteJid,
|
||||||
keyId: messageId,
|
fromMe: messageSent.key.fromMe,
|
||||||
remoteJid: messageSent.key.remoteJid,
|
participant: messageSent.key?.remoteJid,
|
||||||
fromMe: messageSent.key.fromMe,
|
status: 'EDITED',
|
||||||
participant: messageSent.key?.remoteJid,
|
instanceId: this.instanceId,
|
||||||
status: 'EDITED',
|
};
|
||||||
instanceId: this.instanceId,
|
await this.prismaRepository.messageUpdate.create({ data: messageUpdate });
|
||||||
};
|
|
||||||
await this.prismaRepository.messageUpdate.create({ data: messageUpdate });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,6 @@ export class N8nService extends BaseChatbotService<N8n, N8nSetting> {
|
|||||||
sessionId: session.sessionId,
|
sessionId: session.sessionId,
|
||||||
remoteJid: remoteJid,
|
remoteJid: remoteJid,
|
||||||
pushName: pushName,
|
pushName: pushName,
|
||||||
keyId: msg?.key?.id,
|
|
||||||
fromMe: msg?.key?.fromMe,
|
fromMe: msg?.key?.fromMe,
|
||||||
instanceName: instance.instanceName,
|
instanceName: instance.instanceName,
|
||||||
serverUrl: this.configService.get<HttpServer>('SERVER').URL,
|
serverUrl: this.configService.get<HttpServer>('SERVER').URL,
|
||||||
|
@ -45,7 +45,7 @@ export class RabbitmqController extends EventController implements EventControll
|
|||||||
heartbeat: 30, // Add heartbeat of 30 seconds
|
heartbeat: 30, // Add heartbeat of 30 seconds
|
||||||
};
|
};
|
||||||
|
|
||||||
amqp.connect(connectionOptions, (error: Error, connection: amqp.Connection) => {
|
amqp.connect(connectionOptions, (error, connection) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
this.logger.error({
|
this.logger.error({
|
||||||
local: 'RabbitmqController.connect',
|
local: 'RabbitmqController.connect',
|
||||||
@ -57,7 +57,7 @@ export class RabbitmqController extends EventController implements EventControll
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Connection event handlers
|
// Connection event handlers
|
||||||
connection.on('error', (err: Error) => {
|
connection.on('error', (err) => {
|
||||||
this.logger.error({
|
this.logger.error({
|
||||||
local: 'RabbitmqController.connectionError',
|
local: 'RabbitmqController.connectionError',
|
||||||
message: 'RabbitMQ connection error',
|
message: 'RabbitMQ connection error',
|
||||||
@ -71,7 +71,7 @@ export class RabbitmqController extends EventController implements EventControll
|
|||||||
this.handleConnectionLoss();
|
this.handleConnectionLoss();
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.createChannel((channelError: Error, channel: amqp.Channel) => {
|
connection.createChannel((channelError, channel) => {
|
||||||
if (channelError) {
|
if (channelError) {
|
||||||
this.logger.error({
|
this.logger.error({
|
||||||
local: 'RabbitmqController.createChannel',
|
local: 'RabbitmqController.createChannel',
|
||||||
@ -83,7 +83,7 @@ export class RabbitmqController extends EventController implements EventControll
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Channel event handlers
|
// Channel event handlers
|
||||||
channel.on('error', (err: Error) => {
|
channel.on('error', (err) => {
|
||||||
this.logger.error({
|
this.logger.error({
|
||||||
local: 'RabbitmqController.channelError',
|
local: 'RabbitmqController.channelError',
|
||||||
message: 'RabbitMQ channel error',
|
message: 'RabbitMQ channel error',
|
||||||
@ -136,7 +136,8 @@ export class RabbitmqController extends EventController implements EventControll
|
|||||||
return; // Already attempting to reconnect
|
return; // Already attempting to reconnect
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cleanup();
|
this.amqpChannel = null;
|
||||||
|
this.amqpConnection = null;
|
||||||
this.scheduleReconnect();
|
this.scheduleReconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,25 +406,4 @@ export class RabbitmqController extends EventController implements EventControll
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async cleanup(): Promise<void> {
|
|
||||||
try {
|
|
||||||
if (this.amqpChannel) {
|
|
||||||
await this.amqpChannel.close();
|
|
||||||
this.amqpChannel = null;
|
|
||||||
}
|
|
||||||
if (this.amqpConnection) {
|
|
||||||
await this.amqpConnection.close();
|
|
||||||
this.amqpConnection = null;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.warn({
|
|
||||||
local: 'RabbitmqController.cleanup',
|
|
||||||
message: 'Error during cleanup',
|
|
||||||
error: error.message || error,
|
|
||||||
});
|
|
||||||
this.amqpChannel = null;
|
|
||||||
this.amqpConnection = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,8 @@ export class WebsocketController extends EventController implements EventControl
|
|||||||
const url = new URL(req.url || '', 'http://localhost');
|
const url = new URL(req.url || '', 'http://localhost');
|
||||||
const params = new URLSearchParams(url.search);
|
const params = new URLSearchParams(url.search);
|
||||||
|
|
||||||
const { remoteAddress } = req.socket;
|
|
||||||
const isLocalhost =
|
|
||||||
remoteAddress === '127.0.0.1' || remoteAddress === '::1' || remoteAddress === '::ffff:127.0.0.1';
|
|
||||||
|
|
||||||
// Permite conexões internas do Socket.IO (EIO=4 é o Engine.IO v4)
|
// Permite conexões internas do Socket.IO (EIO=4 é o Engine.IO v4)
|
||||||
if (params.has('EIO') && isLocalhost) {
|
if (params.has('EIO')) {
|
||||||
return callback(null, true);
|
return callback(null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||||
import { SocksProxyAgent } from 'socks-proxy-agent';
|
|
||||||
|
|
||||||
type Proxy = {
|
type Proxy = {
|
||||||
host: string;
|
host: string;
|
||||||
@ -9,28 +8,9 @@ type Proxy = {
|
|||||||
username?: string;
|
username?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
function selectProxyAgent(proxyUrl: string): HttpsProxyAgent<string> | SocksProxyAgent {
|
export function makeProxyAgent(proxy: Proxy | string) {
|
||||||
const url = new URL(proxyUrl);
|
|
||||||
|
|
||||||
// NOTE: The following constants are not used in the function but are defined for clarity.
|
|
||||||
// When a proxy URL is used to build the URL object, the protocol returned by procotol's property contains a `:` at
|
|
||||||
// the end so, we add the protocol constants without the `:` to avoid confusion.
|
|
||||||
const PROXY_HTTP_PROTOCOL = 'http:';
|
|
||||||
const PROXY_SOCKS_PROTOCOL = 'socks:';
|
|
||||||
|
|
||||||
switch (url.protocol) {
|
|
||||||
case PROXY_HTTP_PROTOCOL:
|
|
||||||
return new HttpsProxyAgent(url);
|
|
||||||
case PROXY_SOCKS_PROTOCOL:
|
|
||||||
return new SocksProxyAgent(url);
|
|
||||||
default:
|
|
||||||
throw new Error(`Unsupported proxy protocol: ${url.protocol}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function makeProxyAgent(proxy: Proxy | string): HttpsProxyAgent<string> | SocksProxyAgent {
|
|
||||||
if (typeof proxy === 'string') {
|
if (typeof proxy === 'string') {
|
||||||
return selectProxyAgent(proxy);
|
return new HttpsProxyAgent(proxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { host, password, port, protocol, username } = proxy;
|
const { host, password, port, protocol, username } = proxy;
|
||||||
@ -39,6 +19,5 @@ export function makeProxyAgent(proxy: Proxy | string): HttpsProxyAgent<string> |
|
|||||||
if (username && password) {
|
if (username && password) {
|
||||||
proxyUrl = `${protocol}://${username}:${password}@${host}:${port}`;
|
proxyUrl = `${protocol}://${username}:${password}@${host}:${port}`;
|
||||||
}
|
}
|
||||||
|
return new HttpsProxyAgent(proxyUrl);
|
||||||
return selectProxyAgent(proxyUrl);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user