lib.itmens/journal/models/comment.py

170 lines
5.7 KiB
Python
Raw Permalink Normal View History

2023-07-20 21:59:49 -04:00
from datetime import datetime
from functools import cached_property
2024-12-30 01:51:19 -05:00
from typing import Any
2024-06-14 00:17:27 -04:00
from django.conf import settings
from django.db import models
from django.utils import timezone
2024-06-14 00:17:27 -04:00
from django.utils.translation import gettext as _
from catalog.models import Item
2024-06-13 20:44:15 -04:00
from takahe.utils import Takahe
2023-07-20 21:59:49 -04:00
from users.models import APIdentity
from .common import Content
from .rating import Rating
2024-07-05 16:26:26 -04:00
from .renderers import render_post_with_macro, render_spoiler_text, render_text
2024-06-14 00:17:27 -04:00
from .shelf import ShelfManager, ShelfType
class Comment(Content):
text = models.TextField(blank=False, null=False)
2023-07-20 21:59:49 -04:00
@property
def ap_object(self):
2023-11-19 15:19:49 -05:00
d = {
2023-07-20 21:59:49 -04:00
"id": self.absolute_url,
"type": "Comment",
"content": self.text,
"published": self.created_time.isoformat(),
"updated": self.edited_time.isoformat(),
"attributedTo": self.owner.actor_uri,
2023-11-28 08:45:04 -05:00
"withRegardTo": self.item.absolute_url,
"href": self.absolute_url,
2023-07-20 21:59:49 -04:00
}
2023-11-19 15:19:49 -05:00
if self.metadata.get("position"):
d["relatedWithItemPosition"] = self.metadata["position"]
d["relatedWithItemPositionType"] = "time"
return d
2023-07-20 21:59:49 -04:00
@classmethod
2025-01-19 16:04:22 -05:00
def update_by_ap_object(cls, owner, item, obj, post, crosspost=None):
2025-02-03 17:20:35 -05:00
if post.local: # ignore local user updating their post via Mastodon API
return
2023-11-20 19:11:02 -05:00
p = cls.objects.filter(owner=owner, item=item).first()
if p and p.edited_time >= datetime.fromisoformat(obj["updated"]):
return p # incoming ap object is older than what we have, no update needed
2023-07-20 21:59:49 -04:00
content = obj.get("content", "").strip() if obj else ""
if not content:
cls.objects.filter(owner=owner, item=item).delete()
return
d = {
"text": content,
"local": False,
"remote_id": obj["id"],
2024-06-13 20:44:15 -04:00
"visibility": Takahe.visibility_t2n(post.visibility),
2023-07-20 21:59:49 -04:00
"created_time": datetime.fromisoformat(obj["published"]),
"edited_time": datetime.fromisoformat(obj["updated"]),
}
2023-11-19 15:19:49 -05:00
if obj.get("relatedWithItemPosition"):
d["metadata"] = {"position": obj["relatedWithItemPosition"]}
2023-07-20 21:59:49 -04:00
p, _ = cls.objects.update_or_create(owner=owner, item=item, defaults=d)
2024-06-13 20:44:15 -04:00
p.link_post_id(post.id)
2023-07-20 21:59:49 -04:00
return p
@property
def html(self):
return render_text(self.text)
@cached_property
def rating_grade(self):
2023-07-20 21:59:49 -04:00
return Rating.get_item_rating(self.item, self.owner)
@cached_property
def mark(self):
from .mark import Mark
m = Mark(self.owner, self.item)
m.comment = self
return m
@property
def item_url(self):
if self.metadata.get("position"):
2023-11-19 15:19:49 -05:00
return self.item.get_url_with_position(self.metadata["position"])
else:
return self.item.url
@staticmethod
2023-07-20 21:59:49 -04:00
def comment_item(
item: Item, owner: APIdentity, text: str | None, visibility=0, created_time=None
):
2023-07-20 21:59:49 -04:00
comment = Comment.objects.filter(owner=owner, item=item).first()
if not text:
if comment is not None:
comment.delete()
comment = None
elif comment is None:
comment = Comment.objects.create(
2023-07-20 21:59:49 -04:00
owner=owner,
item=item,
text=text,
visibility=visibility,
created_time=created_time or timezone.now(),
)
elif comment.text != text or comment.visibility != visibility:
comment.text = text
comment.visibility = visibility
if created_time:
comment.created_time = created_time
comment.save()
return comment
2024-06-14 00:17:27 -04:00
2024-06-16 21:54:20 -04:00
def get_crosspost_postfix(self):
2024-06-14 00:17:27 -04:00
tags = render_post_with_macro(
self.owner.user.preference.mastodon_append_tag, self.item
)
return "\n" + tags if tags else ""
2024-06-16 21:54:20 -04:00
def get_crosspost_template(self):
2024-06-14 00:17:27 -04:00
return _(
ShelfManager.get_action_template(ShelfType.PROGRESS, self.item.category)
)
2024-07-03 16:42:20 -04:00
def to_crosspost_params(self):
2024-06-14 00:17:27 -04:00
spoiler_text, txt = render_spoiler_text(self.text, self.item)
2024-07-05 16:26:26 -04:00
txt = "\n" + txt if txt else ""
action = self.get_crosspost_template().format(item="##obj##")
content = f"{action}\n##obj_link_if_plain##{txt}{self.get_crosspost_postfix()}"
2024-06-14 00:17:27 -04:00
params = {
"content": content,
"spoiler_text": spoiler_text,
"sensitive": bool(spoiler_text),
2024-07-05 16:26:26 -04:00
"obj": self.item,
2024-06-14 00:17:27 -04:00
}
return params
def to_post_params(self):
item_link = f"{settings.SITE_INFO['site_url']}/~neodb~{self.item_url}"
2024-06-15 21:54:39 -04:00
prepend_content = (
2024-06-16 21:54:20 -04:00
self.get_crosspost_template().format(
2024-06-14 00:17:27 -04:00
item=f'<a href="{item_link}">{self.item.display_title}</a>'
)
+ "<br>"
)
spoiler_text, txt = render_spoiler_text(self.text, self.item)
2024-06-16 21:54:20 -04:00
content = f"{txt}\n{self.get_crosspost_postfix()}"
2024-06-14 00:17:27 -04:00
return {
2024-06-15 21:54:39 -04:00
"prepend_content": prepend_content,
2024-06-14 00:17:27 -04:00
"content": content,
"summary": spoiler_text,
"sensitive": bool(spoiler_text),
}
2024-12-30 01:51:19 -05:00
@cached_property
def sibling_shelfmember(self):
from .shelf import ShelfMember
return ShelfMember.objects.filter(owner=self.owner, item=self.item).first()
def to_indexable_doc(self) -> dict[str, Any]:
if self.sibling_shelfmember:
return {}
return {
"item_id": [self.item.id],
"item_class": [self.item.__class__.__name__],
"item_title": self.item.to_indexable_titles(),
"rating": self.rating_grade or 0,
"content": [self.text],
}