@wopr-network/platform-core 1.54.0 → 1.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/email/default-templates.js +49 -49
- package/dist/email/notification-templates.js +154 -111
- package/dist/email/templates.d.ts +9 -9
- package/dist/email/templates.js +61 -55
- package/dist/email/templates.test.js +1 -1
- package/package.json +1 -1
- package/src/email/default-templates.ts +56 -56
- package/src/email/notification-templates.ts +155 -107
- package/src/email/templates.test.ts +1 -1
- package/src/email/templates.ts +67 -47
|
@@ -54,7 +54,7 @@ export type TemplateName = NotificationTemplateName;
|
|
|
54
54
|
// Shared layout helpers (duplicated locally so this file is self-contained)
|
|
55
55
|
// ---------------------------------------------------------------------------
|
|
56
56
|
|
|
57
|
-
function wrapHtml(title: string, bodyContent: string): string {
|
|
57
|
+
function wrapHtml(title: string, bodyContent: string, brandName = "WOPR"): string {
|
|
58
58
|
return `<!DOCTYPE html>
|
|
59
59
|
<html>
|
|
60
60
|
<head>
|
|
@@ -69,7 +69,7 @@ function wrapHtml(title: string, bodyContent: string): string {
|
|
|
69
69
|
<table role="presentation" style="width: 600px; margin: 0 auto; background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
|
70
70
|
${bodyContent}
|
|
71
71
|
</table>
|
|
72
|
-
<p style="margin-top: 20px; color: #a0aec0; font-size: 12px;">© ${new Date().getFullYear()}
|
|
72
|
+
<p style="margin-top: 20px; color: #a0aec0; font-size: 12px;">© ${new Date().getFullYear()} ${escapeHtml(brandName)}. All rights reserved.</p>
|
|
73
73
|
</td>
|
|
74
74
|
</tr>
|
|
75
75
|
</table>
|
|
@@ -109,8 +109,13 @@ function footer(text: string): string {
|
|
|
109
109
|
</tr>`;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
function copyright(): string {
|
|
113
|
-
return `\n\n(c) ${new Date().getFullYear()}
|
|
112
|
+
function copyright(brandName = "WOPR"): string {
|
|
113
|
+
return `\n\n(c) ${new Date().getFullYear()} ${brandName}. All rights reserved.`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Extract the brand name from template data, defaulting to "WOPR". */
|
|
117
|
+
function brand(data: Record<string, unknown>): string {
|
|
118
|
+
return (data.brandName as string) || "WOPR";
|
|
114
119
|
}
|
|
115
120
|
|
|
116
121
|
// ---------------------------------------------------------------------------
|
|
@@ -118,11 +123,12 @@ function copyright(): string {
|
|
|
118
123
|
// ---------------------------------------------------------------------------
|
|
119
124
|
|
|
120
125
|
function creditsDepletedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
126
|
+
const b = brand(data);
|
|
121
127
|
const creditsUrl = (data.creditsUrl as string) || "";
|
|
122
128
|
const parts = [
|
|
123
|
-
heading(
|
|
129
|
+
heading(`Your ${escapeHtml(b)} Credits Are Depleted`),
|
|
124
130
|
paragraph(
|
|
125
|
-
|
|
131
|
+
`<p>Your ${escapeHtml(b)} credit balance has reached $0. All agent capabilities have been paused.</p>` +
|
|
126
132
|
"<p>Add credits now to resume service immediately.</p>",
|
|
127
133
|
),
|
|
128
134
|
];
|
|
@@ -130,18 +136,19 @@ function creditsDepletedTemplate(data: Record<string, unknown>): TemplateResult
|
|
|
130
136
|
parts.push(footer("Your data is preserved. Add credits to reactivate."));
|
|
131
137
|
|
|
132
138
|
return {
|
|
133
|
-
subject:
|
|
134
|
-
html: wrapHtml("Credits Depleted", parts.join("\n")),
|
|
135
|
-
text: `Your
|
|
139
|
+
subject: `Your ${b} credits are depleted — capabilities paused`,
|
|
140
|
+
html: wrapHtml("Credits Depleted", parts.join("\n"), b),
|
|
141
|
+
text: `Your ${b} Credits Are Depleted\n\nYour ${b} credit balance has reached $0. All agent capabilities have been paused.\n\nAdd credits now to resume service immediately.\n${creditsUrl ? `\nAdd credits: ${creditsUrl}\n` : ""}${copyright(b)}`,
|
|
136
142
|
};
|
|
137
143
|
}
|
|
138
144
|
|
|
139
145
|
function gracePeriodStartTemplate(data: Record<string, unknown>): TemplateResult {
|
|
146
|
+
const b = brand(data);
|
|
140
147
|
const balanceDollars = escapeHtml((data.balanceDollars as string) || "$0.00");
|
|
141
148
|
const graceDays = Number(data.graceDays) || 7;
|
|
142
149
|
const creditsUrl = (data.creditsUrl as string) || "";
|
|
143
150
|
const parts = [
|
|
144
|
-
heading(
|
|
151
|
+
heading(`Action Needed: Top Up to Keep Your ${escapeHtml(b)} Agents Running`),
|
|
145
152
|
paragraph(
|
|
146
153
|
`<p>Your current balance is <strong>${balanceDollars}</strong> and the monthly deduction could not be processed.</p>` +
|
|
147
154
|
`<p>You have a <strong>${graceDays}-day grace period</strong> to add credits before your account is suspended.</p>`,
|
|
@@ -151,16 +158,17 @@ function gracePeriodStartTemplate(data: Record<string, unknown>): TemplateResult
|
|
|
151
158
|
parts.push(footer("This is a critical notification about your account status."));
|
|
152
159
|
|
|
153
160
|
return {
|
|
154
|
-
subject:
|
|
155
|
-
html: wrapHtml("Grace Period Started", parts.join("\n")),
|
|
156
|
-
text: `Action Needed: Top Up to Keep Your
|
|
161
|
+
subject: `Action needed: top up to keep your ${b} agents running`,
|
|
162
|
+
html: wrapHtml("Grace Period Started", parts.join("\n"), b),
|
|
163
|
+
text: `Action Needed: Top Up to Keep Your ${b} Agents Running\n\nYour current balance is ${data.balanceDollars} and the monthly deduction could not be processed.\n\nYou have a ${graceDays}-day grace period to add credits before your account is suspended.\n${creditsUrl ? `\nAdd credits: ${creditsUrl}\n` : ""}${copyright(b)}`,
|
|
157
164
|
};
|
|
158
165
|
}
|
|
159
166
|
|
|
160
167
|
function gracePeriodWarningTemplate(data: Record<string, unknown>): TemplateResult {
|
|
168
|
+
const b = brand(data);
|
|
161
169
|
const creditsUrl = (data.creditsUrl as string) || "";
|
|
162
170
|
const parts = [
|
|
163
|
-
heading("Last Chance: Your
|
|
171
|
+
heading("Last Chance: Your Agents Will Be Suspended Tomorrow"),
|
|
164
172
|
paragraph(
|
|
165
173
|
"<p>Your grace period expires tomorrow. If you do not add credits, your account will be suspended.</p>" +
|
|
166
174
|
"<p>Add credits now to keep your agents running.</p>",
|
|
@@ -170,19 +178,20 @@ function gracePeriodWarningTemplate(data: Record<string, unknown>): TemplateResu
|
|
|
170
178
|
parts.push(footer("This is a critical notification about your account status."));
|
|
171
179
|
|
|
172
180
|
return {
|
|
173
|
-
subject: "Last chance: your
|
|
174
|
-
html: wrapHtml("Grace Period Warning", parts.join("\n")),
|
|
175
|
-
text: `Last Chance: Your
|
|
181
|
+
subject: "Last chance: your agents will be suspended tomorrow",
|
|
182
|
+
html: wrapHtml("Grace Period Warning", parts.join("\n"), b),
|
|
183
|
+
text: `Last Chance: Your Agents Will Be Suspended Tomorrow\n\nYour grace period expires tomorrow. If you do not add credits, your account will be suspended.\n${creditsUrl ? `\nAdd credits: ${creditsUrl}\n` : ""}${copyright(b)}`,
|
|
176
184
|
};
|
|
177
185
|
}
|
|
178
186
|
|
|
179
187
|
function autoSuspendedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
188
|
+
const b = brand(data);
|
|
180
189
|
const reason = escapeHtml((data.reason as string) || "Grace period expired");
|
|
181
190
|
const creditsUrl = (data.creditsUrl as string) || "";
|
|
182
191
|
const parts = [
|
|
183
192
|
heading("Your Account Has Been Suspended"),
|
|
184
193
|
paragraph(
|
|
185
|
-
`<p>Your
|
|
194
|
+
`<p>Your ${escapeHtml(b)} account has been automatically suspended.</p>` +
|
|
186
195
|
`<p><strong>Reason:</strong> ${reason}</p>` +
|
|
187
196
|
`<p>Add credits to reactivate your account immediately.</p>`,
|
|
188
197
|
),
|
|
@@ -192,12 +201,13 @@ function autoSuspendedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
|
192
201
|
|
|
193
202
|
return {
|
|
194
203
|
subject: "Your account has been suspended",
|
|
195
|
-
html: wrapHtml("Account Suspended", parts.join("\n")),
|
|
196
|
-
text: `Your Account Has Been Suspended\n\nReason: ${data.reason}\n\nAdd credits to reactivate your account immediately.\n${creditsUrl ? `\nAdd credits: ${creditsUrl}\n` : ""}${copyright()}`,
|
|
204
|
+
html: wrapHtml("Account Suspended", parts.join("\n"), b),
|
|
205
|
+
text: `Your Account Has Been Suspended\n\nReason: ${data.reason}\n\nAdd credits to reactivate your account immediately.\n${creditsUrl ? `\nAdd credits: ${creditsUrl}\n` : ""}${copyright(b)}`,
|
|
197
206
|
};
|
|
198
207
|
}
|
|
199
208
|
|
|
200
209
|
function autoTopupSuccessTemplate(data: Record<string, unknown>): TemplateResult {
|
|
210
|
+
const b = brand(data);
|
|
201
211
|
const amountDollars = escapeHtml((data.amountDollars as string) || "$0.00");
|
|
202
212
|
const newBalanceDollars = escapeHtml((data.newBalanceDollars as string) || "$0.00");
|
|
203
213
|
const creditsUrl = (data.creditsUrl as string) || "";
|
|
@@ -213,13 +223,15 @@ function autoTopupSuccessTemplate(data: Record<string, unknown>): TemplateResult
|
|
|
213
223
|
|
|
214
224
|
return {
|
|
215
225
|
subject: `Auto top-up: ${data.amountDollars} credits added`,
|
|
216
|
-
html: wrapHtml("Auto Top-Up Successful", parts.join("\n")),
|
|
217
|
-
text: `Auto Top-Up: ${data.amountDollars} Credits Added\n\nYour auto top-up was successful. ${data.amountDollars} in credits has been added.\n\nYour new balance is ${data.newBalanceDollars}.\n${creditsUrl ? `\nView credits: ${creditsUrl}\n` : ""}${copyright()}`,
|
|
226
|
+
html: wrapHtml("Auto Top-Up Successful", parts.join("\n"), b),
|
|
227
|
+
text: `Auto Top-Up: ${data.amountDollars} Credits Added\n\nYour auto top-up was successful. ${data.amountDollars} in credits has been added.\n\nYour new balance is ${data.newBalanceDollars}.\n${creditsUrl ? `\nView credits: ${creditsUrl}\n` : ""}${copyright(b)}`,
|
|
218
228
|
};
|
|
219
229
|
}
|
|
220
230
|
|
|
221
231
|
function autoTopupFailedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
232
|
+
const b = brand(data);
|
|
222
233
|
const creditsUrl = (data.creditsUrl as string) || "";
|
|
234
|
+
const supportEmail = (data.supportEmail as string) || "support@wopr.bot";
|
|
223
235
|
const parts = [
|
|
224
236
|
heading("Auto Top-Up Failed"),
|
|
225
237
|
paragraph(
|
|
@@ -228,12 +240,12 @@ function autoTopupFailedTemplate(data: Record<string, unknown>): TemplateResult
|
|
|
228
240
|
),
|
|
229
241
|
];
|
|
230
242
|
if (creditsUrl) parts.push(button(creditsUrl, "Add Credits"));
|
|
231
|
-
parts.push(footer(
|
|
243
|
+
parts.push(footer(`If you need help, contact ${escapeHtml(supportEmail)}.`));
|
|
232
244
|
|
|
233
245
|
return {
|
|
234
246
|
subject: "Auto top-up failed — update your payment method",
|
|
235
|
-
html: wrapHtml("Auto Top-Up Failed", parts.join("\n")),
|
|
236
|
-
text: `Auto Top-Up Failed\n\nYour auto top-up failed. We were unable to charge your payment method.\n\nPlease update your payment method or add credits manually to avoid service interruption.\n${creditsUrl ? `\nAdd credits: ${creditsUrl}\n` : ""}${copyright()}`,
|
|
247
|
+
html: wrapHtml("Auto Top-Up Failed", parts.join("\n"), b),
|
|
248
|
+
text: `Auto Top-Up Failed\n\nYour auto top-up failed. We were unable to charge your payment method.\n\nPlease update your payment method or add credits manually to avoid service interruption.\n${creditsUrl ? `\nAdd credits: ${creditsUrl}\n` : ""}${copyright(b)}`,
|
|
237
249
|
};
|
|
238
250
|
}
|
|
239
251
|
|
|
@@ -247,39 +259,43 @@ function cryptoPaymentConfirmedTemplate(data: Record<string, unknown>): Template
|
|
|
247
259
|
`<p>Your new balance is <strong>${newBalanceDollars}</strong>.</p>`,
|
|
248
260
|
),
|
|
249
261
|
];
|
|
250
|
-
|
|
262
|
+
const b = brand(data);
|
|
263
|
+
parts.push(footer(`Thank you for supporting ${escapeHtml(b)}!`));
|
|
251
264
|
|
|
252
265
|
return {
|
|
253
266
|
subject: `Crypto payment confirmed: ${data.amountDollars} credits added`,
|
|
254
|
-
html: wrapHtml("Crypto Payment Confirmed", parts.join("\n")),
|
|
255
|
-
text: `Crypto Payment Confirmed: ${data.amountDollars} Credits Added\n\nYour crypto payment has been confirmed. ${data.amountDollars} in credits has been added.\n\nYour new balance is ${data.newBalanceDollars}.\n${copyright()}`,
|
|
267
|
+
html: wrapHtml("Crypto Payment Confirmed", parts.join("\n"), b),
|
|
268
|
+
text: `Crypto Payment Confirmed: ${data.amountDollars} Credits Added\n\nYour crypto payment has been confirmed. ${data.amountDollars} in credits has been added.\n\nYour new balance is ${data.newBalanceDollars}.\n${copyright(b)}`,
|
|
256
269
|
};
|
|
257
270
|
}
|
|
258
271
|
|
|
259
272
|
function adminSuspendedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
273
|
+
const b = brand(data);
|
|
260
274
|
const reason = escapeHtml((data.reason as string) || "Policy violation");
|
|
275
|
+
const supportEmail = (data.supportEmail as string) || "support@wopr.bot";
|
|
261
276
|
const parts = [
|
|
262
277
|
heading("Your Account Has Been Suspended"),
|
|
263
278
|
paragraph(
|
|
264
|
-
`<p>Your
|
|
279
|
+
`<p>Your ${escapeHtml(b)} account has been suspended by an administrator.</p>` +
|
|
265
280
|
`<p><strong>Reason:</strong> ${reason}</p>` +
|
|
266
|
-
`<p>If you believe this is an error, please contact
|
|
281
|
+
`<p>If you believe this is an error, please contact ${escapeHtml(supportEmail)}.</p>`,
|
|
267
282
|
),
|
|
268
283
|
];
|
|
269
|
-
parts.push(footer(
|
|
284
|
+
parts.push(footer(`Contact ${escapeHtml(supportEmail)} if you have questions.`));
|
|
270
285
|
|
|
271
286
|
return {
|
|
272
287
|
subject: "Your account has been suspended",
|
|
273
|
-
html: wrapHtml("Account Suspended", parts.join("\n")),
|
|
274
|
-
text: `Your Account Has Been Suspended\n\nReason: ${data.reason}\n\nIf you believe this is an error, please contact
|
|
288
|
+
html: wrapHtml("Account Suspended", parts.join("\n"), b),
|
|
289
|
+
text: `Your Account Has Been Suspended\n\nReason: ${data.reason}\n\nIf you believe this is an error, please contact ${supportEmail}.\n${copyright(b)}`,
|
|
275
290
|
};
|
|
276
291
|
}
|
|
277
292
|
|
|
278
|
-
function adminReactivatedTemplate(
|
|
293
|
+
function adminReactivatedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
294
|
+
const b = brand(data);
|
|
279
295
|
const parts = [
|
|
280
296
|
heading("Your Account Has Been Reactivated"),
|
|
281
297
|
paragraph(
|
|
282
|
-
|
|
298
|
+
`<p>Your ${escapeHtml(b)} account has been reactivated. You now have full access to all services.</p>` +
|
|
283
299
|
"<p>Your agents and channels are ready to use.</p>",
|
|
284
300
|
),
|
|
285
301
|
];
|
|
@@ -287,55 +303,59 @@ function adminReactivatedTemplate(_data: Record<string, unknown>): TemplateResul
|
|
|
287
303
|
|
|
288
304
|
return {
|
|
289
305
|
subject: "Your account has been reactivated",
|
|
290
|
-
html: wrapHtml("Account Reactivated", parts.join("\n")),
|
|
291
|
-
text: `Your Account Has Been Reactivated\n\nYour
|
|
306
|
+
html: wrapHtml("Account Reactivated", parts.join("\n"), b),
|
|
307
|
+
text: `Your Account Has Been Reactivated\n\nYour ${b} account has been reactivated. You now have full access to all services.\n${copyright(b)}`,
|
|
292
308
|
};
|
|
293
309
|
}
|
|
294
310
|
|
|
295
311
|
function creditsGrantedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
312
|
+
const b = brand(data);
|
|
296
313
|
const amountDollars = escapeHtml((data.amountDollars as string) || "$0.00");
|
|
297
314
|
const reason = escapeHtml((data.reason as string) || "");
|
|
298
315
|
const parts = [
|
|
299
316
|
heading(`You Received ${amountDollars} in Credits`),
|
|
300
317
|
paragraph(
|
|
301
|
-
`<p><strong>${amountDollars}</strong> in credits has been added to your
|
|
318
|
+
`<p><strong>${amountDollars}</strong> in credits has been added to your ${escapeHtml(b)} account.</p>` +
|
|
302
319
|
(reason ? `<p><strong>Note:</strong> ${reason}</p>` : ""),
|
|
303
320
|
),
|
|
304
321
|
];
|
|
305
|
-
parts.push(footer(
|
|
322
|
+
parts.push(footer(`Thank you for using ${escapeHtml(b)}!`));
|
|
306
323
|
|
|
307
324
|
return {
|
|
308
325
|
subject: `You received ${data.amountDollars} in credits`,
|
|
309
|
-
html: wrapHtml("Credits Granted", parts.join("\n")),
|
|
310
|
-
text: `You Received ${data.amountDollars} in Credits\n\n${data.amountDollars} has been added to your account.${reason ? `\n\nNote: ${data.reason}` : ""}\n${copyright()}`,
|
|
326
|
+
html: wrapHtml("Credits Granted", parts.join("\n"), b),
|
|
327
|
+
text: `You Received ${data.amountDollars} in Credits\n\n${data.amountDollars} has been added to your account.${reason ? `\n\nNote: ${data.reason}` : ""}\n${copyright(b)}`,
|
|
311
328
|
};
|
|
312
329
|
}
|
|
313
330
|
|
|
314
331
|
function roleChangedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
332
|
+
const b = brand(data);
|
|
315
333
|
const newRole = escapeHtml((data.newRole as string) || "");
|
|
334
|
+
const supportEmail = (data.supportEmail as string) || "support@wopr.bot";
|
|
316
335
|
const parts = [
|
|
317
336
|
heading("Your Role Has Been Updated"),
|
|
318
337
|
paragraph(
|
|
319
|
-
`<p>Your role on the
|
|
338
|
+
`<p>Your role on the ${escapeHtml(b)} platform has been updated to <strong>${newRole}</strong>.</p>` +
|
|
320
339
|
"<p>Your new permissions are now active.</p>",
|
|
321
340
|
),
|
|
322
341
|
];
|
|
323
|
-
parts.push(footer(
|
|
342
|
+
parts.push(footer(`If you did not expect this change, contact ${escapeHtml(supportEmail)}.`));
|
|
324
343
|
|
|
325
344
|
return {
|
|
326
345
|
subject: "Your role has been updated",
|
|
327
|
-
html: wrapHtml("Role Changed", parts.join("\n")),
|
|
328
|
-
text: `Your Role Has Been Updated\n\nYour role has been updated to ${data.newRole}.\n${copyright()}`,
|
|
346
|
+
html: wrapHtml("Role Changed", parts.join("\n"), b),
|
|
347
|
+
text: `Your Role Has Been Updated\n\nYour role has been updated to ${data.newRole}.\n${copyright(b)}`,
|
|
329
348
|
};
|
|
330
349
|
}
|
|
331
350
|
|
|
332
351
|
function teamInviteTemplate(data: Record<string, unknown>): TemplateResult {
|
|
352
|
+
const b = brand(data);
|
|
333
353
|
const tenantName = escapeHtml((data.tenantName as string) || "a tenant");
|
|
334
354
|
const inviteUrl = (data.inviteUrl as string) || "";
|
|
335
355
|
const parts = [
|
|
336
356
|
heading(`You've Been Invited to Join ${tenantName}`),
|
|
337
357
|
paragraph(
|
|
338
|
-
`<p>You've been invited to join <strong>${tenantName}</strong> on the
|
|
358
|
+
`<p>You've been invited to join <strong>${tenantName}</strong> on the ${escapeHtml(b)} platform.</p>` +
|
|
339
359
|
"<p>Click below to accept the invitation.</p>",
|
|
340
360
|
),
|
|
341
361
|
];
|
|
@@ -344,15 +364,16 @@ function teamInviteTemplate(data: Record<string, unknown>): TemplateResult {
|
|
|
344
364
|
|
|
345
365
|
return {
|
|
346
366
|
subject: `You've been invited to join ${data.tenantName}`,
|
|
347
|
-
html: wrapHtml("Team Invite", parts.join("\n")),
|
|
348
|
-
text: `You've Been Invited to Join ${data.tenantName}\n\n${inviteUrl ? `Accept: ${inviteUrl}\n` : ""}${copyright()}`,
|
|
367
|
+
html: wrapHtml("Team Invite", parts.join("\n"), b),
|
|
368
|
+
text: `You've Been Invited to Join ${data.tenantName}\n\n${inviteUrl ? `Accept: ${inviteUrl}\n` : ""}${copyright(b)}`,
|
|
349
369
|
};
|
|
350
370
|
}
|
|
351
371
|
|
|
352
372
|
function agentCreatedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
373
|
+
const b = brand(data);
|
|
353
374
|
const agentName = escapeHtml((data.agentName as string) || "your agent");
|
|
354
375
|
const parts = [
|
|
355
|
-
heading(`Your
|
|
376
|
+
heading(`Your ${escapeHtml(b)} ${agentName} Is Ready`),
|
|
356
377
|
paragraph(
|
|
357
378
|
`<p>Your new agent <strong>${agentName}</strong> has been created and is ready to use.</p>` +
|
|
358
379
|
"<p>Connect it to a channel to start receiving and sending messages.</p>",
|
|
@@ -361,13 +382,14 @@ function agentCreatedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
|
361
382
|
parts.push(footer("Happy building!"));
|
|
362
383
|
|
|
363
384
|
return {
|
|
364
|
-
subject: `Your
|
|
365
|
-
html: wrapHtml("Agent Created", parts.join("\n")),
|
|
366
|
-
text: `Your
|
|
385
|
+
subject: `Your ${b} ${data.agentName} is ready`,
|
|
386
|
+
html: wrapHtml("Agent Created", parts.join("\n"), b),
|
|
387
|
+
text: `Your ${b} ${data.agentName} Is Ready\n\nYour new agent has been created and is ready to use.\n${copyright(b)}`,
|
|
367
388
|
};
|
|
368
389
|
}
|
|
369
390
|
|
|
370
391
|
function channelConnectedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
392
|
+
const b = brand(data);
|
|
371
393
|
const channelName = escapeHtml((data.channelName as string) || "A channel");
|
|
372
394
|
const agentName = escapeHtml((data.agentName as string) || "your agent");
|
|
373
395
|
const parts = [
|
|
@@ -381,12 +403,13 @@ function channelConnectedTemplate(data: Record<string, unknown>): TemplateResult
|
|
|
381
403
|
|
|
382
404
|
return {
|
|
383
405
|
subject: `${data.channelName} connected to ${data.agentName}`,
|
|
384
|
-
html: wrapHtml("Channel Connected", parts.join("\n")),
|
|
385
|
-
text: `${data.channelName} Connected to ${data.agentName}\n\n${data.channelName} has been successfully connected to ${data.agentName}.\n${copyright()}`,
|
|
406
|
+
html: wrapHtml("Channel Connected", parts.join("\n"), b),
|
|
407
|
+
text: `${data.channelName} Connected to ${data.agentName}\n\n${data.channelName} has been successfully connected to ${data.agentName}.\n${copyright(b)}`,
|
|
386
408
|
};
|
|
387
409
|
}
|
|
388
410
|
|
|
389
411
|
function channelDisconnectedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
412
|
+
const b = brand(data);
|
|
390
413
|
const channelName = escapeHtml((data.channelName as string) || "A channel");
|
|
391
414
|
const agentName = escapeHtml((data.agentName as string) || "your agent");
|
|
392
415
|
const reason = escapeHtml((data.reason as string) || "");
|
|
@@ -402,14 +425,16 @@ function channelDisconnectedTemplate(data: Record<string, unknown>): TemplateRes
|
|
|
402
425
|
|
|
403
426
|
return {
|
|
404
427
|
subject: `${data.channelName} disconnected from ${data.agentName}`,
|
|
405
|
-
html: wrapHtml("Channel Disconnected", parts.join("\n")),
|
|
406
|
-
text: `${data.channelName} Disconnected from ${data.agentName}\n\n${reason ? `Reason: ${data.reason}\n\n` : ""}Reconnect from your dashboard to restore service.\n${copyright()}`,
|
|
428
|
+
html: wrapHtml("Channel Disconnected", parts.join("\n"), b),
|
|
429
|
+
text: `${data.channelName} Disconnected from ${data.agentName}\n\n${reason ? `Reason: ${data.reason}\n\n` : ""}Reconnect from your dashboard to restore service.\n${copyright(b)}`,
|
|
407
430
|
};
|
|
408
431
|
}
|
|
409
432
|
|
|
410
433
|
function agentSuspendedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
434
|
+
const b = brand(data);
|
|
411
435
|
const agentName = escapeHtml((data.agentName as string) || "Your agent");
|
|
412
436
|
const reason = escapeHtml((data.reason as string) || "");
|
|
437
|
+
const supportEmail = (data.supportEmail as string) || "support@wopr.bot";
|
|
413
438
|
const parts = [
|
|
414
439
|
heading(`${agentName} Has Been Paused`),
|
|
415
440
|
paragraph(
|
|
@@ -417,41 +442,45 @@ function agentSuspendedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
|
417
442
|
(reason ? `<p><strong>Reason:</strong> ${reason}</p>` : ""),
|
|
418
443
|
),
|
|
419
444
|
];
|
|
420
|
-
parts.push(footer(
|
|
445
|
+
parts.push(footer(`Contact ${escapeHtml(supportEmail)} if you have questions.`));
|
|
421
446
|
|
|
422
447
|
return {
|
|
423
448
|
subject: `${data.agentName} has been paused`,
|
|
424
|
-
html: wrapHtml("Agent Paused", parts.join("\n")),
|
|
425
|
-
text: `${data.agentName} Has Been Paused\n\n${reason ? `Reason: ${data.reason}\n` : ""}${copyright()}`,
|
|
449
|
+
html: wrapHtml("Agent Paused", parts.join("\n"), b),
|
|
450
|
+
text: `${data.agentName} Has Been Paused\n\n${reason ? `Reason: ${data.reason}\n` : ""}${copyright(b)}`,
|
|
426
451
|
};
|
|
427
452
|
}
|
|
428
453
|
|
|
429
454
|
function accountDeletionRequestedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
455
|
+
const b = brand(data);
|
|
430
456
|
const email = escapeHtml((data.email as string) || "");
|
|
431
457
|
const deleteAfterDate = escapeHtml((data.deleteAfterDate as string) || "");
|
|
432
458
|
const cancelUrl = (data.cancelUrl as string) || "";
|
|
459
|
+
const supportEmail = (data.supportEmail as string) || "support@wopr.bot";
|
|
433
460
|
|
|
434
461
|
const parts = [
|
|
435
462
|
heading("Account Deletion Requested"),
|
|
436
463
|
paragraph(
|
|
437
464
|
`<p>Hi <strong>${email}</strong>,</p>` +
|
|
438
|
-
`<p>We've received your request to delete your
|
|
465
|
+
`<p>We've received your request to delete your ${escapeHtml(b)} account and all associated data.</p>` +
|
|
439
466
|
`<p>Your account will be permanently deleted on <strong>${deleteAfterDate}</strong>. Until then, you can cancel this request and keep your account.</p>` +
|
|
440
467
|
`<p>After that date, all your data will be permanently and irreversibly removed, including bots, conversation history, credit records, and plugin configurations.</p>`,
|
|
441
468
|
),
|
|
442
469
|
];
|
|
443
470
|
if (cancelUrl) parts.push(button(cancelUrl, "Cancel Deletion", "#22c55e"));
|
|
444
|
-
parts.push(footer(
|
|
471
|
+
parts.push(footer(`If you did not request this, please contact ${escapeHtml(supportEmail)} immediately.`));
|
|
445
472
|
|
|
446
473
|
return {
|
|
447
|
-
subject:
|
|
448
|
-
html: wrapHtml("Account Deletion Requested", parts.join("\n")),
|
|
449
|
-
text: `Account Deletion Requested\n\nHi ${data.email as string},\n\nWe've received your request to delete your
|
|
474
|
+
subject: `Your ${b} account deletion request`,
|
|
475
|
+
html: wrapHtml("Account Deletion Requested", parts.join("\n"), b),
|
|
476
|
+
text: `Account Deletion Requested\n\nHi ${data.email as string},\n\nWe've received your request to delete your ${b} account and all associated data.\n\nYour account will be permanently deleted on ${data.deleteAfterDate as string}. Until then, you can cancel this request.\n\nAfter that date, all your data will be permanently and irreversibly removed.\n${cancelUrl ? `\nCancel deletion: ${cancelUrl}\n` : ""}If you did not request this, please contact ${supportEmail} immediately.${copyright(b)}`,
|
|
450
477
|
};
|
|
451
478
|
}
|
|
452
479
|
|
|
453
480
|
function accountDeletionCancelledTemplate(data: Record<string, unknown>): TemplateResult {
|
|
481
|
+
const b = brand(data);
|
|
454
482
|
const email = escapeHtml((data.email as string) || "");
|
|
483
|
+
const supportEmail = (data.supportEmail as string) || "support@wopr.bot";
|
|
455
484
|
|
|
456
485
|
const parts = [
|
|
457
486
|
heading("Account Deletion Cancelled"),
|
|
@@ -460,38 +489,40 @@ function accountDeletionCancelledTemplate(data: Record<string, unknown>): Templa
|
|
|
460
489
|
`<p>Your account deletion request has been cancelled. Your account and all data remain intact.</p>` +
|
|
461
490
|
`<p>No further action is needed.</p>`,
|
|
462
491
|
),
|
|
463
|
-
footer(
|
|
492
|
+
footer(`If you didn't cancel this, please contact ${escapeHtml(supportEmail)}.`),
|
|
464
493
|
];
|
|
465
494
|
|
|
466
495
|
return {
|
|
467
|
-
subject:
|
|
468
|
-
html: wrapHtml("Account Deletion Cancelled", parts.join("\n")),
|
|
469
|
-
text: `Account Deletion Cancelled\n\nHi ${data.email as string},\n\nYour account deletion request has been cancelled. Your account and all data remain intact.\n\nNo further action is needed.${copyright()}`,
|
|
496
|
+
subject: `Your ${b} account deletion has been cancelled`,
|
|
497
|
+
html: wrapHtml("Account Deletion Cancelled", parts.join("\n"), b),
|
|
498
|
+
text: `Account Deletion Cancelled\n\nHi ${data.email as string},\n\nYour account deletion request has been cancelled. Your account and all data remain intact.\n\nNo further action is needed.${copyright(b)}`,
|
|
470
499
|
};
|
|
471
500
|
}
|
|
472
501
|
|
|
473
502
|
function accountDeletionCompletedTemplate(data: Record<string, unknown>): TemplateResult {
|
|
503
|
+
const b = brand(data);
|
|
474
504
|
const email = escapeHtml((data.email as string) || "");
|
|
475
505
|
|
|
476
506
|
const parts = [
|
|
477
507
|
heading("Your Account Has Been Deleted"),
|
|
478
508
|
paragraph(
|
|
479
509
|
`<p>Hi <strong>${email}</strong>,</p>` +
|
|
480
|
-
`<p>Your
|
|
510
|
+
`<p>Your ${escapeHtml(b)} account and all associated data have been permanently deleted as requested.</p>` +
|
|
481
511
|
`<p>This includes all bots, conversation history, credit records, billing data, and plugin configurations.</p>` +
|
|
482
|
-
`<p>If you'd like to use
|
|
512
|
+
`<p>If you'd like to use ${escapeHtml(b)} again in the future, you're welcome to create a new account.</p>`,
|
|
483
513
|
),
|
|
484
|
-
footer(
|
|
514
|
+
footer(`Thank you for using ${escapeHtml(b)}. We're sorry to see you go.`),
|
|
485
515
|
];
|
|
486
516
|
|
|
487
517
|
return {
|
|
488
|
-
subject:
|
|
489
|
-
html: wrapHtml("Account Deleted", parts.join("\n")),
|
|
490
|
-
text: `Your Account Has Been Deleted\n\nHi ${data.email as string},\n\nYour
|
|
518
|
+
subject: `Your ${b} account has been deleted`,
|
|
519
|
+
html: wrapHtml("Account Deleted", parts.join("\n"), b),
|
|
520
|
+
text: `Your Account Has Been Deleted\n\nHi ${data.email as string},\n\nYour ${b} account and all associated data have been permanently deleted as requested.\n\nThis includes all bots, conversation history, credit records, billing data, and plugin configurations.\n\nIf you'd like to use ${b} again in the future, you're welcome to create a new account.${copyright(b)}`,
|
|
491
521
|
};
|
|
492
522
|
}
|
|
493
523
|
|
|
494
524
|
function dividendWeeklyDigestTemplate(data: Record<string, unknown>): TemplateResult {
|
|
525
|
+
const b = brand(data);
|
|
495
526
|
const weeklyTotal = escapeHtml((data.weeklyTotalDollars as string) || "$0.00");
|
|
496
527
|
const lifetimeTotal = escapeHtml((data.lifetimeTotalDollars as string) || "$0.00");
|
|
497
528
|
const distributionCount = Number(data.distributionCount) || 0;
|
|
@@ -505,7 +536,7 @@ function dividendWeeklyDigestTemplate(data: Record<string, unknown>): TemplateRe
|
|
|
505
536
|
const poolAvgDollars = `$${(poolAvgCents / 100).toFixed(2)}`;
|
|
506
537
|
|
|
507
538
|
const parts = [
|
|
508
|
-
heading(
|
|
539
|
+
heading(`${escapeHtml(b)} Paid You ${weeklyTotal} This Week`),
|
|
509
540
|
paragraph(
|
|
510
541
|
`<p>Here's your weekly dividend summary for <strong>${weekStart} – ${weekEnd}</strong>.</p>` +
|
|
511
542
|
`<table style="width: 100%; border-collapse: collapse; margin: 16px 0;">` +
|
|
@@ -533,10 +564,10 @@ function dividendWeeklyDigestTemplate(data: Record<string, unknown>): TemplateRe
|
|
|
533
564
|
}
|
|
534
565
|
|
|
535
566
|
return {
|
|
536
|
-
subject:
|
|
537
|
-
html: wrapHtml("Weekly Dividend Digest", parts.join("\n")),
|
|
567
|
+
subject: `${b} paid you ${data.weeklyTotalDollars as string} this week`,
|
|
568
|
+
html: wrapHtml("Weekly Dividend Digest", parts.join("\n"), b),
|
|
538
569
|
text:
|
|
539
|
-
|
|
570
|
+
`${b} Paid You ${data.weeklyTotalDollars as string} This Week\n\n` +
|
|
540
571
|
`Weekly summary for ${data.weekStartDate as string} – ${data.weekEndDate as string}:\n\n` +
|
|
541
572
|
`This week's dividends: ${data.weeklyTotalDollars as string}\n` +
|
|
542
573
|
`Days with distributions: ${distributionCount} of 7\n` +
|
|
@@ -546,22 +577,23 @@ function dividendWeeklyDigestTemplate(data: Record<string, unknown>): TemplateRe
|
|
|
546
577
|
`Next dividend: ${data.nextDividendDate as string}\n\n` +
|
|
547
578
|
`Community dividends are distributed daily from platform revenue.` +
|
|
548
579
|
(unsubscribeUrl ? `\n\nUnsubscribe: ${unsubscribeUrl}` : "") +
|
|
549
|
-
copyright(),
|
|
580
|
+
copyright(b),
|
|
550
581
|
};
|
|
551
582
|
}
|
|
552
583
|
|
|
553
584
|
function customTemplate(data: Record<string, unknown>): TemplateResult {
|
|
554
|
-
const
|
|
585
|
+
const b = brand(data);
|
|
586
|
+
const subject = (data.subject as string) || `Message from ${b}`;
|
|
555
587
|
const rawBody = (data.bodyText as string) || "";
|
|
556
588
|
const escapedBody = escapeHtml(rawBody).replace(/\n/g, "<br>\n");
|
|
557
589
|
|
|
558
|
-
const parts = [heading(
|
|
559
|
-
parts.push(footer(
|
|
590
|
+
const parts = [heading(`Message from ${escapeHtml(b)}`), paragraph(`<p>${escapedBody}</p>`)];
|
|
591
|
+
parts.push(footer(`This is an administrative message from ${escapeHtml(b)}.`));
|
|
560
592
|
|
|
561
593
|
return {
|
|
562
594
|
subject,
|
|
563
|
-
html: wrapHtml(escapeHtml(subject), parts.join("\n")),
|
|
564
|
-
text: `${rawBody}\n${copyright()}`,
|
|
595
|
+
html: wrapHtml(escapeHtml(subject), parts.join("\n"), b),
|
|
596
|
+
text: `${rawBody}\n${copyright(b)}`,
|
|
565
597
|
};
|
|
566
598
|
}
|
|
567
599
|
|
|
@@ -610,6 +642,7 @@ export function renderNotificationTemplate(template: TemplateName, data: Record<
|
|
|
610
642
|
case "agent-suspended":
|
|
611
643
|
return agentSuspendedTemplate(data);
|
|
612
644
|
case "affiliate-credit-match": {
|
|
645
|
+
const b = brand(data);
|
|
613
646
|
const amountDollars = escapeHtml((data.amountDollars as string) || "$0.00");
|
|
614
647
|
const creditsUrl = (data.creditsUrl as string) || "";
|
|
615
648
|
const parts = [
|
|
@@ -619,14 +652,15 @@ export function renderNotificationTemplate(template: TemplateName, data: Record<
|
|
|
619
652
|
),
|
|
620
653
|
];
|
|
621
654
|
if (creditsUrl) parts.push(button(creditsUrl, "View Credit Balance"));
|
|
622
|
-
parts.push(footer(
|
|
655
|
+
parts.push(footer(`Thank you for spreading the word about ${escapeHtml(b)}!`));
|
|
623
656
|
return {
|
|
624
657
|
subject: `You earned ${data.amountDollars as string} in affiliate credits!`,
|
|
625
|
-
html: wrapHtml("Affiliate Credits Earned", parts.join("\n")),
|
|
626
|
-
text: `You Earned Affiliate Credits!\n\nA user you referred just made their first purchase, and you've been credited ${data.amountDollars as string}.\n${creditsUrl ? `\nView your balance: ${creditsUrl}\n` : ""}${copyright()}`,
|
|
658
|
+
html: wrapHtml("Affiliate Credits Earned", parts.join("\n"), b),
|
|
659
|
+
text: `You Earned Affiliate Credits!\n\nA user you referred just made their first purchase, and you've been credited ${data.amountDollars as string}.\n${creditsUrl ? `\nView your balance: ${creditsUrl}\n` : ""}${copyright(b)}`,
|
|
627
660
|
};
|
|
628
661
|
}
|
|
629
662
|
case "spend-alert": {
|
|
663
|
+
const b = brand(data);
|
|
630
664
|
const currentSpend = escapeHtml(String(data.currentSpendDollars ?? "$0.00"));
|
|
631
665
|
const alertAt = escapeHtml(String(data.alertAtDollars ?? "$0.00"));
|
|
632
666
|
const creditsUrl = (data.creditsUrl as string) || "";
|
|
@@ -642,12 +676,12 @@ export function renderNotificationTemplate(template: TemplateName, data: Record<
|
|
|
642
676
|
parts.push(footer("This alert fires once per day when your spend exceeds your configured threshold."));
|
|
643
677
|
return {
|
|
644
678
|
subject: `Spending alert: you've reached your ${data.alertAtDollars as string} threshold`,
|
|
645
|
-
html: wrapHtml("Spending Alert", parts.join("\n")),
|
|
679
|
+
html: wrapHtml("Spending Alert", parts.join("\n"), b),
|
|
646
680
|
text:
|
|
647
681
|
`Spending Alert: Threshold Reached\n\nYour monthly spend has reached ${data.currentSpendDollars as string}, ` +
|
|
648
682
|
`crossing your alert threshold of ${data.alertAtDollars as string}.\n` +
|
|
649
683
|
(creditsUrl ? `\nReview spending: ${creditsUrl}\n` : "") +
|
|
650
|
-
copyright(),
|
|
684
|
+
copyright(b),
|
|
651
685
|
};
|
|
652
686
|
}
|
|
653
687
|
case "custom":
|
|
@@ -661,6 +695,7 @@ export function renderNotificationTemplate(template: TemplateName, data: Record<
|
|
|
661
695
|
case "account-deletion-completed":
|
|
662
696
|
return accountDeletionCompletedTemplate(data);
|
|
663
697
|
case "fleet-update-available": {
|
|
698
|
+
const b = brand(data);
|
|
664
699
|
const version = escapeHtml((data.version as string) || "");
|
|
665
700
|
const changelogDate = escapeHtml((data.changelogDate as string) || "");
|
|
666
701
|
const changelogSummary = escapeHtml((data.changelogSummary as string) || "");
|
|
@@ -679,11 +714,12 @@ export function renderNotificationTemplate(template: TemplateName, data: Record<
|
|
|
679
714
|
faParts.push(footer("Review the changelog and update when ready."));
|
|
680
715
|
return {
|
|
681
716
|
subject: `Fleet update available: ${data.version}`,
|
|
682
|
-
html: wrapHtml("Fleet Update Available", faParts.join("\n")),
|
|
683
|
-
text: `Fleet Update Available: ${data.version}\n\nA new version ${data.version} is available for your fleet.\n${changelogDate ? `Released: ${data.changelogDate}\n` : ""}${changelogSummary ? `Changelog: ${data.changelogSummary}\n` : ""}${fleetUrl ? `\nFleet dashboard: ${fleetUrl}\n` : ""}${copyright()}`,
|
|
717
|
+
html: wrapHtml("Fleet Update Available", faParts.join("\n"), b),
|
|
718
|
+
text: `Fleet Update Available: ${data.version}\n\nA new version ${data.version} is available for your fleet.\n${changelogDate ? `Released: ${data.changelogDate}\n` : ""}${changelogSummary ? `Changelog: ${data.changelogSummary}\n` : ""}${fleetUrl ? `\nFleet dashboard: ${fleetUrl}\n` : ""}${copyright(b)}`,
|
|
684
719
|
};
|
|
685
720
|
}
|
|
686
721
|
case "fleet-update-complete": {
|
|
722
|
+
const b = brand(data);
|
|
687
723
|
const fcVersion = escapeHtml((data.version as string) || "");
|
|
688
724
|
const succeeded = Number(data.succeeded) || 0;
|
|
689
725
|
const failed = Number(data.failed) || 0;
|
|
@@ -714,27 +750,31 @@ export function renderNotificationTemplate(template: TemplateName, data: Record<
|
|
|
714
750
|
);
|
|
715
751
|
return {
|
|
716
752
|
subject: `Fleet updated to ${data.version} \u2014 ${statusText}`,
|
|
717
|
-
html: wrapHtml("Fleet Update Complete", fcParts.join("\n")),
|
|
718
|
-
text: `Fleet Updated to ${data.version}\n\nSucceeded: ${succeeded}\nFailed: ${failed}\nTotal: ${total}\n${failed > 0 ? "\nSome instances failed to update.\n" : ""}${fleetUrl2 ? `\nFleet dashboard: ${fleetUrl2}\n` : ""}${copyright()}`,
|
|
753
|
+
html: wrapHtml("Fleet Update Complete", fcParts.join("\n"), b),
|
|
754
|
+
text: `Fleet Updated to ${data.version}\n\nSucceeded: ${succeeded}\nFailed: ${failed}\nTotal: ${total}\n${failed > 0 ? "\nSome instances failed to update.\n" : ""}${fleetUrl2 ? `\nFleet dashboard: ${fleetUrl2}\n` : ""}${copyright(b)}`,
|
|
719
755
|
};
|
|
720
756
|
}
|
|
721
|
-
case "low-balance":
|
|
757
|
+
case "low-balance": {
|
|
758
|
+
const b = brand(data);
|
|
722
759
|
return {
|
|
723
|
-
subject:
|
|
760
|
+
subject: `Your ${b} credits are running low`,
|
|
724
761
|
html: wrapHtml(
|
|
725
762
|
"Low Balance",
|
|
726
763
|
[
|
|
727
|
-
heading(
|
|
764
|
+
heading(`Your ${escapeHtml(b)} Credits Are Running Low`),
|
|
728
765
|
paragraph(
|
|
729
766
|
`<p>Your balance is <strong>${escapeHtml((data.balanceDollars as string) || "$0.00")}</strong>. Top up to keep your agents running.</p>`,
|
|
730
767
|
),
|
|
731
768
|
...(data.creditsUrl ? [button(data.creditsUrl as string, "Buy Credits")] : []),
|
|
732
769
|
footer("This is an automated billing notification."),
|
|
733
770
|
].join("\n"),
|
|
771
|
+
b,
|
|
734
772
|
),
|
|
735
|
-
text: `Your
|
|
773
|
+
text: `Your ${b} Credits Are Running Low\n\nBalance: ${data.balanceDollars}\n${data.creditsUrl ? `\nBuy credits: ${data.creditsUrl}\n` : ""}${copyright(b)}`,
|
|
736
774
|
};
|
|
737
|
-
|
|
775
|
+
}
|
|
776
|
+
case "credit-purchase-receipt": {
|
|
777
|
+
const b = brand(data);
|
|
738
778
|
return {
|
|
739
779
|
subject: "Credits added to your account",
|
|
740
780
|
html: wrapHtml(
|
|
@@ -747,27 +787,33 @@ export function renderNotificationTemplate(template: TemplateName, data: Record<
|
|
|
747
787
|
? `<p>New balance: <strong>${escapeHtml(data.newBalanceDollars as string)}</strong></p>`
|
|
748
788
|
: ""),
|
|
749
789
|
),
|
|
750
|
-
footer(
|
|
790
|
+
footer(`Thank you for supporting ${escapeHtml(b)}!`),
|
|
751
791
|
].join("\n"),
|
|
792
|
+
b,
|
|
752
793
|
),
|
|
753
|
-
text: `Credits Added\n\n${data.amountDollars} added.\n${copyright()}`,
|
|
794
|
+
text: `Credits Added\n\n${data.amountDollars} added.\n${copyright(b)}`,
|
|
754
795
|
};
|
|
755
|
-
|
|
796
|
+
}
|
|
797
|
+
case "welcome": {
|
|
798
|
+
const b = brand(data);
|
|
756
799
|
return {
|
|
757
|
-
subject:
|
|
800
|
+
subject: `Welcome to ${b}`,
|
|
758
801
|
html: wrapHtml(
|
|
759
802
|
"Welcome",
|
|
760
803
|
[
|
|
761
|
-
heading(
|
|
804
|
+
heading(`Welcome to ${escapeHtml(b)}!`),
|
|
762
805
|
paragraph("<p>Your account is now active. Start building!</p>"),
|
|
763
806
|
footer("Happy building!"),
|
|
764
807
|
].join("\n"),
|
|
808
|
+
b,
|
|
765
809
|
),
|
|
766
|
-
text: `Welcome to
|
|
810
|
+
text: `Welcome to ${b}!\n\nYour account is now active.\n${copyright(b)}`,
|
|
767
811
|
};
|
|
768
|
-
|
|
812
|
+
}
|
|
813
|
+
case "password-reset": {
|
|
814
|
+
const b = brand(data);
|
|
769
815
|
return {
|
|
770
|
-
subject:
|
|
816
|
+
subject: `Reset your ${b} password`,
|
|
771
817
|
html: wrapHtml(
|
|
772
818
|
"Reset Password",
|
|
773
819
|
[
|
|
@@ -776,9 +822,11 @@ export function renderNotificationTemplate(template: TemplateName, data: Record<
|
|
|
776
822
|
...(data.resetUrl ? [button(data.resetUrl as string, "Reset Password")] : []),
|
|
777
823
|
footer("If you did not request this, ignore this email."),
|
|
778
824
|
].join("\n"),
|
|
825
|
+
b,
|
|
779
826
|
),
|
|
780
|
-
text: `Reset Your Password\n\n${data.resetUrl ? `${data.resetUrl}\n` : ""}${copyright()}`,
|
|
827
|
+
text: `Reset Your Password\n\n${data.resetUrl ? `${data.resetUrl}\n` : ""}${copyright(b)}`,
|
|
781
828
|
};
|
|
829
|
+
}
|
|
782
830
|
default: {
|
|
783
831
|
// Exhaustiveness check
|
|
784
832
|
const _exhaustive: never = template;
|