Browse Source
feat: add reaction (#60)
feat: add reaction (#60)
* feat: add reaction * feat: separate message new domain * feat: update open api * feat: update UI * feat: update go modulespull/61/head
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 496 additions and 201 deletions
-
77docs/openapi.yaml
-
2src/cmd/root.go
-
2src/config/settings.go
-
9src/domains/message/message.go
-
12src/domains/message/reaction.go
-
11src/domains/message/revoke.go
-
12src/domains/message/update.go
-
10src/domains/send/message.go
-
2src/domains/send/send.go
-
11src/go.mod
-
59src/go.sum
-
78src/internal/rest/message.go
-
40src/internal/rest/send.go
-
95src/services/message.go
-
42src/services/send.go
-
50src/validations/message_validation.go
-
27src/validations/send_validation.go
-
156src/views/index.html
@ -0,0 +1,9 @@ |
|||
package message |
|||
|
|||
import "context" |
|||
|
|||
type IMessageService interface { |
|||
ReactMessage(ctx context.Context, request ReactionRequest) (response ReactionResponse, err error) |
|||
RevokeMessage(ctx context.Context, request RevokeRequest) (response RevokeResponse, err error) |
|||
UpdateMessage(ctx context.Context, request UpdateMessageRequest) (response UpdateMessageResponse, err error) |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
package message |
|||
|
|||
type ReactionRequest struct { |
|||
MessageID string `json:"message_id" form:"message_id"` |
|||
Phone string `json:"phone" form:"phone"` |
|||
Emoji string `json:"emoji" form:"emoji"` |
|||
} |
|||
|
|||
type ReactionResponse struct { |
|||
MessageID string `json:"message_id"` |
|||
Status string `json:"status"` |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
package message |
|||
|
|||
type RevokeRequest struct { |
|||
MessageID string `json:"message_id" uri:"message_id"` |
|||
Phone string `json:"phone" form:"phone"` |
|||
} |
|||
|
|||
type RevokeResponse struct { |
|||
MessageID string `json:"message_id"` |
|||
Status string `json:"status"` |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
package message |
|||
|
|||
type UpdateMessageRequest struct { |
|||
MessageID string `json:"message_id" uri:"message_id"` |
|||
Message string `json:"message" form:"message"` |
|||
Phone string `json:"phone" form:"phone"` |
|||
} |
|||
|
|||
type UpdateMessageResponse struct { |
|||
MessageID string `json:"message_id"` |
|||
Status string `json:"status"` |
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
package rest |
|||
|
|||
import ( |
|||
"github.com/aldinokemal/go-whatsapp-web-multidevice/domains/message" |
|||
domainMessage "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/message" |
|||
"github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/utils" |
|||
"github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/whatsapp" |
|||
"github.com/gofiber/fiber/v2" |
|||
) |
|||
|
|||
type Message struct { |
|||
Service domainMessage.IMessageService |
|||
} |
|||
|
|||
func InitRestMessage(app *fiber.App, service domainMessage.IMessageService) Message { |
|||
rest := Message{Service: service} |
|||
app.Post("/message/:message_id/reaction", rest.ReactMessage) |
|||
app.Post("/message/:message_id/revoke", rest.RevokeMessage) |
|||
app.Post("/message/:message_id/update", rest.UpdateMessage) |
|||
return rest |
|||
} |
|||
|
|||
func (controller *Message) RevokeMessage(c *fiber.Ctx) error { |
|||
var request domainMessage.RevokeRequest |
|||
err := c.BodyParser(&request) |
|||
utils.PanicIfNeeded(err) |
|||
|
|||
request.MessageID = c.Params("message_id") |
|||
whatsapp.SanitizePhone(&request.Phone) |
|||
|
|||
response, err := controller.Service.RevokeMessage(c.UserContext(), request) |
|||
utils.PanicIfNeeded(err) |
|||
|
|||
return c.JSON(utils.ResponseData{ |
|||
Status: 200, |
|||
Code: "SUCCESS", |
|||
Message: response.Status, |
|||
Results: response, |
|||
}) |
|||
} |
|||
|
|||
func (controller *Message) UpdateMessage(c *fiber.Ctx) error { |
|||
var request domainMessage.UpdateMessageRequest |
|||
err := c.BodyParser(&request) |
|||
utils.PanicIfNeeded(err) |
|||
|
|||
request.MessageID = c.Params("message_id") |
|||
whatsapp.SanitizePhone(&request.Phone) |
|||
|
|||
response, err := controller.Service.UpdateMessage(c.UserContext(), request) |
|||
utils.PanicIfNeeded(err) |
|||
|
|||
return c.JSON(utils.ResponseData{ |
|||
Status: 200, |
|||
Code: "SUCCESS", |
|||
Message: response.Status, |
|||
Results: response, |
|||
}) |
|||
} |
|||
|
|||
func (controller *Message) ReactMessage(c *fiber.Ctx) error { |
|||
var request message.ReactionRequest |
|||
err := c.BodyParser(&request) |
|||
utils.PanicIfNeeded(err) |
|||
|
|||
request.MessageID = c.Params("message_id") |
|||
whatsapp.SanitizePhone(&request.Phone) |
|||
|
|||
response, err := controller.Service.ReactMessage(c.UserContext(), request) |
|||
utils.PanicIfNeeded(err) |
|||
|
|||
return c.JSON(utils.ResponseData{ |
|||
Status: 200, |
|||
Code: "SUCCESS", |
|||
Message: response.Status, |
|||
Results: response, |
|||
}) |
|||
} |
|||
@ -0,0 +1,95 @@ |
|||
package services |
|||
|
|||
import ( |
|||
"context" |
|||
"fmt" |
|||
"github.com/aldinokemal/go-whatsapp-web-multidevice/domains/message" |
|||
domainMessage "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/message" |
|||
"github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/whatsapp" |
|||
"github.com/aldinokemal/go-whatsapp-web-multidevice/validations" |
|||
"go.mau.fi/whatsmeow" |
|||
waProto "go.mau.fi/whatsmeow/binary/proto" |
|||
"go.mau.fi/whatsmeow/types" |
|||
"google.golang.org/protobuf/proto" |
|||
"time" |
|||
) |
|||
|
|||
type serviceMessage struct { |
|||
WaCli *whatsmeow.Client |
|||
} |
|||
|
|||
func NewMessageService(waCli *whatsmeow.Client) domainMessage.IMessageService { |
|||
return &serviceMessage{ |
|||
WaCli: waCli, |
|||
} |
|||
} |
|||
|
|||
func (service serviceMessage) ReactMessage(ctx context.Context, request message.ReactionRequest) (response message.ReactionResponse, err error) { |
|||
if err = validations.ValidateReactMessage(ctx, request); err != nil { |
|||
return response, err |
|||
} |
|||
dataWaRecipient, err := whatsapp.ValidateJidWithLogin(service.WaCli, request.Phone) |
|||
if err != nil { |
|||
return response, err |
|||
} |
|||
|
|||
msg := &waProto.Message{ |
|||
ReactionMessage: &waProto.ReactionMessage{ |
|||
Key: &waProto.MessageKey{ |
|||
FromMe: proto.Bool(true), |
|||
Id: proto.String(request.MessageID), |
|||
RemoteJid: proto.String(dataWaRecipient.String()), |
|||
}, |
|||
Text: proto.String(request.Emoji), |
|||
SenderTimestampMs: proto.Int64(time.Now().UnixMilli()), |
|||
}, |
|||
} |
|||
ts, err := service.WaCli.SendMessage(ctx, dataWaRecipient, msg) |
|||
if err != nil { |
|||
return response, err |
|||
} |
|||
|
|||
response.MessageID = ts.ID |
|||
response.Status = fmt.Sprintf("Reaction sent to %s (server timestamp: %s)", request.Phone, ts) |
|||
return response, nil |
|||
} |
|||
|
|||
func (service serviceMessage) RevokeMessage(ctx context.Context, request domainMessage.RevokeRequest) (response domainMessage.RevokeResponse, err error) { |
|||
if err = validations.ValidateRevokeMessage(ctx, request); err != nil { |
|||
return response, err |
|||
} |
|||
dataWaRecipient, err := whatsapp.ValidateJidWithLogin(service.WaCli, request.Phone) |
|||
if err != nil { |
|||
return response, err |
|||
} |
|||
|
|||
ts, err := service.WaCli.SendMessage(context.Background(), dataWaRecipient, service.WaCli.BuildRevoke(dataWaRecipient, types.EmptyJID, request.MessageID)) |
|||
if err != nil { |
|||
return response, err |
|||
} |
|||
|
|||
response.MessageID = ts.ID |
|||
response.Status = fmt.Sprintf("Revoke success %s (server timestamp: %s)", request.Phone, ts) |
|||
return response, nil |
|||
} |
|||
|
|||
func (service serviceMessage) UpdateMessage(ctx context.Context, request domainMessage.UpdateMessageRequest) (response domainMessage.UpdateMessageResponse, err error) { |
|||
if err = validations.ValidateUpdateMessage(ctx, request); err != nil { |
|||
return response, err |
|||
} |
|||
|
|||
dataWaRecipient, err := whatsapp.ValidateJidWithLogin(service.WaCli, request.Phone) |
|||
if err != nil { |
|||
return response, err |
|||
} |
|||
|
|||
msg := &waProto.Message{Conversation: proto.String(request.Message)} |
|||
ts, err := service.WaCli.SendMessage(context.Background(), dataWaRecipient, service.WaCli.BuildEdit(dataWaRecipient, request.MessageID, msg)) |
|||
if err != nil { |
|||
return response, err |
|||
} |
|||
|
|||
response.MessageID = ts.ID |
|||
response.Status = fmt.Sprintf("Update message success %s (server timestamp: %s)", request.Phone, ts) |
|||
return response, nil |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
package validations |
|||
|
|||
import ( |
|||
"context" |
|||
"github.com/aldinokemal/go-whatsapp-web-multidevice/domains/message" |
|||
domainMessage "github.com/aldinokemal/go-whatsapp-web-multidevice/domains/message" |
|||
pkgError "github.com/aldinokemal/go-whatsapp-web-multidevice/pkg/error" |
|||
validation "github.com/go-ozzo/ozzo-validation/v4" |
|||
) |
|||
|
|||
func ValidateRevokeMessage(ctx context.Context, request domainMessage.RevokeRequest) error { |
|||
err := validation.ValidateStructWithContext(ctx, &request, |
|||
validation.Field(&request.Phone, validation.Required), |
|||
validation.Field(&request.MessageID, validation.Required), |
|||
) |
|||
|
|||
if err != nil { |
|||
return pkgError.ValidationError(err.Error()) |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func ValidateUpdateMessage(ctx context.Context, request domainMessage.UpdateMessageRequest) error { |
|||
err := validation.ValidateStructWithContext(ctx, &request, |
|||
validation.Field(&request.Phone, validation.Required), |
|||
validation.Field(&request.MessageID, validation.Required), |
|||
validation.Field(&request.Message, validation.Required), |
|||
) |
|||
|
|||
if err != nil { |
|||
return pkgError.ValidationError(err.Error()) |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
|
|||
func ValidateReactMessage(ctx context.Context, request message.ReactionRequest) error { |
|||
err := validation.ValidateStructWithContext(ctx, &request, |
|||
validation.Field(&request.Phone, validation.Required), |
|||
validation.Field(&request.MessageID, validation.Required), |
|||
validation.Field(&request.Emoji, validation.Required), |
|||
) |
|||
|
|||
if err != nil { |
|||
return pkgError.ValidationError(err.Error()) |
|||
} |
|||
|
|||
return nil |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue