diff --git a/go.mod b/go.mod index a217452b..67c83495 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.25.0 require ( firebase.google.com/go/v4 v4.19.0 - github.com/android-sms-gateway/client-go v1.12.5 + github.com/android-sms-gateway/client-go v1.12.7-0.20260508050135-17a184bc31e9 github.com/ansrivas/fiberprometheus/v2 v2.6.1 github.com/capcom6/go-helpers v0.3.0 github.com/capcom6/go-infra-fx v0.5.2 diff --git a/go.sum b/go.sum index d3a1c6ed..f6021f74 100644 --- a/go.sum +++ b/go.sum @@ -50,8 +50,10 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/android-sms-gateway/client-go v1.12.5 h1:LcfTIvtRxOujPxmtFfCjHuFiX5wFyjN9yqGE+82jZdw= -github.com/android-sms-gateway/client-go v1.12.5/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4= +github.com/android-sms-gateway/client-go v1.12.6 h1:xqCYPZ1xePQNt6UMxC39Gjgr1WIOncGUjLJL848mkXw= +github.com/android-sms-gateway/client-go v1.12.6/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4= +github.com/android-sms-gateway/client-go v1.12.7-0.20260508050135-17a184bc31e9 h1:a/TCgspzLhBFPaJ/88pmie0AVu+M49qvGU5eqa9G7Lk= +github.com/android-sms-gateway/client-go v1.12.7-0.20260508050135-17a184bc31e9/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4= github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eTWro= github.com/andybalholm/brotli v1.2.1/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY= github.com/ansrivas/fiberprometheus/v2 v2.6.1 h1:wac3pXaE6BYYTF04AC6K0ktk6vCD+MnDOJZ3SK66kXM= diff --git a/internal/sms-gateway/handlers/inbox/3rdparty.go b/internal/sms-gateway/handlers/inbox/3rdparty.go index 8cf5a9c1..05e5dc15 100644 --- a/internal/sms-gateway/handlers/inbox/3rdparty.go +++ b/internal/sms-gateway/handlers/inbox/3rdparty.go @@ -1,6 +1,7 @@ package inbox import ( + "github.com/android-sms-gateway/client-go/smsgateway" "github.com/android-sms-gateway/server/internal/sms-gateway/handlers/base" "github.com/android-sms-gateway/server/internal/sms-gateway/handlers/middlewares/permissions" "github.com/android-sms-gateway/server/internal/sms-gateway/handlers/middlewares/userauth" @@ -63,22 +64,37 @@ func (h *ThirdPartyController) list(_ string, _ *fiber.Ctx) error { } // @Summary Request inbox messages refresh -// @Description Refreshes inbox messages. Webhooks will not be triggered. +// @Description Refreshes inbox messages. Webhooks are triggered when triggerWebhooks is true. // @Security ApiAuth // @Security JWTAuth // @Tags User, Inbox // @Accept json // @Produce json -// @Param request body smsgateway.MessagesExportRequest true "Export inbox request" -// @Success 202 {object} object "Inbox refresh request accepted" -// @Failure 400 {object} smsgateway.ErrorResponse "Invalid request" -// @Failure 401 {object} smsgateway.ErrorResponse "Unauthorized" -// @Failure 403 {object} smsgateway.ErrorResponse "Forbidden" -// @Failure 500 {object} smsgateway.ErrorResponse "Internal server error" -// @Failure 501 {object} smsgateway.ErrorResponse "Not implemented" +// @Param request body smsgateway.InboxRefreshRequest true "Refresh inbox request" +// @Success 202 "Inbox refresh request accepted" +// @Failure 400 {object} smsgateway.ErrorResponse "Invalid request" +// @Failure 401 {object} smsgateway.ErrorResponse "Unauthorized" +// @Failure 403 {object} smsgateway.ErrorResponse "Forbidden" +// @Failure 500 {object} smsgateway.ErrorResponse "Internal server error" // @Router /3rdparty/v1/inbox/refresh [post] // // Request inbox refresh. -func (h *ThirdPartyController) refresh(_ string, _ *fiber.Ctx) error { - return fiber.NewError(fiber.StatusNotImplemented, "Inbox API is not implemented yet") +func (h *ThirdPartyController) refresh(userID string, c *fiber.Ctx) error { + req := new(smsgateway.InboxRefreshRequest) + if err := h.BodyParserValidator(c, req); err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + + if err := h.inboxSvc.Refresh( + userID, + &req.DeviceID, + req.Since, + req.Until, + req.MessageTypes, + &req.TriggerWebhooks, + ); err != nil { + return fiber.NewError(fiber.StatusInternalServerError, err.Error()) + } + + return c.SendStatus(fiber.StatusAccepted) } diff --git a/internal/sms-gateway/handlers/messages/3rdparty.go b/internal/sms-gateway/handlers/messages/3rdparty.go index 5976677c..47890172 100644 --- a/internal/sms-gateway/handlers/messages/3rdparty.go +++ b/internal/sms-gateway/handlers/messages/3rdparty.go @@ -17,6 +17,7 @@ import ( "github.com/capcom6/go-helpers/slices" "github.com/go-playground/validator/v10" "github.com/gofiber/fiber/v2" + "github.com/samber/lo" "go.uber.org/fx" "go.uber.org/zap" ) @@ -244,32 +245,27 @@ func (h *ThirdPartyController) get(userID string, c *fiber.Ctx) error { return c.JSON(converters.MessageStateToDTO(*state)) } -// @Summary Request inbox messages export -// @Description Initiates process of inbox messages export via webhooks. For each message the `sms:received` webhook will be triggered. The webhooks will be triggered without specific order. -// @Security ApiAuth -// @Security JWTAuth -// @Tags User, Messages -// @Accept json -// @Produce json -// @Param request body smsgateway.MessagesExportRequest true "Export inbox request" -// @Success 202 {object} object "Inbox export request accepted" -// @Failure 400 {object} smsgateway.ErrorResponse "Invalid request" -// @Failure 401 {object} smsgateway.ErrorResponse "Unauthorized" -// @Failure 403 {object} smsgateway.ErrorResponse "Forbidden" -// @Failure 500 {object} smsgateway.ErrorResponse "Internal server error" -// @Router /3rdparty/v1/messages/inbox/export [post] -// // Export inbox. +// +// Deprecated: use /3rdparty/v1/inbox/refresh instead. func (h *ThirdPartyController) postInboxExport(userID string, c *fiber.Ctx) error { req := new(smsgateway.MessagesExportRequest) if err := h.BodyParserValidator(c, req); err != nil { return fiber.NewError(fiber.StatusBadRequest, err.Error()) } - if err := h.inboxSvc.Refresh(userID, &req.DeviceID, req.Since, req.Until); err != nil { - return fmt.Errorf("failed to refresh inbox: %w", err) + if err := h.inboxSvc.Refresh( + userID, + &req.DeviceID, + req.Since, + req.Until, + []smsgateway.IncomingMessageType{smsgateway.IncomingMessageTypeSMS}, + lo.ToPtr(true), + ); err != nil { + return fiber.NewError(fiber.StatusInternalServerError, err.Error()) } + c.Set("Deprecation", "true") return c.SendStatus(fiber.StatusAccepted) } diff --git a/internal/sms-gateway/inbox/service.go b/internal/sms-gateway/inbox/service.go index 6f0ba9c6..8cb8b144 100644 --- a/internal/sms-gateway/inbox/service.go +++ b/internal/sms-gateway/inbox/service.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/android-sms-gateway/client-go/smsgateway" "github.com/android-sms-gateway/server/internal/sms-gateway/modules/events" "go.uber.org/zap" ) @@ -22,8 +23,14 @@ func New(eventsSvc *events.Service, logger *zap.Logger) *Service { } } -func (s *Service) Refresh(userID string, deviceID *string, since, until time.Time) error { - event := events.NewMessagesExportRequestedEvent(since, until) +func (s *Service) Refresh( + userID string, + deviceID *string, + since, until time.Time, + types []smsgateway.IncomingMessageType, + triggerWebhooks *bool, +) error { + event := events.NewMessagesExportRequestedEvent(since, until, types, triggerWebhooks) if err := s.eventsSvc.Notify(userID, deviceID, event); err != nil { return fmt.Errorf("failed to notify device: %w", err) diff --git a/internal/sms-gateway/modules/events/events.go b/internal/sms-gateway/modules/events/events.go index e3d2b043..bd126417 100644 --- a/internal/sms-gateway/modules/events/events.go +++ b/internal/sms-gateway/modules/events/events.go @@ -1,6 +1,8 @@ package events import ( + "strconv" + "strings" "time" "github.com/android-sms-gateway/client-go/smsgateway" @@ -14,13 +16,34 @@ func NewWebhooksUpdatedEvent() Event { return NewEvent(smsgateway.PushWebhooksUpdated, nil) } -func NewMessagesExportRequestedEvent(since, until time.Time) Event { +func NewMessagesExportRequestedEvent( + since, until time.Time, + types []smsgateway.IncomingMessageType, + triggerWebhooks *bool, +) Event { + data := map[string]string{ + "since": since.Format(time.RFC3339), + "until": until.Format(time.RFC3339), + } + if len(types) > 0 { + str := strings.Builder{} + str.WriteString("[") + for i, t := range types { + if i > 0 { + str.WriteString(",") + } + str.WriteString(strconv.Quote(string(t))) + } + str.WriteString("]") + data["messageTypes"] = str.String() + } + if triggerWebhooks != nil { + data["triggerWebhooks"] = strconv.FormatBool(*triggerWebhooks) + } + return NewEvent( smsgateway.PushMessagesExportRequested, - map[string]string{ - "since": since.Format(time.RFC3339), - "until": until.Format(time.RFC3339), - }, + data, ) } diff --git a/internal/sms-gateway/openapi/docs.go b/internal/sms-gateway/openapi/docs.go index 0549f910..63e239ef 100644 --- a/internal/sms-gateway/openapi/docs.go +++ b/internal/sms-gateway/openapi/docs.go @@ -481,7 +481,7 @@ const docTemplate = `{ "JWTAuth": [] } ], - "description": "Refreshes inbox messages. Webhooks will not be triggered.", + "description": "Refreshes inbox messages. Webhooks are triggered when triggerWebhooks is true.", "consumes": [ "application/json" ], @@ -495,21 +495,18 @@ const docTemplate = `{ "summary": "Request inbox messages refresh", "parameters": [ { - "description": "Export inbox request", + "description": "Refresh inbox request", "name": "request", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/smsgateway.MessagesExportRequest" + "$ref": "#/definitions/smsgateway.InboxRefreshRequest" } } ], "responses": { "202": { - "description": "Inbox refresh request accepted", - "schema": { - "type": "object" - } + "description": "Inbox refresh request accepted" }, "400": { "description": "Invalid request", @@ -534,12 +531,6 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/smsgateway.ErrorResponse" } - }, - "501": { - "description": "Not implemented", - "schema": { - "$ref": "#/definitions/smsgateway.ErrorResponse" - } } } } @@ -824,73 +815,6 @@ const docTemplate = `{ } } }, - "/3rdparty/v1/messages/inbox/export": { - "post": { - "security": [ - { - "ApiAuth": [] - }, - { - "JWTAuth": [] - } - ], - "description": "Initiates process of inbox messages export via webhooks. For each message the ` + "`" + `sms:received` + "`" + ` webhook will be triggered. The webhooks will be triggered without specific order.", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "User", - "Messages" - ], - "summary": "Request inbox messages export", - "parameters": [ - { - "description": "Export inbox request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/smsgateway.MessagesExportRequest" - } - } - ], - "responses": { - "202": { - "description": "Inbox export request accepted", - "schema": { - "type": "object" - } - }, - "400": { - "description": "Invalid request", - "schema": { - "$ref": "#/definitions/smsgateway.ErrorResponse" - } - }, - "401": { - "description": "Unauthorized", - "schema": { - "$ref": "#/definitions/smsgateway.ErrorResponse" - } - }, - "403": { - "description": "Forbidden", - "schema": { - "$ref": "#/definitions/smsgateway.ErrorResponse" - } - }, - "500": { - "description": "Internal server error", - "schema": { - "$ref": "#/definitions/smsgateway.ErrorResponse" - } - } - } - } - }, "/3rdparty/v1/messages/{id}": { "get": { "security": [ @@ -1673,6 +1597,47 @@ const docTemplate = `{ "HealthStatusFail" ] }, + "smsgateway.InboxRefreshRequest": { + "type": "object", + "required": [ + "deviceId", + "since", + "until" + ], + "properties": { + "deviceId": { + "description": "ID of the device to refresh messages for\".", + "type": "string", + "maxLength": 21, + "example": "PyDmBQZZXYmyxMwED8Fzy" + }, + "messageTypes": { + "description": "List of message types to refresh. By default, SMS messages are refreshed.", + "type": "array", + "minItems": 1, + "items": { + "$ref": "#/definitions/smsgateway.IncomingMessageType" + } + }, + "since": { + "description": "Start of the time range to refresh.", + "type": "string", + "format": "date-time", + "example": "2024-01-01T00:00:00Z" + }, + "triggerWebhooks": { + "description": "Indicates whether to trigger webhooks for the refreshed messages.", + "type": "boolean", + "example": true + }, + "until": { + "description": "End of the time range to refresh.", + "type": "string", + "format": "date-time", + "example": "2024-01-01T23:59:59Z" + } + } + }, "smsgateway.IncomingMessage": { "type": "object", "required": [ @@ -2024,32 +1989,6 @@ const docTemplate = `{ } } }, - "smsgateway.MessagesExportRequest": { - "type": "object", - "required": [ - "deviceId", - "since", - "until" - ], - "properties": { - "deviceId": { - "description": "DeviceID is the ID of the device to export messages for.", - "type": "string", - "maxLength": 21, - "example": "PyDmBQZZXYmyxMwED8Fzy" - }, - "since": { - "description": "Since is the start of the time range to export.", - "type": "string", - "example": "2024-01-01T00:00:00Z" - }, - "until": { - "description": "Until is the end of the time range to export.", - "type": "string", - "example": "2024-01-01T23:59:59Z" - } - } - }, "smsgateway.MessagesProcessingOrder": { "type": "string", "enum": [