122 lines
3.3 KiB
Go
122 lines
3.3 KiB
Go
package services
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/patbritton/sojorn-backend/internal/repository"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type NotificationService struct {
|
|
notifRepo *repository.NotificationRepository
|
|
pushSvc *PushService
|
|
}
|
|
|
|
func NewNotificationService(notifRepo *repository.NotificationRepository, pushSvc *PushService) *NotificationService {
|
|
return &NotificationService{
|
|
notifRepo: notifRepo,
|
|
pushSvc: pushSvc,
|
|
}
|
|
}
|
|
|
|
func (s *NotificationService) CreateNotification(ctx context.Context, userID, actorID, notificationType string, postID *string, commentID *string, metadata map[string]interface{}) error {
|
|
// Parse UUIDs
|
|
// Validate UUIDs (for future use when we fix notification storage)
|
|
_, err := uuid.Parse(userID)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid user ID: %w", err)
|
|
}
|
|
|
|
_, err = uuid.Parse(actorID)
|
|
if err != nil {
|
|
return fmt.Errorf("invalid actor ID: %w", err)
|
|
}
|
|
|
|
// Send push notification
|
|
if s.pushSvc != nil {
|
|
title, body, data := s.buildPushNotification(notificationType, metadata)
|
|
if err := s.pushSvc.SendPush(ctx, userID, title, body, data); err != nil {
|
|
log.Warn().Err(err).Str("user_id", userID).Msg("Failed to send push notification")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *NotificationService) buildPushNotification(notificationType string, metadata map[string]interface{}) (title, body string, data map[string]string) {
|
|
actorName, _ := metadata["actor_name"].(string)
|
|
|
|
switch notificationType {
|
|
case "beacon_vouch":
|
|
title = "Beacon Vouched"
|
|
body = fmt.Sprintf("%s vouched for your beacon", actorName)
|
|
data = map[string]string{
|
|
"type": "beacon_vouch",
|
|
"beacon_id": getString(metadata, "beacon_id"),
|
|
"target": "beacon_map", // Deep link to map
|
|
}
|
|
case "beacon_report":
|
|
title = "Beacon Reported"
|
|
body = fmt.Sprintf("%s reported your beacon", actorName)
|
|
data = map[string]string{
|
|
"type": "beacon_report",
|
|
"beacon_id": getString(metadata, "beacon_id"),
|
|
"target": "beacon_map", // Deep link to map
|
|
}
|
|
case "comment":
|
|
title = "New Comment"
|
|
postType := getString(metadata, "post_type")
|
|
if postType == "beacon" {
|
|
body = fmt.Sprintf("%s commented on your beacon", actorName)
|
|
data = map[string]string{
|
|
"type": "comment",
|
|
"post_id": getString(metadata, "post_id"),
|
|
"target": "beacon_map", // Deep link to map for beacon comments
|
|
}
|
|
} else if postType == "quip" {
|
|
body = fmt.Sprintf("%s commented on your quip", actorName)
|
|
data = map[string]string{
|
|
"type": "comment",
|
|
"post_id": getString(metadata, "post_id"),
|
|
"target": "quip_feed", // Deep link to quip feed
|
|
}
|
|
} else {
|
|
body = fmt.Sprintf("%s commented on your post", actorName)
|
|
data = map[string]string{
|
|
"type": "comment",
|
|
"post_id": getString(metadata, "post_id"),
|
|
"target": "main_feed", // Deep link to main feed
|
|
}
|
|
}
|
|
default:
|
|
title = "Sojorn"
|
|
body = "You have a new notification"
|
|
data = map[string]string{"type": notificationType}
|
|
}
|
|
|
|
return title, body, data
|
|
}
|
|
|
|
// Helper functions
|
|
func parseNullableUUID(s *string) *uuid.UUID {
|
|
if s == nil {
|
|
return nil
|
|
}
|
|
u, err := uuid.Parse(*s)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return &u
|
|
}
|
|
|
|
func getString(m map[string]interface{}, key string) string {
|
|
if val, ok := m[key]; ok {
|
|
if str, ok := val.(string); ok {
|
|
return str
|
|
}
|
|
}
|
|
return ""
|
|
}
|