2024-06-18 09:40:14 +02:00

144 lines
4.0 KiB
TypeScript

import EmailRepository from "@Repositories/EmailRepository";
import BaseService from "@Services/BaseService";
import { Emails, Prisma } from "@prisma/client";
import { Service } from "typedi";
import MailchimpClient from "@mailchimp/mailchimp_transactional";
import { BackendVariables } from "@Common/config/variables/Variables";
@Service()
export default class MailchimpService extends BaseService {
private static readonly from = "no-reply@lecoffre.io";
// Construct the service
constructor(private emailRepository: EmailRepository, protected variables: BackendVariables) {
super();
}
/**
* @description : Get all emails
* @throws {Error} If emails cannot be get
*/
public async get(query: Prisma.EmailsFindManyArgs): Promise<Emails[]> {
return this.emailRepository.findMany(query);
}
/**
* @description : Create a new email
* @throws {Error} If email cannot be created
*/
public async create(emailEntity: Emails): Promise<Emails> {
emailEntity.from = MailchimpService.from;
return this.emailRepository.create(emailEntity);
}
/**
* @description : Modify an email
* @throws {Error} If email cannot be modified
*/
public async update(uid: string, emailEntity: Emails): Promise<Emails> {
return this.emailRepository.update(uid, emailEntity);
}
/**
* @description : Get a email by uid
* @throws {Error} If email cannot be get
*/
public async getByUid(uid: string, query?: any): Promise<Emails | null> {
return this.emailRepository.findOneByUid(uid);
}
/**
* @description : Function called by cron to send emails
* @throws {Error} If email cannot be sent
*/
public async sendEmails() {
const emailsToSend = await this.get({ where: { sentAt: null } });
const currentDate = new Date();
let nextTrySendDate = null;
for (const email of emailsToSend) {
//If tries exceed 10, we stop trying to send the email
if (email.nbTrySend && email.nbTrySend > 9) continue;
//If email has never been sent, we send it
if (email.nbTrySend == 0) {
nextTrySendDate = currentDate;
}
//If email has already been sent, we send it again every nbTrySend^2 minutes
else {
nextTrySendDate = new Date(email.lastTrySendDate!);
nextTrySendDate.setMinutes(nextTrySendDate.getMinutes() + Math.pow(email.nbTrySend!, 2));
}
//If the next try send date is passed, we send the email
if (currentDate >= nextTrySendDate) {
try {
await this.sendEmail(email);
email.sentAt = currentDate;
} catch (error) {
email.lastTrySendDate = currentDate;
email.nbTrySend = email.nbTrySend! + 1;
}
await this.update(email.uid, email);
}
}
}
private async sendEmail(email: Emails) {
const apiKey = this.variables.MAILCHIMP_API_KEY;
const mailchimpApiClient = MailchimpClient(apiKey!);
await mailchimpApiClient.messages.sendTemplate({
template_name: email.templateName,
template_content: [],
message: {
global_merge_vars: this.buildVariables(email.templateVariables),
from_email: email.from!,
from_name: "LeCoffre.io",
subject: email.subject,
to: [
{
email: email.to,
type: "to",
},
],
},
});
}
private buildVariables(templateVariables: any) {
return Object.keys(templateVariables).map((key) => {
return {
name: key,
content: templateVariables[key],
};
});
}
// private async addToMailchimpList(email: string) {
// const MAILCHIMP_API_KEY = "3fa54304bc766dfd0b8043a827b28a3a-us17"
// const data = {
// email_address: email,
// status: 'subscribed'
// };
// const response = await fetch(`https://us17.api.mailchimp.com/3.0/lists/6ea48f811d/members`, {
// method: 'POST',
// headers: {
// 'Authorization': `apikey ${MAILCHIMP_API_KEY}`,
// 'Content-Type': 'application/json'
// },
// body: JSON.stringify(data)
// });
// const json = await response.json();
// if (response.status === 200) {
// res.json({ message: 'Successfully subscribed!' });
// } else {
// res.json({ message: 'Failed to subscribe.' });
// }
// }
}