@adatechnology/meta-whatsapp-module 0.2.0-rc.8 → 0.2.0-rc.9

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/index.cjs CHANGED
@@ -162,6 +162,12 @@ var messages = metaWhatsAppSchema.table("messages", {
162
162
  readAt: (0, import_pg_core.timestamp)("read_at", {
163
163
  withTimezone: true
164
164
  }),
165
+ // Moderação de conteúdo. `null` significa NÃO AVALIADO (moderação desligada, ou mensagem
166
+ // anterior ao recurso) — diferente de `false`, que é avaliado e limpo. Colunas em vez de chave
167
+ // dentro de `payload` porque "listar o que foi sinalizado" é consulta de operação, e índice
168
+ // parcial sobre boolean resolve isso sem cavar jsonb.
169
+ moderationFlagged: (0, import_pg_core.boolean)("moderation_flagged"),
170
+ moderationTerms: (0, import_pg_core.jsonb)("moderation_terms").$type(),
165
171
  createdAt: (0, import_pg_core.timestamp)("created_at", {
166
172
  withTimezone: true
167
173
  }).notNull().defaultNow()
@@ -173,7 +179,10 @@ var messages = metaWhatsAppSchema.table("messages", {
173
179
  // paralelo, então as duas passariam pela checagem e inseririam duplicado. Parcial porque
174
180
  // mensagens outbound ainda sem waMessageId (envio em curso) são legitimamente NULL, e NULLs
175
181
  // não podem competir entre si por unicidade.
176
- (0, import_pg_core.uniqueIndex)("idx_messages_company_wa_message_id").on(table.companyId, table.waMessageId).where(import_drizzle_orm.sql`${table.waMessageId} is not null`)
182
+ (0, import_pg_core.uniqueIndex)("idx_messages_company_wa_message_id").on(table.companyId, table.waMessageId).where(import_drizzle_orm.sql`${table.waMessageId} is not null`),
183
+ // Parcial: só as sinalizadas entram, então o índice fica do tamanho do problema e não do
184
+ // tamanho do transcript.
185
+ (0, import_pg_core.index)("idx_messages_moderation_flagged").on(table.companyId, table.createdAt).where(import_drizzle_orm.sql`${table.moderationFlagged}`)
177
186
  ]);
178
187
  var flowGraphs = metaWhatsAppSchema.table("flow_graphs", {
179
188
  id: (0, import_pg_core.uuid)("id").primaryKey().defaultRandom(),
@@ -427,7 +436,9 @@ var MessageRepository = class {
427
436
  content: params.content ?? null,
428
437
  payload: params.payload ?? null,
429
438
  waMessageId: params.waMessageId ?? null,
430
- status: params.status ?? null
439
+ status: params.status ?? null,
440
+ moderationFlagged: params.moderationFlagged ?? null,
441
+ moderationTerms: params.moderationTerms ?? null
431
442
  };
432
443
  const [created] = await this.db.insert(messages).values(values).onConflictDoNothing().returning();
433
444
  return created;
@@ -643,16 +654,19 @@ var LogMessageUseCase = class {
643
654
  sessionRepository;
644
655
  messageRepository;
645
656
  realtime;
646
- constructor(sessionRepository, messageRepository, realtime) {
657
+ moderator;
658
+ constructor(sessionRepository, messageRepository, realtime, moderator) {
647
659
  this.sessionRepository = sessionRepository;
648
660
  this.messageRepository = messageRepository;
649
661
  this.realtime = realtime;
662
+ this.moderator = moderator;
650
663
  }
651
664
  async execute(params) {
652
665
  const session = await this.sessionRepository.getOrCreate(params.companyId, params.whatsappNumber, params.startState);
653
666
  const saved = await this.messageRepository.insertMessage({
654
667
  ...params,
655
- sessionId: session.id
668
+ sessionId: session.id,
669
+ ...this.moderationOf(params)
656
670
  });
657
671
  if (!saved) return void 0;
658
672
  if (params.direction === "inbound") {
@@ -665,6 +679,20 @@ var LogMessageUseCase = class {
665
679
  this.realtime?.emit("global", "data-changed", {});
666
680
  return saved;
667
681
  }
682
+ // Só o que o cliente escreveu: marcar o que o próprio atendente ou o bot enviou não sinaliza
683
+ // abuso, apenas sujaria o transcript com etiqueta na resposta de quem atende.
684
+ moderationOf(params) {
685
+ if (!this.moderator || params.direction !== "inbound") return {};
686
+ const text2 = params.content?.trim();
687
+ if (!text2) return {};
688
+ const verdict = this.moderator.inspect(text2);
689
+ return {
690
+ moderationFlagged: verdict.isOffensive,
691
+ moderationTerms: verdict.isOffensive ? [
692
+ ...verdict.matchedTerms
693
+ ] : null
694
+ };
695
+ }
668
696
  };
669
697
 
670
698
  // src/use-cases/SendMessage.use-case.ts
@@ -1418,7 +1446,7 @@ function createMetaWhatsAppModule(params) {
1418
1446
  const messageRepository = new MessageRepository(db);
1419
1447
  const settingsRepository = new SettingsRepository(db);
1420
1448
  const flowGraphRepository = new FlowGraphRepository(db);
1421
- const logMessage = new LogMessageUseCase(sessionRepository, messageRepository, providers.realtime);
1449
+ const logMessage = new LogMessageUseCase(sessionRepository, messageRepository, providers.realtime, providers.moderator);
1422
1450
  const sendMessage = new SendMessageUseCase(channel, sessionRepository, logMessage, providers.objectStorage);
1423
1451
  const receiveWebhook = new ReceiveWebhookUseCase({
1424
1452
  appSecret: config.appSecret,