mirror of
https://github.com/makayabou/asg-server.git
synced 2026-05-02 17:43:36 +02:00
[messages] add device last seen filter
This commit is contained in:
parent
2152e60243
commit
26e205d73b
@ -3,6 +3,7 @@ package messages
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/android-sms-gateway/client-go/smsgateway"
|
||||
"github.com/android-sms-gateway/server/internal/sms-gateway/handlers/base"
|
||||
@ -44,49 +45,58 @@ type ThirdPartyController struct {
|
||||
// @Tags User, Messages
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param skipPhoneValidation query bool false "Skip phone validation"
|
||||
// @Param request body smsgateway.Message true "Send message request"
|
||||
// @Success 202 {object} smsgateway.MessageState "Message enqueued"
|
||||
// @Failure 400 {object} smsgateway.ErrorResponse "Invalid request"
|
||||
// @Failure 401 {object} smsgateway.ErrorResponse "Unauthorized"
|
||||
// @Failure 409 {object} smsgateway.ErrorResponse "Message with such ID already exists"
|
||||
// @Failure 500 {object} smsgateway.ErrorResponse "Internal server error"
|
||||
// @Header 202 {string} Location "Get message state URL"
|
||||
// @Router /3rdparty/v1/messages [post]
|
||||
// @Param skipPhoneValidation query bool false "Skip phone validation"
|
||||
// @Param deviceActiveWithin query int false "Filter devices active within the specified number of hours" default(0)
|
||||
// @Param request body smsgateway.Message true "Send message request"
|
||||
// @Success 202 {object} smsgateway.MessageState "Message enqueued"
|
||||
// @Failure 400 {object} smsgateway.ErrorResponse "Invalid request"
|
||||
// @Failure 401 {object} smsgateway.ErrorResponse "Unauthorized"
|
||||
// @Failure 409 {object} smsgateway.ErrorResponse "Message with such ID already exists"
|
||||
// @Failure 500 {object} smsgateway.ErrorResponse "Internal server error"
|
||||
// @Header 202 {string} Location "Get message state URL"
|
||||
// @Router /3rdparty/v1/messages [post]
|
||||
//
|
||||
// Enqueue message
|
||||
func (h *ThirdPartyController) post(user models.User, c *fiber.Ctx) error {
|
||||
req := smsgateway.Message{}
|
||||
var params postQueryParams
|
||||
if err := h.QueryParserValidator(c, ¶ms); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
var req smsgateway.Message
|
||||
if err := h.BodyParserValidator(c, &req); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
skipPhoneValidation := c.QueryBool("skipPhoneValidation", false)
|
||||
|
||||
var device models.Device
|
||||
var err error
|
||||
var filters []devices.SelectFilter
|
||||
|
||||
if params.DeviceActiveWithin > 0 {
|
||||
filters = append(filters, devices.ActiveWithin(time.Duration(params.DeviceActiveWithin)*time.Hour))
|
||||
}
|
||||
|
||||
// Check if device_id is provided
|
||||
if req.DeviceID != "" {
|
||||
// Validate device ownership
|
||||
device, err = h.devicesSvc.Get(user.ID, devices.WithID(req.DeviceID))
|
||||
|
||||
device, err = h.devicesSvc.Get(user.ID, append(filters, devices.WithID(req.DeviceID))...)
|
||||
if err != nil {
|
||||
if errors.Is(err, devices.ErrNotFound) {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid device ID")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "No active device with such ID found")
|
||||
}
|
||||
h.Logger.Error("Failed to get device", zap.Error(err), zap.String("user_id", user.ID), zap.String("device_id", req.DeviceID))
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Can't select device. Please contact support")
|
||||
}
|
||||
} else {
|
||||
// Fallback to random selection
|
||||
devices, err := h.devicesSvc.Select(user.ID)
|
||||
devices, err := h.devicesSvc.Select(user.ID, filters...)
|
||||
if err != nil {
|
||||
h.Logger.Error("Failed to select devices", zap.Error(err), zap.String("user_id", user.ID))
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Can't select devices. Please contact support")
|
||||
}
|
||||
|
||||
if len(devices) < 1 {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "No devices registered")
|
||||
return fiber.NewError(fiber.StatusBadRequest, "No active devices found")
|
||||
}
|
||||
|
||||
device, err = slices.Random(devices)
|
||||
@ -125,7 +135,7 @@ func (h *ThirdPartyController) post(user models.User, c *fiber.Ctx) error {
|
||||
ValidUntil: req.ValidUntil,
|
||||
Priority: req.Priority,
|
||||
}
|
||||
state, err := h.messagesSvc.Enqueue(device, msg, messages.EnqueueOptions{SkipPhoneValidation: skipPhoneValidation})
|
||||
state, err := h.messagesSvc.Enqueue(device, msg, messages.EnqueueOptions{SkipPhoneValidation: params.SkipPhoneValidation})
|
||||
if err != nil {
|
||||
var errValidation messages.ErrValidation
|
||||
if isBadRequest := errors.As(err, &errValidation); isBadRequest {
|
||||
@ -155,12 +165,12 @@ func (h *ThirdPartyController) post(user models.User, c *fiber.Ctx) error {
|
||||
// @Security ApiAuth
|
||||
// @Tags User, Messages
|
||||
// @Produce json
|
||||
// @Param id path string true "Message ID"
|
||||
// @Success 200 {object} smsgateway.MessageState "Message state"
|
||||
// @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/{id} [get]
|
||||
// @Param id path string true "Message ID"
|
||||
// @Success 200 {object} smsgateway.MessageState "Message state"
|
||||
// @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/{id} [get]
|
||||
//
|
||||
// Get message state
|
||||
func (h *ThirdPartyController) get(user models.User, c *fiber.Ctx) error {
|
||||
@ -184,12 +194,12 @@ func (h *ThirdPartyController) get(user models.User, c *fiber.Ctx) error {
|
||||
// @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]
|
||||
// @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 {
|
||||
|
||||
6
internal/sms-gateway/handlers/messages/params.go
Normal file
6
internal/sms-gateway/handlers/messages/params.go
Normal file
@ -0,0 +1,6 @@
|
||||
package messages
|
||||
|
||||
type postQueryParams struct {
|
||||
SkipPhoneValidation bool `query:"skipPhoneValidation"`
|
||||
DeviceActiveWithin uint `query:"deviceActiveWithin"`
|
||||
}
|
||||
@ -1,6 +1,10 @@
|
||||
package devices
|
||||
|
||||
import "gorm.io/gorm"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type SelectFilter func(*selectFilter)
|
||||
|
||||
@ -22,10 +26,17 @@ func WithUserID(userID string) SelectFilter {
|
||||
}
|
||||
}
|
||||
|
||||
func ActiveWithin(duration time.Duration) SelectFilter {
|
||||
return func(f *selectFilter) {
|
||||
f.activeWithin = duration
|
||||
}
|
||||
}
|
||||
|
||||
type selectFilter struct {
|
||||
id *string
|
||||
userID *string
|
||||
token *string
|
||||
id *string
|
||||
userID *string
|
||||
token *string
|
||||
activeWithin time.Duration
|
||||
}
|
||||
|
||||
func newFilter(filters ...SelectFilter) *selectFilter {
|
||||
@ -50,5 +61,8 @@ func (f *selectFilter) apply(query *gorm.DB) *gorm.DB {
|
||||
if f.userID != nil {
|
||||
query = query.Where("user_id = ?", *f.userID)
|
||||
}
|
||||
if f.activeWithin != 0 {
|
||||
query = query.Where("last_seen > ?", time.Now().Add(-f.activeWithin))
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ GET {{baseUrl}}/health HTTP/1.1
|
||||
GET {{baseUrl}}/3rdparty/v1/health HTTP/1.1
|
||||
|
||||
###
|
||||
POST {{baseUrl}}/3rdparty/v1/messages?skipPhoneValidation=false HTTP/1.1
|
||||
POST {{baseUrl}}/3rdparty/v1/messages?skipPhoneValidation=false&deviceActiveWithin=240 HTTP/1.1
|
||||
Content-Type: application/json
|
||||
Authorization: Basic {{credentials}}
|
||||
|
||||
|
||||
@ -290,6 +290,13 @@
|
||||
"name": "skipPhoneValidation",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"default": 0,
|
||||
"description": "Filter devices active within the specified number of hours",
|
||||
"name": "deviceActiveWithin",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"description": "Send message request",
|
||||
"name": "request",
|
||||
|
||||
@ -900,6 +900,11 @@ paths:
|
||||
in: query
|
||||
name: skipPhoneValidation
|
||||
type: boolean
|
||||
- default: 0
|
||||
description: Filter devices active within the specified number of hours
|
||||
in: query
|
||||
name: deviceActiveWithin
|
||||
type: integer
|
||||
- description: Send message request
|
||||
in: body
|
||||
name: request
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user