This commit is contained in:
parent
1b43f742d3
commit
3f1ef8dfd8
|
@ -6,8 +6,6 @@ from sqlalchemy.sql.functions import coalesce
|
||||||
|
|
||||||
from cache.cache import cache_author, cache_topic
|
from cache.cache import cache_author, cache_topic
|
||||||
from orm.author import Author
|
from orm.author import Author
|
||||||
from orm.rating import is_negative, is_positive
|
|
||||||
from orm.reaction import Reaction, ReactionKind
|
|
||||||
from orm.shout import Shout, ShoutAuthor, ShoutTopic
|
from orm.shout import Shout, ShoutAuthor, ShoutTopic
|
||||||
from orm.topic import Topic
|
from orm.topic import Topic
|
||||||
from resolvers.follower import follow, unfollow
|
from resolvers.follower import follow, unfollow
|
||||||
|
@ -17,7 +15,6 @@ from services.db import local_session
|
||||||
from services.notify import notify_shout
|
from services.notify import notify_shout
|
||||||
from services.schema import mutation, query
|
from services.schema import mutation, query
|
||||||
from services.search import search_service
|
from services.search import search_service
|
||||||
from utils.diff import apply_diff, get_diff
|
|
||||||
from utils.logger import root_logger as logger
|
from utils.logger import root_logger as logger
|
||||||
|
|
||||||
|
|
||||||
|
@ -329,40 +326,3 @@ async def delete_shout(_, info, shout_id: int):
|
||||||
return {"error": None}
|
return {"error": None}
|
||||||
else:
|
else:
|
||||||
return {"error": "access denied"}
|
return {"error": "access denied"}
|
||||||
|
|
||||||
|
|
||||||
def handle_proposing(session, r, shout):
|
|
||||||
if is_positive(r.kind):
|
|
||||||
replied_reaction = session.query(Reaction).filter(Reaction.id == r.reply_to, Reaction.shout == r.shout).first()
|
|
||||||
|
|
||||||
if replied_reaction and replied_reaction.kind is ReactionKind.PROPOSE.value and replied_reaction.quote:
|
|
||||||
# patch all the proposals' quotes
|
|
||||||
proposals = (
|
|
||||||
session.query(Reaction)
|
|
||||||
.filter(
|
|
||||||
and_(
|
|
||||||
Reaction.shout == r.shout,
|
|
||||||
Reaction.kind == ReactionKind.PROPOSE.value,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.all()
|
|
||||||
)
|
|
||||||
|
|
||||||
for proposal in proposals:
|
|
||||||
if proposal.quote:
|
|
||||||
proposal_diff = get_diff(shout.body, proposal.quote)
|
|
||||||
proposal_dict = proposal.dict()
|
|
||||||
proposal_dict["quote"] = apply_diff(replied_reaction.quote, proposal_diff)
|
|
||||||
Reaction.update(proposal, proposal_dict)
|
|
||||||
session.add(proposal)
|
|
||||||
|
|
||||||
# patch shout's body
|
|
||||||
shout_dict = shout.dict()
|
|
||||||
shout_dict["body"] = replied_reaction.quote
|
|
||||||
Shout.update(shout, shout_dict)
|
|
||||||
session.add(shout)
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
if is_negative(r.kind):
|
|
||||||
# TODO: rejection logic
|
|
||||||
pass
|
|
||||||
|
|
48
resolvers/proposals.py
Normal file
48
resolvers/proposals.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
|
||||||
|
from sqlalchemy import and_
|
||||||
|
from orm.rating import is_negative, is_positive
|
||||||
|
from orm.reaction import Reaction, ReactionKind
|
||||||
|
from orm.shout import Shout
|
||||||
|
from services.db import local_session
|
||||||
|
from utils.diff import apply_diff, get_diff
|
||||||
|
|
||||||
|
|
||||||
|
def handle_proposing(kind: ReactionKind, reply_to: int, shout_id: int):
|
||||||
|
with local_session() as session:
|
||||||
|
if is_positive(kind):
|
||||||
|
replied_reaction = session.query(Reaction).filter(Reaction.id == reply_to, Reaction.shout == shout_id).first()
|
||||||
|
|
||||||
|
if replied_reaction and replied_reaction.kind is ReactionKind.PROPOSE.value and replied_reaction.quote:
|
||||||
|
# patch all the proposals' quotes
|
||||||
|
proposals = (
|
||||||
|
session.query(Reaction)
|
||||||
|
.filter(
|
||||||
|
and_(
|
||||||
|
Reaction.shout == shout_id,
|
||||||
|
Reaction.kind == ReactionKind.PROPOSE.value,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
|
||||||
|
# patch shout's body
|
||||||
|
shout = session.query(Shout).filter(Shout.id == shout_id).first()
|
||||||
|
body = replied_reaction.quote
|
||||||
|
Shout.update(shout, { body })
|
||||||
|
session.add(shout)
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
# реакция содержит цитату -> обновляются все предложения
|
||||||
|
# (proposals) для соответствующего Shout.
|
||||||
|
for proposal in proposals:
|
||||||
|
if proposal.quote:
|
||||||
|
proposal_diff = get_diff(shout.body, proposal.quote)
|
||||||
|
proposal_dict = proposal.dict()
|
||||||
|
proposal_dict["quote"] = apply_diff(replied_reaction.quote, proposal_diff)
|
||||||
|
Reaction.update(proposal, proposal_dict)
|
||||||
|
session.add(proposal)
|
||||||
|
|
||||||
|
if is_negative(kind):
|
||||||
|
# TODO: rejection logic
|
||||||
|
pass
|
|
@ -7,7 +7,7 @@ from orm.author import Author
|
||||||
from orm.rating import PROPOSAL_REACTIONS, RATING_REACTIONS, is_negative, is_positive
|
from orm.rating import PROPOSAL_REACTIONS, RATING_REACTIONS, is_negative, is_positive
|
||||||
from orm.reaction import Reaction, ReactionKind
|
from orm.reaction import Reaction, ReactionKind
|
||||||
from orm.shout import Shout
|
from orm.shout import Shout
|
||||||
from resolvers.editor import handle_proposing
|
from resolvers.proposals import handle_proposing
|
||||||
from resolvers.follower import follow
|
from resolvers.follower import follow
|
||||||
from resolvers.stat import update_author_stat
|
from resolvers.stat import update_author_stat
|
||||||
from services.auth import add_user_role, login_required
|
from services.auth import add_user_role, login_required
|
||||||
|
@ -82,8 +82,12 @@ def get_reactions_with_stat(q, limit, offset):
|
||||||
with local_session() as session:
|
with local_session() as session:
|
||||||
result_rows = session.execute(q)
|
result_rows = session.execute(q)
|
||||||
for reaction, author, shout, commented_stat, rating_stat in result_rows:
|
for reaction, author, shout, commented_stat, rating_stat in result_rows:
|
||||||
reaction.created_by = author
|
if shout is None:
|
||||||
reaction.shout = shout
|
logger.error(f"пустое поле Shout: {reaction.dict()}")
|
||||||
|
continue # Или обработайте иначе
|
||||||
|
|
||||||
|
reaction.created_by = author.dict()
|
||||||
|
reaction.shout = shout.dict()
|
||||||
reaction.stat = {"rating": rating_stat, "comments": commented_stat}
|
reaction.stat = {"rating": rating_stat, "comments": commented_stat}
|
||||||
reactions.append(reaction)
|
reactions.append(reaction)
|
||||||
|
|
||||||
|
@ -186,7 +190,7 @@ def set_unfeatured(session, shout_id):
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
async def _create_reaction(session, info, shout, author_id: int, reaction) -> dict:
|
async def _create_reaction(session, info, shout_dict, author_id: int, reaction) -> dict:
|
||||||
"""
|
"""
|
||||||
Create a new reaction and perform related actions such as updating counters and notification.
|
Create a new reaction and perform related actions such as updating counters and notification.
|
||||||
|
|
||||||
|
@ -207,20 +211,21 @@ async def _create_reaction(session, info, shout, author_id: int, reaction) -> di
|
||||||
update_author_stat(author_id)
|
update_author_stat(author_id)
|
||||||
|
|
||||||
# Handle proposal
|
# Handle proposal
|
||||||
if r.reply_to and r.kind in PROPOSAL_REACTIONS and author_id in shout.authors:
|
is_author = bool(list(filter(lambda x: x['id'] == int(author_id), [x for x in shout_dict['authors']])))
|
||||||
handle_proposing(session, r, shout)
|
if r.reply_to and r.kind in PROPOSAL_REACTIONS and is_author:
|
||||||
|
handle_proposing(r.kind, r.reply_to, shout_dict['id'])
|
||||||
|
|
||||||
# Handle rating
|
# Handle rating
|
||||||
if r.kind in RATING_REACTIONS:
|
if r.kind in RATING_REACTIONS:
|
||||||
if check_to_unfeature(session, author_id, r):
|
if check_to_unfeature(session, author_id, r):
|
||||||
set_unfeatured(session, shout.id)
|
set_unfeatured(session, shout_dict['id'])
|
||||||
elif check_to_feature(session, author_id, r):
|
elif check_to_feature(session, author_id, r):
|
||||||
await set_featured(session, shout.id)
|
await set_featured(session, shout_dict['id'])
|
||||||
|
|
||||||
# Follow if liked
|
# Follow if liked
|
||||||
if r.kind == ReactionKind.LIKE.value:
|
if r.kind == ReactionKind.LIKE.value:
|
||||||
try:
|
try:
|
||||||
follow(None, info, "shout", shout.slug)
|
follow(None, info, "shout", shout_dict['slug'])
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -292,6 +297,7 @@ async def create_reaction(_, info, reaction):
|
||||||
logger.debug(f"Loaded shout: {shout and shout.id}")
|
logger.debug(f"Loaded shout: {shout and shout.id}")
|
||||||
|
|
||||||
if shout:
|
if shout:
|
||||||
|
shout_dict = shout.dict()
|
||||||
reaction["created_by"] = author_id
|
reaction["created_by"] = author_id
|
||||||
kind = reaction.get(
|
kind = reaction.get(
|
||||||
"kind", ReactionKind.COMMENT.value if isinstance(reaction.get("body"), str) else None
|
"kind", ReactionKind.COMMENT.value if isinstance(reaction.get("body"), str) else None
|
||||||
|
@ -305,6 +311,7 @@ async def create_reaction(_, info, reaction):
|
||||||
logger.error(f"Rating preparation error: {error_result}")
|
logger.error(f"Rating preparation error: {error_result}")
|
||||||
return error_result
|
return error_result
|
||||||
|
|
||||||
|
logger.debug(f"Creating reaction for shout: {shout_dict['id']}")
|
||||||
rdict = await _create_reaction(session, info, shout, author_id, reaction)
|
rdict = await _create_reaction(session, info, shout, author_id, reaction)
|
||||||
|
|
||||||
logger.debug(f"Created reaction result: {rdict}")
|
logger.debug(f"Created reaction result: {rdict}")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user