Browse Source

feat: add send link

feat: add more response when send api
pull/29/head
Aldino Kemal 3 years ago
parent
commit
025690fb44
  1. 2
      src/config/settings.go
  2. 3
      src/domains/send/contact.go
  3. 4
      src/domains/send/file.go
  4. 4
      src/domains/send/image.go
  5. 13
      src/domains/send/link.go
  6. 1
      src/domains/send/send.go
  7. 3
      src/domains/send/text.go
  8. 4
      src/domains/send/video.go
  9. 25
      src/internal/rest/send_controller.go
  10. 92
      src/services/send_service.go
  11. 16
      src/validations/send_validation.go

2
src/config/settings.go

@ -6,7 +6,7 @@ import (
) )
var ( var (
AppVersion = "v3.7.1"
AppVersion = "v3.10.0"
AppPort = "3000" AppPort = "3000"
AppDebug = false AppDebug = false
AppOs = fmt.Sprintf("AldinoKemal") AppOs = fmt.Sprintf("AldinoKemal")

3
src/domains/send/contact.go

@ -8,5 +8,6 @@ type ContactRequest struct {
} }
type ContactResponse struct { type ContactResponse struct {
Status string `json:"status"`
MessageID string `json:"message_id"`
Status string `json:"status"`
} }

4
src/domains/send/file.go

@ -9,5 +9,7 @@ type FileRequest struct {
} }
type FileResponse struct { type FileResponse struct {
Status string `json:"status"`
MessageID string `json:"message_id"`
Status string `json:"status"`
Url string `json:"url"`
} }

4
src/domains/send/image.go

@ -12,5 +12,7 @@ type ImageRequest struct {
} }
type ImageResponse struct { type ImageResponse struct {
Status string `json:"status"`
MessageID string `json:"message_id"`
Status string `json:"status"`
Url string `json:"url"`
} }

13
src/domains/send/link.go

@ -0,0 +1,13 @@
package send
type LinkRequest struct {
Phone string `json:"phone" form:"phone"`
Caption string `json:"caption"`
Link string `json:"link"`
Type Type `json:"type" form:"type"`
}
type LinkResponse struct {
MessageID string `json:"message_id"`
Status string `json:"status"`
}

1
src/domains/send/send.go

@ -15,4 +15,5 @@ type ISendService interface {
SendFile(ctx context.Context, request FileRequest) (response FileResponse, err error) SendFile(ctx context.Context, request FileRequest) (response FileResponse, err error)
SendVideo(ctx context.Context, request VideoRequest) (response VideoResponse, err error) SendVideo(ctx context.Context, request VideoRequest) (response VideoResponse, err error)
SendContact(ctx context.Context, request ContactRequest) (response ContactResponse, err error) SendContact(ctx context.Context, request ContactRequest) (response ContactResponse, err error)
SendLink(ctx context.Context, request LinkRequest) (response LinkResponse, err error)
} }

3
src/domains/send/text.go

@ -7,5 +7,6 @@ type MessageRequest struct {
} }
type MessageResponse struct { type MessageResponse struct {
Status string `json:"status"`
MessageID string `json:"message_id"`
Status string `json:"status"`
} }

4
src/domains/send/video.go

@ -12,5 +12,7 @@ type VideoRequest struct {
} }
type VideoResponse struct { type VideoResponse struct {
Status string `json:"status"`
MessageID string `json:"message_id"`
Status string `json:"status"`
Url string `json:"url"`
} }

25
src/internal/rest/send_controller.go

@ -18,6 +18,7 @@ func InitRestSend(app *fiber.App, service domainSend.ISendService) Send {
app.Post("/send/file", rest.SendFile) app.Post("/send/file", rest.SendFile)
app.Post("/send/video", rest.SendVideo) app.Post("/send/video", rest.SendVideo)
app.Post("/send/contact", rest.SendContact) app.Post("/send/contact", rest.SendContact)
app.Post("/send/link", rest.SendLink)
return rest return rest
} }
@ -158,3 +159,27 @@ func (controller *Send) SendContact(c *fiber.Ctx) error {
Results: response, Results: response,
}) })
} }
func (controller *Send) SendLink(c *fiber.Ctx) error {
var request domainSend.LinkRequest
err := c.BodyParser(&request)
utils.PanicIfNeeded(err)
err = validations.ValidateSendLink(request)
utils.PanicIfNeeded(err)
if request.Type == domainSend.TypeGroup {
request.Phone = request.Phone + "@g.us"
} else {
request.Phone = request.Phone + "@s.whatsapp.net"
}
response, err := controller.Service.SendLink(c.UserContext(), request)
utils.PanicIfNeeded(err)
return c.JSON(utils.ResponseData{
Code: 200,
Message: response.Status,
Results: response,
})
}

92
src/services/send_service.go

@ -35,13 +35,16 @@ func (service serviceSend) SendText(ctx context.Context, request domainSend.Mess
if !ok { if !ok {
return response, errors.New("invalid JID " + request.Phone) return response, errors.New("invalid JID " + request.Phone)
} }
msgId := whatsmeow.GenerateMessageID()
msg := &waProto.Message{Conversation: proto.String(request.Message)} msg := &waProto.Message{Conversation: proto.String(request.Message)}
ts, err := service.WaCli.SendMessage(ctx, recipient, "", msg)
ts, err := service.WaCli.SendMessage(ctx, recipient, msgId, msg)
if err != nil { if err != nil {
return response, err return response, err
} else {
response.Status = fmt.Sprintf("Message sent to %s (server timestamp: %s)", request.Phone, ts)
} }
response.MessageID = msgId
response.Status = fmt.Sprintf("Message sent to %s (server timestamp: %s)", request.Phone, ts)
return response, nil return response, nil
} }
@ -111,6 +114,7 @@ func (service serviceSend) SendImage(ctx context.Context, request domainSend.Ima
} }
dataWaThumbnail, err := os.ReadFile(imageThumbnail) dataWaThumbnail, err := os.ReadFile(imageThumbnail)
msgId := whatsmeow.GenerateMessageID()
msg := &waProto.Message{ImageMessage: &waProto.ImageMessage{ msg := &waProto.Message{ImageMessage: &waProto.ImageMessage{
JpegThumbnail: dataWaThumbnail, JpegThumbnail: dataWaThumbnail,
Caption: proto.String(dataWaCaption), Caption: proto.String(dataWaCaption),
@ -123,7 +127,7 @@ func (service serviceSend) SendImage(ctx context.Context, request domainSend.Ima
FileLength: proto.Uint64(uint64(len(dataWaImage))), FileLength: proto.Uint64(uint64(len(dataWaImage))),
ViewOnce: proto.Bool(request.ViewOnce), ViewOnce: proto.Bool(request.ViewOnce),
}} }}
ts, err := service.WaCli.SendMessage(ctx, dataWaRecipient, "", msg)
ts, err := service.WaCli.SendMessage(ctx, dataWaRecipient, msgId, msg)
go func() { go func() {
errDelete := utils.RemoveFile(0, deletedItems...) errDelete := utils.RemoveFile(0, deletedItems...)
if errDelete != nil { if errDelete != nil {
@ -132,10 +136,12 @@ func (service serviceSend) SendImage(ctx context.Context, request domainSend.Ima
}() }()
if err != nil { if err != nil {
return response, err return response, err
} else {
response.Status = fmt.Sprintf("Message sent to %s (server timestamp: %s)", request.Phone, ts)
return response, nil
} }
response.MessageID = msgId
response.Url = uploadedImage.URL
response.Status = fmt.Sprintf("Message sent to %s (server timestamp: %s)", request.Phone, ts)
return response, nil
} }
func (service serviceSend) SendFile(ctx context.Context, request domainSend.FileRequest) (response domainSend.FileResponse, err error) { func (service serviceSend) SendFile(ctx context.Context, request domainSend.FileRequest) (response domainSend.FileResponse, err error) {
@ -162,6 +168,7 @@ func (service serviceSend) SendFile(ctx context.Context, request domainSend.File
return response, err return response, err
} }
msgId := whatsmeow.GenerateMessageID()
msg := &waProto.Message{DocumentMessage: &waProto.DocumentMessage{ msg := &waProto.Message{DocumentMessage: &waProto.DocumentMessage{
Url: proto.String(uploadedFile.URL), Url: proto.String(uploadedFile.URL),
Mimetype: proto.String(http.DetectContentType(dataWaFile)), Mimetype: proto.String(http.DetectContentType(dataWaFile)),
@ -173,7 +180,7 @@ func (service serviceSend) SendFile(ctx context.Context, request domainSend.File
FileEncSha256: uploadedFile.FileEncSHA256, FileEncSha256: uploadedFile.FileEncSHA256,
DirectPath: proto.String(uploadedFile.DirectPath), DirectPath: proto.String(uploadedFile.DirectPath),
}} }}
ts, err := service.WaCli.SendMessage(ctx, dataWaRecipient, "", msg)
ts, err := service.WaCli.SendMessage(ctx, dataWaRecipient, msgId, msg)
go func() { go func() {
errDelete := utils.RemoveFile(0, oriFilePath) errDelete := utils.RemoveFile(0, oriFilePath)
if errDelete != nil { if errDelete != nil {
@ -182,10 +189,12 @@ func (service serviceSend) SendFile(ctx context.Context, request domainSend.File
}() }()
if err != nil { if err != nil {
return response, err return response, err
} else {
response.Status = fmt.Sprintf("Document sent to %s (server timestamp: %s)", request.Phone, ts)
return response, nil
} }
response.MessageID = msgId
response.Url = uploadedFile.URL
response.Status = fmt.Sprintf("Document sent to %s (server timestamp: %s)", request.Phone, ts)
return response, nil
} }
func (service serviceSend) SendVideo(ctx context.Context, request domainSend.VideoRequest) (response domainSend.VideoResponse, err error) { func (service serviceSend) SendVideo(ctx context.Context, request domainSend.VideoRequest) (response domainSend.VideoResponse, err error) {
@ -250,7 +259,7 @@ func (service serviceSend) SendVideo(ctx context.Context, request domainSend.Vid
if err != nil { if err != nil {
return response, err return response, err
} }
uploadedFile, err := service.WaCli.Upload(context.Background(), dataWaVideo, whatsmeow.MediaVideo)
uploaded, err := service.WaCli.Upload(context.Background(), dataWaVideo, whatsmeow.MediaVideo)
if err != nil { if err != nil {
fmt.Printf("Failed to upload file: %v", err) fmt.Printf("Failed to upload file: %v", err)
return response, err return response, err
@ -260,19 +269,20 @@ func (service serviceSend) SendVideo(ctx context.Context, request domainSend.Vid
return response, err return response, err
} }
msgId := whatsmeow.GenerateMessageID()
msg := &waProto.Message{VideoMessage: &waProto.VideoMessage{ msg := &waProto.Message{VideoMessage: &waProto.VideoMessage{
Url: proto.String(uploadedFile.URL),
Url: proto.String(uploaded.URL),
Mimetype: proto.String(http.DetectContentType(dataWaVideo)), Mimetype: proto.String(http.DetectContentType(dataWaVideo)),
Caption: proto.String(request.Caption), Caption: proto.String(request.Caption),
FileLength: proto.Uint64(uploadedFile.FileLength),
FileSha256: uploadedFile.FileSHA256,
FileEncSha256: uploadedFile.FileEncSHA256,
MediaKey: uploadedFile.MediaKey,
DirectPath: proto.String(uploadedFile.DirectPath),
FileLength: proto.Uint64(uploaded.FileLength),
FileSha256: uploaded.FileSHA256,
FileEncSha256: uploaded.FileEncSHA256,
MediaKey: uploaded.MediaKey,
DirectPath: proto.String(uploaded.DirectPath),
ViewOnce: proto.Bool(request.ViewOnce), ViewOnce: proto.Bool(request.ViewOnce),
JpegThumbnail: dataWaThumbnail, JpegThumbnail: dataWaThumbnail,
}} }}
ts, err := service.WaCli.SendMessage(ctx, dataWaRecipient, "", msg)
ts, err := service.WaCli.SendMessage(ctx, dataWaRecipient, msgId, msg)
go func() { go func() {
errDelete := utils.RemoveFile(0, deletedItems...) errDelete := utils.RemoveFile(0, deletedItems...)
if errDelete != nil { if errDelete != nil {
@ -281,10 +291,12 @@ func (service serviceSend) SendVideo(ctx context.Context, request domainSend.Vid
}() }()
if err != nil { if err != nil {
return response, err return response, err
} else {
response.Status = fmt.Sprintf("Video sent to %s (server timestamp: %s)", request.Phone, ts)
return response, nil
} }
response.MessageID = msgId
response.Url = uploaded.URL
response.Status = fmt.Sprintf("Video sent to %s (server timestamp: %s)", request.Phone, ts)
return response, nil
} }
func (service serviceSend) SendContact(ctx context.Context, request domainSend.ContactRequest) (response domainSend.ContactResponse, err error) { func (service serviceSend) SendContact(ctx context.Context, request domainSend.ContactRequest) (response domainSend.ContactResponse, err error) {
@ -296,6 +308,7 @@ func (service serviceSend) SendContact(ctx context.Context, request domainSend.C
} }
msgVCard := fmt.Sprintf("BEGIN:VCARD\nVERSION:3.0\nN:;%v;;;\nFN:%v\nTEL;type=CELL;waid=%v:+%v\nEND:VCARD", msgVCard := fmt.Sprintf("BEGIN:VCARD\nVERSION:3.0\nN:;%v;;;\nFN:%v\nTEL;type=CELL;waid=%v:+%v\nEND:VCARD",
request.ContactName, request.ContactName, request.ContactPhone, request.ContactPhone) request.ContactName, request.ContactName, request.ContactPhone, request.ContactPhone)
msgId := whatsmeow.GenerateMessageID()
msg := &waProto.Message{ContactMessage: &waProto.ContactMessage{ msg := &waProto.Message{ContactMessage: &waProto.ContactMessage{
DisplayName: proto.String(request.ContactName), DisplayName: proto.String(request.ContactName),
Vcard: proto.String(msgVCard), Vcard: proto.String(msgVCard),
@ -303,8 +316,39 @@ func (service serviceSend) SendContact(ctx context.Context, request domainSend.C
ts, err := service.WaCli.SendMessage(ctx, recipient, "", msg) ts, err := service.WaCli.SendMessage(ctx, recipient, "", msg)
if err != nil { if err != nil {
return response, err return response, err
} else {
response.Status = fmt.Sprintf("Contact sent to %s (server timestamp: %s)", request.Phone, ts)
} }
response.MessageID = msgId
response.Status = fmt.Sprintf("Contact sent to %s (server timestamp: %s)", request.Phone, ts)
return response, nil
}
func (service serviceSend) SendLink(ctx context.Context, request domainSend.LinkRequest) (response domainSend.LinkResponse, err error) {
utils.MustLogin(service.WaCli)
recipient, ok := utils.ParseJID(request.Phone)
if !ok {
return response, errors.New("invalid JID " + request.Phone)
}
msgId := whatsmeow.GenerateMessageID()
msg := &waProto.Message{ExtendedTextMessage: &waProto.ExtendedTextMessage{
Text: proto.String(request.Caption),
MatchedText: proto.String(request.Caption),
CanonicalUrl: proto.String(request.Link),
ContextInfo: &waProto.ContextInfo{
ActionLink: &waProto.ActionLink{
Url: proto.String(request.Link),
ButtonTitle: proto.String(request.Caption),
},
},
}}
ts, err := service.WaCli.SendMessage(ctx, recipient, msgId, msg)
if err != nil {
return response, err
}
response.MessageID = msgId
response.Status = fmt.Sprintf("Link sent to %s (server timestamp: %s)", request.Phone, ts)
return response, nil return response, nil
} }

16
src/validations/send_validation.go

@ -113,3 +113,19 @@ func ValidateSendContact(request domainSend.ContactRequest) {
}) })
} }
} }
func ValidateSendLink(request domainSend.LinkRequest) error {
err := validation.ValidateStruct(&request,
validation.Field(&request.Phone, validation.Required, validation.Length(10, 25)),
validation.Field(&request.Link, validation.Required),
validation.Field(&request.Caption, validation.Required),
)
if err != nil {
return utils.ValidationError{
Message: err.Error(),
}
}
return nil
}
Loading…
Cancel
Save