Untitled

mail@pastecode.io avatar
unknown
golang
2 years ago
3.8 kB
2
Indexable
Never
package template

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"

	"bitbucket.org/resumelibrary/jbe/pkg/models"
	"bitbucket.org/resumelibrary/jbe/pkg/processor/template/html"
	"bitbucket.org/resumelibrary/jbe/pkg/processor/template/text"
	"go.uber.org/zap"
)

// Cache interface for storing matched Jobs.
type Cache interface {
	GetJobs(ctx context.Context, msg *models.Message) (models.Jobs, error)
	PutEmail(ctx context.Context, msg *models.Message, email models.Email) error
}

// Service for the Template processing stage.
type Service struct {
	Log   *zap.Logger
	Cache Cache
}

// New creates a Service processor.
func New(log *zap.Logger, ca Cache) (*Service, error) {
	return &Service{
		Log:   log,
		Cache: ca,
	}, nil
}

// Name returns the stage name.
func (s *Service) Name() string {
	return "template"
}

// Process consumes an incoming message and produces one or more output messages.
func (s *Service) Process(ctx context.Context, data string) ([]string, error) {
	var m models.Message

	if err := json.Unmarshal([]byte(data), &m); err != nil {
		return nil, err
	}

	jobs, err := s.Cache.GetJobs(ctx, &m)
	if err != nil {
		return nil, err
	}

	templateData, err := s.buildPayload(ctx, &m, jobs)
	if err != nil {
		return nil, err
	}

	err = s.setEmailProperties(&m, templateData)
	if err != nil {
		return nil, err
	}

	email, err := s.buildEmail(m.TemplateProp.HTMLTemplatePath, m.TemplateProp.TextTemplatePath, templateData)
	if err != nil {
		return nil, err
	}

	err = s.Cache.PutEmail(ctx, &m, *email)
	if err != nil {
		return nil, err
	}

	return []string{data}, nil
}

func (s *Service) buildPayload(ctx context.Context, m *models.Message, j models.Jobs) (*models.TemplateData, error) {
	site := models.Site{
		URL: m.TemplateProp.SiteURL,
	}

	config := models.TConfig{
		EmailInstanceID: m.TemplateProp.EmailInstance.ID,
		AnalyticsID:     m.TemplateProp.AnalyticsID,
	}

	return models.NewTemplateData(&site, &config, m, j), nil
}

func (s *Service) buildEmail(htmlPath string, textPath string, templateData *models.TemplateData) (*models.Email, error) {
	HTMLTemplate := html.Template{
		Path: htmlPath,
	}

	if err := HTMLTemplate.Init(); err != nil {
		return &models.Email{}, err
	}

	htmlContent, err := HTMLTemplate.AddParams(templateData)
	if err != nil {
		return nil, err
	}

	TextTemplate := text.Template{
		Path: textPath,
	}

	if err := TextTemplate.Init(); err != nil {
		return &models.Email{}, err
	}

	textContent, err := TextTemplate.AddParams(templateData)
	if err != nil {
		return nil, err
	}

	return &models.Email{HTMLTemplate: htmlContent, TextTemplate: textContent}, nil
}

func (s *Service) setEmailProperties(m *models.Message, templateData *models.TemplateData) error {
	headers, err := s.newHeaders(m, templateData)
	if err != nil {
		return err
	}

	m.EmailProp = &models.EmailProp{
		Subject:      templateData.Subject,
		To:           templateData.Candidate.EmailAddress,
		From:         m.TemplateProp.EmailFrom,
		FromName:     m.TemplateProp.FromName,
		Headers:      headers,
		EnvelopeFrom: s.newEnvelopeFrom(m, templateData),
	}

	return nil
}

func (s *Service) newEnvelopeFrom(m *models.Message, templateData *models.TemplateData) string {
	email := strings.Replace(templateData.Candidate.EmailAddress, "@", "=", -1)
	return fmt.Sprintf("%s-%s+%s@%s", m.TemplateProp.UnsubscribeAddrFromPrefix, m.TemplateProp.EmailInstance.ID, email, m.TemplateProp.UnsubscribeDomain)
}

func (s *Service) newHeaders(m *models.Message, templateData *models.TemplateData) (string, error) {
	header := make(map[string]string, 1)

	header["List-Unsubscribe"] = fmt.Sprint(templateData.Candidate.JBEUnsubscribeLink + ", " + s.newEnvelopeFrom(m, templateData))

	h, err := json.Marshal(header)
	if err != nil {
		return "", err
	}

	return string(h), nil
}