adds email notifications
This commit is contained in:
67
db/util/email_templates.go
Normal file
67
db/util/email_templates.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
t "html/template"
|
||||
|
||||
"github.com/pocketbase/pocketbase/tools/template"
|
||||
)
|
||||
|
||||
type EmailData struct {
|
||||
AppUrl string
|
||||
RecipientName string
|
||||
Content t.HTML
|
||||
Link string
|
||||
FollowerName string
|
||||
}
|
||||
|
||||
var notificationTemplates = map[NotificationType]string{
|
||||
TrailCreate: "{{.Author}} has created a new trail: {{.trail}}.",
|
||||
TrailShare: "{{.Author}} has shared a trail with you: {{.trail}}.",
|
||||
ListCreate: "{{.Author}} has created a new list: {{.list}}.",
|
||||
ListShare: "{{.Author}} has shared a list with you: {{.list}}.",
|
||||
NewFollower: "Good news! You have a new follower: {{.Author}}.",
|
||||
TrailComment: "{{.Author}} commented on your trail '{{.trail}}': '{{.comment}}'.",
|
||||
}
|
||||
|
||||
func GenerateHTML(appUrl string, recipientName string, authorName string, notificationType NotificationType, metadata map[string]string) (string, error) {
|
||||
registry := template.NewRegistry()
|
||||
|
||||
// Get custom content template for the notification type
|
||||
customTemplate, exists := notificationTemplates[notificationType]
|
||||
if !exists {
|
||||
return "", errors.New("unknown notification type")
|
||||
}
|
||||
|
||||
// Create content template with dynamic data
|
||||
contentTmpl, err := t.New("content").Parse(customTemplate)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Render the custom content with data
|
||||
metadata["Author"] = authorName
|
||||
var contentBuffer bytes.Buffer
|
||||
err = contentTmpl.Execute(&contentBuffer, metadata)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Assemble the final email with boilerplate and custom content
|
||||
content := EmailData{
|
||||
AppUrl: appUrl,
|
||||
RecipientName: recipientName,
|
||||
Content: t.HTML(contentBuffer.String()),
|
||||
}
|
||||
|
||||
html, err := registry.LoadFiles(
|
||||
"templates/mail/notification.html",
|
||||
).Render(content)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return html, nil
|
||||
}
|
||||
@@ -2,10 +2,12 @@ package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/mail"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"github.com/pocketbase/pocketbase/tools/mailer"
|
||||
)
|
||||
|
||||
type NotificationType string
|
||||
@@ -20,10 +22,10 @@ const (
|
||||
)
|
||||
|
||||
type Notification struct {
|
||||
Type NotificationType `json:"type"`
|
||||
Metadata interface{} `json:"metadata,omitempty"`
|
||||
Seen bool `json:"seen"`
|
||||
Author string `json:"author"`
|
||||
Type NotificationType `json:"type"`
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
Seen bool `json:"seen"`
|
||||
Author string `json:"author"`
|
||||
}
|
||||
|
||||
type NotificationSettings struct {
|
||||
@@ -59,22 +61,50 @@ func SendNotification(app *pocketbase.PocketBase, notification Notification, rec
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !permissions.Web {
|
||||
return nil
|
||||
}
|
||||
|
||||
notifications, err := app.Dao().FindCollectionByNameOrId("notifications")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n := models.NewRecord(notifications)
|
||||
n.Set("type", string(notification.Type))
|
||||
n.Set("metadata", notification.Metadata)
|
||||
n.Set("seen", notification.Seen)
|
||||
n.Set("recipient", recipient)
|
||||
n.Set("author", notification.Author)
|
||||
|
||||
if err := app.Dao().SaveRecord(n); err != nil {
|
||||
return err
|
||||
if permissions.Web {
|
||||
n := models.NewRecord(notifications)
|
||||
n.Set("type", string(notification.Type))
|
||||
n.Set("metadata", notification.Metadata)
|
||||
n.Set("seen", notification.Seen)
|
||||
n.Set("recipient", recipient)
|
||||
n.Set("author", notification.Author)
|
||||
|
||||
if err := app.Dao().SaveRecord(n); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if permissions.Email {
|
||||
recipientUser, err := app.Dao().FindRecordById("users", recipient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
authorUser, err := app.Dao().FindRecordById("users", notification.Author)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
html, err := GenerateHTML(app.Settings().Meta.AppUrl, recipientUser.Username(), authorUser.Username(), notification.Type, notification.Metadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
message := &mailer.Message{
|
||||
From: mail.Address{
|
||||
Address: app.Settings().Meta.SenderAddress,
|
||||
Name: app.Settings().Meta.SenderName,
|
||||
},
|
||||
To: []mail.Address{{Address: recipientUser.Email()}},
|
||||
Subject: "wanderer - New Notification",
|
||||
HTML: html,
|
||||
}
|
||||
|
||||
app.NewMailClient().Send(message)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -85,32 +115,11 @@ func SendNotificationToFollowers(app *pocketbase.PocketBase, notification Notifi
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
notifications, err := app.Dao().FindCollectionByNameOrId("notifications")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, f := range followers {
|
||||
recipient := f.GetString("follower")
|
||||
if notification.Author == recipient {
|
||||
continue
|
||||
}
|
||||
permissions, err := getNotificationPermissions(app, recipient, notification.Type)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if !permissions.Web {
|
||||
continue
|
||||
}
|
||||
n := models.NewRecord(notifications)
|
||||
n.Set("type", string(notification.Type))
|
||||
n.Set("metadata", notification.Metadata)
|
||||
n.Set("seen", notification.Seen)
|
||||
n.Set("recipient", recipient)
|
||||
n.Set("author", notification.Author)
|
||||
SendNotification(app, notification, recipient)
|
||||
|
||||
if err := app.Dao().SaveRecord(n); err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user