phantasmobile/app/item/models.py

198 lines
6.8 KiB
Python
Raw Permalink Normal View History

2023-07-15 07:30:36 +00:00
from django.utils.timezone import datetime, timedelta
from django.utils import timezone
import json
2023-07-16 05:56:14 +00:00
import requests
import lxml.html
2023-07-15 07:30:36 +00:00
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models
2023-08-16 15:58:28 +00:00
from django.db.models.functions import ExtractWeek, ExtractYear
2023-07-15 07:30:36 +00:00
from django.urls import reverse
2023-07-24 21:00:43 +00:00
from django.utils.timesince import timesince
2023-07-15 07:30:36 +00:00
User = get_user_model()
2023-07-24 11:05:45 +00:00
2023-07-15 07:30:36 +00:00
class Settings(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
key = models.CharField(max_length=1024, unique=True)
value = models.JSONField(default=dict, editable=False)
class Item(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
title = models.CharField(max_length=1024)
2023-07-25 19:03:54 +00:00
url = models.CharField(max_length=1024, unique=True)
description = models.TextField(default="", blank=True, editable=False)
2023-10-26 15:32:01 +00:00
published = models.DateTimeField(default=None, null=True, blank=True)
2023-07-25 19:03:54 +00:00
announced = models.DateTimeField(null=True, default=None, blank=True, editable=False)
2023-07-15 07:30:36 +00:00
data = models.JSONField(default=dict, editable=False)
2023-07-25 19:03:54 +00:00
user = models.ForeignKey(User, null=True, related_name='items', on_delete=models.CASCADE)
2023-07-15 07:30:36 +00:00
2023-07-16 05:56:14 +00:00
def save(self, *args, **kwargs):
2023-09-10 12:03:52 +00:00
#if self.url and not self.data.get("url") == self.url:
if self.url:
2023-07-16 05:56:14 +00:00
self.update_data()
super().save(*args, **kwargs)
2023-07-24 11:05:45 +00:00
2023-07-15 07:30:36 +00:00
def __str__(self):
return '%s (%s)' % (self.title, self.url)
def public_comments(self):
return self.comments.exclude(published=None)
def public_comments_json(self):
comments = []
for comment in self.public_comments():
comments.append({
"name": comment.name,
"date": comment.date,
"text": comment.text,
})
return json.dumps(comments)
@classmethod
2023-10-01 07:08:09 +00:00
def all_public(cls, now=None):
2023-08-14 12:10:30 +00:00
if now is None:
2023-08-14 21:30:57 +00:00
now = timezone.make_aware(datetime.now(), timezone.get_default_timezone())
2023-07-15 07:30:36 +00:00
qs = cls.objects.exclude(published=None).filter(published__lte=now).order_by('-published')
2023-10-01 07:08:09 +00:00
archive = qs.annotate(year=ExtractYear('published')).annotate(week=ExtractWeek('published'))
return archive
@classmethod
def public(cls, now=None):
if now is None:
now = timezone.make_aware(datetime.now(), timezone.get_default_timezone())
qs = cls.all_public(now)
2023-07-15 07:30:36 +00:00
cal = now.date().isocalendar()
monday = now.date() - timedelta(days=now.date().isocalendar().weekday - 1)
monday = timezone.datetime(monday.year, monday.month, monday.day, tzinfo=now.tzinfo)
first_post = qs.filter(published__gt=monday).first()
2023-07-24 11:05:45 +00:00
if first_post and first_post.published < now:
week = qs.filter(published__gt=monday)
elif not first_post:
while qs.exists() and not first_post:
monday = monday - timedelta(days=7)
first_post = qs.filter(published__gt=monday).first()
2023-07-15 07:30:36 +00:00
week = qs.filter(published__gt=monday)
else:
last_monday = monday - timedelta(days=7)
week = qs.filter(published__gt=last_monday)
2023-10-01 07:08:09 +00:00
archive = qs.exclude(id__in=week)
2023-07-15 07:30:36 +00:00
return week, archive
2023-08-31 16:05:27 +00:00
def get_week(self):
return int(self.published.strftime('%W'))
def get_year(self):
return int(self.published.strftime('%Y'))
def get_monday(self):
d = '%s-W%s' % (self.get_year(), self.get_week())
return datetime.strptime(d + '-1', "%Y-W%W-%w").strftime('%Y-%m-%d')
2023-07-15 07:30:36 +00:00
def get_absolute_url(self):
return reverse('item', kwargs={'id': self.id})
2023-09-23 12:58:41 +00:00
def full_url(self):
return settings.URL + self.get_absolute_url()
2023-07-16 05:56:14 +00:00
def update_data(self):
self.data.update(self.parse_url())
def parse_url(self):
content = requests.get(self.url).text
doc = lxml.html.fromstring(content)
data = {}
for meta in doc.cssselect('meta'):
key = meta.attrib.get('name')
if not key:
key = meta.attrib.get('property')
value = meta.attrib.get('content')
if key and value:
if key in ('viewport', ):
continue
key = key.replace('og:', '')
data[key] = value
2023-08-16 14:52:09 +00:00
data["url"] = self.url
2023-12-01 19:45:47 +00:00
if "m/documents" in self.url:
data["type"] = "document"
2023-12-01 19:46:58 +00:00
data["thumbnail"] = data["thumbnail"].replace('/512p', '/1024p')
2023-07-16 05:56:14 +00:00
return data
2023-07-15 07:30:36 +00:00
class Comment(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
item = models.ForeignKey(Item, related_name='comments', on_delete=models.CASCADE)
2023-07-25 19:03:54 +00:00
text = models.TextField(default="")
name = models.CharField(max_length=1024, blank=True)
email = models.CharField(max_length=1024, blank=True)
2023-07-15 07:30:36 +00:00
user = models.ForeignKey(User, null=True, related_name='comments', on_delete=models.CASCADE, blank=True)
2023-07-25 19:03:54 +00:00
session_key = models.CharField(max_length=60, null=True, default=None, blank=True, editable=False)
2023-07-15 07:30:36 +00:00
data = models.JSONField(default=dict, editable=False)
2023-07-25 19:03:54 +00:00
published = models.DateTimeField(null=True, default=None, blank=True)
2023-07-15 07:30:36 +00:00
2023-07-24 11:05:45 +00:00
class Meta:
permissions = [
("can_post_comment", "Can post comments without moderation")
]
2023-07-16 05:56:14 +00:00
@property
def is_published(self):
return bool(self.published)
2023-07-15 07:30:36 +00:00
def __str__(self):
return '%s: %s' % (self.item, self.user)
def save(self, *args, **kwargs):
if self.user:
self.name = self.user.username
self.email = self.user.email
super().save(*args, **kwargs)
@property
def date(self):
2023-07-24 21:00:43 +00:00
now = timezone.now()
difference = now - self.created
if difference <= timedelta(minutes=1):
return "just now"
return '%(time)s ago' % {'time': timesince(self.created).split(', ')[0]}
return self.created.strftime('%B %d, %Y at %H:%M')
2023-07-15 07:30:36 +00:00
return self.created.strftime('%Y-%m-%d %H:%M')
def json(self):
data = {}
2023-07-24 11:05:45 +00:00
if not self.user:
data['name'] = '%s (guest)' % self.name
else:
data['name'] = self.name
2023-07-15 07:30:36 +00:00
data['date'] = self.date
data['text'] = self.text
2023-07-24 21:00:43 +00:00
data['id'] = self.id
data['published'] = self.is_published
2023-07-15 07:30:36 +00:00
return data
2023-07-24 11:05:45 +00:00
2023-08-31 17:24:52 +00:00
class Week(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
monday = models.DateField(unique=True)
2023-12-03 14:11:13 +00:00
title = models.CharField(max_length=2048, blank=True, default="")
2024-02-06 16:47:54 +00:00
byline = models.CharField(max_length=2048, blank=True, default="")
2023-11-19 13:29:39 +00:00
published = models.DateTimeField(null=True, default=None, blank=True, editable=False)
2023-08-31 17:24:52 +00:00
def __str__(self):
return "%s (%s)" % (self.title, self.monday)