Track when user was last active

fixes #10
This commit is contained in:
Mouse Reeve 2020-11-01 09:16:49 -08:00
parent c334451216
commit 4e02a8df99
5 changed files with 55 additions and 3 deletions

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.7 on 2020-11-01 17:05
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bookwyrm', '0062_auto_20201031_1936'),
]
operations = [
migrations.AddField(
model_name='user',
name='last_active_date',
field=models.DateTimeField(auto_now=True),
),
]

View File

@ -129,6 +129,11 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
).serialize() ).serialize()
return ActivitypubMixin.to_activity(self, pure=pure) return ActivitypubMixin.to_activity(self, pure=pure)
def save(self, *args, **kwargs):
self.user.last_active_date = timezone.now()
self.user.save()
super().save(*args, **kwargs)
class GeneratedNote(Status): class GeneratedNote(Status):
''' these are app-generated messages about user activity ''' ''' these are app-generated messages about user activity '''
@ -228,6 +233,11 @@ class Favorite(ActivitypubMixin, BookWyrmModel):
activity_serializer = activitypub.Like activity_serializer = activitypub.Like
def save(self, *args, **kwargs):
self.user.last_active_date = timezone.now()
self.user.save()
super().save(*args, **kwargs)
class Meta: class Meta:
''' can't fav things twice ''' ''' can't fav things twice '''
@ -268,6 +278,11 @@ class ReadThrough(BookWyrmModel):
blank=True, blank=True,
null=True) null=True)
def save(self, *args, **kwargs):
self.user.last_active_date = timezone.now()
self.user.save()
super().save(*args, **kwargs)
NotificationType = models.TextChoices( NotificationType = models.TextChoices(
'NotificationType', 'NotificationType',

View File

@ -69,6 +69,7 @@ class User(OrderedCollectionPageMixin, AbstractUser):
remote_id = models.CharField(max_length=255, null=True, unique=True) remote_id = models.CharField(max_length=255, null=True, unique=True)
created_date = models.DateTimeField(auto_now_add=True) created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True) updated_date = models.DateTimeField(auto_now=True)
last_active_date = models.DateTimeField(auto_now=True)
manually_approves_followers = models.BooleanField(default=False) manually_approves_followers = models.BooleanField(default=False)
# ---- activitypub serialization settings for this model ----- # # ---- activitypub serialization settings for this model ----- #
@ -172,6 +173,7 @@ class User(OrderedCollectionPageMixin, AbstractUser):
# this user already exists, no need to populate fields # this user already exists, no need to populate fields
if self.id: if self.id:
return return
if not self.local: if not self.local:
# generate a username that uses the domain (webfinger format) # generate a username that uses the domain (webfinger format)
actor_parts = urlparse(self.remote_id) actor_parts = urlparse(self.remote_id)

View File

@ -4,13 +4,15 @@ from PIL import Image
import dateutil.parser import dateutil.parser
from dateutil.parser import ParserError from dateutil.parser import ParserError
from django.contrib.auth import authenticate, login, logout from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.core.exceptions import PermissionDenied
from django.core.files.base import ContentFile from django.core.files.base import ContentFile
from django.http import HttpResponseBadRequest, HttpResponseNotFound from django.http import HttpResponseBadRequest, HttpResponseNotFound
from django.shortcuts import redirect from django.shortcuts import redirect
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.core.exceptions import PermissionDenied from django.utils import timezone
from bookwyrm import books_manager from bookwyrm import books_manager
from bookwyrm import forms, models, outgoing from bookwyrm import forms, models, outgoing
@ -32,7 +34,9 @@ def user_login(request):
password = login_form.data['password'] password = login_form.data['password']
user = authenticate(request, username=username, password=password) user = authenticate(request, username=username, password=password)
if user is not None: if user is not None:
# successful login
login(request, user) login(request, user)
user.last_active_date = timezone.now()
return redirect(request.GET.get('next', '/')) return redirect(request.GET.get('next', '/'))
login_form.non_field_errors = 'Username or password are incorrect' login_form.non_field_errors = 'Username or password are incorrect'

View File

@ -1,4 +1,7 @@
''' responds to various requests to /.well-know ''' ''' responds to various requests to /.well-know '''
from datetime import datetime
from dateutil.relativedelta import relativedelta
from django.http import HttpResponseBadRequest, HttpResponseNotFound from django.http import HttpResponseBadRequest, HttpResponseNotFound
from django.http import JsonResponse from django.http import JsonResponse
@ -52,6 +55,16 @@ def nodeinfo(request):
status_count = models.Status.objects.filter(user__local=True).count() status_count = models.Status.objects.filter(user__local=True).count()
user_count = models.User.objects.count() user_count = models.User.objects.count()
month_ago = datetime.now() - relativedelta(months=1)
last_month_count = models.User.objects.filter(
last_active_date__gt=month_ago
).count()
six_months_ago = datetime.now() - relativedelta(months=6)
six_month_count = models.User.objects.filter(
last_active_date__gt=six_months_ago
).count()
return JsonResponse({ return JsonResponse({
'version': '2.0', 'version': '2.0',
'software': { 'software': {
@ -64,8 +77,8 @@ def nodeinfo(request):
'usage': { 'usage': {
'users': { 'users': {
'total': user_count, 'total': user_count,
'activeMonth': user_count, # TODO 'activeMonth': last_month_count,
'activeHalfyear': user_count, # TODO 'activeHalfyear': six_month_count,
}, },
'localPosts': status_count, 'localPosts': status_count,
}, },