diff --git a/migrate.py b/migrate.py index 66cd43e1..4710b1a6 100644 --- a/migrate.py +++ b/migrate.py @@ -83,6 +83,7 @@ def topics(export_topics, topics_by_slug, topics_by_oid, cats_data, tags_data): if len(sys.argv) > 2: limit = int(sys.argv[2]) print('migrating %d topics...' % limit) counter = 0 + topics_by_title = {} for tag in tags_data: old_id = tag["createdBy"] tag["createdBy"] = user_id_map.get(old_id, 0) diff --git a/migration/aaronsw-html2text.py b/migration/aaronsw-html2text.py index 6766cf89..12f994da 100644 --- a/migration/aaronsw-html2text.py +++ b/migration/aaronsw-html2text.py @@ -417,15 +417,17 @@ class HTML2Text(HTMLParser.HTMLParser): self.o('`') # NOTE: same as self.span_hightlight = True elif attrs['class'] == 'lead': - self.o('==') # NOTE: but CriticMarkup uses {== ==} - self.span_lead = True + if self.span_lead == False: + self.o('==\n') # NOTE: but CriticMarkup uses {== ==} + self.span_lead = True else: if self.span_hightlight: self.o('`') self.span_hightlight = False elif self.span_lead: - self.o('==') - self.span_lead = False + if self.span_lead == True: + self.o('\n==') + self.span_lead = False if tag in ['p', 'div']: if self.google_doc: diff --git a/migration/content/.gitkeep b/migration/content/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/migration/content/article/.gitkeep b/migration/content/article/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/migration/content/image/.gitkeep b/migration/content/image/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/migration/content/music/.gitkeep b/migration/content/music/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/migration/content/prose/.gitkeep b/migration/content/prose/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/migration/content/video/.gitkeep b/migration/content/video/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/orm/__init__.py b/orm/__init__.py index 958a9310..0f37ca12 100644 --- a/orm/__init__.py +++ b/orm/__init__.py @@ -4,7 +4,7 @@ from orm.user import User, UserRating, UserRole, UserStorage from orm.topic import Topic, TopicSubscription, TopicStorage from orm.notification import Notification from orm.shout import Shout, ShoutAuthor, ShoutTopic, ShoutRating, ShoutViewByDay,\ - ShoutRatingStorage, ShoutViewStorage + ShoutRatingStorage, ShoutViewStorage, ShoutCommentsSubscription from orm.base import Base, engine, local_session from orm.comment import Comment, CommentRating #, CommentRatingStorage from orm.proposal import Proposal, ProposalRating #, ProposalRatingStorage diff --git a/orm/shout.py b/orm/shout.py index 0631c7bc..de6f1d6b 100644 --- a/orm/shout.py +++ b/orm/shout.py @@ -11,6 +11,14 @@ from functools import reduce import asyncio +class ShoutCommentsSubscription(Base): + __tablename__ = "shout_comments_subscription" + + id = None + 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") + class ShoutAuthor(Base): __tablename__ = "shout_author" diff --git a/resolvers/comments.py b/resolvers/comments.py index f6e4dd19..29a4163c 100644 --- a/resolvers/comments.py +++ b/resolvers/comments.py @@ -1,10 +1,61 @@ from orm import Comment, CommentRating from orm.base import local_session +from orm.shout import ShoutCommentsSubscription from resolvers.base import mutation, query, subscription 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 + +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) + +def comments_unsubscribe(user, slug): + with local_session() as session: + sub = session.query(ShoutCommentsSubscription).\ + filter(and_(ShoutCommentsSubscription.subscriber == user.slug, ShoutCommentsSubscription.shout == slug)).\ + first() + if not sub: + raise Exception("subscription not exist") + session.delete(sub) + session.commit() + @mutation.field("createComment") @login_required async def create_comment(_, info, body, shout, replyTo = None): @@ -18,6 +69,9 @@ async def create_comment(_, info, body, shout, replyTo = None): replyTo = replyTo ) + result = CommentResult("NEW", comment) + await ShoutCommentsStorage.put(result) + return {"comment": comment} @mutation.field("updateComment") @@ -38,6 +92,9 @@ async def update_comment(_, info, id, body): session.commit() + result = CommentResult("UPDATED", comment) + await ShoutCommentsStorage.put(result) + return {"comment": comment} @mutation.field("deleteComment") @@ -56,6 +113,9 @@ async def delete_comment(_, info, id): comment.deletedAt = datetime.now() session.commit() + result = CommentResult("DELETED", comment) + await ShoutCommentsStorage.put(result) + return {} @mutation.field("rateComment") @@ -81,4 +141,7 @@ async def rate_comment(_, info, id, value): createdBy = user_id, value = value) + result = CommentResult("UPDATED_RATING", comment) + await ShoutCommentsStorage.put(result) + return {} diff --git a/resolvers/editor.py b/resolvers/editor.py index 670cd4e1..86e7654c 100644 --- a/resolvers/editor.py +++ b/resolvers/editor.py @@ -35,6 +35,8 @@ async def create_shout(_, info, input): user.email, "new shout %s" % (new_shout.slug) ) + + await ShoutCommentsStorage.send_shout(new_shout) return { "shout" : new_shout @@ -104,4 +106,4 @@ async def delete_shout(_, info, slug): shout.deletedAt = datetime.now() session.commit() - return {} + return {} \ No newline at end of file diff --git a/resolvers/zine.py b/resolvers/zine.py index 27916de5..9a94872c 100644 --- a/resolvers/zine.py +++ b/resolvers/zine.py @@ -1,12 +1,13 @@ from orm import Shout, ShoutAuthor, ShoutTopic, ShoutRating, ShoutViewByDay, \ User, Community, Resource, ShoutRatingStorage, ShoutViewStorage, \ - Comment, CommentRating, Topic + Comment, CommentRating, Topic, ShoutCommentsSubscription from orm.community import CommunitySubscription from orm.base import local_session from orm.user import UserStorage, AuthorSubscription from orm.topic import TopicSubscription from resolvers.base import mutation, query +from resolvers.comments import comments_subscribe, comments_unsubscribe from auth.authenticate import login_required from settings import SHOUTS_REPO @@ -314,16 +315,18 @@ async def shouts_by_communities(_, info, slugs, page, size): @mutation.field("subscribe") @login_required -async def subscribe(_, info, what, slug): +async def subscribe(_, info, subscription, slug): user = info.context["request"].user try: - if what == "AUTHOR": + if subscription == "AUTHOR": author_subscribe(user, slug) - elif what == "TOPIC": + elif subscription == "TOPIC": topic_subscribe(user, slug) - elif what == "COMMUNITY": + elif subscription == "COMMUNITY": community_subscribe(user, slug) + elif comments_subscription == "COMMENTS": + comments_subscribe(user, slug) except Exception as e: return {"error" : e} @@ -331,16 +334,18 @@ async def subscribe(_, info, what, slug): @mutation.field("unsubscribe") @login_required -async def unsubscribe(_, info, what, slug): +async def unsubscribe(_, info, subscription, slug): user = info.context["request"].user try: - if what == "AUTHOR": + if subscription == "AUTHOR": author_unsubscribe(user, slug) - elif what == "TOPIC": + elif subscription == "TOPIC": topic_unsubscribe(user, slug) - elif what == "COMMUNITY": + elif subscription == "COMMUNITY": community_unsubscribe(user, slug) + elif subscription == "COMMENTS": + comments_unsubscribe(user, slug) except Exception as e: return {"error" : e} @@ -369,4 +374,4 @@ async def rate_shout(_, info, slug, value): await ShoutRatingStorage.update_rating(rating) - return {"error" : ""} + return {"error" : ""} \ No newline at end of file