from django.conf import settings from django.db import models from apps.core.models import Audience, TimeStampedModel from apps.library.models import LibraryItem class MomentQuerySet(models.QuerySet): def visible_to(self, user): """FAMILY and CUSTOM audiences intentionally fall back to owner-only visibility until circles/custom-audience membership (V1.5) exists — better to under-share than leak content.""" from apps.accounts.models import Follow following_ids = Follow.objects.filter( follower=user, status=Follow.Status.ACCEPTED ).values_list("following_id", flat=True) follower_ids = set( Follow.objects.filter( following=user, status=Follow.Status.ACCEPTED ).values_list("follower_id", flat=True) ) friend_ids = follower_ids & set(following_ids) return self.filter( models.Q(owner=user) | models.Q(audience=Audience.PUBLIC) | models.Q(audience=Audience.FOLLOWERS, owner_id__in=following_ids) | models.Q(audience=Audience.FRIENDS, owner_id__in=friend_ids) ).distinct() class Moment(TimeStampedModel): """The social-media object: one or more LibraryItems shared with an explicit audience. Sharing a Moment never moves or copies the original file — it just makes the existing library item visible to others.""" owner = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="moments", on_delete=models.CASCADE) caption = models.TextField(max_length=2200, blank=True) location = models.CharField(max_length=255, blank=True) audience = models.CharField(max_length=10, choices=Audience.choices, default=Audience.PUBLIC) objects = MomentQuerySet.as_manager() class Meta: ordering = ["-created_at"] def __str__(self): return f"Moment({self.id}) by {self.owner}" class MomentItem(models.Model): moment = models.ForeignKey(Moment, related_name="items", on_delete=models.CASCADE) library_item = models.ForeignKey(LibraryItem, related_name="moment_items", on_delete=models.CASCADE) order = models.PositiveIntegerField(default=0) class Meta: ordering = ["order"] unique_together = ("moment", "library_item") class Comment(TimeStampedModel): moment = models.ForeignKey(Moment, related_name="comments", on_delete=models.CASCADE) author = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="comments", on_delete=models.CASCADE) parent = models.ForeignKey("self", related_name="replies", on_delete=models.CASCADE, null=True, blank=True) body = models.TextField(max_length=1000) class Meta: ordering = ["created_at"] def __str__(self): return f"{self.author}: {self.body[:40]}" class Reaction(models.Model): class ReactionType(models.TextChoices): LIKE = "like", "Like" moment = models.ForeignKey(Moment, related_name="reactions", on_delete=models.CASCADE) user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="reactions", on_delete=models.CASCADE) reaction_type = models.CharField(max_length=10, choices=ReactionType.choices, default=ReactionType.LIKE) created_at = models.DateTimeField(auto_now_add=True) class Meta: unique_together = ("moment", "user")