From a2517b248db47ef742ada16fcd8d65b61771c669 Mon Sep 17 00:00:00 2001 From: devlikepro Date: Sat, 10 Jan 2026 14:35:03 +0700 Subject: [PATCH] [core] ChatWoot - handle not found app fix #1290 fix #1790 --- src/apps/chatwoot/consumers/inbox/base.ts | 11 ++++++++++- src/apps/chatwoot/consumers/scheduled/base.ts | 11 ++++++++++- src/apps/chatwoot/consumers/task/base.ts | 11 ++++++++++- src/apps/chatwoot/consumers/waha/base.ts | 11 ++++++++++- src/apps/chatwoot/error/ChatWootErrorReporter.ts | 12 ++++++++++++ src/apps/chatwoot/errors.ts | 6 ++++++ 6 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/apps/chatwoot/consumers/inbox/base.ts b/src/apps/chatwoot/consumers/inbox/base.ts index a67de4cc..0123db3a 100644 --- a/src/apps/chatwoot/consumers/inbox/base.ts +++ b/src/apps/chatwoot/consumers/inbox/base.ts @@ -8,6 +8,7 @@ import { InboxData } from '@waha/apps/chatwoot/consumers/types'; import { DIContainer } from '@waha/apps/chatwoot/di/DIContainer'; import { ChatIDNotFoundForContactError, + ChatWootAppNotFoundError, PhoneNumberNotFoundInWhatsAppError, } from '@waha/apps/chatwoot/errors'; import { WAHASessionAPI } from '@waha/apps/app_sdk/waha/WAHASelf'; @@ -43,7 +44,11 @@ export abstract class ChatWootInboxMessageConsumer extends AppConsumer { const knex = this.manager.store.getWAHADatabase(); this.appRepository = new AppRepository(knex); const logger = new JobLoggerWrapper(job, this.logger); - const app = await this.appRepository.getById(appId); + const app = await this.appRepository.findEnabledAppById(appId); + if (!app) { + logger.warn(`Chatwoot app not found or disabled: ${appId}`); + throw new ChatWootAppNotFoundError(appId); + } return new DIContainer(app.pk, app.config, logger, knex); } @@ -86,6 +91,10 @@ export abstract class ChatWootInboxMessageConsumer extends AppConsumer { await this.ReportErrorRecovered(job, body); return result; } catch (err) { + if (err instanceof ChatWootAppNotFoundError) { + this.logger.warn(err.message); + throw err; + } await this.ReportErrorForMessage(job, err, body); throw err; } diff --git a/src/apps/chatwoot/consumers/scheduled/base.ts b/src/apps/chatwoot/consumers/scheduled/base.ts index 20d95457..f3e796b9 100644 --- a/src/apps/chatwoot/consumers/scheduled/base.ts +++ b/src/apps/chatwoot/consumers/scheduled/base.ts @@ -11,6 +11,7 @@ import { PinoLogger } from 'nestjs-pino'; import { AppRepository } from '../../storage'; import { TKey } from '@waha/apps/chatwoot/i18n/templates'; +import { ChatWootAppNotFoundError } from '@waha/apps/chatwoot/errors'; /** * Base class for ChatWoot scheduled consumers @@ -35,7 +36,11 @@ export abstract class ChatWootScheduledConsumer extends AppConsumer { const knex = this.manager.store.getWAHADatabase(); this.appRepository = new AppRepository(knex); const logger = new JobLoggerWrapper(job, this.logger); - const app = await this.appRepository.getById(appId); + const app = await this.appRepository.findEnabledAppById(appId); + if (!app) { + logger.warn(`Chatwoot app not found or disabled: ${appId}`); + throw new ChatWootAppNotFoundError(appId); + } return new DIContainer(app.pk, app.config, logger, knex); } @@ -62,6 +67,10 @@ export abstract class ChatWootScheduledConsumer extends AppConsumer { await this.ReportErrorRecovered(job); return result; } catch (err) { + if (err instanceof ChatWootAppNotFoundError) { + this.logger.warn(err.message); + throw err; + } await this.ReportErrorForJob(job, err); throw err; } diff --git a/src/apps/chatwoot/consumers/task/base.ts b/src/apps/chatwoot/consumers/task/base.ts index 1ac48b48..793911a6 100644 --- a/src/apps/chatwoot/consumers/task/base.ts +++ b/src/apps/chatwoot/consumers/task/base.ts @@ -13,6 +13,7 @@ import { AppRepository } from '../../storage'; import { TKey } from '@waha/apps/chatwoot/i18n/templates'; import { SignalRace } from '@waha/utils/abortable'; import { IsCommandsChat } from '@waha/apps/chatwoot/client/ids'; +import { ChatWootAppNotFoundError } from '@waha/apps/chatwoot/errors'; /** * Base class for ChatWoot background task consumers @@ -36,7 +37,11 @@ export abstract class ChatWootTaskConsumer extends AppConsumer { const knex = this.manager.store.getWAHADatabase(); this.appRepository = new AppRepository(knex); const logger = new JobLoggerWrapper(job, this.logger); - const app = await this.appRepository.getById(appId); + const app = await this.appRepository.findEnabledAppById(appId); + if (!app) { + logger.warn(`Chatwoot app not found or disabled: ${appId}`); + throw new ChatWootAppNotFoundError(appId); + } return new DIContainer(app.pk, app.config, logger, knex); } @@ -68,6 +73,10 @@ export abstract class ChatWootTaskConsumer extends AppConsumer { await this.ReportErrorRecovered(job); return result; } catch (err) { + if (err instanceof ChatWootAppNotFoundError) { + this.logger.warn(err.message); + throw err; + } this.ReportErrorForJob(job, err).catch((exc) => this.logger.error(`Failed to report error for job ${job.id}: ${exc}`), ); diff --git a/src/apps/chatwoot/consumers/waha/base.ts b/src/apps/chatwoot/consumers/waha/base.ts index 44467c0c..ce7ba241 100644 --- a/src/apps/chatwoot/consumers/waha/base.ts +++ b/src/apps/chatwoot/consumers/waha/base.ts @@ -12,6 +12,7 @@ import { WhatsAppChatIdKey } from '@waha/apps/chatwoot/consumers/mutex'; import { EventData } from '@waha/apps/chatwoot/consumers/types'; import { WhatsAppContactInfo } from '@waha/apps/chatwoot/contacts/WhatsAppContactInfo'; import { DIContainer } from '@waha/apps/chatwoot/di/DIContainer'; +import { ChatWootAppNotFoundError } from '@waha/apps/chatwoot/errors'; import { Locale } from '@waha/apps/chatwoot/i18n/locale'; import { WAHASelf, WAHASessionAPI } from '@waha/apps/app_sdk/waha/WAHASelf'; import { @@ -83,6 +84,10 @@ export abstract class ChatWootWAHABaseConsumer extends AppConsumer { await this.ReportErrorRecovered(errorReportInfo, job); return result; } catch (err) { + if (err instanceof ChatWootAppNotFoundError) { + this.logger.warn(err.message); + throw err; + } await this.ReportErrorForMessage(errorReportInfo, job, err); throw err; } @@ -95,7 +100,11 @@ export abstract class ChatWootWAHABaseConsumer extends AppConsumer { const knex = this.manager.store.getWAHADatabase(); this.appRepository = new AppRepository(knex); const logger = new JobLoggerWrapper(job, this.logger); - const app = await this.appRepository.getById(appId); + const app = await this.appRepository.findEnabledAppById(appId); + if (!app) { + logger.warn(`Chatwoot app not found or disabled: ${appId}`); + throw new ChatWootAppNotFoundError(appId); + } return new DIContainer(app.pk, app.config, logger, knex); } diff --git a/src/apps/chatwoot/error/ChatWootErrorReporter.ts b/src/apps/chatwoot/error/ChatWootErrorReporter.ts index ee8e369d..ea116adf 100644 --- a/src/apps/chatwoot/error/ChatWootErrorReporter.ts +++ b/src/apps/chatwoot/error/ChatWootErrorReporter.ts @@ -45,6 +45,12 @@ export class ChatWootErrorReporter { // There's retries more left - ignore it for now return; } + if (!conversation) { + this.logger.error( + 'Chatwoot error report skipped: conversation not ready', + ); + return; + } const attempts = { current: this.job.attemptsMade + 1, max: this.job.opts?.attempts || 1, @@ -87,6 +93,12 @@ export class ChatWootErrorReporter { // https://github.com/devlikeapro/waha/issues/1395 return null; + if (!conversation) { + this.logger.warn( + 'Chatwoot success report skipped: conversation not ready', + ); + return; + } const template = this.l.key(TKey.JOB_REPORT_SUCCEEDED); const attempts = { current: this.job.attemptsMade + 1, diff --git a/src/apps/chatwoot/errors.ts b/src/apps/chatwoot/errors.ts index 04f6b785..e48ecfff 100644 --- a/src/apps/chatwoot/errors.ts +++ b/src/apps/chatwoot/errors.ts @@ -15,3 +15,9 @@ export class UnknownJIDFormat extends Error { super(`WhatsApp Chat ID is not recognized: ${jid}`); } } + +export class ChatWootAppNotFoundError extends Error { + constructor(public appId: string) { + super(`Chatwoot app not found or disabled: ${appId}`); + } +}