Spaces:
Runtime error
Runtime error
RyZ commited on
Commit ·
c099d87
1
Parent(s): fddd3d4
feat: adding contact fetching and sending message feature; qa: adding swagger UI
Browse files- controllers/auth_controller.go +44 -2
- controllers/chat_controller.go +98 -0
- controllers/connection_controller.go +34 -11
- docs/docs.go +590 -0
- docs/swagger.json +566 -0
- docs/swagger.yaml +369 -0
- go.mod +19 -1
- go.sum +77 -6
- main.go +18 -0
- models/dto/chat_dto.go +26 -0
- models/error/error.go +4 -0
- provider/controller_provider.go +8 -0
- provider/repositories_provider.go +8 -0
- provider/services_provider.go +8 -0
- repositories/chat_repository.go +48 -0
- router/auth_router.go +1 -1
- router/chat_router.go +19 -0
- router/router.go +8 -0
- services/chat_service.go +74 -0
controllers/auth_controller.go
CHANGED
|
@@ -28,6 +28,16 @@ func NewAuthController(authService services.AuthService) AuthController {
|
|
| 28 |
return &authController{authService: authService}
|
| 29 |
}
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
func (c *authController) Register(ctx *gin.Context) {
|
| 32 |
var req dto.RegisterRequest
|
| 33 |
if err := ctx.ShouldBindJSON(&req); err != nil {
|
|
@@ -48,7 +58,7 @@ func (c *authController) Register(ctx *gin.Context) {
|
|
| 48 |
}
|
| 49 |
|
| 50 |
ctx.SetSameSite(http.SameSiteNoneMode)
|
| 51 |
-
ctx.
|
| 52 |
ctx.SetCookie("Authorization", resp.Token, 3600*24, "/", "", true, true)
|
| 53 |
ctx.SetCookie("RefreshToken", resp.RefreshToken, 3600*24*365, "/api/auth/refresh", "", true, true)
|
| 54 |
ctx.SetCookie("XSRF-TOKEN", csrfToken, 3600*24, "/", "", true, false)
|
|
@@ -56,6 +66,16 @@ func (c *authController) Register(ctx *gin.Context) {
|
|
| 56 |
utils.SendResponse[dto.AuthResponse, any](ctx, nil, *resp, nil)
|
| 57 |
}
|
| 58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
func (c *authController) Login(ctx *gin.Context) {
|
| 60 |
var req dto.LoginRequest
|
| 61 |
if err := ctx.ShouldBindJSON(&req); err != nil {
|
|
@@ -75,7 +95,6 @@ func (c *authController) Login(ctx *gin.Context) {
|
|
| 75 |
return
|
| 76 |
}
|
| 77 |
|
| 78 |
-
ctx.SetSameSite(http.SameSiteNoneMode)
|
| 79 |
ctx.SetSameSite(http.SameSiteNoneMode)
|
| 80 |
ctx.SetCookie("Authorization", resp.Token, 3600*24, "/", "", true, true)
|
| 81 |
ctx.SetCookie("RefreshToken", resp.RefreshToken, 3600*24*365, "/api/auth/refresh", "", true, true)
|
|
@@ -84,6 +103,13 @@ func (c *authController) Login(ctx *gin.Context) {
|
|
| 84 |
utils.SendResponse[dto.AuthResponse, any](ctx, nil, *resp, nil)
|
| 85 |
}
|
| 86 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
func (c *authController) Logout(ctx *gin.Context) {
|
| 88 |
tokenString := ""
|
| 89 |
authHeader := ctx.GetHeader("Authorization")
|
|
@@ -109,6 +135,14 @@ func (c *authController) Logout(ctx *gin.Context) {
|
|
| 109 |
utils.SendResponse[any, any](ctx, nil, nil, nil)
|
| 110 |
}
|
| 111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
func (c *authController) RefreshToken(ctx *gin.Context) {
|
| 113 |
refreshToken, err := ctx.Cookie("RefreshToken")
|
| 114 |
if err != nil || refreshToken == "" {
|
|
@@ -133,6 +167,14 @@ func (c *authController) RefreshToken(ctx *gin.Context) {
|
|
| 133 |
}, nil)
|
| 134 |
}
|
| 135 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
func (c *authController) Me(ctx *gin.Context) {
|
| 137 |
userId, exists := ctx.Get("user_id")
|
| 138 |
if !exists {
|
|
|
|
| 28 |
return &authController{authService: authService}
|
| 29 |
}
|
| 30 |
|
| 31 |
+
// Register godoc
|
| 32 |
+
// @Summary Register a new user
|
| 33 |
+
// @Description Register a new user with the provided details
|
| 34 |
+
// @Tags auth
|
| 35 |
+
// @Accept json
|
| 36 |
+
// @Produce json
|
| 37 |
+
// @Param request body dto.RegisterRequest true "Register Request"
|
| 38 |
+
// @Success 200 {object} dto.AuthResponse
|
| 39 |
+
// @Failure 400 {object} dto.ErrorResponse
|
| 40 |
+
// @Router /auth/register [post]
|
| 41 |
func (c *authController) Register(ctx *gin.Context) {
|
| 42 |
var req dto.RegisterRequest
|
| 43 |
if err := ctx.ShouldBindJSON(&req); err != nil {
|
|
|
|
| 58 |
}
|
| 59 |
|
| 60 |
ctx.SetSameSite(http.SameSiteNoneMode)
|
| 61 |
+
ctx.Header("X-CSRF-Token", csrfToken)
|
| 62 |
ctx.SetCookie("Authorization", resp.Token, 3600*24, "/", "", true, true)
|
| 63 |
ctx.SetCookie("RefreshToken", resp.RefreshToken, 3600*24*365, "/api/auth/refresh", "", true, true)
|
| 64 |
ctx.SetCookie("XSRF-TOKEN", csrfToken, 3600*24, "/", "", true, false)
|
|
|
|
| 66 |
utils.SendResponse[dto.AuthResponse, any](ctx, nil, *resp, nil)
|
| 67 |
}
|
| 68 |
|
| 69 |
+
// Login godoc
|
| 70 |
+
// @Summary Login a user
|
| 71 |
+
// @Description Login a user with credentials
|
| 72 |
+
// @Tags auth
|
| 73 |
+
// @Accept json
|
| 74 |
+
// @Produce json
|
| 75 |
+
// @Param request body dto.LoginRequest true "Login Request"
|
| 76 |
+
// @Success 200 {object} dto.AuthResponse
|
| 77 |
+
// @Failure 400 {object} dto.ErrorResponse
|
| 78 |
+
// @Router /auth/login [post]
|
| 79 |
func (c *authController) Login(ctx *gin.Context) {
|
| 80 |
var req dto.LoginRequest
|
| 81 |
if err := ctx.ShouldBindJSON(&req); err != nil {
|
|
|
|
| 95 |
return
|
| 96 |
}
|
| 97 |
|
|
|
|
| 98 |
ctx.SetSameSite(http.SameSiteNoneMode)
|
| 99 |
ctx.SetCookie("Authorization", resp.Token, 3600*24, "/", "", true, true)
|
| 100 |
ctx.SetCookie("RefreshToken", resp.RefreshToken, 3600*24*365, "/api/auth/refresh", "", true, true)
|
|
|
|
| 103 |
utils.SendResponse[dto.AuthResponse, any](ctx, nil, *resp, nil)
|
| 104 |
}
|
| 105 |
|
| 106 |
+
// Logout godoc
|
| 107 |
+
// @Summary Logout a user
|
| 108 |
+
// @Description Logout the current user
|
| 109 |
+
// @Tags auth
|
| 110 |
+
// @Param X-CSRF-Token header string true "CSRF Protection Token"
|
| 111 |
+
// @Success 200
|
| 112 |
+
// @Router /auth/logout [post]
|
| 113 |
func (c *authController) Logout(ctx *gin.Context) {
|
| 114 |
tokenString := ""
|
| 115 |
authHeader := ctx.GetHeader("Authorization")
|
|
|
|
| 135 |
utils.SendResponse[any, any](ctx, nil, nil, nil)
|
| 136 |
}
|
| 137 |
|
| 138 |
+
// RefreshToken godoc
|
| 139 |
+
// @Summary Refresh access token
|
| 140 |
+
// @Description Refresh the access token using the refresh token cookie
|
| 141 |
+
// @Tags auth
|
| 142 |
+
// @Param X-CSRF-Token header string true "CSRF Protection Token"
|
| 143 |
+
// @Success 200 {object} dto.AuthResponse
|
| 144 |
+
// @Failure 401 {object} dto.ErrorResponse
|
| 145 |
+
// @Router /auth/refresh [post]
|
| 146 |
func (c *authController) RefreshToken(ctx *gin.Context) {
|
| 147 |
refreshToken, err := ctx.Cookie("RefreshToken")
|
| 148 |
if err != nil || refreshToken == "" {
|
|
|
|
| 167 |
}, nil)
|
| 168 |
}
|
| 169 |
|
| 170 |
+
// Me godoc
|
| 171 |
+
// @Summary Get current user profile
|
| 172 |
+
// @Description Get the profile of the currently logged-in user
|
| 173 |
+
// @Tags auth
|
| 174 |
+
// @Security BearerAuth
|
| 175 |
+
// @Success 200 {object} dto.MeResponse
|
| 176 |
+
// @Failure 401 {object} dto.ErrorResponse
|
| 177 |
+
// @Router /auth/me [get]
|
| 178 |
func (c *authController) Me(ctx *gin.Context) {
|
| 179 |
userId, exists := ctx.Get("user_id")
|
| 180 |
if !exists {
|
controllers/chat_controller.go
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package controllers
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"whatsapp-backend/models/dto"
|
| 5 |
+
http_error "whatsapp-backend/models/error"
|
| 6 |
+
"whatsapp-backend/services"
|
| 7 |
+
"whatsapp-backend/utils"
|
| 8 |
+
|
| 9 |
+
"github.com/gin-gonic/gin"
|
| 10 |
+
"github.com/google/uuid"
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
type ChatController interface {
|
| 14 |
+
FetchContacts(ctx *gin.Context)
|
| 15 |
+
SendMessage(ctx *gin.Context)
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
type chatController struct {
|
| 19 |
+
chatService services.ChatService
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
func NewChatController(chatService services.ChatService) ChatController {
|
| 23 |
+
return &chatController{chatService}
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
// FetchContacts godoc
|
| 27 |
+
// @Summary Fetch WhatsApp contacts
|
| 28 |
+
// @Description Fetch list of contacts from the connected WhatsApp account
|
| 29 |
+
// @Tags chat
|
| 30 |
+
// @Security BearerAuth
|
| 31 |
+
// @Accept json
|
| 32 |
+
// @Produce json
|
| 33 |
+
// @Success 200 {object} dto.FetchContactsResponse
|
| 34 |
+
// @Failure 401 {object} dto.ErrorResponse
|
| 35 |
+
// @Failure 400 {object} dto.ErrorResponse
|
| 36 |
+
// @Router /chat/fetch [get]
|
| 37 |
+
func (c *chatController) FetchContacts(ctx *gin.Context) {
|
| 38 |
+
userID, exists := ctx.Get("user_id")
|
| 39 |
+
if !exists {
|
| 40 |
+
utils.SendResponse[any, any](ctx, nil, nil, http_error.UNAUTHORIZED)
|
| 41 |
+
return
|
| 42 |
+
}
|
| 43 |
+
accountID := userID.(uuid.UUID)
|
| 44 |
+
|
| 45 |
+
contacts, err := c.chatService.FetchContacts(ctx, accountID)
|
| 46 |
+
if err != nil {
|
| 47 |
+
utils.SendResponse[any, any](ctx, nil, nil, err)
|
| 48 |
+
return
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
response := dto.FetchContactsResponse{
|
| 52 |
+
AccountID: accountID,
|
| 53 |
+
Contacts: contacts,
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
utils.SendResponse[dto.FetchContactsResponse, any](ctx, nil, response, nil)
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
// SendMessage godoc
|
| 60 |
+
// @Summary Send WhatsApp message
|
| 61 |
+
// @Description Send a text message to a WhatsApp number
|
| 62 |
+
// @Tags chat
|
| 63 |
+
// @Security BearerAuth
|
| 64 |
+
// @Accept json
|
| 65 |
+
// @Produce json
|
| 66 |
+
// @Param request body dto.SendMessageRequest true "Send Message Request"
|
| 67 |
+
// @Param X-CSRF-Token header string true "CSRF Protection Token"
|
| 68 |
+
// @Success 200 {object} dto.SendMessageResponse
|
| 69 |
+
// @Failure 401 {object} dto.ErrorResponse
|
| 70 |
+
// @Failure 400 {object} dto.ErrorResponse
|
| 71 |
+
// @Router /chat/send [post]
|
| 72 |
+
func (c *chatController) SendMessage(ctx *gin.Context) {
|
| 73 |
+
userID, exists := ctx.Get("user_id")
|
| 74 |
+
if !exists {
|
| 75 |
+
utils.SendResponse[any, any](ctx, nil, nil, http_error.UNAUTHORIZED)
|
| 76 |
+
return
|
| 77 |
+
}
|
| 78 |
+
accountID := userID.(uuid.UUID)
|
| 79 |
+
|
| 80 |
+
var req dto.SendMessageRequest
|
| 81 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 82 |
+
utils.SendResponse[any, any](ctx, nil, nil, http_error.ERR_BAD_REQUEST)
|
| 83 |
+
return
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
msgID, err := c.chatService.SendMessage(ctx, accountID, req.Recipient, req.Message)
|
| 87 |
+
if err != nil {
|
| 88 |
+
utils.SendResponse[any, any](ctx, nil, nil, err)
|
| 89 |
+
return
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
response := dto.SendMessageResponse{
|
| 93 |
+
MessageID: msgID,
|
| 94 |
+
Status: "SENT",
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
utils.SendResponse[dto.SendMessageResponse, any](ctx, nil, response, nil)
|
| 98 |
+
}
|
controllers/connection_controller.go
CHANGED
|
@@ -2,15 +2,14 @@ package controllers
|
|
| 2 |
|
| 3 |
import (
|
| 4 |
"context"
|
| 5 |
-
|
| 6 |
-
"github.com/gin-gonic/gin"
|
| 7 |
-
"github.com/google/uuid"
|
| 8 |
-
|
| 9 |
"whatsapp-backend/models/dto"
|
| 10 |
entity "whatsapp-backend/models/entity"
|
| 11 |
http_error "whatsapp-backend/models/error"
|
| 12 |
"whatsapp-backend/services"
|
| 13 |
"whatsapp-backend/utils"
|
|
|
|
|
|
|
|
|
|
| 14 |
)
|
| 15 |
|
| 16 |
type ConnectionController interface {
|
|
@@ -26,10 +25,23 @@ func NewConnectionController(connectionService services.ConnectionService) Conne
|
|
| 26 |
return &connectionController{connectionService}
|
| 27 |
}
|
| 28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
func (cc *connectionController) Connect(ctx *gin.Context) {
|
| 30 |
userID, exists := ctx.Get("user_id")
|
| 31 |
if !exists {
|
| 32 |
-
utils.SendResponse[any, any](ctx,
|
| 33 |
return
|
| 34 |
}
|
| 35 |
accountID := userID.(uuid.UUID)
|
|
@@ -39,12 +51,12 @@ func (cc *connectionController) Connect(ctx *gin.Context) {
|
|
| 39 |
|
| 40 |
qrCode, err := cc.connectionService.Connect(context.Background(), accountID)
|
| 41 |
if err != nil {
|
| 42 |
-
utils.SendResponse[any, any](ctx,
|
| 43 |
return
|
| 44 |
}
|
| 45 |
|
| 46 |
if qrCode == "" {
|
| 47 |
-
utils.SendResponse[any, any](ctx,
|
| 48 |
Message: entity.CONNECTION_ALREADY_CONNECTED,
|
| 49 |
AccountID: accountID,
|
| 50 |
Details: entity.CONNECTION_ALREADY_ACTIVE,
|
|
@@ -59,13 +71,24 @@ func (cc *connectionController) Connect(ctx *gin.Context) {
|
|
| 59 |
QRCode: qrCode,
|
| 60 |
}
|
| 61 |
|
| 62 |
-
utils.SendResponse[dto.ConnectResponse, any](ctx,
|
| 63 |
}
|
| 64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
func (cc *connectionController) GetStatus(ctx *gin.Context) {
|
| 66 |
userID, exists := ctx.Get("user_id")
|
| 67 |
if !exists {
|
| 68 |
-
utils.SendResponse[any, any](ctx,
|
| 69 |
return
|
| 70 |
}
|
| 71 |
accountID := userID.(uuid.UUID)
|
|
@@ -76,7 +99,7 @@ func (cc *connectionController) GetStatus(ctx *gin.Context) {
|
|
| 76 |
AccountID: accountID,
|
| 77 |
Status: entity.WHATSAPP_STATUS_DISCONNECTED,
|
| 78 |
}
|
| 79 |
-
utils.SendResponse[dto.ConnectionStatusResponse, any](ctx,
|
| 80 |
return
|
| 81 |
}
|
| 82 |
|
|
@@ -93,5 +116,5 @@ func (cc *connectionController) GetStatus(ctx *gin.Context) {
|
|
| 93 |
JID: client.Store.ID.String(),
|
| 94 |
}
|
| 95 |
|
| 96 |
-
utils.SendResponse[dto.ConnectionStatusResponse, any](ctx,
|
| 97 |
}
|
|
|
|
| 2 |
|
| 3 |
import (
|
| 4 |
"context"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
"whatsapp-backend/models/dto"
|
| 6 |
entity "whatsapp-backend/models/entity"
|
| 7 |
http_error "whatsapp-backend/models/error"
|
| 8 |
"whatsapp-backend/services"
|
| 9 |
"whatsapp-backend/utils"
|
| 10 |
+
|
| 11 |
+
"github.com/gin-gonic/gin"
|
| 12 |
+
"github.com/google/uuid"
|
| 13 |
)
|
| 14 |
|
| 15 |
type ConnectionController interface {
|
|
|
|
| 25 |
return &connectionController{connectionService}
|
| 26 |
}
|
| 27 |
|
| 28 |
+
// Connect godoc
|
| 29 |
+
// @Summary Connect new WhatsApp account
|
| 30 |
+
// @Description Initiate a connection request for a new WhatsApp account. Returns a QR code if not connected.
|
| 31 |
+
// @Tags whatsapp
|
| 32 |
+
// @Security BearerAuth
|
| 33 |
+
// @Accept json
|
| 34 |
+
// @Produce json
|
| 35 |
+
// @Param request body dto.ConnectRequest true "Connect Request"
|
| 36 |
+
// @Param X-CSRF-Token header string true "CSRF Protection Token"
|
| 37 |
+
// @Success 200 {object} dto.ConnectResponse
|
| 38 |
+
// @Failure 401 {object} dto.ErrorResponse
|
| 39 |
+
// @Failure 500 {object} dto.ErrorResponse
|
| 40 |
+
// @Router /whatsapp/connect [post]
|
| 41 |
func (cc *connectionController) Connect(ctx *gin.Context) {
|
| 42 |
userID, exists := ctx.Get("user_id")
|
| 43 |
if !exists {
|
| 44 |
+
utils.SendResponse[any, any](ctx, nil, nil, http_error.UNAUTHORIZED)
|
| 45 |
return
|
| 46 |
}
|
| 47 |
accountID := userID.(uuid.UUID)
|
|
|
|
| 51 |
|
| 52 |
qrCode, err := cc.connectionService.Connect(context.Background(), accountID)
|
| 53 |
if err != nil {
|
| 54 |
+
utils.SendResponse[any, any](ctx, nil, nil, err)
|
| 55 |
return
|
| 56 |
}
|
| 57 |
|
| 58 |
if qrCode == "" {
|
| 59 |
+
utils.SendResponse[any, any](ctx, nil, dto.ConnectResponse{
|
| 60 |
Message: entity.CONNECTION_ALREADY_CONNECTED,
|
| 61 |
AccountID: accountID,
|
| 62 |
Details: entity.CONNECTION_ALREADY_ACTIVE,
|
|
|
|
| 71 |
QRCode: qrCode,
|
| 72 |
}
|
| 73 |
|
| 74 |
+
utils.SendResponse[dto.ConnectResponse, any](ctx, nil, response, nil)
|
| 75 |
}
|
| 76 |
|
| 77 |
+
// GetStatus godoc
|
| 78 |
+
// @Summary Get WhatsApp connection status
|
| 79 |
+
// @Description Get the current status of the WhatsApp connection
|
| 80 |
+
// @Tags whatsapp
|
| 81 |
+
// @Security BearerAuth
|
| 82 |
+
// @Accept json
|
| 83 |
+
// @Produce json
|
| 84 |
+
// @Success 200 {object} dto.ConnectionStatusResponse
|
| 85 |
+
// @Failure 401 {object} dto.ErrorResponse
|
| 86 |
+
// @Failure 500 {object} dto.ErrorResponse
|
| 87 |
+
// @Router /whatsapp/status [get]
|
| 88 |
func (cc *connectionController) GetStatus(ctx *gin.Context) {
|
| 89 |
userID, exists := ctx.Get("user_id")
|
| 90 |
if !exists {
|
| 91 |
+
utils.SendResponse[any, any](ctx, nil, nil, http_error.UNAUTHORIZED)
|
| 92 |
return
|
| 93 |
}
|
| 94 |
accountID := userID.(uuid.UUID)
|
|
|
|
| 99 |
AccountID: accountID,
|
| 100 |
Status: entity.WHATSAPP_STATUS_DISCONNECTED,
|
| 101 |
}
|
| 102 |
+
utils.SendResponse[dto.ConnectionStatusResponse, any](ctx, nil, response, nil)
|
| 103 |
return
|
| 104 |
}
|
| 105 |
|
|
|
|
| 116 |
JID: client.Store.ID.String(),
|
| 117 |
}
|
| 118 |
|
| 119 |
+
utils.SendResponse[dto.ConnectionStatusResponse, any](ctx, nil, response, nil)
|
| 120 |
}
|
docs/docs.go
ADDED
|
@@ -0,0 +1,590 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Package docs Code generated by swaggo/swag. DO NOT EDIT
|
| 2 |
+
package docs
|
| 3 |
+
|
| 4 |
+
import "github.com/swaggo/swag"
|
| 5 |
+
|
| 6 |
+
const docTemplate = `{
|
| 7 |
+
"schemes": {{ marshal .Schemes }},
|
| 8 |
+
"swagger": "2.0",
|
| 9 |
+
"info": {
|
| 10 |
+
"description": "{{escape .Description}}",
|
| 11 |
+
"title": "{{.Title}}",
|
| 12 |
+
"termsOfService": "http://swagger.io/terms/",
|
| 13 |
+
"contact": {
|
| 14 |
+
"name": "API Support",
|
| 15 |
+
"url": "http://www.swagger.io/support",
|
| 16 |
+
"email": "support@swagger.io"
|
| 17 |
+
},
|
| 18 |
+
"license": {
|
| 19 |
+
"name": "Apache 2.0",
|
| 20 |
+
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
| 21 |
+
},
|
| 22 |
+
"version": "{{.Version}}"
|
| 23 |
+
},
|
| 24 |
+
"host": "{{.Host}}",
|
| 25 |
+
"basePath": "{{.BasePath}}",
|
| 26 |
+
"paths": {
|
| 27 |
+
"/auth/login": {
|
| 28 |
+
"post": {
|
| 29 |
+
"description": "Login a user with credentials",
|
| 30 |
+
"consumes": [
|
| 31 |
+
"application/json"
|
| 32 |
+
],
|
| 33 |
+
"produces": [
|
| 34 |
+
"application/json"
|
| 35 |
+
],
|
| 36 |
+
"tags": [
|
| 37 |
+
"auth"
|
| 38 |
+
],
|
| 39 |
+
"summary": "Login a user",
|
| 40 |
+
"parameters": [
|
| 41 |
+
{
|
| 42 |
+
"description": "Login Request",
|
| 43 |
+
"name": "request",
|
| 44 |
+
"in": "body",
|
| 45 |
+
"required": true,
|
| 46 |
+
"schema": {
|
| 47 |
+
"$ref": "#/definitions/dto.LoginRequest"
|
| 48 |
+
}
|
| 49 |
+
}
|
| 50 |
+
],
|
| 51 |
+
"responses": {
|
| 52 |
+
"200": {
|
| 53 |
+
"description": "OK",
|
| 54 |
+
"schema": {
|
| 55 |
+
"$ref": "#/definitions/dto.AuthResponse"
|
| 56 |
+
}
|
| 57 |
+
},
|
| 58 |
+
"400": {
|
| 59 |
+
"description": "Bad Request",
|
| 60 |
+
"schema": {
|
| 61 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
}
|
| 65 |
+
}
|
| 66 |
+
},
|
| 67 |
+
"/auth/logout": {
|
| 68 |
+
"post": {
|
| 69 |
+
"description": "Logout the current user",
|
| 70 |
+
"tags": [
|
| 71 |
+
"auth"
|
| 72 |
+
],
|
| 73 |
+
"summary": "Logout a user",
|
| 74 |
+
"parameters": [
|
| 75 |
+
{
|
| 76 |
+
"type": "string",
|
| 77 |
+
"description": "CSRF Protection Token",
|
| 78 |
+
"name": "X-CSRF-Token",
|
| 79 |
+
"in": "header",
|
| 80 |
+
"required": true
|
| 81 |
+
}
|
| 82 |
+
],
|
| 83 |
+
"responses": {
|
| 84 |
+
"200": {
|
| 85 |
+
"description": "OK"
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
}
|
| 89 |
+
},
|
| 90 |
+
"/auth/me": {
|
| 91 |
+
"get": {
|
| 92 |
+
"security": [
|
| 93 |
+
{
|
| 94 |
+
"BearerAuth": []
|
| 95 |
+
}
|
| 96 |
+
],
|
| 97 |
+
"description": "Get the profile of the currently logged-in user",
|
| 98 |
+
"tags": [
|
| 99 |
+
"auth"
|
| 100 |
+
],
|
| 101 |
+
"summary": "Get current user profile",
|
| 102 |
+
"responses": {
|
| 103 |
+
"200": {
|
| 104 |
+
"description": "OK",
|
| 105 |
+
"schema": {
|
| 106 |
+
"$ref": "#/definitions/dto.MeResponse"
|
| 107 |
+
}
|
| 108 |
+
},
|
| 109 |
+
"401": {
|
| 110 |
+
"description": "Unauthorized",
|
| 111 |
+
"schema": {
|
| 112 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 113 |
+
}
|
| 114 |
+
}
|
| 115 |
+
}
|
| 116 |
+
}
|
| 117 |
+
},
|
| 118 |
+
"/auth/refresh": {
|
| 119 |
+
"post": {
|
| 120 |
+
"description": "Refresh the access token using the refresh token cookie",
|
| 121 |
+
"tags": [
|
| 122 |
+
"auth"
|
| 123 |
+
],
|
| 124 |
+
"summary": "Refresh access token",
|
| 125 |
+
"parameters": [
|
| 126 |
+
{
|
| 127 |
+
"type": "string",
|
| 128 |
+
"description": "CSRF Protection Token",
|
| 129 |
+
"name": "X-CSRF-Token",
|
| 130 |
+
"in": "header",
|
| 131 |
+
"required": true
|
| 132 |
+
}
|
| 133 |
+
],
|
| 134 |
+
"responses": {
|
| 135 |
+
"200": {
|
| 136 |
+
"description": "OK",
|
| 137 |
+
"schema": {
|
| 138 |
+
"$ref": "#/definitions/dto.AuthResponse"
|
| 139 |
+
}
|
| 140 |
+
},
|
| 141 |
+
"401": {
|
| 142 |
+
"description": "Unauthorized",
|
| 143 |
+
"schema": {
|
| 144 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 145 |
+
}
|
| 146 |
+
}
|
| 147 |
+
}
|
| 148 |
+
}
|
| 149 |
+
},
|
| 150 |
+
"/auth/register": {
|
| 151 |
+
"post": {
|
| 152 |
+
"description": "Register a new user with the provided details",
|
| 153 |
+
"consumes": [
|
| 154 |
+
"application/json"
|
| 155 |
+
],
|
| 156 |
+
"produces": [
|
| 157 |
+
"application/json"
|
| 158 |
+
],
|
| 159 |
+
"tags": [
|
| 160 |
+
"auth"
|
| 161 |
+
],
|
| 162 |
+
"summary": "Register a new user",
|
| 163 |
+
"parameters": [
|
| 164 |
+
{
|
| 165 |
+
"description": "Register Request",
|
| 166 |
+
"name": "request",
|
| 167 |
+
"in": "body",
|
| 168 |
+
"required": true,
|
| 169 |
+
"schema": {
|
| 170 |
+
"$ref": "#/definitions/dto.RegisterRequest"
|
| 171 |
+
}
|
| 172 |
+
}
|
| 173 |
+
],
|
| 174 |
+
"responses": {
|
| 175 |
+
"200": {
|
| 176 |
+
"description": "OK",
|
| 177 |
+
"schema": {
|
| 178 |
+
"$ref": "#/definitions/dto.AuthResponse"
|
| 179 |
+
}
|
| 180 |
+
},
|
| 181 |
+
"400": {
|
| 182 |
+
"description": "Bad Request",
|
| 183 |
+
"schema": {
|
| 184 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 185 |
+
}
|
| 186 |
+
}
|
| 187 |
+
}
|
| 188 |
+
}
|
| 189 |
+
},
|
| 190 |
+
"/chat/fetch": {
|
| 191 |
+
"get": {
|
| 192 |
+
"security": [
|
| 193 |
+
{
|
| 194 |
+
"BearerAuth": []
|
| 195 |
+
}
|
| 196 |
+
],
|
| 197 |
+
"description": "Fetch list of contacts from the connected WhatsApp account",
|
| 198 |
+
"consumes": [
|
| 199 |
+
"application/json"
|
| 200 |
+
],
|
| 201 |
+
"produces": [
|
| 202 |
+
"application/json"
|
| 203 |
+
],
|
| 204 |
+
"tags": [
|
| 205 |
+
"chat"
|
| 206 |
+
],
|
| 207 |
+
"summary": "Fetch WhatsApp contacts",
|
| 208 |
+
"responses": {
|
| 209 |
+
"200": {
|
| 210 |
+
"description": "OK",
|
| 211 |
+
"schema": {
|
| 212 |
+
"$ref": "#/definitions/dto.FetchContactsResponse"
|
| 213 |
+
}
|
| 214 |
+
},
|
| 215 |
+
"400": {
|
| 216 |
+
"description": "Bad Request",
|
| 217 |
+
"schema": {
|
| 218 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 219 |
+
}
|
| 220 |
+
},
|
| 221 |
+
"401": {
|
| 222 |
+
"description": "Unauthorized",
|
| 223 |
+
"schema": {
|
| 224 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 225 |
+
}
|
| 226 |
+
}
|
| 227 |
+
}
|
| 228 |
+
}
|
| 229 |
+
},
|
| 230 |
+
"/chat/send": {
|
| 231 |
+
"post": {
|
| 232 |
+
"security": [
|
| 233 |
+
{
|
| 234 |
+
"BearerAuth": []
|
| 235 |
+
}
|
| 236 |
+
],
|
| 237 |
+
"description": "Send a text message to a WhatsApp number",
|
| 238 |
+
"consumes": [
|
| 239 |
+
"application/json"
|
| 240 |
+
],
|
| 241 |
+
"produces": [
|
| 242 |
+
"application/json"
|
| 243 |
+
],
|
| 244 |
+
"tags": [
|
| 245 |
+
"chat"
|
| 246 |
+
],
|
| 247 |
+
"summary": "Send WhatsApp message",
|
| 248 |
+
"parameters": [
|
| 249 |
+
{
|
| 250 |
+
"description": "Send Message Request",
|
| 251 |
+
"name": "request",
|
| 252 |
+
"in": "body",
|
| 253 |
+
"required": true,
|
| 254 |
+
"schema": {
|
| 255 |
+
"$ref": "#/definitions/dto.SendMessageRequest"
|
| 256 |
+
}
|
| 257 |
+
},
|
| 258 |
+
{
|
| 259 |
+
"type": "string",
|
| 260 |
+
"description": "CSRF Protection Token",
|
| 261 |
+
"name": "X-CSRF-Token",
|
| 262 |
+
"in": "header",
|
| 263 |
+
"required": true
|
| 264 |
+
}
|
| 265 |
+
],
|
| 266 |
+
"responses": {
|
| 267 |
+
"200": {
|
| 268 |
+
"description": "OK",
|
| 269 |
+
"schema": {
|
| 270 |
+
"$ref": "#/definitions/dto.SendMessageResponse"
|
| 271 |
+
}
|
| 272 |
+
},
|
| 273 |
+
"400": {
|
| 274 |
+
"description": "Bad Request",
|
| 275 |
+
"schema": {
|
| 276 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 277 |
+
}
|
| 278 |
+
},
|
| 279 |
+
"401": {
|
| 280 |
+
"description": "Unauthorized",
|
| 281 |
+
"schema": {
|
| 282 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 283 |
+
}
|
| 284 |
+
}
|
| 285 |
+
}
|
| 286 |
+
}
|
| 287 |
+
},
|
| 288 |
+
"/whatsapp/connect": {
|
| 289 |
+
"post": {
|
| 290 |
+
"security": [
|
| 291 |
+
{
|
| 292 |
+
"BearerAuth": []
|
| 293 |
+
}
|
| 294 |
+
],
|
| 295 |
+
"description": "Initiate a connection request for a new WhatsApp account. Returns a QR code if not connected.",
|
| 296 |
+
"consumes": [
|
| 297 |
+
"application/json"
|
| 298 |
+
],
|
| 299 |
+
"produces": [
|
| 300 |
+
"application/json"
|
| 301 |
+
],
|
| 302 |
+
"tags": [
|
| 303 |
+
"whatsapp"
|
| 304 |
+
],
|
| 305 |
+
"summary": "Connect new WhatsApp account",
|
| 306 |
+
"parameters": [
|
| 307 |
+
{
|
| 308 |
+
"description": "Connect Request",
|
| 309 |
+
"name": "request",
|
| 310 |
+
"in": "body",
|
| 311 |
+
"required": true,
|
| 312 |
+
"schema": {
|
| 313 |
+
"$ref": "#/definitions/dto.ConnectRequest"
|
| 314 |
+
}
|
| 315 |
+
},
|
| 316 |
+
{
|
| 317 |
+
"type": "string",
|
| 318 |
+
"description": "CSRF Protection Token",
|
| 319 |
+
"name": "X-CSRF-Token",
|
| 320 |
+
"in": "header",
|
| 321 |
+
"required": true
|
| 322 |
+
}
|
| 323 |
+
],
|
| 324 |
+
"responses": {
|
| 325 |
+
"200": {
|
| 326 |
+
"description": "OK",
|
| 327 |
+
"schema": {
|
| 328 |
+
"$ref": "#/definitions/dto.ConnectResponse"
|
| 329 |
+
}
|
| 330 |
+
},
|
| 331 |
+
"401": {
|
| 332 |
+
"description": "Unauthorized",
|
| 333 |
+
"schema": {
|
| 334 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 335 |
+
}
|
| 336 |
+
},
|
| 337 |
+
"500": {
|
| 338 |
+
"description": "Internal Server Error",
|
| 339 |
+
"schema": {
|
| 340 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 341 |
+
}
|
| 342 |
+
}
|
| 343 |
+
}
|
| 344 |
+
}
|
| 345 |
+
},
|
| 346 |
+
"/whatsapp/status": {
|
| 347 |
+
"get": {
|
| 348 |
+
"security": [
|
| 349 |
+
{
|
| 350 |
+
"BearerAuth": []
|
| 351 |
+
}
|
| 352 |
+
],
|
| 353 |
+
"description": "Get the current status of the WhatsApp connection",
|
| 354 |
+
"consumes": [
|
| 355 |
+
"application/json"
|
| 356 |
+
],
|
| 357 |
+
"produces": [
|
| 358 |
+
"application/json"
|
| 359 |
+
],
|
| 360 |
+
"tags": [
|
| 361 |
+
"whatsapp"
|
| 362 |
+
],
|
| 363 |
+
"summary": "Get WhatsApp connection status",
|
| 364 |
+
"responses": {
|
| 365 |
+
"200": {
|
| 366 |
+
"description": "OK",
|
| 367 |
+
"schema": {
|
| 368 |
+
"$ref": "#/definitions/dto.ConnectionStatusResponse"
|
| 369 |
+
}
|
| 370 |
+
},
|
| 371 |
+
"401": {
|
| 372 |
+
"description": "Unauthorized",
|
| 373 |
+
"schema": {
|
| 374 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 375 |
+
}
|
| 376 |
+
},
|
| 377 |
+
"500": {
|
| 378 |
+
"description": "Internal Server Error",
|
| 379 |
+
"schema": {
|
| 380 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 381 |
+
}
|
| 382 |
+
}
|
| 383 |
+
}
|
| 384 |
+
}
|
| 385 |
+
}
|
| 386 |
+
},
|
| 387 |
+
"definitions": {
|
| 388 |
+
"dto.AuthResponse": {
|
| 389 |
+
"type": "object",
|
| 390 |
+
"properties": {
|
| 391 |
+
"token": {
|
| 392 |
+
"type": "string"
|
| 393 |
+
},
|
| 394 |
+
"user_id": {
|
| 395 |
+
"type": "string"
|
| 396 |
+
},
|
| 397 |
+
"username": {
|
| 398 |
+
"type": "string"
|
| 399 |
+
}
|
| 400 |
+
}
|
| 401 |
+
},
|
| 402 |
+
"dto.ConnectRequest": {
|
| 403 |
+
"type": "object"
|
| 404 |
+
},
|
| 405 |
+
"dto.ConnectResponse": {
|
| 406 |
+
"type": "object",
|
| 407 |
+
"properties": {
|
| 408 |
+
"account_id": {
|
| 409 |
+
"type": "string"
|
| 410 |
+
},
|
| 411 |
+
"details": {
|
| 412 |
+
"type": "string"
|
| 413 |
+
},
|
| 414 |
+
"message": {
|
| 415 |
+
"type": "string"
|
| 416 |
+
},
|
| 417 |
+
"qr_code": {
|
| 418 |
+
"type": "string"
|
| 419 |
+
}
|
| 420 |
+
}
|
| 421 |
+
},
|
| 422 |
+
"dto.ConnectionStatusResponse": {
|
| 423 |
+
"type": "object",
|
| 424 |
+
"properties": {
|
| 425 |
+
"account_id": {
|
| 426 |
+
"type": "string"
|
| 427 |
+
},
|
| 428 |
+
"jid": {
|
| 429 |
+
"type": "string"
|
| 430 |
+
},
|
| 431 |
+
"status": {
|
| 432 |
+
"type": "string"
|
| 433 |
+
}
|
| 434 |
+
}
|
| 435 |
+
},
|
| 436 |
+
"dto.ContactResponse": {
|
| 437 |
+
"type": "object",
|
| 438 |
+
"properties": {
|
| 439 |
+
"full_name": {
|
| 440 |
+
"type": "string"
|
| 441 |
+
},
|
| 442 |
+
"jid": {
|
| 443 |
+
"type": "string"
|
| 444 |
+
},
|
| 445 |
+
"name": {
|
| 446 |
+
"type": "string"
|
| 447 |
+
},
|
| 448 |
+
"phone_number": {
|
| 449 |
+
"type": "string"
|
| 450 |
+
},
|
| 451 |
+
"push_name": {
|
| 452 |
+
"type": "string"
|
| 453 |
+
}
|
| 454 |
+
}
|
| 455 |
+
},
|
| 456 |
+
"dto.ErrorResponse": {
|
| 457 |
+
"type": "object",
|
| 458 |
+
"properties": {
|
| 459 |
+
"errors": {},
|
| 460 |
+
"message": {},
|
| 461 |
+
"meta_data": {},
|
| 462 |
+
"status": {
|
| 463 |
+
"type": "string"
|
| 464 |
+
}
|
| 465 |
+
}
|
| 466 |
+
},
|
| 467 |
+
"dto.FetchContactsResponse": {
|
| 468 |
+
"type": "object",
|
| 469 |
+
"properties": {
|
| 470 |
+
"account_id": {
|
| 471 |
+
"type": "string"
|
| 472 |
+
},
|
| 473 |
+
"contacts": {
|
| 474 |
+
"type": "array",
|
| 475 |
+
"items": {
|
| 476 |
+
"$ref": "#/definitions/dto.ContactResponse"
|
| 477 |
+
}
|
| 478 |
+
}
|
| 479 |
+
}
|
| 480 |
+
},
|
| 481 |
+
"dto.LoginRequest": {
|
| 482 |
+
"type": "object",
|
| 483 |
+
"required": [
|
| 484 |
+
"password",
|
| 485 |
+
"username"
|
| 486 |
+
],
|
| 487 |
+
"properties": {
|
| 488 |
+
"password": {
|
| 489 |
+
"type": "string"
|
| 490 |
+
},
|
| 491 |
+
"username": {
|
| 492 |
+
"type": "string"
|
| 493 |
+
}
|
| 494 |
+
}
|
| 495 |
+
},
|
| 496 |
+
"dto.MeResponse": {
|
| 497 |
+
"type": "object",
|
| 498 |
+
"properties": {
|
| 499 |
+
"account_name": {
|
| 500 |
+
"type": "string"
|
| 501 |
+
},
|
| 502 |
+
"is_active": {
|
| 503 |
+
"type": "boolean"
|
| 504 |
+
},
|
| 505 |
+
"jid": {
|
| 506 |
+
"type": "string"
|
| 507 |
+
},
|
| 508 |
+
"phone": {
|
| 509 |
+
"type": "string"
|
| 510 |
+
},
|
| 511 |
+
"user_id": {
|
| 512 |
+
"type": "string"
|
| 513 |
+
},
|
| 514 |
+
"username": {
|
| 515 |
+
"type": "string"
|
| 516 |
+
}
|
| 517 |
+
}
|
| 518 |
+
},
|
| 519 |
+
"dto.RegisterRequest": {
|
| 520 |
+
"type": "object",
|
| 521 |
+
"required": [
|
| 522 |
+
"password",
|
| 523 |
+
"username"
|
| 524 |
+
],
|
| 525 |
+
"properties": {
|
| 526 |
+
"password": {
|
| 527 |
+
"type": "string",
|
| 528 |
+
"minLength": 6
|
| 529 |
+
},
|
| 530 |
+
"username": {
|
| 531 |
+
"type": "string",
|
| 532 |
+
"minLength": 3
|
| 533 |
+
}
|
| 534 |
+
}
|
| 535 |
+
},
|
| 536 |
+
"dto.SendMessageRequest": {
|
| 537 |
+
"type": "object",
|
| 538 |
+
"required": [
|
| 539 |
+
"message",
|
| 540 |
+
"recipient"
|
| 541 |
+
],
|
| 542 |
+
"properties": {
|
| 543 |
+
"message": {
|
| 544 |
+
"type": "string",
|
| 545 |
+
"example": "Hello world"
|
| 546 |
+
},
|
| 547 |
+
"recipient": {
|
| 548 |
+
"type": "string",
|
| 549 |
+
"example": "628123456789"
|
| 550 |
+
}
|
| 551 |
+
}
|
| 552 |
+
},
|
| 553 |
+
"dto.SendMessageResponse": {
|
| 554 |
+
"type": "object",
|
| 555 |
+
"properties": {
|
| 556 |
+
"message_id": {
|
| 557 |
+
"type": "string"
|
| 558 |
+
},
|
| 559 |
+
"status": {
|
| 560 |
+
"type": "string"
|
| 561 |
+
}
|
| 562 |
+
}
|
| 563 |
+
}
|
| 564 |
+
},
|
| 565 |
+
"securityDefinitions": {
|
| 566 |
+
"BearerAuth": {
|
| 567 |
+
"type": "apiKey",
|
| 568 |
+
"name": "Authorization",
|
| 569 |
+
"in": "header"
|
| 570 |
+
}
|
| 571 |
+
}
|
| 572 |
+
}`
|
| 573 |
+
|
| 574 |
+
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
| 575 |
+
var SwaggerInfo = &swag.Spec{
|
| 576 |
+
Version: "1.0",
|
| 577 |
+
Host: "localhost:8080",
|
| 578 |
+
BasePath: "/api",
|
| 579 |
+
Schemes: []string{},
|
| 580 |
+
Title: "Whatsapp Backend API",
|
| 581 |
+
Description: "This is the API documentation for the Whatsapp Backend.",
|
| 582 |
+
InfoInstanceName: "swagger",
|
| 583 |
+
SwaggerTemplate: docTemplate,
|
| 584 |
+
LeftDelim: "{{",
|
| 585 |
+
RightDelim: "}}",
|
| 586 |
+
}
|
| 587 |
+
|
| 588 |
+
func init() {
|
| 589 |
+
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
|
| 590 |
+
}
|
docs/swagger.json
ADDED
|
@@ -0,0 +1,566 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"swagger": "2.0",
|
| 3 |
+
"info": {
|
| 4 |
+
"description": "This is the API documentation for the Whatsapp Backend.",
|
| 5 |
+
"title": "Whatsapp Backend API",
|
| 6 |
+
"termsOfService": "http://swagger.io/terms/",
|
| 7 |
+
"contact": {
|
| 8 |
+
"name": "API Support",
|
| 9 |
+
"url": "http://www.swagger.io/support",
|
| 10 |
+
"email": "support@swagger.io"
|
| 11 |
+
},
|
| 12 |
+
"license": {
|
| 13 |
+
"name": "Apache 2.0",
|
| 14 |
+
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
| 15 |
+
},
|
| 16 |
+
"version": "1.0"
|
| 17 |
+
},
|
| 18 |
+
"host": "localhost:8080",
|
| 19 |
+
"basePath": "/api",
|
| 20 |
+
"paths": {
|
| 21 |
+
"/auth/login": {
|
| 22 |
+
"post": {
|
| 23 |
+
"description": "Login a user with credentials",
|
| 24 |
+
"consumes": [
|
| 25 |
+
"application/json"
|
| 26 |
+
],
|
| 27 |
+
"produces": [
|
| 28 |
+
"application/json"
|
| 29 |
+
],
|
| 30 |
+
"tags": [
|
| 31 |
+
"auth"
|
| 32 |
+
],
|
| 33 |
+
"summary": "Login a user",
|
| 34 |
+
"parameters": [
|
| 35 |
+
{
|
| 36 |
+
"description": "Login Request",
|
| 37 |
+
"name": "request",
|
| 38 |
+
"in": "body",
|
| 39 |
+
"required": true,
|
| 40 |
+
"schema": {
|
| 41 |
+
"$ref": "#/definitions/dto.LoginRequest"
|
| 42 |
+
}
|
| 43 |
+
}
|
| 44 |
+
],
|
| 45 |
+
"responses": {
|
| 46 |
+
"200": {
|
| 47 |
+
"description": "OK",
|
| 48 |
+
"schema": {
|
| 49 |
+
"$ref": "#/definitions/dto.AuthResponse"
|
| 50 |
+
}
|
| 51 |
+
},
|
| 52 |
+
"400": {
|
| 53 |
+
"description": "Bad Request",
|
| 54 |
+
"schema": {
|
| 55 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 56 |
+
}
|
| 57 |
+
}
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
},
|
| 61 |
+
"/auth/logout": {
|
| 62 |
+
"post": {
|
| 63 |
+
"description": "Logout the current user",
|
| 64 |
+
"tags": [
|
| 65 |
+
"auth"
|
| 66 |
+
],
|
| 67 |
+
"summary": "Logout a user",
|
| 68 |
+
"parameters": [
|
| 69 |
+
{
|
| 70 |
+
"type": "string",
|
| 71 |
+
"description": "CSRF Protection Token",
|
| 72 |
+
"name": "X-CSRF-Token",
|
| 73 |
+
"in": "header",
|
| 74 |
+
"required": true
|
| 75 |
+
}
|
| 76 |
+
],
|
| 77 |
+
"responses": {
|
| 78 |
+
"200": {
|
| 79 |
+
"description": "OK"
|
| 80 |
+
}
|
| 81 |
+
}
|
| 82 |
+
}
|
| 83 |
+
},
|
| 84 |
+
"/auth/me": {
|
| 85 |
+
"get": {
|
| 86 |
+
"security": [
|
| 87 |
+
{
|
| 88 |
+
"BearerAuth": []
|
| 89 |
+
}
|
| 90 |
+
],
|
| 91 |
+
"description": "Get the profile of the currently logged-in user",
|
| 92 |
+
"tags": [
|
| 93 |
+
"auth"
|
| 94 |
+
],
|
| 95 |
+
"summary": "Get current user profile",
|
| 96 |
+
"responses": {
|
| 97 |
+
"200": {
|
| 98 |
+
"description": "OK",
|
| 99 |
+
"schema": {
|
| 100 |
+
"$ref": "#/definitions/dto.MeResponse"
|
| 101 |
+
}
|
| 102 |
+
},
|
| 103 |
+
"401": {
|
| 104 |
+
"description": "Unauthorized",
|
| 105 |
+
"schema": {
|
| 106 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 107 |
+
}
|
| 108 |
+
}
|
| 109 |
+
}
|
| 110 |
+
}
|
| 111 |
+
},
|
| 112 |
+
"/auth/refresh": {
|
| 113 |
+
"post": {
|
| 114 |
+
"description": "Refresh the access token using the refresh token cookie",
|
| 115 |
+
"tags": [
|
| 116 |
+
"auth"
|
| 117 |
+
],
|
| 118 |
+
"summary": "Refresh access token",
|
| 119 |
+
"parameters": [
|
| 120 |
+
{
|
| 121 |
+
"type": "string",
|
| 122 |
+
"description": "CSRF Protection Token",
|
| 123 |
+
"name": "X-CSRF-Token",
|
| 124 |
+
"in": "header",
|
| 125 |
+
"required": true
|
| 126 |
+
}
|
| 127 |
+
],
|
| 128 |
+
"responses": {
|
| 129 |
+
"200": {
|
| 130 |
+
"description": "OK",
|
| 131 |
+
"schema": {
|
| 132 |
+
"$ref": "#/definitions/dto.AuthResponse"
|
| 133 |
+
}
|
| 134 |
+
},
|
| 135 |
+
"401": {
|
| 136 |
+
"description": "Unauthorized",
|
| 137 |
+
"schema": {
|
| 138 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 139 |
+
}
|
| 140 |
+
}
|
| 141 |
+
}
|
| 142 |
+
}
|
| 143 |
+
},
|
| 144 |
+
"/auth/register": {
|
| 145 |
+
"post": {
|
| 146 |
+
"description": "Register a new user with the provided details",
|
| 147 |
+
"consumes": [
|
| 148 |
+
"application/json"
|
| 149 |
+
],
|
| 150 |
+
"produces": [
|
| 151 |
+
"application/json"
|
| 152 |
+
],
|
| 153 |
+
"tags": [
|
| 154 |
+
"auth"
|
| 155 |
+
],
|
| 156 |
+
"summary": "Register a new user",
|
| 157 |
+
"parameters": [
|
| 158 |
+
{
|
| 159 |
+
"description": "Register Request",
|
| 160 |
+
"name": "request",
|
| 161 |
+
"in": "body",
|
| 162 |
+
"required": true,
|
| 163 |
+
"schema": {
|
| 164 |
+
"$ref": "#/definitions/dto.RegisterRequest"
|
| 165 |
+
}
|
| 166 |
+
}
|
| 167 |
+
],
|
| 168 |
+
"responses": {
|
| 169 |
+
"200": {
|
| 170 |
+
"description": "OK",
|
| 171 |
+
"schema": {
|
| 172 |
+
"$ref": "#/definitions/dto.AuthResponse"
|
| 173 |
+
}
|
| 174 |
+
},
|
| 175 |
+
"400": {
|
| 176 |
+
"description": "Bad Request",
|
| 177 |
+
"schema": {
|
| 178 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 179 |
+
}
|
| 180 |
+
}
|
| 181 |
+
}
|
| 182 |
+
}
|
| 183 |
+
},
|
| 184 |
+
"/chat/fetch": {
|
| 185 |
+
"get": {
|
| 186 |
+
"security": [
|
| 187 |
+
{
|
| 188 |
+
"BearerAuth": []
|
| 189 |
+
}
|
| 190 |
+
],
|
| 191 |
+
"description": "Fetch list of contacts from the connected WhatsApp account",
|
| 192 |
+
"consumes": [
|
| 193 |
+
"application/json"
|
| 194 |
+
],
|
| 195 |
+
"produces": [
|
| 196 |
+
"application/json"
|
| 197 |
+
],
|
| 198 |
+
"tags": [
|
| 199 |
+
"chat"
|
| 200 |
+
],
|
| 201 |
+
"summary": "Fetch WhatsApp contacts",
|
| 202 |
+
"responses": {
|
| 203 |
+
"200": {
|
| 204 |
+
"description": "OK",
|
| 205 |
+
"schema": {
|
| 206 |
+
"$ref": "#/definitions/dto.FetchContactsResponse"
|
| 207 |
+
}
|
| 208 |
+
},
|
| 209 |
+
"400": {
|
| 210 |
+
"description": "Bad Request",
|
| 211 |
+
"schema": {
|
| 212 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 213 |
+
}
|
| 214 |
+
},
|
| 215 |
+
"401": {
|
| 216 |
+
"description": "Unauthorized",
|
| 217 |
+
"schema": {
|
| 218 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 219 |
+
}
|
| 220 |
+
}
|
| 221 |
+
}
|
| 222 |
+
}
|
| 223 |
+
},
|
| 224 |
+
"/chat/send": {
|
| 225 |
+
"post": {
|
| 226 |
+
"security": [
|
| 227 |
+
{
|
| 228 |
+
"BearerAuth": []
|
| 229 |
+
}
|
| 230 |
+
],
|
| 231 |
+
"description": "Send a text message to a WhatsApp number",
|
| 232 |
+
"consumes": [
|
| 233 |
+
"application/json"
|
| 234 |
+
],
|
| 235 |
+
"produces": [
|
| 236 |
+
"application/json"
|
| 237 |
+
],
|
| 238 |
+
"tags": [
|
| 239 |
+
"chat"
|
| 240 |
+
],
|
| 241 |
+
"summary": "Send WhatsApp message",
|
| 242 |
+
"parameters": [
|
| 243 |
+
{
|
| 244 |
+
"description": "Send Message Request",
|
| 245 |
+
"name": "request",
|
| 246 |
+
"in": "body",
|
| 247 |
+
"required": true,
|
| 248 |
+
"schema": {
|
| 249 |
+
"$ref": "#/definitions/dto.SendMessageRequest"
|
| 250 |
+
}
|
| 251 |
+
},
|
| 252 |
+
{
|
| 253 |
+
"type": "string",
|
| 254 |
+
"description": "CSRF Protection Token",
|
| 255 |
+
"name": "X-CSRF-Token",
|
| 256 |
+
"in": "header",
|
| 257 |
+
"required": true
|
| 258 |
+
}
|
| 259 |
+
],
|
| 260 |
+
"responses": {
|
| 261 |
+
"200": {
|
| 262 |
+
"description": "OK",
|
| 263 |
+
"schema": {
|
| 264 |
+
"$ref": "#/definitions/dto.SendMessageResponse"
|
| 265 |
+
}
|
| 266 |
+
},
|
| 267 |
+
"400": {
|
| 268 |
+
"description": "Bad Request",
|
| 269 |
+
"schema": {
|
| 270 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 271 |
+
}
|
| 272 |
+
},
|
| 273 |
+
"401": {
|
| 274 |
+
"description": "Unauthorized",
|
| 275 |
+
"schema": {
|
| 276 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 277 |
+
}
|
| 278 |
+
}
|
| 279 |
+
}
|
| 280 |
+
}
|
| 281 |
+
},
|
| 282 |
+
"/whatsapp/connect": {
|
| 283 |
+
"post": {
|
| 284 |
+
"security": [
|
| 285 |
+
{
|
| 286 |
+
"BearerAuth": []
|
| 287 |
+
}
|
| 288 |
+
],
|
| 289 |
+
"description": "Initiate a connection request for a new WhatsApp account. Returns a QR code if not connected.",
|
| 290 |
+
"consumes": [
|
| 291 |
+
"application/json"
|
| 292 |
+
],
|
| 293 |
+
"produces": [
|
| 294 |
+
"application/json"
|
| 295 |
+
],
|
| 296 |
+
"tags": [
|
| 297 |
+
"whatsapp"
|
| 298 |
+
],
|
| 299 |
+
"summary": "Connect new WhatsApp account",
|
| 300 |
+
"parameters": [
|
| 301 |
+
{
|
| 302 |
+
"description": "Connect Request",
|
| 303 |
+
"name": "request",
|
| 304 |
+
"in": "body",
|
| 305 |
+
"required": true,
|
| 306 |
+
"schema": {
|
| 307 |
+
"$ref": "#/definitions/dto.ConnectRequest"
|
| 308 |
+
}
|
| 309 |
+
},
|
| 310 |
+
{
|
| 311 |
+
"type": "string",
|
| 312 |
+
"description": "CSRF Protection Token",
|
| 313 |
+
"name": "X-CSRF-Token",
|
| 314 |
+
"in": "header",
|
| 315 |
+
"required": true
|
| 316 |
+
}
|
| 317 |
+
],
|
| 318 |
+
"responses": {
|
| 319 |
+
"200": {
|
| 320 |
+
"description": "OK",
|
| 321 |
+
"schema": {
|
| 322 |
+
"$ref": "#/definitions/dto.ConnectResponse"
|
| 323 |
+
}
|
| 324 |
+
},
|
| 325 |
+
"401": {
|
| 326 |
+
"description": "Unauthorized",
|
| 327 |
+
"schema": {
|
| 328 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 329 |
+
}
|
| 330 |
+
},
|
| 331 |
+
"500": {
|
| 332 |
+
"description": "Internal Server Error",
|
| 333 |
+
"schema": {
|
| 334 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 335 |
+
}
|
| 336 |
+
}
|
| 337 |
+
}
|
| 338 |
+
}
|
| 339 |
+
},
|
| 340 |
+
"/whatsapp/status": {
|
| 341 |
+
"get": {
|
| 342 |
+
"security": [
|
| 343 |
+
{
|
| 344 |
+
"BearerAuth": []
|
| 345 |
+
}
|
| 346 |
+
],
|
| 347 |
+
"description": "Get the current status of the WhatsApp connection",
|
| 348 |
+
"consumes": [
|
| 349 |
+
"application/json"
|
| 350 |
+
],
|
| 351 |
+
"produces": [
|
| 352 |
+
"application/json"
|
| 353 |
+
],
|
| 354 |
+
"tags": [
|
| 355 |
+
"whatsapp"
|
| 356 |
+
],
|
| 357 |
+
"summary": "Get WhatsApp connection status",
|
| 358 |
+
"responses": {
|
| 359 |
+
"200": {
|
| 360 |
+
"description": "OK",
|
| 361 |
+
"schema": {
|
| 362 |
+
"$ref": "#/definitions/dto.ConnectionStatusResponse"
|
| 363 |
+
}
|
| 364 |
+
},
|
| 365 |
+
"401": {
|
| 366 |
+
"description": "Unauthorized",
|
| 367 |
+
"schema": {
|
| 368 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 369 |
+
}
|
| 370 |
+
},
|
| 371 |
+
"500": {
|
| 372 |
+
"description": "Internal Server Error",
|
| 373 |
+
"schema": {
|
| 374 |
+
"$ref": "#/definitions/dto.ErrorResponse"
|
| 375 |
+
}
|
| 376 |
+
}
|
| 377 |
+
}
|
| 378 |
+
}
|
| 379 |
+
}
|
| 380 |
+
},
|
| 381 |
+
"definitions": {
|
| 382 |
+
"dto.AuthResponse": {
|
| 383 |
+
"type": "object",
|
| 384 |
+
"properties": {
|
| 385 |
+
"token": {
|
| 386 |
+
"type": "string"
|
| 387 |
+
},
|
| 388 |
+
"user_id": {
|
| 389 |
+
"type": "string"
|
| 390 |
+
},
|
| 391 |
+
"username": {
|
| 392 |
+
"type": "string"
|
| 393 |
+
}
|
| 394 |
+
}
|
| 395 |
+
},
|
| 396 |
+
"dto.ConnectRequest": {
|
| 397 |
+
"type": "object"
|
| 398 |
+
},
|
| 399 |
+
"dto.ConnectResponse": {
|
| 400 |
+
"type": "object",
|
| 401 |
+
"properties": {
|
| 402 |
+
"account_id": {
|
| 403 |
+
"type": "string"
|
| 404 |
+
},
|
| 405 |
+
"details": {
|
| 406 |
+
"type": "string"
|
| 407 |
+
},
|
| 408 |
+
"message": {
|
| 409 |
+
"type": "string"
|
| 410 |
+
},
|
| 411 |
+
"qr_code": {
|
| 412 |
+
"type": "string"
|
| 413 |
+
}
|
| 414 |
+
}
|
| 415 |
+
},
|
| 416 |
+
"dto.ConnectionStatusResponse": {
|
| 417 |
+
"type": "object",
|
| 418 |
+
"properties": {
|
| 419 |
+
"account_id": {
|
| 420 |
+
"type": "string"
|
| 421 |
+
},
|
| 422 |
+
"jid": {
|
| 423 |
+
"type": "string"
|
| 424 |
+
},
|
| 425 |
+
"status": {
|
| 426 |
+
"type": "string"
|
| 427 |
+
}
|
| 428 |
+
}
|
| 429 |
+
},
|
| 430 |
+
"dto.ContactResponse": {
|
| 431 |
+
"type": "object",
|
| 432 |
+
"properties": {
|
| 433 |
+
"full_name": {
|
| 434 |
+
"type": "string"
|
| 435 |
+
},
|
| 436 |
+
"jid": {
|
| 437 |
+
"type": "string"
|
| 438 |
+
},
|
| 439 |
+
"name": {
|
| 440 |
+
"type": "string"
|
| 441 |
+
},
|
| 442 |
+
"phone_number": {
|
| 443 |
+
"type": "string"
|
| 444 |
+
},
|
| 445 |
+
"push_name": {
|
| 446 |
+
"type": "string"
|
| 447 |
+
}
|
| 448 |
+
}
|
| 449 |
+
},
|
| 450 |
+
"dto.ErrorResponse": {
|
| 451 |
+
"type": "object",
|
| 452 |
+
"properties": {
|
| 453 |
+
"errors": {},
|
| 454 |
+
"message": {},
|
| 455 |
+
"meta_data": {},
|
| 456 |
+
"status": {
|
| 457 |
+
"type": "string"
|
| 458 |
+
}
|
| 459 |
+
}
|
| 460 |
+
},
|
| 461 |
+
"dto.FetchContactsResponse": {
|
| 462 |
+
"type": "object",
|
| 463 |
+
"properties": {
|
| 464 |
+
"account_id": {
|
| 465 |
+
"type": "string"
|
| 466 |
+
},
|
| 467 |
+
"contacts": {
|
| 468 |
+
"type": "array",
|
| 469 |
+
"items": {
|
| 470 |
+
"$ref": "#/definitions/dto.ContactResponse"
|
| 471 |
+
}
|
| 472 |
+
}
|
| 473 |
+
}
|
| 474 |
+
},
|
| 475 |
+
"dto.LoginRequest": {
|
| 476 |
+
"type": "object",
|
| 477 |
+
"required": [
|
| 478 |
+
"password",
|
| 479 |
+
"username"
|
| 480 |
+
],
|
| 481 |
+
"properties": {
|
| 482 |
+
"password": {
|
| 483 |
+
"type": "string"
|
| 484 |
+
},
|
| 485 |
+
"username": {
|
| 486 |
+
"type": "string"
|
| 487 |
+
}
|
| 488 |
+
}
|
| 489 |
+
},
|
| 490 |
+
"dto.MeResponse": {
|
| 491 |
+
"type": "object",
|
| 492 |
+
"properties": {
|
| 493 |
+
"account_name": {
|
| 494 |
+
"type": "string"
|
| 495 |
+
},
|
| 496 |
+
"is_active": {
|
| 497 |
+
"type": "boolean"
|
| 498 |
+
},
|
| 499 |
+
"jid": {
|
| 500 |
+
"type": "string"
|
| 501 |
+
},
|
| 502 |
+
"phone": {
|
| 503 |
+
"type": "string"
|
| 504 |
+
},
|
| 505 |
+
"user_id": {
|
| 506 |
+
"type": "string"
|
| 507 |
+
},
|
| 508 |
+
"username": {
|
| 509 |
+
"type": "string"
|
| 510 |
+
}
|
| 511 |
+
}
|
| 512 |
+
},
|
| 513 |
+
"dto.RegisterRequest": {
|
| 514 |
+
"type": "object",
|
| 515 |
+
"required": [
|
| 516 |
+
"password",
|
| 517 |
+
"username"
|
| 518 |
+
],
|
| 519 |
+
"properties": {
|
| 520 |
+
"password": {
|
| 521 |
+
"type": "string",
|
| 522 |
+
"minLength": 6
|
| 523 |
+
},
|
| 524 |
+
"username": {
|
| 525 |
+
"type": "string",
|
| 526 |
+
"minLength": 3
|
| 527 |
+
}
|
| 528 |
+
}
|
| 529 |
+
},
|
| 530 |
+
"dto.SendMessageRequest": {
|
| 531 |
+
"type": "object",
|
| 532 |
+
"required": [
|
| 533 |
+
"message",
|
| 534 |
+
"recipient"
|
| 535 |
+
],
|
| 536 |
+
"properties": {
|
| 537 |
+
"message": {
|
| 538 |
+
"type": "string",
|
| 539 |
+
"example": "Hello world"
|
| 540 |
+
},
|
| 541 |
+
"recipient": {
|
| 542 |
+
"type": "string",
|
| 543 |
+
"example": "628123456789"
|
| 544 |
+
}
|
| 545 |
+
}
|
| 546 |
+
},
|
| 547 |
+
"dto.SendMessageResponse": {
|
| 548 |
+
"type": "object",
|
| 549 |
+
"properties": {
|
| 550 |
+
"message_id": {
|
| 551 |
+
"type": "string"
|
| 552 |
+
},
|
| 553 |
+
"status": {
|
| 554 |
+
"type": "string"
|
| 555 |
+
}
|
| 556 |
+
}
|
| 557 |
+
}
|
| 558 |
+
},
|
| 559 |
+
"securityDefinitions": {
|
| 560 |
+
"BearerAuth": {
|
| 561 |
+
"type": "apiKey",
|
| 562 |
+
"name": "Authorization",
|
| 563 |
+
"in": "header"
|
| 564 |
+
}
|
| 565 |
+
}
|
| 566 |
+
}
|
docs/swagger.yaml
ADDED
|
@@ -0,0 +1,369 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
basePath: /api
|
| 2 |
+
definitions:
|
| 3 |
+
dto.AuthResponse:
|
| 4 |
+
properties:
|
| 5 |
+
token:
|
| 6 |
+
type: string
|
| 7 |
+
user_id:
|
| 8 |
+
type: string
|
| 9 |
+
username:
|
| 10 |
+
type: string
|
| 11 |
+
type: object
|
| 12 |
+
dto.ConnectRequest:
|
| 13 |
+
type: object
|
| 14 |
+
dto.ConnectResponse:
|
| 15 |
+
properties:
|
| 16 |
+
account_id:
|
| 17 |
+
type: string
|
| 18 |
+
details:
|
| 19 |
+
type: string
|
| 20 |
+
message:
|
| 21 |
+
type: string
|
| 22 |
+
qr_code:
|
| 23 |
+
type: string
|
| 24 |
+
type: object
|
| 25 |
+
dto.ConnectionStatusResponse:
|
| 26 |
+
properties:
|
| 27 |
+
account_id:
|
| 28 |
+
type: string
|
| 29 |
+
jid:
|
| 30 |
+
type: string
|
| 31 |
+
status:
|
| 32 |
+
type: string
|
| 33 |
+
type: object
|
| 34 |
+
dto.ContactResponse:
|
| 35 |
+
properties:
|
| 36 |
+
full_name:
|
| 37 |
+
type: string
|
| 38 |
+
jid:
|
| 39 |
+
type: string
|
| 40 |
+
name:
|
| 41 |
+
type: string
|
| 42 |
+
phone_number:
|
| 43 |
+
type: string
|
| 44 |
+
push_name:
|
| 45 |
+
type: string
|
| 46 |
+
type: object
|
| 47 |
+
dto.ErrorResponse:
|
| 48 |
+
properties:
|
| 49 |
+
errors: {}
|
| 50 |
+
message: {}
|
| 51 |
+
meta_data: {}
|
| 52 |
+
status:
|
| 53 |
+
type: string
|
| 54 |
+
type: object
|
| 55 |
+
dto.FetchContactsResponse:
|
| 56 |
+
properties:
|
| 57 |
+
account_id:
|
| 58 |
+
type: string
|
| 59 |
+
contacts:
|
| 60 |
+
items:
|
| 61 |
+
$ref: '#/definitions/dto.ContactResponse'
|
| 62 |
+
type: array
|
| 63 |
+
type: object
|
| 64 |
+
dto.LoginRequest:
|
| 65 |
+
properties:
|
| 66 |
+
password:
|
| 67 |
+
type: string
|
| 68 |
+
username:
|
| 69 |
+
type: string
|
| 70 |
+
required:
|
| 71 |
+
- password
|
| 72 |
+
- username
|
| 73 |
+
type: object
|
| 74 |
+
dto.MeResponse:
|
| 75 |
+
properties:
|
| 76 |
+
account_name:
|
| 77 |
+
type: string
|
| 78 |
+
is_active:
|
| 79 |
+
type: boolean
|
| 80 |
+
jid:
|
| 81 |
+
type: string
|
| 82 |
+
phone:
|
| 83 |
+
type: string
|
| 84 |
+
user_id:
|
| 85 |
+
type: string
|
| 86 |
+
username:
|
| 87 |
+
type: string
|
| 88 |
+
type: object
|
| 89 |
+
dto.RegisterRequest:
|
| 90 |
+
properties:
|
| 91 |
+
password:
|
| 92 |
+
minLength: 6
|
| 93 |
+
type: string
|
| 94 |
+
username:
|
| 95 |
+
minLength: 3
|
| 96 |
+
type: string
|
| 97 |
+
required:
|
| 98 |
+
- password
|
| 99 |
+
- username
|
| 100 |
+
type: object
|
| 101 |
+
dto.SendMessageRequest:
|
| 102 |
+
properties:
|
| 103 |
+
message:
|
| 104 |
+
example: Hello world
|
| 105 |
+
type: string
|
| 106 |
+
recipient:
|
| 107 |
+
example: "628123456789"
|
| 108 |
+
type: string
|
| 109 |
+
required:
|
| 110 |
+
- message
|
| 111 |
+
- recipient
|
| 112 |
+
type: object
|
| 113 |
+
dto.SendMessageResponse:
|
| 114 |
+
properties:
|
| 115 |
+
message_id:
|
| 116 |
+
type: string
|
| 117 |
+
status:
|
| 118 |
+
type: string
|
| 119 |
+
type: object
|
| 120 |
+
host: localhost:8080
|
| 121 |
+
info:
|
| 122 |
+
contact:
|
| 123 |
+
email: support@swagger.io
|
| 124 |
+
name: API Support
|
| 125 |
+
url: http://www.swagger.io/support
|
| 126 |
+
description: This is the API documentation for the Whatsapp Backend.
|
| 127 |
+
license:
|
| 128 |
+
name: Apache 2.0
|
| 129 |
+
url: http://www.apache.org/licenses/LICENSE-2.0.html
|
| 130 |
+
termsOfService: http://swagger.io/terms/
|
| 131 |
+
title: Whatsapp Backend API
|
| 132 |
+
version: "1.0"
|
| 133 |
+
paths:
|
| 134 |
+
/auth/login:
|
| 135 |
+
post:
|
| 136 |
+
consumes:
|
| 137 |
+
- application/json
|
| 138 |
+
description: Login a user with credentials
|
| 139 |
+
parameters:
|
| 140 |
+
- description: Login Request
|
| 141 |
+
in: body
|
| 142 |
+
name: request
|
| 143 |
+
required: true
|
| 144 |
+
schema:
|
| 145 |
+
$ref: '#/definitions/dto.LoginRequest'
|
| 146 |
+
produces:
|
| 147 |
+
- application/json
|
| 148 |
+
responses:
|
| 149 |
+
"200":
|
| 150 |
+
description: OK
|
| 151 |
+
schema:
|
| 152 |
+
$ref: '#/definitions/dto.AuthResponse'
|
| 153 |
+
"400":
|
| 154 |
+
description: Bad Request
|
| 155 |
+
schema:
|
| 156 |
+
$ref: '#/definitions/dto.ErrorResponse'
|
| 157 |
+
summary: Login a user
|
| 158 |
+
tags:
|
| 159 |
+
- auth
|
| 160 |
+
/auth/logout:
|
| 161 |
+
post:
|
| 162 |
+
description: Logout the current user
|
| 163 |
+
parameters:
|
| 164 |
+
- description: CSRF Protection Token
|
| 165 |
+
in: header
|
| 166 |
+
name: X-CSRF-Token
|
| 167 |
+
required: true
|
| 168 |
+
type: string
|
| 169 |
+
responses:
|
| 170 |
+
"200":
|
| 171 |
+
description: OK
|
| 172 |
+
summary: Logout a user
|
| 173 |
+
tags:
|
| 174 |
+
- auth
|
| 175 |
+
/auth/me:
|
| 176 |
+
get:
|
| 177 |
+
description: Get the profile of the currently logged-in user
|
| 178 |
+
responses:
|
| 179 |
+
"200":
|
| 180 |
+
description: OK
|
| 181 |
+
schema:
|
| 182 |
+
$ref: '#/definitions/dto.MeResponse'
|
| 183 |
+
"401":
|
| 184 |
+
description: Unauthorized
|
| 185 |
+
schema:
|
| 186 |
+
$ref: '#/definitions/dto.ErrorResponse'
|
| 187 |
+
security:
|
| 188 |
+
- BearerAuth: []
|
| 189 |
+
summary: Get current user profile
|
| 190 |
+
tags:
|
| 191 |
+
- auth
|
| 192 |
+
/auth/refresh:
|
| 193 |
+
post:
|
| 194 |
+
description: Refresh the access token using the refresh token cookie
|
| 195 |
+
parameters:
|
| 196 |
+
- description: CSRF Protection Token
|
| 197 |
+
in: header
|
| 198 |
+
name: X-CSRF-Token
|
| 199 |
+
required: true
|
| 200 |
+
type: string
|
| 201 |
+
responses:
|
| 202 |
+
"200":
|
| 203 |
+
description: OK
|
| 204 |
+
schema:
|
| 205 |
+
$ref: '#/definitions/dto.AuthResponse'
|
| 206 |
+
"401":
|
| 207 |
+
description: Unauthorized
|
| 208 |
+
schema:
|
| 209 |
+
$ref: '#/definitions/dto.ErrorResponse'
|
| 210 |
+
summary: Refresh access token
|
| 211 |
+
tags:
|
| 212 |
+
- auth
|
| 213 |
+
/auth/register:
|
| 214 |
+
post:
|
| 215 |
+
consumes:
|
| 216 |
+
- application/json
|
| 217 |
+
description: Register a new user with the provided details
|
| 218 |
+
parameters:
|
| 219 |
+
- description: Register Request
|
| 220 |
+
in: body
|
| 221 |
+
name: request
|
| 222 |
+
required: true
|
| 223 |
+
schema:
|
| 224 |
+
$ref: '#/definitions/dto.RegisterRequest'
|
| 225 |
+
produces:
|
| 226 |
+
- application/json
|
| 227 |
+
responses:
|
| 228 |
+
"200":
|
| 229 |
+
description: OK
|
| 230 |
+
schema:
|
| 231 |
+
$ref: '#/definitions/dto.AuthResponse'
|
| 232 |
+
"400":
|
| 233 |
+
description: Bad Request
|
| 234 |
+
schema:
|
| 235 |
+
$ref: '#/definitions/dto.ErrorResponse'
|
| 236 |
+
summary: Register a new user
|
| 237 |
+
tags:
|
| 238 |
+
- auth
|
| 239 |
+
/chat/fetch:
|
| 240 |
+
get:
|
| 241 |
+
consumes:
|
| 242 |
+
- application/json
|
| 243 |
+
description: Fetch list of contacts from the connected WhatsApp account
|
| 244 |
+
produces:
|
| 245 |
+
- application/json
|
| 246 |
+
responses:
|
| 247 |
+
"200":
|
| 248 |
+
description: OK
|
| 249 |
+
schema:
|
| 250 |
+
$ref: '#/definitions/dto.FetchContactsResponse'
|
| 251 |
+
"400":
|
| 252 |
+
description: Bad Request
|
| 253 |
+
schema:
|
| 254 |
+
$ref: '#/definitions/dto.ErrorResponse'
|
| 255 |
+
"401":
|
| 256 |
+
description: Unauthorized
|
| 257 |
+
schema:
|
| 258 |
+
$ref: '#/definitions/dto.ErrorResponse'
|
| 259 |
+
security:
|
| 260 |
+
- BearerAuth: []
|
| 261 |
+
summary: Fetch WhatsApp contacts
|
| 262 |
+
tags:
|
| 263 |
+
- chat
|
| 264 |
+
/chat/send:
|
| 265 |
+
post:
|
| 266 |
+
consumes:
|
| 267 |
+
- application/json
|
| 268 |
+
description: Send a text message to a WhatsApp number
|
| 269 |
+
parameters:
|
| 270 |
+
- description: Send Message Request
|
| 271 |
+
in: body
|
| 272 |
+
name: request
|
| 273 |
+
required: true
|
| 274 |
+
schema:
|
| 275 |
+
$ref: '#/definitions/dto.SendMessageRequest'
|
| 276 |
+
- description: CSRF Protection Token
|
| 277 |
+
in: header
|
| 278 |
+
name: X-CSRF-Token
|
| 279 |
+
required: true
|
| 280 |
+
type: string
|
| 281 |
+
produces:
|
| 282 |
+
- application/json
|
| 283 |
+
responses:
|
| 284 |
+
"200":
|
| 285 |
+
description: OK
|
| 286 |
+
schema:
|
| 287 |
+
$ref: '#/definitions/dto.SendMessageResponse'
|
| 288 |
+
"400":
|
| 289 |
+
description: Bad Request
|
| 290 |
+
schema:
|
| 291 |
+
$ref: '#/definitions/dto.ErrorResponse'
|
| 292 |
+
"401":
|
| 293 |
+
description: Unauthorized
|
| 294 |
+
schema:
|
| 295 |
+
$ref: '#/definitions/dto.ErrorResponse'
|
| 296 |
+
security:
|
| 297 |
+
- BearerAuth: []
|
| 298 |
+
summary: Send WhatsApp message
|
| 299 |
+
tags:
|
| 300 |
+
- chat
|
| 301 |
+
/whatsapp/connect:
|
| 302 |
+
post:
|
| 303 |
+
consumes:
|
| 304 |
+
- application/json
|
| 305 |
+
description: Initiate a connection request for a new WhatsApp account. Returns
|
| 306 |
+
a QR code if not connected.
|
| 307 |
+
parameters:
|
| 308 |
+
- description: Connect Request
|
| 309 |
+
in: body
|
| 310 |
+
name: request
|
| 311 |
+
required: true
|
| 312 |
+
schema:
|
| 313 |
+
$ref: '#/definitions/dto.ConnectRequest'
|
| 314 |
+
- description: CSRF Protection Token
|
| 315 |
+
in: header
|
| 316 |
+
name: X-CSRF-Token
|
| 317 |
+
required: true
|
| 318 |
+
type: string
|
| 319 |
+
produces:
|
| 320 |
+
- application/json
|
| 321 |
+
responses:
|
| 322 |
+
"200":
|
| 323 |
+
description: OK
|
| 324 |
+
schema:
|
| 325 |
+
$ref: '#/definitions/dto.ConnectResponse'
|
| 326 |
+
"401":
|
| 327 |
+
description: Unauthorized
|
| 328 |
+
schema:
|
| 329 |
+
$ref: '#/definitions/dto.ErrorResponse'
|
| 330 |
+
"500":
|
| 331 |
+
description: Internal Server Error
|
| 332 |
+
schema:
|
| 333 |
+
$ref: '#/definitions/dto.ErrorResponse'
|
| 334 |
+
security:
|
| 335 |
+
- BearerAuth: []
|
| 336 |
+
summary: Connect new WhatsApp account
|
| 337 |
+
tags:
|
| 338 |
+
- whatsapp
|
| 339 |
+
/whatsapp/status:
|
| 340 |
+
get:
|
| 341 |
+
consumes:
|
| 342 |
+
- application/json
|
| 343 |
+
description: Get the current status of the WhatsApp connection
|
| 344 |
+
produces:
|
| 345 |
+
- application/json
|
| 346 |
+
responses:
|
| 347 |
+
"200":
|
| 348 |
+
description: OK
|
| 349 |
+
schema:
|
| 350 |
+
$ref: '#/definitions/dto.ConnectionStatusResponse'
|
| 351 |
+
"401":
|
| 352 |
+
description: Unauthorized
|
| 353 |
+
schema:
|
| 354 |
+
$ref: '#/definitions/dto.ErrorResponse'
|
| 355 |
+
"500":
|
| 356 |
+
description: Internal Server Error
|
| 357 |
+
schema:
|
| 358 |
+
$ref: '#/definitions/dto.ErrorResponse'
|
| 359 |
+
security:
|
| 360 |
+
- BearerAuth: []
|
| 361 |
+
summary: Get WhatsApp connection status
|
| 362 |
+
tags:
|
| 363 |
+
- whatsapp
|
| 364 |
+
securityDefinitions:
|
| 365 |
+
BearerAuth:
|
| 366 |
+
in: header
|
| 367 |
+
name: Authorization
|
| 368 |
+
type: apiKey
|
| 369 |
+
swagger: "2.0"
|
go.mod
CHANGED
|
@@ -5,9 +5,13 @@ go 1.24.5
|
|
| 5 |
require (
|
| 6 |
github.com/gin-contrib/gzip v1.2.5
|
| 7 |
github.com/gin-gonic/gin v1.11.0
|
|
|
|
| 8 |
github.com/golang-jwt/jwt/v5 v5.3.0
|
| 9 |
github.com/google/uuid v1.6.0
|
| 10 |
github.com/joho/godotenv v1.5.1
|
|
|
|
|
|
|
|
|
|
| 11 |
go.mau.fi/whatsmeow v0.0.0-20251217143725-11cf47c62d32
|
| 12 |
golang.org/x/crypto v0.46.0
|
| 13 |
gorm.io/driver/postgres v1.6.0
|
|
@@ -16,6 +20,7 @@ require (
|
|
| 16 |
|
| 17 |
require (
|
| 18 |
filippo.io/edwards25519 v1.1.0 // indirect
|
|
|
|
| 19 |
github.com/beeper/argo-go v1.1.2 // indirect
|
| 20 |
github.com/bytedance/gopkg v0.1.3 // indirect
|
| 21 |
github.com/bytedance/sonic v1.14.2 // indirect
|
|
@@ -25,9 +30,18 @@ require (
|
|
| 25 |
github.com/elliotchance/orderedmap/v3 v3.1.0 // indirect
|
| 26 |
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
| 27 |
github.com/gin-contrib/sse v1.1.0 // indirect
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
github.com/go-playground/locales v0.14.1 // indirect
|
| 29 |
github.com/go-playground/universal-translator v0.18.1 // indirect
|
| 30 |
-
github.com/go-playground/validator/v10 v10.29.0 // indirect
|
| 31 |
github.com/goccy/go-json v0.10.5 // indirect
|
| 32 |
github.com/goccy/go-yaml v1.19.1 // indirect
|
| 33 |
github.com/jackc/pgpassfile v1.0.0 // indirect
|
|
@@ -38,6 +52,7 @@ require (
|
|
| 38 |
github.com/jinzhu/now v1.1.5 // indirect
|
| 39 |
github.com/json-iterator/go v1.1.12 // indirect
|
| 40 |
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
|
|
|
| 41 |
github.com/leodido/go-urn v1.4.0 // indirect
|
| 42 |
github.com/mattn/go-colorable v0.1.14 // indirect
|
| 43 |
github.com/mattn/go-isatty v0.0.20 // indirect
|
|
@@ -53,11 +68,14 @@ require (
|
|
| 53 |
github.com/vektah/gqlparser/v2 v2.5.27 // indirect
|
| 54 |
go.mau.fi/libsignal v0.2.1 // indirect
|
| 55 |
go.mau.fi/util v0.9.4 // indirect
|
|
|
|
| 56 |
golang.org/x/arch v0.23.0 // indirect
|
| 57 |
golang.org/x/exp v0.0.0-20251209150349-8475f28825e9 // indirect
|
|
|
|
| 58 |
golang.org/x/net v0.48.0 // indirect
|
| 59 |
golang.org/x/sync v0.19.0 // indirect
|
| 60 |
golang.org/x/sys v0.39.0 // indirect
|
| 61 |
golang.org/x/text v0.32.0 // indirect
|
|
|
|
| 62 |
google.golang.org/protobuf v1.36.11 // indirect
|
| 63 |
)
|
|
|
|
| 5 |
require (
|
| 6 |
github.com/gin-contrib/gzip v1.2.5
|
| 7 |
github.com/gin-gonic/gin v1.11.0
|
| 8 |
+
github.com/go-playground/validator/v10 v10.29.0
|
| 9 |
github.com/golang-jwt/jwt/v5 v5.3.0
|
| 10 |
github.com/google/uuid v1.6.0
|
| 11 |
github.com/joho/godotenv v1.5.1
|
| 12 |
+
github.com/swaggo/files v1.0.1
|
| 13 |
+
github.com/swaggo/gin-swagger v1.6.1
|
| 14 |
+
github.com/swaggo/swag v1.16.6
|
| 15 |
go.mau.fi/whatsmeow v0.0.0-20251217143725-11cf47c62d32
|
| 16 |
golang.org/x/crypto v0.46.0
|
| 17 |
gorm.io/driver/postgres v1.6.0
|
|
|
|
| 20 |
|
| 21 |
require (
|
| 22 |
filippo.io/edwards25519 v1.1.0 // indirect
|
| 23 |
+
github.com/KyleBanks/depth v1.2.1 // indirect
|
| 24 |
github.com/beeper/argo-go v1.1.2 // indirect
|
| 25 |
github.com/bytedance/gopkg v0.1.3 // indirect
|
| 26 |
github.com/bytedance/sonic v1.14.2 // indirect
|
|
|
|
| 30 |
github.com/elliotchance/orderedmap/v3 v3.1.0 // indirect
|
| 31 |
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
| 32 |
github.com/gin-contrib/sse v1.1.0 // indirect
|
| 33 |
+
github.com/go-openapi/jsonpointer v0.22.4 // indirect
|
| 34 |
+
github.com/go-openapi/jsonreference v0.21.4 // indirect
|
| 35 |
+
github.com/go-openapi/spec v0.22.3 // indirect
|
| 36 |
+
github.com/go-openapi/swag/conv v0.25.4 // indirect
|
| 37 |
+
github.com/go-openapi/swag/jsonname v0.25.4 // indirect
|
| 38 |
+
github.com/go-openapi/swag/jsonutils v0.25.4 // indirect
|
| 39 |
+
github.com/go-openapi/swag/loading v0.25.4 // indirect
|
| 40 |
+
github.com/go-openapi/swag/stringutils v0.25.4 // indirect
|
| 41 |
+
github.com/go-openapi/swag/typeutils v0.25.4 // indirect
|
| 42 |
+
github.com/go-openapi/swag/yamlutils v0.25.4 // indirect
|
| 43 |
github.com/go-playground/locales v0.14.1 // indirect
|
| 44 |
github.com/go-playground/universal-translator v0.18.1 // indirect
|
|
|
|
| 45 |
github.com/goccy/go-json v0.10.5 // indirect
|
| 46 |
github.com/goccy/go-yaml v1.19.1 // indirect
|
| 47 |
github.com/jackc/pgpassfile v1.0.0 // indirect
|
|
|
|
| 52 |
github.com/jinzhu/now v1.1.5 // indirect
|
| 53 |
github.com/json-iterator/go v1.1.12 // indirect
|
| 54 |
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
| 55 |
+
github.com/kr/text v0.2.0 // indirect
|
| 56 |
github.com/leodido/go-urn v1.4.0 // indirect
|
| 57 |
github.com/mattn/go-colorable v0.1.14 // indirect
|
| 58 |
github.com/mattn/go-isatty v0.0.20 // indirect
|
|
|
|
| 68 |
github.com/vektah/gqlparser/v2 v2.5.27 // indirect
|
| 69 |
go.mau.fi/libsignal v0.2.1 // indirect
|
| 70 |
go.mau.fi/util v0.9.4 // indirect
|
| 71 |
+
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
| 72 |
golang.org/x/arch v0.23.0 // indirect
|
| 73 |
golang.org/x/exp v0.0.0-20251209150349-8475f28825e9 // indirect
|
| 74 |
+
golang.org/x/mod v0.31.0 // indirect
|
| 75 |
golang.org/x/net v0.48.0 // indirect
|
| 76 |
golang.org/x/sync v0.19.0 // indirect
|
| 77 |
golang.org/x/sys v0.39.0 // indirect
|
| 78 |
golang.org/x/text v0.32.0 // indirect
|
| 79 |
+
golang.org/x/tools v0.40.0 // indirect
|
| 80 |
google.golang.org/protobuf v1.36.11 // indirect
|
| 81 |
)
|
go.sum
CHANGED
|
@@ -2,6 +2,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
|
| 2 |
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
| 3 |
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
| 4 |
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
|
|
|
|
|
|
| 5 |
github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM=
|
| 6 |
github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU=
|
| 7 |
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
|
@@ -19,6 +21,7 @@ github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gE
|
|
| 19 |
github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=
|
| 20 |
github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
|
| 21 |
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
|
|
|
| 22 |
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
| 23 |
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
| 24 |
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
@@ -32,6 +35,33 @@ github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w
|
|
| 32 |
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
| 33 |
github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
|
| 34 |
github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
| 36 |
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
| 37 |
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
|
@@ -70,6 +100,10 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
|
| 70 |
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
| 71 |
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
| 72 |
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
| 74 |
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
| 75 |
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
|
@@ -81,8 +115,6 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
|
| 81 |
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
| 82 |
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
|
| 83 |
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
| 84 |
-
github.com/mdp/qrterminal/v3 v3.2.1 h1:6+yQjiiOsSuXT5n9/m60E54vdgFsw0zhADHhHLrFet4=
|
| 85 |
-
github.com/mdp/qrterminal/v3 v3.2.1/go.mod h1:jOTmXvnBsMy5xqLniO0R++Jmjs2sTm9dFSuQ5kpz/SU=
|
| 86 |
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
| 87 |
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
| 88 |
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
@@ -99,6 +131,8 @@ github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
|
| 99 |
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
| 100 |
github.com/quic-go/quic-go v0.58.0 h1:ggY2pvZaVdB9EyojxL1p+5mptkuHyX5MOSv4dgWF4Ug=
|
| 101 |
github.com/quic-go/quic-go v0.58.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
|
|
|
|
|
|
| 102 |
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
| 103 |
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
| 104 |
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
|
@@ -116,12 +150,19 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
|
|
| 116 |
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
| 117 |
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
| 118 |
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
| 120 |
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
| 121 |
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
| 122 |
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
| 123 |
github.com/vektah/gqlparser/v2 v2.5.27 h1:RHPD3JOplpk5mP5JGX8RKZkt2/Vwj/PZv0HxTdwFp0s=
|
| 124 |
github.com/vektah/gqlparser/v2 v2.5.27/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
|
|
|
|
| 125 |
go.mau.fi/libsignal v0.2.1 h1:vRZG4EzTn70XY6Oh/pVKrQGuMHBkAWlGRC22/85m9L0=
|
| 126 |
go.mau.fi/libsignal v0.2.1/go.mod h1:iVvjrHyfQqWajOUaMEsIfo3IqgVMrhWcPiiEzk7NgoU=
|
| 127 |
go.mau.fi/util v0.9.4 h1:gWdUff+K2rCynRPysXalqqQyr2ahkSWaestH6YhSpso=
|
|
@@ -130,28 +171,60 @@ go.mau.fi/whatsmeow v0.0.0-20251217143725-11cf47c62d32 h1:NeE9eEYY4kEJVCfCXaAU27
|
|
| 130 |
go.mau.fi/whatsmeow v0.0.0-20251217143725-11cf47c62d32/go.mod h1:S4OWR9+hTx+54+jRzl+NfRBXnGpPm5IRPyhXB7haSd0=
|
| 131 |
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
| 132 |
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
|
|
|
|
|
|
| 133 |
golang.org/x/arch v0.23.0 h1:lKF64A2jF6Zd8L0knGltUnegD62JMFBiCPBmQpToHhg=
|
| 134 |
golang.org/x/arch v0.23.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
|
|
|
|
|
|
| 135 |
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
| 136 |
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
| 137 |
golang.org/x/exp v0.0.0-20251209150349-8475f28825e9 h1:MDfG8Cvcqlt9XXrmEiD4epKn7VJHZO84hejP9Jmp0MM=
|
| 138 |
golang.org/x/exp v0.0.0-20251209150349-8475f28825e9/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
| 140 |
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
|
|
|
|
|
|
| 141 |
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
| 142 |
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
|
|
| 144 |
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 145 |
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 146 |
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
| 147 |
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
| 148 |
-
golang.org/x/term v0.
|
| 149 |
-
golang.org/x/term v0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 150 |
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
| 151 |
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
| 153 |
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
| 154 |
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
|
|
|
|
|
| 155 |
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
| 156 |
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
| 157 |
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@@ -159,5 +232,3 @@ gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
|
|
| 159 |
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
| 160 |
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
|
| 161 |
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
|
| 162 |
-
rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
|
| 163 |
-
rsc.io/qr v0.2.0/go.mod h1:IF+uZjkb9fqyeF/4tlBoynqmQxUoPfWEKh921coOuXs=
|
|
|
|
| 2 |
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
| 3 |
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
| 4 |
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
| 5 |
+
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
|
| 6 |
+
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
|
| 7 |
github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM=
|
| 8 |
github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU=
|
| 9 |
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
|
|
|
| 21 |
github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=
|
| 22 |
github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
|
| 23 |
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
| 24 |
+
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
| 25 |
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
| 26 |
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
| 27 |
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
|
|
| 35 |
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
| 36 |
github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
|
| 37 |
github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
|
| 38 |
+
github.com/go-openapi/jsonpointer v0.22.4 h1:dZtK82WlNpVLDW2jlA1YCiVJFVqkED1MegOUy9kR5T4=
|
| 39 |
+
github.com/go-openapi/jsonpointer v0.22.4/go.mod h1:elX9+UgznpFhgBuaMQ7iu4lvvX1nvNsesQ3oxmYTw80=
|
| 40 |
+
github.com/go-openapi/jsonreference v0.21.4 h1:24qaE2y9bx/q3uRK/qN+TDwbok1NhbSmGjjySRCHtC8=
|
| 41 |
+
github.com/go-openapi/jsonreference v0.21.4/go.mod h1:rIENPTjDbLpzQmQWCj5kKj3ZlmEh+EFVbz3RTUh30/4=
|
| 42 |
+
github.com/go-openapi/spec v0.22.3 h1:qRSmj6Smz2rEBxMnLRBMeBWxbbOvuOoElvSvObIgwQc=
|
| 43 |
+
github.com/go-openapi/spec v0.22.3/go.mod h1:iIImLODL2loCh3Vnox8TY2YWYJZjMAKYyLH2Mu8lOZs=
|
| 44 |
+
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
| 45 |
+
github.com/go-openapi/swag/conv v0.25.4 h1:/Dd7p0LZXczgUcC/Ikm1+YqVzkEeCc9LnOWjfkpkfe4=
|
| 46 |
+
github.com/go-openapi/swag/conv v0.25.4/go.mod h1:3LXfie/lwoAv0NHoEuY1hjoFAYkvlqI/Bn5EQDD3PPU=
|
| 47 |
+
github.com/go-openapi/swag/jsonname v0.25.4 h1:bZH0+MsS03MbnwBXYhuTttMOqk+5KcQ9869Vye1bNHI=
|
| 48 |
+
github.com/go-openapi/swag/jsonname v0.25.4/go.mod h1:GPVEk9CWVhNvWhZgrnvRA6utbAltopbKwDu8mXNUMag=
|
| 49 |
+
github.com/go-openapi/swag/jsonutils v0.25.4 h1:VSchfbGhD4UTf4vCdR2F4TLBdLwHyUDTd1/q4i+jGZA=
|
| 50 |
+
github.com/go-openapi/swag/jsonutils v0.25.4/go.mod h1:7OYGXpvVFPn4PpaSdPHJBtF0iGnbEaTk8AvBkoWnaAY=
|
| 51 |
+
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4 h1:IACsSvBhiNJwlDix7wq39SS2Fh7lUOCJRmx/4SN4sVo=
|
| 52 |
+
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.4/go.mod h1:Mt0Ost9l3cUzVv4OEZG+WSeoHwjWLnarzMePNDAOBiM=
|
| 53 |
+
github.com/go-openapi/swag/loading v0.25.4 h1:jN4MvLj0X6yhCDduRsxDDw1aHe+ZWoLjW+9ZQWIKn2s=
|
| 54 |
+
github.com/go-openapi/swag/loading v0.25.4/go.mod h1:rpUM1ZiyEP9+mNLIQUdMiD7dCETXvkkC30z53i+ftTE=
|
| 55 |
+
github.com/go-openapi/swag/stringutils v0.25.4 h1:O6dU1Rd8bej4HPA3/CLPciNBBDwZj9HiEpdVsb8B5A8=
|
| 56 |
+
github.com/go-openapi/swag/stringutils v0.25.4/go.mod h1:GTsRvhJW5xM5gkgiFe0fV3PUlFm0dr8vki6/VSRaZK0=
|
| 57 |
+
github.com/go-openapi/swag/typeutils v0.25.4 h1:1/fbZOUN472NTc39zpa+YGHn3jzHWhv42wAJSN91wRw=
|
| 58 |
+
github.com/go-openapi/swag/typeutils v0.25.4/go.mod h1:Ou7g//Wx8tTLS9vG0UmzfCsjZjKhpjxayRKTHXf2pTE=
|
| 59 |
+
github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtPBZ9A56h92Sw=
|
| 60 |
+
github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc=
|
| 61 |
+
github.com/go-openapi/testify/enable/yaml/v2 v2.0.2 h1:0+Y41Pz1NkbTHz8NngxTuAXxEodtNSI1WG1c/m5Akw4=
|
| 62 |
+
github.com/go-openapi/testify/enable/yaml/v2 v2.0.2/go.mod h1:kme83333GCtJQHXQ8UKX3IBZu6z8T5Dvy5+CW3NLUUg=
|
| 63 |
+
github.com/go-openapi/testify/v2 v2.0.2 h1:X999g3jeLcoY8qctY/c/Z8iBHTbwLz7R2WXd6Ub6wls=
|
| 64 |
+
github.com/go-openapi/testify/v2 v2.0.2/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
|
| 65 |
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
| 66 |
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
| 67 |
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
|
|
|
| 100 |
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
| 101 |
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
| 102 |
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
| 103 |
+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
| 104 |
+
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
| 105 |
+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
| 106 |
+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
| 107 |
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
| 108 |
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
| 109 |
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
|
|
|
| 115 |
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
| 116 |
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
|
| 117 |
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
|
|
|
|
|
|
| 118 |
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
| 119 |
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
| 120 |
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
|
|
| 131 |
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
| 132 |
github.com/quic-go/quic-go v0.58.0 h1:ggY2pvZaVdB9EyojxL1p+5mptkuHyX5MOSv4dgWF4Ug=
|
| 133 |
github.com/quic-go/quic-go v0.58.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
| 134 |
+
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
| 135 |
+
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
| 136 |
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
| 137 |
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
| 138 |
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
|
|
|
| 150 |
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
| 151 |
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
| 152 |
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
| 153 |
+
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
|
| 154 |
+
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
|
| 155 |
+
github.com/swaggo/gin-swagger v1.6.1 h1:Ri06G4gc9N4t4k8hekMigJ9zKTFSlqj/9paAQCQs7cY=
|
| 156 |
+
github.com/swaggo/gin-swagger v1.6.1/go.mod h1:LQ+hJStHakCWRiK/YNYtJOu4mR2FP+pxLnILT/qNiTw=
|
| 157 |
+
github.com/swaggo/swag v1.16.6 h1:qBNcx53ZaX+M5dxVyTrgQ0PJ/ACK+NzhwcbieTt+9yI=
|
| 158 |
+
github.com/swaggo/swag v1.16.6/go.mod h1:ngP2etMK5a0P3QBizic5MEwpRmluJZPHjXcMoj4Xesg=
|
| 159 |
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
| 160 |
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
| 161 |
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
| 162 |
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
| 163 |
github.com/vektah/gqlparser/v2 v2.5.27 h1:RHPD3JOplpk5mP5JGX8RKZkt2/Vwj/PZv0HxTdwFp0s=
|
| 164 |
github.com/vektah/gqlparser/v2 v2.5.27/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
|
| 165 |
+
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
| 166 |
go.mau.fi/libsignal v0.2.1 h1:vRZG4EzTn70XY6Oh/pVKrQGuMHBkAWlGRC22/85m9L0=
|
| 167 |
go.mau.fi/libsignal v0.2.1/go.mod h1:iVvjrHyfQqWajOUaMEsIfo3IqgVMrhWcPiiEzk7NgoU=
|
| 168 |
go.mau.fi/util v0.9.4 h1:gWdUff+K2rCynRPysXalqqQyr2ahkSWaestH6YhSpso=
|
|
|
|
| 171 |
go.mau.fi/whatsmeow v0.0.0-20251217143725-11cf47c62d32/go.mod h1:S4OWR9+hTx+54+jRzl+NfRBXnGpPm5IRPyhXB7haSd0=
|
| 172 |
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
| 173 |
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
| 174 |
+
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
| 175 |
+
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
| 176 |
golang.org/x/arch v0.23.0 h1:lKF64A2jF6Zd8L0knGltUnegD62JMFBiCPBmQpToHhg=
|
| 177 |
golang.org/x/arch v0.23.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
| 178 |
+
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
| 179 |
+
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
| 180 |
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
| 181 |
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
| 182 |
golang.org/x/exp v0.0.0-20251209150349-8475f28825e9 h1:MDfG8Cvcqlt9XXrmEiD4epKn7VJHZO84hejP9Jmp0MM=
|
| 183 |
golang.org/x/exp v0.0.0-20251209150349-8475f28825e9/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
|
| 184 |
+
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
| 185 |
+
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
| 186 |
+
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
| 187 |
+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
| 188 |
+
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
| 189 |
+
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
| 190 |
+
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
| 191 |
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
| 192 |
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
| 193 |
+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
| 194 |
+
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
| 195 |
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
| 196 |
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
| 197 |
+
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
| 198 |
+
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
| 199 |
+
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 200 |
+
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 201 |
+
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 202 |
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 203 |
+
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 204 |
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 205 |
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
| 206 |
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
| 207 |
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
| 208 |
+
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
| 209 |
+
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
| 210 |
+
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
| 211 |
+
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
| 212 |
+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
| 213 |
+
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
| 214 |
+
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
| 215 |
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
| 216 |
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
| 217 |
+
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
| 218 |
+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
| 219 |
+
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
| 220 |
+
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
| 221 |
+
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
| 222 |
+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
| 223 |
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
| 224 |
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
| 225 |
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
| 226 |
+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
| 227 |
+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
| 228 |
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
| 229 |
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
| 230 |
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
|
|
| 232 |
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
| 233 |
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
|
| 234 |
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
|
|
|
|
|
|
main.go
CHANGED
|
@@ -5,6 +5,24 @@ import (
|
|
| 5 |
"whatsapp-backend/router"
|
| 6 |
)
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
func main() {
|
| 9 |
appProvider := provider.NewAppProvider()
|
| 10 |
router.RunRouter(appProvider)
|
|
|
|
| 5 |
"whatsapp-backend/router"
|
| 6 |
)
|
| 7 |
|
| 8 |
+
// @title Whatsapp Backend API
|
| 9 |
+
// @version 1.0
|
| 10 |
+
// @description This is the API documentation for the Whatsapp Backend.
|
| 11 |
+
// @termsOfService http://swagger.io/terms/
|
| 12 |
+
|
| 13 |
+
// @contact.name API Support
|
| 14 |
+
// @contact.url http://www.swagger.io/support
|
| 15 |
+
// @contact.email support@swagger.io
|
| 16 |
+
|
| 17 |
+
// @license.name Apache 2.0
|
| 18 |
+
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
|
| 19 |
+
|
| 20 |
+
// @host localhost:8080
|
| 21 |
+
// @BasePath /api
|
| 22 |
+
|
| 23 |
+
// @securityDefinitions.apikey BearerAuth
|
| 24 |
+
// @in header
|
| 25 |
+
// @name Authorization
|
| 26 |
func main() {
|
| 27 |
appProvider := provider.NewAppProvider()
|
| 28 |
router.RunRouter(appProvider)
|
models/dto/chat_dto.go
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package dto
|
| 2 |
+
|
| 3 |
+
import "github.com/google/uuid"
|
| 4 |
+
|
| 5 |
+
type SendMessageRequest struct {
|
| 6 |
+
Recipient string `json:"recipient" binding:"required" example:"628123456789"`
|
| 7 |
+
Message string `json:"message" binding:"required" example:"Hello world"`
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
type SendMessageResponse struct {
|
| 11 |
+
MessageID string `json:"message_id"`
|
| 12 |
+
Status string `json:"status"`
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
type ContactResponse struct {
|
| 16 |
+
JID string `json:"jid"`
|
| 17 |
+
Name string `json:"name"`
|
| 18 |
+
FullName string `json:"full_name"`
|
| 19 |
+
PushName string `json:"push_name"`
|
| 20 |
+
PhoneNumber string `json:"phone_number"`
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
type FetchContactsResponse struct {
|
| 24 |
+
AccountID uuid.UUID `json:"account_id"`
|
| 25 |
+
Contacts []ContactResponse `json:"contacts"`
|
| 26 |
+
}
|
models/error/error.go
CHANGED
|
@@ -42,4 +42,8 @@ var (
|
|
| 42 |
ERR_DB_CONNECTION_FAILED = errors.New("Failed to get database connection")
|
| 43 |
ERR_SQLSTORE_FAILED = errors.New("Failed to initialize SQL store")
|
| 44 |
ERR_DEVICE_STORE_FAILED = errors.New("Failed to retrieve device from store")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
)
|
|
|
|
| 42 |
ERR_DB_CONNECTION_FAILED = errors.New("Failed to get database connection")
|
| 43 |
ERR_SQLSTORE_FAILED = errors.New("Failed to initialize SQL store")
|
| 44 |
ERR_DEVICE_STORE_FAILED = errors.New("Failed to retrieve device from store")
|
| 45 |
+
|
| 46 |
+
// Chat Errors
|
| 47 |
+
ERR_CLIENT_NOT_CONNECTED = errors.New("WhatsApp client is not connected")
|
| 48 |
+
ERR_BAD_REQUEST = errors.New("Bad request")
|
| 49 |
)
|
provider/controller_provider.go
CHANGED
|
@@ -5,21 +5,25 @@ import "whatsapp-backend/controllers"
|
|
| 5 |
type ControllerProvider interface {
|
| 6 |
ProvideConnectionController() controllers.ConnectionController
|
| 7 |
ProvideAuthController() controllers.AuthController
|
|
|
|
| 8 |
}
|
| 9 |
|
| 10 |
type controllerProvider struct {
|
| 11 |
connectionController controllers.ConnectionController
|
| 12 |
authController controllers.AuthController
|
|
|
|
| 13 |
}
|
| 14 |
|
| 15 |
func NewControllerProvider(servicesProvider ServicesProvider) ControllerProvider {
|
| 16 |
|
| 17 |
connectionController := controllers.NewConnectionController(servicesProvider.ProvideConnectionService())
|
| 18 |
authController := controllers.NewAuthController(servicesProvider.ProvideAuthService())
|
|
|
|
| 19 |
|
| 20 |
return &controllerProvider{
|
| 21 |
connectionController: connectionController,
|
| 22 |
authController: authController,
|
|
|
|
| 23 |
}
|
| 24 |
}
|
| 25 |
|
|
@@ -30,3 +34,7 @@ func (c *controllerProvider) ProvideConnectionController() controllers.Connectio
|
|
| 30 |
func (c *controllerProvider) ProvideAuthController() controllers.AuthController {
|
| 31 |
return c.authController
|
| 32 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
type ControllerProvider interface {
|
| 6 |
ProvideConnectionController() controllers.ConnectionController
|
| 7 |
ProvideAuthController() controllers.AuthController
|
| 8 |
+
ProvideChatController() controllers.ChatController
|
| 9 |
}
|
| 10 |
|
| 11 |
type controllerProvider struct {
|
| 12 |
connectionController controllers.ConnectionController
|
| 13 |
authController controllers.AuthController
|
| 14 |
+
chatController controllers.ChatController
|
| 15 |
}
|
| 16 |
|
| 17 |
func NewControllerProvider(servicesProvider ServicesProvider) ControllerProvider {
|
| 18 |
|
| 19 |
connectionController := controllers.NewConnectionController(servicesProvider.ProvideConnectionService())
|
| 20 |
authController := controllers.NewAuthController(servicesProvider.ProvideAuthService())
|
| 21 |
+
chatController := controllers.NewChatController(servicesProvider.ProvideChatService())
|
| 22 |
|
| 23 |
return &controllerProvider{
|
| 24 |
connectionController: connectionController,
|
| 25 |
authController: authController,
|
| 26 |
+
chatController: chatController,
|
| 27 |
}
|
| 28 |
}
|
| 29 |
|
|
|
|
| 34 |
func (c *controllerProvider) ProvideAuthController() controllers.AuthController {
|
| 35 |
return c.authController
|
| 36 |
}
|
| 37 |
+
|
| 38 |
+
func (c *controllerProvider) ProvideChatController() controllers.ChatController {
|
| 39 |
+
return c.chatController
|
| 40 |
+
}
|
provider/repositories_provider.go
CHANGED
|
@@ -5,21 +5,25 @@ import "whatsapp-backend/repositories"
|
|
| 5 |
type RepositoriesProvider interface {
|
| 6 |
ProvideConnectionRepository() repositories.ConnectionRepository
|
| 7 |
ProvideAuthRepository() repositories.AuthRepository
|
|
|
|
| 8 |
}
|
| 9 |
|
| 10 |
type repositoriesProvider struct {
|
| 11 |
connectionRepository repositories.ConnectionRepository
|
| 12 |
authRepository repositories.AuthRepository
|
|
|
|
| 13 |
}
|
| 14 |
|
| 15 |
func NewRepositoriesProvider(cfg ConfigProvider) RepositoriesProvider {
|
| 16 |
db := cfg.ProvideDatabaseConfig().GetInstance()
|
| 17 |
connectionRepository, _ := repositories.NewConnectionRepository(db)
|
| 18 |
authRepository := repositories.NewAuthRepository(db)
|
|
|
|
| 19 |
|
| 20 |
return &repositoriesProvider{
|
| 21 |
connectionRepository: connectionRepository,
|
| 22 |
authRepository: authRepository,
|
|
|
|
| 23 |
}
|
| 24 |
}
|
| 25 |
|
|
@@ -30,3 +34,7 @@ func (rp *repositoriesProvider) ProvideConnectionRepository() repositories.Conne
|
|
| 30 |
func (rp *repositoriesProvider) ProvideAuthRepository() repositories.AuthRepository {
|
| 31 |
return rp.authRepository
|
| 32 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
type RepositoriesProvider interface {
|
| 6 |
ProvideConnectionRepository() repositories.ConnectionRepository
|
| 7 |
ProvideAuthRepository() repositories.AuthRepository
|
| 8 |
+
ProvideChatRepository() repositories.ChatRepository
|
| 9 |
}
|
| 10 |
|
| 11 |
type repositoriesProvider struct {
|
| 12 |
connectionRepository repositories.ConnectionRepository
|
| 13 |
authRepository repositories.AuthRepository
|
| 14 |
+
chatRepository repositories.ChatRepository
|
| 15 |
}
|
| 16 |
|
| 17 |
func NewRepositoriesProvider(cfg ConfigProvider) RepositoriesProvider {
|
| 18 |
db := cfg.ProvideDatabaseConfig().GetInstance()
|
| 19 |
connectionRepository, _ := repositories.NewConnectionRepository(db)
|
| 20 |
authRepository := repositories.NewAuthRepository(db)
|
| 21 |
+
chatRepository := repositories.NewChatRepository()
|
| 22 |
|
| 23 |
return &repositoriesProvider{
|
| 24 |
connectionRepository: connectionRepository,
|
| 25 |
authRepository: authRepository,
|
| 26 |
+
chatRepository: chatRepository,
|
| 27 |
}
|
| 28 |
}
|
| 29 |
|
|
|
|
| 34 |
func (rp *repositoriesProvider) ProvideAuthRepository() repositories.AuthRepository {
|
| 35 |
return rp.authRepository
|
| 36 |
}
|
| 37 |
+
|
| 38 |
+
func (rp *repositoriesProvider) ProvideChatRepository() repositories.ChatRepository {
|
| 39 |
+
return rp.chatRepository
|
| 40 |
+
}
|
provider/services_provider.go
CHANGED
|
@@ -5,20 +5,24 @@ import "whatsapp-backend/services"
|
|
| 5 |
type ServicesProvider interface {
|
| 6 |
ProvideConnectionService() services.ConnectionService
|
| 7 |
ProvideAuthService() services.AuthService
|
|
|
|
| 8 |
}
|
| 9 |
|
| 10 |
type servicesProvider struct {
|
| 11 |
connectionService services.ConnectionService
|
| 12 |
authService services.AuthService
|
|
|
|
| 13 |
}
|
| 14 |
|
| 15 |
func NewServicesProvider(repoProvider RepositoriesProvider, configProvider ConfigProvider) ServicesProvider {
|
| 16 |
connectionService := services.NewConnectionService(repoProvider.ProvideConnectionRepository())
|
| 17 |
authService := services.NewAuthService(repoProvider.ProvideAuthRepository(), repoProvider.ProvideConnectionRepository(), configProvider.ProvideJWTConfig())
|
|
|
|
| 18 |
|
| 19 |
return &servicesProvider{
|
| 20 |
connectionService: connectionService,
|
| 21 |
authService: authService,
|
|
|
|
| 22 |
}
|
| 23 |
}
|
| 24 |
|
|
@@ -29,3 +33,7 @@ func (s *servicesProvider) ProvideConnectionService() services.ConnectionService
|
|
| 29 |
func (s *servicesProvider) ProvideAuthService() services.AuthService {
|
| 30 |
return s.authService
|
| 31 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
type ServicesProvider interface {
|
| 6 |
ProvideConnectionService() services.ConnectionService
|
| 7 |
ProvideAuthService() services.AuthService
|
| 8 |
+
ProvideChatService() services.ChatService
|
| 9 |
}
|
| 10 |
|
| 11 |
type servicesProvider struct {
|
| 12 |
connectionService services.ConnectionService
|
| 13 |
authService services.AuthService
|
| 14 |
+
chatService services.ChatService
|
| 15 |
}
|
| 16 |
|
| 17 |
func NewServicesProvider(repoProvider RepositoriesProvider, configProvider ConfigProvider) ServicesProvider {
|
| 18 |
connectionService := services.NewConnectionService(repoProvider.ProvideConnectionRepository())
|
| 19 |
authService := services.NewAuthService(repoProvider.ProvideAuthRepository(), repoProvider.ProvideConnectionRepository(), configProvider.ProvideJWTConfig())
|
| 20 |
+
chatService := services.NewChatService(connectionService, repoProvider.ProvideChatRepository())
|
| 21 |
|
| 22 |
return &servicesProvider{
|
| 23 |
connectionService: connectionService,
|
| 24 |
authService: authService,
|
| 25 |
+
chatService: chatService,
|
| 26 |
}
|
| 27 |
}
|
| 28 |
|
|
|
|
| 33 |
func (s *servicesProvider) ProvideAuthService() services.AuthService {
|
| 34 |
return s.authService
|
| 35 |
}
|
| 36 |
+
|
| 37 |
+
func (s *servicesProvider) ProvideChatService() services.ChatService {
|
| 38 |
+
return s.chatService
|
| 39 |
+
}
|
repositories/chat_repository.go
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package repositories
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"context"
|
| 5 |
+
|
| 6 |
+
"go.mau.fi/whatsmeow"
|
| 7 |
+
waProto "go.mau.fi/whatsmeow/binary/proto"
|
| 8 |
+
"go.mau.fi/whatsmeow/types"
|
| 9 |
+
"google.golang.org/protobuf/proto"
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
type ChatRepository interface {
|
| 13 |
+
FetchContacts(ctx context.Context, client *whatsmeow.Client) (map[types.JID]types.ContactInfo, error)
|
| 14 |
+
SendMessage(ctx context.Context, client *whatsmeow.Client, recipient string, message string) (string, error)
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
type chatRepository struct{}
|
| 18 |
+
|
| 19 |
+
func NewChatRepository() ChatRepository {
|
| 20 |
+
return &chatRepository{}
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
func (r *chatRepository) FetchContacts(ctx context.Context, client *whatsmeow.Client) (map[types.JID]types.ContactInfo, error) {
|
| 24 |
+
contacts, err := client.Store.Contacts.GetAllContacts(ctx)
|
| 25 |
+
if err != nil {
|
| 26 |
+
return nil, err
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
return contacts, nil
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
func (r *chatRepository) SendMessage(ctx context.Context, client *whatsmeow.Client, recipient string, message string) (string, error) {
|
| 33 |
+
jid, err := types.ParseJID(recipient + "@s.whatsapp.net")
|
| 34 |
+
if err != nil {
|
| 35 |
+
return "", err
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
msg := &waProto.Message{
|
| 39 |
+
Conversation: proto.String(message),
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
resp, err := client.SendMessage(ctx, jid, msg)
|
| 43 |
+
if err != nil {
|
| 44 |
+
return "", err
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
return resp.ID, nil
|
| 48 |
+
}
|
router/auth_router.go
CHANGED
|
@@ -15,7 +15,7 @@ func AuthRouter(router *gin.Engine, controller provider.ControllerProvider, midd
|
|
| 15 |
routerGroup.POST("/register", authController.Register)
|
| 16 |
routerGroup.POST("/login", authController.Login)
|
| 17 |
routerGroup.POST("/logout", middleware.ProvideAuthMiddleware().RequireAuth(), middleware.ProvideAuthMiddleware().RequireCSRF(), authController.Logout)
|
| 18 |
-
routerGroup.POST("/refresh", authController.RefreshToken)
|
| 19 |
routerGroup.GET("/me", middleware.ProvideAuthMiddleware().RequireAuth(), authController.Me)
|
| 20 |
}
|
| 21 |
}
|
|
|
|
| 15 |
routerGroup.POST("/register", authController.Register)
|
| 16 |
routerGroup.POST("/login", authController.Login)
|
| 17 |
routerGroup.POST("/logout", middleware.ProvideAuthMiddleware().RequireAuth(), middleware.ProvideAuthMiddleware().RequireCSRF(), authController.Logout)
|
| 18 |
+
routerGroup.POST("/refresh", middleware.ProvideAuthMiddleware().RequireAuth(), middleware.ProvideAuthMiddleware().RequireCSRF(), authController.RefreshToken)
|
| 19 |
routerGroup.GET("/me", middleware.ProvideAuthMiddleware().RequireAuth(), authController.Me)
|
| 20 |
}
|
| 21 |
}
|
router/chat_router.go
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package router
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"whatsapp-backend/provider"
|
| 5 |
+
|
| 6 |
+
"github.com/gin-contrib/gzip"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func ChatRouter(router *gin.Engine, controller provider.ControllerProvider, middleware provider.MiddlewareProvider) {
|
| 11 |
+
chatController := controller.ProvideChatController()
|
| 12 |
+
authMiddleware := middleware.ProvideAuthMiddleware()
|
| 13 |
+
routerGroup := router.Group("/api/chat", authMiddleware.RequireAuth(), authMiddleware.RequireCSRF())
|
| 14 |
+
routerGroup.Use(gzip.Gzip(gzip.DefaultCompression))
|
| 15 |
+
{
|
| 16 |
+
routerGroup.GET("/fetch", chatController.FetchContacts)
|
| 17 |
+
routerGroup.POST("/send", chatController.SendMessage)
|
| 18 |
+
}
|
| 19 |
+
}
|
router/router.go
CHANGED
|
@@ -2,6 +2,11 @@ package router
|
|
| 2 |
|
| 3 |
import (
|
| 4 |
"whatsapp-backend/provider"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
)
|
| 6 |
|
| 7 |
func RunRouter(appProvider provider.AppProvider) {
|
|
@@ -9,6 +14,9 @@ func RunRouter(appProvider provider.AppProvider) {
|
|
| 9 |
|
| 10 |
ConnectionRouter(router, controller, middleware)
|
| 11 |
AuthRouter(router, controller, middleware)
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
err := router.Run(config.ProvideEnvConfig().GetTCPAddress())
|
| 14 |
if err != nil {
|
|
|
|
| 2 |
|
| 3 |
import (
|
| 4 |
"whatsapp-backend/provider"
|
| 5 |
+
|
| 6 |
+
_ "whatsapp-backend/docs"
|
| 7 |
+
|
| 8 |
+
swaggerFiles "github.com/swaggo/files"
|
| 9 |
+
ginSwagger "github.com/swaggo/gin-swagger"
|
| 10 |
)
|
| 11 |
|
| 12 |
func RunRouter(appProvider provider.AppProvider) {
|
|
|
|
| 14 |
|
| 15 |
ConnectionRouter(router, controller, middleware)
|
| 16 |
AuthRouter(router, controller, middleware)
|
| 17 |
+
ChatRouter(router, controller, middleware)
|
| 18 |
+
|
| 19 |
+
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
| 20 |
|
| 21 |
err := router.Run(config.ProvideEnvConfig().GetTCPAddress())
|
| 22 |
if err != nil {
|
services/chat_service.go
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package services
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"context"
|
| 5 |
+
"whatsapp-backend/models/dto"
|
| 6 |
+
http_error "whatsapp-backend/models/error"
|
| 7 |
+
"whatsapp-backend/repositories"
|
| 8 |
+
|
| 9 |
+
"github.com/google/uuid"
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
type ChatService interface {
|
| 13 |
+
FetchContacts(ctx context.Context, accountID uuid.UUID) ([]dto.ContactResponse, error)
|
| 14 |
+
SendMessage(ctx context.Context, accountID uuid.UUID, recipient string, message string) (string, error)
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
type chatService struct {
|
| 18 |
+
connectionService ConnectionService
|
| 19 |
+
chatRepository repositories.ChatRepository
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
func NewChatService(connectionService ConnectionService, chatRepository repositories.ChatRepository) ChatService {
|
| 23 |
+
return &chatService{
|
| 24 |
+
connectionService: connectionService,
|
| 25 |
+
chatRepository: chatRepository,
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
func (s *chatService) FetchContacts(ctx context.Context, accountID uuid.UUID) ([]dto.ContactResponse, error) {
|
| 30 |
+
client, err := s.connectionService.GetActiveClient(accountID)
|
| 31 |
+
if err != nil {
|
| 32 |
+
return nil, err
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
if !client.IsConnected() {
|
| 36 |
+
return nil, http_error.ERR_CLIENT_NOT_CONNECTED
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
contacts, err := s.chatRepository.FetchContacts(ctx, client)
|
| 40 |
+
if err != nil {
|
| 41 |
+
return nil, err
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
var response []dto.ContactResponse
|
| 45 |
+
for jid, contact := range contacts {
|
| 46 |
+
response = append(response, dto.ContactResponse{
|
| 47 |
+
JID: jid.String(),
|
| 48 |
+
Name: contact.FirstName,
|
| 49 |
+
FullName: contact.FullName,
|
| 50 |
+
PushName: contact.PushName,
|
| 51 |
+
PhoneNumber: jid.User,
|
| 52 |
+
})
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
return response, nil
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
func (s *chatService) SendMessage(ctx context.Context, accountID uuid.UUID, recipient string, message string) (string, error) {
|
| 59 |
+
client, err := s.connectionService.GetActiveClient(accountID)
|
| 60 |
+
if err != nil {
|
| 61 |
+
return "", err
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
if !client.IsConnected() {
|
| 65 |
+
return "", http_error.ERR_CLIENT_NOT_CONNECTED
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
msgID, err := s.chatRepository.SendMessage(ctx, client, recipient, message)
|
| 69 |
+
if err != nil {
|
| 70 |
+
return "", err
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
return msgID, nil
|
| 74 |
+
}
|