Skip to content

Commit

Permalink
[feature] add inbox export endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
capcom6 committed Jan 2, 2025
1 parent 35c3ad3 commit 70297a5
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 17 deletions.
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.22.0

require (
firebase.google.com/go/v4 v4.12.1
github.com/android-sms-gateway/client-go v1.2.0
github.com/android-sms-gateway/client-go v1.2.1-0.20241231042455-ce468dd89fdb
github.com/ansrivas/fiberprometheus/v2 v2.6.1
github.com/capcom6/go-helpers v0.0.0-20240521035631-865ee2879fa3
github.com/capcom6/go-infra-fx v0.2.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/android-sms-gateway/client-go v1.2.0 h1:P02e/Nm2XY6gpxVQVZiaxh1ZfInVkwfOLzz8Mp/1dy0=
github.com/android-sms-gateway/client-go v1.2.0/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/android-sms-gateway/client-go v1.2.1-0.20241231005427-53ab5bf34e4f h1:BfLaSqzXTRwAiXafZO/kA7kK8uPEXNB/32iHfSJlOSE=
github.com/android-sms-gateway/client-go v1.2.1-0.20241231005427-53ab5bf34e4f/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/android-sms-gateway/client-go v1.2.1-0.20241231042455-ce468dd89fdb h1:c3ll8h375G/oL4Qzexo35XBxHrw9HgGOqmxK6CPX5Bg=
github.com/android-sms-gateway/client-go v1.2.1-0.20241231042455-ce468dd89fdb/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/ansrivas/fiberprometheus/v2 v2.6.1 h1:wac3pXaE6BYYTF04AC6K0ktk6vCD+MnDOJZ3SK66kXM=
Expand Down
38 changes: 38 additions & 0 deletions internal/sms-gateway/handlers/messages/3rdparty.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,47 @@ func (h *ThirdPartyController) get(user models.User, c *fiber.Ctx) error {
return c.JSON(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
// @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 500 {object} smsgateway.ErrorResponse "Internal server error"
// @Router /3rdparty/v1/inbox/export [post]
//
// Export inbox
func (h *ThirdPartyController) postInboxExport(user models.User, c *fiber.Ctx) error {
req := smsgateway.MessagesExportRequest{}
if err := h.BodyParserValidator(c, &req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}

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

return err
}

if err := h.messagesSvc.ExportInbox(device, req.Since, req.Until); err != nil {
return err
}

return c.SendStatus(fiber.StatusAccepted)
}

func (h *ThirdPartyController) Register(router fiber.Router) {
router.Post("", auth.WithUser(h.post))
router.Get(":id", auth.WithUser(h.get))

router.Post("inbox/export", auth.WithUser(h.postInboxExport))
}

func NewThirdPartyController(params thirdPartyControllerParams) *ThirdPartyController {
Expand Down
11 changes: 11 additions & 0 deletions internal/sms-gateway/modules/messages/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package messages
import (
"context"
"crypto/sha256"
"errors"
"fmt"
"sync"
"time"
Expand Down Expand Up @@ -244,6 +245,16 @@ func (s *Service) Enqeue(device models.Device, message smsgateway.Message, opts
return state, nil
}

func (s *Service) ExportInbox(device models.Device, since, until time.Time) error {
if device.PushToken == nil {
return errors.New("no push token")
}

event := push.NewMessagesExportRequestedEvent(since, until)

return s.pushSvc.Enqueue(*device.PushToken, event)
}

func (s *Service) Clean(ctx context.Context) error {
//TODO: use delete queue to optimize deletion
n, err := s.messages.removeProcessed(ctx, time.Now().Add(-s.config.ProcessedLifetime))
Expand Down
7 changes: 4 additions & 3 deletions internal/sms-gateway/modules/push/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"time"

"github.com/android-sms-gateway/server/internal/sms-gateway/modules/push/domain"
"github.com/android-sms-gateway/server/pkg/types/cache"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
Expand Down Expand Up @@ -36,7 +37,7 @@ type Service struct {

client client

cache *cache.Cache[Event]
cache *cache.Cache[domain.Event]

enqueuedCounter *prometheus.CounterVec

Expand All @@ -61,7 +62,7 @@ func New(params Params) *Service {
return &Service{
config: params.Config,
client: params.Client,
cache: cache.New[Event](cache.Config{}),
cache: cache.New[domain.Event](cache.Config{}),
enqueuedCounter: enqueuedCounter,
logger: params.Logger,
}
Expand All @@ -83,7 +84,7 @@ func (s *Service) Run(ctx context.Context) {
}

// Enqueue adds the data to the cache and immediately sends all messages if the debounce is 0.
func (s *Service) Enqueue(token string, event *Event) error {
func (s *Service) Enqueue(token string, event *domain.Event) error {
if err := s.cache.Set(token, *event); err != nil {
return fmt.Errorf("can't add message to cache: %w", err)
}
Expand Down
17 changes: 14 additions & 3 deletions internal/sms-gateway/modules/push/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package push

import (
"context"
"time"

"github.com/android-sms-gateway/client-go/smsgateway"
"github.com/android-sms-gateway/server/internal/sms-gateway/modules/push/domain"
Expand All @@ -17,14 +18,24 @@ const (

type client interface {
Open(ctx context.Context) error
Send(ctx context.Context, messages map[string]Event) error
Send(ctx context.Context, messages map[string]domain.Event) error
Close(ctx context.Context) error
}

func NewMessageEnqueuedEvent() *Event {
func NewMessageEnqueuedEvent() *domain.Event {
return domain.NewEvent(smsgateway.PushMessageEnqueued, nil)
}

func NewWebhooksUpdatedEvent() *Event {
func NewWebhooksUpdatedEvent() *domain.Event {
return domain.NewEvent(smsgateway.PushWebhooksUpdated, nil)
}

func NewMessagesExportRequestedEvent(since, until time.Time) *domain.Event {
return domain.NewEvent(
smsgateway.PushMessagesExportRequested,
map[string]string{
"since": since.Format(time.RFC3339),
"until": until.Format(time.RFC3339),
},
)
}
17 changes: 14 additions & 3 deletions pkg/swagger/docs/requests.http
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ GET {{baseUrl}}/health HTTP/1.1
GET {{baseUrl}}/api/3rdparty/v1/health HTTP/1.1

###
POST {{baseUrl}}/api/3rdparty/v1/message?skipPhoneValidation=false HTTP/1.1
POST {{baseUrl}}/api/3rdparty/v1/messages?skipPhoneValidation=false HTTP/1.1
Content-Type: application/json
Authorization: Basic {{credentials}}

Expand All @@ -25,7 +25,7 @@ Authorization: Basic {{credentials}}
}

###
POST {{baseUrl}}/api/3rdparty/v1/message HTTP/1.1
POST {{baseUrl}}/api/3rdparty/v1/messages HTTP/1.1
Content-Type: application/json
Authorization: Basic {{credentials}}

Expand All @@ -41,9 +41,20 @@ Authorization: Basic {{credentials}}
}

###
GET {{baseUrl}}/api/3rdparty/v1/message/K56aIsVsQ2rECdv_ajzTd HTTP/1.1
GET {{baseUrl}}/api/3rdparty/v1/messages/K56aIsVsQ2rECdv_ajzTd HTTP/1.1
Authorization: Basic {{credentials}}

###
POST {{baseUrl}}/api/3rdparty/v1/messages/inbox/export HTTP/1.1
Authorization: Basic {{credentials}}
Content-Type: application/json

{
"since": "2024-12-01T00:00:00.000Z",
"until": "2024-12-31T23:59:59.999Z",
"deviceId": "MxKw03Q2ZVoomrLeDLlMO"
}

###
GET {{baseUrl}}/api/3rdparty/v1/devices HTTP/1.1
Authorization: Basic {{credentials}}
Expand Down
97 changes: 92 additions & 5 deletions pkg/swagger/docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,64 @@
}
}
},
"/3rdparty/v1/inbox/export": {
"post": {
"security": [
{
"ApiAuth": []
}
],
"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"
}
},
"500": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/smsgateway.ErrorResponse"
}
}
}
}
},
"/3rdparty/v1/logs": {
"get": {
"security": [
Expand Down Expand Up @@ -149,7 +207,7 @@
}
}
},
"/3rdparty/v1/message": {
"/3rdparty/v1/messages": {
"post": {
"security": [
{
Expand Down Expand Up @@ -225,7 +283,7 @@
}
}
},
"/3rdparty/v1/message/{id}": {
"/3rdparty/v1/messages/{id}": {
"get": {
"security": [
{
Expand Down Expand Up @@ -1075,6 +1133,32 @@
}
}
},
"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.MobileChangePasswordRequest": {
"type": "object",
"required": [
Expand Down Expand Up @@ -1198,11 +1282,13 @@
"type": "string",
"enum": [
"MessageEnqueued",
"WebhooksUpdated"
"WebhooksUpdated",
"MessagesExportRequested"
],
"x-enum-varnames": [
"PushMessageEnqueued",
"PushWebhooksUpdated"
"PushWebhooksUpdated",
"PushMessagesExportRequested"
]
},
"smsgateway.PushNotification": {
Expand All @@ -1223,7 +1309,8 @@
"default": "MessageEnqueued",
"enum": [
"MessageEnqueued",
"WebhooksUpdated"
"WebhooksUpdated",
"MessagesExportRequested"
],
"allOf": [
{
Expand Down
Loading

0 comments on commit 70297a5

Please sign in to comment.