From df1a84b27b90372d061d3e769de744a8b5792920 Mon Sep 17 00:00:00 2001 From: Aleksandr Soloshenko Date: Sun, 3 Dec 2023 20:33:25 +0700 Subject: [PATCH] Added: `withDeliveryReport` field support --- api/local.http | 5 ++-- api/requests.http | 3 ++- api/swagger.json | 5 ++++ api/swagger.yaml | 4 ++++ .../mysql/20231203200642_delivery_report.sql | 10 ++++++++ internal/sms-gateway/models/models.go | 15 ++++++------ internal/sms-gateway/services/messages.go | 24 ++++++++++--------- pkg/smsgateway/domain.go | 11 +++++---- pkg/types/types.go | 7 ++++++ 9 files changed, 58 insertions(+), 26 deletions(-) create mode 100644 internal/sms-gateway/models/migrations/mysql/20231203200642_delivery_report.sql diff --git a/api/local.http b/api/local.http index 425931e..ebf4932 100644 --- a/api/local.http +++ b/api/local.http @@ -8,12 +8,13 @@ Content-Type: application/json Authorization: Basic {{localCredentials}} { - "message": "Test", + "message": "{{$localDatetime iso8601}}", "ttl": 600, "phoneNumbers": [ "{{phone}}" ], - "simNumber": 1 + "simNumber": 1, + "withDeliveryReport": true } ### diff --git a/api/requests.http b/api/requests.http index b2b383e..ac28024 100644 --- a/api/requests.http +++ b/api/requests.http @@ -23,7 +23,8 @@ Authorization: Basic {{credentials}} "phoneNumbers": [ "{{phone}}" ], - "simNumber": 3 + "simNumber": 1, + "withDeliveryReport": true } ### diff --git a/api/swagger.json b/api/swagger.json index 1eca0a0..1a63bc0 100644 --- a/api/swagger.json +++ b/api/swagger.json @@ -369,6 +369,11 @@ "type": "integer", "minimum": 5, "example": 86400 + }, + "withDeliveryReport": { + "description": "Запрашивать отчет о доставке", + "type": "boolean", + "example": true } } }, diff --git a/api/swagger.yaml b/api/swagger.yaml index 31aeda0..b707bd6 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -43,6 +43,10 @@ definitions: example: 86400 minimum: 5 type: integer + withDeliveryReport: + description: Запрашивать отчет о доставке + example: true + type: boolean required: - message - phoneNumbers diff --git a/internal/sms-gateway/models/migrations/mysql/20231203200642_delivery_report.sql b/internal/sms-gateway/models/migrations/mysql/20231203200642_delivery_report.sql new file mode 100644 index 0000000..4296136 --- /dev/null +++ b/internal/sms-gateway/models/migrations/mysql/20231203200642_delivery_report.sql @@ -0,0 +1,10 @@ +-- +goose Up +-- +goose StatementBegin +ALTER TABLE `messages` +ADD `with_delivery_report` tinyint(1) unsigned DEFAULT false; +-- +goose StatementEnd +--- +-- +goose Down +-- +goose StatementBegin +ALTER TABLE `messages` DROP `with_delivery_report`; +-- +goose StatementEnd \ No newline at end of file diff --git a/internal/sms-gateway/models/models.go b/internal/sms-gateway/models/models.go index 6214084..38d646b 100644 --- a/internal/sms-gateway/models/models.go +++ b/internal/sms-gateway/models/models.go @@ -42,13 +42,14 @@ type Device struct { } type Message struct { - ID uint64 `gorm:"primaryKey;type:BIGINT UNSIGNED;autoIncrement"` - DeviceID string `gorm:"not null;type:char(21);uniqueIndex:unq_messages_id_device,priority:2;index:idx_messages_device_state"` - ExtID string `gorm:"not null;type:varchar(36);uniqueIndex:unq_messages_id_device,priority:1"` - Message string `gorm:"not null;type:tinytext"` - State MessageState `gorm:"not null;type:enum('Pending','Sent','Processed','Delivered','Failed');default:Pending;index:idx_messages_device_state"` - ValidUntil *time.Time `gorm:"type:datetime"` - SimNumber *uint8 `gorm:"type:tinyint(1) unsigned"` + ID uint64 `gorm:"primaryKey;type:BIGINT UNSIGNED;autoIncrement"` + DeviceID string `gorm:"not null;type:char(21);uniqueIndex:unq_messages_id_device,priority:2;index:idx_messages_device_state"` + ExtID string `gorm:"not null;type:varchar(36);uniqueIndex:unq_messages_id_device,priority:1"` + Message string `gorm:"not null;type:tinytext"` + State MessageState `gorm:"not null;type:enum('Pending','Sent','Processed','Delivered','Failed');default:Pending;index:idx_messages_device_state"` + ValidUntil *time.Time `gorm:"type:datetime"` + SimNumber *uint8 `gorm:"type:tinyint(1) unsigned"` + WithDeliveryReport bool `gorm:"type:tinyint(1) unsigned;default:0"` Device Device `gorm:"foreignKey:DeviceID;constraint:OnDelete:CASCADE"` Recipients []MessageRecipient `gorm:"foreignKey:MessageID;constraint:OnDelete:CASCADE"` diff --git a/internal/sms-gateway/services/messages.go b/internal/sms-gateway/services/messages.go index 059f467..48fffc6 100644 --- a/internal/sms-gateway/services/messages.go +++ b/internal/sms-gateway/services/messages.go @@ -62,11 +62,12 @@ func (s *MessagesService) SelectPending(deviceID string) ([]smsgateway.Message, } result[i] = smsgateway.Message{ - ID: v.ExtID, - Message: v.Message, - TTL: ttl, - PhoneNumbers: s.recipientsToDomain(v.Recipients), - SimNumber: v.SimNumber, + ID: v.ExtID, + Message: v.Message, + TTL: ttl, + PhoneNumbers: s.recipientsToDomain(v.Recipients), + SimNumber: v.SimNumber, + WithDeliveryReport: types.AsPointer[bool](v.WithDeliveryReport), } } @@ -129,12 +130,13 @@ func (s *MessagesService) Enqeue(device models.Device, message smsgateway.Messag } msg := models.Message{ - DeviceID: device.ID, - ExtID: message.ID, - Message: message.Message, - ValidUntil: validUntil, - SimNumber: message.SimNumber, - Recipients: s.recipientsToModel(message.PhoneNumbers), + DeviceID: device.ID, + ExtID: message.ID, + Message: message.Message, + ValidUntil: validUntil, + SimNumber: message.SimNumber, + WithDeliveryReport: types.OrDefault[bool](message.WithDeliveryReport, true), + Recipients: s.recipientsToModel(message.PhoneNumbers), } if msg.ExtID == "" { msg.ExtID = s.idgen() diff --git a/pkg/smsgateway/domain.go b/pkg/smsgateway/domain.go index f762142..5416304 100644 --- a/pkg/smsgateway/domain.go +++ b/pkg/smsgateway/domain.go @@ -12,11 +12,12 @@ const ( // Сообщение type Message struct { - ID string `json:"id,omitempty" validate:"omitempty,max=36" example:"PyDmBQZZXYmyxMwED8Fzy"` // Идентификатор - Message string `json:"message" validate:"required,max=256" example:"Hello World!"` // Текст сообщения - TTL *uint64 `json:"ttl,omitempty" validate:"omitempty,min=5" example:"86400"` // Время жизни сообщения в секундах - SimNumber *uint8 `json:"simNumber,omitempty" validate:"omitempty,max=3" example:"1"` // Номер сим-карты - PhoneNumbers []string `json:"phoneNumbers" validate:"required,min=1,max=100,dive,required,min=10" example:"79990001234"` // Получатели + ID string `json:"id,omitempty" validate:"omitempty,max=36" example:"PyDmBQZZXYmyxMwED8Fzy"` // Идентификатор + Message string `json:"message" validate:"required,max=256" example:"Hello World!"` // Текст сообщения + TTL *uint64 `json:"ttl,omitempty" validate:"omitempty,min=5" example:"86400"` // Время жизни сообщения в секундах + SimNumber *uint8 `json:"simNumber,omitempty" validate:"omitempty,max=3" example:"1"` // Номер сим-карты + WithDeliveryReport *bool `json:"withDeliveryReport,omitempty" example:"true"` // Запрашивать отчет о доставке + PhoneNumbers []string `json:"phoneNumbers" validate:"required,min=1,max=100,dive,required,min=10" example:"79990001234"` // Получатели } // Состояние сообщения diff --git a/pkg/types/types.go b/pkg/types/types.go index f7e2558..f54c08b 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -3,3 +3,10 @@ package types func AsPointer[T any](v T) *T { return &v } + +func OrDefault[T any](v *T, def T) T { + if v == nil { + return def + } + return *v +}