Passed
Push — main ( df0a9c...c818dd )
by Acho
01:49
created

services.*MarketingService.attributes   A

Complexity

Conditions 3

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 11
dl 0
loc 16
rs 9.85
c 0
b 0
f 0
nop 1
1
package services
2
3
import (
4
	"context"
5
	"fmt"
6
	"strings"
7
8
	semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
9
10
	"firebase.google.com/go/auth"
11
	"github.com/NdoleStudio/httpsms/pkg/entities"
12
	"github.com/NdoleStudio/httpsms/pkg/telemetry"
13
	plunk "github.com/NdoleStudio/plunk-go"
14
	"github.com/gofiber/fiber/v2"
15
	"github.com/palantir/stacktrace"
16
)
17
18
// MarketingService is handles marketing requests
19
type MarketingService struct {
20
	logger      telemetry.Logger
21
	tracer      telemetry.Tracer
22
	authClient  *auth.Client
23
	plunkClient *plunk.Client
24
}
25
26
// NewMarketingService creates a new instance of the MarketingService
27
func NewMarketingService(
28
	logger telemetry.Logger,
29
	tracer telemetry.Tracer,
30
	authClient *auth.Client,
31
	plunkClient *plunk.Client,
32
) *MarketingService {
33
	return &MarketingService{
34
		logger:      logger.WithService(fmt.Sprintf("%T", &MarketingService{})),
35
		tracer:      tracer,
36
		authClient:  authClient,
37
		plunkClient: plunkClient,
38
	}
39
}
40
41
// DeleteContact a user if exists as a contact
42
func (service *MarketingService) DeleteContact(ctx context.Context, email string) error {
43
	ctx, span, ctxLogger := service.tracer.StartWithLogger(ctx, service.logger)
44
	defer span.End()
45
46
	response, _, err := service.plunkClient.Contacts.List(ctx, map[string]string{"limit": "1", "search": email})
47
	if err != nil {
48
		return service.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, fmt.Sprintf("cannot search for contact with email [%s]", email)))
49
	}
50
51
	if len(response.Contacts) == 0 {
52
		ctxLogger.Info(fmt.Sprintf("no contact found with email [%s], skipping deletion", email))
53
		return nil
54
	}
55
56
	contact := response.Contacts[0]
57
	if _, err = service.plunkClient.Contacts.Delete(ctx, contact.ID); err != nil {
58
		return service.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, fmt.Sprintf("cannot delete user with ID [%s] from contacts", contact.Data[string(semconv.EnduserIDKey)])))
59
	}
60
61
	ctxLogger.Info(fmt.Sprintf("deleted user with ID [%s] from as marketting contact with ID [%s]", contact.Data[string(semconv.EnduserIDKey)], contact.ID))
62
	return nil
63
}
64
65
// CreateContact adds a new user on the onboarding automation.
66
func (service *MarketingService) CreateContact(ctx context.Context, userID entities.UserID) error {
67
	ctx, span, ctxLogger := service.tracer.StartWithLogger(ctx, service.logger)
68
	defer span.End()
69
70
	userRecord, err := service.authClient.GetUser(ctx, userID.String())
71
	if err != nil {
72
		msg := fmt.Sprintf("cannot get auth user with id [%s]", userID)
73
		return service.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))
74
	}
75
76
	data := service.attributes(userRecord)
77
	data[string(semconv.ServiceNameKey)] = "httpsms.com"
78
	data[string(semconv.EnduserIDKey)] = userRecord.UID
79
80
	event, _, err := service.plunkClient.Tracker.TrackEvent(ctx, &plunk.TrackEventRequest{
81
		Email:      userRecord.Email,
82
		Event:      "contact.created",
83
		Subscribed: true,
84
		Data:       data,
85
	})
86
	if err != nil {
87
		msg := fmt.Sprintf("cannot create contact for user with id [%s]", userID)
88
		return service.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, msg))
89
	}
90
91
	ctxLogger.Info(fmt.Sprintf("user [%s] added to marketting list with contact ID [%s] and event ID [%s]", userID, event.Data.Contact, event.Data.Event))
92
	return nil
93
}
94
95
func (service *MarketingService) attributes(user *auth.UserRecord) map[string]any {
96
	name := strings.TrimSpace(user.DisplayName)
97
	if name == "" {
98
		return fiber.Map{}
99
	}
100
101
	parts := strings.Split(name, " ")
102
	if len(parts) == 1 {
103
		return fiber.Map{
104
			"firstName": name,
105
		}
106
	}
107
108
	return fiber.Map{
109
		"firstName": strings.Join(parts[0:len(parts)-1], " "),
110
		"lastName":  parts[len(parts)-1],
111
	}
112
}
113