forked from mirrors/bookwyrm
Merge branch 'main' into production
This commit is contained in:
commit
3d1f4e3452
8 changed files with 77 additions and 36 deletions
19
bookwyrm/migrations/0081_alter_user_last_active_date.py
Normal file
19
bookwyrm/migrations/0081_alter_user_last_active_date.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# Generated by Django 3.2.4 on 2021-08-06 02:51
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookwyrm", "0080_alter_shelfbook_options"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="user",
|
||||||
|
name="last_active_date",
|
||||||
|
field=models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
),
|
||||||
|
]
|
|
@ -111,7 +111,7 @@ class User(OrderedCollectionPageMixin, AbstractUser):
|
||||||
remote_id = fields.RemoteIdField(null=True, unique=True, activitypub_field="id")
|
remote_id = fields.RemoteIdField(null=True, unique=True, activitypub_field="id")
|
||||||
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)
|
last_active_date = models.DateTimeField(default=timezone.now)
|
||||||
manually_approves_followers = fields.BooleanField(default=False)
|
manually_approves_followers = fields.BooleanField(default=False)
|
||||||
show_goal = models.BooleanField(default=True)
|
show_goal = models.BooleanField(default=True)
|
||||||
discoverable = fields.BooleanField(default=False)
|
discoverable = fields.BooleanField(default=False)
|
||||||
|
|
|
@ -19,7 +19,7 @@ class SuggestedUsers(RedisStore):
|
||||||
|
|
||||||
def get_rank(self, obj):
|
def get_rank(self, obj):
|
||||||
"""get computed rank"""
|
"""get computed rank"""
|
||||||
return obj.mutuals + (1.0 - (1.0 / (obj.shared_books + 1)))
|
return obj.mutuals # + (1.0 - (1.0 / (obj.shared_books + 1)))
|
||||||
|
|
||||||
def store_id(self, user): # pylint: disable=no-self-use
|
def store_id(self, user): # pylint: disable=no-self-use
|
||||||
"""the key used to store this user's recs"""
|
"""the key used to store this user's recs"""
|
||||||
|
@ -31,7 +31,7 @@ class SuggestedUsers(RedisStore):
|
||||||
"""calculate mutuals count and shared books count from rank"""
|
"""calculate mutuals count and shared books count from rank"""
|
||||||
return {
|
return {
|
||||||
"mutuals": math.floor(rank),
|
"mutuals": math.floor(rank),
|
||||||
"shared_books": int(1 / (-1 * (rank % 1 - 1))) - 1,
|
# "shared_books": int(1 / (-1 * (rank % 1 - 1))) - 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_objects_for_store(self, store):
|
def get_objects_for_store(self, store):
|
||||||
|
@ -95,7 +95,7 @@ class SuggestedUsers(RedisStore):
|
||||||
logger.exception(err)
|
logger.exception(err)
|
||||||
continue
|
continue
|
||||||
user.mutuals = counts["mutuals"]
|
user.mutuals = counts["mutuals"]
|
||||||
user.shared_books = counts["shared_books"]
|
# user.shared_books = counts["shared_books"]
|
||||||
results.append(user)
|
results.append(user)
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
@ -115,16 +115,16 @@ def get_annotated_users(viewer, *args, **kwargs):
|
||||||
),
|
),
|
||||||
distinct=True,
|
distinct=True,
|
||||||
),
|
),
|
||||||
shared_books=Count(
|
# shared_books=Count(
|
||||||
"shelfbook",
|
# "shelfbook",
|
||||||
filter=Q(
|
# filter=Q(
|
||||||
~Q(id=viewer.id),
|
# ~Q(id=viewer.id),
|
||||||
shelfbook__book__parent_work__in=[
|
# shelfbook__book__parent_work__in=[
|
||||||
s.book.parent_work for s in viewer.shelfbook_set.all()
|
# s.book.parent_work for s in viewer.shelfbook_set.all()
|
||||||
],
|
# ],
|
||||||
),
|
# ),
|
||||||
distinct=True,
|
# distinct=True,
|
||||||
),
|
# ),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -162,18 +162,18 @@ def update_suggestions_on_unfollow(sender, instance, **kwargs):
|
||||||
rerank_user_task.delay(instance.user_object.id, update_only=False)
|
rerank_user_task.delay(instance.user_object.id, update_only=False)
|
||||||
|
|
||||||
|
|
||||||
@receiver(signals.post_save, sender=models.ShelfBook)
|
# @receiver(signals.post_save, sender=models.ShelfBook)
|
||||||
@receiver(signals.post_delete, sender=models.ShelfBook)
|
# @receiver(signals.post_delete, sender=models.ShelfBook)
|
||||||
# pylint: disable=unused-argument
|
# # pylint: disable=unused-argument
|
||||||
def update_rank_on_shelving(sender, instance, *args, **kwargs):
|
# def update_rank_on_shelving(sender, instance, *args, **kwargs):
|
||||||
"""when a user shelves or unshelves a book, re-compute their rank"""
|
# """when a user shelves or unshelves a book, re-compute their rank"""
|
||||||
# if it's a local user, re-calculate who is rec'ed to them
|
# # if it's a local user, re-calculate who is rec'ed to them
|
||||||
if instance.user.local:
|
# if instance.user.local:
|
||||||
rerank_suggestions_task.delay(instance.user.id)
|
# rerank_suggestions_task.delay(instance.user.id)
|
||||||
|
#
|
||||||
# if the user is discoverable, update their rankings
|
# # if the user is discoverable, update their rankings
|
||||||
if instance.user.discoverable:
|
# if instance.user.discoverable:
|
||||||
rerank_user_task.delay(instance.user.id)
|
# rerank_user_task.delay(instance.user.id)
|
||||||
|
|
||||||
|
|
||||||
@receiver(signals.post_save, sender=models.User)
|
@receiver(signals.post_save, sender=models.User)
|
||||||
|
|
|
@ -171,3 +171,15 @@ class Inventaire(TestCase):
|
||||||
}
|
}
|
||||||
self.assertEqual(get_language_code(options), "there")
|
self.assertEqual(get_language_code(options), "there")
|
||||||
self.assertIsNone(get_language_code({}))
|
self.assertIsNone(get_language_code({}))
|
||||||
|
|
||||||
|
@responses.activate
|
||||||
|
def test_get_description(self):
|
||||||
|
"""extract a wikipedia excerpt"""
|
||||||
|
responses.add(
|
||||||
|
responses.GET,
|
||||||
|
"https://inventaire.io/api/data?action=wp-extract&lang=en&title=test_path",
|
||||||
|
json={"extract": "hi hi"},
|
||||||
|
)
|
||||||
|
|
||||||
|
extract = self.connector.get_description({"enwiki": "test_path"})
|
||||||
|
self.assertEqual(extract, "hi hi")
|
||||||
|
|
|
@ -29,7 +29,7 @@ class SuggestedUsers(TestCase):
|
||||||
Mock = namedtuple("AnnotatedUserMock", ("mutuals", "shared_books"))
|
Mock = namedtuple("AnnotatedUserMock", ("mutuals", "shared_books"))
|
||||||
annotated_user_mock = Mock(3, 27)
|
annotated_user_mock = Mock(3, 27)
|
||||||
rank = suggested_users.get_rank(annotated_user_mock)
|
rank = suggested_users.get_rank(annotated_user_mock)
|
||||||
self.assertEqual(rank, 3.9642857142857144)
|
self.assertEqual(rank, 3) # 3.9642857142857144)
|
||||||
|
|
||||||
def test_store_id(self, *_):
|
def test_store_id(self, *_):
|
||||||
"""redis key generation"""
|
"""redis key generation"""
|
||||||
|
@ -42,7 +42,7 @@ class SuggestedUsers(TestCase):
|
||||||
"""reverse the rank computation to get the mutuals and shared books counts"""
|
"""reverse the rank computation to get the mutuals and shared books counts"""
|
||||||
counts = suggested_users.get_counts_from_rank(3.9642857142857144)
|
counts = suggested_users.get_counts_from_rank(3.9642857142857144)
|
||||||
self.assertEqual(counts["mutuals"], 3)
|
self.assertEqual(counts["mutuals"], 3)
|
||||||
self.assertEqual(counts["shared_books"], 27)
|
# self.assertEqual(counts["shared_books"], 27)
|
||||||
|
|
||||||
def test_get_objects_for_store(self, *_):
|
def test_get_objects_for_store(self, *_):
|
||||||
"""list of people to follow for a given user"""
|
"""list of people to follow for a given user"""
|
||||||
|
@ -126,7 +126,7 @@ class SuggestedUsers(TestCase):
|
||||||
|
|
||||||
user_1_annotated = result.get(id=user_1.id)
|
user_1_annotated = result.get(id=user_1.id)
|
||||||
self.assertEqual(user_1_annotated.mutuals, 1)
|
self.assertEqual(user_1_annotated.mutuals, 1)
|
||||||
self.assertEqual(user_1_annotated.shared_books, 1)
|
# self.assertEqual(user_1_annotated.shared_books, 1)
|
||||||
|
|
||||||
def test_get_annotated_users_counts(self, *_):
|
def test_get_annotated_users_counts(self, *_):
|
||||||
"""correct counting for multiple shared attributed"""
|
"""correct counting for multiple shared attributed"""
|
||||||
|
|
|
@ -299,3 +299,16 @@ class BookViews(TestCase):
|
||||||
|
|
||||||
self.book.refresh_from_db()
|
self.book.refresh_from_db()
|
||||||
self.assertTrue(self.book.cover)
|
self.assertTrue(self.book.cover)
|
||||||
|
|
||||||
|
def test_add_description(self):
|
||||||
|
"""add a book description"""
|
||||||
|
self.local_user.groups.add(self.group)
|
||||||
|
request = self.factory.post("", {"description": "new description hi"})
|
||||||
|
request.user = self.local_user
|
||||||
|
|
||||||
|
with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
|
||||||
|
views.add_description(request, self.book.id)
|
||||||
|
|
||||||
|
self.book.refresh_from_db()
|
||||||
|
self.assertEqual(self.book.description, "new description hi")
|
||||||
|
self.assertEqual(self.book.last_edited_by, self.local_user)
|
||||||
|
|
|
@ -339,18 +339,15 @@ def set_cover_from_url(url):
|
||||||
@permission_required("bookwyrm.edit_book", raise_exception=True)
|
@permission_required("bookwyrm.edit_book", raise_exception=True)
|
||||||
def add_description(request, book_id):
|
def add_description(request, book_id):
|
||||||
"""upload a new cover"""
|
"""upload a new cover"""
|
||||||
if not request.method == "POST":
|
|
||||||
return redirect("/")
|
|
||||||
|
|
||||||
book = get_object_or_404(models.Edition, id=book_id)
|
book = get_object_or_404(models.Edition, id=book_id)
|
||||||
|
|
||||||
description = request.POST.get("description")
|
description = request.POST.get("description")
|
||||||
|
|
||||||
book.description = description
|
book.description = description
|
||||||
book.last_edited_by = request.user
|
book.last_edited_by = request.user
|
||||||
book.save()
|
book.save(update_fields=["description", "last_edited_by"])
|
||||||
|
|
||||||
return redirect("/book/%s" % book.id)
|
return redirect("book", book.id)
|
||||||
|
|
||||||
|
|
||||||
@require_POST
|
@require_POST
|
||||||
|
@ -360,7 +357,7 @@ def resolve_book(request):
|
||||||
connector = connector_manager.get_or_create_connector(remote_id)
|
connector = connector_manager.get_or_create_connector(remote_id)
|
||||||
book = connector.get_or_create_book(remote_id)
|
book = connector.get_or_create_book(remote_id)
|
||||||
|
|
||||||
return redirect("/book/%d" % book.id)
|
return redirect("book", book.id)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
|
|
@ -28,7 +28,7 @@ class Directory(View):
|
||||||
if sort == "recent":
|
if sort == "recent":
|
||||||
users = users.order_by("-last_active_date")
|
users = users.order_by("-last_active_date")
|
||||||
else:
|
else:
|
||||||
users = users.order_by("-mutuals", "-shared_books", "-last_active_date")
|
users = users.order_by("-mutuals", "-last_active_date")
|
||||||
|
|
||||||
paginated = Paginator(users, 12)
|
paginated = Paginator(users, 12)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue