@wabot-dev/framework 0.9.0 → 0.9.2
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/in-memory/InMemoryCronJobRepository.js +45 -0
- package/dist/src/addon/async/in-memory/InMemoryJobRepository.js +75 -0
- package/dist/src/addon/async/in-memory/index.js +2 -0
- package/dist/src/addon/async/pg/PgJobRepository.js +1 -0
- package/dist/src/addon/async/pg/PgTransactionAdapter.js +25 -0
- package/dist/src/addon/async/pg/index.js +3 -0
- package/dist/src/addon/chat-bot/{ram/RamChatMemory.js → in-memory/InMemoryChatMemory.js} +2 -2
- package/dist/src/addon/chat-bot/{ram/RamChatRepository.js → in-memory/InMemoryChatRepository.js} +6 -6
- package/dist/src/addon/chat-bot/in-memory/index.js +2 -0
- package/dist/src/addon/chat-bot/pg/index.js +2 -0
- package/dist/src/addon/chat-controller/socket/@socket.js +3 -1
- package/dist/src/addon/chat-controller/socket/SocketChannelConfig.js +4 -4
- package/dist/src/addon/chat-controller/whatsapp/WhatsAppSender.js +2 -72
- package/dist/src/addon/chat-controller/whatsapp/{WhatsAppReceiver.js → cloud-api/WhatsAppApiReceiver.js} +2 -2
- package/dist/src/addon/chat-controller/whatsapp/cloud-api/WhatsAppApiSender.js +67 -0
- package/dist/src/addon/chat-controller/whatsapp/cloud-api/WhatsAppReceiverByCloudApi.js +5 -7
- package/dist/src/addon/chat-controller/whatsapp/wasender/@wasender.js +23 -0
- package/dist/src/addon/chat-controller/{wasender/WhatsAppByWasenderChannel.js → whatsapp/wasender/WasenderChannel.js} +20 -20
- package/dist/src/addon/chat-controller/{wasender/WhatsAppByWasenderChannelConfig.js → whatsapp/wasender/WasenderChannelConfig.js} +3 -3
- package/dist/src/addon/chat-controller/whatsapp/wasender/WasenderChannelName.js +3 -0
- package/dist/src/addon/chat-controller/{wasender/WhatsAppReceiverByWasender.js → whatsapp/wasender/WasenderReceiver.js} +7 -7
- package/dist/src/addon/chat-controller/{wasender/WhatsAppSenderByWasender.js → whatsapp/wasender/WasenderSender.js} +8 -5
- package/dist/src/addon/chat-controller/{wasender → whatsapp/wasender}/WasenderWebhookController.js +4 -4
- package/dist/src/addon/lock/InMemoryLockKey.js +45 -0
- package/dist/src/addon/lock/InMemoryLocker.js +15 -0
- package/dist/src/addon/lock/index.js +2 -0
- package/dist/src/core/config/resolver.js +19 -1
- package/dist/src/feature/async/{@cron.js → @cronHandler.js} +2 -2
- package/dist/src/feature/async/@transaction.js +22 -0
- package/dist/src/feature/async/AsyncMetadataStore.js +6 -0
- package/dist/src/feature/async/TransactionMetadataStore.js +28 -0
- package/dist/src/feature/chat-controller/metadata/ControllerMetadataStore.js +3 -0
- package/dist/src/feature/pg/index.js +13 -0
- package/dist/src/feature/project-runner/ProjectRunner.js +253 -0
- package/dist/src/feature/rest-controller/metadata/RestControllerMetadataStore.js +3 -0
- package/dist/src/feature/socket-controller/metadata/SocketControllerMetadataStore.js +3 -0
- package/dist/src/index.d.ts +195 -261
- package/dist/src/index.js +23 -29
- package/package.json +6 -6
- package/dist/src/addon/chat-controller/wasender/@whatsAppByWasender.js +0 -20
- package/dist/src/addon/chat-controller/wasender/whatsAppByWasenderChannelName.js +0 -3
- package/dist/src/addon/chat-controller/whatsapp/@whatsApp.js +0 -20
- package/dist/src/addon/chat-controller/whatsapp/EnvWhatsAppRepository.js +0 -49
- package/dist/src/addon/chat-controller/whatsapp/PgWhatsAppRepository.js +0 -48
- package/dist/src/addon/chat-controller/whatsapp/WhatsApp.js +0 -30
- package/dist/src/addon/chat-controller/whatsapp/WhatsAppChannel.js +0 -58
- package/dist/src/addon/chat-controller/whatsapp/WhatsAppChannelConfig.js +0 -8
- package/dist/src/addon/chat-controller/whatsapp/WhatsAppRepository.js +0 -10
- package/dist/src/addon/chat-controller/whatsapp/cloud-api/WhatsAppSenderByCloudApi.js +0 -133
- package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppProxyContracts.js +0 -5
- package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppReceiverByWabotProxy.js +0 -67
- package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppSenderByWabotProxy.js +0 -63
- package/dist/src/addon/chat-controller/whatsapp/proxy/WhatsAppWabotProxyConnection.js +0 -45
- package/dist/src/core/config/decorators.js +0 -22
- /package/dist/src/addon/chat-controller/whatsapp/{whatsAppChannelName.js → cloud-api/whatsAppChannelName.js} +0 -0
- /package/dist/src/addon/chat-controller/{wasender → whatsapp/wasender}/extractNumberFromWasenderKey.js +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { __decorate } from 'tslib';
|
|
2
|
+
import { generate } from 'short-uuid';
|
|
3
|
+
import { singleton } from '../../../core/injection/index.js';
|
|
4
|
+
|
|
5
|
+
let InMemoryCronJobRepository = class InMemoryCronJobRepository {
|
|
6
|
+
items = new Map();
|
|
7
|
+
async create(cronJob) {
|
|
8
|
+
if (cronJob.wasCreated())
|
|
9
|
+
throw new Error('CronJob already created');
|
|
10
|
+
cronJob['data'].id = generate();
|
|
11
|
+
cronJob['data'].createdAt = new Date().getTime();
|
|
12
|
+
cronJob.validate();
|
|
13
|
+
this.items.set(cronJob.id, cronJob);
|
|
14
|
+
}
|
|
15
|
+
async findDue(date) {
|
|
16
|
+
const now = (date ?? new Date()).getTime();
|
|
17
|
+
return [...this.items.values()]
|
|
18
|
+
.filter((c) => c['data'].enabled && c['data'].nextRunAt != null && c['data'].nextRunAt <= now)
|
|
19
|
+
.sort((a, b) => (a['data'].nextRunAt ?? 0) - (b['data'].nextRunAt ?? 0));
|
|
20
|
+
}
|
|
21
|
+
async findOrThrow(id) {
|
|
22
|
+
const item = this.items.get(id);
|
|
23
|
+
if (!item)
|
|
24
|
+
throw new Error(`CronJob with id = '${id}' not found`);
|
|
25
|
+
return item;
|
|
26
|
+
}
|
|
27
|
+
async update(cronJob) {
|
|
28
|
+
if (!cronJob.wasCreated())
|
|
29
|
+
throw new Error('CronJob was not created');
|
|
30
|
+
cronJob.validate();
|
|
31
|
+
this.items.set(cronJob.id, cronJob);
|
|
32
|
+
}
|
|
33
|
+
async findByName(name) {
|
|
34
|
+
for (const c of this.items.values()) {
|
|
35
|
+
if (c['data'].name === name)
|
|
36
|
+
return c;
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
InMemoryCronJobRepository = __decorate([
|
|
42
|
+
singleton()
|
|
43
|
+
], InMemoryCronJobRepository);
|
|
44
|
+
|
|
45
|
+
export { InMemoryCronJobRepository };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { __decorate } from 'tslib';
|
|
2
|
+
import { generate } from 'short-uuid';
|
|
3
|
+
import { singleton } from '../../../core/injection/index.js';
|
|
4
|
+
|
|
5
|
+
let InMemoryJobRepository = class InMemoryJobRepository {
|
|
6
|
+
items = new Map();
|
|
7
|
+
async find(id) {
|
|
8
|
+
return this.items.get(id) ?? null;
|
|
9
|
+
}
|
|
10
|
+
async findOrThrow(id) {
|
|
11
|
+
const item = this.items.get(id);
|
|
12
|
+
if (!item)
|
|
13
|
+
throw new Error(`Job with id = '${id}' not found`);
|
|
14
|
+
return item;
|
|
15
|
+
}
|
|
16
|
+
async findByIds(ids) {
|
|
17
|
+
return ids.map((id) => this.items.get(id)).filter((j) => j != null);
|
|
18
|
+
}
|
|
19
|
+
async findAll() {
|
|
20
|
+
return [...this.items.values()];
|
|
21
|
+
}
|
|
22
|
+
async create(item) {
|
|
23
|
+
if (item.wasCreated())
|
|
24
|
+
throw new Error('Job already created');
|
|
25
|
+
item['data'].id = generate();
|
|
26
|
+
item['data'].createdAt = new Date().getTime();
|
|
27
|
+
item.validate();
|
|
28
|
+
this.items.set(item.id, item);
|
|
29
|
+
}
|
|
30
|
+
async update(item) {
|
|
31
|
+
if (!item.wasCreated())
|
|
32
|
+
throw new Error('Job was not created');
|
|
33
|
+
item.validate();
|
|
34
|
+
this.items.set(item.id, item);
|
|
35
|
+
}
|
|
36
|
+
async delete(item) {
|
|
37
|
+
this.items.delete(item.id);
|
|
38
|
+
}
|
|
39
|
+
async findPendingForRunFrom(date, limit) {
|
|
40
|
+
const now = date.getTime();
|
|
41
|
+
return [...this.items.values()]
|
|
42
|
+
.filter((j) => j['data'].scheduledAt != null &&
|
|
43
|
+
j['data'].scheduledAt <= now &&
|
|
44
|
+
j['data'].startedAt == null &&
|
|
45
|
+
j['data'].successAt == null &&
|
|
46
|
+
j['data'].failedAt == null)
|
|
47
|
+
.sort((a, b) => (a['data'].scheduledAt ?? 0) - (b['data'].scheduledAt ?? 0))
|
|
48
|
+
.slice(0, limit);
|
|
49
|
+
}
|
|
50
|
+
async findRunningJobs() {
|
|
51
|
+
return [...this.items.values()].filter((j) => {
|
|
52
|
+
if (j['data'].successAt != null || j['data'].failedAt != null)
|
|
53
|
+
return false;
|
|
54
|
+
return j['data'].scheduledAt != null && j['data'].startedAt != null;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async countRunningByCommand(commandName) {
|
|
58
|
+
let count = 0;
|
|
59
|
+
for (const j of this.items.values()) {
|
|
60
|
+
if (j['data'].commandName !== commandName)
|
|
61
|
+
continue;
|
|
62
|
+
if (j['data'].successAt != null || j['data'].failedAt != null)
|
|
63
|
+
continue;
|
|
64
|
+
if (j['data'].scheduledAt != null && j['data'].startedAt != null) {
|
|
65
|
+
count++;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return count;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
InMemoryJobRepository = __decorate([
|
|
72
|
+
singleton()
|
|
73
|
+
], InMemoryJobRepository);
|
|
74
|
+
|
|
75
|
+
export { InMemoryJobRepository };
|
|
@@ -10,6 +10,7 @@ import '../../../feature/pg/pgStorage.js';
|
|
|
10
10
|
import '../../../feature/pg/query/PgJsonRepository.js';
|
|
11
11
|
import '../../../feature/pg/query/PgRepositoryMetadataStore.js';
|
|
12
12
|
import '../../../feature/async/AsyncMetadataStore.js';
|
|
13
|
+
import '../../../feature/async/TransactionMetadataStore.js';
|
|
13
14
|
import '../../../feature/async/Async.js';
|
|
14
15
|
import '../../../_virtual/index.js';
|
|
15
16
|
import { Job } from '../../../feature/async/Job.js';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import 'short-uuid';
|
|
2
|
+
import { withPgClient } from '../../../feature/pg/withPgClient.js';
|
|
3
|
+
import 'debug';
|
|
4
|
+
import '../../../feature/pg/PgLocker.js';
|
|
5
|
+
import '../../../core/error/setupErrorHandlers.js';
|
|
6
|
+
import 'node:crypto';
|
|
7
|
+
import '../../../feature/pg/pgStorage.js';
|
|
8
|
+
import '../../../core/injection/index.js';
|
|
9
|
+
import '../../../feature/pg/query/PgJsonRepository.js';
|
|
10
|
+
import '../../../feature/pg/query/PgRepositoryMetadataStore.js';
|
|
11
|
+
import { withPgTransaction } from '../../../feature/pg/withPgTransaction.js';
|
|
12
|
+
|
|
13
|
+
class PgTransactionAdapter {
|
|
14
|
+
pool;
|
|
15
|
+
constructor(pool) {
|
|
16
|
+
this.pool = pool;
|
|
17
|
+
}
|
|
18
|
+
async run(fn) {
|
|
19
|
+
return withPgClient(this.pool, () => withPgTransaction(this.pool, async () => {
|
|
20
|
+
return await fn();
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { PgTransactionAdapter };
|
package/dist/src/addon/chat-bot/{ram/RamChatRepository.js → in-memory/InMemoryChatRepository.js}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { __decorate } from 'tslib';
|
|
2
2
|
import { v4 } from 'uuid';
|
|
3
|
-
import {
|
|
3
|
+
import { InMemoryChatMemory } from './InMemoryChatMemory.js';
|
|
4
4
|
import { singleton } from '../../../core/injection/index.js';
|
|
5
5
|
import '../../../feature/chat-bot/ChatAdapterRegistry.js';
|
|
6
6
|
import '../../../feature/chat-bot/ChatBot.js';
|
|
@@ -10,7 +10,7 @@ import '../../../feature/chat-bot/metadata/ChatAdapterMetadataStore.js';
|
|
|
10
10
|
import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
|
|
11
11
|
import '../../../core/error/setupErrorHandlers.js';
|
|
12
12
|
|
|
13
|
-
let
|
|
13
|
+
let InMemoryChatRepository = class InMemoryChatRepository {
|
|
14
14
|
items = [];
|
|
15
15
|
memories = [];
|
|
16
16
|
async update(chat) {
|
|
@@ -28,7 +28,7 @@ let RamChatRepository = class RamChatRepository {
|
|
|
28
28
|
chat.validate();
|
|
29
29
|
this.items.push(chat);
|
|
30
30
|
const memory = {
|
|
31
|
-
memory: new
|
|
31
|
+
memory: new InMemoryChatMemory(),
|
|
32
32
|
chatId: chat.id,
|
|
33
33
|
};
|
|
34
34
|
this.memories.push(memory);
|
|
@@ -56,8 +56,8 @@ let RamChatRepository = class RamChatRepository {
|
|
|
56
56
|
return this.memories.find((r) => r.chatId === chatId) ?? null;
|
|
57
57
|
}
|
|
58
58
|
};
|
|
59
|
-
|
|
59
|
+
InMemoryChatRepository = __decorate([
|
|
60
60
|
singleton()
|
|
61
|
-
],
|
|
61
|
+
], InMemoryChatRepository);
|
|
62
62
|
|
|
63
|
-
export {
|
|
63
|
+
export { InMemoryChatRepository };
|
|
@@ -2,17 +2,19 @@ import { container } from '../../../core/injection/index.js';
|
|
|
2
2
|
import { ControllerMetadataStore } from '../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
|
|
3
3
|
import '../../../feature/chat-controller/ChatResolver.js';
|
|
4
4
|
import '../../../feature/chat-controller/runChatControllers.js';
|
|
5
|
+
import { resolveConfigReferences } from '../../../core/config/resolver.js';
|
|
5
6
|
import { SocketChannel } from './SocketChannel.js';
|
|
6
7
|
import { SocketChannelConfig } from './SocketChannelConfig.js';
|
|
7
8
|
|
|
8
9
|
function socket(config) {
|
|
9
10
|
return function (target, propertyKey) {
|
|
11
|
+
const resolved = resolveConfigReferences(config);
|
|
10
12
|
const store = container.resolve(ControllerMetadataStore);
|
|
11
13
|
store.saveChannelMetadata({
|
|
12
14
|
channelConstructor: SocketChannel,
|
|
13
15
|
functionName: propertyKey.toString(),
|
|
14
16
|
controllerConstructor: target.constructor,
|
|
15
|
-
channelConfig: new SocketChannelConfig(
|
|
17
|
+
channelConfig: new SocketChannelConfig(resolved),
|
|
16
18
|
});
|
|
17
19
|
};
|
|
18
20
|
}
|
|
@@ -4,14 +4,14 @@ import { injectable } from '../../../core/injection/index.js';
|
|
|
4
4
|
let SocketChannelConfig = class SocketChannelConfig {
|
|
5
5
|
namespace;
|
|
6
6
|
handshakeMidlewares;
|
|
7
|
-
constructor(
|
|
8
|
-
this.namespace = namespace;
|
|
9
|
-
this.handshakeMidlewares = handshakeMidlewares;
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this.namespace = config.namespace;
|
|
9
|
+
this.handshakeMidlewares = config.handshakeMidlewares;
|
|
10
10
|
}
|
|
11
11
|
};
|
|
12
12
|
SocketChannelConfig = __decorate([
|
|
13
13
|
injectable(),
|
|
14
|
-
__metadata("design:paramtypes", [
|
|
14
|
+
__metadata("design:paramtypes", [Object])
|
|
15
15
|
], SocketChannelConfig);
|
|
16
16
|
|
|
17
17
|
export { SocketChannelConfig };
|
|
@@ -1,80 +1,10 @@
|
|
|
1
|
-
import '../../../feature/chat-bot/ChatAdapterRegistry.js';
|
|
2
|
-
import '../../../feature/chat-bot/ChatBot.js';
|
|
3
|
-
import { ChatItem } from '../../../feature/chat-bot/ChatItem.js';
|
|
4
|
-
import '../../../feature/chat-bot/ChatOperator.js';
|
|
5
|
-
import '../../../feature/chat-bot/UnionChatAdapter.js';
|
|
6
|
-
import '../../../core/injection/index.js';
|
|
7
|
-
import '../../../feature/chat-bot/metadata/ChatAdapterMetadataStore.js';
|
|
8
|
-
import 'uuid';
|
|
9
|
-
import '../../../feature/chat-bot/metadata/ChatBotMetadataStore.js';
|
|
10
|
-
import '../../../core/error/setupErrorHandlers.js';
|
|
11
|
-
|
|
12
1
|
class WhatsAppSender {
|
|
13
|
-
|
|
14
|
-
chatResolver;
|
|
15
|
-
whatsAppRepository;
|
|
16
|
-
constructor(chatRepository, chatResolver, whatsAppRepository) {
|
|
17
|
-
this.chatRepository = chatRepository;
|
|
18
|
-
this.chatResolver = chatResolver;
|
|
19
|
-
this.whatsAppRepository = whatsAppRepository;
|
|
20
|
-
}
|
|
21
|
-
async sendWhatsApp(request, options) {
|
|
22
|
-
throw new Error('Not implemented');
|
|
23
|
-
}
|
|
24
|
-
async sendWhatsAppTemplate(request, options) {
|
|
2
|
+
async sendMessage(request) {
|
|
25
3
|
throw new Error('Not implemented');
|
|
26
4
|
}
|
|
27
|
-
|
|
5
|
+
async sendTemplate(request) {
|
|
28
6
|
throw new Error('Not implemented');
|
|
29
7
|
}
|
|
30
|
-
async mapTemplateToChatMessage(request) {
|
|
31
|
-
const template = await this.getWhatsAppTemplate({
|
|
32
|
-
from: request.from,
|
|
33
|
-
templateName: request.templateMessage.templateName,
|
|
34
|
-
languageCode: request.templateMessage.languageCode,
|
|
35
|
-
});
|
|
36
|
-
if (!template) {
|
|
37
|
-
throw new Error(`WhatsAppTemplate with name ${request.templateMessage.templateName} and language ${request.templateMessage.languageCode} not found`);
|
|
38
|
-
}
|
|
39
|
-
const components = template.components
|
|
40
|
-
.filter((x) => x.text != null)
|
|
41
|
-
.map((x) => x.text)
|
|
42
|
-
.join('\n');
|
|
43
|
-
return {
|
|
44
|
-
text: this.replaceTemplateParameters(components, request.templateMessage.parameters),
|
|
45
|
-
senderName: request.senderName,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
async writePrivateChatMemory(message, to) {
|
|
49
|
-
const chatConnection = {
|
|
50
|
-
id: to,
|
|
51
|
-
chatType: 'PRIVATE',
|
|
52
|
-
channelName: 'WhatsAppChannel',
|
|
53
|
-
};
|
|
54
|
-
const chat = await this.chatResolver.resolve(chatConnection);
|
|
55
|
-
const chatMemory = await this.chatRepository.findMemory(chat.id);
|
|
56
|
-
const chatItem = new ChatItem({
|
|
57
|
-
type: 'botMessage',
|
|
58
|
-
botMessage: message,
|
|
59
|
-
});
|
|
60
|
-
await chatMemory.create(chatItem);
|
|
61
|
-
}
|
|
62
|
-
replaceTemplateParameters(template, data) {
|
|
63
|
-
let result = template;
|
|
64
|
-
data.forEach((param) => {
|
|
65
|
-
if (param.type === 'text' && param.parameter_name) {
|
|
66
|
-
const tag = `{{${param.parameter_name}}}`;
|
|
67
|
-
result = result.split(tag).join(param.text);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
data.forEach((param, index) => {
|
|
71
|
-
if (param.type === 'text') {
|
|
72
|
-
const tag = `{{${index + 1}}}`;
|
|
73
|
-
result = result.split(tag).join(param.text);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
return result;
|
|
77
|
-
}
|
|
78
8
|
}
|
|
79
9
|
|
|
80
10
|
export { WhatsAppSender };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
class WhatsAppApiSender {
|
|
2
|
+
accessToken;
|
|
3
|
+
businessNumberId;
|
|
4
|
+
constructor(accessToken, businessNumberId) {
|
|
5
|
+
this.accessToken = accessToken;
|
|
6
|
+
this.businessNumberId = businessNumberId;
|
|
7
|
+
}
|
|
8
|
+
async sendMessage(request) {
|
|
9
|
+
const url = `https://graph.facebook.com/v23.0/${this.businessNumberId}/messages`;
|
|
10
|
+
const payload = {
|
|
11
|
+
messaging_product: 'whatsapp',
|
|
12
|
+
recipient_type: 'individual',
|
|
13
|
+
to: request.to,
|
|
14
|
+
type: 'text',
|
|
15
|
+
text: {
|
|
16
|
+
preview_url: false,
|
|
17
|
+
body: request.message.text ?? '',
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
const response = await fetch(url, {
|
|
21
|
+
method: 'POST',
|
|
22
|
+
headers: {
|
|
23
|
+
Authorization: `Bearer ${this.accessToken}`,
|
|
24
|
+
'Content-Type': 'application/json',
|
|
25
|
+
},
|
|
26
|
+
body: JSON.stringify(payload),
|
|
27
|
+
});
|
|
28
|
+
const data = await response.json();
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
throw new Error(JSON.stringify(data));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async sendTemplate(request) {
|
|
34
|
+
const payload = {
|
|
35
|
+
messaging_product: 'whatsapp',
|
|
36
|
+
recipient_type: 'individual',
|
|
37
|
+
to: request.to,
|
|
38
|
+
type: 'template',
|
|
39
|
+
template: {
|
|
40
|
+
name: request.templateData.templateName,
|
|
41
|
+
language: {
|
|
42
|
+
code: request.templateData.languageCode,
|
|
43
|
+
},
|
|
44
|
+
components: [
|
|
45
|
+
{
|
|
46
|
+
type: 'body',
|
|
47
|
+
parameters: request.templateData.parameters,
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
const response = await fetch(`https://graph.facebook.com/v23.0/${this.businessNumberId}/messages`, {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
headers: {
|
|
55
|
+
Authorization: `Bearer ${this.accessToken}`,
|
|
56
|
+
'Content-Type': 'application/json',
|
|
57
|
+
},
|
|
58
|
+
body: JSON.stringify(payload),
|
|
59
|
+
});
|
|
60
|
+
const data = await response.json();
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
throw new Error(JSON.stringify(data));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { WhatsAppApiSender };
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { Logger } from '../../../../core/logger/Logger.js';
|
|
2
|
-
import { whatsAppChannelName } from '
|
|
2
|
+
import { whatsAppChannelName } from './whatsAppChannelName.js';
|
|
3
3
|
import { json } from 'express';
|
|
4
|
-
import {
|
|
4
|
+
import { WhatsAppApiReceiver } from './WhatsAppApiReceiver.js';
|
|
5
5
|
|
|
6
|
-
class WhatsAppReceiverByCloudApi extends
|
|
6
|
+
class WhatsAppReceiverByCloudApi extends WhatsAppApiReceiver {
|
|
7
7
|
expressProvider;
|
|
8
|
-
whatsAppRepository;
|
|
9
8
|
listeners = new Map();
|
|
10
9
|
expressApp;
|
|
11
10
|
logger = new Logger('wabot:whatsapp-receiver-by-webhook');
|
|
12
11
|
webhookPath = '/whatsapp/web-hook/:slug';
|
|
13
|
-
constructor(expressProvider
|
|
12
|
+
constructor(expressProvider) {
|
|
14
13
|
super();
|
|
15
14
|
this.expressProvider = expressProvider;
|
|
16
|
-
this.whatsAppRepository = whatsAppRepository;
|
|
17
15
|
this.expressApp = this.expressProvider.getExpress();
|
|
18
16
|
}
|
|
19
17
|
async connect() {
|
|
@@ -26,7 +24,7 @@ class WhatsAppReceiverByCloudApi extends WhatsAppReceiver {
|
|
|
26
24
|
res.sendStatus(400);
|
|
27
25
|
return;
|
|
28
26
|
}
|
|
29
|
-
const whatsApp = await this.whatsAppRepository.findBySlug(req.params.slug)
|
|
27
|
+
const whatsApp = 5; // TODO: await this.whatsAppRepository.findBySlug(req.params.slug)
|
|
30
28
|
if (!whatsApp || mode !== 'subscribe' || token !== whatsApp.getVerifyToken()) {
|
|
31
29
|
res.sendStatus(403);
|
|
32
30
|
return;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { container } from '../../../../core/injection/index.js';
|
|
2
|
+
import { resolveConfigReferences } from '../../../../core/config/resolver.js';
|
|
3
|
+
import { WasenderChannelConfig } from './WasenderChannelConfig.js';
|
|
4
|
+
import { ControllerMetadataStore } from '../../../../feature/chat-controller/metadata/ControllerMetadataStore.js';
|
|
5
|
+
import '../../../../feature/chat-controller/ChatResolver.js';
|
|
6
|
+
import '../../../../feature/chat-controller/runChatControllers.js';
|
|
7
|
+
import { WasenderChannel } from './WasenderChannel.js';
|
|
8
|
+
|
|
9
|
+
function wasender(config) {
|
|
10
|
+
return function (target, propertyKey) {
|
|
11
|
+
const cfg = config ?? {};
|
|
12
|
+
const resolvedConfig = resolveConfigReferences(cfg);
|
|
13
|
+
const store = container.resolve(ControllerMetadataStore);
|
|
14
|
+
store.saveChannelMetadata({
|
|
15
|
+
channelConstructor: WasenderChannel,
|
|
16
|
+
functionName: propertyKey.toString(),
|
|
17
|
+
controllerConstructor: target.constructor,
|
|
18
|
+
channelConfig: new WasenderChannelConfig(resolvedConfig),
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { wasender };
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import { __decorate, __metadata } from 'tslib';
|
|
2
|
-
import { injectable } from '
|
|
3
|
-
import { Env } from '
|
|
4
|
-
import { Logger } from '
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
2
|
+
import { injectable } from '../../../../core/injection/index.js';
|
|
3
|
+
import { Env } from '../../../../core/env/Env.js';
|
|
4
|
+
import { Logger } from '../../../../core/logger/Logger.js';
|
|
5
|
+
import { WasenderChannelConfig } from './WasenderChannelConfig.js';
|
|
6
|
+
import { WasenderReceiver } from './WasenderReceiver.js';
|
|
7
|
+
import { WasenderSender } from './WasenderSender.js';
|
|
8
|
+
import { wasenderChannelName } from './WasenderChannelName.js';
|
|
9
9
|
|
|
10
|
-
var
|
|
11
|
-
let
|
|
12
|
-
static {
|
|
10
|
+
var WasenderChannel_1;
|
|
11
|
+
let WasenderChannel = class WasenderChannel {
|
|
12
|
+
static { WasenderChannel_1 = this; }
|
|
13
13
|
logger = new Logger('wabot:whatsapp-by-wasender-channel');
|
|
14
14
|
sender;
|
|
15
15
|
receiver;
|
|
16
16
|
phoneNumber;
|
|
17
|
-
static channelName =
|
|
17
|
+
static channelName = wasenderChannelName;
|
|
18
18
|
constructor(config, env) {
|
|
19
19
|
const apiKey = config.apiKey ?? env.requireString('WASENDER_API_KEY');
|
|
20
20
|
const webhookSecret = config.webhookSecret ?? env.requireString('WASENDER_WEBHOOK_SECRET');
|
|
21
21
|
this.phoneNumber = config.phoneNumber ?? env.requireString('WASENDER_PHONE_NUMBER');
|
|
22
|
-
this.sender = new
|
|
23
|
-
this.receiver = new
|
|
22
|
+
this.sender = new WasenderSender(apiKey, config.retryOptions);
|
|
23
|
+
this.receiver = new WasenderReceiver({
|
|
24
24
|
apiKey,
|
|
25
25
|
webhookSecret,
|
|
26
26
|
webhookPath: config.webhookPath,
|
|
@@ -31,15 +31,15 @@ let WhatsAppByWasenderChannel = class WhatsAppByWasenderChannel {
|
|
|
31
31
|
this.receiver.listenMessage(async (message, from) => {
|
|
32
32
|
try {
|
|
33
33
|
await callback({
|
|
34
|
-
channel:
|
|
34
|
+
channel: wasenderChannelName,
|
|
35
35
|
chatConnection: {
|
|
36
36
|
chatType: 'PRIVATE',
|
|
37
|
-
channelName:
|
|
37
|
+
channelName: WasenderChannel_1.channelName,
|
|
38
38
|
id: from,
|
|
39
39
|
},
|
|
40
40
|
message,
|
|
41
41
|
reply: async (replyMessage) => {
|
|
42
|
-
await this.sender.
|
|
42
|
+
await this.sender.sendMessage({
|
|
43
43
|
from: this.phoneNumber,
|
|
44
44
|
to: from,
|
|
45
45
|
message: replyMessage,
|
|
@@ -59,9 +59,9 @@ let WhatsAppByWasenderChannel = class WhatsAppByWasenderChannel {
|
|
|
59
59
|
this.receiver.disconnect();
|
|
60
60
|
}
|
|
61
61
|
};
|
|
62
|
-
|
|
62
|
+
WasenderChannel = WasenderChannel_1 = __decorate([
|
|
63
63
|
injectable(),
|
|
64
|
-
__metadata("design:paramtypes", [
|
|
65
|
-
],
|
|
64
|
+
__metadata("design:paramtypes", [WasenderChannelConfig, Env])
|
|
65
|
+
], WasenderChannel);
|
|
66
66
|
|
|
67
|
-
export {
|
|
67
|
+
export { WasenderChannel };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class WasenderChannelConfig {
|
|
2
2
|
apiKey;
|
|
3
3
|
webhookSecret;
|
|
4
4
|
phoneNumber;
|
|
@@ -9,8 +9,8 @@ class WhatsAppByWasenderChannelConfig {
|
|
|
9
9
|
this.webhookSecret = config.webhookSecret;
|
|
10
10
|
this.phoneNumber = config.phoneNumber;
|
|
11
11
|
this.webhookPath = config.webhookPath ?? '/wasender/hook';
|
|
12
|
-
this.retryOptions =
|
|
12
|
+
this.retryOptions = { enabled: true, maxRetries: 3 };
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export {
|
|
16
|
+
export { WasenderChannelConfig };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { __decorate, __metadata } from 'tslib';
|
|
2
|
-
import '
|
|
3
|
-
import '
|
|
4
|
-
import { restController } from '
|
|
5
|
-
import { runRestControllers } from '
|
|
6
|
-
import { createWasender } from '
|
|
2
|
+
import '../../../../core/injection/index.js';
|
|
3
|
+
import '../../../../feature/rest-controller/metadata/RestControllerMetadataStore.js';
|
|
4
|
+
import { restController } from '../../../../feature/rest-controller/metadata/@restController.js';
|
|
5
|
+
import { runRestControllers } from '../../../../feature/rest-controller/runRestControllers.js';
|
|
6
|
+
import { createWasender } from '../../../../node_modules/wasenderapi/dist/index.js';
|
|
7
7
|
import { WasenderWebhookController } from './WasenderWebhookController.js';
|
|
8
8
|
|
|
9
|
-
class
|
|
9
|
+
class WasenderReceiver {
|
|
10
10
|
config;
|
|
11
11
|
wasender;
|
|
12
12
|
listener = null;
|
|
@@ -36,4 +36,4 @@ class WhatsAppReceiverByWasender {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
export {
|
|
39
|
+
export { WasenderReceiver };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { Logger } from '
|
|
2
|
-
import { createWasender } from '
|
|
1
|
+
import { Logger } from '../../../../core/logger/Logger.js';
|
|
2
|
+
import { createWasender } from '../../../../node_modules/wasenderapi/dist/index.js';
|
|
3
3
|
|
|
4
|
-
class
|
|
4
|
+
class WasenderSender {
|
|
5
5
|
wasender;
|
|
6
6
|
logger = new Logger('wabot:whatsapp-sender-by-wasender');
|
|
7
7
|
constructor(apiKey, retryOptions) {
|
|
8
8
|
this.wasender = createWasender(apiKey, undefined, undefined, undefined, retryOptions, undefined);
|
|
9
9
|
}
|
|
10
|
-
async
|
|
10
|
+
async sendMessage(request) {
|
|
11
11
|
try {
|
|
12
12
|
const textPayload = {
|
|
13
13
|
messageType: 'text',
|
|
@@ -28,6 +28,9 @@ class WhatsAppSenderByWasender {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
+
sendTemplate(request) {
|
|
32
|
+
throw new Error('Method not implemented.');
|
|
33
|
+
}
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
export {
|
|
36
|
+
export { WasenderSender };
|
package/dist/src/addon/chat-controller/{wasender → whatsapp/wasender}/WasenderWebhookController.js
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { __decorate, __metadata } from 'tslib';
|
|
2
|
-
import { Logger } from '
|
|
3
|
-
import '
|
|
4
|
-
import '
|
|
5
|
-
import { onPost } from '
|
|
2
|
+
import { Logger } from '../../../../core/logger/Logger.js';
|
|
3
|
+
import '../../../../core/injection/index.js';
|
|
4
|
+
import '../../../../feature/rest-controller/metadata/RestControllerMetadataStore.js';
|
|
5
|
+
import { onPost } from '../../../../feature/rest-controller/metadata/@onPost.js';
|
|
6
6
|
import { extractNumberFromWasenderMessageKey } from './extractNumberFromWasenderKey.js';
|
|
7
7
|
import { IncomingMessage } from 'node:http';
|
|
8
8
|
|