123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- import 'reflect-metadata'
- import 'newrelic'
- import { Stream } from 'stream'
- import { Logger } from 'winston'
- import * as dayjs from 'dayjs'
- import * as utc from 'dayjs/plugin/utc'
- import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
- import { ContainerConfigLoader } from '../src/Bootstrap/Container'
- import TYPES from '../src/Bootstrap/Types'
- import { Env } from '../src/Bootstrap/Env'
- import { SettingServiceInterface } from '../src/Domain/Setting/SettingServiceInterface'
- import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
- import { UserSubscriptionRepositoryInterface } from '../src/Domain/Subscription/UserSubscriptionRepositoryInterface'
- import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
- import { MuteMarketingEmailsOption, SettingName } from '@standardnotes/settings'
- import { EmailMessageIdentifier } from '@standardnotes/common'
- import { User } from '../src/Domain/User/User'
- import { EncryptionVersion } from '../src/Domain/Encryption/EncryptionVersion'
- import { TimerInterface } from '@standardnotes/time'
- const inputArgs = process.argv.slice(2)
- const emailMessageIdentifier = inputArgs[0]
- const sendEmailCampaign = async (
- userRepository: UserRepositoryInterface,
- settingService: SettingServiceInterface,
- userSubscriptionRepository: UserSubscriptionRepositoryInterface,
- timer: TimerInterface,
- domainEventFactory: DomainEventFactoryInterface,
- domainEventPublisher: DomainEventPublisherInterface,
- ): Promise<void> => {
- const stream = await userRepository.streamAll()
- return new Promise((resolve, reject) => {
- stream
- .pipe(
- new Stream.Transform({
- objectMode: true,
- transform: async (rawUserData, _encoding, callback) => {
- let emailsMutedSetting = await settingService.findSettingWithDecryptedValue({
- userUuid: rawUserData.user_uuid,
- settingName: SettingName.MuteMarketingEmails,
- })
- if (emailsMutedSetting === null) {
- const user = (await userRepository.findOneByUuid(rawUserData.user_uuid)) as User
- const { setting } = await settingService.createOrReplace({
- user,
- props: {
- name: SettingName.MuteMarketingEmails,
- unencryptedValue: MuteMarketingEmailsOption.NotMuted,
- serverEncryptionVersion: EncryptionVersion.Default,
- sensitive: false,
- },
- })
- emailsMutedSetting = setting
- }
- if (emailsMutedSetting.value === MuteMarketingEmailsOption.Muted) {
- callback()
- return
- }
- let activeSubscription = false
- let subscriptionPlanName = null
- const userSubscription = await userSubscriptionRepository.findOneByUserUuid(rawUserData.user_uuid)
- if (userSubscription !== null) {
- activeSubscription =
- !userSubscription.cancelled && userSubscription.endsAt > timer.getTimestampInMicroseconds()
- subscriptionPlanName = userSubscription.planName
- }
- await domainEventPublisher.publish(
- domainEventFactory.createEmailMessageRequestedEvent({
- userEmail: rawUserData.user_email,
- messageIdentifier: emailMessageIdentifier as EmailMessageIdentifier,
- context: {
- activeSubscription,
- subscriptionPlanName,
- muteEmailsSettingUuid: emailsMutedSetting.uuid,
- },
- }),
- )
- callback()
- },
- }),
- )
- .on('finish', resolve)
- .on('error', reject)
- })
- }
- const container = new ContainerConfigLoader()
- void container.load().then((container) => {
- dayjs.extend(utc)
- const env: Env = new Env()
- env.load()
- const logger: Logger = container.get(TYPES.Logger)
- logger.info(`Starting email campaign for email ${emailMessageIdentifier} ...`)
- if (!emailMessageIdentifier) {
- logger.error('No email message identifier passed as argument. Skipped sending.')
- process.exit(1)
- }
- const userRepository: UserRepositoryInterface = container.get(TYPES.UserRepository)
- const settingService: SettingServiceInterface = container.get(TYPES.SettingService)
- const userSubscriptionRepository: UserSubscriptionRepositoryInterface = container.get(
- TYPES.UserSubscriptionRepository,
- )
- const timer: TimerInterface = container.get(TYPES.Timer)
- const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.DomainEventFactory)
- const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.DomainEventPublisher)
- Promise.resolve(
- sendEmailCampaign(
- userRepository,
- settingService,
- userSubscriptionRepository,
- timer,
- domainEventFactory,
- domainEventPublisher,
- ),
- )
- .then(() => {
- logger.info(`${emailMessageIdentifier} email campaign complete.`)
- process.exit(0)
- })
- .catch((error) => {
- logger.error(`Could not finish ${emailMessageIdentifier} email campaign: ${error.message}`)
- process.exit(1)
- })
- })
|