Compare commits
2 Commits
41f9be4c7e
...
36aef98986
| Author | SHA1 | Date | |
|---|---|---|---|
| 36aef98986 | |||
| 029f0c7b8d |
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import mimetypes
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
@@ -39,12 +40,14 @@ from apps.blog.permissions import (
|
||||
can_review_blog_posts,
|
||||
can_write_blog_posts,
|
||||
)
|
||||
from apps.notifications.services import notify_user
|
||||
from core.api.schemas import ErrorSchema, MessageSchema
|
||||
from core.authentication import jwt_auth
|
||||
|
||||
|
||||
blog_router = Router()
|
||||
User = get_user_model()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
IMAGE_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp", ".tiff", ".svg"}
|
||||
VIDEO_EXTENSIONS = {".mp4", ".webm", ".ogg", ".mov", ".mkv", ".avi"}
|
||||
@@ -240,6 +243,73 @@ def _interaction_payload(post: Post, user) -> BlogInteractionSchema:
|
||||
)
|
||||
|
||||
|
||||
def _frontend_blog_url(post: Post) -> str:
|
||||
root = getattr(settings, "FRONTEND_ROOT", "/") or "/"
|
||||
if not root.endswith("/"):
|
||||
root = f"{root}/"
|
||||
return f"{root}blog/{post.slug}"
|
||||
|
||||
|
||||
def _blog_moderator_ids() -> set[int]:
|
||||
return set(
|
||||
User.objects.filter(is_active=True)
|
||||
.filter(
|
||||
Q(is_staff=True)
|
||||
| Q(is_superuser=True)
|
||||
| Q(groups__permissions__content_type__app_label="blog", groups__permissions__codename="moderate_blog_comment")
|
||||
| Q(user_permissions__content_type__app_label="blog", user_permissions__codename="moderate_blog_comment")
|
||||
)
|
||||
.distinct()
|
||||
.values_list("id", flat=True)
|
||||
)
|
||||
|
||||
|
||||
def _post_author_ids(post: Post) -> set[int]:
|
||||
author_ids = set(post.writers.values_list("id", flat=True))
|
||||
if post.author_id:
|
||||
author_ids.add(post.author_id)
|
||||
return author_ids
|
||||
|
||||
|
||||
def _notify_blog_comment(comment: Comment) -> None:
|
||||
post = comment.post
|
||||
actor_id = comment.author_id
|
||||
action_url = _frontend_blog_url(post)
|
||||
excluded_ids = {actor_id}
|
||||
|
||||
if comment.parent_id and comment.parent.author_id != actor_id:
|
||||
notify_user(
|
||||
comment.parent.author_id,
|
||||
{
|
||||
"type": "blog_reply",
|
||||
"title": "پاسخ جدید",
|
||||
"message": f"به کامنت شما در «{post.title}» پاسخ داده شد.",
|
||||
"level": "info",
|
||||
"action_url": action_url,
|
||||
"entity_type": "blog_comment",
|
||||
"entity_id": comment.id,
|
||||
"meta": {"post_id": post.id, "post_slug": post.slug, "parent_id": comment.parent_id},
|
||||
},
|
||||
)
|
||||
excluded_ids.add(comment.parent.author_id)
|
||||
|
||||
recipient_ids = (_blog_moderator_ids() | _post_author_ids(post)) - excluded_ids
|
||||
for user_id in recipient_ids:
|
||||
notify_user(
|
||||
user_id,
|
||||
{
|
||||
"type": "blog_comment",
|
||||
"title": "کامنت جدید",
|
||||
"message": f"برای «{post.title}» کامنت جدید ثبت شد.",
|
||||
"level": "info",
|
||||
"action_url": action_url,
|
||||
"entity_type": "blog_post",
|
||||
"entity_id": post.id,
|
||||
"meta": {"post_id": post.id, "post_slug": post.slug, "comment_id": comment.id},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@blog_router.get("/admin/writers", response={200: List[AuthorSchema], 403: ErrorSchema}, auth=jwt_auth)
|
||||
def list_blog_writers(request):
|
||||
if not (request.auth.is_superuser or request.auth.is_staff or can_review_blog_posts(request.auth)):
|
||||
@@ -437,16 +507,23 @@ def delete_post_asset(request, post_id: int, asset_id: int):
|
||||
@blog_router.get("/me/activity", response=BlogProfileActivitySchema, auth=jwt_auth)
|
||||
def my_blog_activity(request):
|
||||
comments = (
|
||||
Comment.objects.filter(author=request.auth)
|
||||
Comment.objects.filter(
|
||||
author=request.auth,
|
||||
is_approved=True,
|
||||
is_hidden=False,
|
||||
is_deleted=False,
|
||||
post__status=Post.StatusChoices.PUBLISHED,
|
||||
post__is_deleted=False,
|
||||
)
|
||||
.select_related("author", "post")
|
||||
.order_by("-created_at")[:20]
|
||||
)
|
||||
return BlogProfileActivitySchema(
|
||||
liked_posts=list(_published_queryset().filter(likes__user=request.auth)[:20]),
|
||||
saved_posts=list(_published_queryset().filter(saves__user=request.auth)[:20]),
|
||||
comments=list([comment for comment in comments if comment.parent_id is None]),
|
||||
replies=list([comment for comment in comments if comment.parent_id is not None]),
|
||||
)
|
||||
return {
|
||||
"liked_posts": list(_published_queryset().filter(likes__user=request.auth)[:20]),
|
||||
"saved_posts": list(_published_queryset().filter(saves__user=request.auth)[:20]),
|
||||
"comments": [comment for comment in comments if comment.parent_id is None],
|
||||
"replies": [comment for comment in comments if comment.parent_id is not None],
|
||||
}
|
||||
|
||||
|
||||
@blog_router.get("/banners", response=List[BlogBannerSchema])
|
||||
@@ -619,6 +696,10 @@ def create_comment(request, slug: str, data: CommentCreateSchema):
|
||||
if data.parent_id:
|
||||
parent = get_object_or_404(Comment, id=data.parent_id, post=post, is_approved=True, is_hidden=False, is_deleted=False)
|
||||
comment = Comment.objects.create(post=post, author=request.auth, content=data.content, parent=parent)
|
||||
try:
|
||||
_notify_blog_comment(comment)
|
||||
except Exception:
|
||||
logger.exception("Failed to send blog comment notifications for comment=%s", comment.id)
|
||||
return 201, comment
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user