from datetime import timedelta from django.core.cache import cache from django.db.models import Count, Q from django.utils import timezone from loguru import logger from common.models import BaseJob, JobManager from journal.models import Comment, Review, ShelfMember from takahe.models import Domain, Identity, Post @JobManager.register class TakaheStats(BaseJob): interval = timedelta(hours=6) max_unreachable_days = 31 def active_users(self, d: int) -> int: return ( ShelfMember.objects.filter( created_time__gte=timezone.now() - timedelta(days=d), local=True ) .values("owner_id") .distinct() .count() ) def run(self): logger.info("Updating Tahake stats.") # for /api/v1/instance stats = { "user_count": Identity.objects.filter( local=True, deleted__isnull=True ).count(), "status_count": Post.objects.filter(local=True) .exclude(state__in=["deleted", "deleted_fanned_out"]) .count(), "domain_count": Domain.objects.count(), } cache.set("instance_info_stats", stats, timeout=None) logger.debug(f"/api/v1/instance {stats}") # for /api/v2/instance usage = { "users": { "active_month": self.active_users(30), } } cache.set("instance_info_usage", usage, timeout=None) logger.debug(f"/api/v2/instance {usage}") # for NodeInfo nodeinfo_usage = { "users": { "total": stats["user_count"], "activeMonth": usage["users"]["active_month"], "activeHalfyear": self.active_users(180), }, "localPosts": ShelfMember.objects.filter(local=True).count(), "localComments": Comment.objects.filter(local=True).count() + Review.objects.filter(local=True).count(), } cache.set("nodeinfo_usage", nodeinfo_usage, timeout=None) logger.debug(f"/nodeinfo/2.0/ {nodeinfo_usage}") # disable /api/v1/instance/activity for now as it's slow cache.set("instance_activity_stats", [], timeout=None) logger.info("Tahake stats updated.")