diff --git a/CHANGELOG.md b/CHANGELOG.md index fcf09506..e34529d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +# 1.1.1 (2023-06-28 10:27) + +### Features + +* Added group invitation sending +* Added webhook configuration per event in the individual instance registration + +### Fixed + +* Adjust dockerfile variables + # 1.1.0 (2023-06-21 11:17) ### Features diff --git a/Docker/.env b/Docker/.env deleted file mode 100644 index b0b3ff2a..00000000 --- a/Docker/.env +++ /dev/null @@ -1,87 +0,0 @@ -CORS_ORIGIN='*' # Or separate by commas - ex.: 'yourdomain1.com, yourdomain2.com' -CORS_METHODS='POST,GET,PUT,DELETE' -CORS_CREDENTIALS=true - -# Determine the logs to be displayed -LOG_LEVEL='ERROR,WARN,DEBUG,INFO,LOG,VERBOSE,DARK' -LOG_COLOR=true - -# Determine how long the instance should be deleted from memory in case of no connection. -# Default time: 5 minutes -# If you don't even want an expiration, enter the value false -DEL_INSTANCE=5 - -# Temporary data storage -STORE_MESSAGES=true -STORE_MESSAGE_UP=true -STORE_CONTACTS=false -STORE_CHATS=false - -CLEAN_STORE_CLEANING_INTERVAL=7200 # seconds ===2h -CLEAN_STORE_MESSAGES=true -CLEAN_STORE_MESSAGE_UP=true -CLEAN_STORE_CONTACTS=false -CLEAN_STORE_CHATS=false - -# Permanent data storage -DATABASE_ENABLED=false -DATABASE_CONNECTION_URI='' -DATABASE_CONNECTION_DB_PREFIX_NAME='evolution' -DATABASE_SAVE_DATA_INSTANCE=false -DATABASE_SAVE_DATA_OLD_MESSAGE=false -DATABASE_SAVE_DATA_NEW_MESSAGE=true -DATABASE_SAVE_MESSAGE_UPDATE=true -DATABASE_SAVE_DATA_CONTACTS=true -DATABASE_SAVE_DATA_CHATS=true - -REDIS_ENABLED=true -REDIS_URI='/1' -REDIS_PREFIX_KEY='evolution' - -# Webhook Settings -## Define a global webhook that will listen for enabled events from all instances -WEBHOOK_GLOBAL_URL='' -WEBHOOK_GLOBAL_ENABLED=false -WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=false -## Set the events you want to hear -WEBHOOK_EVENTS_STATUS_INSTANCE=true -WEBHOOK_EVENTS_APPLICATION_STARTUP=true -WEBHOOK_EVENTS_QRCODE_UPDATED=true -WEBHOOK_EVENTS_MESSAGES_SET=true -WEBHOOK_EVENTS_MESSAGES_UPDATE=true -WEBHOOK_EVENTS_MESSAGES_UPSERT=true -WEBHOOK_EVENTS_SEND_MESSAGE=true -WEBHOOK_EVENTS_CONTACTS_SET=true -WEBHOOK_EVENTS_CONTACTS_UPSERT=true -WEBHOOK_EVENTS_CONTACTS_UPDATE=true -WEBHOOK_EVENTS_PRESENCE_UPDATE=true -WEBHOOK_EVENTS_CHATS_SET=true -WEBHOOK_EVENTS_CHATS_UPSERT=true -WEBHOOK_EVENTS_CHATS_UPDATE=true -WEBHOOK_EVENTS_CONNECTION_UPDATE=true -WEBHOOK_EVENTS_GROUPS_UPSERT=false -WEBHOOK_EVENTS_GROUPS_UPDATE=false -WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE=false -## This event fires every time a new token is requested via the refresh route -WEBHOOK_EVENTS_NEW_JWT_TOKEN=true - -CONFIG_SESSION_PHONE_CLIENT='Evolution API' -CONFIG_SESSION_PHONE_NAME='Chrome' - -# Set qrcode display limit -QRCODE_LIMIT=6 - -# Defines an authentication type for the api -AUTHENTICATION_TYPE='jwt' # or 'apikey' -## Define a global apikey to access all instances. -### OBS: This key must be inserted in the request header to create an instance. -AUTHENTICATION_API_KEY='t8OOEeISKzpmc3jjcMqBWYSaJsafdefer' -AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES=true -## Set the secret key to encrypt and decrypt your token and its expiration time -AUTHENTICATION_JWT_EXPIRIN_IN=3600 # seconds - 3600s ===1h | zero (0) - never expires -AUTHENTICATION_JWT_SECRET='L0YWtjb2w554WFqPG' - -AUTHENTICATION_INSTANCE_NAME='evolution' -AUTHENTICATION_INSTANCE_WEBHOOK_URL='' -AUTHENTICATION_INSTANCE_MODE='container' # or 'server' -AUTHENTICATION_INSTANCE_WEBHOOK_BY_EVENTS=false diff --git a/Docker/mongodb/docker-compose.yaml b/Docker/mongodb/docker-compose.yaml new file mode 100644 index 00000000..714109c9 --- /dev/null +++ b/Docker/mongodb/docker-compose.yaml @@ -0,0 +1,27 @@ +version: '3.3' + +networks: + evolution-net: + driver: bridge + +services: + mongodb: + container_name: mongodb + image: mongo + restart: always + volumes: + - evolution_mongodb_data:/data/db + - evolution_mongodb_configdb:/data/configdb + ports: + - 27017:27017 + environment: + MONGO_INITDB_ROOT_USERNAME: root + MONGO_INITDB_ROOT_PASSWORD: root + networks: + - evolution-net + expose: + - 27017 + +volumes: + evolution_mongodb_data: + evolution_mongodb_configdb: \ No newline at end of file diff --git a/Docker/redis/docker-compose.yaml b/Docker/redis/docker-compose.yaml new file mode 100644 index 00000000..f0524630 --- /dev/null +++ b/Docker/redis/docker-compose.yaml @@ -0,0 +1,27 @@ +version: '3.3' + +networks: + evolution-net: + driver: bridge + +services: + redis: + image: redis:latest + command: > + redis-server + --port 6379 + --appendonly yes + --save 900 1 + --save 300 10 + --save 60 10000 + --appendfsync everysec + volumes: + - evolution_redis:/data + container_name: redis + ports: + - 6379:6379 + networks: + - evolution-net + +volumes: + evolution_redis: diff --git a/Dockerfile b/Dockerfile index 919fedf3..50f8e36f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -49,7 +49,6 @@ ENV WEBHOOK_GLOBAL_URL=$WEBHOOK_GLOBAL_URL ENV WEBHOOK_GLOBAL_ENABLED=$WEBHOOK_GLOBAL_ENABLED ENV WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=$WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS -ENV WEBHOOK_EVENTS_STATUS_INSTANCE=$WEBHOOK_EVENTS_STATUS_INSTANCE ENV WEBHOOK_EVENTS_APPLICATION_STARTUP=$WEBHOOK_EVENTS_APPLICATION_STARTUP ENV WEBHOOK_EVENTS_QRCODE_UPDATED=$WEBHOOK_EVENTS_QRCODE_UPDATED ENV WEBHOOK_EVENTS_MESSAGES_SET=$WEBHOOK_EVENTS_MESSAGES_SET @@ -71,7 +70,7 @@ ENV WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE=$WEBHOOK_EVENTS_GROUP_PARTICIPANTS_ ENV WEBHOOK_EVENTS_NEW_JWT_TOKEN=$WEBHOOK_EVENTS_NEW_JWT_TOKEN ENV CONFIG_SESSION_PHONE_CLIENT=$CONFIG_SESSION_PHONE_CLIENT -ENV CONFIG_SESSION_PHONE_NAME="Chrome" +ENV CONFIG_SESSION_PHONE_NAME=$CONFIG_SESSION_PHONE_NAME ENV QRCODE_LIMIT=$QRCODE_LIMIT @@ -86,7 +85,6 @@ ENV AUTHENTICATION_JWT_SECRET="L=0YWt]b2w[WF>#>:&E`" ENV AUTHENTICATION_INSTANCE_NAME=$AUTHENTICATION_INSTANCE_NAME ENV AUTHENTICATION_INSTANCE_WEBHOOK_URL=$AUTHENTICATION_INSTANCE_WEBHOOK_URL ENV AUTHENTICATION_INSTANCE_MODE=$AUTHENTICATION_INSTANCE_MODE -ENV AUTHENTICATION_INSTANCE_WEBHOOK_BY_EVENTS=$AUTHENTICATION_INSTANCE_WEBHOOK_BY_EVENTS RUN npm install diff --git a/docker-compose.yaml b/docker-compose.yaml index d33772c5..8686bd2e 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -13,9 +13,6 @@ services: volumes: - evolution_instances:/evolution/instances - evolution_store:/evolution/store - depends_on: - - mongodb - - redis environment: # Determine how long the instance should be deleted from memory in case of no connection. # Default time: 5 minutes @@ -32,7 +29,7 @@ services: - CLEAN_STORE_CONTACTS=true - CLEAN_STORE_CHATS=true # Permanent data storage - - DATABASE_ENABLED=true + - DATABASE_ENABLED=false - DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true - DATABASE_CONNECTION_DB_PREFIX_NAME=evolution # Choose the data you want to save in the application's database or store @@ -42,23 +39,22 @@ services: - DATABASE_SAVE_MESSAGE_UPDATE=true - DATABASE_SAVE_DATA_CONTACTS=true - DATABASE_SAVE_DATA_CHATS=true - - REDIS_ENABLED=true - - REDIS_URI=redis://redis:6379 + - REDIS_ENABLED=false + - REDIS_URI=redis://redis:6379/1 - REDIS_PREFIX_KEY=evolution # Webhook Settings # Define a global webhook that will listen for enabled events from all instances - - WEBHOOK_GLOBAL_URL=url + - WEBHOOK_GLOBAL_URL= - WEBHOOK_GLOBAL_ENABLED=false # With this option activated, you work with a url per webhook event, respecting the global url and the name of each event - WEBHOOK_GLOBAL_WEBHOOK_BY_EVENTS=false # Automatically maps webhook paths # Set the events you want to hear - - WEBHOOK_EVENTS_STATUS_INSTANCE=true - WEBHOOK_EVENTS_APPLICATION_STARTUP=false - WEBHOOK_EVENTS_QRCODE_UPDATED=true - WEBHOOK_EVENTS_MESSAGES_SET=true - - WEBHOOK_EVENTS_MESSAGES_UPDATE=true - WEBHOOK_EVENTS_MESSAGES_UPSERT=true + - WEBHOOK_EVENTS_MESSAGES_UPDATE=true - WEBHOOK_EVENTS_SEND_MESSAGE=true - WEBHOOK_EVENTS_CONTACTS_SET=true - WEBHOOK_EVENTS_CONTACTS_UPSERT=true @@ -67,14 +63,16 @@ services: - WEBHOOK_EVENTS_CHATS_SET=true - WEBHOOK_EVENTS_CHATS_UPSERT=true - WEBHOOK_EVENTS_CHATS_UPDATE=true - - WEBHOOK_EVENTS_CONNECTION_UPDATE=true + - WEBHOOK_EVENTS_CHATS_DELETE=true - WEBHOOK_EVENTS_GROUPS_UPSERT=true - WEBHOOK_EVENTS_GROUPS_UPDATE=true - WEBHOOK_EVENTS_GROUP_PARTICIPANTS_UPDATE=true + - WEBHOOK_EVENTS_CONNECTION_UPDATE=true # This event fires every time a new token is requested via the refresh route - WEBHOOK_EVENTS_NEW_JWT_TOKEN=true # Name that will be displayed on smartphone connection - - CONFIG_SESSION_PHONE_CLIENT="Evolution API" + - CONFIG_SESSION_PHONE_CLIENT=Evolution API + - CONFIG_SESSION_PHONE_NAME=chrome # chrome | firefox | edge | opera | safari # Set qrcode display limit - QRCODE_LIMIT=30 # Defines an authentication type for the api @@ -88,56 +86,16 @@ services: - AUTHENTICATION_JWT_EXPIRIN_IN=0 # seconds - 3600s === 1h | zero (0) - never expires # Set the instance name and webhook url to create an instance in init the application # With this option activated, you work with a url per webhook event, respecting the local url and the name of each event - - AUTHENTICATION_INSTANCE_WEBHOOK_BY_EVENTS=false - AUTHENTICATION_INSTANCE_MODE=server # container or server # if you are using container mode, set the container name and the webhook url to default instance - AUTHENTICATION_INSTANCE_NAME=evolution - - AUTHENTICATION_INSTANCE_WEBHOOK_URL=url + - AUTHENTICATION_INSTANCE_WEBHOOK_URL= command: ['node', './dist/src/main.js'] networks: - evolution-net expose: - 8080 - mongodb: - container_name: mongodb - image: mongo - restart: always - volumes: - - evolution_mongodb_data:/data/db - - evolution_mongodb_configdb:/data/configdb - ports: - - 27017:27017 - environment: - MONGO_INITDB_ROOT_USERNAME: root - MONGO_INITDB_ROOT_PASSWORD: root - networks: - - evolution-net - expose: - - 27017 - - redis: - image: redis:latest - command: > - redis-server - --port 6379 - --appendonly yes - --save 900 1 - --save 300 10 - --save 60 10000 - --appendfsync everysec - volumes: - - evolution_redis:/data - container_name: redis - ports: - - 6379:6379 - networks: - - evolution-net - - volumes: evolution_instances: - evolution_store: - evolution_mongodb_data: - evolution_mongodb_configdb: - evolution_redis: \ No newline at end of file + evolution_store: \ No newline at end of file diff --git a/docker.sh b/docker.sh index defa76d8..dae560d6 100755 --- a/docker.sh +++ b/docker.sh @@ -8,10 +8,12 @@ then docker network create -d bridge ${NET} fi -sudo mkdir -p ./docker-data/instances -sudo mkdir -p ./docker-data/mongodb -sudo mkdir -p ./docker-data/mongodb/data -sudo mkdir -p ./docker-data/mongodb/configdb +# sudo mkdir -p ./docker-data/instances +# sudo mkdir -p ./docker-data/mongodb +# sudo mkdir -p ./docker-data/mongodb/data +# sudo mkdir -p ./docker-data/mongodb/configdb +# sudo mkdir -p ./docker-data/redis +# sudo mkdir -p ./docker-data/redis/data docker build -t ${IMAGE} . diff --git a/mongodb/docker-compose.yaml b/mongodb/docker-compose.yaml deleted file mode 100644 index 478ecf43..00000000 --- a/mongodb/docker-compose.yaml +++ /dev/null @@ -1,28 +0,0 @@ - -version: '3.8' - -networks: - api-net: - driver: bridge - -services: - mongodb: - container_name: mongodb - - # This image already has a single replica set - image: mongo - - restart: always - volumes: - # sudo mkdir -p /data/mongodb - - /data/mongodb:/data/db - ports: - - 26712:27017 - environment: - MONGO_INITDB_ROOT_USERNAME: root - # Set a password to access the bank - MONGO_INITDB_ROOT_PASSWORD: - networks: - - api-net - expose: - - 26712 diff --git a/src/config/env.config.ts b/src/config/env.config.ts index 2517b4b2..1f09a198 100644 --- a/src/config/env.config.ts +++ b/src/config/env.config.ts @@ -87,7 +87,6 @@ export type Instance = { NAME: string; WEBHOOK_URL: string; MODE: string; - WEBHOOK_BY_EVENTS: boolean; }; export type Auth = { API_KEY: ApiKey; @@ -263,8 +262,6 @@ export class ConfigService { NAME: process.env.AUTHENTICATION_INSTANCE_NAME, WEBHOOK_URL: process.env.AUTHENTICATION_INSTANCE_WEBHOOK_URL, MODE: process.env.AUTHENTICATION_INSTANCE_MODE, - WEBHOOK_BY_EVENTS: - process.env.AUTHENTICATION_INSTANCE_WEBHOOK_BY_EVENTS === 'true', }, }, }; diff --git a/src/dev-env.yml b/src/dev-env.yml index 32ac8dd5..89b99255 100644 --- a/src/dev-env.yml +++ b/src/dev-env.yml @@ -41,7 +41,7 @@ LOG: # Determine how long the instance should be deleted from memory in case of no connection. # Default time: 5 minutes # If you don't even want an expiration, enter the value false -DEL_INSTANCE: false # or false +DEL_INSTANCE: 5 # or false # Temporary data storage STORE: @@ -112,7 +112,7 @@ WEBHOOK: CONFIG_SESSION_PHONE: # Name that will be displayed on smartphone connection CLIENT: 'Evolution API' - NAME: Chrome # firefox | edge | opera | safari + NAME: chrome # chrome | firefox | edge | opera | safari # Set qrcode display limit QRCODE: @@ -120,11 +120,11 @@ QRCODE: # Defines an authentication type for the api AUTHENTICATION: - TYPE: apikey # or jwt apikey + TYPE: apikey # jwt or apikey # Define a global apikey to access all instances API_KEY: # OBS: This key must be inserted in the request header to create an instance. - KEY: B6D711FC-DE4D-4FD5-9365-44120E713976 + KEY: B6D711FCDE4D4FD5936544120E713976 # Expose the api key on return from fetch instances EXPOSE_IN_FETCH_INSTANCES: true # Set the secret key to encrypt and decrypt your token and its expiration time. @@ -134,7 +134,6 @@ AUTHENTICATION: # Set the instance name and webhook url to create an instance in init the application INSTANCE: # With this option activated, you work with a url per webhook event, respecting the local url and the name of each event - WEBHOOK_BY_EVENTS: false MODE: server # container or server # if you are using container mode, set the container name and the webhook url to default instance NAME: evolution diff --git a/src/validate/validate.schema.ts b/src/validate/validate.schema.ts index d95f9268..bab03206 100644 --- a/src/validate/validate.schema.ts +++ b/src/validate/validate.schema.ts @@ -27,6 +27,7 @@ export const instanceNameSchema: JSONSchema7 = { properties: { instanceName: { type: 'string' }, webhook: { type: 'string' }, + webhook_by_events: { type: 'boolean' }, events: { type: 'array', minItems: 1, @@ -665,6 +666,28 @@ export const groupJidSchema: JSONSchema7 = { ...isNotEmpty('groupJid'), }; +export const groupSendInviteSchema: JSONSchema7 = { + $id: v4(), + type: 'object', + properties: { + groupJid: { type: 'string' }, + description: { type: 'string' }, + numbers: { + type: 'array', + minItems: 1, + uniqueItems: true, + items: { + type: 'string', + minLength: 10, + pattern: '\\d+', + description: '"numbers" must be an array of numeric strings', + }, + }, + }, + required: ['groupJid', 'description', 'numbers'], + ...isNotEmpty('groupJid', 'description', 'numbers'), +}; + export const groupInviteSchema: JSONSchema7 = { $id: v4(), type: 'object', diff --git a/src/whatsapp/controllers/group.controller.ts b/src/whatsapp/controllers/group.controller.ts index b4a3fd14..e8376bfa 100644 --- a/src/whatsapp/controllers/group.controller.ts +++ b/src/whatsapp/controllers/group.controller.ts @@ -4,6 +4,7 @@ import { GroupInvite, GroupJid, GroupPictureDto, + GroupSendInvite, GroupSubjectDto, GroupToggleEphemeralDto, GroupUpdateParticipantDto, @@ -56,10 +57,8 @@ export class GroupController { return await this.waMonitor.waInstances[instance.instanceName].inviteInfo(inviteCode); } - public async acceptInvite(instance: InstanceDto, inviteCode: GroupInvite) { - return await this.waMonitor.waInstances[instance.instanceName].acceptInvite( - inviteCode, - ); + public async sendInvite(instance: InstanceDto, data: GroupSendInvite) { + return await this.waMonitor.waInstances[instance.instanceName].sendInvite(data); } public async revokeInviteCode(instance: InstanceDto, groupJid: GroupJid) { diff --git a/src/whatsapp/controllers/instance.controller.ts b/src/whatsapp/controllers/instance.controller.ts index 985fc0df..13ff6cb7 100644 --- a/src/whatsapp/controllers/instance.controller.ts +++ b/src/whatsapp/controllers/instance.controller.ts @@ -26,6 +26,7 @@ export class InstanceController { public async createInstance({ instanceName, webhook, + webhook_by_events, events, qrcode, token, @@ -60,7 +61,12 @@ export class InstanceController { if (webhook) { try { - this.webhookService.create(instance, { enabled: true, url: webhook, events }); + this.webhookService.create(instance, { + enabled: true, + url: webhook, + events, + webhook_by_events, + }); getEvents = (await this.webhookService.find(instance)).events; } catch (error) { @@ -98,7 +104,12 @@ export class InstanceController { if (webhook) { try { - this.webhookService.create(instance, { enabled: true, url: webhook, events }); + this.webhookService.create(instance, { + enabled: true, + url: webhook, + events, + webhook_by_events, + }); getEvents = (await this.webhookService.find(instance)).events; } catch (error) { @@ -121,6 +132,7 @@ export class InstanceController { }, hash, webhook, + webhook_by_events, events: getEvents, qrcode: getQrcode, }; diff --git a/src/whatsapp/dto/group.dto.ts b/src/whatsapp/dto/group.dto.ts index aa76fe90..fba86ae2 100644 --- a/src/whatsapp/dto/group.dto.ts +++ b/src/whatsapp/dto/group.dto.ts @@ -27,6 +27,12 @@ export class GroupInvite { inviteCode: string; } +export class GroupSendInvite { + groupJid: string; + description: string; + numbers: string[]; +} + export class GroupUpdateParticipantDto extends GroupJid { action: 'add' | 'remove' | 'promote' | 'demote'; participants: string[]; diff --git a/src/whatsapp/dto/instance.dto.ts b/src/whatsapp/dto/instance.dto.ts index 2f461435..8a3902e9 100644 --- a/src/whatsapp/dto/instance.dto.ts +++ b/src/whatsapp/dto/instance.dto.ts @@ -1,6 +1,7 @@ export class InstanceDto { instanceName: string; webhook?: string; + webhook_by_events?: boolean; events?: string[]; qrcode?: boolean; token?: string; diff --git a/src/whatsapp/dto/webhook.dto.ts b/src/whatsapp/dto/webhook.dto.ts index 361009db..5203884d 100644 --- a/src/whatsapp/dto/webhook.dto.ts +++ b/src/whatsapp/dto/webhook.dto.ts @@ -2,4 +2,5 @@ export class WebhookDto { enabled?: boolean; url?: string; events?: string[]; + webhook_by_events?: boolean; } diff --git a/src/whatsapp/models/webhook.model.ts b/src/whatsapp/models/webhook.model.ts index 3033c67f..873491bf 100644 --- a/src/whatsapp/models/webhook.model.ts +++ b/src/whatsapp/models/webhook.model.ts @@ -6,6 +6,7 @@ export class WebhookRaw { url?: string; enabled?: boolean; events?: string[]; + webhook_by_events?: boolean; } const webhookSchema = new Schema({ diff --git a/src/whatsapp/routers/group.router.ts b/src/whatsapp/routers/group.router.ts index 6050183d..17764f4e 100644 --- a/src/whatsapp/routers/group.router.ts +++ b/src/whatsapp/routers/group.router.ts @@ -9,6 +9,7 @@ import { updateGroupSubjectSchema, updateGroupDescriptionSchema, groupInviteSchema, + groupSendInviteSchema, } from '../../validate/validate.schema'; import { RouterBroker } from '../abstract/abstract.router'; import { @@ -21,6 +22,7 @@ import { GroupUpdateParticipantDto, GroupUpdateSettingDto, GroupToggleEphemeralDto, + GroupSendInvite, } from '../dto/group.dto'; import { groupController } from '../whatsapp.module'; import { HttpStatus } from './index.router'; @@ -120,12 +122,12 @@ export class GroupRouter extends RouterBroker { res.status(HttpStatus.OK).json(response); }) - .get(this.routerPath('acceptInvite'), ...guards, async (req, res) => { - const response = await this.inviteCodeValidate({ + .post(this.routerPath('sendInvite'), ...guards, async (req, res) => { + const response = await this.groupNoValidate({ request: req, - schema: groupInviteSchema, - ClassRef: GroupInvite, - execute: (instance, data) => groupController.acceptInvite(instance, data), + schema: groupSendInviteSchema, + ClassRef: GroupSendInvite, + execute: (instance, data) => groupController.sendInvite(instance, data), }); res.status(HttpStatus.OK).json(response); diff --git a/src/whatsapp/services/whatsapp.service.ts b/src/whatsapp/services/whatsapp.service.ts index 70f46577..9fa90841 100644 --- a/src/whatsapp/services/whatsapp.service.ts +++ b/src/whatsapp/services/whatsapp.service.ts @@ -104,6 +104,7 @@ import { GroupToggleEphemeralDto, GroupSubjectDto, GroupDescriptionDto, + GroupSendInvite, } from '../dto/group.dto'; import { MessageUpQuery } from '../repository/messageUp.repository'; import { useMultiFileAuthStateDb } from '../../utils/use-multi-file-auth-state-db'; @@ -204,6 +205,7 @@ export class WAStartupService { this.localWebhook.url = data?.url; this.localWebhook.enabled = data?.enabled; this.localWebhook.events = data?.events; + this.localWebhook.webhook_by_events = data?.webhook_by_events; } public async setWebhook(data: WebhookRaw) { @@ -224,11 +226,9 @@ export class WAStartupService { if (Array.isArray(webhookLocal) && webhookLocal.includes(we)) { if (local && instance.MODE !== 'container') { - const { WEBHOOK_BY_EVENTS } = instance; - let baseURL; - if (WEBHOOK_BY_EVENTS) { + if (this.localWebhook.webhook_by_events) { baseURL = `${this.localWebhook.url}/${transformedWe}`; } else { baseURL = this.localWebhook.url; @@ -484,7 +484,7 @@ export class WAStartupService { const { version } = await fetchLatestBaileysVersion(); const session = this.configService.get('CONFIG_SESSION_PHONE'); - const browser: WABrowserDescription = [session.CLIENT, 'Chrome', release()]; + const browser: WABrowserDescription = [session.CLIENT, session.NAME, release()]; const socketConfig: UserFacingSocketConfig = { auth: { @@ -1773,11 +1773,28 @@ export class WAStartupService { } } - public async acceptInvite(id: GroupInvite) { + public async sendInvite(id: GroupSendInvite) { try { - return await this.client.groupAcceptInvite(id.inviteCode); + const inviteCode = await this.inviteCode({ groupJid: id.groupJid }); + const inviteUrl = inviteCode.inviteUrl; + const numbers = id.numbers.map((number) => this.createJid(number)); + const description = id.description ?? ''; + + const msg = `${description}\n${inviteUrl}`; + + const message = { + linkPreview: { + text: msg, + }, + }; + + for await (const number of numbers) { + await this.sendMessageWithTyping(number, message); + } + + return { send: true, inviteUrl }; } catch (error) { - throw new NotFoundException('No invite info', id.inviteCode); + throw new NotFoundException('No send invite'); } } @@ -1831,7 +1848,7 @@ export class WAStartupService { update.groupJid, update.expiration, ); - return { toggleEphemeral: toggleEphemeral }; + return { success: true }; } catch (error) { throw new BadRequestException('Error updating setting', error.toString()); } diff --git a/src/whatsapp/types/wa.types.ts b/src/whatsapp/types/wa.types.ts index 4bc87db9..fbf2fb99 100644 --- a/src/whatsapp/types/wa.types.ts +++ b/src/whatsapp/types/wa.types.ts @@ -34,7 +34,12 @@ export declare namespace wa { profilePictureUrl?: string; }; - export type LocalWebHook = { enabled?: boolean; url?: string; events?: string[] }; + export type LocalWebHook = { + enabled?: boolean; + url?: string; + events?: string[]; + webhook_by_events?: boolean; + }; export type StateConnection = { instance?: string;