package classes import ( "context" "fmt" "time" "git.golem15.com/golem15/sm-user-plugin/models" "gorm.io/gorm" ) // ThrottleStates reads the ban and suspension state of userIDs from // user_throttle in one query. A user is banned when any of their rows is // banned, and suspended when a row is suspended and its suspended_at lies // inside the suspension window (golem15.user.throttle.suspension_minutes, // read from ctx as ContextWithThrottle stores it). It is a pure read: an // expired suspension is not lifted here. func ThrottleStates(ctx context.Context, db *gorm.DB, userIDs []uint) (banned, suspended map[uint]bool, err error) { banned, suspended = map[uint]bool{}, map[uint]bool{} if db == nil { return nil, nil, fmt.Errorf("golem15.user: gorm handle is missing") } if len(userIDs) == 0 { return banned, suspended, nil } minutes := throttleFrom(ctx).minutes if minutes <= 0 { minutes = 15 } window := time.Duration(minutes) * time.Minute var rows []models.Throttle err = db.Session(&gorm.Session{NewDB: true}).WithContext(ctx). Where("user_id IN ? AND (is_banned OR is_suspended)", userIDs). Find(&rows).Error if err != nil { return nil, nil, err } now := time.Now() for _, row := range rows { if row.IsBanned { banned[row.UserID] = true } if row.IsSuspended && row.SuspendedAt != nil && now.Before(row.SuspendedAt.Add(window)) { suspended[row.UserID] = true } } return banned, suspended, nil }