File size: 3,224 Bytes
4327358
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import type { conversation_message_create } from '@figuro/chatwoot-sdk/dist/models/conversation_message_create';
import { ILogger } from '@waha/apps/app_sdk/ILogger';
import { NextAttemptDelayInWholeSeconds } from '@waha/apps/app_sdk/JobUtils';
import { Conversation } from '@waha/apps/chatwoot/client/Conversation';
import { MessageType } from '@waha/apps/chatwoot/client/types';
import { ErrorRenderer } from '@waha/apps/chatwoot/error/ErrorRenderer';
import { Locale, TKey } from '@waha/apps/chatwoot/locale';
import { Job } from 'bullmq';

export class ChatWootErrorReporter {
  private errorRenderer: ErrorRenderer = new ErrorRenderer();

  constructor(
    private logger: ILogger,
    private job: Job,
    private l: Locale,
  ) {}

  async ReportError(
    conversation: Conversation,
    header: string,
    type: MessageType,
    error: any,
    replyTo?: number,
  ) {
    const errorText = this.errorRenderer.renderError(error);
    this.logger.error(errorText);
    const errorUrl = `http://localhost:3000/jobs/queue/${encodeURIComponent(
      this.job.queueName,
    )}/${this.job.id}`;
    const template = this.l.key(TKey.JOB_ERROR_REPORT);
    const nextDelay = NextAttemptDelayInWholeSeconds(this.job);
    const attempts = {
      current: this.job.attemptsMade + 1,
      max: this.job.opts?.attempts || 1,
      nextDelay: nextDelay,
    };
    const content = template.render({
      header: header,
      error: nextDelay != null ? null : errorText,
      details: {
        text: `${this.job.queueName} => ${this.job.id}`,
        url: errorUrl,
      },
      attempts: attempts,
    });
    const request: conversation_message_create = {
      content: content,
      message_type: type as any,
      private: true, // Always private note
    };
    if (replyTo) {
      request.content_attributes = {
        in_reply_to: replyTo,
      };
    }
    await conversation.send(request);
  }

  /**
   * Reports a job as recovered after retries.
   * This method will only send a report if the job has been retried (not on its first attempt).
   *
   * @param conversation The conversation to send the report to
   * @param type The message type
   * @param replyTo Optional message ID to reply to
   * @returns Promise that resolves when the report is sent, or void if no report is sent
   */
  async ReportSucceeded(
    conversation: Conversation,
    type: MessageType,
    replyTo?: number,
  ): Promise<void> {
    const jobUrl = `http://localhost:3000/jobs/queue/${encodeURIComponent(
      this.job.queueName,
    )}/${this.job.id}`;
    const template = this.l.key(TKey.JOB_SUCCEEDED_REPORT);
    const attempts = {
      current: this.job.attemptsMade + 1,
      max: this.job.opts?.attempts || 1,
    };

    const content = template.render({
      details: {
        text: `${this.job.queueName} => ${this.job.id}`,
        url: jobUrl,
      },
      attempts: attempts,
    });

    const request: conversation_message_create = {
      content: content,
      message_type: type as any,
      private: true, // Always private note
    };

    if (replyTo) {
      request.content_attributes = {
        in_reply_to: replyTo,
      };
    }

    await conversation.send(request);
  }
}