package query import ( "context" "strings" "time" "forge.cadoles.com/Cadoles/fake-sms/internal/model" "forge.cadoles.com/Cadoles/fake-sms/internal/storm" stormdb "github.com/asdine/storm/v3" "github.com/asdine/storm/v3/q" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/cqrs" "gitlab.com/wpetit/goweb/middleware/container" ) type OutboxSearch struct { Recipient string Body string After time.Time Before time.Time } type GetOutboxRequest struct { OrderBy string Limit int Skip int Reverse bool Search *OutboxSearch } type OutboxData struct { Messages []*model.SMS } func HandleGetOutbox(ctx context.Context, qry cqrs.Query) (interface{}, error) { req, ok := qry.Request().(*GetOutboxRequest) if !ok { return nil, cqrs.ErrUnexpectedRequest } ctn, err := container.From(ctx) if err != nil { return nil, errors.Wrap(err, "could not retrieve service container") } db, err := storm.From(ctn) if err != nil { return nil, errors.Wrap(err, "could not retrieve storm service") } messages := make([]*model.SMS, 0) var query stormdb.Query if req.Search != nil { matchers := make([]q.Matcher, 0) if req.Search.Body != "" { matchers = append(matchers, q.Or( q.Re("Body", req.Search.Body), )) } query = db.Select(matchers...) } else { query = db.Select() } if req.OrderBy != "" { query = query.OrderBy(req.OrderBy) } else { query = query.OrderBy("SentAt").Reverse() } if req.Reverse { query = query.Reverse() } if req.Limit != 0 { query = query.Limit(req.Limit) } if req.Skip != 0 { query = query.Limit(req.Skip) } if err := query.Find(&messages); err != nil { if err == storm.ErrNotFound { return &OutboxData{messages}, nil } return nil, errors.Wrap(err, "could not retrieve emails") } if req.Search == nil { return &OutboxData{messages}, nil } filtered := make([]*model.SMS, 0, len(messages)) for _, sms := range messages { match := true if req.Search.Recipient != "" { match = strings.Contains(sms.Recipient, req.Search.Recipient) } if !req.Search.After.IsZero() && !sms.SentAt.After(req.Search.After) { match = false } if !req.Search.Before.IsZero() && !sms.SentAt.Before(req.Search.Before) { match = false } if match { filtered = append(filtered, sms) } } return &OutboxData{filtered}, nil }