import uuid from django.contrib.auth.models import User from django.db import models from django.urls import reverse from django.utils import timezone def gen_message_id(): """Generate a time-based identifier for use in "In-Reply-To" header.""" return f'<{uuid.uuid1()}@sfconservancy.org>' class Candidate(models.Model): """A source/binary release we'd like to verify CCS status of.""" name = models.CharField('Candidate name', max_length=50) slug = models.SlugField(max_length=50, unique=True) vendor = models.CharField('Vendor name', max_length=50) device = models.CharField('Device name', max_length=50) release_date = models.DateField(null=True, blank=True) description = models.TextField(blank=True) source_url = models.URLField() binary_url = models.URLField(blank=True) ordering = models.SmallIntegerField(default=0) email_message_id = models.CharField(max_length=255, default=gen_message_id) class Meta: ordering = ['ordering', 'name'] def __str__(self): return self.name def get_absolute_url(self): return reverse('usethesource:candidate', kwargs={'slug': self.slug}) class Comment(models.Model): """A comment about experiences or learnings building the candidate.""" candidate = models.ForeignKey(Candidate, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.PROTECT) time = models.DateTimeField(default=timezone.now) message = models.TextField() email_message_id = models.CharField(max_length=255, default=gen_message_id) def __str__(self): return f'{self.id}: {self.candidate.name}, {self.user}, {self.time}' def _find_previous_comment(self): try: return self.__class__.objects.filter(candidate=self.candidate, id__lt=self.id).latest('id') except self.__class__.DoesNotExist: return None def in_reply_to(self): """Determine the message_id of the previous comment or the candidate. Used for email threading. """ if prev_comment := self._find_previous_comment(): return prev_comment.email_message_id else: return self.candidate.email_message_id class Meta: ordering = ['id']