diff --git a/commands/slash/signin.go b/commands/slash/signin.go index a8fd79d..a60df28 100644 --- a/commands/slash/signin.go +++ b/commands/slash/signin.go @@ -238,15 +238,15 @@ func Signin() *structs.SlashCommand { logging.Error(s, "Error encounted while deleting message\n\n"+err.Error(), i.Member.User, span, logrus.Fields{"error": err}) } - users, err := data.Signin.QueryUsers(time.Duration(12)*time.Hour, entSigninType, span.Context()) + userPairs, err := data.Signin.Query(time.Duration(12)*time.Hour, entSigninType, span.Context()) if err != nil { logging.Error(s, err.Error(), i.Member.User, span, logrus.Fields{"error": err}) return } - message := fmt.Sprintf("Signins for `%s`; %d users signed in:\n", signinType, len(users)) - for _, user := range users { - message += fmt.Sprintf("- %s\n", helpers.AtUser(user.ID)) + message := fmt.Sprintf("Signins for `%s`; %d users signed in:\n", signinType, len(userPairs)) + for _, user := range userPairs { + message += fmt.Sprintf("- %s\n", helpers.AtUser(user.Key)) } err = helpers.SendDirectMessage(s, i.Message.Author.ID, "", span.Context()) diff --git a/data/signin.go b/data/signin.go index 6d09e89..6356759 100644 --- a/data/signin.go +++ b/data/signin.go @@ -6,6 +6,7 @@ import ( "gitlab.ritsec.cloud/1nv8rZim/ops-bot-iii/ent" "gitlab.ritsec.cloud/1nv8rZim/ops-bot-iii/ent/signin" "gitlab.ritsec.cloud/1nv8rZim/ops-bot-iii/ent/user" + "gitlab.ritsec.cloud/1nv8rZim/ops-bot-iii/structs" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace" "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer" ) @@ -86,7 +87,7 @@ func (*signin_s) RecentSignin(userID string, signinType signin.Type, ctx ddtrace return ok, nil } -func (*signin_s) QueryUsers(delta time.Duration, signinType signin.Type, ctx ddtrace.SpanContext) ([]*ent.User, error) { +func (*signin_s) Query(delta time.Duration, signinType signin.Type, ctx ddtrace.SpanContext) (structs.PairList[string], error) { span := tracer.StartSpan( "data.signin:Query", tracer.ResourceName("Data.Signin.Query"), @@ -94,12 +95,46 @@ func (*signin_s) QueryUsers(delta time.Duration, signinType signin.Type, ctx ddt ) defer span.Finish() - return Client.User.Query(). - Where( - user.HasSigninsWith( + var ( + entSignins []*ent.Signin + err error + ) + + if signinType == "All" { + entSignins, err = Client.Signin.Query(). + Where( + signin.TimestampGTE(time.Now().Add(-delta)), + ). + WithUser(). + All(Ctx) + } else { + entSignins, err = Client.Signin.Query(). + Where( signin.TypeEQ(signinType), signin.TimestampGTE(time.Now().Add(-delta)), - ), - ). - All(Ctx) + ). + WithUser(). + All(Ctx) + } + if err != nil { + return nil, err + } + + userCount := make(map[string]int) + + for _, entSignin := range entSignins { + userCount[entSignin.Edges.User.ID]++ + } + + pairList := make(structs.PairList[string], len(userCount)) + + i := 0 + for userID, count := range userCount { + pairList[i] = structs.Pair[string]{Key: userID, Value: count} + i++ + } + + pairList.Sort() + + return pairList, nil } diff --git a/structs/pair.go b/structs/pair.go new file mode 100644 index 0000000..b6fbb29 --- /dev/null +++ b/structs/pair.go @@ -0,0 +1,26 @@ +package structs + +import "sort" + +type Pair[T any] struct { + Key T + Value int +} + +type PairList[T any] []Pair[T] + +func (p PairList[T]) Len() int { + return len(p) +} + +func (p PairList[T]) Less(i, j int) bool { + return p[i].Value < p[j].Value +} + +func (p PairList[T]) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} + +func (p PairList[T]) Sort() { + sort.Sort(p) +}