@wabot-dev/framework 0.1.0-beta.44 → 0.1.0-beta.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/src/addon/async/pg/PgJobRepository.js +1 -1
  2. package/dist/src/addon/auth/api-key/@apiKeyGuard.js +17 -0
  3. package/dist/src/addon/auth/api-key/ApiKey.js +46 -0
  4. package/dist/src/addon/auth/api-key/ApiKeyGuardMiddleware.js +45 -0
  5. package/dist/src/addon/auth/api-key/ApiKeyRepository.js +13 -0
  6. package/dist/src/addon/auth/api-key/PgApiKeyRepository.js +14 -0
  7. package/dist/src/addon/auth/jwt/@jwtConnectionGuard.js +16 -0
  8. package/dist/src/addon/auth/jwt/JwtConnectionGuardMiddleware.js +57 -0
  9. package/dist/src/addon/auth/jwt/JwtRefreshTokenRepository.js +25 -0
  10. package/dist/src/addon/{rest-controller → auth}/jwt/JwtTokenDto.js +3 -3
  11. package/dist/src/addon/{rest-controller/jwt/JwtRefreshTokenRepository.js → auth/jwt/PgJwtRefreshTokenRepository.js} +6 -6
  12. package/dist/src/addon/chat-bot/openia/OpenaiChatAdapter.js +1 -1
  13. package/dist/src/addon/chat-bot/pg/PgChatMemory.js +1 -1
  14. package/dist/src/addon/chat-bot/pg/PgChatRepository.js +1 -1
  15. package/dist/src/addon/chat-controller/whatsapp/{@whatsapp.js → @whatsApp.js} +3 -3
  16. package/dist/src/addon/chat-controller/whatsapp/PgWhatsAppRepository.js +1 -1
  17. package/dist/src/addon/chat-controller/whatsapp/WhatsAppReceiver.js +3 -49
  18. package/dist/src/addon/chat-controller/whatsapp/WhatsAppSender.js +7 -44
  19. package/dist/src/addon/chat-controller/whatsapp/cloud-api/WhatsAppReceiverByCloudApi.js +97 -0
  20. package/dist/src/addon/chat-controller/whatsapp/{WhatsAppSenderByCloudApi.js → cloud-api/WhatsAppSenderByCloudApi.js} +24 -16
  21. package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppProxyContracts.js +5 -0
  22. package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppReceiverByWabotProxy.js +65 -0
  23. package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppSenderByWabotProxy.js +60 -0
  24. package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppWabotProxyConnection.js +45 -0
  25. package/dist/src/core/password/Password.js +30 -0
  26. package/dist/src/core/validation/metadata/@isArray.js +1 -1
  27. package/dist/src/core/validation/metadata/@isModel.js +1 -1
  28. package/dist/src/core/validation/metadata/@isOptional.js +1 -1
  29. package/dist/src/core/validation/metadata/ValidationMetadataStore.js +2 -2
  30. package/dist/src/core/validation/validate.js +1 -1
  31. package/dist/src/{addon/validation → core/validation/validators}/is-boolean/@isBoolean.js +2 -2
  32. package/dist/src/{addon/validation → core/validation/validators}/is-date/@isDate.js +2 -2
  33. package/dist/src/{addon/validation → core/validation/validators}/is-not-empty/@isNotEmpty.js +2 -2
  34. package/dist/src/{addon/validation → core/validation/validators}/is-number/@isNumber.js +2 -2
  35. package/dist/src/{addon/validation → core/validation/validators}/is-present/@isPresent.js +2 -2
  36. package/dist/src/{addon/validation → core/validation/validators}/is-string/@isString.js +2 -2
  37. package/dist/src/{addon/validation → core/validation/validators}/max/@max.js +2 -2
  38. package/dist/src/{addon/validation → core/validation/validators}/min/@min.js +2 -2
  39. package/dist/src/feature/chat-bot/ChatBot.js +4 -0
  40. package/dist/src/{addon → feature}/money/MoneyDto.js +2 -2
  41. package/dist/src/{addon/repository → feature}/pg/PgCrudRepository.js +1 -1
  42. package/dist/src/feature/socket-controller/metadata/@connectionMiddleware.js +16 -0
  43. package/dist/src/feature/socket-controller/metadata/@socketConnection.js +18 -0
  44. package/dist/src/feature/socket-controller/metadata/@socketController.js +15 -0
  45. package/dist/src/feature/socket-controller/metadata/@socketEvent.js +18 -0
  46. package/dist/src/feature/socket-controller/metadata/SocketControllerMetadataStore.js +65 -0
  47. package/dist/src/feature/socket-controller/runSocketControllers.js +98 -0
  48. package/dist/src/index.d.ts +546 -368
  49. package/dist/src/index.js +53 -36
  50. package/package.json +1 -1
  51. package/dist/src/addon/chat-controller/whatsapp/WabotDevConnection.js +0 -57
  52. package/dist/src/addon/chat-controller/whatsapp/WabotDevSocketContracts.js +0 -10
  53. package/dist/src/addon/chat-controller/whatsapp/WhatsAppReceiverByDevConnection.js +0 -26
  54. package/dist/src/addon/chat-controller/whatsapp/WhatsAppReceiverByWebHook.js +0 -57
  55. package/dist/src/addon/chat-controller/whatsapp/WhatsAppSenderByDevConnection.js +0 -60
  56. package/dist/src/addon/{rest-controller → auth}/jwt/@jwtGuard.js +0 -0
  57. package/dist/src/addon/{rest-controller → auth}/jwt/Jwt.js +0 -0
  58. package/dist/src/addon/{rest-controller → auth}/jwt/JwtAccessAndRefreshTokenDto.js +0 -0
  59. package/dist/src/addon/{rest-controller → auth}/jwt/JwtConfig.js +0 -0
  60. package/dist/src/addon/{rest-controller → auth}/jwt/JwtGuardMiddleware.js +1 -1
  61. /package/dist/src/addon/{rest-controller → auth}/jwt/JwtRefreshToken.js +0 -0
  62. /package/dist/src/addon/{rest-controller → auth}/jwt/JwtSigner.js +0 -0
  63. /package/dist/src/core/validation/{validators → core}/validateArray.js +0 -0
  64. /package/dist/src/core/validation/{validators → core}/validateIsOptional.js +0 -0
  65. /package/dist/src/core/validation/{validators → core}/validateModel.js +0 -0
  66. /package/dist/src/{addon/validation → core/validation/validators}/is-boolean/validateIsBoolean.js +0 -0
  67. /package/dist/src/{addon/validation → core/validation/validators}/is-date/validateIsDate.js +0 -0
  68. /package/dist/src/{addon/validation → core/validation/validators}/is-not-empty/validateIsNotEmpty.js +0 -0
  69. /package/dist/src/{addon/validation → core/validation/validators}/is-number/validateIsNumber.js +0 -0
  70. /package/dist/src/{addon/validation → core/validation/validators}/is-present/validateIsPresent.js +0 -0
  71. /package/dist/src/{addon/validation → core/validation/validators}/is-string/validateIsString.js +0 -0
  72. /package/dist/src/{addon/validation → core/validation/validators}/max/validateMax.js +0 -0
  73. /package/dist/src/{addon/validation → core/validation/validators}/min/validateMin.js +0 -0
  74. /package/dist/src/{addon/repository → feature}/pg/PgRepositoryBase.js +0 -0
@@ -1,7 +1,7 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { Pool } from 'pg';
3
3
  import { singleton } from '../../../core/injection/index.js';
4
- import { PgCrudRepository } from '../../repository/pg/PgCrudRepository.js';
4
+ import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
5
5
  import '../../../feature/async/CommandMetadataStore.js';
6
6
  import '../../../feature/async/Async.js';
7
7
  import { Job } from '../../../feature/async/Job.js';
@@ -0,0 +1,17 @@
1
+ import '../../../core/injection/index.js';
2
+ import '../../../feature/rest-controller/metadata/RestControllerMetadataStore.js';
3
+ import { middleware } from '../../../feature/rest-controller/metadata/@middleware.js';
4
+ import 'debug';
5
+ import '../../../core/validation/metadata/ValidationMetadataStore.js';
6
+ import '../../../feature/express/ExpressProvider.js';
7
+ import 'express';
8
+ import 'path';
9
+ import { ApiKeyGuardMiddleware } from './ApiKeyGuardMiddleware.js';
10
+
11
+ function apiKeyGuard() {
12
+ return function (target, propertyKey) {
13
+ middleware(ApiKeyGuardMiddleware)(target, propertyKey);
14
+ };
15
+ }
16
+
17
+ export { apiKeyGuard };
@@ -0,0 +1,46 @@
1
+ import { Entity } from '../../../core/entity/Entity.js';
2
+ import { CustomError } from '../../../core/error/CustomError.js';
3
+ import { Password } from '../../../core/password/Password.js';
4
+
5
+ class ApiKey extends Entity {
6
+ get authInfo() {
7
+ return this.data.authInfo;
8
+ }
9
+ generatePassword() {
10
+ if (this.data.passwordHash) {
11
+ throw new Error('This api key, already has a secret');
12
+ }
13
+ const password = Password.generate(64);
14
+ this.data.passwordHash = Password.hash({ password: password });
15
+ return password;
16
+ }
17
+ isValidPassword(password) {
18
+ if (!this.data.passwordHash)
19
+ return false;
20
+ return Password.isValid({ password: password, hash: this.data.passwordHash });
21
+ }
22
+ validatePassword(password) {
23
+ if (!this.isValidPassword(password)) {
24
+ throw new CustomError({ message: 'Invalid Api key', httpCode: 401 });
25
+ }
26
+ }
27
+ static inflate(secret) {
28
+ try {
29
+ const json = Buffer.from(secret, 'base64').toString('utf-8');
30
+ const data = JSON.parse(json);
31
+ if (!data.id || !data.pass) {
32
+ throw new Error('Invalid secret structure');
33
+ }
34
+ return data;
35
+ }
36
+ catch (err) {
37
+ throw new Error('Failed to inflate secret: ' + err.message);
38
+ }
39
+ }
40
+ static deflate(data) {
41
+ const json = JSON.stringify(data);
42
+ return Buffer.from(json, 'utf-8').toString('base64');
43
+ }
44
+ }
45
+
46
+ export { ApiKey };
@@ -0,0 +1,45 @@
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import { injectable } from '../../../core/injection/index.js';
3
+ import { Auth } from '../../../core/auth/Auth.js';
4
+ import { CustomError } from '../../../core/error/CustomError.js';
5
+ import { ApiKeyRepository } from './ApiKeyRepository.js';
6
+ import { ApiKey } from './ApiKey.js';
7
+
8
+ let ApiKeyGuardMiddleware = class ApiKeyGuardMiddleware {
9
+ apiKeyRepository;
10
+ auth;
11
+ constructor(apiKeyRepository, auth) {
12
+ this.apiKeyRepository = apiKeyRepository;
13
+ this.auth = auth;
14
+ }
15
+ async handle(req, res, container) {
16
+ const authorization = req.header('Authorization');
17
+ if (!authorization) {
18
+ throw new CustomError({ httpCode: 401, message: 'Authorization header not available' });
19
+ }
20
+ const [keyPrefix, keySecret] = authorization.split(' ');
21
+ if (keyPrefix.toLowerCase() !== 'api-key' || !keySecret) {
22
+ throw new CustomError({ httpCode: 401, message: 'Authorization should be an Api-Key' });
23
+ }
24
+ try {
25
+ const keyData = ApiKey.inflate(keySecret);
26
+ const apiKey = await this.apiKeyRepository.findOrThrow(keyData.id);
27
+ apiKey.validatePassword(keyData.pass);
28
+ this.auth.assign(apiKey.authInfo);
29
+ }
30
+ catch (err) {
31
+ throw new CustomError({
32
+ httpCode: 401,
33
+ message: err instanceof Error ? `Invalid token: ${err.message}` : 'Invalid token',
34
+ cause: err instanceof Error ? err : undefined,
35
+ });
36
+ }
37
+ }
38
+ };
39
+ ApiKeyGuardMiddleware = __decorate([
40
+ injectable(),
41
+ __metadata("design:paramtypes", [ApiKeyRepository,
42
+ Auth])
43
+ ], ApiKeyGuardMiddleware);
44
+
45
+ export { ApiKeyGuardMiddleware };
@@ -0,0 +1,13 @@
1
+ class ApiKeyRepository {
2
+ find(id) {
3
+ throw new Error('Method not implemented.');
4
+ }
5
+ findOrThrow(id) {
6
+ throw new Error('Method not implemented.');
7
+ }
8
+ create(item) {
9
+ throw new Error('Method not implemented.');
10
+ }
11
+ }
12
+
13
+ export { ApiKeyRepository };
@@ -0,0 +1,14 @@
1
+ import { ApiKey } from './ApiKey.js';
2
+ import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
3
+
4
+ class PgApiKeyRepository extends PgCrudRepository {
5
+ constructor(pool) {
6
+ super(pool, {
7
+ schema: 'wabot',
8
+ table: 'apy_key',
9
+ constructor: ApiKey,
10
+ });
11
+ }
12
+ }
13
+
14
+ export { PgApiKeyRepository };
@@ -0,0 +1,16 @@
1
+ import { connectionMiddleware } from '../../../feature/socket-controller/metadata/@connectionMiddleware.js';
2
+ import '../../../core/injection/index.js';
3
+ import '../../../feature/socket-controller/metadata/SocketControllerMetadataStore.js';
4
+ import 'path';
5
+ import 'debug';
6
+ import '../../../feature/socket/SocketServerProvider.js';
7
+ import '../../../core/validation/metadata/ValidationMetadataStore.js';
8
+ import { JwtConnectionGuardMiddleware } from './JwtConnectionGuardMiddleware.js';
9
+
10
+ function jwtConnectionGuard() {
11
+ return function (target, propertyKey) {
12
+ connectionMiddleware(JwtConnectionGuardMiddleware)(target, propertyKey);
13
+ };
14
+ }
15
+
16
+ export { jwtConnectionGuard };
@@ -0,0 +1,57 @@
1
+ import { __decorate, __metadata } from 'tslib';
2
+ import jwt from 'jsonwebtoken';
3
+ import { injectable } from '../../../core/injection/index.js';
4
+ import { Auth } from '../../../core/auth/Auth.js';
5
+ import { CustomError } from '../../../core/error/CustomError.js';
6
+ import { JwtConfig } from './JwtConfig.js';
7
+
8
+ let JwtConnectionGuardMiddleware = class JwtConnectionGuardMiddleware {
9
+ config;
10
+ auth;
11
+ constructor(config, auth) {
12
+ this.config = config;
13
+ this.auth = auth;
14
+ }
15
+ async handle(socket, container) {
16
+ if (!socket.handshake.auth.token) {
17
+ let authorization = socket.handshake.headers['Authorization'] ?? socket.handshake.headers['authorization'];
18
+ if (Array.isArray(authorization)) {
19
+ authorization = authorization[0];
20
+ }
21
+ if (authorization) {
22
+ const [bearer, token] = authorization.split(' ');
23
+ if (bearer.toLowerCase() !== 'bearer' || !token) {
24
+ throw new CustomError({
25
+ httpCode: 401,
26
+ message: 'Authorization should be a bearer token',
27
+ });
28
+ }
29
+ socket.handshake.auth.token = token;
30
+ }
31
+ }
32
+ let token = socket.handshake.auth.token;
33
+ if (!token) {
34
+ throw new CustomError({ httpCode: 401, message: 'Token not available' });
35
+ }
36
+ try {
37
+ const jwtPayload = jwt.verify(token, this.config.secretOrPublicKey, {
38
+ algorithms: [this.config.algorithm],
39
+ });
40
+ this.auth.assign(jwtPayload);
41
+ }
42
+ catch (err) {
43
+ throw new CustomError({
44
+ httpCode: 401,
45
+ message: err instanceof Error ? `Invalid token: ${err.message}` : 'Invalid token',
46
+ cause: err instanceof Error ? err : undefined,
47
+ });
48
+ }
49
+ }
50
+ };
51
+ JwtConnectionGuardMiddleware = __decorate([
52
+ injectable(),
53
+ __metadata("design:paramtypes", [JwtConfig,
54
+ Auth])
55
+ ], JwtConnectionGuardMiddleware);
56
+
57
+ export { JwtConnectionGuardMiddleware };
@@ -0,0 +1,25 @@
1
+ class JwtRefreshTokenRepository {
2
+ find(id) {
3
+ throw new Error('Method not implemented.');
4
+ }
5
+ findOrThrow(id) {
6
+ throw new Error('Method not implemented.');
7
+ }
8
+ findByIds(ids) {
9
+ throw new Error('Method not implemented.');
10
+ }
11
+ findAll(id) {
12
+ throw new Error('Method not implemented.');
13
+ }
14
+ create(item) {
15
+ throw new Error('Method not implemented.');
16
+ }
17
+ update(item) {
18
+ throw new Error('Method not implemented.');
19
+ }
20
+ discard(item) {
21
+ throw new Error('Method not implemented.');
22
+ }
23
+ }
24
+
25
+ export { JwtRefreshTokenRepository };
@@ -1,9 +1,9 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import '../../../core/injection/index.js';
3
3
  import '../../../core/validation/metadata/ValidationMetadataStore.js';
4
- import { isDate } from '../../validation/is-date/@isDate.js';
5
- import { isNotEmpty } from '../../validation/is-not-empty/@isNotEmpty.js';
6
- import { isString } from '../../validation/is-string/@isString.js';
4
+ import { isDate } from '../../../core/validation/validators/is-date/@isDate.js';
5
+ import { isNotEmpty } from '../../../core/validation/validators/is-not-empty/@isNotEmpty.js';
6
+ import { isString } from '../../../core/validation/validators/is-string/@isString.js';
7
7
 
8
8
  class JwtTokenDto {
9
9
  token;
@@ -1,10 +1,10 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
2
  import { singleton } from '../../../core/injection/index.js';
3
- import { JwtRefreshToken } from './JwtRefreshToken.js';
4
3
  import { Pool } from 'pg';
5
- import { PgCrudRepository } from '../../repository/pg/PgCrudRepository.js';
4
+ import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
5
+ import { JwtRefreshToken } from './JwtRefreshToken.js';
6
6
 
7
- let JwtRefreshTokenRepository = class JwtRefreshTokenRepository extends PgCrudRepository {
7
+ let PgJwtRefreshTokenRepository = class PgJwtRefreshTokenRepository extends PgCrudRepository {
8
8
  constructor(pool) {
9
9
  super(pool, {
10
10
  schema: 'wabot',
@@ -13,9 +13,9 @@ let JwtRefreshTokenRepository = class JwtRefreshTokenRepository extends PgCrudRe
13
13
  });
14
14
  }
15
15
  };
16
- JwtRefreshTokenRepository = __decorate([
16
+ PgJwtRefreshTokenRepository = __decorate([
17
17
  singleton(),
18
18
  __metadata("design:paramtypes", [Pool])
19
- ], JwtRefreshTokenRepository);
19
+ ], PgJwtRefreshTokenRepository);
20
20
 
21
- export { JwtRefreshTokenRepository };
21
+ export { PgJwtRefreshTokenRepository };
@@ -74,9 +74,9 @@ let OpenaiChatAdapter = class OpenaiChatAdapter {
74
74
  [param.name]: { type: param.type, description: param.description },
75
75
  }), {}),
76
76
  required: tool.parameters.map((param) => param.name),
77
+ additionalProperties: false,
77
78
  },
78
79
  strict: true,
79
- additionalProperties: false,
80
80
  };
81
81
  }
82
82
  mapResponse(response) {
@@ -1,4 +1,4 @@
1
- import { PgCrudRepository } from '../../repository/pg/PgCrudRepository.js';
1
+ import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
2
2
  import '../../../feature/chat-bot/ChatBot.js';
3
3
  import { ChatItem } from '../../../feature/chat-bot/ChatItem.js';
4
4
  import '../../../core/injection/index.js';
@@ -2,7 +2,7 @@ import { __decorate, __metadata } from 'tslib';
2
2
  import { Pool } from 'pg';
3
3
  import { PgChatMemory } from './PgChatMemory.js';
4
4
  import { singleton } from '../../../core/injection/index.js';
5
- import { PgCrudRepository } from '../../repository/pg/PgCrudRepository.js';
5
+ import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
6
6
  import { Chat } from '../../../feature/chat-bot/Chat.js';
7
7
  import '../../../feature/chat-bot/ChatBot.js';
8
8
  import 'uuid';
@@ -10,16 +10,16 @@ import '../../../feature/mindset/metadata/MindsetMetadataStore.js';
10
10
  import '../../../feature/mindset/MindsetOperator.js';
11
11
  import { WhatsAppChannel } from './WhatsAppChannel.js';
12
12
 
13
- function whatsapp(config) {
13
+ function whatsApp(config) {
14
14
  return function (target, propertyKey) {
15
15
  const store = container.resolve(ControllerMetadataStore);
16
16
  store.saveChannelMetadata({
17
17
  channelConstructor: WhatsAppChannel,
18
18
  functionName: propertyKey.toString(),
19
19
  controllerConstructor: target.constructor,
20
- channelConfig: new WhatsappChannelConfig(config.number),
20
+ channelConfig: new WhatsappChannelConfig(typeof config === 'string' ? config : config.number),
21
21
  });
22
22
  };
23
23
  }
24
24
 
25
- export { whatsapp };
25
+ export { whatsApp };
@@ -2,7 +2,7 @@ import { __decorate, __metadata } from 'tslib';
2
2
  import { Pool } from 'pg';
3
3
  import { WhatsApp } from './WhatsApp.js';
4
4
  import { singleton } from '../../../core/injection/index.js';
5
- import { PgCrudRepository } from '../../repository/pg/PgCrudRepository.js';
5
+ import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
6
6
 
7
7
  let PgWhatsAppRepository = class PgWhatsAppRepository extends PgCrudRepository {
8
8
  constructor(pool) {
@@ -1,55 +1,9 @@
1
1
  class WhatsAppReceiver {
2
- logger;
3
- listeners = new Map();
4
- constructor(logger) {
5
- this.logger = logger;
2
+ connect() {
3
+ throw new Error('Not Implemented');
6
4
  }
7
5
  listenMessage(request) {
8
- this.listeners.set(request.to, request.listener);
9
- }
10
- async handlePayload(payload) {
11
- try {
12
- for (const entry of payload.entry) {
13
- for (const change of entry.changes) {
14
- if (change.field !== 'messages' || !change.value.messages || !change.value.contacts) {
15
- continue;
16
- }
17
- for (const message of change.value.messages) {
18
- const contact = change.value.contacts.find((x) => x.wa_id === message.from);
19
- if (!contact) {
20
- continue;
21
- }
22
- await this.emmitMessage(change.value.metadata, message, contact);
23
- }
24
- }
25
- }
26
- }
27
- catch (err) {
28
- this.logger.error(err);
29
- }
30
- }
31
- async emmitMessage(metadata, message, contact) {
32
- const listener = this.listeners.get(metadata.display_phone_number);
33
- if (!listener) {
34
- return;
35
- }
36
- if (message.type !== 'text') {
37
- this.logger.error(`message type ${message.type} is not supported yet`);
38
- return;
39
- }
40
- const channelName = 'WhatsAppChannel';
41
- const chatConnection = {
42
- id: contact.wa_id,
43
- chatType: 'PRIVATE',
44
- channelName,
45
- };
46
- await listener({
47
- chatConnection,
48
- message: {
49
- senderName: contact.profile.name,
50
- text: message.text.body,
51
- },
52
- });
6
+ throw new Error('Not Implemented');
53
7
  }
54
8
  }
55
9
 
@@ -5,62 +5,25 @@ import 'uuid';
5
5
  import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
6
6
 
7
7
  class WhatsAppSender {
8
- logger;
9
8
  chatRepository;
10
9
  chatResolver;
11
10
  whatsAppRepository;
12
- constructor(logger, chatRepository, chatResolver, whatsAppRepository) {
13
- this.logger = logger;
11
+ constructor(chatRepository, chatResolver, whatsAppRepository) {
14
12
  this.chatRepository = chatRepository;
15
13
  this.chatResolver = chatResolver;
16
14
  this.whatsAppRepository = whatsAppRepository;
17
15
  }
18
- handleSendRequest(request) {
16
+ async sendWhatsApp(request, options) {
19
17
  throw new Error('Not implemented');
20
18
  }
21
- handleSendTemplateRequest(request) {
19
+ async sendWhatsAppTemplate(request, options) {
22
20
  throw new Error('Not implemented');
23
21
  }
24
- handleGetWhatsAppTemplate(request) {
22
+ getWhatsAppTemplate(request) {
25
23
  throw new Error('Not implemented');
26
24
  }
27
- async sendWhatsApp(request, options) {
28
- try {
29
- await this.handleSendRequest(request);
30
- if (options?.writeChatMemory) {
31
- await this.writePrivateChatMemory(request.message, request.to);
32
- }
33
- }
34
- catch (error) {
35
- this.logger.error(`Error sending WhatsApp message: ${error}`);
36
- throw new Error(`Error sending WhatsApp message: ${error}`, { cause: error });
37
- }
38
- }
39
- async sendWhatsAppTemplate(request, options) {
40
- try {
41
- await this.handleSendTemplateRequest(request);
42
- if (options?.writeChatMemory) {
43
- const message = await this.resolveTemplateToChatMessage(request);
44
- await this.writePrivateChatMemory(message, request.to);
45
- }
46
- }
47
- catch (error) {
48
- this.logger.error(`Error sending WhatsApp message: ${error}`);
49
- throw new Error(`Error sending WhatsApp message: ${error}`, { cause: error });
50
- }
51
- }
52
- async getWhatsAppTemplate(request) {
53
- try {
54
- const template = await this.handleGetWhatsAppTemplate(request);
55
- return template;
56
- }
57
- catch (error) {
58
- this.logger.error(error);
59
- throw new Error('Error getting WhatsApp template:', { cause: error });
60
- }
61
- }
62
- async resolveTemplateToChatMessage(request) {
63
- const template = await this.handleGetWhatsAppTemplate({
25
+ async mapTemplateToChatMessage(request) {
26
+ const template = await this.getWhatsAppTemplate({
64
27
  from: request.from,
65
28
  templateName: request.templateMessage.templateName,
66
29
  languageCode: request.templateMessage.languageCode,
@@ -87,7 +50,7 @@ class WhatsAppSender {
87
50
  const chatMemory = await this.chatRepository.findMemory(chat.id);
88
51
  const chatItem = new ChatItem({
89
52
  type: 'botMessage',
90
- botMessage: message
53
+ botMessage: message,
91
54
  });
92
55
  await chatMemory.create(chatItem);
93
56
  }
@@ -0,0 +1,97 @@
1
+ import { Logger } from '../../../../core/logger/Logger.js';
2
+ import { json } from 'express';
3
+ import { WhatsAppReceiver } from '../WhatsAppReceiver.js';
4
+
5
+ class WhatsAppReceiverByCloudApi extends WhatsAppReceiver {
6
+ expressProvider;
7
+ whatsAppRepository;
8
+ listeners = new Map();
9
+ expressApp;
10
+ logger = new Logger('wabot:whatsapp-receiver-by-webhook');
11
+ webhookPath = '/whatsapp/web-hook/:slug';
12
+ constructor(expressProvider, whatsAppRepository) {
13
+ super();
14
+ this.expressProvider = expressProvider;
15
+ this.whatsAppRepository = whatsAppRepository;
16
+ this.expressApp = this.expressProvider.getExpress();
17
+ }
18
+ async connect() {
19
+ this.expressApp.get(this.webhookPath, json(), async (req, res) => {
20
+ try {
21
+ let mode = req.query['hub.mode'];
22
+ let token = req.query['hub.verify_token'];
23
+ let challenge = req.query['hub.challenge'];
24
+ if (!mode || !token || !challenge) {
25
+ res.sendStatus(400);
26
+ return;
27
+ }
28
+ const whatsApp = await this.whatsAppRepository.findBySlug(req.params.slug);
29
+ if (!whatsApp || mode !== 'subscribe' || token !== whatsApp.getVerifyToken()) {
30
+ res.sendStatus(403);
31
+ return;
32
+ }
33
+ res.status(200).send(challenge);
34
+ }
35
+ catch (e) {
36
+ this.logger.error(e);
37
+ res.sendStatus(500);
38
+ return;
39
+ }
40
+ });
41
+ this.expressApp.post(this.webhookPath, json(), (req, res) => {
42
+ const payload = req.body;
43
+ this.handlePayload(payload);
44
+ res.sendStatus(200);
45
+ });
46
+ this.expressProvider.listen();
47
+ }
48
+ listenMessage(request) {
49
+ this.listeners.set(request.to, request.listener);
50
+ }
51
+ async handlePayload(payload) {
52
+ try {
53
+ for (const entry of payload.entry) {
54
+ for (const change of entry.changes) {
55
+ if (change.field !== 'messages' || !change.value.messages || !change.value.contacts) {
56
+ continue;
57
+ }
58
+ for (const message of change.value.messages) {
59
+ const contact = change.value.contacts.find((x) => x.wa_id === message.from);
60
+ if (!contact) {
61
+ continue;
62
+ }
63
+ await this.emmitMessage(change.value.metadata, message, contact);
64
+ }
65
+ }
66
+ }
67
+ }
68
+ catch (err) {
69
+ this.logger.error(err);
70
+ }
71
+ }
72
+ async emmitMessage(metadata, message, contact) {
73
+ const listener = this.listeners.get(metadata.display_phone_number);
74
+ if (!listener) {
75
+ return;
76
+ }
77
+ if (message.type !== 'text') {
78
+ this.logger.error(`message type ${message.type} is not supported yet`);
79
+ return;
80
+ }
81
+ const channelName = 'WhatsAppChannel';
82
+ const chatConnection = {
83
+ id: contact.wa_id,
84
+ chatType: 'PRIVATE',
85
+ channelName,
86
+ };
87
+ await listener({
88
+ chatConnection,
89
+ message: {
90
+ senderName: contact.profile.name,
91
+ text: message.text.body,
92
+ },
93
+ });
94
+ }
95
+ }
96
+
97
+ export { WhatsAppReceiverByCloudApi };
@@ -1,23 +1,24 @@
1
1
  import { __decorate, __metadata } from 'tslib';
2
- import { Logger } from '../../../core/logger/Logger.js';
3
- import { WhatsAppSender } from './WhatsAppSender.js';
4
- import { singleton } from '../../../core/injection/index.js';
5
- import '../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
6
- import { ChatResolver } from '../../../feature/chat-controller/ChatResolver.js';
7
- import '../../../feature/chat-bot/ChatBot.js';
8
- import { ChatRepository } from '../../../feature/chat-bot/ChatRepository.js';
2
+ import { Logger } from '../../../../core/logger/Logger.js';
3
+ import { WhatsAppSender } from '../WhatsAppSender.js';
4
+ import { singleton } from '../../../../core/injection/index.js';
5
+ import '../../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
6
+ import { ChatResolver } from '../../../../feature/chat-controller/ChatResolver.js';
7
+ import '../../../../feature/chat-bot/ChatBot.js';
8
+ import { ChatRepository } from '../../../../feature/chat-bot/ChatRepository.js';
9
9
  import 'uuid';
10
- import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
10
+ import '../../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
11
11
  import 'reflect-metadata';
12
- import '../../../feature/mindset/metadata/MindsetMetadataStore.js';
13
- import '../../../feature/mindset/MindsetOperator.js';
14
- import { WhatsAppRepository } from './WhatsAppRepository.js';
12
+ import '../../../../feature/mindset/metadata/MindsetMetadataStore.js';
13
+ import '../../../../feature/mindset/MindsetOperator.js';
14
+ import { WhatsAppRepository } from '../WhatsAppRepository.js';
15
15
 
16
16
  let WhatsAppSenderByCloudApi = class WhatsAppSenderByCloudApi extends WhatsAppSender {
17
+ logger = new Logger('wabot:whatsapp-sender-by-cloud-api');
17
18
  constructor(chatRepository, chatResolver, whatsAppRepository) {
18
- super(new Logger('wabot:whatsapp-sender-by-cloud-api'), chatRepository, chatResolver, whatsAppRepository);
19
+ super(chatRepository, chatResolver, whatsAppRepository);
19
20
  }
20
- async handleSendRequest(request) {
21
+ async sendWhatsApp(request, options) {
21
22
  const whatsApp = await this.whatsAppRepository.findByBusinessNumber(request.from);
22
23
  if (!whatsApp) {
23
24
  throw new Error(`not found WhatsApp with bussiness number '${request.from}'`);
@@ -46,8 +47,11 @@ let WhatsAppSenderByCloudApi = class WhatsAppSenderByCloudApi extends WhatsAppSe
46
47
  if (!response.ok) {
47
48
  throw new Error(JSON.stringify(data));
48
49
  }
50
+ if (options?.writeChatMemory) {
51
+ await this.writePrivateChatMemory(request.message, request.to);
52
+ }
49
53
  }
50
- async handleSendTemplateRequest(request) {
54
+ async sendWhatsAppTemplate(request, options) {
51
55
  const whatsApp = await this.whatsAppRepository.findByBusinessNumber(request.from);
52
56
  if (!whatsApp) {
53
57
  throw new Error(`not found WhatsApp with bussiness number '${request.from}'`);
@@ -83,8 +87,12 @@ let WhatsAppSenderByCloudApi = class WhatsAppSenderByCloudApi extends WhatsAppSe
83
87
  if (!response.ok) {
84
88
  throw new Error(JSON.stringify(data));
85
89
  }
90
+ if (options?.writeChatMemory) {
91
+ const message = await this.mapTemplateToChatMessage(request);
92
+ await this.writePrivateChatMemory(message, request.to);
93
+ }
86
94
  }
87
- async handleGetWhatsAppTemplate(request) {
95
+ async getWhatsAppTemplate(request) {
88
96
  const whatsApp = await this.whatsAppRepository.findByBusinessNumber(request.from);
89
97
  if (!whatsApp) {
90
98
  throw new Error(`not found WhatsApp with bussiness number '${request.from}'`);
@@ -107,7 +115,7 @@ let WhatsAppSenderByCloudApi = class WhatsAppSenderByCloudApi extends WhatsAppSe
107
115
  return template;
108
116
  }
109
117
  catch (error) {
110
- console.error('Failed to get WhatsApp template:', error);
118
+ this.logger.error(error);
111
119
  throw error;
112
120
  }
113
121
  }