diff --git a/resolvers/author.py b/resolvers/author.py index abaa29f8..dbd9f636 100644 --- a/resolvers/author.py +++ b/resolvers/author.py @@ -1,7 +1,7 @@ import json import time -from sqlalchemy import and_, desc, or_, select, text +from sqlalchemy import and_, desc, select, text from sqlalchemy.orm import aliased from orm.author import Author, AuthorFollower @@ -72,9 +72,7 @@ async def get_author(_, _info, slug="", author_id=0): logger.debug(f"found author id: {found_author.id}") author_id = found_author.id if found_author.id else author_id if author_id: - cached_result = await redis.execute( - "GET", f"author:{author_id}" - ) + cached_result = await redis.execute("GET", f"author:{author_id}") if isinstance(cached_result, str): author_dict = json.loads(cached_result) @@ -140,10 +138,7 @@ async def load_authors_by(_, _info, by, limit, offset): authors_query = authors_query.filter(Author.name.ilike(f"%{by['name']}%")) elif by.get("topic"): authors_query = ( - authors_query.join(ShoutAuthor) - .join(ShoutTopic) - .join(Topic) - .where(Topic.slug == str(by["topic"])) + authors_query.join(ShoutAuthor).join(ShoutTopic).join(Topic).where(Topic.slug == str(by["topic"])) ) if by.get("last_seen"): # in unix time @@ -162,14 +157,10 @@ async def load_authors_by(_, _info, by, limit, offset): if isinstance(a, Author): author_id = a.id if bool(author_id): - cached_result = await redis.execute( - "GET", f"author:{author_id}" - ) + cached_result = await redis.execute("GET", f"author:{author_id}") if isinstance(cached_result, str): author_dict = json.loads(cached_result) - if not author_dict or not isinstance( - author_dict.get("shouts"), int - ): + if not author_dict or not isinstance(author_dict.get("shouts"), int): break # order @@ -181,78 +172,68 @@ async def load_authors_by(_, _info, by, limit, offset): return authors or [] +def get_author_id_from(slug="", user=None, author_id=None): + if not slug and not user and not author_id: + raise ValueError("One of slug, user, or author_id must be provided") + + author_query = select(Author.id) + if user: + author_query = author_query.filter(Author.user == user) + elif slug: + author_query = author_query.filter(Author.slug == slug) + elif author_id: + author_query = author_query.filter(Author.id == author_id) + + with local_session() as session: + author_id_result = session.execute(author_query).first() + author_id = author_id_result[0] if author_id_result else None + + if not author_id: + raise ValueError("Author not found") + + return author_id + + @query.field("get_author_follows") async def get_author_follows(_, _info, slug="", user=None, author_id=0): try: - author_query = select(Author) - if user: - author_query = author_query.filter(Author.user == user) - elif slug: - author_query = author_query.filter(Author.slug == slug) - elif author_id: - author_query = author_query.filter(Author.id == author_id) - else: - return {"error": "One of slug, user, or author_id must be provided"} - with local_session() as session: - result = session.execute(author_query) - if result: - # logger.debug(result) - [author] = result - # logger.debug(author) - if author and isinstance(author, Author): - # logger.debug(author.dict()) - author_id = author.id if not author_id else author_id - topics = [] - authors = [] - if bool(author_id): - rkey = f"author:{author_id}:follows-authors" - logger.debug(f"getting {author_id} follows authors") - cached = await redis.execute("GET", rkey) - if not cached: - authors = author_follows_authors(author_id) # type: ignore - prepared = [author.dict() for author in authors] - await redis.execute( - "SET", rkey, json.dumps(prepared, cls=CustomJSONEncoder) - ) - elif isinstance(cached, str): - authors = json.loads(cached) + author_id = get_author_id_from(slug, user, author_id) + topics = [] + authors = [] + rkey = f"author:{author_id}:follows-authors" + logger.debug(f"getting {author_id} follows authors") + cached = await redis.execute("GET", rkey) + if not cached: + authors = author_follows_authors(author_id) # type: ignore + prepared = [a.dict() for a in authors] + await redis.execute("SET", rkey, json.dumps(prepared, cls=CustomJSONEncoder)) + elif isinstance(cached, str): + authors = json.loads(cached) - rkey = f"author:{author_id}:follows-topics" - cached = await redis.execute("GET", rkey) - if cached and isinstance(cached, str): - topics = json.loads(cached) - if not cached: - topics = author_follows_topics(author_id) # type: ignore - prepared = [topic.dict() for topic in topics] - await redis.execute( - "SET", rkey, json.dumps(prepared, cls=CustomJSONEncoder) - ) - return { - "topics": topics, - "authors": authors, - "communities": [ - {"id": 1, "name": "Дискурс", "slug": "discours", "pic": ""} - ], - } + rkey = f"author:{author_id}:follows-topics" + cached = await redis.execute("GET", rkey) + if cached and isinstance(cached, str): + topics = json.loads(cached) + if not cached: + topics = author_follows_topics(author_id) # type: ignore + prepared = [topic.dict() for topic in topics] + await redis.execute("SET", rkey, json.dumps(prepared, cls=CustomJSONEncoder)) + return { + "topics": topics, + "authors": authors, + "communities": [{"id": 1, "name": "Дискурс", "slug": "discours", "pic": ""}], + } except Exception: import traceback traceback.print_exc() - return {"error": "Author not found"} + return {"error": "Author not found"} @query.field("get_author_follows_topics") async def get_author_follows_topics(_, _info, slug="", user=None, author_id=None): - with local_session() as session: - if user or slug: - 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 - if not author_id: - raise ValueError("Author not found") + try: + author_id = get_author_id_from(slug, user, author_id) logger.debug(f"getting {author_id} follows topics") rkey = f"author:{author_id}:follows-topics" cached = await redis.execute("GET", rkey) @@ -262,38 +243,33 @@ async def get_author_follows_topics(_, _info, slug="", user=None, author_id=None if not cached: topics = author_follows_topics(author_id) prepared = [topic.dict() for topic in topics] - await redis.execute( - "SET", rkey, json.dumps(prepared, cls=CustomJSONEncoder) - ) + await redis.execute("SET", rkey, json.dumps(prepared, cls=CustomJSONEncoder)) return topics + except Exception: + import traceback + + traceback.print_exc() @query.field("get_author_follows_authors") async def get_author_follows_authors(_, _info, slug="", user=None, author_id=None): - with local_session() as session: - if user or slug: - 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 - if author_id: - logger.debug(f"getting {author_id} follows authors") - rkey = f"author:{author_id}:follows-authors" - cached = await redis.execute("GET", rkey) - authors = [] - if isinstance(cached, str): - authors = json.loads(cached) - if not authors: - authors = author_follows_authors(author_id) - prepared = [author.dict() for author in authors] - await redis.execute( - "SET", rkey, json.dumps(prepared, cls=CustomJSONEncoder) - ) - return authors - else: - raise ValueError("Author not found") + try: + author_id = get_author_id_from(slug, user, author_id) + logger.debug(f"getting {author_id} follows authors") + rkey = f"author:{author_id}:follows-authors" + cached = await redis.execute("GET", rkey) + authors = [] + if isinstance(cached, str): + authors = json.loads(cached) + if not authors: + authors = author_follows_authors(author_id) + prepared = [author.dict() for author in authors] + await redis.execute("SET", rkey, json.dumps(prepared, cls=CustomJSONEncoder)) + return authors + except Exception: + import traceback + + traceback.print_exc() def create_author(user_id: str, slug: str, name: str = ""): @@ -332,9 +308,7 @@ async def get_author_followers(_, _info, slug: str): if cached and cached_author: followers = json.loads(cached) author_dict = json.loads(cached_author) - if isinstance(followers, list) and str(len(followers)) == str( - author_dict["stat"]["followers"] - ): + if isinstance(followers, list) and str(len(followers)) == str(author_dict["stat"]["followers"]): logger.debug(f"@{slug} got {len(followers)} followers cached") return followers @@ -352,9 +326,7 @@ async def get_author_followers(_, _info, slug: str): if isinstance(followers, list): followers_data = [follower.dict() for follower in followers] - await redis.execute( - "SET", f"author:{author_id}:followers", json.dumps(followers_data) - ) + await redis.execute("SET", f"author:{author_id}:followers", json.dumps(followers_data)) logger.debug(f"@{slug} cache updated with {len(followers)} followers") return followers except Exception as exc: diff --git a/resolvers/collab.py b/resolvers/collab.py index 981f244c..aa1d6bb3 100644 --- a/resolvers/collab.py +++ b/resolvers/collab.py @@ -18,18 +18,12 @@ async def accept_invite(_, info, invite_id: int): with local_session() as session: # Check if the invite exists invite = session.query(Invite).filter(Invite.id == invite_id).first() - if ( - invite - and invite.author_id is author_id - and invite.status is InviteStatus.PENDING.value - ): + if invite and invite.author_id is author_id and invite.status is InviteStatus.PENDING.value: # Add the user to the shout authors shout = session.query(Shout).filter(Shout.id == invite.shout_id).first() if shout: if author_id not in shout.authors: - author = ( - session.query(Author).filter(Author.id == author_id).first() - ) + author = session.query(Author).filter(Author.id == author_id).first() if author: shout.authors.append(author) session.add(shout) @@ -57,11 +51,7 @@ async def reject_invite(_, info, invite_id: int): author_id = int(author_id) # Check if the invite exists invite = session.query(Invite).filter(Invite.id == invite_id).first() - if ( - invite - and invite.author_id is author_id - and invite.status is InviteStatus.PENDING.value - ): + if invite and invite.author_id is author_id and invite.status is InviteStatus.PENDING.value: # Delete the invite session.delete(invite) session.commit() @@ -124,9 +114,7 @@ async def remove_author(_, info, slug: str = "", author_id: int = 0): shout = session.query(Shout).filter(Shout.slug == slug).first() # NOTE: owner should be first in a list if shout and author.id is shout.created_by: - shout.authors = [ - author for author in shout.authors if author.id != author_id - ] + shout.authors = [author for author in shout.authors if author.id != author_id] session.commit() return {} return {"error": "Access denied"} diff --git a/resolvers/community.py b/resolvers/community.py index 219b5604..0c057b16 100644 --- a/resolvers/community.py +++ b/resolvers/community.py @@ -14,9 +14,7 @@ def get_communities_from_query(q): for [c, shouts_stat, followers_stat] in session.execute(q): c.stat = { "shouts": session.execute( - select(func.count(distinct(ShoutCommunity.shout))).filter( - ShoutCommunity.community == c.id - ) + select(func.count(distinct(ShoutCommunity.shout))).filter(ShoutCommunity.community == c.id) ), # "authors": session.execute(select(func.count(distinct(ShoutCommunity.shout))).filter(ShoutCommunity.community == c.id)), # "followers": session.execute(select(func.count(distinct(ShoutCommunity.shout))).filter(ShoutCommunity.community == c.id)), diff --git a/resolvers/editor.py b/resolvers/editor.py index af7dacc4..dd3544b4 100644 --- a/resolvers/editor.py +++ b/resolvers/editor.py @@ -57,16 +57,12 @@ async def get_my_shout(_, info, shout_id: int): if not shout: return {"error": "no shout found", "shout": None} - logger.debug( - f"got shout authors: {shout.authors} created by {shout.created_by}" - ) + logger.debug(f"got shout authors: {shout.authors} created by {shout.created_by}") is_editor = "editor" in roles logger.debug(f'viewer is{'' if is_editor else ' not'} editor') is_creator = author_id == shout.created_by logger.debug(f'viewer is{'' if is_creator else ' not'} creator') - is_author = bool( - list(filter(lambda x: x.id == int(author_id), [x for x in shout.authors])) - ) + is_author = bool(list(filter(lambda x: x.id == int(author_id), [x for x in shout.authors]))) logger.debug(f'viewer is{'' if is_creator else ' not'} author') can_edit = is_editor or is_author or is_creator @@ -91,9 +87,7 @@ async def get_shouts_drafts(_, info): q = ( select(Shout) .options(joinedload(Shout.authors), joinedload(Shout.topics)) - .filter( - and_(Shout.deleted_at.is_(None), Shout.created_by == int(author_id)) - ) + .filter(and_(Shout.deleted_at.is_(None), Shout.created_by == int(author_id))) .filter(Shout.published_at.is_(None)) .order_by(desc(coalesce(Shout.updated_at, Shout.created_at))) .group_by(Shout.id) @@ -129,18 +123,10 @@ async def create_shout(_, info, inp): "published_at": None, "created_at": current_time, # Set created_at as Unix timestamp } - same_slug_shout = ( - session.query(Shout) - .filter(Shout.slug == shout_dict.get("slug")) - .first() - ) + same_slug_shout = session.query(Shout).filter(Shout.slug == shout_dict.get("slug")).first() c = 1 while same_slug_shout is not None: - same_slug_shout = ( - session.query(Shout) - .filter(Shout.slug == shout_dict.get("slug")) - .first() - ) + same_slug_shout = session.query(Shout).filter(Shout.slug == shout_dict.get("slug")).first() c += 1 shout_dict["slug"] += f"-{c}" new_shout = Shout(**shout_dict) @@ -153,11 +139,7 @@ async def create_shout(_, info, inp): sa = ShoutAuthor(shout=shout.id, author=author_id) session.add(sa) - topics = ( - session.query(Topic) - .filter(Topic.slug.in_(inp.get("topics", []))) - .all() - ) + topics = session.query(Topic).filter(Topic.slug.in_(inp.get("topics", []))).all() for topic in topics: t = ShoutTopic(topic=topic.id, shout=shout.id) session.add(t) @@ -176,18 +158,11 @@ async def create_shout(_, info, inp): def patch_main_topic(session, main_topic, shout): with session.begin(): - shout = ( - session.query(Shout) - .options(joinedload(Shout.topics)) - .filter(Shout.id == shout.id) - .first() - ) + shout = session.query(Shout).options(joinedload(Shout.topics)).filter(Shout.id == shout.id).first() if not shout: return old_main_topic = ( - session.query(ShoutTopic) - .filter(and_(ShoutTopic.shout == shout.id, ShoutTopic.main.is_(True))) - .first() + session.query(ShoutTopic).filter(and_(ShoutTopic.shout == shout.id, ShoutTopic.main.is_(True))).first() ) main_topic = session.query(Topic).filter(Topic.slug == main_topic).first() @@ -195,19 +170,11 @@ def patch_main_topic(session, main_topic, shout): if main_topic: new_main_topic = ( session.query(ShoutTopic) - .filter( - and_( - ShoutTopic.shout == shout.id, ShoutTopic.topic == main_topic.id - ) - ) + .filter(and_(ShoutTopic.shout == shout.id, ShoutTopic.topic == main_topic.id)) .first() ) - if ( - old_main_topic - and new_main_topic - and old_main_topic is not new_main_topic - ): + if old_main_topic and new_main_topic and old_main_topic is not new_main_topic: ShoutTopic.update(old_main_topic, {"main": False}) session.add(old_main_topic) @@ -216,9 +183,7 @@ def patch_main_topic(session, main_topic, shout): def patch_topics(session, shout, topics_input): - new_topics_to_link = [ - Topic(**new_topic) for new_topic in topics_input if new_topic["id"] < 0 - ] + new_topics_to_link = [Topic(**new_topic) for new_topic in topics_input if new_topic["id"] < 0] if new_topics_to_link: session.add_all(new_topics_to_link) session.commit() @@ -227,9 +192,7 @@ def patch_topics(session, shout, topics_input): created_unlinked_topic = ShoutTopic(shout=shout.id, topic=new_topic_to_link.id) session.add(created_unlinked_topic) - existing_topics_input = [ - topic_input for topic_input in topics_input if topic_input.get("id", 0) > 0 - ] + existing_topics_input = [topic_input for topic_input in topics_input if topic_input.get("id", 0) > 0] existing_topic_to_link_ids = [ existing_topic_input["id"] for existing_topic_input in existing_topics_input @@ -237,9 +200,7 @@ def patch_topics(session, shout, topics_input): ] for existing_topic_to_link_id in existing_topic_to_link_ids: - created_unlinked_topic = ShoutTopic( - shout=shout.id, topic=existing_topic_to_link_id - ) + created_unlinked_topic = ShoutTopic(shout=shout.id, topic=existing_topic_to_link_id) session.add(created_unlinked_topic) topic_to_unlink_ids = [ @@ -276,24 +237,15 @@ async def update_shout(_, info, shout_id: int, shout_input=None, publish=False): if not shout_by_id: return {"error": "shout not found"} if slug != shout_by_id.slug: - same_slug_shout = ( - session.query(Shout).filter(Shout.slug == slug).first() - ) + same_slug_shout = session.query(Shout).filter(Shout.slug == slug).first() c = 1 while same_slug_shout is not None: c += 1 slug = f"{slug}-{c}" - same_slug_shout = ( - session.query(Shout).filter(Shout.slug == slug).first() - ) + same_slug_shout = session.query(Shout).filter(Shout.slug == slug).first() shout_input["slug"] = slug - if ( - filter( - lambda x: x.id == author_id, [x for x in shout_by_id.authors] - ) - or "editor" in roles - ): + if filter(lambda x: x.id == author_id, [x for x in shout_by_id.authors]) or "editor" in roles: # topics patch topics_input = shout_input.get("topics") if topics_input: @@ -376,17 +328,9 @@ async def delete_shout(_, info, shout_id: int): 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() - ) + 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 - ): + if replied_reaction and replied_reaction.kind is ReactionKind.PROPOSE.value and replied_reaction.quote: # patch all the proposals' quotes proposals = ( session.query(Reaction) @@ -403,9 +347,7 @@ def handle_proposing(session, r, shout): 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 - ) + proposal_dict["quote"] = apply_diff(replied_reaction.quote, proposal_diff) Reaction.update(proposal, proposal_dict) session.add(proposal) diff --git a/resolvers/follower.py b/resolvers/follower.py index 1b24219b..c9e96860 100644 --- a/resolvers/follower.py +++ b/resolvers/follower.py @@ -154,9 +154,7 @@ async def get_follows_by_user_id(user_id: str): follows = { "topics": topics, "authors": authors, - "communities": [ - {"id": 1, "name": "Дискурс", "slug": "discours", "pic": ""} - ], + "communities": [{"id": 1, "name": "Дискурс", "slug": "discours", "pic": ""}], } else: logger.debug(f"getting follows for {user_id} from redis") @@ -212,9 +210,7 @@ def reactions_follow(author_id, shout_id, auto=False): ) if not following: - following = ShoutReactionsFollower( - follower=author_id, shout=shout.id, auto=auto - ) + following = ShoutReactionsFollower(follower=author_id, shout=shout.id, auto=auto) session.add(following) session.commit() return None @@ -269,9 +265,7 @@ def author_unfollow(follower_id, slug): flw = ( session.query(AuthorFollower) .join(Author, Author.id == AuthorFollower.author) - .filter( - and_(AuthorFollower.follower == follower_id, Author.slug == slug) - ) + .filter(and_(AuthorFollower.follower == follower_id, Author.slug == slug)) .first() ) if flw: @@ -295,9 +289,7 @@ async def get_topic_followers(_, _info, slug: str) -> List[Author]: @query.field("get_shout_followers") -def get_shout_followers( - _, _info, slug: str = "", shout_id: int | None = None -) -> List[Author]: +def get_shout_followers(_, _info, slug: str = "", shout_id: int | None = None) -> List[Author]: followers = [] with local_session() as session: shout = None diff --git a/resolvers/notifier.py b/resolvers/notifier.py index 8a3b9a91..9cc50149 100644 --- a/resolvers/notifier.py +++ b/resolvers/notifier.py @@ -16,9 +16,7 @@ from services.logger import root_logger as logger from services.schema import mutation, query -def query_notifications( - author_id: int, after: int = 0 -) -> Tuple[int, int, List[Tuple[Notification, bool]]]: +def query_notifications(author_id: int, after: int = 0) -> Tuple[int, int, List[Tuple[Notification, bool]]]: notification_seen_alias = aliased(NotificationSeen) q = select(Notification, notification_seen_alias.viewer.label("seen")).outerjoin( NotificationSeen, @@ -63,9 +61,7 @@ def query_notifications( return total, unread, notifications -def group_notification( - thread, authors=None, shout=None, reactions=None, entity="follower", action="follow" -): +def group_notification(thread, authors=None, shout=None, reactions=None, entity="follower", action="follow"): reactions = reactions or [] authors = authors or [] return { @@ -79,9 +75,7 @@ def group_notification( } -def get_notifications_grouped( - author_id: int, after: int = 0, limit: int = 10, offset: int = 0 -): +def get_notifications_grouped(author_id: int, after: int = 0, limit: int = 10, offset: int = 0): """ Retrieves notifications for a given author. @@ -147,9 +141,7 @@ def get_notifications_grouped( author_id = reaction.get("created_by", 0) if shout_id and author_id: with local_session() as session: - author = ( - session.query(Author).filter(Author.id == author_id).first() - ) + author = session.query(Author).filter(Author.id == author_id).first() shout = session.query(Shout).filter(Shout.id == shout_id).first() if shout and author: author = author.dict() @@ -162,9 +154,7 @@ def get_notifications_grouped( if existing_group: existing_group["seen"] = False existing_group["authors"].append(author_id) - existing_group["reactions"] = ( - existing_group["reactions"] or [] - ) + existing_group["reactions"] = existing_group["reactions"] or [] existing_group["reactions"].append(reaction) groups_by_thread[thread_id] = existing_group else: @@ -217,9 +207,7 @@ async def load_notifications(_, info, after: int, limit: int = 50, offset=0): try: if author_id: groups, unread, total = get_notifications_grouped(author_id, after, limit) - notifications = sorted( - groups.values(), key=lambda group: group.updated_at, reverse=True - ) + notifications = sorted(groups.values(), key=lambda group: group.updated_at, reverse=True) except Exception as e: error = e logger.error(e) @@ -257,11 +245,7 @@ async def notifications_seen_after(_, info, after: int): author_id = info.context.get("author", {}).get("id") if author_id: with local_session() as session: - nnn = ( - session.query(Notification) - .filter(and_(Notification.created_at > after)) - .all() - ) + nnn = session.query(Notification).filter(and_(Notification.created_at > after)).all() for n in nnn: try: ns = NotificationSeen(notification=n.id, viewer=author_id) diff --git a/resolvers/rating.py b/resolvers/rating.py index 21cb4daf..2607edee 100644 --- a/resolvers/rating.py +++ b/resolvers/rating.py @@ -35,9 +35,7 @@ async def rate_author(_, info, rated_slug, value): return {} else: try: - rating = AuthorRating( - rater=rater_id, author=rated_author.id, plus=value > 0 - ) + rating = AuthorRating(rater=rater_id, author=rated_author.id, plus=value > 0) session.add(rating) session.commit() except Exception as err: @@ -105,9 +103,7 @@ def count_author_shouts_rating(session, author_id) -> int: def get_author_rating_old(session, author: Author): likes_count = ( - session.query(AuthorRating) - .filter(and_(AuthorRating.author == author.id, AuthorRating.plus.is_(True))) - .count() + session.query(AuthorRating).filter(and_(AuthorRating.author == author.id, AuthorRating.plus.is_(True))).count() ) dislikes_count = ( session.query(AuthorRating) @@ -167,9 +163,7 @@ def get_author_rating_comments(session, author: Author) -> int: and_( replied_comment.kind == ReactionKind.COMMENT.value, replied_comment.created_by == author.id, - Reaction.kind.in_( - [ReactionKind.LIKE.value, ReactionKind.DISLIKE.value] - ), + Reaction.kind.in_([ReactionKind.LIKE.value, ReactionKind.DISLIKE.value]), Reaction.reply_to == replied_comment.id, Reaction.deleted_at.is_(None), ), @@ -184,9 +178,7 @@ def add_author_rating_columns(q, group_list): # old karma q = q.outerjoin(AuthorRating, AuthorRating.author == Author.id) - q = q.add_columns( - func.sum(case((AuthorRating.plus == true(), 1), else_=-1)).label("rating") - ) + q = q.add_columns(func.sum(case((AuthorRating.plus == true(), 1), else_=-1)).label("rating")) # by shouts rating shout_reaction = aliased(Reaction) @@ -243,9 +235,7 @@ def add_author_rating_columns(q, group_list): and_( replied_comment.kind == ReactionKind.COMMENT.value, replied_comment.created_by == Author.id, - reaction_2.kind.in_( - [ReactionKind.LIKE.value, ReactionKind.DISLIKE.value] - ), + reaction_2.kind.in_([ReactionKind.LIKE.value, ReactionKind.DISLIKE.value]), reaction_2.reply_to == replied_comment.id, reaction_2.deleted_at.is_(None), ), diff --git a/resolvers/reaction.py b/resolvers/reaction.py index 0b369cd6..5d87745a 100644 --- a/resolvers/reaction.py +++ b/resolvers/reaction.py @@ -23,15 +23,9 @@ from services.viewed import ViewedStorage def add_reaction_stat_columns(q, aliased_reaction): q = q.outerjoin(aliased_reaction).add_columns( func.sum(aliased_reaction.id).label("reacted_stat"), - func.sum( - case((aliased_reaction.kind == str(ReactionKind.COMMENT.value), 1), else_=0) - ).label("comments_stat"), - func.sum( - case((aliased_reaction.kind == str(ReactionKind.LIKE.value), 1), else_=0) - ).label("likes_stat"), - func.sum( - case((aliased_reaction.kind == str(ReactionKind.DISLIKE.value), 1), else_=0) - ).label("dislikes_stat"), + func.sum(case((aliased_reaction.kind == str(ReactionKind.COMMENT.value), 1), else_=0)).label("comments_stat"), + func.sum(case((aliased_reaction.kind == str(ReactionKind.LIKE.value), 1), else_=0)).label("likes_stat"), + func.sum(case((aliased_reaction.kind == str(ReactionKind.DISLIKE.value), 1), else_=0)).label("dislikes_stat"), func.max( case( (aliased_reaction.kind != str(ReactionKind.COMMENT.value), None), @@ -60,9 +54,7 @@ def check_to_feature(session, approver_id, reaction): if is_featured_author(session, approver_id): approvers = [approver_id] # now count how many approvers are voted already - reacted_readers = ( - session.query(Reaction).where(Reaction.shout == reaction.shout).all() - ) + reacted_readers = session.query(Reaction).where(Reaction.shout == reaction.shout).all() for reacted_reader in reacted_readers: if is_featured_author(session, reacted_reader.id): approvers.append(reacted_reader.id) @@ -87,9 +79,7 @@ def check_to_unfeature(session, rejecter_id, reaction): ) rejects = 0 for r in reactions: - approver = ( - session.query(Author).filter(Author.id == r.created_by).first() - ) + approver = session.query(Author).filter(Author.id == r.created_by).first() if is_featured_author(session, approver): if is_negative(r.kind): rejects += 1 @@ -127,11 +117,7 @@ async def _create_reaction(session, shout, author_id: int, reaction): await update_author_stat(author_id) # collaborative editing - if ( - rdict.get("reply_to") - and r.kind in PROPOSAL_REACTIONS - and author_id in shout.authors - ): + if rdict.get("reply_to") and r.kind in PROPOSAL_REACTIONS and author_id in shout.authors: handle_proposing(session, r, shout) # рейтинг и саморегуляция @@ -165,9 +151,7 @@ async def _create_reaction(session, shout, author_id: int, reaction): def prepare_new_rating(reaction: dict, shout_id: int, session, author_id: int): kind = reaction.get("kind") - opposite_kind = ( - ReactionKind.DISLIKE.value if is_positive(kind) else ReactionKind.LIKE.value - ) + opposite_kind = ReactionKind.DISLIKE.value if is_positive(kind) else ReactionKind.LIKE.value q = select(Reaction).filter( and_( @@ -226,9 +210,7 @@ async def create_reaction(_, info, reaction): return {"error": "cannot create reaction without a kind"} if kind in RATING_REACTIONS: - error_result = prepare_new_rating( - reaction, shout_id, session, author_id - ) + error_result = prepare_new_rating(reaction, shout_id, session, author_id) if error_result: return error_result @@ -275,9 +257,7 @@ async def update_reaction(_, info, reaction): if not r: return {"error": "invalid reaction id"} - author = ( - session.query(Author).filter(Author.user == user_id).first() - ) + author = session.query(Author).filter(Author.user == user_id).first() if author: if r.created_by != author.id and "editor" not in roles: return {"error": "access denied"} @@ -460,9 +440,7 @@ async def reacted_shouts_updates(follower_id: int, limit=50, offset=0) -> List[S select(Shout) .outerjoin( Reaction, - and_( - Reaction.shout == Shout.id, Reaction.created_by == follower_id - ), + and_(Reaction.shout == Shout.id, Reaction.created_by == follower_id), ) .outerjoin(Author, Shout.authors.any(id=follower_id)) .options(joinedload(Shout.reactions), joinedload(Shout.authors)) @@ -481,12 +459,7 @@ async def reacted_shouts_updates(follower_id: int, limit=50, offset=0) -> List[S q2 = add_reaction_stat_columns(q2, aliased(Reaction)) # Sort shouts by the `last_comment` field - combined_query = ( - union(q1, q2) - .order_by(desc(text("last_comment_stat"))) - .limit(limit) - .offset(offset) - ) + combined_query = union(q1, q2).order_by(desc(text("last_comment_stat"))).limit(limit).offset(offset) results = session.execute(combined_query).scalars() for [ diff --git a/resolvers/reader.py b/resolvers/reader.py index 2caa5412..b350595b 100644 --- a/resolvers/reader.py +++ b/resolvers/reader.py @@ -28,21 +28,14 @@ def filter_my(info, session, q): user_id = info.context.get("user_id") reader_id = info.context.get("author", {}).get("id") if user_id and reader_id: - reader_followed_authors = select(AuthorFollower.author).where( - AuthorFollower.follower == reader_id - ) - reader_followed_topics = select(TopicFollower.topic).where( - TopicFollower.follower == reader_id - ) + reader_followed_authors = select(AuthorFollower.author).where(AuthorFollower.follower == reader_id) + reader_followed_topics = select(TopicFollower.topic).where(TopicFollower.follower == reader_id) subquery = ( select(Shout.id) .where(Shout.id == ShoutAuthor.shout) .where(Shout.id == ShoutTopic.shout) - .where( - (ShoutAuthor.author.in_(reader_followed_authors)) - | (ShoutTopic.topic.in_(reader_followed_topics)) - ) + .where((ShoutAuthor.author.in_(reader_followed_authors)) | (ShoutTopic.topic.in_(reader_followed_topics))) ) q = q.filter(Shout.id.in_(subquery)) return q, reader_id @@ -188,9 +181,7 @@ async def load_shouts_by(_, _info, options): order_str = options.get("order_by") if order_str in ["likes", "followers", "comments", "last_comment"]: q = q.order_by(desc(text(f"{order_str}_stat"))) - query_order_by = ( - desc(order_by) if options.get("order_by_desc", True) else asc(order_by) - ) + query_order_by = desc(order_by) if options.get("order_by_desc", True) else asc(order_by) q = q.order_by(nulls_last(query_order_by)) # limit offset @@ -257,20 +248,13 @@ async def load_shouts_feed(_, info, options): Shout.featured_at if filters.get("featured") else Shout.published_at, ) - query_order_by = ( - desc(order_by) if options.get("order_by_desc", True) else asc(order_by) - ) + query_order_by = desc(order_by) if options.get("order_by_desc", True) else asc(order_by) # pagination offset = options.get("offset", 0) limit = options.get("limit", 10) - q = ( - q.group_by(Shout.id) - .order_by(nulls_last(query_order_by)) - .limit(limit) - .offset(offset) - ) + q = q.group_by(Shout.id).order_by(nulls_last(query_order_by)).limit(limit).offset(offset) logger.debug(q.compile(compile_kwargs={"literal_binds": True})) @@ -328,9 +312,7 @@ async def load_shouts_unrated(_, info, limit: int = 50, offset: int = 0): and_( Reaction.shout == Shout.id, Reaction.reply_to.is_(None), - Reaction.kind.in_( - [ReactionKind.LIKE.value, ReactionKind.DISLIKE.value] - ), + Reaction.kind.in_([ReactionKind.LIKE.value, ReactionKind.DISLIKE.value]), ), ) .outerjoin(Author, Author.user == bindparam("user_id")) @@ -403,9 +385,7 @@ async def load_shouts_random_top(_, _info, options): aliased_reaction = aliased(Reaction) subquery = ( - select(Shout.id) - .outerjoin(aliased_reaction) - .where(and_(Shout.deleted_at.is_(None), Shout.layout.is_not(None))) + select(Shout.id).outerjoin(aliased_reaction).where(and_(Shout.deleted_at.is_(None), Shout.layout.is_not(None))) ) subquery = apply_filters(subquery, options.get("filters", {})) @@ -428,11 +408,7 @@ async def load_shouts_random_top(_, _info, options): if random_limit: subquery = subquery.limit(random_limit) - q = ( - select(Shout) - .options(joinedload(Shout.authors), joinedload(Shout.topics)) - .where(Shout.id.in_(subquery)) - ) + q = select(Shout).options(joinedload(Shout.authors), joinedload(Shout.topics)).where(Shout.id.in_(subquery)) q = add_reaction_stat_columns(q, aliased_reaction) diff --git a/resolvers/stat.py b/resolvers/stat.py index 79fa23e7..3c434e42 100644 --- a/resolvers/stat.py +++ b/resolvers/stat.py @@ -12,9 +12,7 @@ from services.logger import root_logger as logger def add_topic_stat_columns(q): aliased_shout = aliased(ShoutTopic) - q = q.outerjoin(aliased_shout).add_columns( - func.count(distinct(aliased_shout.shout)).label("shouts_stat") - ) + q = q.outerjoin(aliased_shout).add_columns(func.count(distinct(aliased_shout.shout)).label("shouts_stat")) aliased_follower = aliased(TopicFollower) q = q.outerjoin(aliased_follower, aliased_follower.topic == Topic.id).add_columns( func.count(distinct(aliased_follower.follower)).label("followers_stat") @@ -27,9 +25,7 @@ def add_topic_stat_columns(q): def add_author_stat_columns(q): aliased_shout = aliased(ShoutAuthor) - q = q.outerjoin(aliased_shout).add_columns( - func.count(distinct(aliased_shout.shout)).label("shouts_stat") - ) + q = q.outerjoin(aliased_shout).add_columns(func.count(distinct(aliased_shout.shout)).label("shouts_stat")) aliased_follower = aliased(AuthorFollower) q = q.outerjoin(aliased_follower, aliased_follower.author == Author.id).add_columns( func.count(distinct(aliased_follower.follower)).label("followers_stat") @@ -79,9 +75,7 @@ def get_topic_authors_stat(topic_id: int): def get_topic_followers_stat(topic_id: int): aliased_followers = aliased(TopicFollower) - q = select(func.count(distinct(aliased_followers.follower))).filter( - aliased_followers.topic == topic_id - ) + q = select(func.count(distinct(aliased_followers.follower))).filter(aliased_followers.topic == topic_id) with local_session() as session: result = session.execute(q).first() return result[0] if result else 0 @@ -106,9 +100,7 @@ def get_topic_comments_stat(topic_id: int): .group_by(Shout.id) .subquery() ) - q = select(func.coalesce(func.sum(sub_comments.c.comments_count), 0)).filter( - ShoutTopic.topic == topic_id - ) + q = select(func.coalesce(func.sum(sub_comments.c.comments_count), 0)).filter(ShoutTopic.topic == topic_id) q = q.outerjoin(sub_comments, ShoutTopic.shout == sub_comments.c.shout_id) with local_session() as session: result = session.execute(q).first() @@ -152,9 +144,7 @@ def get_author_authors_stat(author_id: int): def get_author_followers_stat(author_id: int): aliased_followers = aliased(AuthorFollower) - q = select(func.count(distinct(aliased_followers.follower))).filter( - aliased_followers.author == author_id - ) + q = select(func.count(distinct(aliased_followers.follower))).filter(aliased_followers.author == author_id) with local_session() as session: result = session.execute(q).first() return result[0] if result else 0 @@ -162,9 +152,7 @@ def get_author_followers_stat(author_id: int): def get_author_comments_stat(author_id: int): sub_comments = ( - select( - Author.id, func.coalesce(func.count(Reaction.id)).label("comments_count") - ) + select(Author.id, func.coalesce(func.count(Reaction.id)).label("comments_count")) .select_from(Author) # явно указываем левый элемент join'а .outerjoin( Reaction, @@ -219,9 +207,7 @@ def get_with_stat(q): def author_follows_authors(author_id: int): af = aliased(AuthorFollower, name="af") author_follows_authors_query = ( - select(Author) - .select_from(join(Author, af, Author.id == af.author)) - .where(af.follower == author_id) + select(Author).select_from(join(Author, af, Author.id == af.author)).where(af.follower == author_id) ) return get_with_stat(author_follows_authors_query) diff --git a/resolvers/topic.py b/resolvers/topic.py index e7907247..afd89f05 100644 --- a/resolvers/topic.py +++ b/resolvers/topic.py @@ -38,17 +38,11 @@ def get_topics_by_community(_, _info, community_id: int): async def get_topics_by_author(_, _info, author_id=0, slug="", user=""): topics_by_author_query = select(Topic) if author_id: - topics_by_author_query = topics_by_author_query.join(Author).where( - Author.id == author_id - ) + topics_by_author_query = topics_by_author_query.join(Author).where(Author.id == author_id) elif slug: - topics_by_author_query = topics_by_author_query.join(Author).where( - Author.slug == slug - ) + topics_by_author_query = topics_by_author_query.join(Author).where(Author.slug == slug) elif user: - topics_by_author_query = topics_by_author_query.join(Author).where( - Author.user == user - ) + topics_by_author_query = topics_by_author_query.join(Author).where(Author.user == user) return get_with_stat(topics_by_author_query) diff --git a/services/cache.py b/services/cache.py index fd9d5616..01587b1e 100644 --- a/services/cache.py +++ b/services/cache.py @@ -26,9 +26,7 @@ async def cache_author(author: dict): if isinstance(followers, list): for follower in followers: follower_follows_authors = [] - follower_follows_authors_str = await redis.execute( - "GET", f"author:{author_id}:follows-authors" - ) + follower_follows_authors_str = await redis.execute("GET", f"author:{author_id}:follows-authors") if isinstance(follower_follows_authors_str, str): follower_follows_authors = json.loads(follower_follows_authors_str) c = 0 @@ -49,9 +47,7 @@ async def cache_author(author: dict): if isinstance(follows_authors, list): for followed_author in follows_authors: followed_author_followers = [] - followed_author_followers_str = await redis.execute( - "GET", f"author:{author_id}:followers" - ) + followed_author_followers_str = await redis.execute("GET", f"author:{author_id}:followers") if isinstance(followed_author_followers_str, str): followed_author_followers = json.loads(followed_author_followers_str) c = 0 @@ -139,18 +135,11 @@ async def cache_follow_author_change(follower: dict, author: dict, is_insert=Tru async def cache_topic(topic_dict: dict): # update stat all field for followers' caches in list - followers = ( - local_session() - .query(TopicFollower) - .filter(TopicFollower.topic == topic_dict.get("id")) - .all() - ) + followers = local_session().query(TopicFollower).filter(TopicFollower.topic == topic_dict.get("id")).all() for tf in followers: follower_id = tf.follower follower_follows_topics = [] - follower_follows_topics_str = await redis.execute( - "GET", f"author:{follower_id}:follows-topics" - ) + follower_follows_topics_str = await redis.execute("GET", f"author:{follower_id}:follows-topics") if isinstance(follower_follows_topics_str, str): follower_follows_topics = json.loads(follower_follows_topics_str) c = 0 diff --git a/services/db.py b/services/db.py index d71e8142..7d37e45a 100644 --- a/services/db.py +++ b/services/db.py @@ -45,9 +45,7 @@ class Base(declarative_base()): REGISTRY[cls.__name__] = cls def dict(self) -> Dict[str, Any]: - column_names = filter( - lambda x: x not in FILTERED_FIELDS, self.__table__.columns.keys() - ) + column_names = filter(lambda x: x not in FILTERED_FIELDS, self.__table__.columns.keys()) try: data = {} for c in column_names: @@ -76,9 +74,7 @@ Base.metadata.create_all(bind=engine) # Функция для вывода полного трейсбека при предупреждениях -def warning_with_traceback( - message: Warning | str, category, filename: str, lineno: int, file=None, line=None -): +def warning_with_traceback(message: Warning | str, category, filename: str, lineno: int, file=None, line=None): tb = traceback.format_stack() tb_str = "".join(tb) return f"{message} ({filename}, {lineno}): {category.__name__}\n{tb_str}" diff --git a/services/search.py b/services/search.py index 5a97906b..a29e216a 100644 --- a/services/search.py +++ b/services/search.py @@ -127,9 +127,7 @@ class SearchService: logger.debug(f"Проверяем индекс {self.index_name}...") if not self.client.indices.exists(index=self.index_name): self.create_index() - self.client.indices.put_mapping( - index=self.index_name, body=expected_mapping - ) + self.client.indices.put_mapping(index=self.index_name, body=expected_mapping) else: logger.info(f"Найден существующий индекс {self.index_name}") # Проверка и обновление структуры индекса, если необходимо @@ -138,17 +136,9 @@ class SearchService: result = json.loads(result) if isinstance(result, dict): mapping = result.get(self.index_name, {}).get("mappings") - logger.debug( - f"Найдена структура индексации: {mapping['properties'].keys()}" - ) - if ( - mapping - and mapping["properties"].keys() - != expected_mapping["properties"].keys() - ): - logger.debug( - f"Ожидаемая структура индексации: {expected_mapping}" - ) + logger.debug(f"Найдена структура индексации: {mapping['properties'].keys()}") + if mapping and mapping["properties"].keys() != expected_mapping["properties"].keys(): + logger.debug(f"Ожидаемая структура индексации: {expected_mapping}") logger.warn("[!!!] Требуется переиндексация всех данных") self.delete_index() self.client = None @@ -177,9 +167,7 @@ class SearchService: logger.debug(f"Ищем: {text}") search_body = {"query": {"match": {"_all": text}}} if self.client: - search_response = self.client.search( - index=self.index_name, body=search_body, size=limit, from_=offset - ) + search_response = self.client.search(index=self.index_name, body=search_body, size=limit, from_=offset) hits = search_response["hits"]["hits"] results = [{**hit["_source"], "score": hit["_score"]} for hit in hits] diff --git a/services/triggers.py b/services/triggers.py index cdeb9087..ca8599c0 100644 --- a/services/triggers.py +++ b/services/triggers.py @@ -20,9 +20,7 @@ DEFAULT_FOLLOWS = { } -async def handle_author_follower_change( - author_id: int, follower_id: int, is_insert: bool -): +async def handle_author_follower_change(author_id: int, follower_id: int, is_insert: bool): logger.info(author_id) author_query = select(Author).select_from(Author).filter(Author.id == author_id) [author] = get_with_stat(author_query) @@ -30,17 +28,13 @@ async def handle_author_follower_change( [follower] = get_with_stat(follower_query) if follower and author: await cache_author(author.dict()) - await cache_follows( - follower.dict(), "author", author.dict(), is_insert - ) # cache_author(follower_dict) inside + await cache_follows(follower.dict(), "author", author.dict(), is_insert) # cache_author(follower_dict) inside await cache_follow_author_change( follower.dict(), author.dict(), is_insert ) # cache_author(follower_dict) inside -async def handle_topic_follower_change( - topic_id: int, follower_id: int, is_insert: bool -): +async def handle_topic_follower_change(topic_id: int, follower_id: int, is_insert: bool): logger.info(topic_id) topic_query = select(Topic).filter(Topic.id == topic_id) [topic] = get_with_stat(topic_query) @@ -48,9 +42,7 @@ async def handle_topic_follower_change( [follower] = get_with_stat(follower_query) if follower and topic: await cache_author(follower.dict()) - await redis.execute( - "SET", f"topic:{topic.id}", json.dumps(topic.dict(), cls=CustomJSONEncoder) - ) + await redis.execute("SET", f"topic:{topic.id}", json.dumps(topic.dict(), cls=CustomJSONEncoder)) await cache_follows(follower.dict(), "topic", topic.dict(), is_insert) @@ -84,9 +76,7 @@ def after_reaction_update(mapper, connection, reaction: Reaction): # reaction repliers replied_author_subquery = ( - select(Author) - .join(Reaction, Author.id == Reaction.created_by) - .where(Reaction.id == reaction.reply_to) + select(Author).join(Reaction, Author.id == Reaction.created_by).where(Reaction.id == reaction.reply_to) ) authors_with_stat = get_with_stat(replied_author_subquery) for author_with_stat in authors_with_stat: diff --git a/services/viewed.py b/services/viewed.py index f04de2db..15723a5f 100644 --- a/services/viewed.py +++ b/services/viewed.py @@ -60,25 +60,19 @@ class ViewedStorage: try: if os.path.exists(VIEWS_FILEPATH): start_date_int = os.path.getmtime(VIEWS_FILEPATH) - start_date_str = datetime.fromtimestamp(start_date_int).strftime( - "%Y-%m-%d" - ) + start_date_str = datetime.fromtimestamp(start_date_int).strftime("%Y-%m-%d") self.start_date = start_date_str now_date = datetime.now().strftime("%Y-%m-%d") if now_date == self.start_date: logger.info(" * Данные актуализованы!") else: - logger.warn( - f" * Файл просмотров {VIEWS_FILEPATH} устарел: {self.start_date}" - ) + logger.warn(f" * Файл просмотров {VIEWS_FILEPATH} устарел: {self.start_date}") with open(VIEWS_FILEPATH, "r") as file: precounted_views = json.load(file) self.views_by_shout.update(precounted_views) - logger.info( - f" * {len(precounted_views)} публикаций с просмотрами успешно загружены." - ) + logger.info(f" * {len(precounted_views)} публикаций с просмотрами успешно загружены.") else: logger.info(" * Файл просмотров не найден.") except Exception as e: @@ -99,9 +93,7 @@ class ViewedStorage: property=f"properties/{GOOGLE_PROPERTY_ID}", dimensions=[Dimension(name="pagePath")], metrics=[Metric(name="screenPageViews")], - date_ranges=[ - DateRange(start_date=self.start_date, end_date="today") - ], + date_ranges=[DateRange(start_date=self.start_date, end_date="today")], ) response = self.analytics_client.run_report(request) if response and isinstance(response.rows, list): @@ -118,9 +110,7 @@ class ViewedStorage: views_count = int(row.metric_values[0].value) # Обновление данных в хранилище - self.views_by_shout[slug] = self.views_by_shout.get( - slug, 0 - ) + self.views_by_shout[slug] = self.views_by_shout.get(slug, 0) self.views_by_shout[slug] += views_count self.update_topics(slug) @@ -179,20 +169,12 @@ class ViewedStorage: # Обновление тем и авторов с использованием вспомогательной функции for [_shout_topic, topic] in ( - session.query(ShoutTopic, Topic) - .join(Topic) - .join(Shout) - .where(Shout.slug == shout_slug) - .all() + session.query(ShoutTopic, Topic).join(Topic).join(Shout).where(Shout.slug == shout_slug).all() ): update_groups(self.shouts_by_topic, topic.slug, shout_slug) for [_shout_topic, author] in ( - session.query(ShoutAuthor, Author) - .join(Author) - .join(Shout) - .where(Shout.slug == shout_slug) - .all() + session.query(ShoutAuthor, Author).join(Author).join(Shout).where(Shout.slug == shout_slug).all() ): update_groups(self.shouts_by_author, author.slug, shout_slug) @@ -219,8 +201,7 @@ class ViewedStorage: when = datetime.now(timezone.utc) + timedelta(seconds=self.period) t = format(when.astimezone().isoformat()) logger.info( - " ⎩ Следующее обновление: %s" - % (t.split("T")[0] + " " + t.split("T")[1].split(".")[0]) + " ⎩ Следующее обновление: %s" % (t.split("T")[0] + " " + t.split("T")[1].split(".")[0]) ) await asyncio.sleep(self.period) else: diff --git a/services/webhook.py b/services/webhook.py index acd526fd..7cc29820 100644 --- a/services/webhook.py +++ b/services/webhook.py @@ -21,15 +21,11 @@ class WebhookEndpoint(HTTPEndpoint): raise HTTPException(status_code=400, detail="Request body is empty") auth = request.headers.get("Authorization") if not auth or auth != os.environ.get("WEBHOOK_SECRET"): - raise HTTPException( - status_code=401, detail="Invalid Authorization header" - ) + raise HTTPException(status_code=401, detail="Invalid Authorization header") # logger.debug(data) user = data.get("user") if not isinstance(user, dict): - raise HTTPException( - status_code=400, detail="User data is not a dictionary" - ) + raise HTTPException(status_code=400, detail="User data is not a dictionary") # name: str = ( f"{user.get('given_name', user.get('slug'))} {user.get('middle_name', '')}" @@ -40,19 +36,13 @@ class WebhookEndpoint(HTTPEndpoint): pic: str = user.get("picture", "") if user_id: with local_session() as session: - author = ( - session.query(Author).filter(Author.user == user_id).first() - ) + author = session.query(Author).filter(Author.user == user_id).first() if not author: # If the author does not exist, create a new one slug: str = email.split("@")[0].replace(".", "-").lower() slug: str = re.sub("[^0-9a-z]+", "-", slug) while True: - author = ( - session.query(Author) - .filter(Author.slug == slug) - .first() - ) + author = session.query(Author).filter(Author.slug == slug).first() if not author: break slug = f"{slug}-{len(session.query(Author).filter(Author.email == email).all()) + 1}" @@ -66,9 +56,7 @@ class WebhookEndpoint(HTTPEndpoint): return JSONResponse({"status": "success"}) except HTTPException as e: - return JSONResponse( - {"status": "error", "message": str(e.detail)}, status_code=e.status_code - ) + return JSONResponse({"status": "error", "message": str(e.detail)}, status_code=e.status_code) except Exception as e: import traceback