daddy/internal/task/newsletter.go

220 lines
5.4 KiB
Go

package task
import (
"bytes"
"context"
"fmt"
"text/template"
"time"
"forge.cadoles.com/Cadoles/daddy/internal/mail"
"forge.cadoles.com/Cadoles/daddy/internal/model"
"github.com/pkg/errors"
"forge.cadoles.com/Cadoles/daddy/internal/orm"
"gitlab.com/wpetit/goweb/middleware/container"
"gitlab.com/wpetit/goweb/logger"
)
type Newsletter struct {
ctx context.Context
timeRange time.Duration
baseURL string
contentTemplate string
subjectTemplate string
from string
}
func (t *Newsletter) Name() string {
return "newsletter"
}
func (t *Newsletter) Run() {
ctx := t.ctx
logger.Info(ctx, "preparing newsletter", logger.F("timeRange", t.timeRange))
contentTmpl, err := template.New("").Parse(t.contentTemplate)
if err != nil {
logger.Error(ctx, "could not parse newsletter content template", logger.E(errors.WithStack(err)))
return
}
subjectTmpl, err := template.New("").Parse(t.subjectTemplate)
if err != nil {
logger.Error(ctx, "could not parse newsletter subject template", logger.E(errors.WithStack(err)))
return
}
ctn := container.Must(ctx)
orm := orm.Must(ctn)
db := orm.DB()
mailSrv := mail.Must(ctn)
eventRepo := model.NewEventRepository(db)
to := time.Now()
from := to.Add(-t.timeRange)
events, err := eventRepo.Search(ctx, &model.EventFilter{
From: &from,
To: &to,
})
if err != nil {
logger.Error(ctx, "could not search events", logger.E(errors.WithStack(err)))
return
}
newWorkgroups := make([]*model.Workgroup, 0)
newDecisionSupportFiles := make([]*model.DecisionSupportFile, 0)
readyToVote := make([]*model.DecisionSupportFile, 0)
voted := make([]*model.DecisionSupportFile, 0)
workgroupRepo := model.NewWorkgroupRepository(db)
dsfRepo := model.NewDSFRepository(db)
for _, evt := range events {
switch {
case evt.Type == model.EventTypeCreated && evt.ObjectType == model.ObjectTypeWorkgroup:
workgroup, err := workgroupRepo.Find(ctx, fmt.Sprintf("%d", evt.ObjectID))
if err != nil {
logger.Error(
ctx, "could not find workgroup",
logger.E(errors.WithStack(err)),
logger.F("id", evt.ObjectID),
)
return
}
newWorkgroups = append(newWorkgroups, workgroup)
case evt.Type == model.EventTypeCreated && evt.ObjectType == model.ObjectTypeDecisionSupportFile:
dsf, err := dsfRepo.Find(ctx, fmt.Sprintf("%d", evt.ObjectID))
if err != nil {
logger.Error(
ctx, "could not find decision support file",
logger.E(errors.WithStack(err)),
logger.F("id", evt.ObjectID),
)
return
}
newDecisionSupportFiles = append(newDecisionSupportFiles, dsf)
case evt.Type == model.EventTypeStatusChanged && evt.ObjectType == model.ObjectTypeDecisionSupportFile:
dsf, err := dsfRepo.Find(ctx, fmt.Sprintf("%d", evt.ObjectID))
if err != nil {
logger.Error(
ctx, "could not find decision support file",
logger.E(errors.WithStack(err)),
logger.F("id", evt.ObjectID),
)
return
}
if dsf.Status == model.StatusReady {
readyToVote = append(readyToVote, dsf)
}
if dsf.Status == model.StatusVoted {
voted = append(voted, dsf)
}
}
}
hasEvents := len(newDecisionSupportFiles) > 0 || len(newWorkgroups) > 0
userRepo := model.NewUserRepository(db)
users, err := userRepo.All(ctx)
if err != nil {
logger.Error(ctx, "could not find users", logger.E(errors.WithStack(err)))
return
}
var (
contentBuff bytes.Buffer
subjectBuff bytes.Buffer
)
for _, u := range users {
tmplData := struct {
User *model.User
NewWorkgroups []*model.Workgroup
NewDecisionSupportFiles []*model.DecisionSupportFile
ReadyToVote []*model.DecisionSupportFile
Voted []*model.DecisionSupportFile
BaseURL string
From time.Time
To time.Time
HasEvents bool
}{
User: u,
BaseURL: t.baseURL,
NewWorkgroups: newWorkgroups,
NewDecisionSupportFiles: newDecisionSupportFiles,
ReadyToVote: readyToVote,
Voted: voted,
From: from.Local(),
To: to.Local(),
HasEvents: hasEvents,
}
err = contentTmpl.Execute(&contentBuff, tmplData)
if err != nil {
logger.Error(ctx, "could not execute newsletter content template", logger.E(errors.WithStack(err)))
return
}
err = subjectTmpl.Execute(&subjectBuff, tmplData)
if err != nil {
logger.Error(ctx, "could not execute newsletter subject template", logger.E(errors.WithStack(err)))
return
}
newsletterContent := contentBuff.String()
newsletterSubject := subjectBuff.String()
err := mailSrv.Send(
mail.WithRecipients(u.Email),
mail.WithSubject(newsletterSubject),
mail.WithSender(t.from, ""),
mail.WithBody(mail.ContentTypeText, newsletterContent, nil),
)
if err != nil {
logger.Error(
ctx, "could not send newsletter",
logger.E(errors.WithStack(err)),
logger.F("email", u.Email),
)
return
}
contentBuff.Reset()
subjectBuff.Reset()
}
}
func NewNewsletter(ctx context.Context, timeRange time.Duration, baseURL, contentTemplate, subjectTemplate, from string) *Newsletter {
return &Newsletter{
ctx: ctx,
timeRange: timeRange,
baseURL: baseURL,
contentTemplate: contentTemplate,
subjectTemplate: subjectTemplate,
from: from,
}
}