Passed
Push — main ( 842d7d...6d66c3 )
by Acho
03:04 queued 15s
created

services.*LemonsqueezyService.subscriptionName   D

Complexity

Conditions 13

Size

Total Lines 41
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 23
dl 0
loc 41
rs 4.2
c 0
b 0
f 0
nop 1

How to fix   Complexity   

Complexity

Complex classes like services.*LemonsqueezyService.subscriptionName often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package services
2
3
import (
4
	"context"
5
	"fmt"
6
	"strings"
7
	"time"
8
9
	"github.com/NdoleStudio/httpsms/pkg/repositories"
10
11
	"github.com/NdoleStudio/httpsms/pkg/entities"
12
	"github.com/NdoleStudio/httpsms/pkg/events"
13
	"github.com/NdoleStudio/httpsms/pkg/telemetry"
14
	lemonsqueezy "github.com/NdoleStudio/lemonsqueezy-go"
15
	"github.com/palantir/stacktrace"
16
)
17
18
// LemonsqueezyService is responsible for managing lemonsqueezy events
19
type LemonsqueezyService struct {
20
	service
21
	logger          telemetry.Logger
22
	tracer          telemetry.Tracer
23
	eventDispatcher *EventDispatcher
24
	userRepository  repositories.UserRepository
25
}
26
27
// NewLemonsqueezyService creates a new LemonsqueezyService
28
func NewLemonsqueezyService(
29
	logger telemetry.Logger,
30
	tracer telemetry.Tracer,
31
	repository repositories.UserRepository,
32
	eventDispatcher *EventDispatcher,
33
) (s *LemonsqueezyService) {
34
	return &LemonsqueezyService{
35
		logger:          logger.WithService(fmt.Sprintf("%T", s)),
36
		tracer:          tracer,
37
		userRepository:  repository,
38
		eventDispatcher: eventDispatcher,
39
	}
40
}
41
42
// HandleSubscriptionCreatedEvent handles the subscription_created lemonsqueezy event
43
func (service *LemonsqueezyService) HandleSubscriptionCreatedEvent(ctx context.Context, source string, request *lemonsqueezy.WebhookRequestSubscription) error {
44
	ctx, span, ctxLogger := service.tracer.StartWithLogger(ctx, service.logger)
45
	defer span.End()
46
47
	payload := &events.UserSubscriptionCreatedPayload{
48
		UserID:                entities.UserID(request.Meta.CustomData["user_id"].(string)),
49
		SubscriptionCreatedAt: request.Data.Attributes.CreatedAt,
50
		SubscriptionID:        request.Data.ID,
51
		SubscriptionName:      service.subscriptionName(request.Data.Attributes.VariantName),
52
		SubscriptionRenewsAt:  request.Data.Attributes.RenewsAt,
53
		SubscriptionStatus:    request.Data.Attributes.Status,
54
	}
55
56
	event, err := service.createEvent(events.UserSubscriptionCreated, source, payload)
57
	if err != nil {
58
		msg := fmt.Sprintf("cannot create [%s] event for user [%s]", events.UserSubscriptionCreated, payload.UserID)
59
		return stacktrace.Propagate(err, msg)
60
	}
61
62
	if err = service.eventDispatcher.Dispatch(ctx, event); err != nil {
63
		msg := fmt.Sprintf("cannot dispatch [%s] event for user [%s]", events.UserSubscriptionCreated, payload.UserID)
64
		return stacktrace.Propagate(err, msg)
65
	}
66
	ctxLogger.Info(fmt.Sprintf("[%s] subscription [%s] created for user [%s]", payload.SubscriptionName, payload.SubscriptionID, payload.UserID))
67
	return nil
68
}
69
70
// HandleSubscriptionCanceledEvent handles the subscription_cancelled lemonsqueezy event
71
func (service *LemonsqueezyService) HandleSubscriptionCanceledEvent(ctx context.Context, source string, request *lemonsqueezy.WebhookRequestSubscription) error {
72
	ctx, span, ctxLogger := service.tracer.StartWithLogger(ctx, service.logger)
73
	defer span.End()
74
75
	user, err := service.userRepository.LoadBySubscriptionID(ctx, request.Data.ID)
76
	if err != nil {
77
		msg := fmt.Sprintf("cannot load user with subscription ID [%s]", request.Data.ID)
78
		return stacktrace.Propagate(err, msg)
79
	}
80
81
	payload := &events.UserSubscriptionCancelledPayload{
82
		UserID:                  user.ID,
83
		SubscriptionCancelledAt: request.Data.Attributes.CreatedAt,
84
		SubscriptionID:          request.Data.ID,
85
		SubscriptionName:        service.subscriptionName(request.Data.Attributes.VariantName),
86
		SubscriptionEndsAt:      *request.Data.Attributes.EndsAt,
87
		SubscriptionStatus:      request.Data.Attributes.Status,
88
	}
89
90
	event, err := service.createEvent(events.UserSubscriptionCancelled, source, payload)
91
	if err != nil {
92
		msg := fmt.Sprintf("cannot created [%s] event for user [%s]", events.UserSubscriptionCancelled, payload.UserID)
93
		return stacktrace.Propagate(err, msg)
94
	}
95
96
	if err = service.eventDispatcher.Dispatch(ctx, event); err != nil {
97
		msg := fmt.Sprintf("cannot dispatch [%s] event for user [%s]", events.UserSubscriptionCancelled, payload.UserID)
98
		return stacktrace.Propagate(err, msg)
99
	}
100
	ctxLogger.Info(fmt.Sprintf("[%s] subscription [%s] cancelled for user [%s]", payload.SubscriptionName, payload.SubscriptionID, payload.UserID))
101
	return nil
102
}
103
104
// HandleSubscriptionUpdatedEvent handles the subscription_cancelled lemonsqueezy event
105
func (service *LemonsqueezyService) HandleSubscriptionUpdatedEvent(ctx context.Context, source string, request *lemonsqueezy.WebhookRequestSubscription) error {
106
	ctx, span, ctxLogger := service.tracer.StartWithLogger(ctx, service.logger)
107
	defer span.End()
108
109
	user, err := service.userRepository.LoadBySubscriptionID(ctx, request.Data.ID)
110
	if err != nil {
111
		msg := fmt.Sprintf("cannot load user with subscription ID [%s]", request.Data.ID)
112
		return stacktrace.Propagate(err, msg)
113
	}
114
115
	payload := &events.UserSubscriptionUpdatedPayload{
116
		UserID:                user.ID,
117
		SubscriptionUpdatedAt: request.Data.Attributes.UpdatedAt,
118
		SubscriptionID:        request.Data.ID,
119
		SubscriptionName:      service.subscriptionName(request.Data.Attributes.VariantName),
120
		SubscriptionEndsAt:    request.Data.Attributes.EndsAt,
121
		SubscriptionRenewsAt:  request.Data.Attributes.RenewsAt,
122
		SubscriptionStatus:    request.Data.Attributes.Status,
123
	}
124
125
	event, err := service.createEvent(events.UserSubscriptionUpdated, source, payload)
126
	if err != nil {
127
		msg := fmt.Sprintf("cannot created [%s] event for user [%s]", events.UserSubscriptionUpdated, payload.UserID)
128
		return stacktrace.Propagate(err, msg)
129
	}
130
131
	if err = service.eventDispatcher.Dispatch(ctx, event); err != nil {
132
		msg := fmt.Sprintf("cannot dispatch [%s] event for user [%s]", event.Type(), payload.UserID)
133
		return stacktrace.Propagate(err, msg)
134
	}
135
	ctxLogger.Info(fmt.Sprintf("[%s] subscription [%s] updated for user [%s]", payload.SubscriptionName, payload.SubscriptionID, payload.UserID))
136
	return nil
137
}
138
139
// HandleSubscriptionExpiredEvent handles the subscription_expired lemonsqueezy event
140
func (service *LemonsqueezyService) HandleSubscriptionExpiredEvent(ctx context.Context, source string, request *lemonsqueezy.WebhookRequestSubscription) error {
141
	ctx, span, ctxLogger := service.tracer.StartWithLogger(ctx, service.logger)
142
	defer span.End()
143
144
	user, err := service.userRepository.LoadBySubscriptionID(ctx, request.Data.ID)
145
	if err != nil {
146
		msg := fmt.Sprintf("cannot load user with subscription ID [%s]", request.Data.ID)
147
		return stacktrace.Propagate(err, msg)
148
	}
149
150
	payload := &events.UserSubscriptionExpiredPayload{
151
		UserID:                user.ID,
152
		SubscriptionExpiredAt: time.Now().UTC(),
153
		SubscriptionID:        request.Data.ID,
154
		IsCancelled:           request.Data.Attributes.Cancelled,
155
		SubscriptionName:      service.subscriptionName(request.Data.Attributes.VariantName),
156
		SubscriptionEndsAt:    *request.Data.Attributes.EndsAt,
157
		SubscriptionStatus:    request.Data.Attributes.Status,
158
	}
159
160
	event, err := service.createEvent(events.UserSubscriptionExpired, source, payload)
161
	if err != nil {
162
		msg := fmt.Sprintf("cannot created [%s] event for user [%s]", events.UserSubscriptionExpired, payload.UserID)
163
		return stacktrace.Propagate(err, msg)
164
	}
165
166
	if err = service.eventDispatcher.Dispatch(ctx, event); err != nil {
167
		msg := fmt.Sprintf("cannot dispatch [%s] event for user [%s]", event.Type(), payload.UserID)
168
		return stacktrace.Propagate(err, msg)
169
	}
170
	ctxLogger.Info(fmt.Sprintf("[%s] subscription [%s] expired for user [%s]", payload.SubscriptionName, payload.SubscriptionID, payload.UserID))
171
	return nil
172
}
173
174
func (service *LemonsqueezyService) subscriptionName(variant string) entities.SubscriptionName {
175
	if strings.Contains(strings.ToLower(variant), "pro") {
176
		if strings.Contains(strings.ToLower(variant), "monthly") {
177
			return entities.SubscriptionNameProMonthly
178
		}
179
		return entities.SubscriptionNameProYearly
180
	}
181
182
	if strings.Contains(strings.ToLower(variant), "ultra") {
183
		if strings.Contains(strings.ToLower(variant), "monthly") {
184
			return entities.SubscriptionNameUltraMonthly
185
		}
186
		return entities.SubscriptionNameUltraYearly
187
	}
188
189
	if strings.Contains(strings.ToLower(variant), "20k") {
190
		if strings.Contains(strings.ToLower(variant), "monthly") {
191
			return entities.SubscriptionName20KMonthly
192
		}
193
		return entities.SubscriptionName20KYearly
194
	}
195
196
	if strings.Contains(strings.ToLower(variant), "100k") {
197
		if strings.Contains(strings.ToLower(variant), "monthly") {
198
			return entities.SubscriptionName100KMonthly
199
		}
200
	}
201
202
	if strings.Contains(strings.ToLower(variant), "50k") {
203
		if strings.Contains(strings.ToLower(variant), "monthly") {
204
			return entities.SubscriptionName50KMonthly
205
		}
206
	}
207
208
	if strings.Contains(strings.ToLower(variant), "200k") {
209
		if strings.Contains(strings.ToLower(variant), "monthly") {
210
			return entities.SubscriptionName200KMonthly
211
		}
212
	}
213
214
	return entities.SubscriptionNameFree
215
}
216