This commit is contained in:
parent
12137eccda
commit
eaaace4d28
|
@ -7,9 +7,9 @@ from resolvers.author import (
|
||||||
get_author_id,
|
get_author_id,
|
||||||
get_authors_all,
|
get_authors_all,
|
||||||
load_authors_by,
|
load_authors_by,
|
||||||
rate_author,
|
|
||||||
update_author,
|
update_author,
|
||||||
)
|
)
|
||||||
|
from resolvers.rating import rate_author
|
||||||
from resolvers.community import get_communities_all, get_community
|
from resolvers.community import get_communities_all, get_community
|
||||||
from resolvers.editor import create_shout, delete_shout, update_shout
|
from resolvers.editor import create_shout, delete_shout, update_shout
|
||||||
from resolvers.follower import (
|
from resolvers.follower import (
|
||||||
|
|
|
@ -1,14 +1,19 @@
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from sqlalchemy import and_, desc, select, or_, distinct, func
|
from sqlalchemy import desc, select, or_, distinct, func
|
||||||
from sqlalchemy.orm import aliased
|
from sqlalchemy.orm import aliased
|
||||||
|
|
||||||
from orm.author import Author, AuthorFollower, AuthorRating
|
from orm.author import Author, AuthorFollower
|
||||||
from orm.shout import ShoutAuthor, ShoutTopic
|
from orm.shout import ShoutAuthor, ShoutTopic
|
||||||
from orm.topic import Topic
|
from orm.topic import Topic
|
||||||
from resolvers.follower import query_follows
|
from resolvers.follower import query_follows
|
||||||
from resolvers.stat import get_authors_with_stat, execute_with_ministat, author_follows_authors, author_follows_topics
|
from resolvers.stat import (
|
||||||
|
get_authors_with_stat,
|
||||||
|
execute_with_ministat,
|
||||||
|
author_follows_authors,
|
||||||
|
author_follows_topics,
|
||||||
|
)
|
||||||
from services.auth import login_required
|
from services.auth import login_required
|
||||||
from services.db import local_session
|
from services.db import local_session
|
||||||
from services.rediscache import redis
|
from services.rediscache import redis
|
||||||
|
@ -47,7 +52,7 @@ def get_author(_, _info, slug='', author_id=None):
|
||||||
if author_id:
|
if author_id:
|
||||||
q = select(Author).where(Author.id == author_id)
|
q = select(Author).where(Author.id == author_id)
|
||||||
|
|
||||||
[author, ] = get_authors_with_stat(q, ratings=True)
|
[author] = get_authors_with_stat(q, ratings=True)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error(exc)
|
logger.error(exc)
|
||||||
return author
|
return author
|
||||||
|
@ -67,7 +72,7 @@ async def get_author_by_user_id(user_id: str, ratings=False):
|
||||||
logger.info(f'getting author id for {user_id}')
|
logger.info(f'getting author id for {user_id}')
|
||||||
q = select(Author).filter(Author.user == user_id)
|
q = select(Author).filter(Author.user == user_id)
|
||||||
|
|
||||||
[author, ] = get_authors_with_stat(q, ratings)
|
[author] = get_authors_with_stat(q, ratings)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error(exc)
|
logger.error(exc)
|
||||||
return author
|
return author
|
||||||
|
@ -115,7 +120,11 @@ def load_authors_by(_, _info, by, limit, offset):
|
||||||
def get_author_follows(_, _info, slug='', user=None, author_id=None):
|
def get_author_follows(_, _info, slug='', user=None, author_id=None):
|
||||||
with local_session() as session:
|
with local_session() as session:
|
||||||
if user or slug:
|
if user or slug:
|
||||||
author_id_result = session.query(Author.id).filter(or_(Author.user == user, Author.slug == slug)).first()
|
author_id_result = (
|
||||||
|
session.query(Author.id)
|
||||||
|
.filter(or_(Author.user == user, Author.slug == slug))
|
||||||
|
.first()
|
||||||
|
)
|
||||||
author_id = author_id_result[0] if author_id_result else None
|
author_id = author_id_result[0] if author_id_result else None
|
||||||
if author_id:
|
if author_id:
|
||||||
follows = query_follows(author_id)
|
follows = query_follows(author_id)
|
||||||
|
@ -128,7 +137,11 @@ def get_author_follows(_, _info, slug='', user=None, author_id=None):
|
||||||
def get_author_follows_topics(_, _info, slug='', user=None, author_id=None):
|
def get_author_follows_topics(_, _info, slug='', user=None, author_id=None):
|
||||||
with local_session() as session:
|
with local_session() as session:
|
||||||
if user or slug:
|
if user or slug:
|
||||||
author_id_result = session.query(Author.id).filter(or_(Author.user == user, Author.slug == slug)).first()
|
author_id_result = (
|
||||||
|
session.query(Author.id)
|
||||||
|
.filter(or_(Author.user == user, Author.slug == slug))
|
||||||
|
.first()
|
||||||
|
)
|
||||||
author_id = author_id_result[0] if author_id_result else None
|
author_id = author_id_result[0] if author_id_result else None
|
||||||
if author_id:
|
if author_id:
|
||||||
follows = author_follows_authors(author_id)
|
follows = author_follows_authors(author_id)
|
||||||
|
@ -141,7 +154,11 @@ def get_author_follows_topics(_, _info, slug='', user=None, author_id=None):
|
||||||
def get_author_follows_authors(_, _info, slug='', user=None, author_id=None):
|
def get_author_follows_authors(_, _info, slug='', user=None, author_id=None):
|
||||||
with local_session() as session:
|
with local_session() as session:
|
||||||
if user or slug:
|
if user or slug:
|
||||||
author_id_result = session.query(Author.id).filter(or_(Author.user == user, Author.slug == slug)).first()
|
author_id_result = (
|
||||||
|
session.query(Author.id)
|
||||||
|
.filter(or_(Author.user == user, Author.slug == slug))
|
||||||
|
.first()
|
||||||
|
)
|
||||||
author_id = author_id_result[0] if author_id_result else None
|
author_id = author_id_result[0] if author_id_result else None
|
||||||
if author_id:
|
if author_id:
|
||||||
follows = author_follows_topics(author_id)
|
follows = author_follows_topics(author_id)
|
||||||
|
@ -150,42 +167,6 @@ def get_author_follows_authors(_, _info, slug='', user=None, author_id=None):
|
||||||
raise ValueError('Author not found')
|
raise ValueError('Author not found')
|
||||||
|
|
||||||
|
|
||||||
@mutation.field('rate_author')
|
|
||||||
@login_required
|
|
||||||
def rate_author(_, info, rated_slug, value):
|
|
||||||
user_id = info.context['user_id']
|
|
||||||
|
|
||||||
with local_session() as session:
|
|
||||||
rated_author = session.query(Author).filter(Author.slug == rated_slug).first()
|
|
||||||
rater = session.query(Author).filter(Author.slug == user_id).first()
|
|
||||||
if rater and rated_author:
|
|
||||||
rating: AuthorRating = (
|
|
||||||
session.query(AuthorRating)
|
|
||||||
.filter(
|
|
||||||
and_(
|
|
||||||
AuthorRating.rater == rater.id,
|
|
||||||
AuthorRating.author == rated_author.id,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.first()
|
|
||||||
)
|
|
||||||
if rating:
|
|
||||||
rating.plus = value > 0
|
|
||||||
session.add(rating)
|
|
||||||
session.commit()
|
|
||||||
return {}
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
rating = AuthorRating(
|
|
||||||
rater=rater.id, author=rated_author.id, plus=value > 0
|
|
||||||
)
|
|
||||||
session.add(rating)
|
|
||||||
session.commit()
|
|
||||||
except Exception as err:
|
|
||||||
return {'error': err}
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
def create_author(user_id: str, slug: str, name: str = ''):
|
def create_author(user_id: str, slug: str, name: str = ''):
|
||||||
with local_session() as session:
|
with local_session() as session:
|
||||||
new_author = Author(user=user_id, slug=slug, name=name)
|
new_author = Author(user=user_id, slug=slug, name=name)
|
||||||
|
|
137
resolvers/rating.py
Normal file
137
resolvers/rating.py
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
from sqlalchemy import and_
|
||||||
|
from sqlalchemy.orm import aliased
|
||||||
|
|
||||||
|
from orm.author import AuthorRating, Author
|
||||||
|
from orm.reaction import Reaction, ReactionKind
|
||||||
|
from orm.shout import Shout
|
||||||
|
from services.auth import login_required
|
||||||
|
from services.db import local_session
|
||||||
|
from services.schema import mutation
|
||||||
|
|
||||||
|
|
||||||
|
@mutation.field('rate_author')
|
||||||
|
@login_required
|
||||||
|
def rate_author(_, info, rated_slug, value):
|
||||||
|
user_id = info.context['user_id']
|
||||||
|
|
||||||
|
with local_session() as session:
|
||||||
|
rated_author = session.query(Author).filter(Author.slug == rated_slug).first()
|
||||||
|
rater = session.query(Author).filter(Author.slug == user_id).first()
|
||||||
|
if rater and rated_author:
|
||||||
|
rating: AuthorRating = (
|
||||||
|
session.query(AuthorRating)
|
||||||
|
.filter(
|
||||||
|
and_(
|
||||||
|
AuthorRating.rater == rater.id,
|
||||||
|
AuthorRating.author == rated_author.id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.first()
|
||||||
|
)
|
||||||
|
if rating:
|
||||||
|
rating.plus = value > 0
|
||||||
|
session.add(rating)
|
||||||
|
session.commit()
|
||||||
|
return {}
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
rating = AuthorRating(
|
||||||
|
rater=rater.id, author=rated_author.id, plus=value > 0
|
||||||
|
)
|
||||||
|
session.add(rating)
|
||||||
|
session.commit()
|
||||||
|
except Exception as err:
|
||||||
|
return {'error': err}
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def count_author_comments_rating(session, author_id) -> int:
|
||||||
|
replied_alias = aliased(Reaction)
|
||||||
|
replies_likes = (
|
||||||
|
session.query(replied_alias)
|
||||||
|
.join(Reaction, replied_alias.id == Reaction.reply_to)
|
||||||
|
.where(
|
||||||
|
and_(
|
||||||
|
replied_alias.created_by == author_id,
|
||||||
|
replied_alias.kind == ReactionKind.COMMENT.value,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.filter(replied_alias.kind == ReactionKind.LIKE.value)
|
||||||
|
.count()
|
||||||
|
) or 0
|
||||||
|
replies_dislikes = (
|
||||||
|
session.query(replied_alias)
|
||||||
|
.join(Reaction, replied_alias.id == Reaction.reply_to)
|
||||||
|
.where(
|
||||||
|
and_(
|
||||||
|
replied_alias.created_by == author_id,
|
||||||
|
replied_alias.kind == ReactionKind.COMMENT.value,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.filter(replied_alias.kind == ReactionKind.DISLIKE.value)
|
||||||
|
.count()
|
||||||
|
) or 0
|
||||||
|
|
||||||
|
return replies_likes - replies_dislikes
|
||||||
|
|
||||||
|
|
||||||
|
def count_author_shouts_rating(session, author_id) -> int:
|
||||||
|
shouts_likes = (
|
||||||
|
session.query(Reaction, Shout)
|
||||||
|
.join(Shout, Shout.id == Reaction.shout)
|
||||||
|
.filter(
|
||||||
|
and_(
|
||||||
|
Shout.authors.any(id=author_id),
|
||||||
|
Reaction.kind == ReactionKind.LIKE.value,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.count()
|
||||||
|
or 0
|
||||||
|
)
|
||||||
|
shouts_dislikes = (
|
||||||
|
session.query(Reaction, Shout)
|
||||||
|
.join(Shout, Shout.id == Reaction.shout)
|
||||||
|
.filter(
|
||||||
|
and_(
|
||||||
|
Shout.authors.any(id=author_id),
|
||||||
|
Reaction.kind == ReactionKind.DISLIKE.value,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.count()
|
||||||
|
or 0
|
||||||
|
)
|
||||||
|
return shouts_likes - shouts_dislikes
|
||||||
|
|
||||||
|
|
||||||
|
def load_author_ratings(author: Author):
|
||||||
|
with local_session() as session:
|
||||||
|
comments_count = (
|
||||||
|
session.query(Reaction)
|
||||||
|
.filter(
|
||||||
|
and_(
|
||||||
|
Reaction.created_by == author.id,
|
||||||
|
Reaction.kind == ReactionKind.COMMENT.value,
|
||||||
|
Reaction.deleted_at.is_(None),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.count()
|
||||||
|
)
|
||||||
|
likes_count = (
|
||||||
|
session.query(AuthorRating)
|
||||||
|
.filter(and_(AuthorRating.author == author.id, AuthorRating.plus.is_(True)))
|
||||||
|
.count()
|
||||||
|
)
|
||||||
|
dislikes_count = (
|
||||||
|
session.query(AuthorRating)
|
||||||
|
.filter(
|
||||||
|
and_(AuthorRating.author == author.id, AuthorRating.plus.is_not(True))
|
||||||
|
)
|
||||||
|
.count()
|
||||||
|
)
|
||||||
|
author.stat['rating'] = likes_count - dislikes_count
|
||||||
|
author.stat['rating_shouts'] = count_author_shouts_rating(session, author.id)
|
||||||
|
author.stat['rating_comments'] = count_author_comments_rating(
|
||||||
|
session, author.id
|
||||||
|
)
|
||||||
|
author.stat['commented'] = comments_count
|
||||||
|
return author
|
|
@ -57,7 +57,7 @@ def check_to_feature(session, approver_id, reaction):
|
||||||
"""set shout to public if publicated approvers amount > 4"""
|
"""set shout to public if publicated approvers amount > 4"""
|
||||||
if not reaction.reply_to and is_positive(reaction.kind):
|
if not reaction.reply_to and is_positive(reaction.kind):
|
||||||
if is_featured_author(session, approver_id):
|
if is_featured_author(session, approver_id):
|
||||||
approvers = [approver_id, ]
|
approvers = [approver_id]
|
||||||
# now count how many approvers are voted already
|
# now count how many approvers are voted already
|
||||||
reacted_readers = (
|
reacted_readers = (
|
||||||
session.query(Reaction).where(Reaction.shout == reaction.shout).all()
|
session.query(Reaction).where(Reaction.shout == reaction.shout).all()
|
||||||
|
@ -148,36 +148,10 @@ async def _create_reaction(session, shout, author, reaction):
|
||||||
return rdict
|
return rdict
|
||||||
|
|
||||||
|
|
||||||
@mutation.field('create_reaction')
|
def check_rating(reaction: dict, shout_id: int, session, author: Author):
|
||||||
@login_required
|
|
||||||
async def create_reaction(_, info, reaction):
|
|
||||||
user_id = info.context['user_id']
|
|
||||||
|
|
||||||
shout_id = reaction.get('shout')
|
|
||||||
|
|
||||||
if not shout_id:
|
|
||||||
return {'error': 'Shout ID is required to create a reaction.'}
|
|
||||||
|
|
||||||
try:
|
|
||||||
with local_session() as session:
|
|
||||||
shout = session.query(Shout).filter(Shout.id == shout_id).first()
|
|
||||||
author = session.query(Author).filter(Author.user == user_id).first()
|
|
||||||
if shout and author:
|
|
||||||
reaction['created_by'] = author.id
|
|
||||||
kind = reaction.get('kind')
|
kind = reaction.get('kind')
|
||||||
shout_id = shout.id
|
|
||||||
|
|
||||||
if not kind and isinstance(reaction.get('body'), str):
|
|
||||||
kind = ReactionKind.COMMENT.value
|
|
||||||
|
|
||||||
if not kind:
|
|
||||||
return {'error': 'cannot create reaction without a kind'}
|
|
||||||
|
|
||||||
if kind in RATING_REACTIONS:
|
|
||||||
opposite_kind = (
|
opposite_kind = (
|
||||||
ReactionKind.DISLIKE.value
|
ReactionKind.DISLIKE.value if is_positive(kind) else ReactionKind.LIKE.value
|
||||||
if is_positive(kind)
|
|
||||||
else ReactionKind.LIKE.value
|
|
||||||
)
|
)
|
||||||
|
|
||||||
q = select(Reaction).filter(
|
q = select(Reaction).filter(
|
||||||
|
@ -205,6 +179,38 @@ async def create_reaction(_, info, reaction):
|
||||||
return {'error': 'Remove opposite vote first'}
|
return {'error': 'Remove opposite vote first'}
|
||||||
elif filter(lambda r: r.created_by == author.id, rating_reactions):
|
elif filter(lambda r: r.created_by == author.id, rating_reactions):
|
||||||
return {'error': "You can't rate your own thing"}
|
return {'error': "You can't rate your own thing"}
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@mutation.field('create_reaction')
|
||||||
|
@login_required
|
||||||
|
async def create_reaction(_, info, reaction):
|
||||||
|
user_id = info.context['user_id']
|
||||||
|
|
||||||
|
shout_id = reaction.get('shout')
|
||||||
|
|
||||||
|
if not shout_id:
|
||||||
|
return {'error': 'Shout ID is required to create a reaction.'}
|
||||||
|
|
||||||
|
try:
|
||||||
|
with local_session() as session:
|
||||||
|
shout = session.query(Shout).filter(Shout.id == shout_id).first()
|
||||||
|
author = session.query(Author).filter(Author.user == user_id).first()
|
||||||
|
if shout and author:
|
||||||
|
reaction['created_by'] = author.id
|
||||||
|
kind = reaction.get('kind')
|
||||||
|
shout_id = shout.id
|
||||||
|
|
||||||
|
if not kind and isinstance(reaction.get('body'), str):
|
||||||
|
kind = ReactionKind.COMMENT.value
|
||||||
|
|
||||||
|
if not kind:
|
||||||
|
return {'error': 'cannot create reaction without a kind'}
|
||||||
|
|
||||||
|
if kind in RATING_REACTIONS:
|
||||||
|
result = check_rating(reaction, shout_id, session, author)
|
||||||
|
if result:
|
||||||
|
return result
|
||||||
|
|
||||||
rdict = await _create_reaction(session, shout, author, reaction)
|
rdict = await _create_reaction(session, shout, author, reaction)
|
||||||
return {'reaction': rdict}
|
return {'reaction': rdict}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
from sqlalchemy import func, distinct, select, join, and_
|
from sqlalchemy import func, distinct, select, join
|
||||||
from sqlalchemy.orm import aliased
|
from sqlalchemy.orm import aliased
|
||||||
|
|
||||||
from orm.reaction import Reaction, ReactionKind
|
|
||||||
from orm.topic import TopicFollower, Topic
|
from orm.topic import TopicFollower, Topic
|
||||||
|
from resolvers.rating import load_author_ratings
|
||||||
from services.db import local_session
|
from services.db import local_session
|
||||||
from orm.author import AuthorFollower, Author, AuthorRating
|
from orm.author import AuthorFollower, Author
|
||||||
from orm.shout import ShoutTopic, ShoutAuthor, Shout
|
from orm.shout import ShoutTopic, ShoutAuthor
|
||||||
from services.logger import root_logger as logger
|
from services.logger import root_logger as logger
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,11 +16,22 @@ def add_topic_stat_columns(q):
|
||||||
|
|
||||||
q = (
|
q = (
|
||||||
q.outerjoin(aliased_shout_topic, aliased_shout_topic.topic == Topic.id)
|
q.outerjoin(aliased_shout_topic, aliased_shout_topic.topic == Topic.id)
|
||||||
.add_columns(func.count(distinct(aliased_shout_topic.shout)).label("shouts_stat"))
|
.add_columns(
|
||||||
.outerjoin(aliased_shout_author, aliased_shout_topic.shout == aliased_shout_author.shout)
|
func.count(distinct(aliased_shout_topic.shout)).label('shouts_stat')
|
||||||
.add_columns(func.count(distinct(aliased_shout_author.author)).label("authors_stat"))
|
)
|
||||||
|
.outerjoin(
|
||||||
|
aliased_shout_author,
|
||||||
|
aliased_shout_topic.shout == aliased_shout_author.shout,
|
||||||
|
)
|
||||||
|
.add_columns(
|
||||||
|
func.count(distinct(aliased_shout_author.author)).label('authors_stat')
|
||||||
|
)
|
||||||
.outerjoin(aliased_topic_follower)
|
.outerjoin(aliased_topic_follower)
|
||||||
.add_columns(func.count(distinct(aliased_topic_follower.follower)).label("followers_stat"))
|
.add_columns(
|
||||||
|
func.count(distinct(aliased_topic_follower.follower)).label(
|
||||||
|
'followers_stat'
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
q = q.group_by(Topic.id)
|
q = q.group_by(Topic.id)
|
||||||
|
@ -35,11 +46,21 @@ def add_author_stat_columns(q):
|
||||||
|
|
||||||
q = (
|
q = (
|
||||||
q.outerjoin(aliased_shout_author, aliased_shout_author.author == Author.id)
|
q.outerjoin(aliased_shout_author, aliased_shout_author.author == Author.id)
|
||||||
.add_columns(func.count(distinct(aliased_shout_author.shout)).label("shouts_stat"))
|
.add_columns(
|
||||||
|
func.count(distinct(aliased_shout_author.shout)).label('shouts_stat')
|
||||||
|
)
|
||||||
.outerjoin(aliased_author_authors, aliased_author_authors.follower == Author.id)
|
.outerjoin(aliased_author_authors, aliased_author_authors.follower == Author.id)
|
||||||
.add_columns(func.count(distinct(aliased_shout_author.author)).label("authors_stat"))
|
.add_columns(
|
||||||
.outerjoin(aliased_author_followers, aliased_author_followers.author == Author.id)
|
func.count(distinct(aliased_shout_author.author)).label('authors_stat')
|
||||||
.add_columns(func.count(distinct(aliased_author_followers.follower)).label("followers_stat"))
|
)
|
||||||
|
.outerjoin(
|
||||||
|
aliased_author_followers, aliased_author_followers.author == Author.id
|
||||||
|
)
|
||||||
|
.add_columns(
|
||||||
|
func.count(distinct(aliased_author_followers.follower)).label(
|
||||||
|
'followers_stat'
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
q = q.group_by(Author.id)
|
q = q.group_by(Author.id)
|
||||||
|
@ -47,104 +68,6 @@ def add_author_stat_columns(q):
|
||||||
return q
|
return q
|
||||||
|
|
||||||
|
|
||||||
def count_author_comments_rating(session, author_id) -> int:
|
|
||||||
replied_alias = aliased(Reaction)
|
|
||||||
replies_likes = (
|
|
||||||
session.query(replied_alias)
|
|
||||||
.join(Reaction, replied_alias.id == Reaction.reply_to)
|
|
||||||
.where(
|
|
||||||
and_(
|
|
||||||
replied_alias.created_by == author_id,
|
|
||||||
replied_alias.kind == ReactionKind.COMMENT.value,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.filter(replied_alias.kind == ReactionKind.LIKE.value)
|
|
||||||
.count()
|
|
||||||
) or 0
|
|
||||||
replies_dislikes = (
|
|
||||||
session.query(replied_alias)
|
|
||||||
.join(Reaction, replied_alias.id == Reaction.reply_to)
|
|
||||||
.where(
|
|
||||||
and_(
|
|
||||||
replied_alias.created_by == author_id,
|
|
||||||
replied_alias.kind == ReactionKind.COMMENT.value,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.filter(replied_alias.kind == ReactionKind.DISLIKE.value)
|
|
||||||
.count()
|
|
||||||
) or 0
|
|
||||||
|
|
||||||
return replies_likes - replies_dislikes
|
|
||||||
|
|
||||||
|
|
||||||
def count_author_shouts_rating(session, author_id) -> int:
|
|
||||||
shouts_likes = (
|
|
||||||
session.query(Reaction, Shout)
|
|
||||||
.join(Shout, Shout.id == Reaction.shout)
|
|
||||||
.filter(
|
|
||||||
and_(
|
|
||||||
Shout.authors.any(id=author_id),
|
|
||||||
Reaction.kind == ReactionKind.LIKE.value,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.count()
|
|
||||||
or 0
|
|
||||||
)
|
|
||||||
shouts_dislikes = (
|
|
||||||
session.query(Reaction, Shout)
|
|
||||||
.join(Shout, Shout.id == Reaction.shout)
|
|
||||||
.filter(
|
|
||||||
and_(
|
|
||||||
Shout.authors.any(id=author_id),
|
|
||||||
Reaction.kind == ReactionKind.DISLIKE.value,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.count()
|
|
||||||
or 0
|
|
||||||
)
|
|
||||||
return shouts_likes - shouts_dislikes
|
|
||||||
|
|
||||||
|
|
||||||
def load_author_ratings(author: Author):
|
|
||||||
with local_session() as session:
|
|
||||||
comments_count = (
|
|
||||||
session.query(Reaction)
|
|
||||||
.filter(
|
|
||||||
and_(
|
|
||||||
Reaction.created_by == author.id,
|
|
||||||
Reaction.kind == ReactionKind.COMMENT.value,
|
|
||||||
Reaction.deleted_at.is_(None),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.count()
|
|
||||||
)
|
|
||||||
likes_count = (
|
|
||||||
session.query(AuthorRating)
|
|
||||||
.filter(
|
|
||||||
and_(AuthorRating.author == author.id, AuthorRating.plus.is_(True))
|
|
||||||
)
|
|
||||||
.count()
|
|
||||||
)
|
|
||||||
dislikes_count = (
|
|
||||||
session.query(AuthorRating)
|
|
||||||
.filter(
|
|
||||||
and_(
|
|
||||||
AuthorRating.author == author.id, AuthorRating.plus.is_not(True)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.count()
|
|
||||||
)
|
|
||||||
author.stat['rating'] = likes_count - dislikes_count
|
|
||||||
author.stat['rating_shouts'] = count_author_shouts_rating(
|
|
||||||
session, author.id
|
|
||||||
)
|
|
||||||
author.stat['rating_comments'] = count_author_comments_rating(
|
|
||||||
session, author.id
|
|
||||||
)
|
|
||||||
author.stat['commented'] = comments_count
|
|
||||||
return author
|
|
||||||
|
|
||||||
|
|
||||||
def execute_with_ministat(q):
|
def execute_with_ministat(q):
|
||||||
records = []
|
records = []
|
||||||
with local_session() as session:
|
with local_session() as session:
|
||||||
|
@ -176,11 +99,11 @@ def get_topics_with_stat(q):
|
||||||
|
|
||||||
|
|
||||||
def author_follows_authors(author_id: int):
|
def author_follows_authors(author_id: int):
|
||||||
af = aliased(AuthorFollower, name="af")
|
af = aliased(AuthorFollower, name='af')
|
||||||
q = (
|
q = (
|
||||||
select(Author).select_from(
|
select(Author)
|
||||||
join(Author, af, Author.id == int(af.author))
|
.select_from(join(Author, af, Author.id == int(af.author)))
|
||||||
).where(af.follower == author_id)
|
.where(af.follower == author_id)
|
||||||
)
|
)
|
||||||
q = add_author_stat_columns(q)
|
q = add_author_stat_columns(q)
|
||||||
return execute_with_ministat(q)
|
return execute_with_ministat(q)
|
||||||
|
@ -188,9 +111,9 @@ def author_follows_authors(author_id: int):
|
||||||
|
|
||||||
def author_follows_topics(author_id: int):
|
def author_follows_topics(author_id: int):
|
||||||
q = (
|
q = (
|
||||||
select(Topic).select_from(
|
select(Topic)
|
||||||
join(Topic, TopicFollower, Topic.id == TopicFollower.topic)
|
.select_from(join(Topic, TopicFollower, Topic.id == TopicFollower.topic))
|
||||||
).where(TopicFollower.follower == author_id)
|
.where(TopicFollower.follower == author_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
q = add_topic_stat_columns(q)
|
q = add_topic_stat_columns(q)
|
||||||
|
@ -207,5 +130,5 @@ def query_follows(author_id: int):
|
||||||
'communities': [{'id': 1, 'name': 'Дискурс', 'slug': 'discours'}],
|
'communities': [{'id': 1, 'name': 'Дискурс', 'slug': 'discours'}],
|
||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f"An error occurred while executing query_follows: {e}")
|
logger.exception(f'An error occurred while executing query_follows: {e}')
|
||||||
raise Exception("An error occurred while executing query_follows") from e
|
raise Exception('An error occurred while executing query_follows') from e
|
||||||
|
|
|
@ -28,16 +28,15 @@ async def update_author_cache(author: Author, ttl=25 * 60 * 60):
|
||||||
@event.listens_for(Shout, 'after_update')
|
@event.listens_for(Shout, 'after_update')
|
||||||
def after_shouts_update(mapper, connection, shout: Shout):
|
def after_shouts_update(mapper, connection, shout: Shout):
|
||||||
# Создаем подзапрос для проверки наличия авторов в списке shout.authors
|
# Создаем подзапрос для проверки наличия авторов в списке shout.authors
|
||||||
subquery = (
|
subquery = select(1).where(
|
||||||
select(1)
|
or_(
|
||||||
.where(or_(
|
|
||||||
Author.id == shout.created_by,
|
Author.id == shout.created_by,
|
||||||
and_(
|
and_(
|
||||||
Shout.id == shout.id,
|
Shout.id == shout.id,
|
||||||
ShoutAuthor.shout == Shout.id,
|
ShoutAuthor.shout == Shout.id,
|
||||||
ShoutAuthor.author == Author.id
|
ShoutAuthor.author == Author.id,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Основной запрос с использованием объединения и подзапроса exists
|
# Основной запрос с использованием объединения и подзапроса exists
|
||||||
|
@ -45,10 +44,7 @@ def after_shouts_update(mapper, connection, shout: Shout):
|
||||||
select(Author)
|
select(Author)
|
||||||
.join(ShoutAuthor, Author.id == ShoutAuthor.author)
|
.join(ShoutAuthor, Author.id == ShoutAuthor.author)
|
||||||
.where(ShoutAuthor.shout == shout.id)
|
.where(ShoutAuthor.shout == shout.id)
|
||||||
.union(
|
.union(select(Author).where(exists(subquery)))
|
||||||
select(Author)
|
|
||||||
.where(exists(subquery))
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
authors = get_authors_with_stat(authors_query, ratings=True)
|
authors = get_authors_with_stat(authors_query, ratings=True)
|
||||||
for author in authors:
|
for author in authors:
|
||||||
|
@ -57,10 +53,7 @@ def after_shouts_update(mapper, connection, shout: Shout):
|
||||||
|
|
||||||
@event.listens_for(Reaction, 'after_insert')
|
@event.listens_for(Reaction, 'after_insert')
|
||||||
def after_reaction_insert(mapper, connection, reaction: Reaction):
|
def after_reaction_insert(mapper, connection, reaction: Reaction):
|
||||||
author_subquery = (
|
author_subquery = select(Author).where(Author.id == reaction.created_by)
|
||||||
select(Author)
|
|
||||||
.where(Author.id == reaction.created_by)
|
|
||||||
)
|
|
||||||
replied_author_subquery = (
|
replied_author_subquery = (
|
||||||
select(Author)
|
select(Author)
|
||||||
.join(Reaction, Author.id == Reaction.created_by)
|
.join(Reaction, Author.id == Reaction.created_by)
|
||||||
|
@ -112,7 +105,9 @@ def after_author_follower_delete(mapper, connection, target: AuthorFollower):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def update_follows_for_user(connection, user_id, entity_type, entity: dict, is_insert):
|
async def update_follows_for_user(
|
||||||
|
connection, user_id, entity_type, entity: dict, is_insert
|
||||||
|
):
|
||||||
redis_key = f'user:{user_id}:follows'
|
redis_key = f'user:{user_id}:follows'
|
||||||
follows_str = await redis.get(redis_key)
|
follows_str = await redis.get(redis_key)
|
||||||
if follows_str:
|
if follows_str:
|
||||||
|
@ -123,13 +118,17 @@ async def update_follows_for_user(connection, user_id, entity_type, entity: dict
|
||||||
follows[f'{entity_type}s'].append(entity)
|
follows[f'{entity_type}s'].append(entity)
|
||||||
else:
|
else:
|
||||||
# Remove the entity from follows
|
# Remove the entity from follows
|
||||||
follows[f'{entity_type}s'] = [e for e in follows[f'{entity_type}s'] if e['id'] != entity['id']]
|
follows[f'{entity_type}s'] = [
|
||||||
|
e for e in follows[f'{entity_type}s'] if e['id'] != entity['id']
|
||||||
|
]
|
||||||
await redis.execute('SET', redis_key, json.dumps(follows))
|
await redis.execute('SET', redis_key, json.dumps(follows))
|
||||||
|
|
||||||
|
|
||||||
async def handle_author_follower_change(connection, author_id: int, follower_id: int, is_insert: bool):
|
async def handle_author_follower_change(
|
||||||
|
connection, author_id: int, follower_id: int, is_insert: bool
|
||||||
|
):
|
||||||
author_query = select(Author).filter(Author.id == author_id)
|
author_query = select(Author).filter(Author.id == author_id)
|
||||||
[author, ] = get_authors_with_stat(author_query, ratings=True)
|
[author] = get_authors_with_stat(author_query, ratings=True)
|
||||||
follower_query = select(Author).filter(Author.id == follower_id)
|
follower_query = select(Author).filter(Author.id == follower_id)
|
||||||
follower = get_authors_with_stat(follower_query, ratings=True)
|
follower = get_authors_with_stat(follower_query, ratings=True)
|
||||||
if follower and author:
|
if follower and author:
|
||||||
|
@ -151,7 +150,9 @@ async def handle_author_follower_change(connection, author_id: int, follower_id:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def handle_topic_follower_change(connection, topic_id: int, follower_id: int, is_insert: bool):
|
async def handle_topic_follower_change(
|
||||||
|
connection, topic_id: int, follower_id: int, is_insert: bool
|
||||||
|
):
|
||||||
q = select(Topic).filter(Topic.id == topic_id)
|
q = select(Topic).filter(Topic.id == topic_id)
|
||||||
topics = get_topics_with_stat(q)
|
topics = get_topics_with_stat(q)
|
||||||
topic = topics[0]
|
topic = topics[0]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user