import Mail from "nodemailer/lib/mailer"; import { member } from "../entity/member"; import { newsletter } from "../entity/newsletter"; import { newsletterDates } from "../entity/newsletterDates"; import { newsletterRecipients } from "../entity/newsletterRecipients"; import MemberService from "../service/memberService"; import NewsletterDatesService from "../service/newsletterDatesService"; import NewsletterRecipientsService from "../service/newsletterRecipientsService"; import NewsletterService from "../service/newsletterService"; import { CalendarHelper } from "./calendarHelper"; import DynamicQueryBuilder from "./dynamicQueryBuilder"; import { FileSystemHelper } from "./fileSystemHelper"; import MailHelper from "./mailHelper"; import { CLUB_NAME } from "../env.defaults"; import { TemplateHelper } from "./templateHelper"; import { PdfExport } from "./pdfExport"; import NewsletterConfigService from "../service/newsletterConfigService"; import { NewsletterConfigType } from "../enums/newsletterConfigType"; import InternalException from "../exceptions/internalException"; export abstract class NewsletterHelper { public static buildData( newsletter: newsletter, dates: Array, recipient?: member, showAdress: boolean = false ) { return { title: newsletter.title, description: newsletter.description, newsletterTitle: newsletter.newsletterTitle, newsletterText: newsletter.newsletterText, newsletterSignatur: newsletter.newsletterSignatur, dates: dates.map((d) => ({ title: d.diffTitle ?? d.calendar.title, content: d.diffDescription ?? d.calendar.content, starttime: d.calendar.starttime, formattedStarttime: new Date(d.calendar.starttime).toLocaleDateString("de-DE", { weekday: "long", day: "2-digit", month: "long", }), formattedFullStarttime: new Date(d.calendar.starttime).toLocaleDateString("de-DE", { weekday: "long", day: "2-digit", month: "long", year: "numeric", hour: "2-digit", minute: "2-digit", }), endtime: d.calendar.endtime, formattedEndtime: new Date(d.calendar.endtime).toLocaleDateString("de-DE", { weekday: "long", day: "2-digit", month: "long", }), formattedFullEndtime: new Date(d.calendar.endtime).toLocaleDateString("de-DE", { weekday: "long", day: "2-digit", month: "long", year: "numeric", hour: "2-digit", minute: "2-digit", }), location: d.calendar.location, })), ...(recipient ? { recipient: { firstname: recipient.firstname, lastname: recipient.lastname, salutation: recipient.salutation, nameaffix: recipient.nameaffix, ...(showAdress ? { street: recipient.sendNewsletter.street ?? "", streetNumber: recipient.sendNewsletter.streetNumber ?? "", streetNumberAdd: recipient.sendNewsletter.streetNumberAddition ?? "", } : {}), }, } : {}), }; } public static async transformRecipientsToMembers( newsletter: newsletter, recipients: Array ): Promise> { let useQuery = newsletter.recipientsByQuery?.query; let queryMemberIds: Array = []; if (useQuery) { let result = await DynamicQueryBuilder.executeQuery( useQuery.startsWith("{") ? JSON.parse(useQuery) : useQuery, 0, 1000 ); if (result.stats == "success") { let keys = Object.keys(result.rows?.[0] ?? {}); let memberKey = keys.find((k) => k.includes("member_id")); queryMemberIds = result.rows.map((t) => parseInt((t[memberKey] ?? t.id) as string)); } } for (let recipient of recipients) { if (!queryMemberIds.includes(recipient.memberId)) { queryMemberIds.push(recipient.memberId); } } console.log(queryMemberIds); let members = await MemberService.getAll(0, 1000); return members[0].filter((m) => queryMemberIds.includes(m.id)); } public static getICSFilePath(newsletter: newsletter) { return FileSystemHelper.formatPath( "newsletter", `${newsletter.id}_${newsletter.title.replace(" ", "")}`, `events.ics` ); } public static saveIcsToFile(newsletter: newsletter, ics: string) { FileSystemHelper.writeFile(`newsletter/${newsletter.id}_${newsletter.title.replace(" ", "")}`, "events.ics", ics); } public static async sendMails(newsletterId: number) { let newsletter = await NewsletterService.getById(newsletterId); let dates = await NewsletterDatesService.getAll(newsletterId); let recipients = await NewsletterRecipientsService.getAll(newsletterId); let config = await NewsletterConfigService.getAll(); const { value, error } = CalendarHelper.buildICS(dates.map((r) => r.calendar)); if (error) throw new InternalException("Failed Building ICS form Mail", error); this.saveIcsToFile(newsletter, value); let allowedForMail = config.filter((c) => c.config == NewsletterConfigType.mail).map((c) => c.comTypeId); const members = await this.transformRecipientsToMembers(newsletter, recipients); const mailRecipients = members.filter( (m) => m.sendNewsletter != null && m.sendNewsletter?.email != null && allowedForMail.includes(m.sendNewsletter?.type?.id) ); for (const rec of mailRecipients) { let data = this.buildData(newsletter, dates, rec); const { body } = await TemplateHelper.renderFileForModule({ module: "newsletter", bodyData: data, title: `Newsletter von ${CLUB_NAME}`, }); await MailHelper.sendMail(rec.sendNewsletter.email, `Newsletter von ${CLUB_NAME}`, body, [ { filename: "events.ics", path: this.getICSFilePath(newsletter) }, ]) .then(() => {}) .catch((err) => { console.log("mail send", err); }); } } public static async printPdfs(newsletterId: number) { let newsletter = await NewsletterService.getById(newsletterId); let dates = await NewsletterDatesService.getAll(newsletterId); let recipients = await NewsletterRecipientsService.getAll(newsletterId); let config = await NewsletterConfigService.getAll(); FileSystemHelper.clearDirectoryByFiletype( `newsletter/${newsletter.id}_${newsletter.title.replace(" ", "")}`, ".pdf" ); const { value, error } = CalendarHelper.buildICS(dates.map((r) => r.calendar)); if (error) throw new InternalException("Failed Building ICS form Pdf", error); this.saveIcsToFile(newsletter, value); let notAllowedForPdf = config.filter((c) => c.config == NewsletterConfigType.mail).map((c) => c.comTypeId); let printWithAdress = config.filter((c) => c.config == NewsletterConfigType.pdf).map((c) => c.comTypeId); const members = await this.transformRecipientsToMembers(newsletter, recipients); const pdfRecipients = members.filter( (m) => !notAllowedForPdf.includes(m.sendNewsletter?.type?.id) || m.sendNewsletter == null ); for (const rec of pdfRecipients) { let data = this.buildData(newsletter, dates, rec, printWithAdress.includes(rec.sendNewsletter?.type?.id)); await PdfExport.renderFile({ template: "newsletter", title: `Newsletter von ${CLUB_NAME}`, filename: `${rec.lastname}_${rec.firstname}_${rec.id}`, folder: `newsletter/${newsletter.id}_${newsletter.title.replace(" ", "")}`, data: data, }) .then(() => {}) .catch((err) => { console.log("pdf print", err); }); } await PdfExport.sqashToSingleFile( `newsletter/${newsletter.id}_${newsletter.title.replace(" ", "")}`, "allPdfsTogether", `newsletter/${newsletter.id}_${newsletter.title.replace(" ", "")}` ) .then(() => {}) .catch((err) => { console.log("pdf squash", err); }); } }