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 { return this.emailRepository.findMany(query); } /** * @description : Create a new email * @throws {Error} If email cannot be created */ public async create(emailEntity: Emails): Promise { 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 { 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 { 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.' }); // } // } }