diff --git a/packages/emails/src/emails/AlmostReachedChatsLimitEmail.tsx b/packages/emails/src/emails/AlmostReachedChatsLimitEmail.tsx
index 385d5d52d..e8afc9d91 100644
--- a/packages/emails/src/emails/AlmostReachedChatsLimitEmail.tsx
+++ b/packages/emails/src/emails/AlmostReachedChatsLimitEmail.tsx
@@ -13,6 +13,7 @@ import { SendMailOptions } from 'nodemailer'
import { sendEmail } from '../sendEmail'
type AlmostReachedChatsLimitEmailProps = {
+ usagePercent: number
chatsLimit: number
url: string
}
@@ -26,6 +27,7 @@ const readableResetDate = firstDayOfNextMonth
.join(' ')
export const AlmostReachedChatsLimitEmail = ({
+ usagePercent,
chatsLimit,
url,
}: AlmostReachedChatsLimitEmailProps) => {
@@ -45,7 +47,8 @@ export const AlmostReachedChatsLimitEmail = ({
Your bots are chatting a lot. That's amazing. 💙
This means you've almost reached your monthly chats limit.
- You currently reached 80% of {readableChatsLimit} chats.
+ You currently reached {usagePercent}% of {readableChatsLimit}{' '}
+ chats.
This limit will be reset on {readableResetDate}.
diff --git a/packages/emails/src/emails/AlmostReachedStorageLimitEmail.tsx b/packages/emails/src/emails/AlmostReachedStorageLimitEmail.tsx
deleted file mode 100644
index e3394a16f..000000000
--- a/packages/emails/src/emails/AlmostReachedStorageLimitEmail.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import React, { ComponentProps } from 'react'
-import {
- Mjml,
- MjmlBody,
- MjmlSection,
- MjmlColumn,
- MjmlSpacer,
-} from '@faire/mjml-react'
-import { render } from '@faire/mjml-react/utils/render'
-import { Button, Head, HeroImage, Text } from '../components'
-import { SendMailOptions } from 'nodemailer'
-import { sendEmail } from '../sendEmail'
-
-type AlmostReachedStorageLimitEmailProps = {
- storageLimit: number
- url: string
-}
-
-export const AlmostReachedStorageLimitEmail = ({
- storageLimit,
- url,
-}: AlmostReachedStorageLimitEmailProps) => {
- const readableStorageLimit = `${storageLimit} GB`
-
- return (
-
-
-
-
-
-
-
-
-
-
- Your bots are working a lot. That's amazing. 🤖
-
- This means you've almost reached your storage limit. You
- currently reached 80% of your {readableStorageLimit} storage
- limit.
-
-
- Upon this limit your bots will still continue to collect new
- files, but we ask you kindly to upgrade your storage limit or
- delete existing results to free up space.
-
-
-
-
-
-
-
- )
-}
-
-export const sendAlmostReachedStorageLimitEmail = ({
- to,
- ...props
-}: Pick &
- ComponentProps) =>
- sendEmail({
- to,
- subject: "You're close to your storage limit",
- html: render().html,
- })
diff --git a/packages/emails/src/emails/ReachedChatsLimitEmail.tsx b/packages/emails/src/emails/ReachedChatsLimitEmail.tsx
deleted file mode 100644
index 7986f2ebc..000000000
--- a/packages/emails/src/emails/ReachedChatsLimitEmail.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import { ComponentProps } from 'react'
-import {
- Mjml,
- MjmlBody,
- MjmlSection,
- MjmlColumn,
- MjmlSpacer,
-} from '@faire/mjml-react'
-import { render } from '@faire/mjml-react/utils/render'
-import { Button, Head, HeroImage, Text } from '../components'
-import { parseNumberWithCommas } from '@typebot.io/lib'
-import { SendMailOptions } from 'nodemailer'
-import { sendEmail } from '../sendEmail'
-
-type ReachedChatsLimitEmailProps = {
- chatsLimit: number
- url: string
-}
-
-export const ReachedChatsLimitEmail = ({
- chatsLimit,
- url,
-}: ReachedChatsLimitEmailProps) => {
- const readableChatsLimit = parseNumberWithCommas(chatsLimit)
-
- return (
-
-
-
-
-
-
-
-
-
-
-
- It just happened, you've reached your monthly{' '}
- {readableChatsLimit} chats limit 😮
-
-
- If you'd like your bots to continue chatting with your users
- this month, then you need to upgrade your plan. 🚀
-
-
-
-
-
-
-
-
- )
-}
-
-export const sendReachedChatsLimitEmail = ({
- to,
- ...props
-}: Pick &
- ComponentProps) =>
- sendEmail({
- to,
- subject: "You've reached your chats limit",
- html: render().html,
- })
diff --git a/packages/emails/src/emails/ReachedStorageLimitEmail.tsx b/packages/emails/src/emails/ReachedStorageLimitEmail.tsx
deleted file mode 100644
index 0872725d1..000000000
--- a/packages/emails/src/emails/ReachedStorageLimitEmail.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import React, { ComponentProps } from 'react'
-import {
- Mjml,
- MjmlBody,
- MjmlSection,
- MjmlColumn,
- MjmlSpacer,
-} from '@faire/mjml-react'
-import { render } from '@faire/mjml-react/utils/render'
-import { Button, Head, HeroImage, Text } from '../components'
-import { SendMailOptions } from 'nodemailer'
-import { sendEmail } from '../sendEmail'
-
-type ReachedStorageLimitEmailProps = {
- storageLimit: number
- url: string
-}
-
-export const ReachedStorageLimitEmail = ({
- storageLimit,
- url,
-}: ReachedStorageLimitEmailProps) => {
- const readableStorageLimit = `${storageLimit} GB`
-
- return (
-
-
-
-
-
-
-
-
-
-
-
- It just happened, you've reached your {readableStorageLimit}{' '}
- storage limit 😮
-
-
- If you'd like to continue collecting files, then you need to
- upgrade your plan or remove existing results to free up space. 🚀
-
-
-
-
-
-
-
-
- )
-}
-
-export const sendReachedStorageLimitEmail = ({
- to,
- ...props
-}: Pick &
- ComponentProps) =>
- sendEmail({
- to,
- subject: "You've reached your storage limit",
- html: render().html,
- })
diff --git a/packages/emails/src/emails/index.ts b/packages/emails/src/emails/index.ts
index b2a863cb8..29742a26d 100644
--- a/packages/emails/src/emails/index.ts
+++ b/packages/emails/src/emails/index.ts
@@ -1,8 +1,5 @@
export * from './AlmostReachedChatsLimitEmail'
-export * from './AlmostReachedStorageLimitEmail'
export * from './DefaultBotNotificationEmail'
export * from './GuestInvitationEmail'
-export * from './ReachedChatsLimitEmail'
-export * from './ReachedStorageLimitEmail'
export * from './WorkspaceMemberInvitationEmail'
export * from './MagicLinkEmail'
diff --git a/packages/emails/src/preview.tsx b/packages/emails/src/preview.tsx
index a09126107..36704c411 100644
--- a/packages/emails/src/preview.tsx
+++ b/packages/emails/src/preview.tsx
@@ -3,11 +3,8 @@ import fs from 'fs'
import path from 'path'
import {
AlmostReachedChatsLimitEmail,
- AlmostReachedStorageLimitEmail,
DefaultBotNotificationEmail,
GuestInvitationEmail,
- ReachedChatsLimitEmail,
- ReachedStorageLimitEmail,
WorkspaceMemberInvitation,
} from './emails'
import { MagicLinkEmail } from './emails/MagicLinkEmail'
@@ -47,38 +44,12 @@ const createHtmlFile = () => {
path.resolve(__dirname, 'dist', 'almostReachedChatsLimit.html'),
render(
).html
)
- fs.writeFileSync(
- path.resolve(__dirname, 'dist', 'almostReachedStorageLimit.html'),
- render(
-
- ).html
- )
- fs.writeFileSync(
- path.resolve(__dirname, 'dist', 'reachedChatsLimit.html'),
- render(
-
- ).html
- )
- fs.writeFileSync(
- path.resolve(__dirname, 'dist', 'reachedStorageLimit.html'),
- render(
-
- ).html
- )
fs.writeFileSync(
path.resolve(__dirname, 'dist', 'defaultBotNotification.html'),
render(
diff --git a/packages/scripts/cleanDatabase.ts b/packages/scripts/cleanDatabase.ts
index 7d57ecd89..f8be14450 100644
--- a/packages/scripts/cleanDatabase.ts
+++ b/packages/scripts/cleanDatabase.ts
@@ -14,6 +14,7 @@ export const cleanDatabase = async () => {
if (isFirstOfMonth) {
await deleteArchivedResults()
await deleteArchivedTypebots()
+ await resetQuarantinedWorkspaces()
}
console.log('Done!')
}
@@ -118,4 +119,14 @@ const deleteExpiredVerificationTokens = async () => {
console.log(`Deleted ${count} expired verifiations tokens.`)
}
+const resetQuarantinedWorkspaces = async () =>
+ prisma.workspace.updateMany({
+ where: {
+ isQuarantined: true,
+ },
+ data: {
+ isQuarantined: false,
+ },
+ })
+
cleanDatabase().then()
diff --git a/packages/scripts/sendTotalResultsDigest.ts b/packages/scripts/sendTotalResultsDigest.ts
index b6d057871..bda3583b7 100644
--- a/packages/scripts/sendTotalResultsDigest.ts
+++ b/packages/scripts/sendTotalResultsDigest.ts
@@ -11,6 +11,22 @@ import { sendTelemetryEvents } from '@typebot.io/lib/telemetry/sendTelemetryEven
import { Workspace } from '@typebot.io/schemas'
const prisma = new PrismaClient()
+const LIMIT_EMAIL_TRIGGER_PERCENT = 0.8
+
+type WorkspaceForDigest = Pick<
+ Workspace,
+ | 'id'
+ | 'plan'
+ | 'customChatsLimit'
+ | 'customStorageLimit'
+ | 'additionalChatsIndex'
+ | 'additionalStorageIndex'
+ | 'isQuarantined'
+> & {
+ members: (Pick & {
+ user: { id: string; email: string | null }
+ })[]
+}
export const sendTotalResultsDigest = async () => {
await promptAndSetEnvironment('production')
@@ -53,12 +69,15 @@ export const sendTotalResultsDigest = async () => {
select: {
id: true,
typebots: { select: { id: true } },
- members: { select: { userId: true, role: true } },
+ members: {
+ select: { user: { select: { id: true, email: true } }, role: true },
+ },
additionalChatsIndex: true,
additionalStorageIndex: true,
customChatsLimit: true,
customStorageLimit: true,
plan: true,
+ isQuarantined: true,
},
})
@@ -71,7 +90,7 @@ export const sendTotalResultsDigest = async () => {
return workspace.members
.filter((member) => member.role !== WorkspaceRole.GUEST)
.map((member, memberIndex) => ({
- userId: member.userId,
+ userId: member.user.id,
workspace: workspace,
typebotId: result.typebotId,
totalResultsYesterday: result._count._all,
@@ -115,20 +134,13 @@ export const sendTotalResultsDigest = async () => {
}
const sendAlertIfLimitReached = async (
- workspaces: (Pick<
- Workspace,
- | 'id'
- | 'plan'
- | 'customChatsLimit'
- | 'customStorageLimit'
- | 'additionalChatsIndex'
- | 'additionalStorageIndex'
- > & { members: Pick[] })[]
+ workspaces: WorkspaceForDigest[]
): Promise => {
const events: TelemetryEvent[] = []
const taggedWorkspaces: string[] = []
for (const workspace of workspaces) {
- if (taggedWorkspaces.includes(workspace.id)) continue
+ if (taggedWorkspaces.includes(workspace.id) || workspace.isQuarantined)
+ continue
taggedWorkspaces.push(workspace.id)
const { totalChatsUsed, totalStorageUsed } = await getUsage(workspace.id)
const totalStorageUsedInGb = totalStorageUsed / 1024 / 1024 / 1024
@@ -145,7 +157,7 @@ const sendAlertIfLimitReached = async (
(member) =>
({
name: 'Workspace limit reached',
- userId: member.userId,
+ userId: member.user.id,
workspaceId: workspace.id,
data: {
totalChatsUsed,
@@ -156,7 +168,20 @@ const sendAlertIfLimitReached = async (
} satisfies TelemetryEvent)
)
)
+ continue
}
+ // if (
+ // chatsLimit > 0 &&
+ // totalChatsUsed >= chatsLimit * LIMIT_EMAIL_TRIGGER_PERCENT
+ // )
+ // await sendAlmostReachedChatsLimitEmail({
+ // to: workspace.members
+ // .map((member) => member.user.email)
+ // .filter(isDefined),
+ // usagePercent: Math.round((totalChatsUsed / chatsLimit) * 100),
+ // chatsLimit,
+ // url: `https://app.typebot.io/typebots?workspaceId=${workspace.id}`,
+ // })
}
return events
}