178 lines
5.4 KiB
TypeScript
178 lines
5.4 KiB
TypeScript
import { Injectable, Logger } from "@nestjs/common";
|
|
|
|
import { TemplatesService } from "./templates.service";
|
|
// import { PersonalityDataType, SectionItemType, TextType } from "../interfaces/structure.interface";
|
|
|
|
interface ProcessedTemplateResult {
|
|
html: string;
|
|
text: string;
|
|
hasTemplate: boolean;
|
|
}
|
|
|
|
@Injectable()
|
|
export class TemplateProcessorService {
|
|
private readonly logger = new Logger(TemplateProcessorService.name);
|
|
|
|
constructor(private readonly templatesService: TemplatesService) {}
|
|
|
|
/**
|
|
* Process email content through business template
|
|
*/
|
|
async processEmailWithTemplate(
|
|
businessId: string,
|
|
emailContent: { text?: string; html?: string; subject?: string },
|
|
// userId?: string,
|
|
): Promise<ProcessedTemplateResult> {
|
|
try {
|
|
this.logger.log(`Processing email with template for business: ${businessId}`);
|
|
|
|
// Get business templates
|
|
const templates = await this.templatesService.getTemplatesByBusinessId(businessId);
|
|
|
|
if (!templates || templates.length === 0) {
|
|
this.logger.log(`No templates found for business: ${businessId}, using original content`);
|
|
return {
|
|
html: emailContent.html || this.convertTextToHtml(emailContent.text || ""),
|
|
text: emailContent.text || this.stripHtmlTags(emailContent.html || ""),
|
|
hasTemplate: false,
|
|
};
|
|
}
|
|
|
|
// Use the first template
|
|
const template = templates[0];
|
|
|
|
this.logger.log(`Using template: ${template.name} for email processing`);
|
|
|
|
// Process the template with email content
|
|
const processedContent = await this.injectContentIntoTemplate(emailContent, template.rawHtml);
|
|
|
|
return {
|
|
html: processedContent.html,
|
|
text: processedContent.text,
|
|
hasTemplate: true,
|
|
};
|
|
} catch (error) {
|
|
this.logger.error(`Failed to process email with template for business ${businessId}:`, error);
|
|
|
|
// Fallback to original content if template processing fails
|
|
return {
|
|
html: emailContent.html || this.convertTextToHtml(emailContent.text || ""),
|
|
text: emailContent.text || this.stripHtmlTags(emailContent.html || ""),
|
|
hasTemplate: false,
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Inject email content into template structure
|
|
*/
|
|
private async injectContentIntoTemplate(
|
|
// templateStructure: Record<string, unknown>,
|
|
emailContent: { text?: string; html?: string; subject?: string },
|
|
rawHtml?: string,
|
|
): Promise<{ html: string; text: string }> {
|
|
try {
|
|
// If template has raw HTML, use it as base and inject content
|
|
if (rawHtml) {
|
|
const html = this.injectContentIntoRawHtml(rawHtml, emailContent);
|
|
return {
|
|
html,
|
|
text: this.stripHtmlTags(html),
|
|
};
|
|
}
|
|
|
|
// Otherwise, build simple HTML with email content
|
|
const html = this.buildSimpleTemplate(emailContent);
|
|
return {
|
|
html,
|
|
text: this.stripHtmlTags(html),
|
|
};
|
|
} catch (error) {
|
|
this.logger.error("Failed to inject content into template:", error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Inject email content into raw HTML template
|
|
*/
|
|
private injectContentIntoRawHtml(rawHtml: string, emailContent: { text?: string; html?: string; subject?: string }): string {
|
|
let processedHtml = rawHtml;
|
|
|
|
// Replace placeholders with actual content
|
|
const contentToInject = emailContent.html || this.convertTextToHtml(emailContent.text || "");
|
|
|
|
// Common placeholder patterns
|
|
const placeholders = [/\{\{content\}\}/gi, /\{\{message\}\}/gi, /\{\{body\}\}/gi, /\{content\}/gi, /\{message\}/gi, /\{body\}/gi];
|
|
|
|
placeholders.forEach((placeholder) => {
|
|
processedHtml = processedHtml.replace(placeholder, contentToInject);
|
|
});
|
|
|
|
// Replace subject placeholders
|
|
if (emailContent.subject) {
|
|
const subjectPlaceholders = [/\{\{subject\}\}/gi, /\{\{title\}\}/gi, /\{subject\}/gi, /\{title\}/gi];
|
|
|
|
subjectPlaceholders.forEach((placeholder) => {
|
|
processedHtml = processedHtml.replace(placeholder, emailContent.subject!);
|
|
});
|
|
}
|
|
|
|
return processedHtml;
|
|
}
|
|
|
|
/**
|
|
* Build simple HTML template
|
|
*/
|
|
private buildSimpleTemplate(emailContent: { text?: string; html?: string; subject?: string }): string {
|
|
const content = emailContent.html || this.convertTextToHtml(emailContent.text || "");
|
|
|
|
return `
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>${emailContent.subject || "Email"}</title>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; margin: 0; padding: 20px; line-height: 1.6; }
|
|
.email-container { max-width: 600px; margin: 0 auto; }
|
|
.content { padding: 20px; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="email-container">
|
|
<div class="content">
|
|
${content}
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
`;
|
|
}
|
|
|
|
/**
|
|
* Convert plain text to HTML
|
|
*/
|
|
private convertTextToHtml(text: string): string {
|
|
return text
|
|
.replace(/\n\n/g, "</p><p>")
|
|
.replace(/\n/g, "<br>")
|
|
.replace(/^(.*)$/, "<p>$1</p>");
|
|
}
|
|
|
|
/**
|
|
* Strip HTML tags from content
|
|
*/
|
|
private stripHtmlTags(html: string): string {
|
|
return html
|
|
.replace(/<[^>]*>/g, "")
|
|
.replace(/ /g, " ")
|
|
.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">")
|
|
.replace(/"/g, '"')
|
|
.trim();
|
|
}
|
|
}
|