mirror of
https://github.com/makayabou/asg-server.git
synced 2026-05-02 17:43:36 +02:00
[messages] add get sent messages endpoint
This commit is contained in:
parent
f496d676a7
commit
367729489c
2
go.mod
2
go.mod
@ -6,7 +6,7 @@ toolchain go1.23.2
|
||||
|
||||
require (
|
||||
firebase.google.com/go/v4 v4.12.1
|
||||
github.com/android-sms-gateway/client-go v1.9.1
|
||||
github.com/android-sms-gateway/client-go v1.9.2
|
||||
github.com/ansrivas/fiberprometheus/v2 v2.6.1
|
||||
github.com/capcom6/go-helpers v0.3.0
|
||||
github.com/capcom6/go-infra-fx v0.2.3
|
||||
|
||||
6
go.sum
6
go.sum
@ -28,6 +28,12 @@ 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.9.1 h1:i9hKf+kgaJo9ykWKoeno3MliOThoIlwO0N2eed6bY+Q=
|
||||
github.com/android-sms-gateway/client-go v1.9.1/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
|
||||
github.com/android-sms-gateway/client-go v1.9.2-0.20250805133721-9ebe535d038a h1:ibYxk2m1Qcwydi/GDHpDnUCcLORqLpYGxm6XModDFnM=
|
||||
github.com/android-sms-gateway/client-go v1.9.2-0.20250805133721-9ebe535d038a/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
|
||||
github.com/android-sms-gateway/client-go v1.9.2-0.20250805235002-a840b364bc1d h1:gurnY2hszJ1Yn8vt81Qn9yF/8zcmJK4YzhZAgsYUt/4=
|
||||
github.com/android-sms-gateway/client-go v1.9.2-0.20250805235002-a840b364bc1d/go.mod h1:DQsReciU1xcaVW3T5Z2bqslNdsAwCFCtghawmA6g6L4=
|
||||
github.com/android-sms-gateway/client-go v1.9.2 h1:e9HFgvR+LRMV0dOJvFkxt998UxOMWNf8hfnXwMIc39I=
|
||||
github.com/android-sms-gateway/client-go v1.9.2/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=
|
||||
|
||||
@ -5,7 +5,7 @@ import (
|
||||
"github.com/android-sms-gateway/server/internal/sms-gateway/modules/messages"
|
||||
)
|
||||
|
||||
func MessageToDTO(m messages.MessageOut) smsgateway.MobileMessage {
|
||||
func MessageToMobileDTO(m messages.MessageOut) smsgateway.MobileMessage {
|
||||
var message string
|
||||
var textMessage *smsgateway.TextMessage
|
||||
var dataMessage *smsgateway.DataMessage
|
||||
@ -41,3 +41,15 @@ func MessageToDTO(m messages.MessageOut) smsgateway.MobileMessage {
|
||||
CreatedAt: m.CreatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func MessageStateToDTO(state messages.MessageStateOut) smsgateway.MessageState {
|
||||
return smsgateway.MessageState{
|
||||
ID: state.ID,
|
||||
DeviceID: state.DeviceID,
|
||||
State: smsgateway.ProcessingState(state.State),
|
||||
IsHashed: state.IsHashed,
|
||||
IsEncrypted: state.IsEncrypted,
|
||||
Recipients: state.Recipients,
|
||||
States: state.States,
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ func TestMessageToDTO(t *testing.T) {
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Call the function under test
|
||||
result := converters.MessageToDTO(tc.input)
|
||||
result := converters.MessageToMobileDTO(tc.input)
|
||||
|
||||
// Assert the results
|
||||
assert.Equal(t, tc.expected, result)
|
||||
|
||||
@ -3,10 +3,12 @@ package messages
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"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/converters"
|
||||
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/middlewares/userauth"
|
||||
"github.com/android-sms-gateway/server/internal/sms-gateway/models"
|
||||
"github.com/android-sms-gateway/server/internal/sms-gateway/modules/devices"
|
||||
@ -169,6 +171,42 @@ func (h *ThirdPartyController) post(user models.User, c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
// @Summary Get messages
|
||||
// @Description Retrieves a list of messages with filtering and pagination
|
||||
// @Security ApiAuth
|
||||
// @Tags User, Messages
|
||||
// @Produce json
|
||||
// @Param from query string false "Start date in RFC3339 format" Format(date-time)
|
||||
// @Param to query string false "End date in RFC3339 format" Format(date-time)
|
||||
// @Param state query string false "Filter messages by processing state" Enum(Pending, Processed, Sent, Delivered, Failed)
|
||||
// @Param deviceId query string false "Filter by device ID" min(21) max(21)
|
||||
// @Param limit query int false "Pagination limit" default(50) min(1) max(100)
|
||||
// @Param offset query int false "Pagination offset" default(0)
|
||||
// @Success 200 {object} smsgateway.GetMessagesResponse "A list of messages"
|
||||
// @Failure 400 {object} smsgateway.ErrorResponse "Invalid request"
|
||||
// @Failure 401 {object} smsgateway.ErrorResponse "Unauthorized"
|
||||
// @Failure 500 {object} smsgateway.ErrorResponse "Internal server error"
|
||||
// @Router /3rdparty/v1/messages [get]
|
||||
//
|
||||
// Get message history
|
||||
func (h *ThirdPartyController) list(user models.User, c *fiber.Ctx) error {
|
||||
params := getQueryParams{}
|
||||
if err := h.QueryParserValidator(c, ¶ms); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
messages, total, err := h.messagesSvc.SelectStates(user, params.ToFilter(), params.ToOptions())
|
||||
if err != nil {
|
||||
h.Logger.Error("Failed to get message history", zap.Error(err), zap.String("user_id", user.ID))
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to retrieve message history")
|
||||
}
|
||||
|
||||
c.Set("X-Total-Count", strconv.Itoa(int(total)))
|
||||
return c.JSON(
|
||||
slices.Map(messages, converters.MessageStateToDTO),
|
||||
)
|
||||
}
|
||||
|
||||
// @Summary Get message state
|
||||
// @Description Returns message state by ID
|
||||
// @Security ApiAuth
|
||||
@ -194,15 +232,7 @@ func (h *ThirdPartyController) get(user models.User, c *fiber.Ctx) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.JSON(smsgateway.GetMessageResponse{
|
||||
ID: state.ID,
|
||||
DeviceID: state.DeviceID,
|
||||
State: smsgateway.ProcessingState(state.State),
|
||||
IsHashed: state.IsHashed,
|
||||
IsEncrypted: state.IsEncrypted,
|
||||
Recipients: state.Recipients,
|
||||
States: state.States,
|
||||
})
|
||||
return c.JSON(converters.MessageStateToDTO(state))
|
||||
}
|
||||
|
||||
// @Summary Request inbox messages export
|
||||
@ -242,8 +272,9 @@ func (h *ThirdPartyController) postInboxExport(user models.User, c *fiber.Ctx) e
|
||||
}
|
||||
|
||||
func (h *ThirdPartyController) Register(router fiber.Router) {
|
||||
router.Get("", userauth.WithUser(h.list))
|
||||
router.Post("", userauth.WithUser(h.post))
|
||||
router.Get(":id", userauth.WithUser(h.get))
|
||||
router.Get(":id", userauth.WithUser(h.get)).Name(route3rdPartyGetMessage)
|
||||
|
||||
router.Post("inbox/export", userauth.WithUser(h.postInboxExport))
|
||||
}
|
||||
|
||||
@ -1,6 +1,75 @@
|
||||
package messages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/android-sms-gateway/server/internal/sms-gateway/modules/messages"
|
||||
)
|
||||
|
||||
type postQueryParams struct {
|
||||
SkipPhoneValidation bool `query:"skipPhoneValidation"`
|
||||
DeviceActiveWithin uint `query:"deviceActiveWithin"`
|
||||
}
|
||||
|
||||
type getQueryParams struct {
|
||||
StartDate string `query:"from" validate:"omitempty,datetime=2006-01-02T15:04:05Z07:00"`
|
||||
EndDate string `query:"to" validate:"omitempty,datetime=2006-01-02T15:04:05Z07:00"`
|
||||
State string `query:"state" validate:"omitempty,oneof=Pending Processed Sent Delivered Failed"`
|
||||
DeviceID string `query:"deviceId" validate:"omitempty,len=21"`
|
||||
Limit int `query:"limit" validate:"omitempty,min=1,max=100"`
|
||||
Offset int `query:"offset" validate:"omitempty,min=0"`
|
||||
}
|
||||
|
||||
func (p *getQueryParams) Validate() error {
|
||||
if p.StartDate != "" && p.EndDate != "" && p.StartDate > p.EndDate {
|
||||
return fmt.Errorf("`from` date must be before `to` date")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *getQueryParams) ToFilter() messages.MessagesSelectFilter {
|
||||
filter := messages.MessagesSelectFilter{}
|
||||
|
||||
if p.StartDate != "" {
|
||||
if t, err := time.Parse(time.RFC3339, p.StartDate); err == nil {
|
||||
filter.StartDate = t
|
||||
}
|
||||
}
|
||||
|
||||
if p.EndDate != "" {
|
||||
if t, err := time.Parse(time.RFC3339, p.EndDate); err == nil {
|
||||
filter.EndDate = t
|
||||
}
|
||||
}
|
||||
|
||||
if p.State != "" {
|
||||
filter.State = messages.ProcessingState(p.State)
|
||||
}
|
||||
|
||||
if p.DeviceID != "" {
|
||||
filter.DeviceID = p.DeviceID
|
||||
}
|
||||
|
||||
return filter
|
||||
}
|
||||
|
||||
func (p *getQueryParams) ToOptions() messages.MessagesSelectOptions {
|
||||
options := messages.MessagesSelectOptions{
|
||||
WithRecipients: true,
|
||||
WithStates: true,
|
||||
}
|
||||
|
||||
if p.Limit > 0 {
|
||||
options.Limit = min(p.Limit, 100)
|
||||
} else {
|
||||
options.Limit = 50
|
||||
}
|
||||
|
||||
if p.Offset > 0 {
|
||||
options.Offset = p.Offset
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ func (h *mobileHandler) getMessage(device models.Device, c *fiber.Ctx) error {
|
||||
smsgateway.MobileGetMessagesResponse(
|
||||
slices.Map(
|
||||
msgs,
|
||||
converters.MessageToDTO,
|
||||
converters.MessageToMobileDTO,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-sql-driver/mysql"
|
||||
@ -15,46 +16,108 @@ const hashingLockName = "36444143-1ace-4dbf-891c-cc505911497e"
|
||||
|
||||
var ErrMessageNotFound = gorm.ErrRecordNotFound
|
||||
var ErrMessageAlreadyExists = errors.New("duplicate id")
|
||||
var ErrMultipleMessagesFound = errors.New("multiple messages found")
|
||||
|
||||
type repository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (r *repository) SelectPending(deviceID string) (messages []Message, err error) {
|
||||
err = r.db.
|
||||
Where("device_id = ? AND state = ?", deviceID, ProcessingStatePending).
|
||||
Order("priority DESC, id DESC").
|
||||
Limit(100).
|
||||
Preload("Recipients").
|
||||
Find(&messages).
|
||||
Error
|
||||
func (r *repository) Select(filter MessagesSelectFilter, options MessagesSelectOptions) ([]Message, int64, error) {
|
||||
query := r.db.Model(&Message{})
|
||||
|
||||
return
|
||||
// Apply date range filter
|
||||
if !filter.StartDate.IsZero() {
|
||||
query = query.Where("messages.created_at >= ?", filter.StartDate)
|
||||
}
|
||||
if !filter.EndDate.IsZero() {
|
||||
query = query.Where("messages.created_at < ?", filter.EndDate)
|
||||
}
|
||||
|
||||
// Apply ID filter
|
||||
if filter.ExtID != "" {
|
||||
query = query.Where("messages.ext_id = ?", filter.ExtID)
|
||||
}
|
||||
|
||||
// Apply user filter
|
||||
if filter.UserID != "" {
|
||||
query = query.
|
||||
Joins("JOIN devices ON messages.device_id = devices.id").
|
||||
Where("devices.user_id = ?", filter.UserID)
|
||||
}
|
||||
|
||||
// Apply state filter
|
||||
if filter.State != "" {
|
||||
query = query.Where("messages.state = ?", filter.State)
|
||||
}
|
||||
|
||||
// Apply device filter
|
||||
if filter.DeviceID != "" {
|
||||
query = query.Where("messages.device_id = ?", filter.DeviceID)
|
||||
}
|
||||
|
||||
// Get total count
|
||||
var total int64
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// Apply pagination
|
||||
if options.Limit > 0 {
|
||||
query = query.Limit(options.Limit)
|
||||
}
|
||||
if options.Offset > 0 {
|
||||
query = query.Offset(options.Offset)
|
||||
}
|
||||
|
||||
// Apply ordering
|
||||
query = query.Order("messages.priority DESC, messages.id DESC")
|
||||
|
||||
// Preload related data
|
||||
if options.WithRecipients {
|
||||
query = query.Preload("Recipients")
|
||||
}
|
||||
if filter.UserID == "" && options.WithDevice {
|
||||
query = query.Joins("Device")
|
||||
}
|
||||
if options.WithStates {
|
||||
query = query.Preload("States")
|
||||
}
|
||||
|
||||
messages := make([]Message, 0, min(options.Limit, int(total)))
|
||||
if err := query.Find(&messages).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("can't select messages: %w", err)
|
||||
}
|
||||
|
||||
return messages, total, nil
|
||||
}
|
||||
|
||||
func (r *repository) Get(ID string, filter MessagesSelectFilter, options ...MessagesSelectOptions) (message Message, err error) {
|
||||
query := r.db.Model(&message).
|
||||
Where("ext_id = ?", ID)
|
||||
func (r *repository) SelectPending(deviceID string) ([]Message, error) {
|
||||
messages, _, err := r.Select(MessagesSelectFilter{
|
||||
DeviceID: deviceID,
|
||||
State: ProcessingStatePending,
|
||||
}, MessagesSelectOptions{
|
||||
WithRecipients: true,
|
||||
Limit: 100,
|
||||
})
|
||||
|
||||
if filter.DeviceID != "" {
|
||||
query = query.Where("device_id = ?", filter.DeviceID)
|
||||
return messages, err
|
||||
}
|
||||
|
||||
func (r *repository) Get(filter MessagesSelectFilter, options MessagesSelectOptions) (Message, error) {
|
||||
messages, _, err := r.Select(filter, options)
|
||||
if err != nil {
|
||||
return Message{}, fmt.Errorf("can't get message: %w", err)
|
||||
}
|
||||
|
||||
if len(options) > 0 {
|
||||
if options[0].WithRecipients {
|
||||
query = query.Preload("Recipients")
|
||||
}
|
||||
if options[0].WithDevice {
|
||||
query = query.Joins("Device")
|
||||
}
|
||||
if options[0].WithStates {
|
||||
query = query.Preload("States")
|
||||
}
|
||||
if len(messages) == 0 {
|
||||
return Message{}, ErrMessageNotFound
|
||||
}
|
||||
|
||||
err = query.Take(&message).Error
|
||||
if len(messages) > 1 {
|
||||
return Message{}, ErrMultipleMessagesFound
|
||||
}
|
||||
|
||||
return
|
||||
return messages[0], nil
|
||||
}
|
||||
|
||||
func (r *repository) Insert(message *Message) error {
|
||||
|
||||
@ -1,11 +1,21 @@
|
||||
package messages
|
||||
|
||||
import "time"
|
||||
|
||||
type MessagesSelectFilter struct {
|
||||
DeviceID string
|
||||
ExtID string
|
||||
UserID string
|
||||
DeviceID string
|
||||
StartDate time.Time
|
||||
EndDate time.Time
|
||||
State ProcessingState
|
||||
}
|
||||
|
||||
type MessagesSelectOptions struct {
|
||||
WithRecipients bool
|
||||
WithDevice bool
|
||||
WithStates bool
|
||||
|
||||
Limit int
|
||||
Offset int
|
||||
}
|
||||
|
||||
@ -102,7 +102,7 @@ func (s *Service) SelectPending(deviceID string) ([]MessageOut, error) {
|
||||
}
|
||||
|
||||
func (s *Service) UpdateState(deviceID string, message MessageStateIn) error {
|
||||
existing, err := s.messages.Get(message.ID, MessagesSelectFilter{DeviceID: deviceID})
|
||||
existing, err := s.messages.Get(MessagesSelectFilter{ExtID: message.ID, DeviceID: deviceID}, MessagesSelectOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -132,20 +132,26 @@ func (s *Service) UpdateState(deviceID string, message MessageStateIn) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) SelectStates(user models.User, filter MessagesSelectFilter, options MessagesSelectOptions) ([]MessageStateOut, int64, error) {
|
||||
filter.UserID = user.ID
|
||||
|
||||
messages, total, err := s.messages.Select(filter, options)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("can't select messages: %w", err)
|
||||
}
|
||||
|
||||
return slices.Map(messages, modelToMessageState), total, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetState(user models.User, ID string) (MessageStateOut, error) {
|
||||
message, err := s.messages.Get(
|
||||
ID,
|
||||
MessagesSelectFilter{},
|
||||
MessagesSelectFilter{ExtID: ID, UserID: user.ID},
|
||||
MessagesSelectOptions{WithRecipients: true, WithDevice: true, WithStates: true},
|
||||
)
|
||||
if err != nil {
|
||||
return MessageStateOut{}, ErrMessageNotFound
|
||||
}
|
||||
|
||||
if message.Device.UserID != user.ID {
|
||||
return MessageStateOut{}, ErrMessageNotFound
|
||||
}
|
||||
|
||||
return modelToMessageState(message), nil
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ Authorization: Bearer {{mobileToken}}
|
||||
###
|
||||
POST {{baseUrl}}/device HTTP/1.1
|
||||
# Authorization: Bearer 123456789
|
||||
Authorization: Basic {{credentials}}
|
||||
# Authorization: Basic {{credentials}}
|
||||
# Authorization: Code 065379
|
||||
Content-Type: application/json
|
||||
|
||||
|
||||
@ -74,6 +74,14 @@ Authorization: Basic {{credentials}}
|
||||
GET {{baseUrl}}/3rdparty/v1/messages/K56aIsVsQ2rECdv_ajzTd HTTP/1.1
|
||||
Authorization: Basic {{credentials}}
|
||||
|
||||
###
|
||||
GET {{baseUrl}}/3rdparty/v1/messages HTTP/1.1
|
||||
Authorization: Basic {{credentials}}
|
||||
|
||||
###
|
||||
GET {{baseUrl}}/3rdparty/v1/messages?from=2025-01-01T00:00:00.000Z&to=2025-12-31T23:59:59Z&state=Pending&deviceId=fL2m4IirEvh9BvTf6TIB0&limit=50&offset=0 HTTP/1.1
|
||||
Authorization: Basic {{credentials}}
|
||||
|
||||
###
|
||||
POST {{baseUrl}}/3rdparty/v1/messages/inbox/export HTTP/1.1
|
||||
Authorization: Basic {{credentials}}
|
||||
|
||||
@ -265,6 +265,93 @@
|
||||
}
|
||||
},
|
||||
"/3rdparty/v1/messages": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Retrieves a list of messages with filtering and pagination",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User",
|
||||
"Messages"
|
||||
],
|
||||
"summary": "Get messages",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Start date in RFC3339 format",
|
||||
"name": "from",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "End date in RFC3339 format",
|
||||
"name": "to",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Filter messages by processing state",
|
||||
"name": "state",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Filter by device ID",
|
||||
"name": "deviceId",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"default": 50,
|
||||
"description": "Pagination limit",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"default": 0,
|
||||
"description": "Pagination offset",
|
||||
"name": "offset",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A list of messages",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/smsgateway.MessageState"
|
||||
}
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
@ -1613,6 +1700,63 @@
|
||||
"PriorityMaximum"
|
||||
]
|
||||
},
|
||||
"smsgateway.MessageState": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"deviceId",
|
||||
"id",
|
||||
"recipients",
|
||||
"state"
|
||||
],
|
||||
"properties": {
|
||||
"deviceId": {
|
||||
"description": "Device ID",
|
||||
"type": "string",
|
||||
"maxLength": 21,
|
||||
"example": "PyDmBQZZXYmyxMwED8Fzy"
|
||||
},
|
||||
"id": {
|
||||
"description": "Message ID",
|
||||
"type": "string",
|
||||
"maxLength": 36,
|
||||
"example": "PyDmBQZZXYmyxMwED8Fzy"
|
||||
},
|
||||
"isEncrypted": {
|
||||
"description": "Encrypted",
|
||||
"type": "boolean",
|
||||
"example": false
|
||||
},
|
||||
"isHashed": {
|
||||
"description": "Hashed",
|
||||
"type": "boolean",
|
||||
"example": false
|
||||
},
|
||||
"recipients": {
|
||||
"description": "Recipients states",
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/definitions/smsgateway.RecipientState"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"description": "State",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/smsgateway.ProcessingState"
|
||||
}
|
||||
],
|
||||
"example": "Pending"
|
||||
},
|
||||
"states": {
|
||||
"description": "History of states",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"smsgateway.MessagesExportRequest": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
|
||||
@ -309,6 +309,48 @@ definitions:
|
||||
- PriorityDefault
|
||||
- PriorityBypassThreshold
|
||||
- PriorityMaximum
|
||||
smsgateway.MessageState:
|
||||
properties:
|
||||
deviceId:
|
||||
description: Device ID
|
||||
example: PyDmBQZZXYmyxMwED8Fzy
|
||||
maxLength: 21
|
||||
type: string
|
||||
id:
|
||||
description: Message ID
|
||||
example: PyDmBQZZXYmyxMwED8Fzy
|
||||
maxLength: 36
|
||||
type: string
|
||||
isEncrypted:
|
||||
description: Encrypted
|
||||
example: false
|
||||
type: boolean
|
||||
isHashed:
|
||||
description: Hashed
|
||||
example: false
|
||||
type: boolean
|
||||
recipients:
|
||||
description: Recipients states
|
||||
items:
|
||||
$ref: '#/definitions/smsgateway.RecipientState'
|
||||
minItems: 1
|
||||
type: array
|
||||
state:
|
||||
allOf:
|
||||
- $ref: '#/definitions/smsgateway.ProcessingState'
|
||||
description: State
|
||||
example: Pending
|
||||
states:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: History of states
|
||||
type: object
|
||||
required:
|
||||
- deviceId
|
||||
- id
|
||||
- recipients
|
||||
- state
|
||||
type: object
|
||||
smsgateway.MessagesExportRequest:
|
||||
properties:
|
||||
deviceId:
|
||||
@ -919,6 +961,64 @@ paths:
|
||||
- System
|
||||
- Logs
|
||||
/3rdparty/v1/messages:
|
||||
get:
|
||||
description: Retrieves a list of messages with filtering and pagination
|
||||
parameters:
|
||||
- description: Start date in RFC3339 format
|
||||
format: date-time
|
||||
in: query
|
||||
name: from
|
||||
type: string
|
||||
- description: End date in RFC3339 format
|
||||
format: date-time
|
||||
in: query
|
||||
name: to
|
||||
type: string
|
||||
- description: Filter messages by processing state
|
||||
in: query
|
||||
name: state
|
||||
type: string
|
||||
- description: Filter by device ID
|
||||
in: query
|
||||
name: deviceId
|
||||
type: string
|
||||
- default: 50
|
||||
description: Pagination limit
|
||||
in: query
|
||||
name: limit
|
||||
type: integer
|
||||
- default: 0
|
||||
description: Pagination offset
|
||||
in: query
|
||||
name: offset
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: A list of messages
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/smsgateway.MessageState'
|
||||
type: array
|
||||
"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'
|
||||
security:
|
||||
- ApiAuth: []
|
||||
summary: Get messages
|
||||
tags:
|
||||
- User
|
||||
- Messages
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user