@wabot-dev/framework 0.1.0-beta.45 → 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.
- package/dist/src/addon/async/pg/PgJobRepository.js +1 -1
- package/dist/src/addon/auth/api-key/@apiKeyGuard.js +17 -0
- package/dist/src/addon/auth/api-key/ApiKey.js +46 -0
- package/dist/src/addon/auth/api-key/ApiKeyGuardMiddleware.js +45 -0
- package/dist/src/addon/auth/api-key/ApiKeyRepository.js +13 -0
- package/dist/src/addon/auth/api-key/PgApiKeyRepository.js +14 -0
- package/dist/src/addon/auth/jwt/@jwtConnectionGuard.js +16 -0
- package/dist/src/addon/auth/jwt/JwtConnectionGuardMiddleware.js +57 -0
- package/dist/src/addon/auth/jwt/JwtRefreshTokenRepository.js +25 -0
- package/dist/src/addon/{rest-controller → auth}/jwt/JwtTokenDto.js +3 -3
- package/dist/src/addon/{rest-controller/jwt/JwtRefreshTokenRepository.js → auth/jwt/PgJwtRefreshTokenRepository.js} +6 -6
- package/dist/src/addon/chat-bot/pg/PgChatMemory.js +1 -1
- package/dist/src/addon/chat-bot/pg/PgChatRepository.js +1 -1
- package/dist/src/addon/chat-controller/whatsapp/{@whatsapp.js → @whatsApp.js} +3 -3
- package/dist/src/addon/chat-controller/whatsapp/PgWhatsAppRepository.js +1 -1
- package/dist/src/addon/chat-controller/whatsapp/WhatsAppReceiver.js +3 -49
- package/dist/src/addon/chat-controller/whatsapp/WhatsAppSender.js +7 -44
- package/dist/src/addon/chat-controller/whatsapp/cloud-api/WhatsAppReceiverByCloudApi.js +97 -0
- package/dist/src/addon/chat-controller/whatsapp/{WhatsAppSenderByCloudApi.js → cloud-api/WhatsAppSenderByCloudApi.js} +24 -16
- package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppProxyContracts.js +5 -0
- package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppReceiverByWabotProxy.js +65 -0
- package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppSenderByWabotProxy.js +60 -0
- package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppWabotProxyConnection.js +45 -0
- package/dist/src/core/password/Password.js +30 -0
- package/dist/src/core/validation/metadata/@isArray.js +1 -1
- package/dist/src/core/validation/metadata/@isModel.js +1 -1
- package/dist/src/core/validation/metadata/@isOptional.js +1 -1
- package/dist/src/core/validation/metadata/ValidationMetadataStore.js +2 -2
- package/dist/src/core/validation/validate.js +1 -1
- package/dist/src/{addon/validation → core/validation/validators}/is-boolean/@isBoolean.js +2 -2
- package/dist/src/{addon/validation → core/validation/validators}/is-date/@isDate.js +2 -2
- package/dist/src/{addon/validation → core/validation/validators}/is-not-empty/@isNotEmpty.js +2 -2
- package/dist/src/{addon/validation → core/validation/validators}/is-number/@isNumber.js +2 -2
- package/dist/src/{addon/validation → core/validation/validators}/is-present/@isPresent.js +2 -2
- package/dist/src/{addon/validation → core/validation/validators}/is-string/@isString.js +2 -2
- package/dist/src/{addon/validation → core/validation/validators}/max/@max.js +2 -2
- package/dist/src/{addon/validation → core/validation/validators}/min/@min.js +2 -2
- package/dist/src/feature/chat-bot/ChatBot.js +4 -0
- package/dist/src/{addon → feature}/money/MoneyDto.js +2 -2
- package/dist/src/{addon/repository → feature}/pg/PgCrudRepository.js +1 -1
- package/dist/src/feature/socket-controller/metadata/@connectionMiddleware.js +16 -0
- package/dist/src/feature/socket-controller/metadata/@socketConnection.js +18 -0
- package/dist/src/feature/socket-controller/metadata/@socketController.js +15 -0
- package/dist/src/feature/socket-controller/metadata/@socketEvent.js +18 -0
- package/dist/src/feature/socket-controller/metadata/SocketControllerMetadataStore.js +65 -0
- package/dist/src/feature/socket-controller/runSocketControllers.js +98 -0
- package/dist/src/index.d.ts +546 -368
- package/dist/src/index.js +53 -36
- package/package.json +1 -1
- package/dist/src/addon/chat-controller/whatsapp/WabotDevConnection.js +0 -57
- package/dist/src/addon/chat-controller/whatsapp/WabotDevSocketContracts.js +0 -10
- package/dist/src/addon/chat-controller/whatsapp/WhatsAppReceiverByDevConnection.js +0 -26
- package/dist/src/addon/chat-controller/whatsapp/WhatsAppReceiverByWebHook.js +0 -57
- package/dist/src/addon/chat-controller/whatsapp/WhatsAppSenderByDevConnection.js +0 -60
- package/dist/src/addon/{rest-controller → auth}/jwt/@jwtGuard.js +0 -0
- package/dist/src/addon/{rest-controller → auth}/jwt/Jwt.js +0 -0
- package/dist/src/addon/{rest-controller → auth}/jwt/JwtAccessAndRefreshTokenDto.js +0 -0
- package/dist/src/addon/{rest-controller → auth}/jwt/JwtConfig.js +0 -0
- package/dist/src/addon/{rest-controller → auth}/jwt/JwtGuardMiddleware.js +1 -1
- /package/dist/src/addon/{rest-controller → auth}/jwt/JwtRefreshToken.js +0 -0
- /package/dist/src/addon/{rest-controller → auth}/jwt/JwtSigner.js +0 -0
- /package/dist/src/core/validation/{validators → core}/validateArray.js +0 -0
- /package/dist/src/core/validation/{validators → core}/validateIsOptional.js +0 -0
- /package/dist/src/core/validation/{validators → core}/validateModel.js +0 -0
- /package/dist/src/{addon/validation → core/validation/validators}/is-boolean/validateIsBoolean.js +0 -0
- /package/dist/src/{addon/validation → core/validation/validators}/is-date/validateIsDate.js +0 -0
- /package/dist/src/{addon/validation → core/validation/validators}/is-not-empty/validateIsNotEmpty.js +0 -0
- /package/dist/src/{addon/validation → core/validation/validators}/is-number/validateIsNumber.js +0 -0
- /package/dist/src/{addon/validation → core/validation/validators}/is-present/validateIsPresent.js +0 -0
- /package/dist/src/{addon/validation → core/validation/validators}/is-string/validateIsString.js +0 -0
- /package/dist/src/{addon/validation → core/validation/validators}/max/validateMax.js +0 -0
- /package/dist/src/{addon/validation → core/validation/validators}/min/validateMin.js +0 -0
- /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 '
|
|
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 '
|
|
5
|
-
import { isNotEmpty } from '
|
|
6
|
-
import { isString } from '
|
|
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 '
|
|
4
|
+
import { PgCrudRepository } from '../../../feature/pg/PgCrudRepository.js';
|
|
5
|
+
import { JwtRefreshToken } from './JwtRefreshToken.js';
|
|
6
6
|
|
|
7
|
-
let
|
|
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
|
-
|
|
16
|
+
PgJwtRefreshTokenRepository = __decorate([
|
|
17
17
|
singleton(),
|
|
18
18
|
__metadata("design:paramtypes", [Pool])
|
|
19
|
-
],
|
|
19
|
+
], PgJwtRefreshTokenRepository);
|
|
20
20
|
|
|
21
|
-
export {
|
|
21
|
+
export { PgJwtRefreshTokenRepository };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PgCrudRepository } from '
|
|
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 '
|
|
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
|
|
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 {
|
|
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 '
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
constructor(logger) {
|
|
5
|
-
this.logger = logger;
|
|
2
|
+
connect() {
|
|
3
|
+
throw new Error('Not Implemented');
|
|
6
4
|
}
|
|
7
5
|
listenMessage(request) {
|
|
8
|
-
|
|
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(
|
|
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
|
-
|
|
16
|
+
async sendWhatsApp(request, options) {
|
|
19
17
|
throw new Error('Not implemented');
|
|
20
18
|
}
|
|
21
|
-
|
|
19
|
+
async sendWhatsAppTemplate(request, options) {
|
|
22
20
|
throw new Error('Not implemented');
|
|
23
21
|
}
|
|
24
|
-
|
|
22
|
+
getWhatsAppTemplate(request) {
|
|
25
23
|
throw new Error('Not implemented');
|
|
26
24
|
}
|
|
27
|
-
async
|
|
28
|
-
|
|
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 '
|
|
3
|
-
import { WhatsAppSender } from '
|
|
4
|
-
import { singleton } from '
|
|
5
|
-
import '
|
|
6
|
-
import { ChatResolver } from '
|
|
7
|
-
import '
|
|
8
|
-
import { ChatRepository } from '
|
|
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 '
|
|
10
|
+
import '../../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
|
|
11
11
|
import 'reflect-metadata';
|
|
12
|
-
import '
|
|
13
|
-
import '
|
|
14
|
-
import { WhatsAppRepository } from '
|
|
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(
|
|
19
|
+
super(chatRepository, chatResolver, whatsAppRepository);
|
|
19
20
|
}
|
|
20
|
-
async
|
|
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
|
|
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
|
|
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
|
-
|
|
118
|
+
this.logger.error(error);
|
|
111
119
|
throw error;
|
|
112
120
|
}
|
|
113
121
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const WHATSAPP_PROXY_SEND_MESSAGE_EVENT = 'sendMessage';
|
|
2
|
+
const WHATSAPP_PROXY_LISTEN_MESSAGE_EVENT = 'listenMessage';
|
|
3
|
+
const WHATSAPP_MESSAGE_EVENT = 'message';
|
|
4
|
+
|
|
5
|
+
export { WHATSAPP_MESSAGE_EVENT, WHATSAPP_PROXY_LISTEN_MESSAGE_EVENT, WHATSAPP_PROXY_SEND_MESSAGE_EVENT };
|