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 } }