package email import ( "fmt" "strings" ) func renderTemplate(notifType NotificationType, data interface{}, siteName, siteURL string) string { var content string switch notifType { case TypeWelcome: d := data.(WelcomeData) content = renderWelcome(d) case TypeEmailVerify: d := data.(EmailVerifyData) content = renderEmailVerify(d) case TypePasswordReset: d := data.(PasswordResetData) content = renderPasswordReset(d) case TypeLimitWarning: d := data.(LimitWarningData) content = renderLimitWarning(d) case TypeSpaceInvite: d := data.(SpaceInviteData) content = renderSpaceInvite(d) case TypeSystemAlert: d := data.(SystemAlertData) content = renderSystemAlert(d) default: content = "
Уведомление
" } return wrapBase(content, siteName, siteURL) } func wrapBase(content, siteName, siteURL string) string { return fmt.Sprintf(`Мы рады, что вы присоединились. GooSeek — это ваш AI-помощник для поиска, анализа и работы с информацией.
Вот что вы можете делать:
| 🔍 Умный поиск с AI-ответами |
| 💬 Чат с нейросетью |
| 📚 Библиотека и коллекции |
Здравствуйте, %s! Для завершения регистрации подтвердите ваш email-адрес.
Подтвердить email
Если кнопка не работает, скопируйте ссылку:
%s
Ссылка действительна 24 часа.
`, escapeHTML(d.Name), d.VerifyURL, d.VerifyURL, d.VerifyURL) } func renderPasswordReset(d PasswordResetData) string { return fmt.Sprintf(`Здравствуйте, %s! Мы получили запрос на сброс пароля для вашего аккаунта.
Сбросить пароль
Если кнопка не работает, скопируйте ссылку:
%s
Ссылка действительна 1 час. Если вы не запрашивали сброс — проигнорируйте это письмо.
`, escapeHTML(d.Name), d.ResetURL, d.ResetURL, d.ResetURL) } func renderLimitWarning(d LimitWarningData) string { barColor := "#f59e0b" if d.Percentage >= 100 { barColor = "#ef4444" } tierLabel := "Бесплатный" switch d.Tier { case "pro": tierLabel = "Pro" case "business": tierLabel = "Business" } barWidth := d.Percentage if barWidth > 100 { barWidth = 100 } return fmt.Sprintf(`Здравствуйте, %s! Вы использовали %d%% дневного лимита запросов на тарифе %s.
%d из %d запросов
Увеличить лимит `, escapeHTML(d.Name), d.Percentage, tierLabel, barColor, barWidth, d.UsageCount, d.LimitCount, d.UpgradeURL) } func renderSpaceInvite(d SpaceInviteData) string { return fmt.Sprintf(`%s приглашает вас присоединиться к пространству «%s».
Принять приглашение
Если кнопка не работает, скопируйте ссылку:
%s
%s`, escapeHTML(d.Details)) } return fmt.Sprintf(`
%s
%s `, escapeHTML(d.Title), escapeHTML(d.Message), detailsBlock) } func escapeHTML(s string) string { r := strings.NewReplacer( "&", "&", "<", "<", ">", ">", `"`, """, "'", "'", ) return r.Replace(s) }