lib.itmens/journal/models/mark.py

203 lines
6.7 KiB
Python
Raw Normal View History

import re
import uuid
from functools import cached_property
import django.dispatch
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
from django.db import connection, models
from django.db.models import Avg, Count, Q
from django.utils import timezone
from django.utils.baseconv import base62
from django.utils.translation import gettext_lazy as _
2023-07-20 21:59:49 -04:00
from loguru import logger
from markdownx.models import MarkdownxField
from polymorphic.models import PolymorphicModel
from catalog.collection.models import Collection as CatalogCollection
from catalog.common import jsondata
from catalog.common.models import Item, ItemCategory
from catalog.common.utils import DEFAULT_ITEM_COVER, piece_cover_path
from catalog.models import *
2023-07-20 21:59:49 -04:00
from takahe.utils import Takahe
from users.models import APIdentity
from .comment import Comment
from .rating import Rating
from .review import Review
from .shelf import Shelf, ShelfLogEntry, ShelfManager, ShelfMember, ShelfType
class Mark:
"""
Holding Mark for an item on an shelf,
which is a combo object of ShelfMember, Comment, Rating and Tags.
it mimics previous mark behaviour.
"""
2023-07-20 21:59:49 -04:00
def __init__(self, owner: APIdentity, item: Item):
self.owner = owner
self.item = item
@cached_property
def shelfmember(self) -> ShelfMember:
return self.owner.shelf_manager.locate_item(self.item)
@property
def id(self) -> int | None:
return self.shelfmember.id if self.shelfmember else None
@cached_property
def shelf(self) -> Shelf | None:
return self.shelfmember.parent if self.shelfmember else None
@property
def shelf_type(self) -> ShelfType | None:
return self.shelfmember.parent.shelf_type if self.shelfmember else None
@property
def action_label(self) -> str:
2023-07-20 21:59:49 -04:00
if self.shelfmember and self.shelf_type:
return ShelfManager.get_action_label(self.shelf_type, self.item.category)
if self.comment:
return ShelfManager.get_action_label(
ShelfType.PROGRESS, self.comment.item.category
)
return ""
@property
def shelf_label(self) -> str | None:
return (
ShelfManager.get_label(self.shelf_type, self.item.category)
2023-07-20 21:59:49 -04:00
if self.shelf_type
else None
)
@property
def created_time(self):
return self.shelfmember.created_time if self.shelfmember else None
@property
def metadata(self) -> dict | None:
return self.shelfmember.metadata if self.shelfmember else None
@property
def visibility(self) -> int:
2023-07-20 21:59:49 -04:00
if self.shelfmember:
return self.shelfmember.visibility
else:
logger.warning(f"no shelfmember for mark {self.owner}, {self.item}")
return 2
@cached_property
def tags(self) -> list[str]:
return self.owner.tag_manager.get_item_tags(self.item)
2023-07-20 21:59:49 -04:00
@cached_property
def rating(self):
return Rating.objects.filter(owner=self.owner, item=self.item).first()
@cached_property
def rating_grade(self) -> int | None:
2023-07-20 21:59:49 -04:00
return Rating.get_item_rating(self.item, self.owner)
@cached_property
def comment(self) -> Comment | None:
return Comment.objects.filter(owner=self.owner, item=self.item).first()
@property
def comment_text(self) -> str | None:
return (self.comment.text or None) if self.comment else None
@property
def comment_html(self) -> str | None:
return self.comment.html if self.comment else None
@cached_property
def review(self) -> Review | None:
return Review.objects.filter(owner=self.owner, item=self.item).first()
def update(
self,
2023-07-20 21:59:49 -04:00
shelf_type,
comment_text,
rating_grade,
visibility,
metadata=None,
created_time=None,
share_to_mastodon=False,
):
2023-07-20 21:59:49 -04:00
post_to_feed = shelf_type is not None and (
shelf_type != self.shelf_type
or comment_text != self.comment_text
or rating_grade != self.rating_grade
)
2023-07-20 21:59:49 -04:00
if shelf_type is None:
Takahe.delete_mark(self)
if created_time and created_time >= timezone.now():
created_time = None
2023-07-20 21:59:49 -04:00
post_as_new = shelf_type != self.shelf_type
original_visibility = self.visibility
if shelf_type != self.shelf_type or visibility != original_visibility:
self.shelfmember = self.owner.shelf_manager.move_item(
self.item,
shelf_type,
visibility=visibility,
metadata=metadata,
)
2023-07-20 21:59:49 -04:00
if self.shelfmember and created_time:
# if it's an update(not delete) and created_time is specified,
# update the timestamp of the shelfmember and log
log = ShelfLogEntry.objects.filter(
owner=self.owner,
item=self.item,
timestamp=self.shelfmember.created_time,
).first()
self.shelfmember.created_time = created_time
self.shelfmember.save(update_fields=["created_time"])
if log:
log.timestamp = created_time
log.save(update_fields=["timestamp"])
else:
ShelfLogEntry.objects.create(
owner=self.owner,
shelf_type=shelf_type,
item=self.item,
metadata=self.metadata,
timestamp=created_time,
)
if comment_text != self.comment_text or visibility != original_visibility:
2023-07-20 21:59:49 -04:00
self.comment = Comment.comment_item(
self.item,
self.owner,
comment_text,
visibility,
self.shelfmember.created_time if self.shelfmember else None,
)
if rating_grade != self.rating_grade or visibility != original_visibility:
2023-07-20 21:59:49 -04:00
Rating.update_item_rating(self.item, self.owner, rating_grade, visibility)
self.rating_grade = rating_grade
2023-07-20 21:59:49 -04:00
if post_to_feed:
Takahe.post_mark(self, post_as_new)
def delete(self):
# self.logs.delete() # When deleting a mark, all logs of the mark are deleted first.
2023-07-20 21:59:49 -04:00
self.update(None, None, None, 0)
def delete_log(self, log_id):
ShelfLogEntry.objects.filter(
owner=self.owner, item=self.item, id=log_id
).delete()
def delete_all_logs(self):
self.logs.delete()
@property
def logs(self):
return ShelfLogEntry.objects.filter(owner=self.owner, item=self.item).order_by(
"timestamp"
)