From 2fb63180118057efee5639d0dac1bbd67d6a3e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor=20Souza?= Date: Fri, 27 Dec 2024 10:40:04 -0300 Subject: [PATCH 1/8] feat: updates api evolution for docker --- .dockerignore | 2 ++ Docker/scripts/deploy_database.sh | 27 ++++++++++++++++++++------- Dockerfile | 2 +- package.json | 8 +++++--- src/api/services/monitor.service.ts | 17 +++++++++-------- src/api/types/wa.types.ts | 9 ++++++++- 6 files changed, 45 insertions(+), 20 deletions(-) diff --git a/.dockerignore b/.dockerignore index 0d406464..eb211532 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,7 @@ .git *Dockerfile* *docker-compose* +package-lock.json +.env node_modules dist \ No newline at end of file diff --git a/Docker/scripts/deploy_database.sh b/Docker/scripts/deploy_database.sh index fde46d12..4ee735ee 100755 --- a/Docker/scripts/deploy_database.sh +++ b/Docker/scripts/deploy_database.sh @@ -1,24 +1,36 @@ #!/bin/bash +# Fonte das variáveis de ambiente source ./Docker/scripts/env_functions.sh +# Carregar variáveis de ambiente se não estiver no ambiente Docker if [ "$DOCKER_ENV" != "true" ]; then export_env_vars fi +# Verificar se o banco de dados é PostgreSQL ou MySQL if [[ "$DATABASE_PROVIDER" == "postgresql" || "$DATABASE_PROVIDER" == "mysql" ]]; then export DATABASE_URL echo "Deploying migrations for $DATABASE_PROVIDER" echo "Database URL: $DATABASE_URL" - # rm -rf ./prisma/migrations - # cp -r ./prisma/$DATABASE_PROVIDER-migrations ./prisma/migrations - npm run db:deploy - if [ $? -ne 0 ]; then - echo "Migration failed" - exit 1 + + # Verificar se há migrações pendentes com Prisma + MIGRATION_STATUS=$(npx prisma migrate status) + + if echo "$MIGRATION_STATUS" | grep -q "Pending"; then + echo "Migrações pendentes encontradas. Executando deploy..." + npm run db:deploy # Aplica as migrações pendentes + if [ $? -ne 0 ]; then + echo "Migration failed" + exit 1 + else + echo "Migration succeeded" + fi else - echo "Migration succeeded" + echo "Nenhuma migração pendente. Pulando deploy." fi + + # Gerar o Prisma Client após o deploy npm run db:generate if [ $? -ne 0 ]; then echo "Prisma generate failed" @@ -26,6 +38,7 @@ if [[ "$DATABASE_PROVIDER" == "postgresql" || "$DATABASE_PROVIDER" == "mysql" ]] else echo "Prisma generate succeeded" fi + else echo "Error: Database provider $DATABASE_PROVIDER invalid." exit 1 diff --git a/Dockerfile b/Dockerfile index 4c99317d..12067e12 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM node:20-alpine AS builder RUN apk update && \ - apk add git ffmpeg wget curl bash + apk add --no-cache git ffmpeg wget curl bash openssl LABEL version="2.2.0" description="Api to control whatsapp features through http requests." LABEL maintainer="Davidson Gomes" git="https://github.com/DavidsonGomes" diff --git a/package.json b/package.json index f7e77194..af95f792 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ "db:generate": "node runWithProvider.js \"npx prisma generate --schema ./prisma/DATABASE_PROVIDER-schema.prisma\"", "db:deploy": "node runWithProvider.js \"rm -rf ./prisma/migrations && cp -r ./prisma/DATABASE_PROVIDER-migrations ./prisma/migrations && npx prisma migrate deploy --schema ./prisma/DATABASE_PROVIDER-schema.prisma\"", "db:studio": "node runWithProvider.js \"npx prisma studio --schema ./prisma/DATABASE_PROVIDER-schema.prisma\"", - "db:migrate:dev": "node runWithProvider.js \"rm -rf ./prisma/migrations && cp -r ./prisma/DATABASE_PROVIDER-migrations ./prisma/migrations && npx prisma migrate dev --schema ./prisma/DATABASE_PROVIDER-schema.prisma && cp -r ./prisma/migrations/* ./prisma/DATABASE_PROVIDER-migrations\"" + "db:migrate:dev": "node runWithProvider.js \"rm -rf ./prisma/migrations && cp -r ./prisma/DATABASE_PROVIDER-migrations ./prisma/migrations && npx prisma migrate dev --schema ./prisma/DATABASE_PROVIDER-schema.prisma && cp -r ./prisma/migrations/* ./prisma/DATABASE_PROVIDER-migrations\"", + "docker:build": "docker build -t joaovictorsouza/evolution-api:latest .", + "docker:push": "docker push joaovictorsouza/evolution-api:latest" }, "repository": { "type": "git", @@ -51,7 +53,7 @@ "@ffmpeg-installer/ffmpeg": "^1.1.0", "@figuro/chatwoot-sdk": "^1.1.16", "@hapi/boom": "^10.0.1", - "@prisma/client": "^5.15.0", + "@prisma/client": "^6.1.0", "@sentry/node": "^8.28.0", "amqplib": "^0.10.3", "axios": "^1.6.5", @@ -82,7 +84,7 @@ "openai": "^4.52.7", "pg": "^8.11.3", "pino": "^8.11.0", - "prisma": "^5.15.0", + "prisma": "^6.1.0", "pusher": "^5.2.0", "qrcode": "^1.5.1", "qrcode-terminal": "^0.12.0", diff --git a/src/api/services/monitor.service.ts b/src/api/services/monitor.service.ts index c69e4fca..cd202506 100644 --- a/src/api/services/monitor.service.ts +++ b/src/api/services/monitor.service.ts @@ -72,14 +72,15 @@ export class WAMonitoringService { const clientName = this.configService.get('DATABASE').CONNECTION.CLIENT_NAME; - const where = instanceNames && instanceNames.length > 0 - ? { - name: { - in: instanceNames, - }, - clientName, - } - : { clientName }; + const where = + instanceNames && instanceNames.length > 0 + ? { + name: { + in: instanceNames, + }, + clientName, + } + : { clientName }; const instances = await this.prismaRepository.instance.findMany({ where, diff --git a/src/api/types/wa.types.ts b/src/api/types/wa.types.ts index 72c183b2..472b37af 100644 --- a/src/api/types/wa.types.ts +++ b/src/api/types/wa.types.ts @@ -131,7 +131,14 @@ export declare namespace wa { export type StatusMessage = 'ERROR' | 'PENDING' | 'SERVER_ACK' | 'DELIVERY_ACK' | 'READ' | 'DELETED' | 'PLAYED'; } -export const TypeMediaMessage = ['imageMessage', 'documentMessage', 'audioMessage', 'videoMessage', 'stickerMessage', 'ptvMessage']; +export const TypeMediaMessage = [ + 'imageMessage', + 'documentMessage', + 'audioMessage', + 'videoMessage', + 'stickerMessage', + 'ptvMessage', +]; export const MessageSubtype = [ 'ephemeralMessage', From 0d1e7c08c9568fa590211bafe2649195228e83c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor=20Souza?= Date: Thu, 6 Feb 2025 17:56:21 -0300 Subject: [PATCH 2/8] feat: sendsticket notconvertsticket --- src/api/dto/sendMessage.dto.ts | 1 + .../integrations/channel/whatsapp/whatsapp.baileys.service.ts | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/api/dto/sendMessage.dto.ts b/src/api/dto/sendMessage.dto.ts index 1c9b1154..ba9ecf52 100644 --- a/src/api/dto/sendMessage.dto.ts +++ b/src/api/dto/sendMessage.dto.ts @@ -44,6 +44,7 @@ export class Metadata { mentionsEveryOne?: boolean; mentioned?: string[]; encoding?: boolean; + notConvertSticker?: boolean; } export class SendTextDto extends Metadata { diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 0afd5318..78993547 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -2660,7 +2660,9 @@ export class BaileysStartupService extends ChannelStartupService { if (file) mediaData.sticker = file.buffer.toString('base64'); - const convert = await this.convertToWebP(data.sticker); + const convert = data?.notConvertSticker + ? Buffer.from(data.sticker, 'base64') + : await this.convertToWebP(data.sticker); const gifPlayback = data.sticker.includes('.gif'); const result = await this.sendMessageWithTyping( data.number, From 95401cf9b03ac19cb6fe2b18a9d33b0c01bb75b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor=20Souza?= <47183663+joaosouz4dev@users.noreply.github.com> Date: Thu, 6 Feb 2025 18:05:31 -0300 Subject: [PATCH 3/8] fix: rollback deploy_database.sh --- Docker/scripts/deploy_database.sh | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/Docker/scripts/deploy_database.sh b/Docker/scripts/deploy_database.sh index 4ee735ee..fde46d12 100755 --- a/Docker/scripts/deploy_database.sh +++ b/Docker/scripts/deploy_database.sh @@ -1,36 +1,24 @@ #!/bin/bash -# Fonte das variáveis de ambiente source ./Docker/scripts/env_functions.sh -# Carregar variáveis de ambiente se não estiver no ambiente Docker if [ "$DOCKER_ENV" != "true" ]; then export_env_vars fi -# Verificar se o banco de dados é PostgreSQL ou MySQL if [[ "$DATABASE_PROVIDER" == "postgresql" || "$DATABASE_PROVIDER" == "mysql" ]]; then export DATABASE_URL echo "Deploying migrations for $DATABASE_PROVIDER" echo "Database URL: $DATABASE_URL" - - # Verificar se há migrações pendentes com Prisma - MIGRATION_STATUS=$(npx prisma migrate status) - - if echo "$MIGRATION_STATUS" | grep -q "Pending"; then - echo "Migrações pendentes encontradas. Executando deploy..." - npm run db:deploy # Aplica as migrações pendentes - if [ $? -ne 0 ]; then - echo "Migration failed" - exit 1 - else - echo "Migration succeeded" - fi + # rm -rf ./prisma/migrations + # cp -r ./prisma/$DATABASE_PROVIDER-migrations ./prisma/migrations + npm run db:deploy + if [ $? -ne 0 ]; then + echo "Migration failed" + exit 1 else - echo "Nenhuma migração pendente. Pulando deploy." + echo "Migration succeeded" fi - - # Gerar o Prisma Client após o deploy npm run db:generate if [ $? -ne 0 ]; then echo "Prisma generate failed" @@ -38,7 +26,6 @@ if [[ "$DATABASE_PROVIDER" == "postgresql" || "$DATABASE_PROVIDER" == "mysql" ]] else echo "Prisma generate succeeded" fi - else echo "Error: Database provider $DATABASE_PROVIDER invalid." exit 1 From 6c1355b64b47a6f382bf558799e75c626cc33a65 Mon Sep 17 00:00:00 2001 From: Wayre Avelar Date: Thu, 6 Feb 2025 19:04:28 -0300 Subject: [PATCH 4/8] =?UTF-8?q?feat:=20Criado=20um=20novo=20grupo=20de=20r?= =?UTF-8?q?otas=20(business)=20para=20tratar=20dos=20catalogos=20de=20prod?= =?UTF-8?q?utos=20e=20Cole=C3=A7=C3=B5es=20evitando=20altera=C3=A7=C3=B5es?= =?UTF-8?q?=20desnecess=C3=A1rias=20em=20arquivos=20do=20reposit=C3=B3rio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/controllers/business.controller.ts | 15 ++++++ src/api/controllers/chat.controller.ts | 10 ---- src/api/dto/business.dto.ts | 14 ++++++ src/api/dto/chat.dto.ts | 11 ----- .../whatsapp/whatsapp.baileys.service.ts | 48 +++++++++++++------ src/api/routes/business.router.ts | 37 ++++++++++++++ src/api/routes/chat.router.ts | 25 ---------- src/api/routes/index.router.ts | 2 + src/api/server.module.ts | 2 + src/validate/business.schema.ts | 17 +++++++ src/validate/chat.schema.ts | 18 ------- src/validate/validate.schema.ts | 1 + 12 files changed, 121 insertions(+), 79 deletions(-) create mode 100644 src/api/controllers/business.controller.ts create mode 100644 src/api/dto/business.dto.ts create mode 100644 src/api/routes/business.router.ts create mode 100644 src/validate/business.schema.ts diff --git a/src/api/controllers/business.controller.ts b/src/api/controllers/business.controller.ts new file mode 100644 index 00000000..3c7f166c --- /dev/null +++ b/src/api/controllers/business.controller.ts @@ -0,0 +1,15 @@ +import { getCatalogDto, getCollectionsDto } from '@api/dto/business.dto'; +import { InstanceDto } from '@api/dto/instance.dto'; +import { WAMonitoringService } from '@api/services/monitor.service'; + +export class BusinessController { + constructor(private readonly waMonitor: WAMonitoringService) {} + + public async fetchCatalog({ instanceName }: InstanceDto, data: getCatalogDto) { + return await this.waMonitor.waInstances[instanceName].fetchCatalog(instanceName, data); + } + + public async fetchCollections({ instanceName }: InstanceDto, data: getCollectionsDto) { + return await this.waMonitor.waInstances[instanceName].fetchCollections(instanceName, data); + } +} diff --git a/src/api/controllers/chat.controller.ts b/src/api/controllers/chat.controller.ts index 8c922f11..207d8ba5 100644 --- a/src/api/controllers/chat.controller.ts +++ b/src/api/controllers/chat.controller.ts @@ -3,8 +3,6 @@ import { BlockUserDto, DeleteMessage, getBase64FromMediaMessageDto, - getCatalogDto, - getCollectionsDto, MarkChatUnreadDto, NumberDto, PrivacySettingDto, @@ -111,12 +109,4 @@ export class ChatController { public async blockUser({ instanceName }: InstanceDto, data: BlockUserDto) { return await this.waMonitor.waInstances[instanceName].blockUser(data); } - - public async fetchCatalog({ instanceName }: InstanceDto, data: getCatalogDto) { - return await this.waMonitor.waInstances[instanceName].fetchCatalog(instanceName, data); - } - - public async fetchCatalogCollections({ instanceName }: InstanceDto, data: getCollectionsDto) { - return await this.waMonitor.waInstances[instanceName].fetchCatalogCollections(instanceName, data); - } } diff --git a/src/api/dto/business.dto.ts b/src/api/dto/business.dto.ts new file mode 100644 index 00000000..d29b3cf9 --- /dev/null +++ b/src/api/dto/business.dto.ts @@ -0,0 +1,14 @@ +export class NumberDto { + number: string; +} + +export class getCatalogDto { + number?: string; + limit?: number; + cursor?: string; +} + +export class getCollectionsDto { + number?: string; + limit?: number; +} diff --git a/src/api/dto/chat.dto.ts b/src/api/dto/chat.dto.ts index 1693165e..00da7fdd 100644 --- a/src/api/dto/chat.dto.ts +++ b/src/api/dto/chat.dto.ts @@ -126,14 +126,3 @@ export class BlockUserDto { number: string; status: 'block' | 'unblock'; } - -export class getCatalogDto { - number?: string; - limit?: number; - cursor?: string; -} - -export class getCollectionsDto { - number?: string; - limit?: number; -} diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index 57197e17..d1a4f2e6 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -1,11 +1,10 @@ +import { getCollectionsDto } from '@api/dto/business.dto'; import { OfferCallDto } from '@api/dto/call.dto'; import { ArchiveChatDto, BlockUserDto, DeleteMessage, getBase64FromMediaMessageDto, - getCatalogDto, - getCollectionsDto, LastMessage, MarkChatUnreadDto, NumberBusiness, @@ -4634,11 +4633,11 @@ export class BaileysStartupService extends ChannelStartupService { return response; } - //Catalogs and collections - public async fetchCatalog(instanceName: string, data: getCatalogDto) { + //Business Controller + public async fetchCatalog(instanceName: string, data: getCollectionsDto) { const jid = data.number ? createJid(data.number) : this.client?.user?.id; const limit = data.limit || 10; - const cursor = data.cursor || null; + const cursor = null; const onWhatsapp = (await this.whatsappNumber({ numbers: [jid] }))?.shift(); @@ -4649,15 +4648,35 @@ export class BaileysStartupService extends ChannelStartupService { try { const info = (await this.whatsappNumber({ numbers: [jid] }))?.shift(); const business = await this.fetchBusinessProfile(info?.jid); - const catalog = await this.getCatalog({ jid: info?.jid, limit, cursor }); + + let catalog = await this.getCatalog({ jid: info?.jid, limit, cursor }); + let nextPageCursor = catalog.nextPageCursor; + let nextPageCursorJson = nextPageCursor ? JSON.parse(atob(nextPageCursor)) : null; + let pagination = nextPageCursorJson?.pagination_cursor + ? JSON.parse(atob(nextPageCursorJson.pagination_cursor)) + : null; + let fetcherHasMore = pagination?.fetcher_has_more === true ? true : false; + + let productsCatalog = catalog.products || []; + let countLoops = 0; + while (fetcherHasMore && countLoops < 4) { + catalog = await this.getCatalog({ jid: info?.jid, limit, cursor: nextPageCursor }); + nextPageCursor = catalog.nextPageCursor; + nextPageCursorJson = nextPageCursor ? JSON.parse(atob(nextPageCursor)) : null; + pagination = nextPageCursorJson?.pagination_cursor + ? JSON.parse(atob(nextPageCursorJson.pagination_cursor)) + : null; + fetcherHasMore = pagination?.fetcher_has_more === true ? true : false; + productsCatalog = [...productsCatalog, ...catalog.products]; + countLoops++; + } return { wuid: info?.jid || jid, - name: info?.name, numberExists: info?.exists, isBusiness: business.isBusiness, - catalogLength: catalog?.products.length, - catalog: catalog?.products, + catalogLength: productsCatalog.length, + catalog: productsCatalog, }; } catch (error) { console.log(error); @@ -4692,9 +4711,9 @@ export class BaileysStartupService extends ChannelStartupService { } } - public async fetchCatalogCollections(instanceName: string, data: getCollectionsDto) { + public async fetchCollections(instanceName: string, data: getCollectionsDto) { const jid = data.number ? createJid(data.number) : this.client?.user?.id; - const limit = data.limit || 10; + const limit = data.limit <= 20 ? data.limit : 20; //(tem esse limite, não sei porque) const onWhatsapp = (await this.whatsappNumber({ numbers: [jid] }))?.shift(); @@ -4705,18 +4724,17 @@ export class BaileysStartupService extends ChannelStartupService { try { const info = (await this.whatsappNumber({ numbers: [jid] }))?.shift(); const business = await this.fetchBusinessProfile(info?.jid); - const catalogCollections = await this.getCollections(info?.jid, limit); + const collections = await this.getCollections(info?.jid, limit); return { wuid: info?.jid || jid, name: info?.name, numberExists: info?.exists, isBusiness: business.isBusiness, - catalogLength: catalogCollections?.length, - catalogCollections: catalogCollections, + collectionsLength: collections?.length, + collections: collections, }; } catch (error) { - console.log(error); return { wuid: jid, name: null, diff --git a/src/api/routes/business.router.ts b/src/api/routes/business.router.ts new file mode 100644 index 00000000..1e510a4f --- /dev/null +++ b/src/api/routes/business.router.ts @@ -0,0 +1,37 @@ +import { RouterBroker } from '@api/abstract/abstract.router'; +import { NumberDto } from '@api/dto/chat.dto'; +import { businessController } from '@api/server.module'; +import { catalogSchema, collectionsSchema } from '@validate/validate.schema'; +import { RequestHandler, Router } from 'express'; + +import { HttpStatus } from './index.router'; + +export class BusinessRouter extends RouterBroker { + constructor(...guards: RequestHandler[]) { + super(); + this.router + .post(this.routerPath('getCatalog'), ...guards, async (req, res) => { + const response = await this.dataValidate({ + request: req, + schema: catalogSchema, + ClassRef: NumberDto, + execute: (instance, data) => businessController.fetchCatalog(instance, data), + }); + + return res.status(HttpStatus.OK).json(response); + }) + + .post(this.routerPath('getCollections'), ...guards, async (req, res) => { + const response = await this.dataValidate({ + request: req, + schema: collectionsSchema, + ClassRef: NumberDto, + execute: (instance, data) => businessController.fetchCollections(instance, data), + }); + + return res.status(HttpStatus.OK).json(response); + }); + } + + public readonly router: Router = Router(); +} diff --git a/src/api/routes/chat.router.ts b/src/api/routes/chat.router.ts index aac9fe39..5c556705 100644 --- a/src/api/routes/chat.router.ts +++ b/src/api/routes/chat.router.ts @@ -22,8 +22,6 @@ import { Contact, Message, MessageUpdate } from '@prisma/client'; import { archiveChatSchema, blockUserSchema, - catalogSchema, - collectionsSchema, contactValidateSchema, deleteMessageSchema, markChatUnreadSchema, @@ -209,7 +207,6 @@ export class ChatRouter extends RouterBroker { return res.status(HttpStatus.OK).json(response); }) - .post(this.routerPath('updateProfileName'), ...guards, async (req, res) => { const response = await this.dataValidate({ request: req, @@ -269,28 +266,6 @@ export class ChatRouter extends RouterBroker { }); return res.status(HttpStatus.CREATED).json(response); - }) - - .post(this.routerPath('fetchCatalog'), ...guards, async (req, res) => { - const response = await this.dataValidate({ - request: req, - schema: catalogSchema, - ClassRef: NumberDto, - execute: (instance, data) => chatController.fetchCatalog(instance, data), - }); - - return res.status(HttpStatus.OK).json(response); - }) - - .post(this.routerPath('fetchCollections'), ...guards, async (req, res) => { - const response = await this.dataValidate({ - request: req, - schema: collectionsSchema, - ClassRef: NumberDto, - execute: (instance, data) => chatController.fetchCatalogCollections(instance, data), - }); - - return res.status(HttpStatus.OK).json(response); }); } diff --git a/src/api/routes/index.router.ts b/src/api/routes/index.router.ts index a4a7c071..9c0ecd13 100644 --- a/src/api/routes/index.router.ts +++ b/src/api/routes/index.router.ts @@ -11,6 +11,7 @@ import fs from 'fs'; import mimeTypes from 'mime-types'; import path from 'path'; +import { BusinessRouter } from './business.router'; import { CallRouter } from './call.router'; import { ChatRouter } from './chat.router'; import { GroupRouter } from './group.router'; @@ -82,6 +83,7 @@ router .use('/message', new MessageRouter(...guards).router) .use('/call', new CallRouter(...guards).router) .use('/chat', new ChatRouter(...guards).router) + .use('/business', new BusinessRouter(...guards).router) .use('/group', new GroupRouter(...guards).router) .use('/template', new TemplateRouter(configService, ...guards).router) .use('/settings', new SettingsRouter(...guards).router) diff --git a/src/api/server.module.ts b/src/api/server.module.ts index 49fc5695..9d8df8a6 100644 --- a/src/api/server.module.ts +++ b/src/api/server.module.ts @@ -3,6 +3,7 @@ import { Chatwoot, configService, ProviderSession } from '@config/env.config'; import { eventEmitter } from '@config/event.config'; import { Logger } from '@config/logger.config'; +import { BusinessController } from './controllers/business.controller'; import { CallController } from './controllers/call.controller'; import { ChatController } from './controllers/chat.controller'; import { GroupController } from './controllers/group.controller'; @@ -98,6 +99,7 @@ export const instanceController = new InstanceController( export const sendMessageController = new SendMessageController(waMonitor); export const callController = new CallController(waMonitor); export const chatController = new ChatController(waMonitor); +export const businessController = new BusinessController(waMonitor); export const groupController = new GroupController(waMonitor); export const labelController = new LabelController(waMonitor); diff --git a/src/validate/business.schema.ts b/src/validate/business.schema.ts new file mode 100644 index 00000000..91ad17b2 --- /dev/null +++ b/src/validate/business.schema.ts @@ -0,0 +1,17 @@ +import { JSONSchema7 } from 'json-schema'; + +export const catalogSchema: JSONSchema7 = { + type: 'object', + properties: { + number: { type: 'string' }, + limit: { type: 'number' }, + }, +}; + +export const collectionsSchema: JSONSchema7 = { + type: 'object', + properties: { + number: { type: 'string' }, + limit: { type: 'number' }, + }, +}; diff --git a/src/validate/chat.schema.ts b/src/validate/chat.schema.ts index fd324c10..dba27995 100644 --- a/src/validate/chat.schema.ts +++ b/src/validate/chat.schema.ts @@ -315,21 +315,3 @@ export const profileSchema: JSONSchema7 = { isBusiness: { type: 'boolean' }, }, }; - -export const catalogSchema: JSONSchema7 = { - type: 'object', - properties: { - number: { type: 'string' }, - limit: { type: 'number' }, - cursor: { type: 'string' }, - }, -}; - -export const collectionsSchema: JSONSchema7 = { - type: 'object', - properties: { - number: { type: 'string' }, - limit: { type: 'number' }, - cursor: { type: 'string' }, - }, -}; diff --git a/src/validate/validate.schema.ts b/src/validate/validate.schema.ts index cf3d7828..4577eae3 100644 --- a/src/validate/validate.schema.ts +++ b/src/validate/validate.schema.ts @@ -1,4 +1,5 @@ // Integrations Schema +export * from './business.schema'; export * from './chat.schema'; export * from './group.schema'; export * from './instance.schema'; From 736ca5e4b605f1368bd40350ee1a122f2a6c4b10 Mon Sep 17 00:00:00 2001 From: Rafael Souza Date: Fri, 7 Feb 2025 09:52:08 -0300 Subject: [PATCH 5/8] Fix case in table name --- prisma/mysql-schema.prisma | 2 +- prisma/postgresql-schema.prisma | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/prisma/mysql-schema.prisma b/prisma/mysql-schema.prisma index a73ca069..d93734e4 100644 --- a/prisma/mysql-schema.prisma +++ b/prisma/mysql-schema.prisma @@ -99,7 +99,7 @@ model Instance { Template Template[] Dify Dify[] DifySetting DifySetting? - integrationSessions IntegrationSession[] + IntegrationSessions IntegrationSession[] EvolutionBot EvolutionBot[] EvolutionBotSetting EvolutionBotSetting? Flowise Flowise[] diff --git a/prisma/postgresql-schema.prisma b/prisma/postgresql-schema.prisma index a9782ce5..3c94b808 100644 --- a/prisma/postgresql-schema.prisma +++ b/prisma/postgresql-schema.prisma @@ -99,7 +99,7 @@ model Instance { Template Template[] Dify Dify[] DifySetting DifySetting? - integrationSessions IntegrationSession[] + IntegrationSessions IntegrationSession[] EvolutionBot EvolutionBot[] EvolutionBotSetting EvolutionBotSetting? Flowise Flowise[] From 5a50381a8e34bff7c36b11c2bb803243ce63c92f Mon Sep 17 00:00:00 2001 From: Rafael Souza Date: Fri, 7 Feb 2025 10:07:38 -0300 Subject: [PATCH 6/8] Fix table name --- prisma/mysql-schema.prisma | 2 +- prisma/postgresql-schema.prisma | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/prisma/mysql-schema.prisma b/prisma/mysql-schema.prisma index d93734e4..f2dbb941 100644 --- a/prisma/mysql-schema.prisma +++ b/prisma/mysql-schema.prisma @@ -99,7 +99,7 @@ model Instance { Template Template[] Dify Dify[] DifySetting DifySetting? - IntegrationSessions IntegrationSession[] + IntegrationSession IntegrationSession[] EvolutionBot EvolutionBot[] EvolutionBotSetting EvolutionBotSetting? Flowise Flowise[] diff --git a/prisma/postgresql-schema.prisma b/prisma/postgresql-schema.prisma index 3c94b808..bea632f1 100644 --- a/prisma/postgresql-schema.prisma +++ b/prisma/postgresql-schema.prisma @@ -99,7 +99,7 @@ model Instance { Template Template[] Dify Dify[] DifySetting DifySetting? - IntegrationSessions IntegrationSession[] + IntegrationSession IntegrationSession[] EvolutionBot EvolutionBot[] EvolutionBotSetting EvolutionBotSetting? Flowise Flowise[] From d75c37e233fb08f6b970d6872d55e3a5ff56953c Mon Sep 17 00:00:00 2001 From: Alexis Hernandez Date: Fri, 7 Feb 2025 13:04:36 -0400 Subject: [PATCH 7/8] feat: add message location support meta --- .../channel/meta/whatsapp.business.service.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/api/integrations/channel/meta/whatsapp.business.service.ts b/src/api/integrations/channel/meta/whatsapp.business.service.ts index 5360b9e4..c6f223a9 100644 --- a/src/api/integrations/channel/meta/whatsapp.business.service.ts +++ b/src/api/integrations/channel/meta/whatsapp.business.service.ts @@ -206,6 +206,20 @@ export class BusinessStartupService extends ChannelStartupService { return content; } + private messageLocationJson(received: any) { + const message = received.messages[0]; + let content: any = { + locationMessage: { + degreesLatitude: message.location.latitude, + degreesLongitude: message.location.longitude, + name: message.location?.name, + address: message.location?.address, + }, + }; + message.context ? (content = { ...content, contextInfo: { stanzaId: message.context.id } }) : content; + return content; + } + private messageContactsJson(received: any) { const message = received.messages[0]; let content: any = {}; @@ -283,6 +297,9 @@ export class BusinessStartupService extends ChannelStartupService { case 'template': messageType = 'conversation'; break; + case 'location': + messageType = 'locationMessage'; + break; default: messageType = 'conversation'; break; @@ -438,6 +455,17 @@ export class BusinessStartupService extends ChannelStartupService { source: 'unknown', instanceId: this.instanceId, }; + } else if (received?.messages[0].location) { + messageRaw = { + key, + pushName, + message: this.messageLocationJson(received), + contextInfo: this.messageLocationJson(received)?.contextInfo, + messageType: this.renderMessageType(received.messages[0].type), + messageTimestamp: parseInt(received.messages[0].timestamp) as number, + source: 'unknown', + instanceId: this.instanceId, + }; } else { messageRaw = { key, From 6b120e5da2704f267cb9ea17f7f0f00cfc361fe3 Mon Sep 17 00:00:00 2001 From: mbap-dev Date: Sun, 9 Feb 2025 20:12:40 -0300 Subject: [PATCH 8/8] Fix audio send duplicate from chatwoot. --- .../integrations/chatbot/chatwoot/services/chatwoot.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts b/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts index 77b58bbe..673e6ac5 100644 --- a/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts +++ b/src/api/integrations/chatbot/chatwoot/services/chatwoot.service.ts @@ -1106,7 +1106,7 @@ export class ChatwootService { sendTelemetry('/message/sendWhatsAppAudio'); - const messageSent = await waInstance?.audioWhatsapp(data, true); + const messageSent = await waInstance?.audioWhatsapp(data, null, true); return messageSent; }