Skip to content

Commit

Permalink
add the feature of send documents
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielolivrp committed Jan 24, 2024
1 parent 3616336 commit db5b84f
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 0 deletions.
124 changes: 124 additions & 0 deletions api/handler/send_document_message_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package handler

import (
"net/http"
"zapmeow/api/helper"
"zapmeow/api/model"
"zapmeow/api/response"
"zapmeow/api/service"

"github.com/gin-gonic/gin"
"github.com/vincent-petithory/dataurl"
)

type sendDocumentMessageBody struct {
Phone string `json:"phone"`
Base64 string `json:"base64"`
Filename string `json:"filename"`
}

type sendDocumentMessageResponse struct {
Message response.Message `json:"message"`
}

type sendDocumentMessageHandler struct {
whatsAppService service.WhatsAppService
messageService service.MessageService
}

func NewSendDocumentMessageHandler(
whatsAppService service.WhatsAppService,
messageService service.MessageService,
) *sendDocumentMessageHandler {
return &sendDocumentMessageHandler{
whatsAppService: whatsAppService,
messageService: messageService,
}
}

// Send Image Message on WhatsApp
//
// @Summary Send Image Message on WhatsApp
// @Description Sends an image message on WhatsApp using the specified instance.
// @Tags WhatsApp Chat
// @Param instanceId path string true "Instance ID"
// @Param data body sendDocumentMessageBody true "Image message body"
// @Accept json
// @Produce json
// @Success 200 {object} sendDocumentMessageResponse "Message Send Response"
// @Router /{instanceId}/chat/send/image [post]
func (h *sendDocumentMessageHandler) Handler(c *gin.Context) {
instanceID := c.Param("instanceId")
instance, err := h.whatsAppService.GetInstance(instanceID)
if err != nil {
response.ErrorResponse(c, http.StatusInternalServerError, err.Error())
return
}

if !h.whatsAppService.IsAuthenticated(instance) {
response.ErrorResponse(c, http.StatusUnauthorized, "unautenticated")
return
}

var body sendDocumentMessageBody
if err := c.ShouldBindJSON(&body); err != nil {
response.ErrorResponse(c, http.StatusBadRequest, "Error trying to validate infos. ")
return
}

jid, ok := helper.MakeJID(body.Phone)
if !ok {
response.ErrorResponse(c, http.StatusBadRequest, "Invalid phone")
return
}

mimitype, err := helper.GetMimeTypeFromDataURI(body.Base64)
if err != nil {
response.ErrorResponse(c, http.StatusInternalServerError, err.Error())
return
}

documentURL, err := dataurl.DecodeString(body.Base64)
if err != nil {
response.ErrorResponse(c, http.StatusInternalServerError, err.Error())
return
}

resp, err := h.whatsAppService.SendDocumentMessage(instance, jid, documentURL, mimitype, body.Filename)
if err != nil {
response.ErrorResponse(c, http.StatusInternalServerError, err.Error())
return
}

path, err := helper.SaveMedia(
instanceID,
resp.ID,
documentURL.Data,
mimitype,
)
if err != nil {
response.ErrorResponse(c, http.StatusInternalServerError, err.Error())
return
}

message := model.Message{
FromMe: true,
ChatJID: jid.User,
SenderJID: resp.Sender.User,
InstanceID: instanceID,
Timestamp: resp.Timestamp,
MessageID: resp.ID,
MediaType: "document",
MediaPath: path,
}

err = h.messageService.CreateMessage(&message)
if err != nil {
response.ErrorResponse(c, http.StatusInternalServerError, err.Error())
return
}

response.Response(c, http.StatusOK, sendDocumentMessageResponse{
Message: response.NewMessageResponse(message),
})
}
5 changes: 5 additions & 0 deletions api/route/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ func SetupRouter(
whatsAppService,
messageService,
)
sendDocumentMessageHandler := handler.NewSendDocumentMessageHandler(
whatsAppService,
messageService,
)

group := router.Group("/api")

Expand All @@ -80,6 +84,7 @@ func SetupRouter(
group.POST("/:instanceId/chat/send/text", sendTextMessageHandler.Handler)
group.POST("/:instanceId/chat/send/image", sendImageMessageHandler.Handler)
group.POST("/:instanceId/chat/send/audio", sendAudioMessageHandler.Handler)
group.POST("/:instanceId/chat/send/document", sendDocumentMessageHandler.Handler)
group.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))

return router
Expand Down
11 changes: 11 additions & 0 deletions api/service/whatsapp_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type WhatsAppService interface {
Logout(instance *whatsapp.Instance) error
SendTextMessage(instance *whatsapp.Instance, jid whatsapp.JID, text string) (whatsapp.MessageResponse, error)
SendAudioMessage(instance *whatsapp.Instance, jid whatsapp.JID, audioURL *dataurl.DataURL, mimitype string) (whatsapp.MessageResponse, error)
SendDocumentMessage(instance *whatsapp.Instance, jid whatsapp.JID, documentURL *dataurl.DataURL, mimitype string, filename string) (whatsapp.MessageResponse, error)
SendImageMessage(instance *whatsapp.Instance, jid whatsapp.JID, imageURL *dataurl.DataURL, mimitype string) (whatsapp.MessageResponse, error)
GetContactInfo(instance *whatsapp.Instance, jid whatsapp.JID) (*whatsapp.ContactInfo, error)
ParseEventMessage(instance *whatsapp.Instance, message *events.Message) (whatsapp.Message, error)
Expand Down Expand Up @@ -57,6 +58,16 @@ func (w *whatsAppService) SendTextMessage(
return w.whatsApp.SendTextMessage(instance, jid, text)
}

func (w *whatsAppService) SendDocumentMessage(
instance *whatsapp.Instance,
jid whatsapp.JID,
documentURL *dataurl.DataURL,
mimitype string,
filename string,
) (whatsapp.MessageResponse, error) {
return w.whatsApp.SendDocumentMessage(instance, jid, documentURL, mimitype, filename)
}

func (w *whatsAppService) SendAudioMessage(
instance *whatsapp.Instance,
jid whatsapp.JID,
Expand Down
25 changes: 25 additions & 0 deletions pkg/whatsapp/whatsapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ type WhatsApp interface {
SendTextMessage(instance *Instance, jid JID, text string) (MessageResponse, error)
SendAudioMessage(instance *Instance, jid JID, audioURL *dataurl.DataURL, mimitype string) (MessageResponse, error)
SendImageMessage(instance *Instance, jid JID, imageURL *dataurl.DataURL, mimitype string) (MessageResponse, error)
SendDocumentMessage(instance *Instance, jid JID, documentURL *dataurl.DataURL, mimitype string, filename string) (MessageResponse, error)
GetContactInfo(instance *Instance, jid JID) (*ContactInfo, error)
ParseEventMessage(instance *Instance, message *events.Message) (Message, error)
IsOnWhatsApp(instance *Instance, phones []string) ([]IsOnWhatsAppResponse, error)
Expand Down Expand Up @@ -257,6 +258,28 @@ func (w *whatsApp) SendImageMessage(instance *Instance, jid JID, imageURL *datau
return w.sendMessage(instance, jid, message)
}

func (w *whatsApp) SendDocumentMessage(
instance *Instance, jid JID, documentURL *dataurl.DataURL, mimitype string, filename string) (MessageResponse, error) {
uploaded, err := w.uploadMedia(instance, documentURL, Document)
if err != nil {
return MessageResponse{}, err
}

message := &waProto.Message{
DocumentMessage: &waProto.DocumentMessage{
Url: proto.String(uploaded.URL),
FileName: &filename,
DirectPath: proto.String(uploaded.DirectPath),
MediaKey: uploaded.MediaKey,
Mimetype: proto.String(mimitype),
FileEncSha256: uploaded.FileEncSHA256,
FileSha256: uploaded.FileSHA256,
FileLength: proto.Uint64(uint64(len(documentURL.Data))),
},
}
return w.sendMessage(instance, jid, message)
}

func (w *whatsApp) IsOnWhatsApp(instance *Instance, phones []string) ([]IsOnWhatsAppResponse, error) {
isOnWhatsAppResponse, err := instance.Client.IsOnWhatsApp(phones)
if err != nil {
Expand Down Expand Up @@ -366,6 +389,8 @@ func (w *whatsApp) uploadMedia(instance *Instance, media *dataurl.DataURL, media
mType = whatsmeow.MediaImage
case Audio:
mType = whatsmeow.MediaAudio
case Document:
mType = whatsmeow.MediaDocument
default:
return nil, errors.New("unknown media type")
}
Expand Down

0 comments on commit db5b84f

Please sign in to comment.