Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ ifeq ($(OS),Windows_NT)
endif

.PHONY: \
all fmt lint test coverage benchmark deps release clean help \
all fmt lint test coverage benchmark deps gen release clean help \
init init-dev ngrok air db-upgrade db-upgrade-raw run test-e2e build install \
docker-build docker docker-dev docker-clean

all: fmt lint coverage ## Run all tests and checks
all: gen fmt lint coverage ## Run all tests and checks

fmt: ## Format the code
golangci-lint fmt
Expand All @@ -33,6 +33,9 @@ benchmark: ## Run benchmarks
deps: ## Install dependencies
go mod download

gen: ## Generate code
go generate ./...
Comment thread
capcom6 marked this conversation as resolved.

release: ## Create release
DOCKER_REGISTRY=$(registry_name) RELEASE_ID=0 goreleaser release --snapshot --clean

Expand Down
22 changes: 21 additions & 1 deletion api/local.http
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,24 @@ Content-Type: application/json

###
DELETE {{localUrl}}/auth/token/{{jti}} HTTP/1.1
Authorization: Basic {{localCredentials}}
Authorization: Basic {{localCredentials}}

###
# @name getInbox
@inboxMessageId={{getInbox.response.body.$.0.id}}
GET {{localUrl}}/inbox HTTP/1.1
Authorization: Basic {{localCredentials}}

###
GET {{localUrl}}/inbox?type=SMS&limit=1&offset={{$randomInt 0 100}}&from=2026-01-01T00:00:00.000Z&to=2026-12-31T23:59:59Z HTTP/1.1
Authorization: Basic {{localCredentials}}

###
POST {{localUrl}}/inbox/refresh HTTP/1.1
Authorization: Basic {{localCredentials}}
Content-Type: application/json

{
"since": "2026-01-01T00:00:00.000Z",
"until": "2026-12-31T23:59:59Z"
}
Comment thread
capcom6 marked this conversation as resolved.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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.3
github.com/android-sms-gateway/client-go v1.12.4
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
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -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.3 h1:ToyjxJ1JxP9oKXsAMoBFT8qNFK8f0s3EYrOyASks27g=
github.com/android-sms-gateway/client-go v1.12.3/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/android-sms-gateway/client-go v1.12.4-0.20260411073238-b7c27fa612b2 h1:0UyeZIlv7VxQn6DHkwcWRmkvE34/Sj+9to0ZtizGTYY=
github.com/android-sms-gateway/client-go v1.12.4-0.20260411073238-b7c27fa612b2/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/android-sms-gateway/client-go v1.12.4 h1:umYoIEFQQHFOC4RvqTGorzScicYwzuyRP5Ep6sGwSHs=
github.com/android-sms-gateway/client-go v1.12.4/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=
Expand Down
2 changes: 2 additions & 0 deletions internal/sms-gateway/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
appconfig "github.com/android-sms-gateway/server/internal/config"
"github.com/android-sms-gateway/server/internal/sms-gateway/cache"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers"
"github.com/android-sms-gateway/server/internal/sms-gateway/inbox"
"github.com/android-sms-gateway/server/internal/sms-gateway/jwt"
"github.com/android-sms-gateway/server/internal/sms-gateway/modules/auth"
appdb "github.com/android-sms-gateway/server/internal/sms-gateway/modules/db"
Expand Down Expand Up @@ -63,6 +64,7 @@ func Module() fx.Option {
online.Module(),
jwt.Module(),
otp.Module(),
inbox.Module(),
)
}

Expand Down
5 changes: 5 additions & 0 deletions internal/sms-gateway/handlers/3rdparty.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package handlers
import (
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/base"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/devices"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/inbox"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/logs"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/messages"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/middlewares/jwtauth"
Expand All @@ -28,6 +29,7 @@ type thirdPartyHandler struct {
webhooksHandler *webhooks.ThirdPartyController
devicesHandler *devices.ThirdPartyController
settingsHandler *settings.ThirdPartyController
inboxHandler *inbox.ThirdPartyController
logsHandler *logs.ThirdPartyController
authHandler *thirdparty.AuthHandler
}
Expand All @@ -41,6 +43,7 @@ func newThirdPartyHandler(
webhooksHandler *webhooks.ThirdPartyController,
devicesHandler *devices.ThirdPartyController,
settingsHandler *settings.ThirdPartyController,
inboxHandler *inbox.ThirdPartyController,
logsHandler *logs.ThirdPartyController,
authHandler *thirdparty.AuthHandler,

Expand All @@ -61,6 +64,7 @@ func newThirdPartyHandler(
webhooksHandler: webhooksHandler,
devicesHandler: devicesHandler,
settingsHandler: settingsHandler,
inboxHandler: inboxHandler,
logsHandler: logsHandler,
authHandler: authHandler,
}
Expand All @@ -86,6 +90,7 @@ func (h *thirdPartyHandler) Register(router fiber.Router) {
h.devicesHandler.Register(router.Group("/devices"))

h.settingsHandler.Register(router.Group("/settings"))
h.inboxHandler.Register(router.Group("/inbox"))

h.webhooksHandler.Register(router.Group("/webhooks"))

Expand Down
84 changes: 84 additions & 0 deletions internal/sms-gateway/handlers/inbox/3rdparty.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package inbox

import (
"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"
"github.com/android-sms-gateway/server/internal/sms-gateway/inbox"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)

type ThirdPartyController struct {
base.Handler

inboxSvc *inbox.Service
}

func NewThirdPartyController(
inboxSvc *inbox.Service,
logger *zap.Logger,
validator *validator.Validate,
) *ThirdPartyController {
return &ThirdPartyController{
Handler: base.Handler{
Logger: logger,
Validator: validator,
},

inboxSvc: inboxSvc,
}
}

func (h *ThirdPartyController) Register(router fiber.Router) {
router.Get("", permissions.RequireScope(ScopeList), userauth.WithUserID(h.list))
router.Post("/refresh", permissions.RequireScope(ScopeRefresh), userauth.WithUserID(h.refresh))
}

// @Summary Get incoming messages
// @Description Retrieves incoming messages with filtering and pagination.
// @Security ApiAuth
// @Security JWTAuth
// @Tags User, Inbox
// @Produce json
// @Param type query string false "Filter incoming messages by type" Enums(SMS,DATA_SMS,MMS,MMS_DOWNLOADED)
// @Param limit query int false "Maximum number of messages to return" minimum(1) maximum(500) default(50)
// @Param offset query int false "Number of messages to skip" minimum(0) default(0)
// @Param from query string false "Start of date range (ISO 8601)" Format(date-time)
// @Param to query string false "End of date range (ISO 8601)" Format(date-time)
// @Param deviceId query string false "Device ID"
// @Success 200 {array} smsgateway.IncomingMessage "A list of incoming messages"
// @Header 200 {integer} X-Total-Count "Total number of items available"
// @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"
// @Router /3rdparty/v1/inbox [get]
//
// Get incoming messages.
func (h *ThirdPartyController) list(_ string, _ *fiber.Ctx) error {
return fiber.NewError(fiber.StatusNotImplemented, "Inbox API is not implemented yet")
}

// @Summary Request inbox messages refresh
// @Description Refreshes inbox messages. Webhooks will not be triggered.
// @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"
// @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")
}
6 changes: 6 additions & 0 deletions internal/sms-gateway/handlers/inbox/permissions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package inbox

const (
ScopeList = "inbox:list"
ScopeRefresh = "inbox:refresh"
)
21 changes: 8 additions & 13 deletions internal/sms-gateway/handlers/messages/3rdparty.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/converters"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/middlewares/permissions"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/middlewares/userauth"
"github.com/android-sms-gateway/server/internal/sms-gateway/inbox"
"github.com/android-sms-gateway/server/internal/sms-gateway/modules/devices"
"github.com/android-sms-gateway/server/internal/sms-gateway/modules/messages"
"github.com/capcom6/go-helpers/slices"
Expand All @@ -29,6 +30,7 @@ type thirdPartyControllerParams struct {

MessagesSvc *messages.Service
DevicesSvc *devices.Service
InboxSvc *inbox.Service

Validator *validator.Validate
Logger *zap.Logger
Expand All @@ -39,6 +41,7 @@ type ThirdPartyController struct {

messagesSvc *messages.Service
devicesSvc *devices.Service
inboxSvc *inbox.Service
}

func NewThirdPartyController(params thirdPartyControllerParams) *ThirdPartyController {
Expand All @@ -47,8 +50,10 @@ func NewThirdPartyController(params thirdPartyControllerParams) *ThirdPartyContr
Logger: params.Logger,
Validator: params.Validator,
},

messagesSvc: params.MessagesSvc,
devicesSvc: params.DevicesSvc,
inboxSvc: params.InboxSvc,
}
}

Expand Down Expand Up @@ -179,6 +184,7 @@ func (h *ThirdPartyController) post(userID string, c *fiber.Ctx) error {
// @Param offset query int false "Pagination offset" default(0)
// @Param includeContent query bool false "Include textMessage/dataMessage content for each message. Default is false" default(false)
// @Success 200 {object} smsgateway.GetMessagesResponse "A list of messages"
// @Header 200 {integer} X-Total-Count "Total number of items available"
// @Failure 400 {object} smsgateway.ErrorResponse "Invalid request"
// @Failure 401 {object} smsgateway.ErrorResponse "Unauthorized"
// @Failure 403 {object} smsgateway.ErrorResponse "Forbidden"
Expand Down Expand Up @@ -257,19 +263,8 @@ func (h *ThirdPartyController) postInboxExport(userID string, c *fiber.Ctx) erro
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}

device, err := h.devicesSvc.Get(userID, devices.WithID(req.DeviceID))
if err != nil {
if errors.Is(err, devices.ErrNotFound) {
return fiber.NewError(fiber.StatusBadRequest, "Invalid device ID")
}

h.Logger.Error("failed to get device", zap.Error(err), zap.String("user_id", userID))
return fiber.NewError(fiber.StatusInternalServerError, "failed to get device")
}

if expErr := h.messagesSvc.ExportInbox(device, req.Since, req.Until); expErr != nil {
h.Logger.Error("failed to export inbox", zap.Error(expErr), zap.String("user_id", userID))
return fiber.NewError(fiber.StatusInternalServerError, "failed to export inbox")
if err := h.inboxSvc.Refresh(userID, &req.DeviceID, req.Since, req.Until); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}

return c.SendStatus(fiber.StatusAccepted)
Expand Down
2 changes: 2 additions & 0 deletions internal/sms-gateway/handlers/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package handlers
import (
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/devices"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/events"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/inbox"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/logs"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/messages"
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/settings"
Expand Down Expand Up @@ -34,6 +35,7 @@ func Module() fx.Option {
devices.NewThirdPartyController,
settings.NewThirdPartyController,
settings.NewMobileController,
inbox.NewThirdPartyController,
logs.NewThirdPartyController,
events.NewMobileController,
fx.Private,
Expand Down
16 changes: 16 additions & 0 deletions internal/sms-gateway/inbox/module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package inbox

import (
"github.com/go-core-fx/logger"
"go.uber.org/fx"
)

func Module() fx.Option {
return fx.Module(
"inbox",
logger.WithNamedLogger("inbox"),
fx.Provide(
New,
),
)
}
33 changes: 33 additions & 0 deletions internal/sms-gateway/inbox/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package inbox

import (
"fmt"
"time"

"github.com/android-sms-gateway/server/internal/sms-gateway/modules/events"
"go.uber.org/zap"
)

type Service struct {
eventsSvc *events.Service

logger *zap.Logger
}

func New(eventsSvc *events.Service, logger *zap.Logger) *Service {
return &Service{
eventsSvc: eventsSvc,

logger: logger,
}
}

func (s *Service) Refresh(userID string, deviceID *string, since, until time.Time) error {
event := events.NewMessagesExportRequestedEvent(since, until)

if err := s.eventsSvc.Notify(userID, deviceID, event); err != nil {
return fmt.Errorf("failed to notify device: %w", err)
}

return nil
}
10 changes: 0 additions & 10 deletions internal/sms-gateway/modules/messages/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,16 +292,6 @@ func (s *Service) prepareMessage(
return msg, nil
}

func (s *Service) ExportInbox(device models.Device, since, until time.Time) error {
event := events.NewMessagesExportRequestedEvent(since, until)

if err := s.eventsSvc.Notify(device.UserID, &device.ID, event); err != nil {
return fmt.Errorf("failed to notify device: %w", err)
}

return nil
}

///////////////////////////////////////////////////////////////////////////////

func (s *Service) recipientsStateToModel(input []smsgateway.RecipientState, hash bool) []messageRecipientModel {
Expand Down
Loading
Loading