remove unused code

This commit is contained in:
Your Name 2025-02-22 15:49:41 -05:00 committed by Henri Dickson
parent db7ef50116
commit 6f0217f91c
10 changed files with 1320 additions and 1378 deletions

View file

@ -6,8 +6,4 @@ class SocialConfig(AppConfig):
name = "social" name = "social"
def ready(self): def ready(self):
# load key modules in proper order, make sure class inject and signal works as expected pass
from catalog import models as catalog_models # noqa
from catalog import sites as catalog_sites # noqa
from journal import models as journal_models # noqa
from social import models as social_models # noqa

View file

@ -6,23 +6,11 @@ ActivityManager generates chronological view for user and, in future, ActivitySt
""" """
from typing import Type
from django.conf import settings
from django.db import models from django.db import models
from django.db.models import Q
from django.db.models.signals import post_save, pre_delete
from django.utils import timezone from django.utils import timezone
from loguru import logger
from journal.models import ( from journal.models import (
Collection,
Comment,
FeaturedCollection,
Like,
Piece, Piece,
Review,
ShelfMember,
UserOwnedObjectMixin, UserOwnedObjectMixin,
) )
from users.models import APIdentity from users.models import APIdentity
@ -53,151 +41,3 @@ class LocalActivity(models.Model, UserOwnedObjectMixin):
def __str__(self): def __str__(self):
return f"Activity [{self.owner}:{self.template}:{self.action_object}]" return f"Activity [{self.owner}:{self.template}:{self.action_object}]"
class ActivityManager:
def __init__(self, owner: APIdentity):
self.owner = owner
def get_timeline(self, before_time=None):
following = [x for x in self.owner.following if x not in self.owner.muting]
q = Q(owner_id__in=following, visibility__lt=2) | Q(owner=self.owner)
if before_time:
q = q & Q(created_time__lt=before_time)
return (
LocalActivity.objects.filter(q)
.order_by("-created_time")
.prefetch_related("action_object", "owner")
) # .select_related() https://github.com/django-polymorphic/django-polymorphic/pull/531
@staticmethod
def get_manager_for_user(user):
return ActivityManager(user)
class DataSignalManager:
processors = {}
@staticmethod
def save_handler(sender, instance, created, **kwargs):
processor_class = DataSignalManager.processors.get(instance.__class__)
if processor_class:
processor = processor_class(instance)
if created:
if hasattr(processor, "created"):
processor.created()
elif hasattr(processor, "updated"):
processor.updated()
@staticmethod
def delete_handler(sender, instance, **kwargs):
processor_class = DataSignalManager.processors.get(instance.__class__)
if processor_class:
processor = processor_class(instance)
if hasattr(processor, "deleted"):
processor.deleted()
@staticmethod
def add_handler_for_model(model):
if settings.DISABLE_MODEL_SIGNAL:
logger.warning(
f"{model.__name__} are not being indexed with DISABLE_MODEL_SIGNAL configuration"
)
return
post_save.connect(DataSignalManager.save_handler, sender=model)
pre_delete.connect(DataSignalManager.delete_handler, sender=model)
@staticmethod
def register(processor):
DataSignalManager.add_handler_for_model(processor.model)
DataSignalManager.processors[processor.model] = processor
return processor
class DefaultActivityProcessor:
model: Type[Piece]
template: ActivityTemplate
def __init__(self, action_object):
self.action_object = action_object
def created(self):
params = {
"owner": self.action_object.owner,
"visibility": self.action_object.visibility,
"template": self.template,
"action_object": self.action_object,
"created_time": self.action_object.created_time,
}
LocalActivity.objects.create(**params)
def updated(self):
activity = LocalActivity.objects.filter(
action_object=self.action_object
).first()
if not activity:
self.created()
elif (
activity.visibility != self.action_object.visibility
or activity.created_time != activity.action_object.created_time
):
activity.visibility = self.action_object.visibility
activity.created_time = activity.action_object.created_time
activity.save()
@DataSignalManager.register
class MarkProcessor(DefaultActivityProcessor):
model = ShelfMember
template = ActivityTemplate.MarkItem
@DataSignalManager.register
class ReviewProcessor(DefaultActivityProcessor):
model = Review
template = ActivityTemplate.ReviewItem
@DataSignalManager.register
class CollectionProcessor(DefaultActivityProcessor):
model = Collection
template = ActivityTemplate.CreateCollection
@DataSignalManager.register
class LikeCollectionProcessor(DefaultActivityProcessor):
model = Like
template = ActivityTemplate.LikeCollection
def created(self):
if isinstance(self.action_object.target, Collection):
super().created()
def updated(self):
if isinstance(self.action_object.target, Collection):
super().updated()
@DataSignalManager.register
class FeaturedCollectionProcessor(DefaultActivityProcessor):
model = FeaturedCollection
template = ActivityTemplate.FeatureCollection
@DataSignalManager.register
class CommentChildItemProcessor(DefaultActivityProcessor):
model = Comment
template = ActivityTemplate.CommentChildItem
def created(self):
if self.action_object.item.class_name in ["podcastepisode", "tvepisode"]:
super().created()
def updated(self):
if self.action_object.item.class_name in ["podcastepisode", "tvepisode"]:
super().updated()
def reset_social_visibility_for_user(owner: APIdentity, visibility: int):
LocalActivity.objects.filter(owner=owner).update(visibility=visibility)

View file

@ -1,79 +1,4 @@
from django.test import TestCase
from catalog.models import * from catalog.models import *
from journal.models import * from journal.models import *
from takahe.utils import Takahe
from users.models import User
from .models import * from .models import *
class SocialTest(TestCase):
databases = "__all__"
def setUp(self):
self.book1 = Edition.objects.create(title="Hyperion")
self.book2 = Edition.objects.create(title="Andymion")
self.movie = Edition.objects.create(title="Fight Club")
self.alice = User.register(username="Alice")
self.bob = User.register(username="Bob")
def test_timeline(self):
alice_feed = self.alice.identity.activity_manager
bob_feed = self.bob.identity.activity_manager
# alice see 0 activity in timeline in the beginning
self.assertEqual(len(alice_feed.get_timeline()), 0)
# 1 activity after adding first book to shelf
Mark(self.alice.identity, self.book1).update(ShelfType.WISHLIST, visibility=1)
self.assertEqual(len(alice_feed.get_timeline()), 1)
# 2 activities after adding second book to shelf
Mark(self.alice.identity, self.book2).update(ShelfType.WISHLIST)
self.assertEqual(len(alice_feed.get_timeline()), 2)
# 2 activities after change first mark
Mark(self.alice.identity, self.book1).update(ShelfType.PROGRESS)
self.assertEqual(len(alice_feed.get_timeline()), 2)
# bob see 0 activity in timeline in the beginning
self.assertEqual(len(bob_feed.get_timeline()), 0)
# bob follows alice, see 2 activities
self.bob.identity.follow(self.alice.identity)
Takahe._force_state_cycle()
self.assertEqual(len(bob_feed.get_timeline()), 2)
# bob mute, then unmute alice
self.bob.identity.mute(self.alice.identity)
Takahe._force_state_cycle()
self.assertEqual(len(bob_feed.get_timeline()), 0)
self.bob.identity.unmute(self.alice.identity)
Takahe._force_state_cycle()
self.assertEqual(len(bob_feed.get_timeline()), 2)
# alice:3 bob:2 after alice adding second book to shelf as private
Mark(self.alice.identity, self.movie).update(ShelfType.WISHLIST, visibility=2)
self.assertEqual(len(alice_feed.get_timeline()), 3)
self.assertEqual(len(bob_feed.get_timeline()), 2)
# alice mute bob
self.alice.identity.mute(self.bob.identity)
Takahe._force_state_cycle()
self.assertEqual(len(bob_feed.get_timeline()), 2)
# bob unfollow alice
self.bob.identity.unfollow(self.alice.identity)
Takahe._force_state_cycle()
self.assertEqual(len(bob_feed.get_timeline()), 0)
# bob follow alice
self.bob.identity.follow(self.alice.identity)
Takahe._force_state_cycle()
self.assertEqual(len(bob_feed.get_timeline()), 2)
# alice block bob
self.alice.identity.block(self.bob.identity)
Takahe._force_state_cycle()
self.assertEqual(len(bob_feed.get_timeline()), 0)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,80 @@
{
"kind": "books#volume",
"id": "hV--zQEACAAJ",
"etag": "9e1D4OyyGmU",
"selfLink": "https://www.googleapis.com/books/v1/volumes/hV--zQEACAAJ",
"volumeInfo": {
"title": "1984 Nineteen Eighty-Four",
"subtitle": "New Annotated Edition from the Author of Animal Farm",
"authors": [
"George. Orwell"
],
"publisher": "Alma Classics",
"publishedDate": "2021-01-07",
"description": "In 1984, London is a grim city in the totalitarian state of Oceania where Big Brother is always watching you and the Thought Police can practically read your mind. Winston Smith is a man in grave danger for the simple reason that his memory still functions. Drawn into a forbidden love affair, Winston finds the courage to join a secret revolutionary organization called The Brotherhood, dedicated to the destruction of the Party. Together with his beloved Julia, he hazards his life in a deadly match against the powers that be.Lionel Trilling said of Orwell's masterpiece \" 1984 is a profound, terrifying, and wholly fascinating book. It is a fantasy of the political future, and like any such fantasy, serves its author as a magnifying device for an examination of the present.\" Though the year 1984 now exists in the past, Orwell's novel remains an urgent call for the individual willing to speak truth to power.\"",
"industryIdentifiers": [
{
"type": "ISBN_10",
"identifier": "1847498574"
},
{
"type": "ISBN_13",
"identifier": "9781847498571"
}
],
"readingModes": {
"text": false,
"image": false
},
"pageCount": 283,
"printedPageCount": 283,
"dimensions": {
"height": "19.90 cm",
"width": "13.10 cm",
"thickness": "2.20 cm"
},
"printType": "BOOK",
"categories": [
"Fiction / General",
"Fiction / Classics",
"Fiction / Literary",
"Fiction / Dystopian"
],
"maturityRating": "NOT_MATURE",
"allowAnonLogging": false,
"contentVersion": "preview-1.0.0",
"panelizationSummary": {
"containsEpubBubbles": false,
"containsImageBubbles": false
},
"imageLinks": {
"smallThumbnail": "http://books.google.com/books/content?id=hV--zQEACAAJ&printsec=frontcover&img=1&zoom=5&imgtk=AFLRE71rG2gupVl5iShQ_tWzZOjjkMPO8F0ulE49c0OqwP0yueVuCMbTez34n7I-jGYQAuQMMnedDyz88THNNh2i5B86Zq4l6n2bM4WorOFjtQ1iSnrrx2QRsdi4-rTVBipXfq8OiKBC&source=gbs_api",
"thumbnail": "http://books.google.com/books/content?id=hV--zQEACAAJ&printsec=frontcover&img=1&zoom=1&imgtk=AFLRE73L1GhdQ3fapYb_60j7J-5YQ4EDIi0uB8LU0NFNn65fFdSBTTSVsQ-U8RwhpQynrLW8YotLXYdNTg6rPg8FWXdl_AiFY2009Ye4tkaO7Xwn62IJwTcTNdhYAqNKg0_W_WEZB6sc&source=gbs_api"
},
"language": "en",
"previewLink": "http://books.google.com/books?id=hV--zQEACAAJ&hl=&source=gbs_api",
"infoLink": "https://play.google.com/store/books/details?id=hV--zQEACAAJ&source=gbs_api",
"canonicalVolumeLink": "https://play.google.com/store/books/details?id=hV--zQEACAAJ"
},
"saleInfo": {
"country": "US",
"saleability": "NOT_FOR_SALE",
"isEbook": false
},
"accessInfo": {
"country": "US",
"viewability": "NO_PAGES",
"embeddable": false,
"publicDomain": false,
"textToSpeechPermission": "ALLOWED",
"epub": {
"isAvailable": false
},
"pdf": {
"isAvailable": false
},
"webReaderLink": "http://play.google.com/books/reader?id=hV--zQEACAAJ&hl=&source=gbs_api",
"accessViewStatus": "NONE",
"quoteSharingAllowed": false
}
}

View file

@ -273,12 +273,6 @@ class APIdentity(models.Model):
else: else:
raise cls.DoesNotExist(f"Identity handle invalid {handler}") raise cls.DoesNotExist(f"Identity handle invalid {handler}")
@cached_property
def activity_manager(self):
from social.models import ActivityManager
return ActivityManager(self)
@cached_property @cached_property
def shelf_manager(self): def shelf_manager(self):
from journal.models import ShelfManager from journal.models import ShelfManager

View file

@ -299,12 +299,6 @@ class User(AbstractUser):
return Takahe.get_announcements_for_user(self) return Takahe.get_announcements_for_user(self)
@property
def activity_manager(self):
if not self.identity:
raise ValueError("User has no identity")
return self.identity.activity_manager
@property @property
def shelf_manager(self): def shelf_manager(self):
if not self.identity: if not self.identity:

View file

@ -25,7 +25,6 @@ urlpatterns = [
sync_mastodon_preference, sync_mastodon_preference,
name="sync_mastodon_preference", name="sync_mastodon_preference",
), ),
path("data/reset_visibility", reset_visibility, name="reset_visibility"),
path("data/clear_data", clear_data, name="clear_data"), path("data/clear_data", clear_data, name="clear_data"),
path("preferences", preferences, name="preferences"), path("preferences", preferences, name="preferences"),
path("logout", logout, name="logout"), path("logout", logout, name="logout"),

View file

@ -19,8 +19,7 @@ from journal.importers import (
LetterboxdImporter, LetterboxdImporter,
OPMLImporter, OPMLImporter,
) )
from journal.models import ShelfType, reset_journal_visibility_for_user from journal.models import ShelfType
from social.models import reset_social_visibility_for_user
from takahe.utils import Takahe from takahe.utils import Takahe
from users.models import Task from users.models import Task
@ -238,17 +237,6 @@ def sync_mastodon_preference(request):
return redirect(reverse("users:info")) return redirect(reverse("users:info"))
@login_required
def reset_visibility(request):
if request.method == "POST":
visibility = int(request.POST.get("visibility"))
visibility = visibility if visibility >= 0 and visibility <= 2 else 0
reset_journal_visibility_for_user(request.user.identity, visibility)
reset_social_visibility_for_user(request.user.identity, visibility)
messages.add_message(request, messages.INFO, _("Reset completed."))
return redirect(reverse("users:data"))
@login_required @login_required
def import_goodreads(request): def import_goodreads(request):
if request.method == "POST": if request.method == "POST":