diff --git a/packages/twenty-server/src/command/command.module.ts b/packages/twenty-server/src/command/command.module.ts index fd7e9fd98..86c629f92 100644 --- a/packages/twenty-server/src/command/command.module.ts +++ b/packages/twenty-server/src/command/command.module.ts @@ -7,7 +7,6 @@ import { CalendarCronCommandsModule } from 'src/modules/calendar/crons/commands/ import { AppModule } from 'src/app.module'; import { WorkspaceMigrationRunnerCommandsModule } from 'src/engine/workspace-manager/workspace-migration-runner/commands/workspace-sync-metadata-commands.module'; import { WorkspaceSyncMetadataCommandsModule } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/workspace-sync-metadata-commands.module'; -import { MessagingCronCommandsModule } from 'src/modules/messaging/crons/commands/messaging-cron-commands.module'; import { CalendarCommandsModule } from 'src/modules/calendar/commands/calendar-commands.module'; @Module({ @@ -15,7 +14,7 @@ import { CalendarCommandsModule } from 'src/modules/calendar/commands/calendar-c AppModule, WorkspaceSyncMetadataCommandsModule, DatabaseCommandModule, - MessagingCronCommandsModule, + // MessagingCronCommandsModule, CalendarCronCommandsModule, CalendarCommandsModule, WorkspaceCleanerModule, diff --git a/packages/twenty-server/src/database/commands/0-20-update-message-channel-sync-status-enum.command.ts b/packages/twenty-server/src/database/commands/0-20-update-message-channel-sync-status-enum.command.ts index 63e2405bd..1a1e345ff 100644 --- a/packages/twenty-server/src/database/commands/0-20-update-message-channel-sync-status-enum.command.ts +++ b/packages/twenty-server/src/database/commands/0-20-update-message-channel-sync-status-enum.command.ts @@ -12,7 +12,7 @@ import { TypeORMService } from 'src/database/typeorm/typeorm.service'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { MessageChannelSyncStatus } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +import { MessageChannelSyncStatus } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; interface UpdateMessageChannelSyncStatusEnumCommandOptions { workspaceId?: string; diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts b/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts index cb88f801f..1266723b5 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts @@ -40,11 +40,6 @@ export const seedFeatureFlags = async ( workspaceId: workspaceId, value: true, }, - { - key: FeatureFlagKeys.IsGmailSyncV2Enabled, - workspaceId: workspaceId, - value: true, - }, { key: FeatureFlagKeys.IsContactCreationForSentAndReceivedEmailsEnabled, workspaceId: workspaceId, diff --git a/packages/twenty-server/src/database/typeorm-seeds/workspace/message-channels.ts b/packages/twenty-server/src/database/typeorm-seeds/workspace/message-channels.ts index a44890197..167061d11 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/workspace/message-channels.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/workspace/message-channels.ts @@ -1,7 +1,7 @@ import { EntityManager } from 'typeorm'; import { DEV_SEED_CONNECTED_ACCOUNT_IDS } from 'src/database/typeorm-seeds/workspace/connected-account'; -import { MessageChannelSyncSubStatus } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +import { MessageChannelSyncSubStatus } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; const tableName = 'messageChannel'; diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts index b0bc2bc88..518e14724 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.config.ts @@ -1,5 +1,3 @@ -import { MessageFindManyPreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook'; -import { MessageFindOnePreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-one.pre-query-hook'; import { WorkspaceQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/types/workspace-query-hook.type'; import { CalendarEventFindManyPreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-many.pre-query.hook'; import { CalendarEventFindOnePreQueryHook } from 'src/modules/calendar/query-hooks/calendar-event/calendar-event-find-one.pre-query-hook'; @@ -8,6 +6,8 @@ import { BlocklistUpdateManyPreQueryHook } from 'src/modules/connected-account/q import { BlocklistUpdateOnePreQueryHook } from 'src/modules/connected-account/query-hooks/blocklist/blocklist-update-one.pre-query.hook'; import { WorkspaceMemberDeleteOnePreQueryHook } from 'src/modules/workspace-member/query-hooks/workspace-member-delete-one.pre-query.hook'; import { WorkspaceMemberDeleteManyPreQueryHook } from 'src/modules/workspace-member/query-hooks/workspace-member-delete-many.pre-query.hook'; +import { MessageFindManyPreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook'; +import { MessageFindOnePreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook'; // TODO: move to a decorator export const workspacePreQueryHooks: WorkspaceQueryHook = { diff --git a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts index 7c367e7b2..8ea6b6a6e 100644 --- a/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts +++ b/packages/twenty-server/src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.module.ts @@ -1,9 +1,9 @@ import { Module } from '@nestjs/common'; -import { MessagingQueryHookModule } from 'src/modules/messaging/query-hooks/messaging-query-hook.module'; import { WorkspacePreQueryHookService } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/workspace-pre-query-hook.service'; import { CalendarQueryHookModule } from 'src/modules/calendar/query-hooks/calendar-query-hook.module'; import { ConnectedAccountQueryHookModule } from 'src/modules/connected-account/query-hooks/connected-account-query-hook.module'; +import { MessagingQueryHookModule } from 'src/modules/messaging/common/query-hooks/messaging-query-hook.module'; import { WorkspaceMemberQueryHookModule } from 'src/modules/workspace-member/query-hooks/workspace-member-query-hook.module'; @Module({ diff --git a/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts b/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts index 9391fbacf..32973faab 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/auth.module.ts @@ -25,8 +25,8 @@ import { MicrosoftAuthController } from 'src/engine/core-modules/auth/controller import { AppTokenService } from 'src/engine/core-modules/app-token/services/app-token.service'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-channel.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { AuthResolver } from './auth.resolver'; diff --git a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts index 3dd53036e..bf6d6f662 100644 --- a/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts +++ b/packages/twenty-server/src/engine/core-modules/auth/services/google-apis.service.ts @@ -1,11 +1,9 @@ import { Injectable, Inject } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository, EntityManager } from 'typeorm'; +import { EntityManager } from 'typeorm'; import { v4 } from 'uuid'; import { TypeORMService } from 'src/database/typeorm/typeorm.service'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; @@ -25,16 +23,16 @@ import { ConnectedAccountWorkspaceEntity, ConnectedAccountProvider, } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; import { MessageChannelWorkspaceEntity, MessageChannelType, MessageChannelVisibility, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { - GmailFullMessageListFetchJobData, - GmailFullMessageListFetchJob, -} from 'src/modules/messaging/jobs/gmail-full-message-list-fetch.job'; + MessagingMessageListFetchJob, + MessagingMessageListFetchJobData, +} from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job'; @Injectable() export class GoogleAPIsService { @@ -46,8 +44,6 @@ export class GoogleAPIsService { @Inject(MessageQueue.calendarQueue) private readonly calendarQueueService: MessageQueueService, private readonly environmentService: EnvironmentService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) private readonly connectedAccountRepository: ConnectedAccountRepository, @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) @@ -156,8 +152,8 @@ export class GoogleAPIsService { isCalendarEnabled: boolean, ) { if (this.environmentService.get('MESSAGING_PROVIDER_GMAIL_ENABLED')) { - await this.messageQueueService.add( - GmailFullMessageListFetchJob.name, + await this.messageQueueService.add( + MessagingMessageListFetchJob.name, { workspaceId, connectedAccountId, diff --git a/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts b/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts index 71e823ad1..954461abd 100644 --- a/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts @@ -21,7 +21,6 @@ export enum FeatureFlagKeys { IsAirtableIntegrationEnabled = 'IS_AIRTABLE_INTEGRATION_ENABLED', IsPostgreSQLIntegrationEnabled = 'IS_POSTGRESQL_INTEGRATION_ENABLED', IsStripeIntegrationEnabled = 'IS_STRIPE_INTEGRATION_ENABLED', - IsGmailSyncV2Enabled = 'IS_GMAIL_SYNC_V2_ENABLED', IsContactCreationForSentAndReceivedEmailsEnabled = 'IS_CONTACT_CREATION_FOR_SENT_AND_RECEIVED_EMAILS_ENABLED', } diff --git a/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts b/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts index 6acee1a8b..e2223913e 100644 --- a/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts +++ b/packages/twenty-server/src/engine/integrations/message-queue/jobs.module.ts @@ -17,18 +17,14 @@ import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-s import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; import { CleanInactiveWorkspaceJob } from 'src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job'; import { CalendarEventParticipantModule } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.module'; -import { GmailMessagesImportModule } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import.module'; -import { GmailFullMessageListFetchModule } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.module'; -import { GmailPartialMessageListFetchModule } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.module'; import { TimelineActivityModule } from 'src/modules/timeline/timeline-activity.module'; import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; import { CalendarMessagingParticipantJobModule } from 'src/modules/calendar-messaging-participant/jobs/calendar-messaging-participant-job.module'; import { CalendarCronJobModule } from 'src/modules/calendar/crons/jobs/calendar-cron-job.module'; import { CalendarJobModule } from 'src/modules/calendar/jobs/calendar-job.module'; import { AutoCompaniesAndContactsCreationJobModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/jobs/auto-companies-and-contacts-creation-job.module'; -import { MessagingCronJobModule } from 'src/modules/messaging/crons/jobs/messaging-cron-job.module'; -import { MessagingJobModule } from 'src/modules/messaging/jobs/messaging-job.module'; import { TimelineJobModule } from 'src/modules/timeline/jobs/timeline-job.module'; +import { MessagingModule } from 'src/modules/messaging/messaging.module'; @Module({ imports: [ @@ -41,9 +37,7 @@ import { TimelineJobModule } from 'src/modules/timeline/jobs/timeline-job.module BillingModule, UserWorkspaceModule, WorkspaceModule, - GmailFullMessageListFetchModule, - GmailMessagesImportModule, - GmailPartialMessageListFetchModule, + MessagingModule, CalendarEventParticipantModule, TimelineActivityModule, StripeModule, @@ -53,8 +47,6 @@ import { TimelineJobModule } from 'src/modules/timeline/jobs/timeline-job.module CalendarCronJobModule, CalendarJobModule, AutoCompaniesAndContactsCreationJobModule, - MessagingCronJobModule, - MessagingJobModule, TimelineJobModule, ], providers: [ diff --git a/packages/twenty-server/src/engine/object-metadata-repository/metadata-to-repository.mapping.ts b/packages/twenty-server/src/engine/object-metadata-repository/metadata-to-repository.mapping.ts index d51248fa1..17b4d0e80 100644 --- a/packages/twenty-server/src/engine/object-metadata-repository/metadata-to-repository.mapping.ts +++ b/packages/twenty-server/src/engine/object-metadata-repository/metadata-to-repository.mapping.ts @@ -7,15 +7,15 @@ import { BlocklistRepository } from 'src/modules/connected-account/repositories/ import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { AuditLogRepository } from 'src/modules/timeline/repositiories/audit-log.repository'; import { TimelineActivityRepository } from 'src/modules/timeline/repositiories/timeline-activity.repository'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessageParticipantRepository } from 'src/modules/messaging/repositories/message-participant.repository'; -import { MessageThreadRepository } from 'src/modules/messaging/repositories/message-thread.repository'; -import { MessageRepository } from 'src/modules/messaging/repositories/message.repository'; -import { PersonRepository } from 'src/modules/person/repositories/person.repository'; import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository'; import { AttachmentRepository } from 'src/modules/attachment/repositories/attachment.repository'; import { CommentRepository } from 'src/modules/activity/repositories/comment.repository'; +import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessageParticipantRepository } from 'src/modules/messaging/common/repositories/message-participant.repository'; +import { MessageThreadRepository } from 'src/modules/messaging/common/repositories/message-thread.repository'; +import { MessageRepository } from 'src/modules/messaging/common/repositories/message.repository'; +import { PersonRepository } from 'src/modules/person/repositories/person.repository'; export const metadataToRepositoryMapping = { AuditLogWorkspaceEntity: AuditLogRepository, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts index e08c2cf15..be810ced1 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts @@ -58,7 +58,6 @@ export class AddStandardIdCommand extends CommandRunner { IS_AIRTABLE_INTEGRATION_ENABLED: true, IS_POSTGRESQL_INTEGRATION_ENABLED: true, IS_STRIPE_INTEGRATION_ENABLED: false, - IS_GMAIL_SYNC_V2_ENABLED: true, IS_CONTACT_CREATION_FOR_SENT_AND_RECEIVED_EMAILS_ENABLED: true, }, ); @@ -74,7 +73,6 @@ export class AddStandardIdCommand extends CommandRunner { IS_AIRTABLE_INTEGRATION_ENABLED: true, IS_POSTGRESQL_INTEGRATION_ENABLED: true, IS_STRIPE_INTEGRATION_ENABLED: false, - IS_GMAIL_SYNC_V2_ENABLED: true, IS_CONTACT_CREATION_FOR_SENT_AND_RECEIVED_EMAILS_ENABLED: true, }, ); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts index bba9e1ac6..39ef93760 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts @@ -10,11 +10,6 @@ import { CommentWorkspaceEntity } from 'src/modules/activity/standard-objects/co import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; import { ViewFieldWorkspaceEntity } from 'src/modules/view/standard-objects/view-field.workspace-entity'; @@ -27,6 +22,11 @@ import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/cale import { AuditLogWorkspaceEntity } from 'src/modules/timeline/standard-objects/audit-log.workspace-entity'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; import { BehavioralEventWorkspaceEntity } from 'src/modules/timeline/standard-objects/behavioral-event.workspace-entity'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; +import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; export const standardObjectMetadataDefinitions = [ ActivityTargetWorkspaceEntity, diff --git a/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/calendar-messaging-participant-job.module.ts b/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/calendar-messaging-participant-job.module.ts index 8328f4772..a2c338dac 100644 --- a/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/calendar-messaging-participant-job.module.ts +++ b/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/calendar-messaging-participant-job.module.ts @@ -3,10 +3,10 @@ import { Module } from '@nestjs/common'; import { MatchParticipantJob } from 'src/modules/calendar-messaging-participant/jobs/match-participant.job'; import { UnmatchParticipantJob } from 'src/modules/calendar-messaging-participant/jobs/unmatch-participant.job'; import { CalendarEventParticipantModule } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.module'; -import { MessageParticipantModule } from 'src/modules/messaging/services/message-participant/message-participant.module'; +import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; @Module({ - imports: [MessageParticipantModule, CalendarEventParticipantModule], + imports: [CalendarEventParticipantModule, MessagingCommonModule], providers: [ { provide: MatchParticipantJob.name, diff --git a/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/match-participant.job.ts b/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/match-participant.job.ts index 109a25e56..8f9015bfc 100644 --- a/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/match-participant.job.ts +++ b/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/match-participant.job.ts @@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common'; import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; import { CalendarEventParticipantService } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.service'; -import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service'; +import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service'; export type MatchParticipantJobData = { workspaceId: string; @@ -17,7 +17,7 @@ export class MatchParticipantJob implements MessageQueueJob { constructor( - private readonly messageParticipantService: MessageParticipantService, + private readonly messageParticipantService: MessagingMessageParticipantService, private readonly calendarEventParticipantService: CalendarEventParticipantService, ) {} diff --git a/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/unmatch-participant.job.ts b/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/unmatch-participant.job.ts index 73b64fcfd..11fee2cda 100644 --- a/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/unmatch-participant.job.ts +++ b/packages/twenty-server/src/modules/calendar-messaging-participant/jobs/unmatch-participant.job.ts @@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common'; import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; import { CalendarEventParticipantService } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.service'; -import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service'; +import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service'; export type UnmatchParticipantJobData = { workspaceId: string; @@ -17,7 +17,7 @@ export class UnmatchParticipantJob implements MessageQueueJob { constructor( - private readonly messageParticipantService: MessageParticipantService, + private readonly messageParticipantService: MessagingMessageParticipantService, private readonly calendarEventParticipantService: CalendarEventParticipantService, ) {} diff --git a/packages/twenty-server/src/modules/calendar/listeners/calendar-channel.listener.ts b/packages/twenty-server/src/modules/calendar/listeners/calendar-channel.listener.ts index 168aace11..3d1e28a55 100644 --- a/packages/twenty-server/src/modules/calendar/listeners/calendar-channel.listener.ts +++ b/packages/twenty-server/src/modules/calendar/listeners/calendar-channel.listener.ts @@ -9,7 +9,7 @@ import { CalendarCreateCompanyAndContactAfterSyncJobData, CalendarCreateCompanyAndContactAfterSyncJob, } from 'src/modules/calendar/jobs/calendar-create-company-and-contact-after-sync.job'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; @Injectable() export class CalendarChannelListener { diff --git a/packages/twenty-server/src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.service.ts b/packages/twenty-server/src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.service.ts index fc8d111ec..9f3f5d520 100644 --- a/packages/twenty-server/src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.service.ts +++ b/packages/twenty-server/src/modules/calendar/services/calendar-event-cleaner/calendar-event-cleaner.service.ts @@ -3,7 +3,7 @@ import { Injectable } from '@nestjs/common'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { CalendarEventRepository } from 'src/modules/calendar/repositories/calendar-event.repository'; import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-event.workspace-entity'; -import { deleteUsingPagination } from 'src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util'; +import { deleteUsingPagination } from 'src/modules/messaging/message-cleaner/utils/delete-using-pagination.util'; @Injectable() export class CalendarEventCleanerService { diff --git a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module.ts b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module.ts index 7b1116126..5e6d0fa68 100644 --- a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module.ts +++ b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module.ts @@ -7,11 +7,11 @@ import { CreateContactModule } from 'src/modules/connected-account/auto-companie import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; -import { MessageParticipantModule } from 'src/modules/messaging/services/message-participant/message-participant.module'; import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-event-participant.workspace-entity'; import { CalendarEventParticipantModule } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.module'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; @Module({ imports: [ @@ -22,7 +22,7 @@ import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature- WorkspaceMemberWorkspaceEntity, CalendarEventParticipantWorkspaceEntity, ]), - MessageParticipantModule, + MessagingCommonModule, WorkspaceDataSourceModule, CalendarEventParticipantModule, TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), diff --git a/packages/twenty-server/src/modules/messaging/listeners/messaging-message-channel.listener.ts b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/listeners/messaging-message-channel.listener.ts similarity index 89% rename from packages/twenty-server/src/modules/messaging/listeners/messaging-message-channel.listener.ts rename to packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/listeners/messaging-message-channel.listener.ts index 6f646f268..6b3cde398 100644 --- a/packages/twenty-server/src/modules/messaging/listeners/messaging-message-channel.listener.ts +++ b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/listeners/messaging-message-channel.listener.ts @@ -5,11 +5,11 @@ import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/t import { objectRecordChangedProperties } from 'src/engine/integrations/event-emitter/utils/object-record-changed-properties.util'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { MessagingCreateCompanyAndContactAfterSyncJobData, MessagingCreateCompanyAndContactAfterSyncJob, -} from 'src/modules/messaging/jobs/messaging-create-company-and-contact-after-sync.job'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +} from 'src/modules/messaging/message-participants-manager/jobs/messaging-create-company-and-contact-after-sync.job'; @Injectable() export class MessagingMessageChannelListener { diff --git a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service.ts b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service.ts index 981110b83..fce9ef65b 100644 --- a/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service.ts +++ b/packages/twenty-server/src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service.ts @@ -1,7 +1,6 @@ import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { EntityManager, Repository } from 'typeorm'; +import { EntityManager } from 'typeorm'; import compact from 'lodash.compact'; import { getDomainNameFromHandle } from 'src/modules/calendar-messaging-participant/utils/get-domain-name-from-handle.util'; @@ -16,11 +15,10 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta import { getUniqueContactsAndHandles } from 'src/modules/connected-account/auto-companies-and-contacts-creation/utils/get-unique-contacts-and-handles.util'; import { Contacts } from 'src/modules/connected-account/auto-companies-and-contacts-creation/types/contact.type'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service'; import { CalendarEventParticipantService } from 'src/modules/calendar/services/calendar-event-participant/calendar-event-participant.service'; import { filterOutContactsFromCompanyOrWorkspace } from 'src/modules/connected-account/auto-companies-and-contacts-creation/utils/filter-out-contacts-from-company-or-workspace.util'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; +import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service'; @Injectable() export class CreateCompanyAndContactService { @@ -32,10 +30,8 @@ export class CreateCompanyAndContactService { @InjectObjectMetadataRepository(WorkspaceMemberWorkspaceEntity) private readonly workspaceMemberRepository: WorkspaceMemberRepository, private readonly workspaceDataSourceService: WorkspaceDataSourceService, - private readonly messageParticipantService: MessageParticipantService, + private readonly messageParticipantService: MessagingMessageParticipantService, private readonly calendarEventParticipantService: CalendarEventParticipantService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, ) {} async createCompaniesAndPeople( diff --git a/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module.ts b/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module.ts index 1e090d1f7..0c3180c09 100644 --- a/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module.ts +++ b/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module.ts @@ -3,14 +3,14 @@ import { Module } from '@nestjs/common'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { GmailErrorHandlingModule } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module'; +import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; @Module({ imports: [ ObjectMetadataRepositoryModule.forFeature([ ConnectedAccountWorkspaceEntity, ]), - GmailErrorHandlingModule, + MessagingCommonModule, ], providers: [GoogleAPIRefreshAccessTokenService], exports: [GoogleAPIRefreshAccessTokenService], diff --git a/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service.ts b/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service.ts index 02a935471..0bdfcefb0 100644 --- a/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service.ts +++ b/packages/twenty-server/src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service.ts @@ -6,9 +6,10 @@ import { EnvironmentService } from 'src/engine/integrations/environment/environm import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { GmailErrorHandlingService } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; @Injectable() export class GoogleAPIRefreshAccessTokenService { @@ -18,7 +19,8 @@ export class GoogleAPIRefreshAccessTokenService { private readonly connectedAccountRepository: ConnectedAccountRepository, @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) private readonly messageChannelRepository: MessageChannelRepository, - private readonly gmailErrorHandlingService: GmailErrorHandlingService, + private readonly messagingTelemetryService: MessagingTelemetryService, + private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService, ) {} async refreshAndSaveAccessToken( @@ -65,13 +67,21 @@ export class GoogleAPIRefreshAccessTokenService { ); } - await this.gmailErrorHandlingService.handleGmailError( - { - code: error.code, - reason: error.response.data.error, - }, - 'messages-import', - messageChannel, + await this.messagingTelemetryService.track({ + eventName: `refresh-token.error.insufficient_permissions`, + workspaceId, + connectedAccountId: messageChannel.connectedAccountId, + messageChannelId: messageChannel.id, + message: `${error.code}: ${error.reason}`, + }); + + await this.messagingChannelSyncStatusService.markAsFailedInsufficientPermissionsAndFlushMessagesToImport( + messageChannel.id, + workspaceId, + ); + + await this.connectedAccountRepository.updateAuthFailedAt( + messageChannel.connectedAccountId, workspaceId, ); } diff --git a/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts b/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts index ceef7b7a9..481f31970 100644 --- a/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts +++ b/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts @@ -8,7 +8,6 @@ import { import { CONNECTED_ACCOUNT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-channel.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; @@ -17,6 +16,7 @@ import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/work import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; export enum ConnectedAccountProvider { GOOGLE = 'google', diff --git a/packages/twenty-server/src/modules/messaging/jobs/blocklist-item-delete-messages.job.ts b/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job.ts similarity index 85% rename from packages/twenty-server/src/modules/messaging/jobs/blocklist-item-delete-messages.job.ts rename to packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job.ts index b04605693..ac2f6defa 100644 --- a/packages/twenty-server/src/modules/messaging/jobs/blocklist-item-delete-messages.job.ts +++ b/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job.ts @@ -5,11 +5,11 @@ import { MessageQueueJob } from 'src/engine/integrations/message-queue/interface import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { BlocklistRepository } from 'src/modules/connected-account/repositories/blocklist.repository'; import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { ThreadCleanerService } from 'src/modules/messaging/services/thread-cleaner/thread-cleaner.service'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessagingMessageCleanerService } from 'src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service'; export type BlocklistItemDeleteMessagesJobData = { workspaceId: string; @@ -31,7 +31,7 @@ export class BlocklistItemDeleteMessagesJob private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository, @InjectObjectMetadataRepository(BlocklistWorkspaceEntity) private readonly blocklistRepository: BlocklistRepository, - private readonly threadCleanerService: ThreadCleanerService, + private readonly threadCleanerService: MessagingMessageCleanerService, ) {} async handle(data: BlocklistItemDeleteMessagesJobData): Promise { diff --git a/packages/twenty-server/src/modules/messaging/jobs/blocklist-reimport-messages.job.ts b/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job.ts similarity index 82% rename from packages/twenty-server/src/modules/messaging/jobs/blocklist-reimport-messages.job.ts rename to packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job.ts index 485a0a06b..12952b6ea 100644 --- a/packages/twenty-server/src/modules/messaging/jobs/blocklist-reimport-messages.job.ts +++ b/packages/twenty-server/src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job.ts @@ -5,7 +5,6 @@ import { MessageQueueJob } from 'src/engine/integrations/message-queue/interface import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { GmailFullMessageListFetchService } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service'; export type BlocklistReimportMessagesJobData = { workspaceId: string; @@ -22,7 +21,6 @@ export class BlocklistReimportMessagesJob constructor( @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) private readonly connectedAccountRepository: ConnectedAccountRepository, - private readonly gmailFullMessageListFetchService: GmailFullMessageListFetchService, ) {} async handle(data: BlocklistReimportMessagesJobData): Promise { @@ -46,11 +44,12 @@ export class BlocklistReimportMessagesJob return; } - await this.gmailFullMessageListFetchService.fetchConnectedAccountThreads( - workspaceId, - connectedAccount[0].id, - [handle], - ); + // TODO: reimplement that + // await this.gmailMessageListFetchJob.fetchConnectedAccountThreads( + // workspaceId, + // connectedAccount[0].id, + // [handle], + // ); this.logger.log( `Reimporting messages from ${handle} in workspace ${workspaceId} for workspace member ${workspaceMemberId} done`, diff --git a/packages/twenty-server/src/modules/messaging/listeners/messaging-blocklist.listener.ts b/packages/twenty-server/src/modules/messaging/blocklist-manager/listeners/messaging-blocklist.listener.ts similarity index 92% rename from packages/twenty-server/src/modules/messaging/listeners/messaging-blocklist.listener.ts rename to packages/twenty-server/src/modules/messaging/blocklist-manager/listeners/messaging-blocklist.listener.ts index f612cdc3e..8d2ff5e1f 100644 --- a/packages/twenty-server/src/modules/messaging/listeners/messaging-blocklist.listener.ts +++ b/packages/twenty-server/src/modules/messaging/blocklist-manager/listeners/messaging-blocklist.listener.ts @@ -9,11 +9,11 @@ import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard import { BlocklistReimportMessagesJob, BlocklistReimportMessagesJobData, -} from 'src/modules/messaging/jobs/blocklist-reimport-messages.job'; +} from 'src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-reimport-messages.job'; import { BlocklistItemDeleteMessagesJobData, BlocklistItemDeleteMessagesJob, -} from 'src/modules/messaging/jobs/blocklist-item-delete-messages.job'; +} from 'src/modules/messaging/blocklist-manager/jobs/messaging-blocklist-item-delete-messages.job'; import { ObjectRecordUpdateEvent } from 'src/engine/integrations/event-emitter/types/object-record-update.event'; @Injectable() diff --git a/packages/twenty-server/src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module.ts b/packages/twenty-server/src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module.ts new file mode 100644 index 000000000..0d59ad486 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; + +@Module({ + imports: [], + providers: [], + exports: [], +}) +export class MessagingBlocklistManagerModule {} diff --git a/packages/twenty-server/src/modules/messaging/common/messaging-common.module.ts b/packages/twenty-server/src/modules/messaging/common/messaging-common.module.ts new file mode 100644 index 000000000..f13575d94 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/common/messaging-common.module.ts @@ -0,0 +1,60 @@ +import { HttpModule } from '@nestjs/axios'; +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { AnalyticsModule } from 'src/engine/core-modules/analytics/analytics.module'; +import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; +import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; +import { AddPersonIdAndWorkspaceMemberIdModule } from 'src/modules/calendar-messaging-participant/services/add-person-id-and-workspace-member-id/add-person-id-and-workspace-member-id.module'; +import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; +import { MessagingErrorHandlingService } from 'src/modules/messaging/common/services/messaging-error-handling.service'; +import { MessagingFetchByBatchesService } from 'src/modules/messaging/common/services/messaging-fetch-by-batch.service'; +import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service'; +import { MessagingMessageThreadService } from 'src/modules/messaging/common/services/messaging-message-thread.service'; +import { MessagingMessageService } from 'src/modules/messaging/common/services/messaging-message.service'; +import { MessagingSaveMessagesAndEnqueueContactCreationService } from 'src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service'; +import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service'; +import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; +import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; +import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; + +@Module({ + imports: [ + HttpModule.register({ + baseURL: 'https://www.googleapis.com/batch/gmail/v1', + }), + AnalyticsModule, + WorkspaceDataSourceModule, + ObjectMetadataRepositoryModule.forFeature([ + PersonWorkspaceEntity, + MessageParticipantWorkspaceEntity, + MessageWorkspaceEntity, + MessageThreadWorkspaceEntity, + ]), + TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), + AddPersonIdAndWorkspaceMemberIdModule, + ], + providers: [ + MessagingMessageService, + MessagingMessageThreadService, + MessagingSaveMessagesAndEnqueueContactCreationService, + MessagingErrorHandlingService, + MessagingTelemetryService, + MessagingChannelSyncStatusService, + MessagingMessageParticipantService, + MessagingFetchByBatchesService, + ], + exports: [ + MessagingMessageService, + MessagingMessageThreadService, + MessagingSaveMessagesAndEnqueueContactCreationService, + MessagingErrorHandlingService, + MessagingTelemetryService, + MessagingChannelSyncStatusService, + MessagingMessageParticipantService, + MessagingFetchByBatchesService, + ], +}) +export class MessagingCommonModule {} diff --git a/packages/twenty-server/src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts similarity index 92% rename from packages/twenty-server/src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook.ts rename to packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts index bb83bda45..876a3630b 100644 --- a/packages/twenty-server/src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook.ts @@ -10,15 +10,15 @@ import groupBy from 'lodash.groupby'; import { WorkspacePreQueryHook } from 'src/engine/api/graphql/workspace-query-runner/workspace-pre-query-hook/interfaces/workspace-pre-query-hook.interface'; import { FindManyResolverArgs } from 'src/engine/api/graphql/workspace-resolver-builder/interfaces/workspace-resolvers-builder.interface'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { WorkspaceMemberRepository } from 'src/modules/workspace-member/repositories/workspace-member.repository'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; +import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; @Injectable() export class MessageFindManyPreQueryHook implements WorkspacePreQueryHook { diff --git a/packages/twenty-server/src/modules/messaging/query-hooks/message/message-find-one.pre-query-hook.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/query-hooks/message/message-find-one.pre-query-hook.ts rename to packages/twenty-server/src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook.ts diff --git a/packages/twenty-server/src/modules/messaging/query-hooks/messaging-query-hook.module.ts b/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts similarity index 80% rename from packages/twenty-server/src/modules/messaging/query-hooks/messaging-query-hook.module.ts rename to packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts index 7dfabdeb1..2a80f5152 100644 --- a/packages/twenty-server/src/modules/messaging/query-hooks/messaging-query-hook.module.ts +++ b/packages/twenty-server/src/modules/messaging/common/query-hooks/messaging-query-hook.module.ts @@ -1,12 +1,12 @@ import { Module } from '@nestjs/common'; -import { MessageFindManyPreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-many.pre-query.hook'; -import { MessageFindOnePreQueryHook } from 'src/modules/messaging/query-hooks/message/message-find-one.pre-query-hook'; import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +import { MessageFindManyPreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-many.pre-query.hook'; +import { MessageFindOnePreQueryHook } from 'src/modules/messaging/common/query-hooks/message/message-find-one.pre-query-hook'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; @Module({ imports: [ diff --git a/packages/twenty-server/src/modules/messaging/repositories/message-channel-message-association.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message-channel-message-association.repository.ts similarity index 98% rename from packages/twenty-server/src/modules/messaging/repositories/message-channel-message-association.repository.ts rename to packages/twenty-server/src/modules/messaging/common/repositories/message-channel-message-association.repository.ts index 35feb0968..fddbf24c6 100644 --- a/packages/twenty-server/src/modules/messaging/repositories/message-channel-message-association.repository.ts +++ b/packages/twenty-server/src/modules/messaging/common/repositories/message-channel-message-association.repository.ts @@ -3,8 +3,8 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; @Injectable() export class MessageChannelMessageAssociationRepository { diff --git a/packages/twenty-server/src/modules/messaging/repositories/message-channel.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message-channel.repository.ts similarity index 98% rename from packages/twenty-server/src/modules/messaging/repositories/message-channel.repository.ts rename to packages/twenty-server/src/modules/messaging/common/repositories/message-channel.repository.ts index 3eb6f9d76..0c86ba4de 100644 --- a/packages/twenty-server/src/modules/messaging/repositories/message-channel.repository.ts +++ b/packages/twenty-server/src/modules/messaging/common/repositories/message-channel.repository.ts @@ -3,12 +3,12 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; +import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { MessageChannelWorkspaceEntity, MessageChannelSyncStatus, MessageChannelSyncSubStatus, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; +} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; @Injectable() export class MessageChannelRepository { diff --git a/packages/twenty-server/src/modules/messaging/repositories/message-participant.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message-participant.repository.ts similarity index 97% rename from packages/twenty-server/src/modules/messaging/repositories/message-participant.repository.ts rename to packages/twenty-server/src/modules/messaging/common/repositories/message-participant.repository.ts index 4ae92c68a..c92b19d8e 100644 --- a/packages/twenty-server/src/modules/messaging/repositories/message-participant.repository.ts +++ b/packages/twenty-server/src/modules/messaging/common/repositories/message-participant.repository.ts @@ -3,9 +3,9 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; -import { ParticipantWithId } from 'src/modules/messaging/types/gmail-message'; +import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; +import { ParticipantWithId } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; @Injectable() export class MessageParticipantRepository { diff --git a/packages/twenty-server/src/modules/messaging/repositories/message-thread.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message-thread.repository.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/repositories/message-thread.repository.ts rename to packages/twenty-server/src/modules/messaging/common/repositories/message-thread.repository.ts diff --git a/packages/twenty-server/src/modules/messaging/repositories/message.repository.ts b/packages/twenty-server/src/modules/messaging/common/repositories/message.repository.ts similarity index 97% rename from packages/twenty-server/src/modules/messaging/repositories/message.repository.ts rename to packages/twenty-server/src/modules/messaging/common/repositories/message.repository.ts index 01e088ee7..ed75638c1 100644 --- a/packages/twenty-server/src/modules/messaging/repositories/message.repository.ts +++ b/packages/twenty-server/src/modules/messaging/common/repositories/message.repository.ts @@ -3,8 +3,8 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; @Injectable() export class MessageRepository { diff --git a/packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-channel-sync-status.service.ts similarity index 95% rename from packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-channel-sync-status.service.ts index 522d71dae..1e1884576 100644 --- a/packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-channel-sync-status.service.ts @@ -4,15 +4,15 @@ import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; import { MessageChannelWorkspaceEntity, MessageChannelSyncSubStatus, MessageChannelSyncStatus, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; @Injectable() -export class MessageChannelSyncStatusService { +export class MessagingChannelSyncStatusService { constructor( @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) private readonly messageChannelRepository: MessageChannelRepository, diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-error-handling.service.ts similarity index 84% rename from packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-error-handling.service.ts index b0f96a8cd..5073ade63 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-error-handling.service.ts @@ -6,9 +6,9 @@ import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repos import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelSyncStatusService } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service'; -import { MessagingTelemetryService } from 'src/modules/messaging/services/telemetry/messaging-telemetry.service'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; +import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; type SyncStep = | 'partial-message-list-fetch' @@ -21,11 +21,11 @@ export type GmailError = { }; @Injectable() -export class GmailErrorHandlingService { +export class MessagingErrorHandlingService { constructor( @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) private readonly connectedAccountRepository: ConnectedAccountRepository, - private readonly messageChannelSyncStatusService: MessageChannelSyncStatusService, + private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService, private readonly messagingTelemetryService: MessagingTelemetryService, ) {} @@ -92,7 +92,7 @@ export class GmailErrorHandlingService { break; default: - await this.messageChannelSyncStatusService.markAsFailedUnknownAndFlushMessagesToImport( + await this.messagingChannelSyncStatusService.markAsFailedUnknownAndFlushMessagesToImport( messageChannel.id, workspaceId, ); @@ -116,21 +116,21 @@ export class GmailErrorHandlingService { switch (syncStep) { case 'full-message-list-fetch': - await this.messageChannelSyncStatusService.scheduleFullMessageListFetch( + await this.messagingChannelSyncStatusService.scheduleFullMessageListFetch( messageChannel.id, workspaceId, ); break; case 'partial-message-list-fetch': - await this.messageChannelSyncStatusService.schedulePartialMessageListFetch( + await this.messagingChannelSyncStatusService.schedulePartialMessageListFetch( messageChannel.id, workspaceId, ); break; case 'messages-import': - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messagingChannelSyncStatusService.scheduleMessagesImport( messageChannel.id, workspaceId, ); @@ -155,7 +155,7 @@ export class GmailErrorHandlingService { message: `${error.code}: ${error.reason}`, }); - await this.messageChannelSyncStatusService.markAsFailedInsufficientPermissionsAndFlushMessagesToImport( + await this.messagingChannelSyncStatusService.markAsFailedInsufficientPermissionsAndFlushMessagesToImport( messageChannel.id, workspaceId, ); @@ -184,7 +184,7 @@ export class GmailErrorHandlingService { message: `404: ${error.reason}`, }); - await this.messageChannelSyncStatusService.resetAndScheduleFullMessageListFetch( + await this.messagingChannelSyncStatusService.resetAndScheduleFullMessageListFetch( messageChannel.id, workspaceId, ); diff --git a/packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-fetch-by-batch.service.ts similarity index 93% rename from packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-fetch-by-batch.service.ts index 4d12b306b..354ab9265 100644 --- a/packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-fetch-by-batch.service.ts @@ -3,11 +3,11 @@ import { Injectable } from '@nestjs/common'; import { AxiosResponse } from 'axios'; -import { BatchQueries } from 'src/modules/messaging/types/batch-queries'; -import { GmailMessageParsedResponse } from 'src/modules/messaging/types/gmail-message-parsed-response'; +import { GmailMessageParsedResponse } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message-parsed-response'; +import { BatchQueries } from 'src/modules/messaging/message-import-manager/types/batch-queries'; @Injectable() -export class FetchByBatchesService { +export class MessagingFetchByBatchesService { constructor(private readonly httpService: HttpService) {} async fetchAllByBatches( diff --git a/packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-message-participant.service.ts similarity index 93% rename from packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-message-participant.service.ts index 9d23d7e09..c9538d444 100644 --- a/packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-message-participant.service.ts @@ -3,18 +3,20 @@ import { Injectable } from '@nestjs/common'; import { EntityManager } from 'typeorm'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { ParticipantWithMessageId } from 'src/modules/messaging/types/gmail-message'; import { PersonRepository } from 'src/modules/person/repositories/person.repository'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; import { getFlattenedValuesAndValuesStringForBatchRawQuery } from 'src/modules/calendar/utils/get-flattened-values-and-values-string-for-batch-raw-query.util'; -import { MessageParticipantRepository } from 'src/modules/messaging/repositories/message-participant.repository'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; import { AddPersonIdAndWorkspaceMemberIdService } from 'src/modules/calendar-messaging-participant/services/add-person-id-and-workspace-member-id/add-person-id-and-workspace-member-id.service'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; +import { MessageParticipantRepository } from 'src/modules/messaging/common/repositories/message-participant.repository'; +import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; +import { ParticipantWithMessageId } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; +// Todo: this is not the right place for this file. The code needs to be refactored in term of business modules with a precise scope. +// Putting it here to avoid circular dependencies for now. @Injectable() -export class MessageParticipantService { +export class MessagingMessageParticipantService { constructor( private readonly workspaceDataSourceService: WorkspaceDataSourceService, @InjectObjectMetadataRepository(MessageParticipantWorkspaceEntity) diff --git a/packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-message-thread.service.ts similarity index 79% rename from packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-message-thread.service.ts index 4076dbdc6..35c575638 100644 --- a/packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-message-thread.service.ts @@ -4,15 +4,15 @@ import { EntityManager } from 'typeorm'; import { v4 } from 'uuid'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageRepository } from 'src/modules/messaging/repositories/message.repository'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageThreadRepository } from 'src/modules/messaging/repositories/message-thread.repository'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; +import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; +import { MessageThreadRepository } from 'src/modules/messaging/common/repositories/message-thread.repository'; +import { MessageRepository } from 'src/modules/messaging/common/repositories/message.repository'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; @Injectable() -export class MessageThreadService { +export class MessagingMessageThreadService { constructor( @InjectObjectMetadataRepository( MessageChannelMessageAssociationWorkspaceEntity, diff --git a/packages/twenty-server/src/modules/messaging/services/message/message.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts similarity index 90% rename from packages/twenty-server/src/modules/messaging/services/message/message.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts index 219390b87..4b475d095 100644 --- a/packages/twenty-server/src/modules/messaging/services/message/message.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-message.service.ts @@ -4,23 +4,23 @@ import { DataSource, EntityManager } from 'typeorm'; import { v4 } from 'uuid'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; -import { GmailMessage } from 'src/modules/messaging/types/gmail-message'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageRepository } from 'src/modules/messaging/repositories/message.repository'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessageThreadService } from 'src/modules/messaging/services/message-thread/message-thread.service'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageThreadRepository } from 'src/modules/messaging/repositories/message-thread.repository'; +import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessageThreadRepository } from 'src/modules/messaging/common/repositories/message-thread.repository'; +import { MessageRepository } from 'src/modules/messaging/common/repositories/message.repository'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; +import { GmailMessage } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; +import { MessagingMessageThreadService } from 'src/modules/messaging/common/services/messaging-message-thread.service'; @Injectable() -export class MessageService { - private readonly logger = new Logger(MessageService.name); +export class MessagingMessageService { + private readonly logger = new Logger(MessagingMessageService.name); constructor( private readonly workspaceDataSourceService: WorkspaceDataSourceService, @@ -34,7 +34,7 @@ export class MessageService { private readonly messageChannelRepository: MessageChannelRepository, @InjectObjectMetadataRepository(MessageThreadWorkspaceEntity) private readonly messageThreadRepository: MessageThreadRepository, - private readonly messageThreadService: MessageThreadService, + private readonly messageThreadService: MessagingMessageThreadService, ) {} public async saveMessagesWithinTransaction( diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/save-messages-and-enqueue-contact-creation.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service.ts similarity index 87% rename from packages/twenty-server/src/modules/messaging/services/gmail-messages-import/save-messages-and-enqueue-contact-creation.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service.ts index 63c07ba1a..4e14d46a5 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/save-messages-and-enqueue-contact-creation.service.ts +++ b/packages/twenty-server/src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service.ts @@ -8,13 +8,6 @@ import { MessageQueueService } from 'src/engine/integrations/message-queue/servi import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service'; -import { MessageService } from 'src/modules/messaging/services/message/message.service'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { - GmailMessage, - ParticipantWithMessageId, -} from 'src/modules/messaging/types/gmail-message'; import { CreateCompanyAndContactJobData, CreateCompanyAndContactJob, @@ -23,15 +16,22 @@ import { FeatureFlagEntity, FeatureFlagKeys, } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { + GmailMessage, + ParticipantWithMessageId, +} from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; +import { MessagingMessageService } from 'src/modules/messaging/common/services/messaging-message.service'; +import { MessagingMessageParticipantService } from 'src/modules/messaging/common/services/messaging-message-participant.service'; @Injectable() -export class SaveMessagesAndEnqueueContactCreationService { +export class MessagingSaveMessagesAndEnqueueContactCreationService { constructor( private readonly workspaceDataSourceService: WorkspaceDataSourceService, @Inject(MessageQueue.messagingQueue) private readonly messageQueueService: MessageQueueService, - private readonly messageService: MessageService, - private readonly messageParticipantService: MessageParticipantService, + private readonly messageService: MessagingMessageService, + private readonly messageParticipantService: MessagingMessageParticipantService, @InjectRepository(FeatureFlagEntity, 'core') private readonly featureFlagRepository: Repository, ) {} diff --git a/packages/twenty-server/src/modules/messaging/services/telemetry/messaging-telemetry.service.ts b/packages/twenty-server/src/modules/messaging/common/services/messaging-telemetry.service.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/services/telemetry/messaging-telemetry.service.ts rename to packages/twenty-server/src/modules/messaging/common/services/messaging-telemetry.service.ts diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts similarity index 94% rename from packages/twenty-server/src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity.ts rename to packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts index 55ac9bb44..91e9fa828 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts @@ -3,9 +3,6 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; @@ -14,6 +11,9 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageChannelMessageAssociation, diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message-channel.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts similarity index 98% rename from packages/twenty-server/src/modules/messaging/standard-objects/message-channel.workspace-entity.ts rename to packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts index f947498c7..b457677a6 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message-channel.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts @@ -8,7 +8,6 @@ import { import { MESSAGE_CHANNEL_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; @@ -16,6 +15,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; export enum MessageChannelSyncStatus { // TO BE DEPRECATED diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message-participant.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts similarity index 97% rename from packages/twenty-server/src/modules/messaging/standard-objects/message-participant.workspace-entity.ts rename to packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts index 7b8264a34..b8c1e09f6 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message-participant.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts @@ -3,7 +3,6 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/i import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; @@ -14,6 +13,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageParticipant, diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message-thread.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread.workspace-entity.ts similarity index 91% rename from packages/twenty-server/src/modules/messaging/standard-objects/message-thread.workspace-entity.ts rename to packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread.workspace-entity.ts index ff38d03d4..64b81723f 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message-thread.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread.workspace-entity.ts @@ -6,14 +6,14 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { MESSAGE_THREAD_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.messageThread, diff --git a/packages/twenty-server/src/modules/messaging/standard-objects/message.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts similarity index 95% rename from packages/twenty-server/src/modules/messaging/standard-objects/message.workspace-entity.ts rename to packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts index 03f5752b4..a3ad1ea48 100644 --- a/packages/twenty-server/src/modules/messaging/standard-objects/message.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts @@ -7,9 +7,6 @@ import { } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { MESSAGE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; @@ -17,6 +14,9 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; +import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.message, diff --git a/packages/twenty-server/src/modules/messaging/constants/gmail-excluded-categories.ts b/packages/twenty-server/src/modules/messaging/constants/gmail-excluded-categories.ts deleted file mode 100644 index 1f3dcf828..000000000 --- a/packages/twenty-server/src/modules/messaging/constants/gmail-excluded-categories.ts +++ /dev/null @@ -1 +0,0 @@ -export const GMAIL_EXCLUDED_CATEGORIES = ['promotions', 'social', 'forums']; diff --git a/packages/twenty-server/src/modules/messaging/constants/gmail-ongoing-sync-timeout.constant.ts b/packages/twenty-server/src/modules/messaging/constants/gmail-ongoing-sync-timeout.constant.ts deleted file mode 100644 index c4c67700d..000000000 --- a/packages/twenty-server/src/modules/messaging/constants/gmail-ongoing-sync-timeout.constant.ts +++ /dev/null @@ -1 +0,0 @@ -export const GMAIL_ONGOING_SYNC_TIMEOUT = 1000 * 60 * 60; // 1 hour diff --git a/packages/twenty-server/src/modules/messaging/constants/gmail-users-history-max-result.constant.ts b/packages/twenty-server/src/modules/messaging/constants/gmail-users-history-max-result.constant.ts deleted file mode 100644 index d208d7d24..000000000 --- a/packages/twenty-server/src/modules/messaging/constants/gmail-users-history-max-result.constant.ts +++ /dev/null @@ -1 +0,0 @@ -export const GMAIL_USERS_HISTORY_MAX_RESULT = 500; diff --git a/packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-get-batch-size.constant.ts b/packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-get-batch-size.constant.ts deleted file mode 100644 index b8ca7bb59..000000000 --- a/packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-get-batch-size.constant.ts +++ /dev/null @@ -1 +0,0 @@ -export const GMAIL_USERS_MESSAGES_GET_BATCH_SIZE = 20; diff --git a/packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-list-max-result.constant.ts b/packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-list-max-result.constant.ts deleted file mode 100644 index 29b301215..000000000 --- a/packages/twenty-server/src/modules/messaging/constants/gmail-users-messages-list-max-result.constant.ts +++ /dev/null @@ -1 +0,0 @@ -export const GMAIL_USERS_MESSAGES_LIST_MAX_RESULT = 500; diff --git a/packages/twenty-server/src/modules/messaging/crons/commands/messaging-cron-commands.module.ts b/packages/twenty-server/src/modules/messaging/crons/commands/messaging-cron-commands.module.ts deleted file mode 100644 index 082aff092..000000000 --- a/packages/twenty-server/src/modules/messaging/crons/commands/messaging-cron-commands.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { GmailMessagesImportCronCommand } from 'src/modules/messaging/crons/commands/gmail-messages-import.cron.command'; -import { GmailMessageListFetchCronCommand } from 'src/modules/messaging/crons/commands/gmail-message-list-fetch.cron.command'; -@Module({ - imports: [ - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - ]), - ], - providers: [GmailMessageListFetchCronCommand, GmailMessagesImportCronCommand], -}) -export class MessagingCronCommandsModule {} diff --git a/packages/twenty-server/src/modules/messaging/crons/jobs/gmail-messages-import.cron.job.ts b/packages/twenty-server/src/modules/messaging/crons/jobs/gmail-messages-import.cron.job.ts deleted file mode 100644 index c34be9edf..000000000 --- a/packages/twenty-server/src/modules/messaging/crons/jobs/gmail-messages-import.cron.job.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { Repository, In } from 'typeorm'; - -import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; - -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { GmailMessagesImportService } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service'; -import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; -import { GmailMessagesImportV2Service } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import-v2.service'; -import { - FeatureFlagEntity, - FeatureFlagKeys, -} from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { MessagingTelemetryService } from 'src/modules/messaging/services/telemetry/messaging-telemetry.service'; - -@Injectable() -export class GmailMessagesImportCronJob implements MessageQueueJob { - private readonly logger = new Logger(GmailMessagesImportCronJob.name); - - constructor( - @InjectRepository(Workspace, 'core') - private readonly workspaceRepository: Repository, - @InjectRepository(DataSourceEntity, 'metadata') - private readonly dataSourceRepository: Repository, - @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) - private readonly messageChannelRepository: MessageChannelRepository, - private readonly gmailFetchMessageContentFromCacheService: GmailMessagesImportService, - private readonly gmailFetchMessageContentFromCacheV2Service: GmailMessagesImportV2Service, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, - private readonly environmentService: EnvironmentService, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, - private readonly messagingTelemetryService: MessagingTelemetryService, - ) {} - - async handle(): Promise { - const workspaceIds = ( - await this.workspaceRepository.find({ - where: this.environmentService.get('IS_BILLING_ENABLED') - ? { - subscriptionStatus: In(['active', 'trialing', 'past_due']), - } - : {}, - select: ['id'], - }) - ).map((workspace) => workspace.id); - - const dataSources = await this.dataSourceRepository.find({ - where: { - workspaceId: In(workspaceIds), - }, - }); - - const workspaceIdsWithDataSources = new Set( - dataSources.map((dataSource) => dataSource.workspaceId), - ); - - for (const workspaceId of workspaceIdsWithDataSources) { - await this.fetchWorkspaceMessages(workspaceId); - } - } - - private async fetchWorkspaceMessages(workspaceId: string): Promise { - const messageChannels = - await this.messageChannelRepository.getAll(workspaceId); - - const isGmailSyncV2EnabledFeatureFlag = - await this.featureFlagRepository.findOneBy({ - workspaceId: workspaceId, - key: FeatureFlagKeys.IsGmailSyncV2Enabled, - value: true, - }); - - const isGmailSyncV2Enabled = isGmailSyncV2EnabledFeatureFlag?.value; - - for (const messageChannel of messageChannels) { - if (!messageChannel?.isSyncEnabled) { - continue; - } - - if (isGmailSyncV2Enabled) { - await this.messagingTelemetryService.track({ - eventName: 'messages_import.triggered', - workspaceId, - connectedAccountId: messageChannel.connectedAccountId, - messageChannelId: messageChannel.id, - }); - - const connectedAccount = - await this.connectedAccountRepository.getConnectedAccountOrThrow( - workspaceId, - messageChannel.connectedAccountId, - ); - - await this.gmailFetchMessageContentFromCacheV2Service.processMessageBatchImport( - messageChannel, - connectedAccount, - workspaceId, - ); - } else { - await this.gmailFetchMessageContentFromCacheService.fetchMessageContentFromCache( - workspaceId, - messageChannel.connectedAccountId, - ); - } - } - } -} diff --git a/packages/twenty-server/src/modules/messaging/crons/jobs/messaging-cron-job.module.ts b/packages/twenty-server/src/modules/messaging/crons/jobs/messaging-cron-job.module.ts deleted file mode 100644 index b54d9cb34..000000000 --- a/packages/twenty-server/src/modules/messaging/crons/jobs/messaging-cron-job.module.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; -import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { GmailMessagesImportCronJob } from 'src/modules/messaging/crons/jobs/gmail-messages-import.cron.job'; -import { GmailMessageListFetchCronJob } from 'src/modules/messaging/crons/jobs/gmail-message-list-fetch.cron.job'; -import { GmailMessagesImportModule } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import.module'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessagingTelemetryModule } from 'src/modules/messaging/services/telemetry/messaging-telemetry.module'; - -@Module({ - imports: [ - TypeOrmModule.forFeature([Workspace, FeatureFlagEntity], 'core'), - TypeOrmModule.forFeature([DataSourceEntity], 'metadata'), - ObjectMetadataRepositoryModule.forFeature([MessageChannelWorkspaceEntity]), - GmailMessagesImportModule, - MessagingTelemetryModule, - ], - providers: [ - { - provide: GmailMessagesImportCronJob.name, - useClass: GmailMessagesImportCronJob, - }, - { - provide: GmailMessageListFetchCronJob.name, - useClass: GmailMessageListFetchCronJob, - }, - ], -}) -export class MessagingCronJobModule {} diff --git a/packages/twenty-server/src/modules/messaging/jobs/gmail-full-message-list-fetch.job.ts b/packages/twenty-server/src/modules/messaging/jobs/gmail-full-message-list-fetch.job.ts deleted file mode 100644 index d4a82435b..000000000 --- a/packages/twenty-server/src/modules/messaging/jobs/gmail-full-message-list-fetch.job.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { Repository } from 'typeorm'; - -import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; - -import { - FeatureFlagEntity, - FeatureFlagKeys, -} from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service'; -import { GmailFullMessageListFetchService } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service'; -import { GmailFullMessageListFetchV2Service } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessagingTelemetryService } from 'src/modules/messaging/services/telemetry/messaging-telemetry.service'; - -export type GmailFullMessageListFetchJobData = { - workspaceId: string; - connectedAccountId: string; -}; - -@Injectable() -export class GmailFullMessageListFetchJob - implements MessageQueueJob -{ - private readonly logger = new Logger(GmailFullMessageListFetchJob.name); - - constructor( - private readonly googleAPIsRefreshAccessTokenService: GoogleAPIRefreshAccessTokenService, - private readonly gmailFullMessageListFetchService: GmailFullMessageListFetchService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, - private readonly gmailFullMessageListFetchV2Service: GmailFullMessageListFetchV2Service, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, - @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) - private readonly messageChannelRepository: MessageChannelRepository, - private readonly messagingTelemetryService: MessagingTelemetryService, - ) {} - - async handle(data: GmailFullMessageListFetchJobData): Promise { - const { workspaceId, connectedAccountId } = data; - - this.logger.log( - `gmail full-sync for workspace ${workspaceId} and account ${connectedAccountId}`, - ); - - try { - await this.googleAPIsRefreshAccessTokenService.refreshAndSaveAccessToken( - workspaceId, - connectedAccountId, - ); - } catch (e) { - this.logger.error( - `Error refreshing access token for connected account ${connectedAccountId} in workspace ${workspaceId}`, - e, - ); - - return; - } - - const isGmailSyncV2EnabledFeatureFlag = - await this.featureFlagRepository.findOneBy({ - workspaceId: workspaceId, - key: FeatureFlagKeys.IsGmailSyncV2Enabled, - value: true, - }); - - const isGmailSyncV2Enabled = isGmailSyncV2EnabledFeatureFlag?.value; - - if (isGmailSyncV2Enabled) { - // Todo delete this code block after migration - const connectedAccount = await this.connectedAccountRepository.getById( - connectedAccountId, - workspaceId, - ); - - if (!connectedAccount) { - throw new Error( - `Connected account ${connectedAccountId} not found in workspace ${workspaceId}`, - ); - } - - const messageChannel = - await this.messageChannelRepository.getFirstByConnectedAccountId( - connectedAccountId, - workspaceId, - ); - - if (!messageChannel) { - throw new Error( - `No message channel found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - } - - await this.messagingTelemetryService.track({ - eventName: 'full_message_list_fetch.started', - workspaceId, - connectedAccountId, - }); - - await this.gmailFullMessageListFetchV2Service.processMessageListFetch( - messageChannel, - connectedAccount, - workspaceId, - ); - - await this.messagingTelemetryService.track({ - eventName: 'full_message_list_fetch.completed', - workspaceId, - connectedAccountId, - messageChannelId: messageChannel.id, - }); - } else { - await this.gmailFullMessageListFetchService.fetchConnectedAccountThreads( - data.workspaceId, - data.connectedAccountId, - ); - } - } -} diff --git a/packages/twenty-server/src/modules/messaging/jobs/gmail-partial-message-list-fetch.job.ts b/packages/twenty-server/src/modules/messaging/jobs/gmail-partial-message-list-fetch.job.ts deleted file mode 100644 index 9954492ba..000000000 --- a/packages/twenty-server/src/modules/messaging/jobs/gmail-partial-message-list-fetch.job.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; - -import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; - -import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service'; -import { GmailPartialMessageListFetchService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.service'; - -export type GmailPartialMessageListFetchJobData = { - workspaceId: string; - connectedAccountId: string; -}; - -@Injectable() -export class GmailPartialMessageListFetchJob - implements MessageQueueJob -{ - private readonly logger = new Logger(GmailPartialMessageListFetchJob.name); - - constructor( - private readonly googleAPIsRefreshAccessTokenService: GoogleAPIRefreshAccessTokenService, - private readonly gmailPartialSyncService: GmailPartialMessageListFetchService, - ) {} - - async handle(data: GmailPartialMessageListFetchJobData): Promise { - this.logger.log( - `gmail partial-sync for workspace ${data.workspaceId} and account ${data.connectedAccountId}`, - ); - - try { - await this.googleAPIsRefreshAccessTokenService.refreshAndSaveAccessToken( - data.workspaceId, - data.connectedAccountId, - ); - } catch (e) { - this.logger.error( - `Error refreshing access token for connected account ${data.connectedAccountId} in workspace ${data.workspaceId}`, - e, - ); - - return; - } - - await this.gmailPartialSyncService.fetchConnectedAccountThreads( - data.workspaceId, - data.connectedAccountId, - ); - } -} diff --git a/packages/twenty-server/src/modules/messaging/jobs/messaging-job.module.ts b/packages/twenty-server/src/modules/messaging/jobs/messaging-job.module.ts deleted file mode 100644 index 63b78ffe3..000000000 --- a/packages/twenty-server/src/modules/messaging/jobs/messaging-job.module.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { AutoCompaniesAndContactsCreationModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module'; -import { GoogleAPIRefreshAccessTokenModule } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module'; -import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { BlocklistItemDeleteMessagesJob } from 'src/modules/messaging/jobs/blocklist-item-delete-messages.job'; -import { BlocklistReimportMessagesJob } from 'src/modules/messaging/jobs/blocklist-reimport-messages.job'; -import { DeleteConnectedAccountAssociatedMessagingDataJob } from 'src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job'; -import { GmailFullMessageListFetchJob } from 'src/modules/messaging/jobs/gmail-full-message-list-fetch.job'; -import { GmailMessageListFetchJob } from 'src/modules/messaging/jobs/gmail-message-list-fetch.job'; -import { GmailPartialMessageListFetchJob } from 'src/modules/messaging/jobs/gmail-partial-message-list-fetch.job'; -import { MessagingCreateCompanyAndContactAfterSyncJob } from 'src/modules/messaging/jobs/messaging-create-company-and-contact-after-sync.job'; -import { GmailFullMessageListFetchModule } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.module'; -import { GmailPartialMessageListFetchModule } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.module'; -import { SetMessageChannelSyncStatusModule } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module'; -import { MessagingTelemetryModule } from 'src/modules/messaging/services/telemetry/messaging-telemetry.module'; -import { ThreadCleanerModule } from 'src/modules/messaging/services/thread-cleaner/thread-cleaner.module'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; - -@Module({ - imports: [ - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - MessageChannelWorkspaceEntity, - MessageParticipantWorkspaceEntity, - MessageChannelMessageAssociationWorkspaceEntity, - BlocklistWorkspaceEntity, - ]), - MessagingTelemetryModule, - GmailFullMessageListFetchModule, - GmailPartialMessageListFetchModule, - ThreadCleanerModule, - GoogleAPIRefreshAccessTokenModule, - AutoCompaniesAndContactsCreationModule, - TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), - SetMessageChannelSyncStatusModule, - ], - providers: [ - { - provide: BlocklistReimportMessagesJob.name, - useClass: BlocklistReimportMessagesJob, - }, - { - provide: BlocklistItemDeleteMessagesJob.name, - useClass: BlocklistItemDeleteMessagesJob, - }, - { - provide: GmailFullMessageListFetchJob.name, - useClass: GmailFullMessageListFetchJob, - }, - { - provide: GmailPartialMessageListFetchJob.name, - useClass: GmailPartialMessageListFetchJob, - }, - { - provide: GmailMessageListFetchJob.name, - useClass: GmailMessageListFetchJob, - }, - { - provide: DeleteConnectedAccountAssociatedMessagingDataJob.name, - useClass: DeleteConnectedAccountAssociatedMessagingDataJob, - }, - { - provide: MessagingCreateCompanyAndContactAfterSyncJob.name, - useClass: MessagingCreateCompanyAndContactAfterSyncJob, - }, - ], -}) -export class MessagingJobModule {} diff --git a/packages/twenty-server/src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job.ts similarity index 50% rename from packages/twenty-server/src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job.ts rename to packages/twenty-server/src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job.ts index eacef905b..5cba9355c 100644 --- a/packages/twenty-server/src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job.ts @@ -2,32 +2,33 @@ import { Injectable, Logger } from '@nestjs/common'; import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; -import { ThreadCleanerService } from 'src/modules/messaging/services/thread-cleaner/thread-cleaner.service'; +import { MessagingMessageCleanerService } from 'src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service'; -export type DeleteConnectedAccountAssociatedMessagingDataJobData = { +export type MessagingConnectedAccountDeletionCleanupJobData = { workspaceId: string; connectedAccountId: string; }; @Injectable() -export class DeleteConnectedAccountAssociatedMessagingDataJob - implements - MessageQueueJob +export class MessagingConnectedAccountDeletionCleanupJob + implements MessageQueueJob { private readonly logger = new Logger( - DeleteConnectedAccountAssociatedMessagingDataJob.name, + MessagingConnectedAccountDeletionCleanupJob.name, ); - constructor(private readonly threadCleanerService: ThreadCleanerService) {} + constructor( + private readonly messageCleanerService: MessagingMessageCleanerService, + ) {} async handle( - data: DeleteConnectedAccountAssociatedMessagingDataJobData, + data: MessagingConnectedAccountDeletionCleanupJobData, ): Promise { this.logger.log( `Deleting connected account ${data.connectedAccountId} associated messaging data in workspace ${data.workspaceId}`, ); - await this.threadCleanerService.cleanWorkspaceThreads(data.workspaceId); + await this.messageCleanerService.cleanWorkspaceThreads(data.workspaceId); this.logger.log( `Deleted connected account ${data.connectedAccountId} associated messaging data in workspace ${data.workspaceId}`, diff --git a/packages/twenty-server/src/modules/messaging/listeners/messaging-connected-account.listener.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/listeners/messaging-message-cleaner-connected-account.listener.ts similarity index 65% rename from packages/twenty-server/src/modules/messaging/listeners/messaging-connected-account.listener.ts rename to packages/twenty-server/src/modules/messaging/message-cleaner/listeners/messaging-message-cleaner-connected-account.listener.ts index 6036d3cf7..24d5deb29 100644 --- a/packages/twenty-server/src/modules/messaging/listeners/messaging-connected-account.listener.ts +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/listeners/messaging-message-cleaner-connected-account.listener.ts @@ -1,8 +1,5 @@ -import { Injectable, Inject } from '@nestjs/common'; +import { Inject } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { Repository } from 'typeorm'; import { ObjectRecordDeleteEvent } from 'src/engine/integrations/event-emitter/types/object-record-delete.event'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; @@ -11,30 +8,26 @@ import { DeleteConnectedAccountAssociatedCalendarDataJobData, DeleteConnectedAccountAssociatedCalendarDataJob, } from 'src/modules/calendar/jobs/delete-connected-account-associated-calendar-data.job'; -import { - DeleteConnectedAccountAssociatedMessagingDataJobData, - DeleteConnectedAccountAssociatedMessagingDataJob, -} from 'src/modules/messaging/jobs/delete-connected-account-associated-messaging-data.job'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { + MessagingConnectedAccountDeletionCleanupJob, + MessagingConnectedAccountDeletionCleanupJobData, +} from 'src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job'; -@Injectable() -export class MessagingConnectedAccountListener { +export class MessagingMessageCleanerConnectedAccountListener { constructor( @Inject(MessageQueue.messagingQueue) private readonly messageQueueService: MessageQueueService, @Inject(MessageQueue.calendarQueue) private readonly calendarQueueService: MessageQueueService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, ) {} @OnEvent('connectedAccount.deleted') async handleDeletedEvent( payload: ObjectRecordDeleteEvent, ) { - await this.messageQueueService.add( - DeleteConnectedAccountAssociatedMessagingDataJob.name, + await this.messageQueueService.add( + MessagingConnectedAccountDeletionCleanupJob.name, { workspaceId: payload.workspaceId, connectedAccountId: payload.recordId, diff --git a/packages/twenty-server/src/modules/messaging/message-cleaner/messaging-message-cleaner.module.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/messaging-message-cleaner.module.ts new file mode 100644 index 000000000..4562bd75b --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/messaging-message-cleaner.module.ts @@ -0,0 +1,27 @@ +import { Module } from '@nestjs/common'; + +import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; +import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; +import { MessagingConnectedAccountDeletionCleanupJob } from 'src/modules/messaging/message-cleaner/jobs/messaging-connected-account-deletion-cleanup.job'; +import { MessagingMessageCleanerConnectedAccountListener } from 'src/modules/messaging/message-cleaner/listeners/messaging-message-cleaner-connected-account.listener'; +import { MessagingMessageCleanerService } from 'src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service'; + +@Module({ + imports: [ + ObjectMetadataRepositoryModule.forFeature([ + MessageWorkspaceEntity, + MessageThreadWorkspaceEntity, + ]), + ], + providers: [ + MessagingMessageCleanerService, + { + provide: MessagingConnectedAccountDeletionCleanupJob.name, + useClass: MessagingConnectedAccountDeletionCleanupJob, + }, + MessagingMessageCleanerConnectedAccountListener, + ], + exports: [MessagingMessageCleanerService], +}) +export class MessagingMessageCleanerModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.service.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts similarity index 67% rename from packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.service.ts rename to packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts index 40ddf77ba..19a9d6b2d 100644 --- a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/services/messaging-message-cleaner.service.ts @@ -1,14 +1,14 @@ import { Injectable } from '@nestjs/common'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { MessageThreadRepository } from 'src/modules/messaging/repositories/message-thread.repository'; -import { MessageRepository } from 'src/modules/messaging/repositories/message.repository'; -import { deleteUsingPagination } from 'src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; +import { MessageThreadRepository } from 'src/modules/messaging/common/repositories/message-thread.repository'; +import { MessageRepository } from 'src/modules/messaging/common/repositories/message.repository'; +import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; +import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; +import { deleteUsingPagination } from 'src/modules/messaging/message-cleaner/utils/delete-using-pagination.util'; @Injectable() -export class ThreadCleanerService { +export class MessagingMessageCleanerService { constructor( @InjectObjectMetadataRepository(MessageWorkspaceEntity) private readonly messageRepository: MessageRepository, diff --git a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util.spec.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/utils/__tests__/delete-using-pagination.util.spec.ts similarity index 88% rename from packages/twenty-server/src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util.spec.ts rename to packages/twenty-server/src/modules/messaging/message-cleaner/utils/__tests__/delete-using-pagination.util.spec.ts index cca39a8d6..272553278 100644 --- a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-cleaner/utils/__tests__/delete-using-pagination.util.spec.ts @@ -1,4 +1,4 @@ -import { deleteUsingPagination } from './delete-using-pagination.util'; +import { deleteUsingPagination } from 'src/modules/messaging/message-cleaner/utils/delete-using-pagination.util'; describe('deleteUsingPagination', () => { it('should delete items using pagination', async () => { @@ -29,7 +29,7 @@ describe('deleteUsingPagination', () => { expect(getterPaginated).toHaveBeenNthCalledWith( 2, batchSize, - batchSize, + 0, workspaceId, transactionManager, ); diff --git a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util.ts b/packages/twenty-server/src/modules/messaging/message-cleaner/utils/delete-using-pagination.util.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/services/thread-cleaner/utils/delete-using-pagination.util.ts rename to packages/twenty-server/src/modules/messaging/message-cleaner/utils/delete-using-pagination.util.ts diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/constants/messaging-import-ongoing-sync-timeout.constant.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/constants/messaging-import-ongoing-sync-timeout.constant.ts new file mode 100644 index 000000000..2f59ec93f --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/constants/messaging-import-ongoing-sync-timeout.constant.ts @@ -0,0 +1 @@ +export const MESSAGING_IMPORT_ONGOING_SYNC_TIMEOUT = 1000 * 60 * 60; // 1 hour diff --git a/packages/twenty-server/src/modules/messaging/crons/commands/gmail-message-list-fetch.cron.command.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command.ts similarity index 61% rename from packages/twenty-server/src/modules/messaging/crons/commands/gmail-message-list-fetch.cron.command.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command.ts index 4091eedee..585762d2c 100644 --- a/packages/twenty-server/src/modules/messaging/crons/commands/gmail-message-list-fetch.cron.command.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command.ts @@ -4,16 +4,16 @@ import { Command, CommandRunner } from 'nest-commander'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { GmailMessageListFetchCronJob } from 'src/modules/messaging/crons/jobs/gmail-message-list-fetch.cron.job'; +import { MessagingMessageListFetchCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job'; -const GMAIL_MESSAGE_LIST_FETCH_CRON_PATTERN = '*/5 * * * *'; +const MESSAGING_MESSAGE_LIST_FETCH_CRON_PATTERN = '*/5 * * * *'; @Command({ - name: 'cron:messaging:gmail-message-list-fetch', + name: 'cron:messaging:message-list-fetch', description: 'Starts a cron job to sync existing connected account messages and store them in the cache', }) -export class GmailMessageListFetchCronCommand extends CommandRunner { +export class MessagingMessageListFetchCronCommand extends CommandRunner { constructor( @Inject(MessageQueue.cronQueue) private readonly messageQueueService: MessageQueueService, @@ -23,10 +23,10 @@ export class GmailMessageListFetchCronCommand extends CommandRunner { async run(): Promise { await this.messageQueueService.addCron( - GmailMessageListFetchCronJob.name, + MessagingMessageListFetchCronJob.name, undefined, { - repeat: { pattern: GMAIL_MESSAGE_LIST_FETCH_CRON_PATTERN }, + repeat: { pattern: MESSAGING_MESSAGE_LIST_FETCH_CRON_PATTERN }, }, ); } diff --git a/packages/twenty-server/src/modules/messaging/crons/commands/gmail-messages-import.cron.command.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command.ts similarity index 70% rename from packages/twenty-server/src/modules/messaging/crons/commands/gmail-messages-import.cron.command.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command.ts index ec2986f6a..aae9df372 100644 --- a/packages/twenty-server/src/modules/messaging/crons/commands/gmail-messages-import.cron.command.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command.ts @@ -4,13 +4,13 @@ import { Command, CommandRunner } from 'nest-commander'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { GmailMessagesImportCronJob } from 'src/modules/messaging/crons/jobs/gmail-messages-import.cron.job'; +import { MessagingMessagesImportCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job'; @Command({ - name: 'cron:messaging:gmail-messages-import', + name: 'cron:messaging:messages-import', description: 'Starts a cron job to fetch all messages from cache', }) -export class GmailMessagesImportCronCommand extends CommandRunner { +export class MessagingMessagesImportCronCommand extends CommandRunner { constructor( @Inject(MessageQueue.cronQueue) private readonly messageQueueService: MessageQueueService, @@ -20,7 +20,7 @@ export class GmailMessagesImportCronCommand extends CommandRunner { async run(): Promise { await this.messageQueueService.addCron( - GmailMessagesImportCronJob.name, + MessagingMessagesImportCronJob.name, undefined, { repeat: { diff --git a/packages/twenty-server/src/modules/messaging/crons/jobs/gmail-message-list-fetch.cron.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts similarity index 63% rename from packages/twenty-server/src/modules/messaging/crons/jobs/gmail-message-list-fetch.cron.job.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts index c8266987d..206990a72 100644 --- a/packages/twenty-server/src/modules/messaging/crons/jobs/gmail-message-list-fetch.cron.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job.ts @@ -7,30 +7,22 @@ import { MessageQueueJob } from 'src/engine/integrations/message-queue/interface import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; -import { - GmailPartialMessageListFetchJobData, - GmailPartialMessageListFetchJob, -} from 'src/modules/messaging/jobs/gmail-partial-message-list-fetch.job'; import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { - FeatureFlagEntity, - FeatureFlagKeys, -} from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { - GmailMessageListFetchJobData, - GmailMessageListFetchJob, -} from 'src/modules/messaging/jobs/gmail-message-list-fetch.job'; + MessagingMessageListFetchJobData, + MessagingMessageListFetchJob, +} from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job'; @Injectable() -export class GmailMessageListFetchCronJob +export class MessagingMessageListFetchCronJob implements MessageQueueJob { - private readonly logger = new Logger(GmailMessageListFetchCronJob.name); + private readonly logger = new Logger(MessagingMessageListFetchCronJob.name); constructor( @InjectRepository(Workspace, 'core') @@ -42,8 +34,6 @@ export class GmailMessageListFetchCronJob @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) private readonly messageChannelRepository: MessageChannelRepository, private readonly environmentService: EnvironmentService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, ) {} async handle(): Promise { @@ -74,15 +64,6 @@ export class GmailMessageListFetchCronJob } private async enqueueSyncs(workspaceId: string): Promise { - const isGmailSyncV2EnabledFeatureFlag = - await this.featureFlagRepository.findOneBy({ - workspaceId: workspaceId, - key: FeatureFlagKeys.IsGmailSyncV2Enabled, - value: true, - }); - - const isGmailSyncV2Enabled = isGmailSyncV2EnabledFeatureFlag?.value; - try { const messageChannels = await this.messageChannelRepository.getAll(workspaceId); @@ -92,23 +73,13 @@ export class GmailMessageListFetchCronJob continue; } - if (isGmailSyncV2Enabled) { - await this.messageQueueService.add( - GmailMessageListFetchJob.name, - { - workspaceId, - connectedAccountId: messageChannel.connectedAccountId, - }, - ); - } else { - await this.messageQueueService.add( - GmailPartialMessageListFetchJob.name, - { - workspaceId, - connectedAccountId: messageChannel.connectedAccountId, - }, - ); - } + await this.messageQueueService.add( + MessagingMessageListFetchJob.name, + { + workspaceId, + connectedAccountId: messageChannel.connectedAccountId, + }, + ); } } catch (error) { this.logger.error( diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job.ts new file mode 100644 index 000000000..6780059bd --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job.ts @@ -0,0 +1,65 @@ +import { Inject, Injectable, Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { Repository, In } from 'typeorm'; + +import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; + +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; +import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; +import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; +import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; +import { + MessagingMessagesImportJobData, + MessagingMessagesImportJob, +} from 'src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job'; + +@Injectable() +export class MessagingMessagesImportCronJob + implements MessageQueueJob +{ + private readonly logger = new Logger(MessagingMessagesImportCronJob.name); + + constructor( + @InjectRepository(Workspace, 'core') + private readonly workspaceRepository: Repository, + @InjectRepository(DataSourceEntity, 'metadata') + private readonly dataSourceRepository: Repository, + private readonly environmentService: EnvironmentService, + @Inject(MessageQueue.messagingQueue) + private readonly messageQueueService: MessageQueueService, + ) {} + + async handle(): Promise { + const workspaceIds = ( + await this.workspaceRepository.find({ + where: this.environmentService.get('IS_BILLING_ENABLED') + ? { + subscriptionStatus: In(['active', 'trialing', 'past_due']), + } + : {}, + select: ['id'], + }) + ).map((workspace) => workspace.id); + + const dataSources = await this.dataSourceRepository.find({ + where: { + workspaceId: In(workspaceIds), + }, + }); + + const workspaceIdsWithDataSources = new Set( + dataSources.map((dataSource) => dataSource.workspaceId), + ); + + for (const workspaceId of workspaceIdsWithDataSources) { + await this.messageQueueService.add( + MessagingMessagesImportJob.name, + { + workspaceId, + }, + ); + } + } +} diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-excluded-categories.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-excluded-categories.ts new file mode 100644 index 000000000..1b6cd0152 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-excluded-categories.ts @@ -0,0 +1,5 @@ +export const MESSAGING_GMAIL_EXCLUDED_CATEGORIES = [ + 'promotions', + 'social', + 'forums', +]; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-history-max-result.constant.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-history-max-result.constant.ts new file mode 100644 index 000000000..86dd74054 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-history-max-result.constant.ts @@ -0,0 +1 @@ +export const MESSAGING_GMAIL_USERS_HISTORY_MAX_RESULT = 500; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-get-batch-size.constant.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-get-batch-size.constant.ts new file mode 100644 index 000000000..81255f383 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-get-batch-size.constant.ts @@ -0,0 +1 @@ +export const MESSAGING_GMAIL_USERS_MESSAGES_GET_BATCH_SIZE = 20; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-list-max-result.constant.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-list-max-result.constant.ts new file mode 100644 index 000000000..ece0d18e4 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-list-max-result.constant.ts @@ -0,0 +1 @@ +export const MESSAGING_GMAIL_USERS_MESSAGES_LIST_MAX_RESULT = 500; diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts new file mode 100644 index 000000000..380e4534e --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module.ts @@ -0,0 +1,53 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module'; +import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; +import { GoogleAPIRefreshAccessTokenModule } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module'; +import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; +import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; +import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessagingGmailClientProvider } from 'src/modules/messaging/message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider'; +import { MessagingGmailFetchMessagesByBatchesService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service'; +import { MessagingGmailFetchMessageIdsToExcludeService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-ids-to-exclude.service'; +import { MessagingGmailFullMessageListFetchService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service'; +import { MessagingGmailHistoryService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-history.service'; +import { MessagingGmailMessagesImportService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service'; +import { MessagingGmailPartialMessageListFetchService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service'; + +@Module({ + imports: [ + GoogleAPIRefreshAccessTokenModule, + EnvironmentModule, + ObjectMetadataRepositoryModule.forFeature([ + ConnectedAccountWorkspaceEntity, + MessageChannelWorkspaceEntity, + MessageChannelMessageAssociationWorkspaceEntity, + BlocklistWorkspaceEntity, + ]), + MessagingCommonModule, + TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), + ], + providers: [ + MessagingGmailClientProvider, + MessagingGmailHistoryService, + MessagingGmailFetchMessagesByBatchesService, + MessagingGmailPartialMessageListFetchService, + MessagingGmailFullMessageListFetchService, + MessagingGmailMessagesImportService, + MessagingGmailFetchMessageIdsToExcludeService, + ], + exports: [ + MessagingGmailClientProvider, + MessagingGmailHistoryService, + MessagingGmailFetchMessagesByBatchesService, + MessagingGmailPartialMessageListFetchService, + MessagingGmailFullMessageListFetchService, + MessagingGmailMessagesImportService, + MessagingGmailFetchMessageIdsToExcludeService, + ], +}) +export class MessagingGmailDriverModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/providers/gmail/gmail-client.provider.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider.ts similarity index 96% rename from packages/twenty-server/src/modules/messaging/services/providers/gmail/gmail-client.provider.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider.ts index 3b5e591ac..130e33562 100644 --- a/packages/twenty-server/src/modules/messaging/services/providers/gmail/gmail-client.provider.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider.ts @@ -6,7 +6,7 @@ import { gmail_v1, google } from 'googleapis'; import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; @Injectable() -export class GmailClientProvider { +export class MessagingGmailClientProvider { constructor(private readonly environmentService: EnvironmentService) {} public async getGmailClient(refreshToken: string): Promise { diff --git a/packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service.ts similarity index 90% rename from packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service.ts index 6bfda7d21..cc63ce248 100644 --- a/packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service.ts @@ -5,17 +5,21 @@ import planer from 'planer'; import addressparser from 'addressparser'; import { gmail_v1 } from 'googleapis'; -import { GmailMessage } from 'src/modules/messaging/types/gmail-message'; -import { MessageQuery } from 'src/modules/messaging/types/message-or-thread-query'; -import { FetchByBatchesService } from 'src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service'; -import { formatAddressObjectAsParticipants } from 'src/modules/messaging/services/utils/format-address-object-as-participants.util'; import { assert, assertNotNull } from 'src/utils/assert'; +import { GmailMessage } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; +import { MessageQuery } from 'src/modules/messaging/message-import-manager/types/message-or-thread-query'; +import { formatAddressObjectAsParticipants } from 'src/modules/messaging/message-import-manager/utils/format-address-object-as-participants.util'; +import { MessagingFetchByBatchesService } from 'src/modules/messaging/common/services/messaging-fetch-by-batch.service'; @Injectable() -export class FetchMessagesByBatchesService { - private readonly logger = new Logger(FetchMessagesByBatchesService.name); +export class MessagingGmailFetchMessagesByBatchesService { + private readonly logger = new Logger( + MessagingGmailFetchMessagesByBatchesService.name, + ); - constructor(private readonly fetchByBatchesService: FetchByBatchesService) {} + constructor( + private readonly fetchByBatchesService: MessagingFetchByBatchesService, + ) {} async fetchAllMessages( queries: MessageQuery[], diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-fetch-messages-ids-to-exclude.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-ids-to-exclude.service.ts similarity index 62% rename from packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-fetch-messages-ids-to-exclude.service.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-ids-to-exclude.service.ts index b0df2f31c..266553695 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-fetch-messages-ids-to-exclude.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-ids-to-exclude.service.ts @@ -2,15 +2,15 @@ import { Injectable } from '@nestjs/common'; import { gmail_v1 } from 'googleapis'; -import { GMAIL_EXCLUDED_CATEGORIES } from 'src/modules/messaging/constants/gmail-excluded-categories'; -import { GmailGetHistoryService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-get-history.service'; -import { computeGmailCategoryLabelId } from 'src/modules/messaging/utils/compute-gmail-category-label-id'; +import { MESSAGING_GMAIL_EXCLUDED_CATEGORIES } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-excluded-categories'; +import { MessagingGmailHistoryService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-history.service'; +import { computeGmailCategoryLabelId } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-label-id'; import { assertNotNull } from 'src/utils/assert'; @Injectable() -export class GmailFetchMessageIdsToExcludeService { +export class MessagingGmailFetchMessageIdsToExcludeService { constructor( - private readonly gmailGetHistoryService: GmailGetHistoryService, + private readonly gmailGetHistoryService: MessagingGmailHistoryService, ) {} public async fetchEmailIdsToExcludeOrThrow( @@ -19,7 +19,7 @@ export class GmailFetchMessageIdsToExcludeService { ): Promise { const emailIds: string[] = []; - for (const category of GMAIL_EXCLUDED_CATEGORIES) { + for (const category of MESSAGING_GMAIL_EXCLUDED_CATEGORIES) { const { history, error } = await this.gmailGetHistoryService.getHistory( gmailClient, lastSyncHistoryId, diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service.ts similarity index 77% rename from packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service.ts index d776ffd83..1fb1c4b95 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service.ts @@ -9,27 +9,29 @@ import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decora import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { GMAIL_USERS_MESSAGES_LIST_MAX_RESULT } from 'src/modules/messaging/constants/gmail-users-messages-list-max-result.constant'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; +import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; import { GmailError, - GmailErrorHandlingService, -} from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service'; -import { MessageChannelSyncStatusService } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service'; -import { computeGmailCategoryExcludeSearchFilter } from 'src/modules/messaging/utils/compute-gmail-category-excude-search-filter'; -import { GMAIL_EXCLUDED_CATEGORIES } from 'src/modules/messaging/constants/gmail-excluded-categories'; + MessagingErrorHandlingService, +} from 'src/modules/messaging/common/services/messaging-error-handling.service'; +import { computeGmailCategoryExcludeSearchFilter } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-excude-search-filter'; +import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; +import { MessagingGmailClientProvider } from 'src/modules/messaging/message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider'; +import { MESSAGING_GMAIL_USERS_MESSAGES_LIST_MAX_RESULT } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-list-max-result.constant'; +import { MESSAGING_GMAIL_EXCLUDED_CATEGORIES } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-excluded-categories'; @Injectable() -export class GmailFullMessageListFetchV2Service { - private readonly logger = new Logger(GmailFullMessageListFetchV2Service.name); +export class MessagingGmailFullMessageListFetchService { + private readonly logger = new Logger( + MessagingGmailFullMessageListFetchService.name, + ); constructor( - private readonly gmailClientProvider: GmailClientProvider, + private readonly gmailClientProvider: MessagingGmailClientProvider, @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) private readonly messageChannelRepository: MessageChannelRepository, @InjectCacheStorage(CacheStorageNamespace.Messaging) @@ -38,8 +40,8 @@ export class GmailFullMessageListFetchV2Service { MessageChannelMessageAssociationWorkspaceEntity, ) private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository, - private readonly messageChannelSyncStatusService: MessageChannelSyncStatusService, - private readonly gmailErrorHandlingService: GmailErrorHandlingService, + private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService, + private readonly gmailErrorHandlingService: MessagingErrorHandlingService, ) {} public async processMessageListFetch( @@ -47,7 +49,7 @@ export class GmailFullMessageListFetchV2Service { connectedAccount: ObjectRecord, workspaceId: string, ) { - await this.messageChannelSyncStatusService.markAsMessagesListFetchOngoing( + await this.messagingChannelSyncStatusService.markAsMessagesListFetchOngoing( messageChannel.id, workspaceId, ); @@ -75,7 +77,7 @@ export class GmailFullMessageListFetchV2Service { return; } - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messagingChannelSyncStatusService.scheduleMessagesImport( messageChannel.id, workspaceId, ); @@ -97,9 +99,11 @@ export class GmailFullMessageListFetchV2Service { try { response = await gmailClient.users.messages.list({ userId: 'me', - maxResults: GMAIL_USERS_MESSAGES_LIST_MAX_RESULT, + maxResults: MESSAGING_GMAIL_USERS_MESSAGES_LIST_MAX_RESULT, pageToken, - q: computeGmailCategoryExcludeSearchFilter(GMAIL_EXCLUDED_CATEGORIES), + q: computeGmailCategoryExcludeSearchFilter( + MESSAGING_GMAIL_EXCLUDED_CATEGORIES, + ), }); } catch (error) { return { diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-get-history.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-history.service.ts similarity index 87% rename from packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-get-history.service.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-history.service.ts index ebb68e2d0..ab1812294 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-get-history.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-history.service.ts @@ -3,11 +3,11 @@ import { Injectable } from '@nestjs/common'; import { gmail_v1 } from 'googleapis'; import { GaxiosResponse } from 'gaxios'; -import { GMAIL_USERS_HISTORY_MAX_RESULT } from 'src/modules/messaging/constants/gmail-users-history-max-result.constant'; -import { GmailError } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service'; +import { GmailError } from 'src/modules/messaging/common/services/messaging-error-handling.service'; +import { MESSAGING_GMAIL_USERS_HISTORY_MAX_RESULT } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-history-max-result.constant'; @Injectable() -export class GmailGetHistoryService { +export class MessagingGmailHistoryService { constructor() {} public async getHistory( @@ -30,7 +30,7 @@ export class GmailGetHistoryService { try { response = await gmailClient.users.history.list({ userId: 'me', - maxResults: GMAIL_USERS_HISTORY_MAX_RESULT, + maxResults: MESSAGING_GMAIL_USERS_HISTORY_MAX_RESULT, pageToken, startHistoryId: lastSyncHistoryId, historyTypes: historyTypes || ['messageAdded', 'messageDeleted'], diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import-v2.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service.ts similarity index 71% rename from packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import-v2.service.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service.ts index 64c5bac16..259e6de68 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import-v2.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service.ts @@ -1,39 +1,40 @@ import { Injectable, Logger } from '@nestjs/common'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { FetchMessagesByBatchesService } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service'; -import { - MessageChannelWorkspaceEntity, - MessageChannelSyncSubStatus, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { createQueriesFromMessageIds } from 'src/modules/messaging/utils/create-queries-from-message-ids.util'; import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { GMAIL_USERS_MESSAGES_GET_BATCH_SIZE } from 'src/modules/messaging/constants/gmail-users-messages-get-batch-size.constant'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; -import { SaveMessagesAndEnqueueContactCreationService } from 'src/modules/messaging/services/gmail-messages-import/save-messages-and-enqueue-contact-creation.service'; -import { GmailErrorHandlingService } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service'; -import { MessageChannelSyncStatusService } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service'; import { GoogleAPIRefreshAccessTokenService } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.service'; -import { GmailMessagesImportService } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service'; -import { MessagingTelemetryService } from 'src/modules/messaging/services/telemetry/messaging-telemetry.service'; import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { BlocklistRepository } from 'src/modules/connected-account/repositories/blocklist.repository'; -import { filterEmails } from 'src/modules/messaging/services/utils/filter-emails.util'; +import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service'; +import { + MessageChannelWorkspaceEntity, + MessageChannelSyncSubStatus, +} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { createQueriesFromMessageIds } from 'src/modules/messaging/message-import-manager/utils/create-queries-from-message-ids.util'; +import { filterEmails } from 'src/modules/messaging/message-import-manager/utils/filter-emails.util'; +import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; +import { MESSAGING_GMAIL_USERS_MESSAGES_GET_BATCH_SIZE } from 'src/modules/messaging/message-import-manager/drivers/gmail/constants/messaging-gmail-users-messages-get-batch-size.constant'; +import { MessagingGmailFetchMessagesByBatchesService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-by-batches.service'; +import { MessagingErrorHandlingService } from 'src/modules/messaging/common/services/messaging-error-handling.service'; +import { MessagingSaveMessagesAndEnqueueContactCreationService } from 'src/modules/messaging/common/services/messaging-save-messages-and-enqueue-contact-creation.service'; @Injectable() -export class GmailMessagesImportV2Service { - private readonly logger = new Logger(GmailMessagesImportService.name); +export class MessagingGmailMessagesImportService { + private readonly logger = new Logger( + MessagingGmailMessagesImportService.name, + ); constructor( - private readonly fetchMessagesByBatchesService: FetchMessagesByBatchesService, + private readonly fetchMessagesByBatchesService: MessagingGmailFetchMessagesByBatchesService, @InjectCacheStorage(CacheStorageNamespace.Messaging) private readonly cacheStorage: CacheStorageService, - private readonly messageChannelSyncStatusService: MessageChannelSyncStatusService, - private readonly saveMessagesAndEnqueueContactCreationService: SaveMessagesAndEnqueueContactCreationService, - private readonly gmailErrorHandlingService: GmailErrorHandlingService, + private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService, + private readonly saveMessagesAndEnqueueContactCreationService: MessagingSaveMessagesAndEnqueueContactCreationService, + private readonly gmailErrorHandlingService: MessagingErrorHandlingService, private readonly googleAPIsRefreshAccessTokenService: GoogleAPIRefreshAccessTokenService, private readonly messagingTelemetryService: MessagingTelemetryService, @InjectObjectMetadataRepository(BlocklistWorkspaceEntity) @@ -63,7 +64,7 @@ export class GmailMessagesImportV2Service { `Messaging import for workspace ${workspaceId} and account ${connectedAccount.id} starting...`, ); - await this.messageChannelSyncStatusService.markAsMessagesImportOngoing( + await this.messagingChannelSyncStatusService.markAsMessagesImportOngoing( messageChannel.id, workspaceId, ); @@ -76,11 +77,11 @@ export class GmailMessagesImportV2Service { const messageIdsToFetch = (await this.cacheStorage.setPop( `messages-to-import:${workspaceId}:gmail:${messageChannel.id}`, - GMAIL_USERS_MESSAGES_GET_BATCH_SIZE, + MESSAGING_GMAIL_USERS_MESSAGES_GET_BATCH_SIZE, )) ?? []; if (!messageIdsToFetch?.length) { - await this.messageChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( + await this.messagingChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( messageChannel.id, workspaceId, ); @@ -119,13 +120,15 @@ export class GmailMessagesImportV2Service { workspaceId, ); - if (messageIdsToFetch.length < GMAIL_USERS_MESSAGES_GET_BATCH_SIZE) { - await this.messageChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( + if ( + messageIdsToFetch.length < MESSAGING_GMAIL_USERS_MESSAGES_GET_BATCH_SIZE + ) { + await this.messagingChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( messageChannel.id, workspaceId, ); } else { - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messagingChannelSyncStatusService.scheduleMessagesImport( messageChannel.id, workspaceId, ); diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch-v2.service.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service.ts similarity index 70% rename from packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch-v2.service.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service.ts index 91270d78f..f45c5be52 100644 --- a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch-v2.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service.ts @@ -2,30 +2,30 @@ import { Injectable, Logger } from '@nestjs/common'; import { gmail_v1 } from 'googleapis'; -import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { GmailGetHistoryService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-get-history.service'; import { ObjectRecord } from 'src/engine/workspace-manager/workspace-sync-metadata/types/object-record'; -import { GmailErrorHandlingService } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service'; -import { MessageChannelSyncStatusService } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service'; -import { GmailFetchMessageIdsToExcludeService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-fetch-messages-ids-to-exclude.service'; +import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/common/repositories/message-channel-message-association.repository'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessagingGmailClientProvider } from 'src/modules/messaging/message-import-manager/drivers/gmail/providers/messaging-gmail-client.provider'; +import { MessagingChannelSyncStatusService } from 'src/modules/messaging/common/services/messaging-channel-sync-status.service'; +import { MessagingGmailFetchMessageIdsToExcludeService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-fetch-messages-ids-to-exclude.service'; +import { MessagingErrorHandlingService } from 'src/modules/messaging/common/services/messaging-error-handling.service'; +import { MessagingGmailHistoryService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-history.service'; @Injectable() -export class GmailPartialMessageListFetchV2Service { +export class MessagingGmailPartialMessageListFetchService { private readonly logger = new Logger( - GmailPartialMessageListFetchV2Service.name, + MessagingGmailPartialMessageListFetchService.name, ); constructor( - private readonly gmailClientProvider: GmailClientProvider, + private readonly gmailClientProvider: MessagingGmailClientProvider, @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) private readonly messageChannelRepository: MessageChannelRepository, @InjectCacheStorage(CacheStorageNamespace.Messaging) @@ -34,10 +34,10 @@ export class GmailPartialMessageListFetchV2Service { MessageChannelMessageAssociationWorkspaceEntity, ) private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository, - private readonly gmailErrorHandlingService: GmailErrorHandlingService, - private readonly gmailGetHistoryService: GmailGetHistoryService, - private readonly messageChannelSyncStatusService: MessageChannelSyncStatusService, - private readonly gmailFetchMessageIdsToExcludeService: GmailFetchMessageIdsToExcludeService, + private readonly gmailErrorHandlingService: MessagingErrorHandlingService, + private readonly gmailGetHistoryService: MessagingGmailHistoryService, + private readonly messagingChannelSyncStatusService: MessagingChannelSyncStatusService, + private readonly gmailFetchMessageIdsToExcludeService: MessagingGmailFetchMessageIdsToExcludeService, ) {} public async processMessageListFetch( @@ -45,7 +45,7 @@ export class GmailPartialMessageListFetchV2Service { connectedAccount: ObjectRecord, workspaceId: string, ): Promise { - await this.messageChannelSyncStatusService.markAsMessagesListFetchOngoing( + await this.messagingChannelSyncStatusService.markAsMessagesListFetchOngoing( messageChannel.id, workspaceId, ); @@ -85,7 +85,7 @@ export class GmailPartialMessageListFetchV2Service { `Partial message list import done with history ${historyId} and nothing to update for workspace ${workspaceId} and account ${connectedAccount.id}`, ); - await this.messageChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( + await this.messagingChannelSyncStatusService.markAsCompletedAndSchedulePartialMessageListFetch( messageChannel.id, workspaceId, ); @@ -144,7 +144,7 @@ export class GmailPartialMessageListFetchV2Service { workspaceId, ); - await this.messageChannelSyncStatusService.scheduleMessagesImport( + await this.messagingChannelSyncStatusService.scheduleMessagesImport( messageChannel.id, workspaceId, ); diff --git a/packages/twenty-server/src/modules/messaging/types/gmail-message-parsed-response.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message-parsed-response.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/types/gmail-message-parsed-response.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message-parsed-response.ts diff --git a/packages/twenty-server/src/modules/messaging/types/gmail-message.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/types/gmail-message.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message.ts diff --git a/packages/twenty-server/src/modules/messaging/types/gmail-thread.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-thread.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/types/gmail-thread.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-thread.ts diff --git a/packages/twenty-server/src/modules/messaging/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts similarity index 89% rename from packages/twenty-server/src/modules/messaging/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts index d77f177f0..776ab3356 100644 --- a/packages/twenty-server/src/modules/messaging/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/__tests__/compute-gmail-category-excude-search-filter.spec.ts @@ -1,4 +1,4 @@ -import { computeGmailCategoryExcludeSearchFilter } from 'src/modules/messaging/utils/compute-gmail-category-excude-search-filter'; +import { computeGmailCategoryExcludeSearchFilter } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-excude-search-filter'; describe('computeGmailCategoryExcludeSearchFilter', () => { it('should return correct exclude search filter with empty category array', () => { diff --git a/packages/twenty-server/src/modules/messaging/utils/__tests__/compute-gmail-category-label-id.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/__tests__/compute-gmail-category-label-id.spec.ts similarity index 78% rename from packages/twenty-server/src/modules/messaging/utils/__tests__/compute-gmail-category-label-id.spec.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/__tests__/compute-gmail-category-label-id.spec.ts index 2373669ef..5cacd83c9 100644 --- a/packages/twenty-server/src/modules/messaging/utils/__tests__/compute-gmail-category-label-id.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/__tests__/compute-gmail-category-label-id.spec.ts @@ -1,4 +1,4 @@ -import { computeGmailCategoryLabelId } from 'src/modules/messaging/utils/compute-gmail-category-label-id'; +import { computeGmailCategoryLabelId } from 'src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-label-id'; describe('computeGmailCategoryLabelId', () => { it('should return correct category label id', () => { diff --git a/packages/twenty-server/src/modules/messaging/utils/compute-gmail-category-excude-search-filter.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-excude-search-filter.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/utils/compute-gmail-category-excude-search-filter.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-excude-search-filter.ts diff --git a/packages/twenty-server/src/modules/messaging/utils/compute-gmail-category-label-id.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-label-id.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/utils/compute-gmail-category-label-id.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/drivers/gmail/utils/compute-gmail-category-label-id.ts diff --git a/packages/twenty-server/src/modules/messaging/jobs/gmail-message-list-fetch.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts similarity index 77% rename from packages/twenty-server/src/modules/messaging/jobs/gmail-message-list-fetch.job.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts index 36c86faed..f180a91a9 100644 --- a/packages/twenty-server/src/modules/messaging/jobs/gmail-message-list-fetch.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job.ts @@ -2,32 +2,32 @@ import { Injectable, Logger } from '@nestjs/common'; import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; -import { GmailPartialMessageListFetchV2Service } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch-v2.service'; -import { - MessageChannelSyncSubStatus, - MessageChannelWorkspaceEntity, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { GmailFullMessageListFetchV2Service } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessagingTelemetryService } from 'src/modules/messaging/services/telemetry/messaging-telemetry.service'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service'; +import { + MessageChannelSyncSubStatus, + MessageChannelWorkspaceEntity, +} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessagingGmailFullMessageListFetchService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-full-message-list-fetch.service'; +import { MessagingGmailPartialMessageListFetchService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-partial-message-list-fetch.service'; -export type GmailMessageListFetchJobData = { +export type MessagingMessageListFetchJobData = { workspaceId: string; connectedAccountId: string; }; @Injectable() -export class GmailMessageListFetchJob - implements MessageQueueJob +export class MessagingMessageListFetchJob + implements MessageQueueJob { - private readonly logger = new Logger(GmailMessageListFetchJob.name); + private readonly logger = new Logger(MessagingMessageListFetchJob.name); constructor( - private readonly gmailFullMessageListFetchV2Service: GmailFullMessageListFetchV2Service, - private readonly gmailPartialMessageListFetchV2Service: GmailPartialMessageListFetchV2Service, + private readonly gmailFullMessageListFetchService: MessagingGmailFullMessageListFetchService, + private readonly gmailPartialMessageListFetchV2Service: MessagingGmailPartialMessageListFetchService, @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) private readonly connectedAccountRepository: ConnectedAccountRepository, @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) @@ -35,7 +35,7 @@ export class GmailMessageListFetchJob private readonly messagingTelemetryService: MessagingTelemetryService, ) {} - async handle(data: GmailMessageListFetchJobData): Promise { + async handle(data: MessagingMessageListFetchJobData): Promise { const { workspaceId, connectedAccountId } = data; await this.messagingTelemetryService.track({ @@ -113,7 +113,7 @@ export class GmailMessageListFetchJob connectedAccountId, }); - await this.gmailFullMessageListFetchV2Service.processMessageListFetch( + await this.gmailFullMessageListFetchService.processMessageListFetch( messageChannel, connectedAccount, workspaceId, diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts new file mode 100644 index 000000000..4529e8105 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job.ts @@ -0,0 +1,61 @@ +import { Injectable } from '@nestjs/common'; + +import { MessageQueueJob } from 'src/engine/integrations/message-queue/interfaces/message-queue-job.interface'; + +import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; +import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; +import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessagingTelemetryService } from 'src/modules/messaging/common/services/messaging-telemetry.service'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessagingGmailMessagesImportService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/messaging-gmail-messages-import.service'; + +export type MessagingMessagesImportJobData = { + workspaceId: string; +}; + +@Injectable() +export class MessagingMessagesImportJob + implements MessageQueueJob +{ + constructor( + @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) + private readonly connectedAccountRepository: ConnectedAccountRepository, + private readonly gmailFetchMessageContentFromCacheService: MessagingGmailMessagesImportService, + @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) + private readonly messageChannelRepository: MessageChannelRepository, + private readonly messagingTelemetryService: MessagingTelemetryService, + ) {} + + async handle(data: MessagingMessagesImportJobData): Promise { + const { workspaceId } = data; + + const messageChannels = + await this.messageChannelRepository.getAll(workspaceId); + + for (const messageChannel of messageChannels) { + if (!messageChannel?.isSyncEnabled) { + continue; + } + + await this.messagingTelemetryService.track({ + eventName: 'messages_import.triggered', + workspaceId, + connectedAccountId: messageChannel.connectedAccountId, + messageChannelId: messageChannel.id, + }); + + const connectedAccount = + await this.connectedAccountRepository.getConnectedAccountOrThrow( + workspaceId, + messageChannel.connectedAccountId, + ); + + await this.gmailFetchMessageContentFromCacheService.processMessageBatchImport( + messageChannel, + connectedAccount, + workspaceId, + ); + } + } +} diff --git a/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts new file mode 100644 index 000000000..b0b6362c0 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/messaging-import-manager.module.ts @@ -0,0 +1,44 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; +import { MessagingCommonModule } from 'src/modules/messaging/common/messaging-common.module'; +import { MessagingMessageListFetchCronCommand } from 'src/modules/messaging/message-import-manager/crons/commands/messaging-message-list-fetch.cron.command'; +import { MessagingMessagesImportCronCommand } from 'src/modules/messaging/message-import-manager/crons/commands/messaging-messages-import.cron.command'; +import { MessagingMessageListFetchCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-message-list-fetch.cron.job'; +import { MessagingMessagesImportCronJob } from 'src/modules/messaging/message-import-manager/crons/jobs/messaging-messages-import.cron.job'; +import { MessagingGmailDriverModule } from 'src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module'; +import { MessagingMessageListFetchJob } from 'src/modules/messaging/message-import-manager/jobs/messaging-message-list-fetch.job'; +import { MessagingMessagesImportJob } from 'src/modules/messaging/message-import-manager/jobs/messaging-messages-import.job'; + +@Module({ + imports: [ + MessagingGmailDriverModule, + MessagingCommonModule, + TypeOrmModule.forFeature([Workspace], 'core'), + TypeOrmModule.forFeature([DataSourceEntity], 'metadata'), + ], + providers: [ + MessagingMessageListFetchCronCommand, + MessagingMessagesImportCronCommand, + { + provide: MessagingMessageListFetchJob.name, + useClass: MessagingMessageListFetchJob, + }, + { + provide: MessagingMessagesImportJob.name, + useClass: MessagingMessagesImportJob, + }, + { + provide: MessagingMessageListFetchCronJob.name, + useClass: MessagingMessageListFetchCronJob, + }, + { + provide: MessagingMessagesImportCronJob.name, + useClass: MessagingMessagesImportCronJob, + }, + ], + exports: [], +}) +export class MessagingImportManagerModule {} diff --git a/packages/twenty-server/src/modules/messaging/types/batch-queries.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/types/batch-queries.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/types/batch-queries.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/types/batch-queries.ts diff --git a/packages/twenty-server/src/modules/messaging/types/message-or-thread-query.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/types/message-or-thread-query.ts similarity index 100% rename from packages/twenty-server/src/modules/messaging/types/message-or-thread-query.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/types/message-or-thread-query.ts diff --git a/packages/twenty-server/src/modules/messaging/services/utils/__tests__/format-address-object-as-participants.util.spec.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/__tests__/format-address-object-as-participants.util.spec.ts similarity index 91% rename from packages/twenty-server/src/modules/messaging/services/utils/__tests__/format-address-object-as-participants.util.spec.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/utils/__tests__/format-address-object-as-participants.util.spec.ts index 16a87ea39..84193a5ec 100644 --- a/packages/twenty-server/src/modules/messaging/services/utils/__tests__/format-address-object-as-participants.util.spec.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/__tests__/format-address-object-as-participants.util.spec.ts @@ -1,4 +1,4 @@ -import { formatAddressObjectAsParticipants } from 'src/modules/messaging/services/utils/format-address-object-as-participants.util'; +import { formatAddressObjectAsParticipants } from 'src/modules/messaging/message-import-manager/utils/format-address-object-as-participants.util'; describe('formatAddressObjectAsParticipants', () => { it('should format address object as participants', () => { diff --git a/packages/twenty-server/src/modules/messaging/utils/create-queries-from-message-ids.util.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/create-queries-from-message-ids.util.ts similarity index 68% rename from packages/twenty-server/src/modules/messaging/utils/create-queries-from-message-ids.util.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/utils/create-queries-from-message-ids.util.ts index fbf654934..3da664c12 100644 --- a/packages/twenty-server/src/modules/messaging/utils/create-queries-from-message-ids.util.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/create-queries-from-message-ids.util.ts @@ -1,4 +1,4 @@ -import { MessageQuery } from 'src/modules/messaging/types/message-or-thread-query'; +import { MessageQuery } from 'src/modules/messaging/message-import-manager/types/message-or-thread-query'; export const createQueriesFromMessageIds = ( messageExternalIds: string[], diff --git a/packages/twenty-server/src/modules/messaging/services/utils/filter-emails.util.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/filter-emails.util.ts similarity index 93% rename from packages/twenty-server/src/modules/messaging/services/utils/filter-emails.util.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/utils/filter-emails.util.ts index 2a95c0f5f..01140a00f 100644 --- a/packages/twenty-server/src/modules/messaging/services/utils/filter-emails.util.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/filter-emails.util.ts @@ -1,5 +1,5 @@ -import { GmailMessage } from 'src/modules/messaging/types/gmail-message'; import { isEmailBlocklisted } from 'src/modules/calendar-messaging-participant/utils/is-email-blocklisted.util'; +import { GmailMessage } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; // Todo: refactor this into several utils export const filterEmails = (messages: GmailMessage[], blocklist: string[]) => { diff --git a/packages/twenty-server/src/modules/messaging/services/utils/format-address-object-as-participants.util.ts b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/format-address-object-as-participants.util.ts similarity index 90% rename from packages/twenty-server/src/modules/messaging/services/utils/format-address-object-as-participants.util.ts rename to packages/twenty-server/src/modules/messaging/message-import-manager/utils/format-address-object-as-participants.util.ts index 113a9c1d2..a6b9e9d26 100644 --- a/packages/twenty-server/src/modules/messaging/services/utils/format-address-object-as-participants.util.ts +++ b/packages/twenty-server/src/modules/messaging/message-import-manager/utils/format-address-object-as-participants.util.ts @@ -1,6 +1,6 @@ import addressparser from 'addressparser'; -import { Participant } from 'src/modules/messaging/types/gmail-message'; +import { Participant } from 'src/modules/messaging/message-import-manager/drivers/gmail/types/gmail-message'; const formatAddressObjectAsArray = ( addressObject: addressparser.EmailAddress | addressparser.EmailAddress[], diff --git a/packages/twenty-server/src/modules/messaging/jobs/messaging-create-company-and-contact-after-sync.job.ts b/packages/twenty-server/src/modules/messaging/message-participants-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts similarity index 93% rename from packages/twenty-server/src/modules/messaging/jobs/messaging-create-company-and-contact-after-sync.job.ts rename to packages/twenty-server/src/modules/messaging/message-participants-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts index a51ad8c0f..1f2b3a7e6 100644 --- a/packages/twenty-server/src/modules/messaging/jobs/messaging-create-company-and-contact-after-sync.job.ts +++ b/packages/twenty-server/src/modules/messaging/message-participants-manager/jobs/messaging-create-company-and-contact-after-sync.job.ts @@ -11,10 +11,10 @@ import { } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; import { CreateCompanyAndContactService } from 'src/modules/connected-account/auto-companies-and-contacts-creation/services/create-company-and-contact.service'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { MessageParticipantRepository } from 'src/modules/messaging/repositories/message-participant.repository'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; +import { MessageChannelRepository } from 'src/modules/messaging/common/repositories/message-channel.repository'; +import { MessageParticipantRepository } from 'src/modules/messaging/common/repositories/message-participant.repository'; +import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; +import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; export type MessagingCreateCompanyAndContactAfterSyncJobData = { workspaceId: string; diff --git a/packages/twenty-server/src/modules/messaging/message-participants-manager/messaging-participants-manager.module.ts b/packages/twenty-server/src/modules/messaging/message-participants-manager/messaging-participants-manager.module.ts new file mode 100644 index 000000000..f7744916f --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-participants-manager/messaging-participants-manager.module.ts @@ -0,0 +1,24 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { AnalyticsModule } from 'src/engine/core-modules/analytics/analytics.module'; +import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { AutoCompaniesAndContactsCreationModule } from 'src/modules/connected-account/auto-companies-and-contacts-creation/auto-companies-and-contacts-creation.module'; +import { MessagingGmailDriverModule } from 'src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module'; +import { MessagingCreateCompanyAndContactAfterSyncJob } from 'src/modules/messaging/message-participants-manager/jobs/messaging-create-company-and-contact-after-sync.job'; + +@Module({ + imports: [ + TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), + AnalyticsModule, + MessagingGmailDriverModule, + AutoCompaniesAndContactsCreationModule, + ], + providers: [ + { + provide: MessagingCreateCompanyAndContactAfterSyncJob.name, + useClass: MessagingCreateCompanyAndContactAfterSyncJob, + }, + ], +}) +export class MessaginParticipantsManagerModule {} diff --git a/packages/twenty-server/src/modules/messaging/messaging.module.ts b/packages/twenty-server/src/modules/messaging/messaging.module.ts index 907c5bcb0..0797e3853 100644 --- a/packages/twenty-server/src/modules/messaging/messaging.module.ts +++ b/packages/twenty-server/src/modules/messaging/messaging.module.ts @@ -1,22 +1,18 @@ import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { MessagingMessageChannelListener } from 'src/modules/messaging/listeners/messaging-message-channel.listener'; -import { MessagingConnectedAccountListener } from 'src/modules/messaging/listeners/messaging-connected-account.listener'; -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { ParticipantPersonListener } from 'src/modules/calendar-messaging-participant/listeners/participant-person.listener'; -import { ParticipantWorkspaceMemberListener } from 'src/modules/calendar-messaging-participant/listeners/participant-workspace-member.listener'; -import { MessagingBlocklistListener } from 'src/modules/messaging/listeners/messaging-blocklist.listener'; +import { MessagingBlocklistManagerModule } from 'src/modules/messaging/blocklist-manager/messaging-blocklist-manager.module'; +import { MessagingMessageCleanerModule } from 'src/modules/messaging/message-cleaner/messaging-message-cleaner.module'; +import { MessagingImportManagerModule } from 'src/modules/messaging/message-import-manager/messaging-import-manager.module'; +import { MessaginParticipantsManagerModule } from 'src/modules/messaging/message-participants-manager/messaging-participants-manager.module'; @Module({ - imports: [TypeOrmModule.forFeature([FeatureFlagEntity], 'core')], - providers: [ - ParticipantPersonListener, - ParticipantWorkspaceMemberListener, - MessagingMessageChannelListener, - MessagingConnectedAccountListener, - MessagingBlocklistListener, + imports: [ + MessagingImportManagerModule, + MessagingMessageCleanerModule, + MessaginParticipantsManagerModule, + MessagingBlocklistManagerModule, ], + providers: [], exports: [], }) export class MessagingModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.module.ts b/packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.module.ts deleted file mode 100644 index 0535c95ca..000000000 --- a/packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.module.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { HttpModule } from '@nestjs/axios'; -import { Module } from '@nestjs/common'; - -import { FetchByBatchesService } from 'src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service'; - -@Module({ - imports: [ - HttpModule.register({ - baseURL: 'https://www.googleapis.com/batch/gmail/v1', - }), - ], - providers: [FetchByBatchesService], - exports: [FetchByBatchesService], -}) -export class FetchByBatchModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module.ts b/packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module.ts deleted file mode 100644 index 9bcb91371..000000000 --- a/packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { FetchByBatchModule } from 'src/modules/messaging/services/fetch-by-batch/fetch-by-batch.module'; -import { FetchMessagesByBatchesService } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service'; - -@Module({ - imports: [FetchByBatchModule], - providers: [FetchMessagesByBatchesService], - exports: [FetchMessagesByBatchesService], -}) -export class FetchMessagesByBatchesModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module.ts b/packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module.ts deleted file mode 100644 index 915fac67f..000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { GmailErrorHandlingService } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.service'; -import { SetMessageChannelSyncStatusModule } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module'; -import { MessagingTelemetryModule } from 'src/modules/messaging/services/telemetry/messaging-telemetry.module'; - -@Module({ - imports: [SetMessageChannelSyncStatusModule, MessagingTelemetryModule], - providers: [GmailErrorHandlingService], - exports: [GmailErrorHandlingService], -}) -export class GmailErrorHandlingModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.module.ts b/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.module.ts deleted file mode 100644 index e5733ffc4..000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.module.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; -import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { FetchMessagesByBatchesModule } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module'; -import { GmailErrorHandlingModule } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module'; -import { GmailFullMessageListFetchV2Service } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch-v2.service'; -import { GmailFullMessageListFetchService } from 'src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service'; -import { SetMessageChannelSyncStatusModule } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module'; -import { MessagingProvidersModule } from 'src/modules/messaging/services/providers/messaging-providers.module'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; - -@Module({ - imports: [ - MessagingProvidersModule, - FetchMessagesByBatchesModule, - GmailErrorHandlingModule, - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - MessageChannelWorkspaceEntity, - MessageChannelMessageAssociationWorkspaceEntity, - BlocklistWorkspaceEntity, - ]), - TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), - WorkspaceDataSourceModule, - SetMessageChannelSyncStatusModule, - ], - providers: [ - GmailFullMessageListFetchService, - GmailFullMessageListFetchV2Service, - ], - exports: [ - GmailFullMessageListFetchService, - GmailFullMessageListFetchV2Service, - ], -}) -export class GmailFullMessageListFetchModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service.ts b/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service.ts deleted file mode 100644 index e2ab6e0f5..000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-full-message-list-fetch/gmail-full-message-list-fetch.service.ts +++ /dev/null @@ -1,306 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { EntityManager, Repository } from 'typeorm'; -import { gmail_v1 } from 'googleapis'; - -import { - FeatureFlagEntity, - FeatureFlagKeys, -} from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { BlocklistRepository } from 'src/modules/connected-account/repositories/blocklist.repository'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { GMAIL_USERS_MESSAGES_LIST_MAX_RESULT } from 'src/modules/messaging/constants/gmail-users-messages-list-max-result.constant'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { - MessageChannelWorkspaceEntity, - MessageChannelSyncStatus, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { computeGmailCategoryExcludeSearchFilter } from 'src/modules/messaging/utils/compute-gmail-category-excude-search-filter'; -import { GMAIL_EXCLUDED_CATEGORIES } from 'src/modules/messaging/constants/gmail-excluded-categories'; - -@Injectable() -export class GmailFullMessageListFetchService { - private readonly logger = new Logger(GmailFullMessageListFetchService.name); - - constructor( - private readonly gmailClientProvider: GmailClientProvider, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, - @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) - private readonly messageChannelRepository: MessageChannelRepository, - @InjectObjectMetadataRepository(BlocklistWorkspaceEntity) - private readonly blocklistRepository: BlocklistRepository, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, - @InjectCacheStorage(CacheStorageNamespace.Messaging) - private readonly cacheStorage: CacheStorageService, - @InjectObjectMetadataRepository( - MessageChannelMessageAssociationWorkspaceEntity, - ) - private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository, - private readonly workspaceDataSourceService: WorkspaceDataSourceService, - ) {} - - public async fetchConnectedAccountThreads( - workspaceId: string, - connectedAccountId: string, - includedEmails?: string[], - ) { - const connectedAccount = await this.connectedAccountRepository.getById( - connectedAccountId, - workspaceId, - ); - - if (!connectedAccount) { - this.logger.error( - `Connected account ${connectedAccountId} not found in workspace ${workspaceId}`, - ); - - return; - } - - const refreshToken = connectedAccount.refreshToken; - - if (!refreshToken) { - throw new Error( - `No refresh token found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - } - - const gmailMessageChannel = - await this.messageChannelRepository.getFirstByConnectedAccountId( - connectedAccountId, - workspaceId, - ); - - if (!gmailMessageChannel) { - this.logger.error( - `No message channel found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - - return; - } - - if (gmailMessageChannel.syncStatus === MessageChannelSyncStatus.ONGOING) { - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} is locked, import will be retried later.`, - ); - - return; - } - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.ONGOING, - workspaceId, - ); - - const workspaceDataSource = - await this.workspaceDataSourceService.connectToWorkspaceDataSource( - workspaceId, - ); - - const gmailClient: gmail_v1.Gmail = - await this.gmailClientProvider.getGmailClient(refreshToken); - - const blocklistedEmails = await this.fetchBlocklistEmails( - connectedAccount.accountOwnerId, - workspaceId, - ); - - await workspaceDataSource - ?.transaction(async (transactionManager) => { - await this.fetchAllMessageIdsFromGmailAndStoreInCache( - gmailClient, - gmailMessageChannel.id, - includedEmails || [], - blocklistedEmails, - workspaceId, - transactionManager, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.PENDING, - workspaceId, - transactionManager, - ); - }) - .catch(async (error) => { - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.FAILED, - workspaceId, - ); - - throw new Error( - `Error fetching messages for ${connectedAccountId} in workspace ${workspaceId}: ${error.message}`, - ); - }); - } - - public async fetchAllMessageIdsFromGmailAndStoreInCache( - gmailClient: gmail_v1.Gmail, - messageChannelId: string, - includedEmails: string[], - blocklistedEmails: string[], - workspaceId: string, - transactionManager?: EntityManager, - ) { - let pageToken: string | undefined; - let hasMoreMessages = true; - let messageIdsToFetch = 0; - let firstMessageExternalId; - - while (hasMoreMessages) { - const response = await gmailClient.users.messages.list({ - userId: 'me', - maxResults: GMAIL_USERS_MESSAGES_LIST_MAX_RESULT, - pageToken, - q: computeGmailCategoryExcludeSearchFilter(GMAIL_EXCLUDED_CATEGORIES), - }); - - if (response.data?.messages) { - const messageExternalIds = response.data.messages - .filter((message): message is { id: string } => message.id != null) - .map((message) => message.id); - - if (!firstMessageExternalId) { - firstMessageExternalId = messageExternalIds[0]; - } - - const existingMessageChannelMessageAssociations = - await this.messageChannelMessageAssociationRepository.getByMessageExternalIdsAndMessageChannelId( - messageExternalIds, - messageChannelId, - workspaceId, - transactionManager, - ); - - const existingMessageChannelMessageAssociationsExternalIds = - existingMessageChannelMessageAssociations.map( - (messageChannelMessageAssociation) => - messageChannelMessageAssociation.messageExternalId, - ); - - const messageIdsToImport = messageExternalIds.filter( - (messageExternalId) => - !existingMessageChannelMessageAssociationsExternalIds.includes( - messageExternalId, - ), - ); - - if (messageIdsToImport && messageIdsToImport.length) { - await this.cacheStorage.setAdd( - `messages-to-import:${workspaceId}:gmail:${messageChannelId}`, - messageIdsToImport, - ); - - messageIdsToFetch += messageIdsToImport.length; - } - } - - pageToken = response.data.nextPageToken ?? undefined; - hasMoreMessages = !!pageToken; - } - - if (!messageIdsToFetch) { - this.logger.log( - `No messages found in Gmail for messageChannel ${messageChannelId} in workspace ${workspaceId}`, - ); - - return; - } - - this.logger.log( - `Fetched all ${messageIdsToFetch} message ids from Gmail for messageChannel ${messageChannelId} in workspace ${workspaceId} and added to cache for import`, - ); - - await this.updateLastSyncCursor( - gmailClient, - messageChannelId, - firstMessageExternalId, - workspaceId, - transactionManager, - ); - } - - public async fetchBlocklistEmails( - workspaceMemberId: string, - workspaceId: string, - ) { - const isBlocklistEnabledFeatureFlag = - await this.featureFlagRepository.findOneBy({ - workspaceId, - key: FeatureFlagKeys.IsBlocklistEnabled, - value: true, - }); - - const isBlocklistEnabled = - isBlocklistEnabledFeatureFlag && isBlocklistEnabledFeatureFlag.value; - - const blocklist = isBlocklistEnabled - ? await this.blocklistRepository.getByWorkspaceMemberId( - workspaceMemberId, - workspaceId, - ) - : []; - - return blocklist.map((blocklist) => blocklist.handle); - } - - private async updateLastSyncCursor( - gmailClient: gmail_v1.Gmail, - messageChannelId: string, - firstMessageExternalId: string, - workspaceId: string, - transactionManager?: EntityManager, - ) { - if (!firstMessageExternalId) { - throw new Error( - `No first message found for workspace ${workspaceId} and account ${messageChannelId}, can't update sync external id`, - ); - } - - const firstMessageContent = await gmailClient.users.messages.get({ - userId: 'me', - id: firstMessageExternalId, - }); - - if (!firstMessageContent?.data) { - throw new Error( - `No first message content found for message ${firstMessageExternalId} in workspace ${workspaceId}`, - ); - } - - const historyId = firstMessageContent?.data?.historyId; - - if (!historyId) { - throw new Error( - `No historyId found for message ${firstMessageExternalId} in workspace ${workspaceId}`, - ); - } - - this.logger.log( - `Updating last external id: ${historyId} for workspace ${workspaceId} and account ${messageChannelId} succeeded.`, - ); - - await this.messageChannelRepository.updateLastSyncCursorIfHigher( - messageChannelId, - historyId, - workspaceId, - transactionManager, - ); - } -} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.module.ts b/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.module.ts deleted file mode 100644 index 6aef6fcd2..000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.module.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; -import { GoogleAPIRefreshAccessTokenModule } from 'src/modules/connected-account/services/google-api-refresh-access-token/google-api-refresh-access-token.module'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { FetchMessagesByBatchesModule } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module'; -import { GmailErrorHandlingModule } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module'; -import { GmailMessagesImportV2Service } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import-v2.service'; -import { GmailMessagesImportService } from 'src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service'; -import { SaveMessagesAndEnqueueContactCreationService } from 'src/modules/messaging/services/gmail-messages-import/save-messages-and-enqueue-contact-creation.service'; -import { SetMessageChannelSyncStatusModule } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module'; -import { MessageParticipantModule } from 'src/modules/messaging/services/message-participant/message-participant.module'; -import { MessageModule } from 'src/modules/messaging/services/message/message.module'; -import { MessagingTelemetryModule } from 'src/modules/messaging/services/telemetry/messaging-telemetry.module'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; - -@Module({ - imports: [ - FetchMessagesByBatchesModule, - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - MessageChannelWorkspaceEntity, - ]), - MessageModule, - WorkspaceDataSourceModule, - MessageModule, - MessageParticipantModule, - SetMessageChannelSyncStatusModule, - TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), - GmailErrorHandlingModule, - GoogleAPIRefreshAccessTokenModule, - MessagingTelemetryModule, - ], - providers: [ - GmailMessagesImportService, - GmailMessagesImportV2Service, - SaveMessagesAndEnqueueContactCreationService, - ], - exports: [GmailMessagesImportService, GmailMessagesImportV2Service], -}) -export class GmailMessagesImportModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service.ts b/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service.ts deleted file mode 100644 index 788d65391..000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-messages-import/gmail-messages-import.service.ts +++ /dev/null @@ -1,320 +0,0 @@ -import { Inject, Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; - -import { EntityManager, Repository } from 'typeorm'; - -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { FetchMessagesByBatchesService } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service'; -import { - MessageChannelWorkspaceEntity, - MessageChannelSyncStatus, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { createQueriesFromMessageIds } from 'src/modules/messaging/utils/create-queries-from-message-ids.util'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { GMAIL_USERS_MESSAGES_GET_BATCH_SIZE } from 'src/modules/messaging/constants/gmail-users-messages-get-batch-size.constant'; -import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { - GmailFullMessageListFetchJobData, - GmailFullMessageListFetchJob, -} from 'src/modules/messaging/jobs/gmail-full-message-list-fetch.job'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { GMAIL_ONGOING_SYNC_TIMEOUT } from 'src/modules/messaging/constants/gmail-ongoing-sync-timeout.constant'; -import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service'; -import { MessageService } from 'src/modules/messaging/services/message/message.service'; -import { ParticipantWithMessageId } from 'src/modules/messaging/types/gmail-message'; -import { - CreateCompanyAndContactJobData, - CreateCompanyAndContactJob, -} from 'src/modules/connected-account/auto-companies-and-contacts-creation/jobs/create-company-and-contact.job'; -import { - FeatureFlagEntity, - FeatureFlagKeys, -} from 'src/engine/core-modules/feature-flag/feature-flag.entity'; - -@Injectable() -export class GmailMessagesImportService { - private readonly logger = new Logger(GmailMessagesImportService.name); - - constructor( - private readonly fetchMessagesByBatchesService: FetchMessagesByBatchesService, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, - @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) - private readonly messageChannelRepository: MessageChannelRepository, - @InjectCacheStorage(CacheStorageNamespace.Messaging) - private readonly cacheStorage: CacheStorageService, - private readonly workspaceDataSourceService: WorkspaceDataSourceService, - @Inject(MessageQueue.messagingQueue) - private readonly messageQueueService: MessageQueueService, - private readonly messageService: MessageService, - private readonly messageParticipantService: MessageParticipantService, - @InjectRepository(FeatureFlagEntity, 'core') - private readonly featureFlagRepository: Repository, - ) {} - - async fetchMessageContentFromCache( - workspaceId: string, - connectedAccountId: string, - ) { - const connectedAccount = await this.connectedAccountRepository.getById( - connectedAccountId, - workspaceId, - ); - - if (!connectedAccount) { - this.logger.error( - `Connected account ${connectedAccountId} not found in workspace ${workspaceId}`, - ); - - return; - } - - const { accessToken, refreshToken, authFailedAt } = connectedAccount; - - if (authFailedAt) { - this.logger.error( - `Connected account ${connectedAccountId} in workspace ${workspaceId} is in a failed state. Skipping...`, - ); - - return; - } - - if (!refreshToken) { - throw new Error( - `No refresh token found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - } - - const gmailMessageChannel = - await this.messageChannelRepository.getFirstByConnectedAccountId( - connectedAccountId, - workspaceId, - ); - - if (!gmailMessageChannel) { - this.logger.error( - `No message channel found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - - return; - } - - if (gmailMessageChannel.syncStatus !== MessageChannelSyncStatus.PENDING) { - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} is not pending.`, - ); - - if (gmailMessageChannel.syncStatus !== MessageChannelSyncStatus.ONGOING) { - return; - } - - const ongoingSyncStartedAt = new Date( - gmailMessageChannel.ongoingSyncStartedAt, - ); - - if ( - ongoingSyncStartedAt < new Date(Date.now() - GMAIL_ONGOING_SYNC_TIMEOUT) - ) { - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} failed due to ongoing sync timeout. Restarting full-sync...`, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.FAILED, - workspaceId, - ); - - await this.fallbackToFullSync(workspaceId, connectedAccountId); - - return; - } - - return; - } - - const gmailMessageChannelId = gmailMessageChannel.id; - - const messageIdsToFetch = - (await this.cacheStorage.setPop( - `messages-to-import:${workspaceId}:gmail:${gmailMessageChannelId}`, - GMAIL_USERS_MESSAGES_GET_BATCH_SIZE, - )) ?? []; - - if (!messageIdsToFetch?.length) { - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannelId, - MessageChannelSyncStatus.SUCCEEDED, - workspaceId, - ); - - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} done with nothing to import or delete.`, - ); - - return; - } - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannelId, - MessageChannelSyncStatus.ONGOING, - workspaceId, - ); - - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} starting...`, - ); - - const workspaceDataSource = - await this.workspaceDataSourceService.connectToWorkspaceDataSource( - workspaceId, - ); - - const messageQueries = createQueriesFromMessageIds(messageIdsToFetch); - - const isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag = - await this.featureFlagRepository.findOneBy({ - workspaceId: workspaceId, - key: FeatureFlagKeys.IsContactCreationForSentAndReceivedEmailsEnabled, - value: true, - }); - - const isContactCreationForSentAndReceivedEmailsEnabled = - isContactCreationForSentAndReceivedEmailsEnabledFeatureFlag?.value; - - try { - const messagesToSave = - await this.fetchMessagesByBatchesService.fetchAllMessages( - messageQueries, - accessToken, - workspaceId, - connectedAccountId, - ); - - const participantsWithMessageId = await workspaceDataSource?.transaction( - async (transactionManager: EntityManager) => { - if (!messagesToSave.length) { - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannelId, - MessageChannelSyncStatus.PENDING, - workspaceId, - ); - - return []; - } - - const messageExternalIdsAndIdsMap = - await this.messageService.saveMessagesWithinTransaction( - messagesToSave, - connectedAccount, - gmailMessageChannel.id, - workspaceId, - transactionManager, - ); - - const participantsWithMessageId: (ParticipantWithMessageId & { - shouldCreateContact: boolean; - })[] = messagesToSave.flatMap((message) => { - const messageId = messageExternalIdsAndIdsMap.get( - message.externalId, - ); - - return messageId - ? message.participants.map((participant) => ({ - ...participant, - messageId, - shouldCreateContact: - gmailMessageChannel.isContactAutoCreationEnabled && - (isContactCreationForSentAndReceivedEmailsEnabled || - message.participants.find((p) => p.role === 'from') - ?.handle === connectedAccount.handle), - })) - : []; - }); - - await this.messageParticipantService.saveMessageParticipants( - participantsWithMessageId, - workspaceId, - transactionManager, - ); - - if (messageIdsToFetch.length < GMAIL_USERS_MESSAGES_GET_BATCH_SIZE) { - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannelId, - MessageChannelSyncStatus.SUCCEEDED, - workspaceId, - transactionManager, - ); - - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} done with no more messages to import.`, - ); - } else { - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannelId, - MessageChannelSyncStatus.PENDING, - workspaceId, - transactionManager, - ); - - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} done with more messages to import.`, - ); - } - - return participantsWithMessageId; - }, - ); - - if (gmailMessageChannel.isContactAutoCreationEnabled) { - const contactsToCreate = participantsWithMessageId.filter( - (participant) => participant.shouldCreateContact, - ); - - await this.messageQueueService.add( - CreateCompanyAndContactJob.name, - { - workspaceId, - connectedAccountHandle: connectedAccount.handle, - contactsToCreate, - }, - ); - } - } catch (error) { - await this.cacheStorage.setAdd( - `messages-to-import:${workspaceId}:gmail:${gmailMessageChannelId}`, - messageIdsToFetch, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannelId, - MessageChannelSyncStatus.FAILED, - workspaceId, - ); - - this.logger.error( - `Error fetching messages for ${connectedAccountId} in workspace ${workspaceId}: locking for ${GMAIL_ONGOING_SYNC_TIMEOUT}ms...`, - ); - - throw new Error( - `Error fetching messages for ${connectedAccountId} in workspace ${workspaceId}: ${error.message}`, - ); - } - } - - private async fallbackToFullSync( - workspaceId: string, - connectedAccountId: string, - ) { - await this.messageQueueService.add( - GmailFullMessageListFetchJob.name, - { workspaceId, connectedAccountId }, - ); - } -} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.module.ts b/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.module.ts deleted file mode 100644 index cd0a0c31f..000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.module.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; -import { BlocklistWorkspaceEntity } from 'src/modules/connected-account/standard-objects/blocklist.workspace-entity'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { FetchMessagesByBatchesModule } from 'src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.module'; -import { GmailErrorHandlingModule } from 'src/modules/messaging/services/gmail-error-handling/gmail-error-handling.module'; -import { GmailFetchMessageIdsToExcludeService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-fetch-messages-ids-to-exclude.service'; -import { GmailGetHistoryService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-get-history.service'; -import { GmailPartialMessageListFetchV2Service } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch-v2.service'; -import { GmailPartialMessageListFetchService } from 'src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.service'; -import { SetMessageChannelSyncStatusModule } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module'; -import { MessageModule } from 'src/modules/messaging/services/message/message.module'; -import { MessagingProvidersModule } from 'src/modules/messaging/services/providers/messaging-providers.module'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; - -@Module({ - imports: [ - MessagingProvidersModule, - FetchMessagesByBatchesModule, - ObjectMetadataRepositoryModule.forFeature([ - ConnectedAccountWorkspaceEntity, - MessageChannelWorkspaceEntity, - BlocklistWorkspaceEntity, - ]), - MessageModule, - TypeOrmModule.forFeature([FeatureFlagEntity], 'core'), - WorkspaceDataSourceModule, - SetMessageChannelSyncStatusModule, - GmailErrorHandlingModule, - ], - providers: [ - GmailPartialMessageListFetchService, - GmailPartialMessageListFetchV2Service, - GmailGetHistoryService, - GmailFetchMessageIdsToExcludeService, - ], - exports: [ - GmailPartialMessageListFetchService, - GmailPartialMessageListFetchV2Service, - ], -}) -export class GmailPartialMessageListFetchModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.service.ts b/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.service.ts deleted file mode 100644 index 779c6d6f3..000000000 --- a/packages/twenty-server/src/modules/messaging/services/gmail-partial-message-list-fetch/gmail-partial-message-list-fetch.service.ts +++ /dev/null @@ -1,347 +0,0 @@ -import { Inject, Injectable, Logger } from '@nestjs/common'; - -import { gmail_v1 } from 'googleapis'; -import { EntityManager } from 'typeorm'; - -import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider'; -import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service'; -import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants'; -import { ConnectedAccountRepository } from 'src/modules/connected-account/repositories/connected-account.repository'; -import { MessageChannelRepository } from 'src/modules/messaging/repositories/message-channel.repository'; -import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator'; -import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; -import { - MessageChannelWorkspaceEntity, - MessageChannelSyncStatus, -} from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { GMAIL_USERS_HISTORY_MAX_RESULT } from 'src/modules/messaging/constants/gmail-users-history-max-result.constant'; -import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service'; -import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; -import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; -import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; -import { - GmailFullMessageListFetchJob, - GmailFullMessageListFetchJobData, -} from 'src/modules/messaging/jobs/gmail-full-message-list-fetch.job'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelMessageAssociationRepository } from 'src/modules/messaging/repositories/message-channel-message-association.repository'; - -@Injectable() -export class GmailPartialMessageListFetchService { - private readonly logger = new Logger( - GmailPartialMessageListFetchService.name, - ); - - constructor( - private readonly gmailClientProvider: GmailClientProvider, - @Inject(MessageQueue.messagingQueue) - private readonly messageQueueService: MessageQueueService, - @InjectObjectMetadataRepository(ConnectedAccountWorkspaceEntity) - private readonly connectedAccountRepository: ConnectedAccountRepository, - @InjectObjectMetadataRepository(MessageChannelWorkspaceEntity) - private readonly messageChannelRepository: MessageChannelRepository, - @InjectCacheStorage(CacheStorageNamespace.Messaging) - private readonly cacheStorage: CacheStorageService, - private readonly workspaceDataSourceService: WorkspaceDataSourceService, - @InjectObjectMetadataRepository( - MessageChannelMessageAssociationWorkspaceEntity, - ) - private readonly messageChannelMessageAssociationRepository: MessageChannelMessageAssociationRepository, - ) {} - - public async fetchConnectedAccountThreads( - workspaceId: string, - connectedAccountId: string, - ): Promise { - const connectedAccount = await this.connectedAccountRepository.getById( - connectedAccountId, - workspaceId, - ); - - if (!connectedAccount) { - this.logger.error( - `Connected account ${connectedAccountId} not found in workspace ${workspaceId}`, - ); - - return; - } - - const refreshToken = connectedAccount.refreshToken; - - if (!refreshToken) { - throw new Error( - `No refresh token found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - } - - const gmailMessageChannel = - await this.messageChannelRepository.getFirstByConnectedAccountId( - connectedAccountId, - workspaceId, - ); - - if (!gmailMessageChannel) { - this.logger.error( - `No message channel found for connected account ${connectedAccountId} in workspace ${workspaceId}`, - ); - - return; - } - - if (gmailMessageChannel.syncStatus !== MessageChannelSyncStatus.SUCCEEDED) { - this.logger.log( - `Messaging import for workspace ${workspaceId} and account ${connectedAccountId} is locked, import will be retried later.`, - ); - - return; - } - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.ONGOING, - workspaceId, - ); - - const workspaceDataSource = - await this.workspaceDataSourceService.connectToWorkspaceDataSource( - workspaceId, - ); - - await workspaceDataSource - ?.transaction(async (transactionManager: EntityManager) => { - const lastSyncHistoryId = gmailMessageChannel.syncCursor; - - if (!lastSyncHistoryId) { - this.logger.log( - `No lastSyncHistoryId for workspace ${workspaceId} and account ${connectedAccountId}, falling back to full sync.`, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.PENDING, - workspaceId, - transactionManager, - ); - - await this.fallbackToFullSync(workspaceId, connectedAccountId); - - return; - } - - const gmailClient: gmail_v1.Gmail = - await this.gmailClientProvider.getGmailClient(refreshToken); - - const { history, historyId, error } = await this.getHistoryFromGmail( - gmailClient, - lastSyncHistoryId, - ); - - if (error?.code === 404) { - this.logger.log( - `404: Invalid lastSyncHistoryId: ${lastSyncHistoryId} for workspace ${workspaceId} and account ${connectedAccountId}, falling back to full sync.`, - ); - - await this.messageChannelRepository.resetSyncCursor( - gmailMessageChannel.id, - workspaceId, - transactionManager, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.PENDING, - workspaceId, - transactionManager, - ); - - await this.fallbackToFullSync(workspaceId, connectedAccountId); - - return; - } - - if (error?.code === 429) { - this.logger.log( - `429: rate limit reached for workspace ${workspaceId} and account ${connectedAccountId}: ${error.message}, import will be retried later.`, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.PENDING, - workspaceId, - transactionManager, - ); - - return; - } - - if (error) { - throw new Error( - `Error fetching messages for ${connectedAccountId} in workspace ${workspaceId}: ${error.message}`, - ); - } - - if (!historyId) { - throw new Error( - `No historyId found for ${connectedAccountId} in workspace ${workspaceId} in gmail history response.`, - ); - } - - if (historyId === lastSyncHistoryId || !history?.length) { - this.logger.log( - `Messaging import done with history ${historyId} and nothing to update for workspace ${workspaceId} and account ${connectedAccountId}`, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.PENDING, - workspaceId, - ); - - return; - } - - const { messagesAdded, messagesDeleted } = - await this.getMessageIdsFromHistory(history); - - await this.cacheStorage.setAdd( - `messages-to-import:${workspaceId}:gmail:${gmailMessageChannel.id}`, - messagesAdded, - ); - - await this.messageChannelMessageAssociationRepository.deleteByMessageExternalIdsAndMessageChannelId( - messagesDeleted, - gmailMessageChannel.id, - workspaceId, - transactionManager, - ); - - await this.messageChannelRepository.updateLastSyncCursorIfHigher( - gmailMessageChannel.id, - historyId, - workspaceId, - transactionManager, - ); - - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.PENDING, - workspaceId, - transactionManager, - ); - }) - .catch(async (error) => { - await this.messageChannelRepository.updateSyncStatus( - gmailMessageChannel.id, - MessageChannelSyncStatus.FAILED, - workspaceId, - ); - - throw new Error( - `Error fetching messages for ${connectedAccountId} in workspace ${workspaceId}: ${error.message}`, - ); - }); - } - - private async getMessageIdsFromHistory( - history: gmail_v1.Schema$History[], - ): Promise<{ - messagesAdded: string[]; - messagesDeleted: string[]; - }> { - const { messagesAdded, messagesDeleted } = history.reduce( - ( - acc: { - messagesAdded: string[]; - messagesDeleted: string[]; - }, - history, - ) => { - const messagesAdded = history.messagesAdded?.map( - (messageAdded) => messageAdded.message?.id || '', - ); - - const messagesDeleted = history.messagesDeleted?.map( - (messageDeleted) => messageDeleted.message?.id || '', - ); - - if (messagesAdded) acc.messagesAdded.push(...messagesAdded); - if (messagesDeleted) acc.messagesDeleted.push(...messagesDeleted); - - return acc; - }, - { messagesAdded: [], messagesDeleted: [] }, - ); - - const uniqueMessagesAdded = messagesAdded.filter( - (messageId) => !messagesDeleted.includes(messageId), - ); - - const uniqueMessagesDeleted = messagesDeleted.filter( - (messageId) => !messagesAdded.includes(messageId), - ); - - return { - messagesAdded: uniqueMessagesAdded, - messagesDeleted: uniqueMessagesDeleted, - }; - } - - private async getHistoryFromGmail( - gmailClient: gmail_v1.Gmail, - lastSyncHistoryId: string, - ): Promise<{ - history: gmail_v1.Schema$History[]; - historyId?: string | null; - error?: any; - }> { - const fullHistory: gmail_v1.Schema$History[] = []; - let pageToken: string | undefined; - let hasMoreMessages = true; - let nextHistoryId: string | undefined; - - while (hasMoreMessages) { - try { - const response = await gmailClient.users.history.list({ - userId: 'me', - maxResults: GMAIL_USERS_HISTORY_MAX_RESULT, - pageToken, - startHistoryId: lastSyncHistoryId, - historyTypes: ['messageAdded', 'messageDeleted'], - }); - - nextHistoryId = response?.data?.historyId ?? undefined; - - if (response?.data?.history) { - fullHistory.push(...response.data.history); - } - - pageToken = response?.data?.nextPageToken ?? undefined; - hasMoreMessages = !!pageToken; - } catch (error) { - const errorData = error?.response?.data?.error; - - if (errorData) { - return { - history: [], - error: errorData, - historyId: lastSyncHistoryId, - }; - } - - throw error; - } - } - - return { history: fullHistory, historyId: nextHistoryId }; - } - - private async fallbackToFullSync( - workspaceId: string, - connectedAccountId: string, - ) { - await this.messageQueueService.add( - GmailFullMessageListFetchJob.name, - { workspaceId, connectedAccountId }, - ); - } -} diff --git a/packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module.ts b/packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module.ts deleted file mode 100644 index 42e350d07..000000000 --- a/packages/twenty-server/src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { MessageChannelSyncStatusService } from 'src/modules/messaging/services/message-channel-sync-status/message-channel-sync-status.service'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; - -@Module({ - imports: [ - ObjectMetadataRepositoryModule.forFeature([MessageChannelWorkspaceEntity]), - ], - providers: [MessageChannelSyncStatusService], - exports: [MessageChannelSyncStatusService], -}) -export class SetMessageChannelSyncStatusModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.module.ts b/packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.module.ts deleted file mode 100644 index 907ae76ec..000000000 --- a/packages/twenty-server/src/modules/messaging/services/message-participant/message-participant.module.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; -import { AddPersonIdAndWorkspaceMemberIdModule } from 'src/modules/calendar-messaging-participant/services/add-person-id-and-workspace-member-id/add-person-id-and-workspace-member-id.module'; -import { MessageParticipantService } from 'src/modules/messaging/services/message-participant/message-participant.service'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; -import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; - -@Module({ - imports: [ - WorkspaceDataSourceModule, - ObjectMetadataRepositoryModule.forFeature([ - PersonWorkspaceEntity, - MessageParticipantWorkspaceEntity, - ]), - AddPersonIdAndWorkspaceMemberIdModule, - ], - providers: [MessageParticipantService], - exports: [MessageParticipantService], -}) -export class MessageParticipantModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.module.ts b/packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.module.ts deleted file mode 100644 index eb7cbd748..000000000 --- a/packages/twenty-server/src/modules/messaging/services/message-thread/message-thread.module.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { MessageThreadService } from 'src/modules/messaging/services/message-thread/message-thread.service'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; - -@Module({ - imports: [ - ObjectMetadataRepositoryModule.forFeature([ - MessageChannelMessageAssociationWorkspaceEntity, - MessageWorkspaceEntity, - MessageThreadWorkspaceEntity, - ]), - ], - providers: [MessageThreadService], - exports: [MessageThreadService], -}) -export class MessageThreadModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/message/message.module.ts b/packages/twenty-server/src/modules/messaging/services/message/message.module.ts deleted file mode 100644 index 8bfa2b6d5..000000000 --- a/packages/twenty-server/src/modules/messaging/services/message/message.module.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module'; -import { MessageThreadModule } from 'src/modules/messaging/services/message-thread/message-thread.module'; -import { MessageService } from 'src/modules/messaging/services/message/message.service'; -import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel-message-association.workspace-entity'; -import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-channel.workspace-entity'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; - -@Module({ - imports: [ - WorkspaceDataSourceModule, - ObjectMetadataRepositoryModule.forFeature([ - MessageChannelMessageAssociationWorkspaceEntity, - MessageWorkspaceEntity, - MessageChannelWorkspaceEntity, - MessageThreadWorkspaceEntity, - ]), - MessageThreadModule, - ], - providers: [MessageService], - exports: [MessageService], -}) -export class MessageModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/providers/messaging-providers.module.ts b/packages/twenty-server/src/modules/messaging/services/providers/messaging-providers.module.ts deleted file mode 100644 index fc0cb1c17..000000000 --- a/packages/twenty-server/src/modules/messaging/services/providers/messaging-providers.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { EnvironmentModule } from 'src/engine/integrations/environment/environment.module'; -import { GmailClientProvider } from 'src/modules/messaging/services/providers/gmail/gmail-client.provider'; - -@Module({ - imports: [EnvironmentModule], - providers: [GmailClientProvider], - exports: [GmailClientProvider], -}) -export class MessagingProvidersModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/telemetry/messaging-telemetry.module.ts b/packages/twenty-server/src/modules/messaging/services/telemetry/messaging-telemetry.module.ts deleted file mode 100644 index f5bd69370..000000000 --- a/packages/twenty-server/src/modules/messaging/services/telemetry/messaging-telemetry.module.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { AnalyticsModule } from 'src/engine/core-modules/analytics/analytics.module'; -import { MessagingTelemetryService } from 'src/modules/messaging/services/telemetry/messaging-telemetry.service'; - -@Module({ - imports: [AnalyticsModule], - providers: [MessagingTelemetryService], - exports: [MessagingTelemetryService], -}) -export class MessagingTelemetryModule {} diff --git a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.module.ts b/packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.module.ts deleted file mode 100644 index 6305b55a3..000000000 --- a/packages/twenty-server/src/modules/messaging/services/thread-cleaner/thread-cleaner.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Module } from '@nestjs/common'; - -import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module'; -import { ThreadCleanerService } from 'src/modules/messaging/services/thread-cleaner/thread-cleaner.service'; -import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-thread.workspace-entity'; -import { MessageWorkspaceEntity } from 'src/modules/messaging/standard-objects/message.workspace-entity'; - -@Module({ - imports: [ - ObjectMetadataRepositoryModule.forFeature([ - MessageWorkspaceEntity, - MessageThreadWorkspaceEntity, - ]), - ], - providers: [ThreadCleanerService], - exports: [ThreadCleanerService], -}) -export class ThreadCleanerModule {} diff --git a/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts b/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts index 23b5c33ad..83353993d 100644 --- a/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts +++ b/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts @@ -14,7 +14,6 @@ import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objec import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/standard-objects/calendar-event-participant.workspace-entity'; import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; @@ -23,6 +22,7 @@ import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.person, diff --git a/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts b/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts index 1a5f77e4b..17378a598 100644 --- a/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts @@ -16,7 +16,6 @@ import { CommentWorkspaceEntity } from 'src/modules/activity/standard-objects/co import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; -import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/standard-objects/message-participant.workspace-entity'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; import { AuditLogWorkspaceEntity } from 'src/modules/timeline/standard-objects/audit-log.workspace-entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; @@ -26,6 +25,7 @@ import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/work import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; +import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.workspaceMember,