Closes #51 Reviewed-on: phoenix/textsender-api#52 Co-authored-by: phoenix <kundeng00@pm.me> Co-committed-by: phoenix <kundeng00@pm.me>
192 lines
5.8 KiB
Go
192 lines
5.8 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.kundeng.us/phoenix/swoosh/swoop/send"
|
|
"git.kundeng.us/phoenix/textsender-models/tx0/contact"
|
|
"git.kundeng.us/phoenix/textsender-models/tx0/message"
|
|
"github.com/google/uuid"
|
|
|
|
"git.kundeng.us/phoenix/textsender-api/internal/app"
|
|
"git.kundeng.us/phoenix/textsender-api/internal/store"
|
|
)
|
|
|
|
const Contact_Limit = 400
|
|
|
|
type SendInstantMessageHandler struct {
|
|
App *app.App
|
|
MERStore store.MessageEventResponseStore
|
|
ContactStore store.ContactStore
|
|
MessageStore store.MessageStore
|
|
}
|
|
|
|
func NewSendInstantMessageHandler(apiApp *app.App, str store.MessageEventResponseStore, cStore store.ContactStore, mStore store.MessageStore) *SendInstantMessageHandler {
|
|
return &SendInstantMessageHandler{App: apiApp, MERStore: str, ContactStore: cStore, MessageStore: mStore}
|
|
}
|
|
|
|
type SendInstantMessageRequest struct {
|
|
ContactIds []uuid.UUID `json:"contact_ids"`
|
|
MessageId uuid.UUID `json:"message_id"`
|
|
UserId uuid.UUID `json:"user_id"`
|
|
}
|
|
|
|
type SendInstantMessageResponse struct {
|
|
Message string `json:"message"`
|
|
Data []*message.MessageEventResponse `json:"data"`
|
|
}
|
|
|
|
// Sent godoc
|
|
// @Summary Send instant message
|
|
// @Description Send a message without the constraints of scheduled messages (requires JWT)
|
|
// @Tags messages
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Security BearerAuth
|
|
// @Param request body SendInstantMessageRequest true "Send an instnt message"
|
|
// @Success 201 {object} SendInstantMessageResponse
|
|
// @Failure 400 {object} SendInstantMessageResponse
|
|
// @Failure 500 {object} SendInstantMessageResponse
|
|
// @Router /instant/message [post]
|
|
func (s *SendInstantMessageHandler) Send(w http.ResponseWriter, r *http.Request) {
|
|
var req SendInstantMessageRequest
|
|
if err := ExtractFromRequest(r, &req); err != nil {
|
|
http.Error(w, InvalidJson(err), http.StatusBadRequest)
|
|
}
|
|
defer r.Body.Close()
|
|
|
|
var statusCode int
|
|
var resp SendInstantMessageResponse
|
|
|
|
if req.UserId == uuid.Nil {
|
|
statusCode = http.StatusBadRequest
|
|
resp.Message = "User Id is nil"
|
|
} else if req.MessageId == uuid.Nil {
|
|
statusCode = http.StatusBadRequest
|
|
resp.Message = "Message Id is nil"
|
|
} else if len(req.ContactIds) == 0 {
|
|
statusCode = http.StatusBadRequest
|
|
resp.Message = "No contacts provided"
|
|
} else {
|
|
if len(req.ContactIds) > Contact_Limit {
|
|
statusCode = http.StatusBadRequest
|
|
resp.Message = "Too many contacts"
|
|
} else {
|
|
ctx := r.Context()
|
|
if msg, contacts, err := s.verify(ctx, &req); err != nil {
|
|
statusCode = http.StatusInternalServerError
|
|
resp.Message = err.Error()
|
|
} else {
|
|
if msg == nil {
|
|
statusCode = http.StatusBadRequest
|
|
resp.Message = "Message is empty"
|
|
} else if len(contacts) == 0 {
|
|
statusCode = http.StatusBadRequest
|
|
resp.Message = "Contacts not found"
|
|
} else {
|
|
if s.App != nil {
|
|
msgSender := send.MessageSender{Config: s.App.TwilioConfig}
|
|
for _, c := range contacts {
|
|
if twilioResp, err := msgSender.Send(*msg, *c, nil); err != nil {
|
|
statusCode = http.StatusInternalServerError
|
|
resp.Message = err.Error()
|
|
} else {
|
|
if data, err := json.Marshal(twilioResp); err != nil {
|
|
statusCode = http.StatusInternalServerError
|
|
resp.Message = err.Error()
|
|
} else {
|
|
dateStr := strings.TrimSpace(*twilioResp.DateUpdated)
|
|
if parsedTime, err := time.Parse(time.RFC1123Z, dateStr); err != nil {
|
|
statusCode = http.StatusInternalServerError
|
|
resp.Message = err.Error()
|
|
} else {
|
|
mer := message.MessageEventResponse{}
|
|
mer.Response = data
|
|
mer.UserId = req.UserId
|
|
mer.Sent = parsedTime
|
|
if err := s.MERStore.Create(ctx, &mer); err != nil {
|
|
statusCode = http.StatusInternalServerError
|
|
resp.Message = err.Error()
|
|
} else {
|
|
statusCode = http.StatusOK
|
|
resp.Message = "Successful"
|
|
resp.Data = append(resp.Data, &mer)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
statusCode = http.StatusInternalServerError
|
|
resp.Message = "Config not properly configured"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RespondWithJSON(w, statusCode, &resp)
|
|
}
|
|
|
|
func (s *SendInstantMessageHandler) verify(ctx context.Context, req *SendInstantMessageRequest) (*message.Message, []*contact.Contact, error) {
|
|
if msg, err := s.verifyMessage(ctx, req.MessageId); err != nil {
|
|
log.Println("Huh?")
|
|
return nil, nil, fmt.Errorf("Error:%v", err)
|
|
} else {
|
|
log.Println("Okay")
|
|
if msg != nil {
|
|
if contacts, err := s.verifyContacts(ctx, req.ContactIds); err != nil {
|
|
return nil, nil, fmt.Errorf("Error:%v", err)
|
|
} else {
|
|
if len(contacts) == 0 {
|
|
return msg, nil, nil
|
|
} else {
|
|
return msg, contacts, nil
|
|
}
|
|
}
|
|
} else {
|
|
log.Println("How can this be?")
|
|
return nil, nil, fmt.Errorf("Could not verify message")
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *SendInstantMessageHandler) verifyMessage(ctx context.Context, messageId uuid.UUID) (*message.Message, error) {
|
|
if msg, err := s.MessageStore.GetMessageByID(ctx, messageId); err != nil {
|
|
return nil, fmt.Errorf("Error getting message:%v", err)
|
|
} else {
|
|
if msg == nil {
|
|
log.Println("Message is nil")
|
|
return nil, nil
|
|
} else {
|
|
return msg, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *SendInstantMessageHandler) verifyContacts(ctx context.Context, contactIds []uuid.UUID) ([]*contact.Contact, error) {
|
|
var contacts []*contact.Contact
|
|
|
|
for _, contactId := range contactIds {
|
|
if c, err := s.ContactStore.GetContactByID(ctx, contactId); err != nil {
|
|
return nil, fmt.Errorf("Error getting contacts:%v", err)
|
|
} else {
|
|
if c != nil {
|
|
contacts = append(contacts, c)
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(contacts) == 0 {
|
|
return nil, nil
|
|
} else {
|
|
return contacts, nil
|
|
}
|
|
}
|