From 93608db83a01f297abc1627b3aacdd90ba2b18a2 Mon Sep 17 00:00:00 2001 From: moothz Date: Tue, 24 Mar 2026 21:43:40 -0300 Subject: [PATCH 1/3] feat: add get group info from invite link endpoint --- pkg/group/handler/group_handler.go | 42 ++++++++++++++++++++++++++++++ pkg/group/service/group_service.go | 28 ++++++++++++++++++++ pkg/routes/routes.go | 1 + 3 files changed, 71 insertions(+) diff --git a/pkg/group/handler/group_handler.go b/pkg/group/handler/group_handler.go index 4136266..a348ee4 100644 --- a/pkg/group/handler/group_handler.go +++ b/pkg/group/handler/group_handler.go @@ -12,6 +12,7 @@ type GroupHandler interface { ListGroups(ctx *gin.Context) GetGroupInfo(ctx *gin.Context) GetGroupInviteLink(ctx *gin.Context) + GetGroupInfoFromInviteLink(ctx *gin.Context) SetGroupPhoto(ctx *gin.Context) SetGroupName(ctx *gin.Context) SetGroupDescription(ctx *gin.Context) @@ -135,6 +136,47 @@ func (g *groupHandler) GetGroupInviteLink(ctx *gin.Context) { ctx.JSON(http.StatusOK, gin.H{"message": "success", "data": resp}) } +// Get group info from invite link +// @Summary Get group info from invite link +// @Description Get group info from invite link +// @Tags Group +// @Accept json +// @Produce json +// @Param message body group_service.GetGroupInfoFromInviteLinkStruct true "Group Invite Data" +// @Success 200 {object} gin.H "success" +// @Failure 400 {object} gin.H "Error on validation" +// @Failure 500 {object} gin.H "Internal server error" +// @Router /group/invite-info [post] +func (g *groupHandler) GetGroupInfoFromInviteLink(ctx *gin.Context) { + getInstance := ctx.MustGet("instance") + + instance, ok := getInstance.(*instance_model.Instance) + if !ok { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": "instance not found"}) + return + } + + var data *group_service.GetGroupInfoFromInviteLinkStruct + err := ctx.ShouldBindBodyWithJSON(&data) + if err != nil { + ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + if data.Code == "" { + ctx.JSON(http.StatusBadRequest, gin.H{"error": "code is required"}) + return + } + + resp, err := g.groupService.GetGroupInfoFromInviteLink(data, instance) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + ctx.JSON(http.StatusOK, gin.H{"message": "success", "data": resp}) +} + // Set group photo // @Summary Set group photo // @Description Set group photo diff --git a/pkg/group/service/group_service.go b/pkg/group/service/group_service.go index 227fef2..3ec1e45 100644 --- a/pkg/group/service/group_service.go +++ b/pkg/group/service/group_service.go @@ -23,6 +23,7 @@ type GroupService interface { ListGroups(instance *instance_model.Instance) ([]*types.GroupInfo, error) GetGroupInfo(data *GetGroupInfoStruct, instance *instance_model.Instance) (*types.GroupInfo, error) GetGroupInviteLink(data *GetGroupInviteLinkStruct, instance *instance_model.Instance) (string, error) + GetGroupInfoFromInviteLink(data *GetGroupInfoFromInviteLinkStruct, instance *instance_model.Instance) (*types.GroupInfo, error) SetGroupPhoto(data *SetGroupPhotoStruct, instance *instance_model.Instance) (string, error) SetGroupName(data *SetGroupNameStruct, instance *instance_model.Instance) error SetGroupDescription(data *SetGroupDescriptionStruct, instance *instance_model.Instance) error @@ -60,6 +61,10 @@ type GetGroupInviteLinkStruct struct { Reset bool `json:"reset"` } +type GetGroupInfoFromInviteLinkStruct struct { + Code string `json:"code"` +} + type SetGroupPhotoStruct struct { GroupJID string `json:"groupJid"` Image string `json:"image"` @@ -222,6 +227,29 @@ func (g *groupService) GetGroupInviteLink(data *GetGroupInviteLinkStruct, instan return resp, nil } +func (g *groupService) GetGroupInfoFromInviteLink(data *GetGroupInfoFromInviteLinkStruct, instance *instance_model.Instance) (*types.GroupInfo, error) { + client, err := g.ensureClientConnected(instance.Id) + if err != nil { + return nil, err + } + + code := data.Code + if strings.Contains(code, "chat.whatsapp.com/") { + parts := strings.Split(code, "chat.whatsapp.com/") + if len(parts) > 1 { + code = parts[1] + } + } + + resp, err := client.GetGroupInfoFromLink(context.Background(), code) + if err != nil { + g.loggerWrapper.GetLogger(instance.Id).LogError("[%s] error getting group info from link: %v", instance.Id, err) + return nil, err + } + + return resp, nil +} + func (g *groupService) SetGroupPhoto(data *SetGroupPhotoStruct, instance *instance_model.Instance) (string, error) { client, err := g.ensureClientConnected(instance.Id) if err != nil { diff --git a/pkg/routes/routes.go b/pkg/routes/routes.go index 0064014..e3daa8e 100644 --- a/pkg/routes/routes.go +++ b/pkg/routes/routes.go @@ -175,6 +175,7 @@ func (r *Routes) AssignRoutes(eng *gin.Engine) { routes.GET("/list", r.groupHandler.ListGroups) routes.POST("/info", r.jidValidationMiddleware.ValidateNumberField(), r.groupHandler.GetGroupInfo) routes.POST("/invitelink", r.jidValidationMiddleware.ValidateNumberField(), r.groupHandler.GetGroupInviteLink) + routes.POST("/invite-info", r.groupHandler.GetGroupInfoFromInviteLink) routes.POST("/photo", r.jidValidationMiddleware.ValidateNumberField(), r.groupHandler.SetGroupPhoto) routes.POST("/name", r.jidValidationMiddleware.ValidateNumberField(), r.groupHandler.SetGroupName) routes.POST("/description", r.jidValidationMiddleware.ValidateNumberField(), r.groupHandler.SetGroupDescription) From 14fb1fb6016456ca8c1dab9ca7fb7b83f46771c2 Mon Sep 17 00:00:00 2001 From: moothz Date: Tue, 24 Mar 2026 22:06:17 -0300 Subject: [PATCH 2/3] docs: add documentation for /group/invite-info --- docs/wiki/guias-api/api-groups.md | 51 ++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/docs/wiki/guias-api/api-groups.md b/docs/wiki/guias-api/api-groups.md index de41ed7..e8fa694 100644 --- a/docs/wiki/guias-api/api-groups.md +++ b/docs/wiki/guias-api/api-groups.md @@ -6,6 +6,7 @@ Documentação completa dos endpoints para gerenciar grupos WhatsApp. - [Listar Grupos](#listar-grupos) - [Informações do Grupo](#informações-do-grupo) +- [Informações via Link de Convite](#informações-via-link-de-convite) - [Link de Convite](#link-de-convite) - [Criar Grupo](#criar-grupo) - [Gerenciar Participantes](#gerenciar-participantes) @@ -141,11 +142,59 @@ curl -X POST http://localhost:4000/group/info \ "groupJid": "120363XXXXXXXXXX@g.us" }' ``` +}' --- -## Link de Convite +## Informações via Link de Convite + +Obtém informações de um grupo através de um link de convite sem precisar entrar nele. + +**Endpoint**: `POST /group/invite-info` + +**Body**: +```json +{ +"code": "https://chat.whatsapp.com/ABCDEFGHIJKLMNOP" +} +``` + +**Parâmetros**: + +| Campo | Tipo | Obrigatório | Descrição | +|-------|------|-------------|-----------| +| `code` | string | ✅ Sim | Código do link ou URL completa | +**Resposta de Sucesso (200)**: +```json +{ +"message": "success", +"data": { + "JID": "120363XXXXXXXXXX@g.us", + "OwnerJID": "5511999999999@s.whatsapp.net", + "GroupName": { + "Name": "Nome do Grupo", + "NameSetAt": "2025-01-15T10:30:00Z", + "NameSetBy": "5511999999999@s.whatsapp.net" + }, + "GroupCreated": "2025-01-15T10:00:00Z" +} +} +``` + +**Exemplo cURL**: +```bash +curl -X POST http://localhost:4000/group/invite-info \ +-H "Content-Type: application/json" \ +-H "apikey: SUA-CHAVE-API" \ +-d '{ + "code": "https://chat.whatsapp.com/ABCDEFGHIJKLMNOP" +}' +``` + +--- + +## Link de Convite Obtém ou regenera o link de convite do grupo. **Endpoint**: `POST /group/invitelink` From d9d68d2c37433eb992c043f5b4984247a6267c41 Mon Sep 17 00:00:00 2001 From: moothz Date: Sat, 4 Apr 2026 17:11:45 -0300 Subject: [PATCH 3/3] fix: address code review comments for group invite info - Fix nil pointer dereference in GetGroupInfoFromInviteLink handler. - Implement robust invite code extraction using net/url helper. - Update JoinGroupLink to use robust code extraction. - Remove stray characters in api-groups docs. --- docs/wiki/guias-api/api-groups.md | 2 -- pkg/group/handler/group_handler.go | 4 ++-- pkg/group/service/group_service.go | 26 ++++++++++++++++++-------- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/docs/wiki/guias-api/api-groups.md b/docs/wiki/guias-api/api-groups.md index e8fa694..7acaae8 100644 --- a/docs/wiki/guias-api/api-groups.md +++ b/docs/wiki/guias-api/api-groups.md @@ -142,8 +142,6 @@ curl -X POST http://localhost:4000/group/info \ "groupJid": "120363XXXXXXXXXX@g.us" }' ``` -}' - --- ## Informações via Link de Convite diff --git a/pkg/group/handler/group_handler.go b/pkg/group/handler/group_handler.go index a348ee4..ad4cef6 100644 --- a/pkg/group/handler/group_handler.go +++ b/pkg/group/handler/group_handler.go @@ -156,7 +156,7 @@ func (g *groupHandler) GetGroupInfoFromInviteLink(ctx *gin.Context) { return } - var data *group_service.GetGroupInfoFromInviteLinkStruct + var data group_service.GetGroupInfoFromInviteLinkStruct err := ctx.ShouldBindBodyWithJSON(&data) if err != nil { ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) @@ -168,7 +168,7 @@ func (g *groupHandler) GetGroupInfoFromInviteLink(ctx *gin.Context) { return } - resp, err := g.groupService.GetGroupInfoFromInviteLink(data, instance) + resp, err := g.groupService.GetGroupInfoFromInviteLink(&data, instance) if err != nil { ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return diff --git a/pkg/group/service/group_service.go b/pkg/group/service/group_service.go index 3ec1e45..5a2d03c 100644 --- a/pkg/group/service/group_service.go +++ b/pkg/group/service/group_service.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net/http" + "net/url" "strings" "time" @@ -227,19 +228,27 @@ func (g *groupService) GetGroupInviteLink(data *GetGroupInviteLinkStruct, instan return resp, nil } +func extractInviteCode(code string) string { + code = strings.TrimSpace(code) + if strings.Contains(code, "chat.whatsapp.com/") { + u, err := url.Parse(code) + if err == nil { + pathParts := strings.Split(strings.Trim(u.Path, "/"), "/") + if len(pathParts) > 0 { + return pathParts[len(pathParts)-1] + } + } + } + return code +} + func (g *groupService) GetGroupInfoFromInviteLink(data *GetGroupInfoFromInviteLinkStruct, instance *instance_model.Instance) (*types.GroupInfo, error) { client, err := g.ensureClientConnected(instance.Id) if err != nil { return nil, err } - code := data.Code - if strings.Contains(code, "chat.whatsapp.com/") { - parts := strings.Split(code, "chat.whatsapp.com/") - if len(parts) > 1 { - code = parts[1] - } - } + code := extractInviteCode(data.Code) resp, err := client.GetGroupInfoFromLink(context.Background(), code) if err != nil { @@ -471,7 +480,8 @@ func (g *groupService) JoinGroupLink(data *JoinGroupStruct, instance *instance_m return err } - _, err = client.JoinGroupWithLink(context.Background(), data.Code) + code := extractInviteCode(data.Code) + _, err = client.JoinGroupWithLink(context.Background(), code) if err != nil { g.loggerWrapper.GetLogger(instance.Id).LogError("[%s] error create group: %v", instance.Id, err) return err