Skip to main content
Glama
luiso2

Evolution API WhatsApp MCP Server

by luiso2
template-service.ts7.47 kB
import { MessageTemplate, DEFAULT_TEMPLATES } from '../types/templates.js'; import * as fs from 'fs/promises'; import * as path from 'path'; export class TemplateService { private templates: Map<string, MessageTemplate> = new Map(); private templatesPath: string; constructor(storagePath: string = './templates') { this.templatesPath = storagePath; this.loadDefaultTemplates(); } private loadDefaultTemplates(): void { DEFAULT_TEMPLATES.forEach(template => { this.templates.set(template.id, template); }); } async initialize(): Promise<void> { try { await fs.mkdir(this.templatesPath, { recursive: true }); const customTemplatesFile = path.join(this.templatesPath, 'custom-templates.json'); try { const data = await fs.readFile(customTemplatesFile, 'utf-8'); const customTemplates = JSON.parse(data) as MessageTemplate[]; customTemplates.forEach(template => { this.templates.set(template.id, template); }); } catch (error) { // File doesn't exist, create it with empty array await fs.writeFile(customTemplatesFile, JSON.stringify([], null, 2)); } } catch (error) { console.error('Error initializing template service:', error); } } async saveCustomTemplates(): Promise<void> { const customTemplatesFile = path.join(this.templatesPath, 'custom-templates.json'); const customTemplates = Array.from(this.templates.values()).filter( t => !DEFAULT_TEMPLATES.find(dt => dt.id === t.id) ); await fs.writeFile(customTemplatesFile, JSON.stringify(customTemplates, null, 2)); } /** * Replace variables in template content */ replaceVariables(template: string, variables: Record<string, any>): string { let result = template; Object.entries(variables).forEach(([key, value]) => { const regex = new RegExp(`{{\\s*${key}\\s*}}`, 'g'); result = result.replace(regex, String(value)); }); return result; } /** * Process template content with variables */ processTemplate(template: MessageTemplate, variables: Record<string, any>): any { const processedContent: any = {}; if (template.content.text) { processedContent.text = this.replaceVariables(template.content.text, variables); } if (template.content.media) { processedContent.media = { ...template.content.media, caption: template.content.media.caption ? this.replaceVariables(template.content.media.caption, variables) : undefined, mediaUrl: template.content.media.mediaUrl ? this.replaceVariables(template.content.media.mediaUrl, variables) : undefined }; } if (template.content.buttons) { processedContent.buttons = template.content.buttons.map(button => ({ ...button, buttonText: { displayText: this.replaceVariables(button.buttonText.displayText, variables) } })); } if (template.content.listMessage) { const list = template.content.listMessage; processedContent.listMessage = { title: this.replaceVariables(list.title, variables), description: this.replaceVariables(list.description, variables), buttonText: this.replaceVariables(list.buttonText, variables), footerText: list.footerText ? this.replaceVariables(list.footerText, variables) : undefined, sections: list.sections }; } return processedContent; } /** * Get template by ID */ getTemplate(id: string): MessageTemplate | undefined { return this.templates.get(id); } /** * Get all templates */ getAllTemplates(): MessageTemplate[] { return Array.from(this.templates.values()); } /** * Get templates by category */ getTemplatesByCategory(category: string): MessageTemplate[] { return Array.from(this.templates.values()).filter( t => t.category === category ); } /** * Get templates by tags */ getTemplatesByTags(tags: string[]): MessageTemplate[] { return Array.from(this.templates.values()).filter( t => t.tags && tags.some(tag => t.tags!.includes(tag)) ); } /** * Create new template */ async createTemplate(template: Omit<MessageTemplate, 'id' | 'createdAt' | 'updatedAt'>): Promise<MessageTemplate> { const id = this.generateTemplateId(template.name); const newTemplate: MessageTemplate = { ...template, id, createdAt: new Date(), updatedAt: new Date() }; this.templates.set(id, newTemplate); await this.saveCustomTemplates(); return newTemplate; } /** * Update existing template */ async updateTemplate(id: string, updates: Partial<MessageTemplate>): Promise<MessageTemplate | null> { const template = this.templates.get(id); if (!template) return null; const updatedTemplate = { ...template, ...updates, id, // Preserve ID updatedAt: new Date() }; this.templates.set(id, updatedTemplate); await this.saveCustomTemplates(); return updatedTemplate; } /** * Delete template */ async deleteTemplate(id: string): Promise<boolean> { // Don't delete default templates if (DEFAULT_TEMPLATES.find(t => t.id === id)) { return false; } const deleted = this.templates.delete(id); if (deleted) { await this.saveCustomTemplates(); } return deleted; } /** * Validate template variables */ validateVariables(template: MessageTemplate, variables: Record<string, any>): string[] { const missingVars: string[] = []; if (template.variables) { template.variables.forEach(varName => { if (!(varName in variables)) { missingVars.push(varName); } }); } return missingVars; } /** * Generate template ID from name */ private generateTemplateId(name: string): string { const base = name.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''); let id = base; let counter = 1; while (this.templates.has(id)) { id = `${base}-${counter}`; counter++; } return id; } /** * Export templates to JSON */ async exportTemplates(): Promise<string> { const templates = Array.from(this.templates.values()); return JSON.stringify(templates, null, 2); } /** * Import templates from JSON */ async importTemplates(jsonData: string): Promise<number> { try { const templates = JSON.parse(jsonData) as MessageTemplate[]; let imported = 0; for (const template of templates) { if (!this.templates.has(template.id)) { this.templates.set(template.id, template); imported++; } } await this.saveCustomTemplates(); return imported; } catch (error) { throw new Error('Invalid template JSON format'); } } /** * Search templates by text */ searchTemplates(query: string): MessageTemplate[] { const lowerQuery = query.toLowerCase(); return Array.from(this.templates.values()).filter(template => { return ( template.name.toLowerCase().includes(lowerQuery) || template.description?.toLowerCase().includes(lowerQuery) || template.tags?.some(tag => tag.toLowerCase().includes(lowerQuery)) || template.category?.toLowerCase().includes(lowerQuery) ); }); } }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/luiso2/mcp-evolution-api'

If you have feedback or need assistance with the MCP directory API, please join our Discord server