summaryrefslogtreecommitdiff
path: root/internal/typeutils
diff options
context:
space:
mode:
Diffstat (limited to 'internal/typeutils')
-rw-r--r--internal/typeutils/converter.go58
-rw-r--r--internal/typeutils/internaltofrontend.go12
2 files changed, 70 insertions, 0 deletions
diff --git a/internal/typeutils/converter.go b/internal/typeutils/converter.go
index 311839dc0..4fbe1dfd3 100644
--- a/internal/typeutils/converter.go
+++ b/internal/typeutils/converter.go
@@ -18,10 +18,17 @@
package typeutils
import (
+ crand "crypto/rand"
+ "math/big"
+ "math/rand"
"sync"
+ "sync/atomic"
+ "time"
+ apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
"github.com/superseriousbusiness/gotosocial/internal/filter/interaction"
"github.com/superseriousbusiness/gotosocial/internal/filter/visibility"
+ "github.com/superseriousbusiness/gotosocial/internal/log"
"github.com/superseriousbusiness/gotosocial/internal/state"
)
@@ -31,6 +38,7 @@ type Converter struct {
randAvatars sync.Map
visFilter *visibility.Filter
intFilter *interaction.Filter
+ randStats atomic.Pointer[apimodel.RandomStats]
}
func NewConverter(state *state.State) *Converter {
@@ -41,3 +49,53 @@ func NewConverter(state *state.State) *Converter {
intFilter: interaction.NewFilter(state),
}
}
+
+// RandomStats returns or generates
+// and returns random instance stats.
+func (c *Converter) RandomStats() apimodel.RandomStats {
+ now := time.Now()
+ stats := c.randStats.Load()
+ if stats != nil && time.Since(stats.Generated) < time.Hour {
+ // Random stats are still
+ // fresh (less than 1hr old),
+ // so return them as-is.
+ return *stats
+ }
+
+ // Generate new random stats.
+ newStats := genRandStats()
+ newStats.Generated = now
+ c.randStats.Store(&newStats)
+ return newStats
+}
+
+func genRandStats() apimodel.RandomStats {
+ const (
+ statusesMax = 10000000
+ usersMax = 1000000
+ )
+
+ statusesB, err := crand.Int(crand.Reader, big.NewInt(statusesMax))
+ if err != nil {
+ // Only errs if something is buggered with the OS.
+ log.Panicf(nil, "error randomly generating statuses count: %v", err)
+ }
+
+ totalUsersB, err := crand.Int(crand.Reader, big.NewInt(usersMax))
+ if err != nil {
+ // Only errs if something is buggered with the OS.
+ log.Panicf(nil, "error randomly generating users count: %v", err)
+ }
+
+ // Monthly users should only ever
+ // be <= 100% of total users.
+ totalUsers := totalUsersB.Int64()
+ activeRatio := rand.Float64() //nolint
+ mau := int64(float64(totalUsers) * activeRatio)
+
+ return apimodel.RandomStats{
+ Statuses: statusesB.Int64(),
+ TotalUsers: totalUsers,
+ MonthlyActiveUsers: mau,
+ }
+}
diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go
index 71ff71f8b..487e8434e 100644
--- a/internal/typeutils/internaltofrontend.go
+++ b/internal/typeutils/internaltofrontend.go
@@ -1745,6 +1745,12 @@ func (c *Converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Ins
stats["domain_count"] = util.Ptr(domainCount)
instance.Stats = stats
+ if config.GetInstanceStatsRandomize() {
+ // Whack some random stats on the instance
+ // to be injected by API handlers.
+ instance.RandomStats = c.RandomStats()
+ }
+
// thumbnail
iAccount, err := c.state.DB.GetInstanceAccount(ctx, "")
if err != nil {
@@ -1821,6 +1827,12 @@ func (c *Converter) InstanceToAPIV2Instance(ctx context.Context, i *gtsmodel.Ins
instance.Debug = util.Ptr(true)
}
+ if config.GetInstanceStatsRandomize() {
+ // Whack some random stats on the instance
+ // to be injected by API handlers.
+ instance.RandomStats = c.RandomStats()
+ }
+
// thumbnail
thumbnail := apimodel.InstanceV2Thumbnail{}