166 lines
6.0 KiB
Go
166 lines
6.0 KiB
Go
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分鐘內使用。",
|
||
}
|
||
}
|
||
}
|