comment-delete-handling-patch
All checks were successful
Deploy on push / deploy (push) Successful in 1m15s
All checks were successful
Deploy on push / deploy (push) Successful in 1m15s
This commit is contained in:
parent
354bda0efa
commit
ae48a18536
|
@ -1,3 +1,6 @@
|
|||
#### [0.4.12] - 2025-02-12
|
||||
- `delete_reaction` detects comments and uses `deleted_at` update
|
||||
|
||||
#### [0.4.11] - 2025-02-12
|
||||
- `create_draft` resolver requires draft_id fixed
|
||||
- `create_draft` resolver defaults body and title fields to empty string
|
||||
|
|
6
requirements.dev.txt
Normal file
6
requirements.dev.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
fakeredis
|
||||
pytest
|
||||
pytest-asyncio
|
||||
pytest-cov
|
||||
mypy
|
||||
ruff
|
|
@ -4,11 +4,8 @@ authlib
|
|||
passlib
|
||||
|
||||
google-analytics-data
|
||||
dogpile-cache
|
||||
opensearch-py
|
||||
colorlog
|
||||
psycopg2-binary
|
||||
dogpile-cache
|
||||
httpx
|
||||
redis[hiredis]
|
||||
sentry-sdk[starlette,sqlalchemy]
|
||||
|
@ -17,10 +14,4 @@ gql
|
|||
ariadne
|
||||
granian
|
||||
|
||||
pydantic
|
||||
fakeredis
|
||||
pytest
|
||||
pytest-asyncio
|
||||
pytest-cov
|
||||
mypy
|
||||
ruff
|
||||
pydantic
|
|
@ -1,5 +1,5 @@
|
|||
from operator import or_
|
||||
import time
|
||||
from operator import or_
|
||||
|
||||
from sqlalchemy.sql import and_
|
||||
|
||||
|
@ -56,9 +56,11 @@ async def load_drafts(_, info):
|
|||
return {"error": "User ID and author ID are required"}
|
||||
|
||||
with local_session() as session:
|
||||
drafts = session.query(Draft).filter(or_(
|
||||
Draft.authors.any(Author.id == author_id),
|
||||
Draft.created_by == author_id)).all()
|
||||
drafts = (
|
||||
session.query(Draft)
|
||||
.filter(or_(Draft.authors.any(Author.id == author_id), Draft.created_by == author_id))
|
||||
.all()
|
||||
)
|
||||
return {"drafts": drafts}
|
||||
|
||||
|
||||
|
@ -99,7 +101,7 @@ async def create_draft(_, info, draft_input):
|
|||
# Проверяем обязательные поля
|
||||
if "body" not in draft_input or not draft_input["body"]:
|
||||
draft_input["body"] = "" # Пустая строка вместо NULL
|
||||
|
||||
|
||||
if "title" not in draft_input or not draft_input["title"]:
|
||||
draft_input["title"] = "" # Пустая строка вместо NULL
|
||||
|
||||
|
@ -123,23 +125,29 @@ async def create_draft(_, info, draft_input):
|
|||
|
||||
@mutation.field("update_draft")
|
||||
@login_required
|
||||
async def update_draft(_, info, draft_input):
|
||||
async def update_draft(_, info, draft_id: int, draft_input):
|
||||
"""Обновляет черновик публикации.
|
||||
|
||||
Args:
|
||||
draft_id: ID черновика для обновления
|
||||
draft_input: Данные для обновления черновика
|
||||
|
||||
Returns:
|
||||
dict: Обновленный черновик или сообщение об ошибке
|
||||
"""
|
||||
user_id = info.context.get("user_id")
|
||||
author_dict = info.context.get("author", {})
|
||||
author_id = author_dict.get("id")
|
||||
draft_id = draft_input.get("id")
|
||||
if not draft_id:
|
||||
return {"error": "Draft ID is required"}
|
||||
|
||||
if not user_id or not author_id:
|
||||
return {"error": "Author ID are required"}
|
||||
|
||||
with local_session() as session:
|
||||
draft = session.query(Draft).filter(Draft.id == draft_id).first()
|
||||
del draft_input["id"]
|
||||
Draft.update(draft, {**draft_input})
|
||||
if not draft:
|
||||
return {"error": "Draft not found"}
|
||||
|
||||
Draft.update(draft, draft_input)
|
||||
draft.updated_at = int(time.time())
|
||||
session.commit()
|
||||
return {"draft": draft}
|
||||
|
|
|
@ -133,21 +133,18 @@ def check_to_feature(session, approver_id, reaction) -> bool:
|
|||
return False
|
||||
|
||||
|
||||
def check_to_unfeature(session, rejecter_id, reaction) -> bool:
|
||||
def check_to_unfeature(session, reaction) -> bool:
|
||||
"""
|
||||
Unfeature a shout if 20% of reactions are negative.
|
||||
|
||||
:param session: Database session.
|
||||
:param rejecter_id: Rejecter author ID.
|
||||
:param reaction: Reaction object.
|
||||
:return: True if shout should be unfeatured, else False.
|
||||
"""
|
||||
if not reaction.reply_to and is_negative(reaction.kind):
|
||||
total_reactions = (
|
||||
session.query(Reaction)
|
||||
.filter(
|
||||
Reaction.shout == reaction.shout, Reaction.kind.in_(RATING_REACTIONS), Reaction.deleted_at.is_(None)
|
||||
)
|
||||
.filter(Reaction.shout == reaction.shout, Reaction.reply_to.is_(None), Reaction.kind.in_(RATING_REACTIONS))
|
||||
.count()
|
||||
)
|
||||
|
||||
|
@ -217,7 +214,7 @@ async def _create_reaction(session, shout_id: int, is_author: bool, author_id: i
|
|||
|
||||
# Handle rating
|
||||
if r.kind in RATING_REACTIONS:
|
||||
if check_to_unfeature(session, author_id, r):
|
||||
if check_to_unfeature(session, r):
|
||||
set_unfeatured(session, shout_id)
|
||||
elif check_to_feature(session, author_id, r):
|
||||
await set_featured(session, shout_id)
|
||||
|
@ -354,7 +351,7 @@ async def update_reaction(_, info, reaction):
|
|||
|
||||
result = session.execute(reaction_query).unique().first()
|
||||
if result:
|
||||
r, author, shout, commented_stat, rating_stat = result
|
||||
r, author, _shout, commented_stat, rating_stat = result
|
||||
if not r or not author:
|
||||
return {"error": "Invalid reaction ID or unauthorized"}
|
||||
|
||||
|
@ -406,15 +403,24 @@ async def delete_reaction(_, info, reaction_id: int):
|
|||
if r.created_by != author_id and "editor" not in roles:
|
||||
return {"error": "Access denied"}
|
||||
|
||||
logger.debug(f"{user_id} user removing his #{reaction_id} reaction")
|
||||
reaction_dict = r.dict()
|
||||
session.delete(r)
|
||||
session.commit()
|
||||
|
||||
# Update author stat
|
||||
if r.kind == ReactionKind.COMMENT.value:
|
||||
r.deleted_at = int(time.time())
|
||||
update_author_stat(author.id)
|
||||
session.add(r)
|
||||
session.commit()
|
||||
elif r.kind == ReactionKind.PROPOSE.value:
|
||||
r.deleted_at = int(time.time())
|
||||
session.add(r)
|
||||
session.commit()
|
||||
# TODO: add more reaction types here
|
||||
else:
|
||||
logger.debug(f"{user_id} user removing his #{reaction_id} reaction")
|
||||
session.delete(r)
|
||||
session.commit()
|
||||
if check_to_unfeature(session, r):
|
||||
set_unfeatured(session, r.shout)
|
||||
|
||||
reaction_dict = r.dict()
|
||||
await notify_reaction(reaction_dict, "delete")
|
||||
|
||||
return {"error": None, "reaction": reaction_dict}
|
||||
|
|
Loading…
Reference in New Issue
Block a user