90 lines
2.0 KiB
Go
90 lines
2.0 KiB
Go
package mail
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
"strings"
|
|
"time"
|
|
|
|
"plumber/internal/events"
|
|
"plumber/internal/store"
|
|
)
|
|
|
|
// Subscribe sends reply emails from PostCreated events. Nop or nil is a no-op.
|
|
func Subscribe(bus *events.Bus, st store.Store, n Notifier) {
|
|
if bus == nil || st == nil || n == nil {
|
|
return
|
|
}
|
|
if _, disabled := n.(Nop); disabled {
|
|
return
|
|
}
|
|
s := subscriber{store: st, mail: n}
|
|
bus.Subscribe(s.handle)
|
|
}
|
|
|
|
type subscriber struct {
|
|
store store.Store
|
|
mail Notifier
|
|
}
|
|
|
|
func (s subscriber) handle(_ context.Context, ev any) {
|
|
created, ok := ev.(events.PostCreated)
|
|
if !ok {
|
|
return
|
|
}
|
|
if strings.TrimSpace(created.ParentID) == "" {
|
|
return
|
|
}
|
|
go s.notifyReply(created.PostEvent)
|
|
}
|
|
|
|
func (s subscriber) notifyReply(ev events.PostEvent) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
parent, err := s.store.GetPost(ctx, ev.ParentID)
|
|
if err != nil {
|
|
log.Printf("notify reply %s: load parent: %v", ev.PostID, err)
|
|
return
|
|
}
|
|
root, err := s.store.GetPost(ctx, ev.RootID)
|
|
if err != nil {
|
|
log.Printf("notify reply %s: load root: %v", ev.PostID, err)
|
|
return
|
|
}
|
|
author, err := s.store.UserByID(ctx, ev.AuthorID)
|
|
if err != nil {
|
|
log.Printf("notify reply %s: load author: %v", ev.PostID, err)
|
|
return
|
|
}
|
|
recipientID := parent.AuthorID
|
|
if author.Admin() {
|
|
recipientID = root.AuthorID
|
|
}
|
|
if recipientID == author.ID {
|
|
return
|
|
}
|
|
msg := PostReply{
|
|
RootID: root.ID,
|
|
RootTitle: root.Title,
|
|
ReplyID: ev.PostID,
|
|
ReplyBody: ev.Body,
|
|
ReplyAuthorName: author.Name,
|
|
}
|
|
recipient, err := s.store.UserByID(ctx, recipientID)
|
|
if err != nil {
|
|
log.Printf("notify reply %s: load recipient: %v", msg.ReplyID, err)
|
|
return
|
|
}
|
|
if recipient == nil || strings.TrimSpace(recipient.Email) == "" {
|
|
return
|
|
}
|
|
msg.ToEmail = recipient.Email
|
|
msg.ToName = recipient.Name
|
|
if err := s.mail.NotifyPostReply(ctx, msg); err != nil {
|
|
log.Printf("notify reply %s: %v", msg.ReplyID, err)
|
|
return
|
|
}
|
|
log.Printf("notify reply %s: accepted", msg.ReplyID)
|
|
}
|