Skip to content

Commit 70297a5

Browse files
committed
[feature] add inbox export endpoint
1 parent 35c3ad3 commit 70297a5

File tree

9 files changed

+242
-17
lines changed

9 files changed

+242
-17
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.22.0
44

55
require (
66
firebase.google.com/go/v4 v4.12.1
7-
github.com/android-sms-gateway/client-go v1.2.0
7+
github.com/android-sms-gateway/client-go v1.2.1-0.20241231042455-ce468dd89fdb
88
github.com/ansrivas/fiberprometheus/v2 v2.6.1
99
github.com/capcom6/go-helpers v0.0.0-20240521035631-865ee2879fa3
1010
github.com/capcom6/go-infra-fx v0.2.0

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV
2828
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
2929
github.com/android-sms-gateway/client-go v1.2.0 h1:P02e/Nm2XY6gpxVQVZiaxh1ZfInVkwfOLzz8Mp/1dy0=
3030
github.com/android-sms-gateway/client-go v1.2.0/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
31+
github.com/android-sms-gateway/client-go v1.2.1-0.20241231005427-53ab5bf34e4f h1:BfLaSqzXTRwAiXafZO/kA7kK8uPEXNB/32iHfSJlOSE=
32+
github.com/android-sms-gateway/client-go v1.2.1-0.20241231005427-53ab5bf34e4f/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
33+
github.com/android-sms-gateway/client-go v1.2.1-0.20241231042455-ce468dd89fdb h1:c3ll8h375G/oL4Qzexo35XBxHrw9HgGOqmxK6CPX5Bg=
34+
github.com/android-sms-gateway/client-go v1.2.1-0.20241231042455-ce468dd89fdb/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
3135
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
3236
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
3337
github.com/ansrivas/fiberprometheus/v2 v2.6.1 h1:wac3pXaE6BYYTF04AC6K0ktk6vCD+MnDOJZ3SK66kXM=

internal/sms-gateway/handlers/messages/3rdparty.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,47 @@ func (h *ThirdPartyController) get(user models.User, c *fiber.Ctx) error {
126126
return c.JSON(state)
127127
}
128128

129+
// @Summary Request inbox messages export
130+
// @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.
131+
// @Security ApiAuth
132+
// @Tags User, Messages
133+
// @Accept json
134+
// @Produce json
135+
// @Param request body smsgateway.MessagesExportRequest true "Export inbox request"
136+
// @Success 202 {object} object "Inbox export request accepted"
137+
// @Failure 400 {object} smsgateway.ErrorResponse "Invalid request"
138+
// @Failure 401 {object} smsgateway.ErrorResponse "Unauthorized"
139+
// @Failure 500 {object} smsgateway.ErrorResponse "Internal server error"
140+
// @Router /3rdparty/v1/inbox/export [post]
141+
//
142+
// Export inbox
143+
func (h *ThirdPartyController) postInboxExport(user models.User, c *fiber.Ctx) error {
144+
req := smsgateway.MessagesExportRequest{}
145+
if err := h.BodyParserValidator(c, &req); err != nil {
146+
return fiber.NewError(fiber.StatusBadRequest, err.Error())
147+
}
148+
149+
device, err := h.devicesSvc.Get(devices.WithUserID(user.ID), devices.WithID(req.DeviceID))
150+
if err != nil {
151+
if errors.Is(err, devices.ErrNotFound) {
152+
return fiber.NewError(fiber.StatusBadRequest, "Invalid device ID")
153+
}
154+
155+
return err
156+
}
157+
158+
if err := h.messagesSvc.ExportInbox(device, req.Since, req.Until); err != nil {
159+
return err
160+
}
161+
162+
return c.SendStatus(fiber.StatusAccepted)
163+
}
164+
129165
func (h *ThirdPartyController) Register(router fiber.Router) {
130166
router.Post("", auth.WithUser(h.post))
131167
router.Get(":id", auth.WithUser(h.get))
168+
169+
router.Post("inbox/export", auth.WithUser(h.postInboxExport))
132170
}
133171

134172
func NewThirdPartyController(params thirdPartyControllerParams) *ThirdPartyController {

internal/sms-gateway/modules/messages/service.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package messages
33
import (
44
"context"
55
"crypto/sha256"
6+
"errors"
67
"fmt"
78
"sync"
89
"time"
@@ -244,6 +245,16 @@ func (s *Service) Enqeue(device models.Device, message smsgateway.Message, opts
244245
return state, nil
245246
}
246247

248+
func (s *Service) ExportInbox(device models.Device, since, until time.Time) error {
249+
if device.PushToken == nil {
250+
return errors.New("no push token")
251+
}
252+
253+
event := push.NewMessagesExportRequestedEvent(since, until)
254+
255+
return s.pushSvc.Enqueue(*device.PushToken, event)
256+
}
257+
247258
func (s *Service) Clean(ctx context.Context) error {
248259
//TODO: use delete queue to optimize deletion
249260
n, err := s.messages.removeProcessed(ctx, time.Now().Add(-s.config.ProcessedLifetime))

internal/sms-gateway/modules/push/service.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"time"
77

8+
"github.com/android-sms-gateway/server/internal/sms-gateway/modules/push/domain"
89
"github.com/android-sms-gateway/server/pkg/types/cache"
910
"github.com/prometheus/client_golang/prometheus"
1011
"github.com/prometheus/client_golang/prometheus/promauto"
@@ -36,7 +37,7 @@ type Service struct {
3637

3738
client client
3839

39-
cache *cache.Cache[Event]
40+
cache *cache.Cache[domain.Event]
4041

4142
enqueuedCounter *prometheus.CounterVec
4243

@@ -61,7 +62,7 @@ func New(params Params) *Service {
6162
return &Service{
6263
config: params.Config,
6364
client: params.Client,
64-
cache: cache.New[Event](cache.Config{}),
65+
cache: cache.New[domain.Event](cache.Config{}),
6566
enqueuedCounter: enqueuedCounter,
6667
logger: params.Logger,
6768
}
@@ -83,7 +84,7 @@ func (s *Service) Run(ctx context.Context) {
8384
}
8485

8586
// Enqueue adds the data to the cache and immediately sends all messages if the debounce is 0.
86-
func (s *Service) Enqueue(token string, event *Event) error {
87+
func (s *Service) Enqueue(token string, event *domain.Event) error {
8788
if err := s.cache.Set(token, *event); err != nil {
8889
return fmt.Errorf("can't add message to cache: %w", err)
8990
}

internal/sms-gateway/modules/push/types.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package push
22

33
import (
44
"context"
5+
"time"
56

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

1819
type client interface {
1920
Open(ctx context.Context) error
20-
Send(ctx context.Context, messages map[string]Event) error
21+
Send(ctx context.Context, messages map[string]domain.Event) error
2122
Close(ctx context.Context) error
2223
}
2324

24-
func NewMessageEnqueuedEvent() *Event {
25+
func NewMessageEnqueuedEvent() *domain.Event {
2526
return domain.NewEvent(smsgateway.PushMessageEnqueued, nil)
2627
}
2728

28-
func NewWebhooksUpdatedEvent() *Event {
29+
func NewWebhooksUpdatedEvent() *domain.Event {
2930
return domain.NewEvent(smsgateway.PushWebhooksUpdated, nil)
3031
}
32+
33+
func NewMessagesExportRequestedEvent(since, until time.Time) *domain.Event {
34+
return domain.NewEvent(
35+
smsgateway.PushMessagesExportRequested,
36+
map[string]string{
37+
"since": since.Format(time.RFC3339),
38+
"until": until.Format(time.RFC3339),
39+
},
40+
)
41+
}

pkg/swagger/docs/requests.http

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ GET {{baseUrl}}/health HTTP/1.1
1010
GET {{baseUrl}}/api/3rdparty/v1/health HTTP/1.1
1111

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

@@ -25,7 +25,7 @@ Authorization: Basic {{credentials}}
2525
}
2626

2727
###
28-
POST {{baseUrl}}/api/3rdparty/v1/message HTTP/1.1
28+
POST {{baseUrl}}/api/3rdparty/v1/messages HTTP/1.1
2929
Content-Type: application/json
3030
Authorization: Basic {{credentials}}
3131

@@ -41,9 +41,20 @@ Authorization: Basic {{credentials}}
4141
}
4242

4343
###
44-
GET {{baseUrl}}/api/3rdparty/v1/message/K56aIsVsQ2rECdv_ajzTd HTTP/1.1
44+
GET {{baseUrl}}/api/3rdparty/v1/messages/K56aIsVsQ2rECdv_ajzTd HTTP/1.1
4545
Authorization: Basic {{credentials}}
4646

47+
###
48+
POST {{baseUrl}}/api/3rdparty/v1/messages/inbox/export HTTP/1.1
49+
Authorization: Basic {{credentials}}
50+
Content-Type: application/json
51+
52+
{
53+
"since": "2024-12-01T00:00:00.000Z",
54+
"until": "2024-12-31T23:59:59.999Z",
55+
"deviceId": "MxKw03Q2ZVoomrLeDLlMO"
56+
}
57+
4758
###
4859
GET {{baseUrl}}/api/3rdparty/v1/devices HTTP/1.1
4960
Authorization: Basic {{credentials}}

pkg/swagger/docs/swagger.json

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,64 @@
8686
}
8787
}
8888
},
89+
"/3rdparty/v1/inbox/export": {
90+
"post": {
91+
"security": [
92+
{
93+
"ApiAuth": []
94+
}
95+
],
96+
"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.",
97+
"consumes": [
98+
"application/json"
99+
],
100+
"produces": [
101+
"application/json"
102+
],
103+
"tags": [
104+
"User",
105+
"Messages"
106+
],
107+
"summary": "Request inbox messages export",
108+
"parameters": [
109+
{
110+
"description": "Export inbox request",
111+
"name": "request",
112+
"in": "body",
113+
"required": true,
114+
"schema": {
115+
"$ref": "#/definitions/smsgateway.MessagesExportRequest"
116+
}
117+
}
118+
],
119+
"responses": {
120+
"202": {
121+
"description": "Inbox export request accepted",
122+
"schema": {
123+
"type": "object"
124+
}
125+
},
126+
"400": {
127+
"description": "Invalid request",
128+
"schema": {
129+
"$ref": "#/definitions/smsgateway.ErrorResponse"
130+
}
131+
},
132+
"401": {
133+
"description": "Unauthorized",
134+
"schema": {
135+
"$ref": "#/definitions/smsgateway.ErrorResponse"
136+
}
137+
},
138+
"500": {
139+
"description": "Internal server error",
140+
"schema": {
141+
"$ref": "#/definitions/smsgateway.ErrorResponse"
142+
}
143+
}
144+
}
145+
}
146+
},
89147
"/3rdparty/v1/logs": {
90148
"get": {
91149
"security": [
@@ -149,7 +207,7 @@
149207
}
150208
}
151209
},
152-
"/3rdparty/v1/message": {
210+
"/3rdparty/v1/messages": {
153211
"post": {
154212
"security": [
155213
{
@@ -225,7 +283,7 @@
225283
}
226284
}
227285
},
228-
"/3rdparty/v1/message/{id}": {
286+
"/3rdparty/v1/messages/{id}": {
229287
"get": {
230288
"security": [
231289
{
@@ -1075,6 +1133,32 @@
10751133
}
10761134
}
10771135
},
1136+
"smsgateway.MessagesExportRequest": {
1137+
"type": "object",
1138+
"required": [
1139+
"deviceId",
1140+
"since",
1141+
"until"
1142+
],
1143+
"properties": {
1144+
"deviceId": {
1145+
"description": "DeviceID is the ID of the device to export messages for.",
1146+
"type": "string",
1147+
"maxLength": 21,
1148+
"example": "PyDmBQZZXYmyxMwED8Fzy"
1149+
},
1150+
"since": {
1151+
"description": "Since is the start of the time range to export.",
1152+
"type": "string",
1153+
"example": "2024-01-01T00:00:00Z"
1154+
},
1155+
"until": {
1156+
"description": "Until is the end of the time range to export.",
1157+
"type": "string",
1158+
"example": "2024-01-01T23:59:59Z"
1159+
}
1160+
}
1161+
},
10781162
"smsgateway.MobileChangePasswordRequest": {
10791163
"type": "object",
10801164
"required": [
@@ -1198,11 +1282,13 @@
11981282
"type": "string",
11991283
"enum": [
12001284
"MessageEnqueued",
1201-
"WebhooksUpdated"
1285+
"WebhooksUpdated",
1286+
"MessagesExportRequested"
12021287
],
12031288
"x-enum-varnames": [
12041289
"PushMessageEnqueued",
1205-
"PushWebhooksUpdated"
1290+
"PushWebhooksUpdated",
1291+
"PushMessagesExportRequested"
12061292
]
12071293
},
12081294
"smsgateway.PushNotification": {
@@ -1223,7 +1309,8 @@
12231309
"default": "MessageEnqueued",
12241310
"enum": [
12251311
"MessageEnqueued",
1226-
"WebhooksUpdated"
1312+
"WebhooksUpdated",
1313+
"MessagesExportRequested"
12271314
],
12281315
"allOf": [
12291316
{

0 commit comments

Comments
 (0)