backend/pkg/notification/usecase/template.go

166 lines
6.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package usecase
import (
"backend/pkg/notification/domain"
"backend/pkg/notification/domain/entity"
"backend/pkg/notification/domain/repository"
"backend/pkg/notification/domain/template"
"backend/pkg/notification/domain/usecase"
"context"
"fmt"
"strings"
"backend/pkg/library/errs"
"backend/pkg/library/errs/code"
"github.com/zeromicro/go-zero/core/logx"
)
type TemplateUseCaseParam struct {
TemplateRepo repository.TemplateRepository // 可選的資料庫模板 repository
}
type TemplateUseCase struct {
param TemplateUseCaseParam
}
func MustTemplateUseCase(param TemplateUseCaseParam) usecase.TemplateUseCase {
return &TemplateUseCase{
param,
}
}
// GetEmailTemplateByStatic 從靜態模板獲取郵件模板
func (use *TemplateUseCase) GetEmailTemplateByStatic(_ context.Context, language template.Language, templateID template.Type) (template.EmailTemplate, error) {
// 查找指定語言的模板映射
templateByLang, exists := template.EmailTemplateMap[language]
if !exists {
return template.EmailTemplate{}, errs.ResourceNotFoundWithScope(
code.CloudEPNotification,
domain.FailedToGetTemplateErrorCode,
fmt.Sprintf("email template not found for language: %s", language))
}
// 查找指定類型的模板生成函數
templateFunc, exists := templateByLang[templateID]
if !exists {
return template.EmailTemplate{}, errs.ResourceNotFoundWithScope(
code.CloudEPNotification,
domain.FailedToGetTemplateErrorCode,
fmt.Sprintf("email template not found for type ID: %s", templateID))
}
// 執行模板生成函數
tmp, err := templateFunc()
if err != nil {
return template.EmailTemplate{}, errs.DatabaseErrorWithScope(
code.CloudEPNotification,
domain.FailedToGetTemplateErrorCode,
fmt.Sprintf("error generating email template: %v", err))
}
return tmp, nil
}
// GetEmailTemplate 獲取郵件模板(優先從資料庫,回退到靜態模板)
func (use *TemplateUseCase) GetEmailTemplate(ctx context.Context, language template.Language, templateID template.Type) (template.EmailTemplate, error) {
// 1. 嘗試從資料庫獲取模板
if use.param.TemplateRepo != nil {
dbTemplate, err := use.param.TemplateRepo.GetTemplate(ctx, "email", string(language), string(templateID))
if err == nil && dbTemplate != nil && dbTemplate.IsActive {
logx.WithContext(ctx).Infof("Using database template for %s/%s", language, templateID)
return template.EmailTemplate{
Title: dbTemplate.Subject,
Body: dbTemplate.Body,
}, nil
}
// 記錄資料庫查詢失敗,但不返回錯誤,繼續使用靜態模板
if err != nil {
logx.WithContext(ctx).WithFields(logx.LogField{Key: "error", Value: err.Error()}).Error("Failed to get template from database, falling back to static")
}
}
// 2. 回退到靜態模板
logx.WithContext(ctx).Infof("Using static template for %s/%s", language, templateID)
return use.GetEmailTemplateByStatic(ctx, language, templateID)
}
// GetSMSTemplate 獲取 SMS 模板(優先從資料庫,回退到靜態模板)
func (use *TemplateUseCase) GetSMSTemplate(ctx context.Context, language template.Language, templateID template.Type) (usecase.SMSTemplateResp, error) {
// 1. 嘗試從資料庫獲取模板
if use.param.TemplateRepo != nil {
dbTemplate, err := use.param.TemplateRepo.GetTemplate(ctx, "sms", string(language), string(templateID))
if err == nil && dbTemplate != nil && dbTemplate.IsActive {
logx.WithContext(ctx).Infof("Using database SMS template for %s/%s", language, templateID)
return usecase.SMSTemplateResp{
Body: dbTemplate.Body,
}, nil
}
// 記錄資料庫查詢失敗,但不返回錯誤,繼續使用靜態模板
if err != nil {
logx.WithContext(ctx).WithFields(logx.LogField{Key: "error", Value: err.Error()}).Error("Failed to get SMS template from database, falling back to static")
}
}
// 2. 回退到靜態模板SMS 暫時沒有靜態模板,返回默認)
logx.WithContext(ctx).Infof("Using default SMS template for %s/%s", language, templateID)
return use.getDefaultSMSTemplate(templateID), nil
}
// RenderEmailTemplate 渲染郵件模板(替換變數)
func (use *TemplateUseCase) RenderEmailTemplate(ctx context.Context, tmpl template.EmailTemplate, params entity.TemplateParams) (usecase.EmailTemplateResp, error) {
renderedSubject := use.renderTemplate(tmpl.Title, params)
renderedBody := use.renderTemplate(tmpl.Body, params)
return usecase.EmailTemplateResp{
Subject: renderedSubject,
Body: renderedBody,
}, nil
}
// RenderSMSTemplate 渲染 SMS 模板(替換變數)
func (use *TemplateUseCase) RenderSMSTemplate(ctx context.Context, tmpl usecase.SMSTemplateResp, params entity.TemplateParams) (usecase.SMSTemplateResp, error) {
renderedBody := use.renderTemplate(tmpl.Body, params)
return usecase.SMSTemplateResp{
Body: renderedBody,
}, nil
}
// renderTemplate 渲染模板內容(簡單的字符串替換)
func (use *TemplateUseCase) renderTemplate(content string, params entity.TemplateParams) string {
result := content
// 替換基本參數
result = strings.ReplaceAll(result, "{{.Username}}", params.Username)
result = strings.ReplaceAll(result, "{{.VerifyCode}}", params.VerifyCode)
// 替換額外參數
for key, value := range params.Extra {
placeholder := fmt.Sprintf("{{.%s}}", key)
result = strings.ReplaceAll(result, placeholder, value)
}
return result
}
// getDefaultSMSTemplate 獲取默認 SMS 模板
func (use *TemplateUseCase) getDefaultSMSTemplate(templateID template.Type) usecase.SMSTemplateResp {
switch templateID {
case template.ForgetPasswordVerify:
return usecase.SMSTemplateResp{
Body: "您的密碼重設驗證碼是:{{.VerifyCode}}請在5分鐘內使用。如非本人操作請忽略此訊息。",
}
case template.BindingEmail:
return usecase.SMSTemplateResp{
Body: "您的綁定驗證碼是:{{.VerifyCode}}請在5分鐘內使用。如非本人操作請忽略此訊息。",
}
default:
return usecase.SMSTemplateResp{
Body: "您的驗證碼是:{{.VerifyCode}}請在5分鐘內使用。",
}
}
}