diff --git a/packages/features/tasker/tasks/scanWorkflowBody.test.ts b/packages/features/tasker/tasks/scanWorkflowBody.test.ts index 65503b2d4e..dda3b03086 100644 --- a/packages/features/tasker/tasks/scanWorkflowBody.test.ts +++ b/packages/features/tasker/tasks/scanWorkflowBody.test.ts @@ -216,7 +216,9 @@ describe("scanWorkflowBody", () => { passthrough: true, }), }); - expect(prismaMock.workflowStep.update).not.toHaveBeenCalled(); + expect(prismaMock.workflowStep.update).toHaveBeenCalled(); + expect(scheduleWorkflowNotifications).toHaveBeenCalled(); + expect(lockUser).not.toHaveBeenCalled(); }); }); diff --git a/packages/features/tasker/tasks/scanWorkflowBody.ts b/packages/features/tasker/tasks/scanWorkflowBody.ts index 37183456fd..694dcde180 100644 --- a/packages/features/tasker/tasks/scanWorkflowBody.ts +++ b/packages/features/tasker/tasks/scanWorkflowBody.ts @@ -17,13 +17,23 @@ export const scanWorkflowBodySchema = z.object({ const log = logger.getSubLogger({ prefix: ["[tasker] scanWorkflowBody"] }); export async function scanWorkflowBody(payload: string) { + const { workflowStepIds, userId } = scanWorkflowBodySchema.parse(JSON.parse(payload)); + if (!process.env.IFFY_API_KEY) { log.info("IFFY_API_KEY not set, skipping scan"); + await prisma.workflowStep.updateMany({ + where: { + id: { + in: workflowStepIds, + }, + }, + data: { + verifiedAt: new Date(), + }, + }); return; } - const { workflowStepIds, userId } = scanWorkflowBodySchema.parse(JSON.parse(payload)); - const workflowSteps = await prisma.workflowStep.findMany({ where: { id: { @@ -91,29 +101,27 @@ export async function scanWorkflowBody(payload: string) { const isSpam = await iffyScanBody(workflowStep.reminderBody, workflowStep.id); if (isSpam) { - if (workflowStep.workflow.user?.whitelistWorkflows) { - log.warn( - `For whitelisted user, workflow step ${workflowStep.id} is spam with body ${workflowStep.reminderBody}` - ); + if (!workflowStep.workflow.user?.whitelistWorkflows) { + // We won't delete the workflow step incase it is flagged as a false positive + log.warn(`Workflow step ${workflowStep.id} is spam with body ${workflowStep.reminderBody}`); + await lockUser("userId", userId.toString(), LockReason.SPAM_WORKFLOW_BODY); + + // Return early if spam is detected return; } - - // We won't delete the workflow step incase it is flagged as a false positive - log.warn(`Workflow step ${workflowStep.id} is spam with body ${workflowStep.reminderBody}`); - await lockUser("userId", userId.toString(), LockReason.SPAM_WORKFLOW_BODY); - - // Return early if spam is detected - return; - } else { - await prisma.workflowStep.update({ - where: { - id: workflowStep.id, - }, - data: { - verifiedAt: new Date(), - }, - }); + log.warn( + `For whitelisted user, workflow step ${workflowStep.id} is spam with body ${workflowStep.reminderBody}` + ); } + + await prisma.workflowStep.update({ + where: { + id: workflowStep.id, + }, + data: { + verifiedAt: new Date(), + }, + }); } const workflow = await prisma.workflow.findFirst({ diff --git a/packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts b/packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts index c8d8c6b096..f307c3a581 100644 --- a/packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts +++ b/packages/trpc/server/routers/viewer/workflows/activateEventType.handler.ts @@ -139,7 +139,7 @@ export const activateEventTypeHandler = async ({ ctx, input }: ActivateEventType let allEventTypes = []; - //get all event types of of team or user + //get all event types of team or user if (eventTypeWorkflow.teamId) { allEventTypes = await prisma.eventType.findMany({ where: { @@ -193,7 +193,14 @@ export const activateEventTypeHandler = async ({ ctx, input }: ActivateEventType // activate workflow and schedule reminders for existing bookings const bookingsForReminders = await prisma.booking.findMany({ where: { - eventTypeId: eventTypeId, + OR: [ + { eventTypeId }, + { + eventType: { + parentId: eventTypeId, + }, + }, + ], status: BookingStatus.ACCEPTED, startTime: { gte: new Date(), @@ -352,6 +359,44 @@ export const activateEventTypeHandler = async ({ ctx, input }: ActivateEventType teamId: eventTypeWorkflow.teamId, verifiedAt: step.verifiedAt, }); + } else if (booking.smsReminderNumber) { + if (step.action === WorkflowActions.SMS_ATTENDEE) { + await scheduleSMSReminder({ + evt: bookingInfo, + reminderPhone: booking.smsReminderNumber, + triggerEvent: eventTypeWorkflow.trigger, + action: step.action, + timeSpan: { + time: eventTypeWorkflow.time, + timeUnit: eventTypeWorkflow.timeUnit, + }, + message: step.reminderBody || "", + workflowStepId: step.id, + template: step.template, + sender: step.sender, + userId: booking.userId, + teamId: eventTypeWorkflow.teamId, + verifiedAt: step.verifiedAt, + }); + } else if (step.action === WorkflowActions.WHATSAPP_ATTENDEE) { + await scheduleWhatsappReminder({ + evt: bookingInfo, + reminderPhone: booking.smsReminderNumber, + triggerEvent: eventTypeWorkflow.trigger, + action: step.action, + timeSpan: { + time: eventTypeWorkflow.time, + timeUnit: eventTypeWorkflow.timeUnit, + }, + message: step.reminderBody || "", + workflowStepId: step.id, + template: step.template, + sender: step.sender, + userId: booking.userId, + teamId: eventTypeWorkflow.teamId, + verifiedAt: step.verifiedAt, + }); + } } } } diff --git a/packages/trpc/server/routers/viewer/workflows/util.ts b/packages/trpc/server/routers/viewer/workflows/util.ts index 2d833215d1..1716fb6003 100644 --- a/packages/trpc/server/routers/viewer/workflows/util.ts +++ b/packages/trpc/server/routers/viewer/workflows/util.ts @@ -44,6 +44,7 @@ export const bookingSelect = { title: true, uid: true, metadata: true, + smsReminderNumber: true, attendees: { select: { name: true, @@ -620,10 +621,6 @@ export async function scheduleBookingReminders( //create reminders for all bookings for each workflow step const promiseSteps = workflowSteps.map(async (step) => { - // we do not have attendees phone number (user is notified about that when setting this action) - if (step.action == WorkflowActions.SMS_ATTENDEE || step.action == WorkflowActions.WHATSAPP_ATTENDEE) - return; - const promiseScheduleReminders = bookings.map(async (booking) => { const defaultLocale = "en"; const bookingInfo = { @@ -742,6 +739,44 @@ export async function scheduleBookingReminders( teamId: teamId, verifiedAt: step?.verifiedAt ?? null, }); + } else if (booking.smsReminderNumber) { + if (step.action === WorkflowActions.SMS_ATTENDEE) { + await scheduleSMSReminder({ + evt: bookingInfo, + reminderPhone: booking.smsReminderNumber, + triggerEvent: trigger, + action: step.action, + timeSpan: { + time, + timeUnit, + }, + message: step.reminderBody || "", + workflowStepId: step.id, + template: step.template, + sender: step.sender, + userId: userId, + teamId: teamId, + verifiedAt: step?.verifiedAt ?? null, + }); + } else if (step.action === WorkflowActions.WHATSAPP_ATTENDEE) { + await scheduleWhatsappReminder({ + evt: bookingInfo, + reminderPhone: booking.smsReminderNumber, + triggerEvent: trigger, + action: step.action, + timeSpan: { + time, + timeUnit, + }, + message: step.reminderBody || "", + workflowStepId: step.id, + template: step.template, + sender: step.sender, + userId: userId, + teamId: teamId, + verifiedAt: step?.verifiedAt ?? null, + }); + } } }); await Promise.all(promiseScheduleReminders);