MCPcopy Index your code
hub / github.com/NdoleStudio/httpsms / Store

Method Store

api/pkg/handlers/bulk_message_handler.go:92–147  ·  view source on GitHub ↗

Store sends bulk SMS messages from a CSV or Excel file. @Summary Store bulk SMS file @Description Sends bulk SMS messages to multiple users based on our [CSV template](https://httpsms.com/templates/httpsms-bulk.csv) or our [Excel template](https://httpsms.com/templates/httpsms-bulk.xlsx). @Sec

(c fiber.Ctx)

Source from the content-addressed store, hash-verified

90// @Failure 500 {object} responses.InternalServerError
91// @Router /bulk-messages [post]
92func (h *BulkMessageHandler) Store(c fiber.Ctx) error {
93 ctx, span, ctxLogger := h.tracer.StartFromFiberCtxWithLogger(c, h.logger)
94 defer span.End()
95
96 file, err := c.FormFile("document")
97 if err != nil {
98 msg := fmt.Sprintf("cannot fetch file with name [%s] from request", "document")
99 ctxLogger.Warn(stacktrace.Propagate(err, msg))
100 return h.responseBadRequest(c, err)
101 }
102
103 messages, userLocation, validationErrors := h.validator.ValidateStore(ctx, h.userIDFomContext(c), file)
104 if len(validationErrors) != 0 {
105 msg := fmt.Sprintf("validation errors [%s], while sending bulk sms from CSV file [%s] for [%s]", spew.Sdump(validationErrors), file.Filename, h.userIDFomContext(c))
106 ctxLogger.Warn(stacktrace.NewError(msg))
107 return h.responseUnprocessableEntity(c, validationErrors, "validation errors while sending bulk SMS")
108 }
109
110 if msg := h.billingService.IsEntitledWithCount(ctx, h.userIDFomContext(c), uint(len(messages))); msg != nil {
111 ctxLogger.Warn(stacktrace.NewError(fmt.Sprintf("user with ID [%s] is not entitled to send [%d] messages", h.userIDFomContext(c), len(messages))))
112 return h.responsePaymentRequired(c, *msg)
113 }
114
115 requestID := h.generateRequestID(file.Filename)
116 wg := sync.WaitGroup{}
117 count := atomic.Int64{}
118
119 // Compute per-phone index for rate-based dispatch delay
120 phoneIndexCounter := make(map[string]int)
121
122 for _, message := range messages {
123 wg.Add(1)
124 var perPhoneIndex int
125 if message.GetSendTime(userLocation) == nil {
126 perPhoneIndex = phoneIndexCounter[message.FromPhoneNumber]
127 phoneIndexCounter[message.FromPhoneNumber]++
128 }
129
130 go func(message *requests.BulkMessage, index int) {
131 count.Add(1)
132 _, err = h.messageService.SendMessage(
133 ctx,
134 message.ToMessageSendParams(h.userIDFomContext(c), requestID, c.OriginalURL(), index, userLocation),
135 )
136 if err != nil {
137 count.Add(-1)
138 msg := fmt.Sprintf("cannot send message with payload [%s] at index [%d]", spew.Sdump(message), index)
139 ctxLogger.Error(stacktrace.Propagate(err, msg))
140 }
141 wg.Done()
142 }(message, perPhoneIndex)
143 }
144
145 wg.Wait()
146 return h.responseAccepted(c, fmt.Sprintf("Added %d out of %d messages to the queue", count.Load(), len(messages)))
147}
148
149func (h *BulkMessageHandler) generateRequestID(filename string) string {

Callers

nothing calls this directly

Calls 15

generateRequestIDMethod · 0.95
responseBadRequestMethod · 0.80
userIDFomContextMethod · 0.80
IsEntitledWithCountMethod · 0.80
GetSendTimeMethod · 0.80
SendMessageMethod · 0.80
responseAcceptedMethod · 0.80
WarnMethod · 0.65
ErrorMethod · 0.65

Tested by

no test coverage detected