diff --git a/orm/shout.py b/orm/shout.py index ae276d61..a6ebf6a1 100644 --- a/orm/shout.py +++ b/orm/shout.py @@ -18,6 +18,8 @@ class ShoutCommentsSubscription(Base): subscriber = Column(ForeignKey('user.slug'), primary_key = True) shout = Column(ForeignKey('shout.slug'), primary_key = True) createdAt: str = Column(DateTime, nullable=False, default = datetime.now, comment="Created at") + auto = Column(Boolean, nullable=False, default = False) + deletedAt: str = Column(DateTime, nullable=True) class ShoutAuthor(Base): __tablename__ = "shout_author" diff --git a/resolvers/__init__.py b/resolvers/__init__.py index 7d164795..0941c76b 100644 --- a/resolvers/__init__.py +++ b/resolvers/__init__.py @@ -2,7 +2,7 @@ from resolvers.auth import login, sign_out, is_email_used, register, confirm, au from resolvers.zine import get_shout_by_slug, subscribe, unsubscribe, view_shout, rate_shout, \ top_month, top_overall, recent_published, recent_all, top_viewed, \ shouts_by_authors, shouts_by_topics, shouts_by_communities -from resolvers.profile import get_users_by_slugs, get_current_user, shouts_reviewed, shout_comments_subscribed +from resolvers.profile import get_users_by_slugs, get_current_user, shouts_reviewed from resolvers.topics import topic_subscribe, topic_unsubscribe, topics_by_author, \ topics_by_community, topics_by_slugs from resolvers.comments import create_comment, delete_comment, update_comment, rate_comment @@ -31,7 +31,6 @@ __all__ = [ "shouts_by_topics", "shouts_by_authors", "shouts_by_communities", - "shout_comments_subscribed", "shouts_reviewed", "top_month", "top_overall", diff --git a/resolvers/comments.py b/resolvers/comments.py index 29a4163c..dc426a01 100644 --- a/resolvers/comments.py +++ b/resolvers/comments.py @@ -6,71 +6,55 @@ from auth.authenticate import login_required import asyncio from datetime import datetime -class CommentResult: - def __init__(self, status, comment): - self.status = status - self.comment = comment +def comments_subscribe(user, slug, auto = False): + with local_session() as session: + sub = session.query(ShoutCommentsSubscription).\ + filter(ShoutCommentsSubscription.subscriber == user.slug, ShoutCommentsSubscription.shout == slug).\ + first() + if auto and sub: + return + elif not auto and sub: + if not sub.deletedAt is None: + sub.deletedAt = None + sub.auto = False + session.commit() + return + raise Exception("subscription already exist") -class ShoutCommentsSubscription: - queue = asyncio.Queue() - - def __init__(self, shout_slug): - self.shout_slug = shout_slug - -class ShoutCommentsStorage: - lock = asyncio.Lock() - subscriptions = [] - - @staticmethod - async def register_subscription(subs): - self = ShoutCommentsStorage - async with self.lock: - self.subscriptions.append(subs) - - @staticmethod - async def del_subscription(subs): - self = ShoutCommentsStorage - async with self.lock: - self.subscriptions.remove(subs) - - @staticmethod - async def put(comment_result): - self = ShoutCommentsStorage - async with self.lock: - for subs in self.subscriptions: - if comment_result.comment.shout == subs.shout_slug: - subs.queue.put_nowait(comment_result) - -def comments_subscribe(user, slug): ShoutCommentsSubscription.create( subscriber = user.slug, - shout = slug) + shout = slug, + auto = auto) def comments_unsubscribe(user, slug): with local_session() as session: sub = session.query(ShoutCommentsSubscription).\ - filter(and_(ShoutCommentsSubscription.subscriber == user.slug, ShoutCommentsSubscription.shout == slug)).\ + filter(ShoutCommentsSubscription.subscriber == user.slug, ShoutCommentsSubscription.shout == slug).\ first() if not sub: raise Exception("subscription not exist") - session.delete(sub) + if sub.auto: + sub.deletedAt = datetime.now() + else: + session.delete(sub) session.commit() @mutation.field("createComment") @login_required async def create_comment(_, info, body, shout, replyTo = None): - auth = info.context["request"].auth - user_id = auth.user_id + user = info.context["request"].user comment = Comment.create( - author = user_id, + author = user.id, body = body, shout = shout, replyTo = replyTo ) - result = CommentResult("NEW", comment) - await ShoutCommentsStorage.put(result) + try: + comments_subscribe(user, shout, True) + except Exception as e: + print(f"error on comment autosubscribe: {e}") return {"comment": comment} @@ -92,9 +76,6 @@ async def update_comment(_, info, id, body): session.commit() - result = CommentResult("UPDATED", comment) - await ShoutCommentsStorage.put(result) - return {"comment": comment} @mutation.field("deleteComment") @@ -113,9 +94,6 @@ async def delete_comment(_, info, id): comment.deletedAt = datetime.now() session.commit() - result = CommentResult("DELETED", comment) - await ShoutCommentsStorage.put(result) - return {} @mutation.field("rateComment") @@ -130,7 +108,7 @@ async def rate_comment(_, info, id, value): return {"error": "invalid comment id"} rating = session.query(CommentRating).\ - filter(CommentRating.comment_id == id and CommentRating.createdBy == user_id).first() + filter(CommentRating.comment_id == id, CommentRating.createdBy == user_id).first() if rating: rating.value = value session.commit() @@ -141,7 +119,12 @@ async def rate_comment(_, info, id, value): createdBy = user_id, value = value) - result = CommentResult("UPDATED_RATING", comment) - await ShoutCommentsStorage.put(result) - return {} + +def get_subscribed_shout_comments(slug): + with local_session() as session: + rows = session.query(ShoutCommentsSubscription.shout).\ + filter(ShoutCommentsSubscription.subscriber == slug, ShoutCommentsSubscription.deletedAt == None).\ + all() + slugs = [row.shout for row in rows] + return slugs diff --git a/resolvers/editor.py b/resolvers/editor.py index 86e7654c..27f9c494 100644 --- a/resolvers/editor.py +++ b/resolvers/editor.py @@ -1,6 +1,7 @@ from orm import Shout, ShoutRating, ShoutRatingStorage from orm.base import local_session from resolvers.base import mutation, query, subscription +from resolvers.comments import comments_subscribe from auth.authenticate import login_required import asyncio from datetime import datetime @@ -19,7 +20,9 @@ async def create_shout(_, info, input): ShoutAuthor.create( shout = new_shout.slug, user = user.slug) - + + comments_subscribe(user, new_shout.slug, True) + if "mainTopic" in input: topic_slugs.append(input["mainTopic"]) @@ -106,4 +109,4 @@ async def delete_shout(_, info, slug): shout.deletedAt = datetime.now() session.commit() - return {} \ No newline at end of file + return {} diff --git a/resolvers/profile.py b/resolvers/profile.py index c22c3b1f..930af9aa 100644 --- a/resolvers/profile.py +++ b/resolvers/profile.py @@ -4,6 +4,8 @@ from orm.comment import Comment from orm.base import local_session from orm.topic import Topic, TopicSubscription from resolvers.base import mutation, query, subscription +from resolvers.community import get_subscribed_communities +from resolvers.comments import get_subscribed_shout_comments from auth.authenticate import login_required from inbox_resolvers.inbox import get_total_unread_messages_for_user @@ -30,10 +32,11 @@ def _get_user_subscribed_authors(slug): async def get_user_info(slug): return { - "totalUnreadMessages" : await get_total_unread_messages_for_user(slug), - "userSubscribedTopics" : _get_user_subscribed_topic_slugs(slug), - "userSubscribedAuthors" : _get_user_subscribed_authors(slug), - "userSubscribedCommunities": get_subscribed_communities(slug) + "totalUnreadMessages" : await get_total_unread_messages_for_user(slug), + "userSubscribedTopics" : _get_user_subscribed_topic_slugs(slug), + "userSubscribedAuthors" : _get_user_subscribed_authors(slug), + "userSubscribedCommunities" : get_subscribed_communities(slug), + "userSubscribedShoutComments": get_subscribed_shout_comments(slug) } @query.field("getCurrentUser") @@ -203,22 +206,6 @@ async def shouts_reviewed(_, info, page, size): return shouts -@query.field("shoutCommentsSubscribed") -@login_required -async def shout_comments_subscribed(_, info, slug, page, size): - user = info.context["request"].user - with local_session() as session: - comments_by_shout = session.query(Comment).\ - join(ShoutCommentsSubscription).\ - join(ShoutCommentsSubscription, ShoutCommentsSubscription.shout == slug).\ - where(ShoutCommentsSubscription.subscriber == user.slug) - comments = comments_by_shout.\ - order_by(desc(Shout.createdAt)).\ - limit(size).\ - offset( (page - 1) * size) - - return shouts - @query.field("shoutsCommentedByUser") async def shouts_commented_by_user(_, info, slug, page, size): user = await UserStorage.get_user_by_slug(slug) diff --git a/resolvers/zine.py b/resolvers/zine.py index 2b0f3d51..1e674492 100644 --- a/resolvers/zine.py +++ b/resolvers/zine.py @@ -7,6 +7,9 @@ from orm.user import UserStorage, AuthorSubscription from orm.topic import TopicSubscription from resolvers.base import mutation, query +from resolvers.profile import author_subscribe, author_unsubscribe +from resolvers.topics import topic_subscribe, topic_unsubscribe +from resolvers.community import community_subscribe, community_unsubscribe from resolvers.comments import comments_subscribe, comments_unsubscribe from auth.authenticate import login_required from settings import SHOUTS_REPO @@ -315,39 +318,39 @@ async def shouts_by_communities(_, info, slugs, page, size): @mutation.field("subscribe") @login_required -async def subscribe(_, info, subscription, slug): +async def subscribe(_, info, what, slug): user = info.context["request"].user try: - if subscription == "AUTHOR": + if what == "AUTHOR": author_subscribe(user, slug) - elif subscription == "TOPIC": + elif what == "TOPIC": topic_subscribe(user, slug) - elif subscription == "COMMUNITY": + elif what == "COMMUNITY": community_subscribe(user, slug) - elif comments_subscription == "COMMENTS": + elif what == "COMMENTS": comments_subscribe(user, slug) except Exception as e: - return {"error" : e} + return {"error" : str(e)} return {} @mutation.field("unsubscribe") @login_required -async def unsubscribe(_, info, subscription, slug): +async def unsubscribe(_, info, what, slug): user = info.context["request"].user try: - if subscription == "AUTHOR": + if what == "AUTHOR": author_unsubscribe(user, slug) - elif subscription == "TOPIC": + elif what == "TOPIC": topic_unsubscribe(user, slug) - elif subscription == "COMMUNITY": + elif what == "COMMUNITY": community_unsubscribe(user, slug) - elif subscription == "COMMENTS": + elif what == "COMMENTS": comments_unsubscribe(user, slug) except Exception as e: - return {"error" : e} + return {"error" : str(e)} return {} @@ -374,4 +377,4 @@ async def rate_shout(_, info, slug, value): await ShoutRatingStorage.update_rating(rating) - return {"error" : ""} \ No newline at end of file + return {"error" : ""} diff --git a/schema.graphql b/schema.graphql index 4c386da7..875b2e54 100644 --- a/schema.graphql +++ b/schema.graphql @@ -7,10 +7,11 @@ type Result { } type CurrentUserInfo { - totalUnreadMessages: Int - userSubscribedTopics: [String]! - userSubscribedAuthors: [String]! - userSubscribedCommunities: [String]! + totalUnreadMessages: Int + userSubscribedTopics: [String]! + userSubscribedAuthors: [String]! + userSubscribedCommunities: [String]! + userSubscribedShoutComments: [String]! } type AuthResult { @@ -98,6 +99,7 @@ enum SubscriptionType { TOPIC AUTHOR COMMUNITY + COMMENTS } ################################### Mutation @@ -205,7 +207,6 @@ type Query { getCommunity(slug: String): Community! getCommunities: [Community]! - shoutCommentsSubscribed(slug: String!, page: Int!, size: Int!): [Shout]! shoutsReviewed(page: Int!, size: Int!): [Shout]! recentCommented(page: Int!, size: Int!): [Shout]! }