예제 #1
0
 def from_ids(cls, comment_ids):
     """ Returns a list of CommentDetails instances. Does not include user pins. """
     from canvas.models import Comment
     details = [
         Comment.details_by_id(comment_id) for comment_id in comment_ids
     ]
     return CachedCall.many_multicall(details)[0]
예제 #2
0
def api_monster_details(request, short_id, payload={}):
    view_data = CommentViewData(request, short_id)
    main_comment = view_data.op_comment
    replies = [Comment.details_by_id(cid) for cid in view_data.reply_ids]
    has_replies = len(replies) > 0

    (
        (main_comment,),
        replies
    ) = CachedCall.many_multicall(
        [main_comment],
        replies,
    )

    treplies = []
    made_bottom = False
    for reply in replies:
        cur = reply.to_client()
        if reply.real_author == request.user.username:
            cur['current_user_authored'] = made_bottom = True
        treplies.append(cur)

    ctx = {
        'top': main_comment,
        'bottoms': treplies,
        'current_user_made_bottom': made_bottom,
        'current_user_made_top': main_comment.real_author == request.user.username,
        'start_content': Content.all_objects.get(id=Content.SMALL_DRAW_FROM_SCRATCH_PK).details(),
    }

    return ctx
예제 #3
0
 def from_queryset(cls, comments):
     bottoms, tops = CachedCall.many_multicall([cmt.details           for cmt in comments],
                                               [cmt.thread.op.details for cmt in comments])
     tiles = []
     for bottom, top in zip(bottoms, tops):
         tile = cls(bottom, top)
         tiles.append(tile)
     return tiles
예제 #4
0
 def from_queryset_with_viewer_stickers(cls, viewer, comments):
     bottoms, tops = CachedCall.many_multicall([cmt.details           for cmt in comments],
                                               [cmt.thread.op.details for cmt in comments])
     tiles = []
     for bottom, top in zip(bottoms, tops):
         tile = cls(bottom, top)
         tile.viewer_sticker = Comment.get_sticker_from_user_for_comment_id(bottom.id, viewer)
         tiles.append(tile)
     return tiles
예제 #5
0
    def test_many_multicall(self):
        f1, f2, f3, f4, f5, f6 = [
            CachedCall('key_%s' % n, CB(retvalue=n))
            for n in [1, 2, 3, 4, 5, 6]
        ]

        self.assertEquals([[1], [2, 3], [4, 5, 6]],
                          CachedCall.many_multicall([f1], [f2, f3],
                                                    [f4, f5, f6]))
예제 #6
0
    def get_from_comment(cls, comment):
        candidates = Comment.public.in_bulk_list([comment.id] + comment.top_replies[:10])
        candidates = [post for post in candidates if post.reply_content]
        candidates = sorted(candidates, key=lambda comment: -comment.get_score()[0])
        thread = [comment] + candidates[:5]

        (posts,) = CachedCall.many_multicall([post.details for post in thread])

        return cls(*posts)
예제 #7
0
파일: models.py 프로젝트: eiritana/canvas
 def from_queryset(cls, comments):
     bottoms, tops = CachedCall.many_multicall(
         [cmt.details for cmt in comments],
         [cmt.thread.op.details for cmt in comments])
     tiles = []
     for bottom, top in zip(bottoms, tops):
         tile = cls(bottom, top)
         tiles.append(tile)
     return tiles
예제 #8
0
def mobile_details_from_queryset(comments):
    bottoms, tops = CachedCall.many_multicall([cmt.details           for cmt in comments],
                                              [cmt.thread.op.details for cmt in comments])
    tiles = []
    for bottom, top in zip(bottoms, tops):
        tile = {
            'top': top,
            'bottom': bottom,
        }
        tiles.append(tile)
    return tiles
예제 #9
0
파일: models.py 프로젝트: eiritana/canvas
 def from_queryset_with_viewer_stickers(cls, viewer, comments):
     bottoms, tops = CachedCall.many_multicall(
         [cmt.details for cmt in comments],
         [cmt.thread.op.details for cmt in comments])
     tiles = []
     for bottom, top in zip(bottoms, tops):
         tile = cls(bottom, top)
         tile.viewer_sticker = Comment.get_sticker_from_user_for_comment_id(
             bottom.id, viewer)
         tiles.append(tile)
     return tiles
예제 #10
0
    def get_from_comment(cls, comment):
        candidates = Comment.public.in_bulk_list([comment.id] +
                                                 comment.top_replies[:10])
        candidates = [post for post in candidates if post.reply_content]
        candidates = sorted(candidates,
                            key=lambda comment: -comment.get_score()[0])
        thread = [comment] + candidates[:5]

        (posts, ) = CachedCall.many_multicall(
            [post.details for post in thread])

        return cls(*posts)
예제 #11
0
파일: models.py 프로젝트: eiritana/canvas
def mobile_details_from_queryset(comments):
    bottoms, tops = CachedCall.many_multicall(
        [cmt.details for cmt in comments],
        [cmt.thread.op.details for cmt in comments])
    tiles = []
    for bottom, top in zip(bottoms, tops):
        tile = {
            'top': top,
            'bottom': bottom,
        }
        tiles.append(tile)
    return tiles
예제 #12
0
    def from_queryset_with_pins(cls, comments):
        """
        Returns a list of tile details.

        This will preload this details object with pins, which is more efficient than loading them on demand.
        """
        # Grab the pin data for this user and these comments.
        details, pins = CachedCall.many_multicall([cmt.details        for cmt in comments],
                                                  [cmt.thread.op.pins for cmt in comments])

        tiles = []
        for cmt, pins in zip(details, pins):
            tile = cls(cmt)
            tile.pins = pins
            tiles.append(tile)
        return tiles
    def thread_context(self):
        top_reply_ids = self.top_reply_ids(force_show=features.thread_new(self.request))

        ctx = {
            'short_id': self.short_id,
            'page': self.page,
            'gotoreply': self.gotoreply,

            'viewer_is_staff': self.request.user.is_authenticated() and self.request.user.is_staff,
            'viewer_is_thread_author': self.is_author,
            'root': '/p/',

            'op_content': self.op_content,
            'op_category': self.op_category,
            'page': self.page,
            'per_page': self.per_page,
            'num_replies': self.num_replies,
            'reply_ids': self.reply_ids,
            'pages': self.pages,
            'page_reply_ids': self.page_reply_ids,
            'page_current': self.page_current,
            'page_next': self.page_next,
            'page_last': self.page_last,
            'page_penultimate': self.page_penultimate,
            'explicit_page_view': self.explicit_page_view,

            # Recent replies.
            'recent_reply_ids': self.recent_reply_ids,

            'top_reply_ids': top_reply_ids,
        }

        # Get all the replies in one query, then create the appropriate lists.
        _all_replies = Comment.visible.in_bulk(self.page_reply_ids + self.recent_reply_ids + top_reply_ids)
        _recent_replies = [_all_replies[cid] for cid in self.recent_reply_ids]
        _top_replies = filter(bool, [_all_replies.get(cid) for cid in top_reply_ids])
        _replies = [_all_replies[cid] for cid in self.page_reply_ids]

        replyable = [self._op_comment] + _replies + _recent_replies + _top_replies

        # Get all comment ids (ids so 0 queries) that any of these comments are replies to, that aren't in this
        # page, so we can render them on hover.
        replied_ids = ([reply.replied_comment_id for reply in replyable
                        if (reply.replied_comment_id
                            and reply.replied_comment_id not in [r.id for r in replyable])])

        ctx.update({
            'replied_ids': replied_ids,
            'replyable': replyable,
        })

        recent_replies = [reply.details for reply in _recent_replies]
        replies = [Comment.details_by_id(reply.id) for reply in _replies]
        replied = [Comment.details_by_id(cid) for cid in replied_ids]
        top_replies = [reply.details for reply in _top_replies]

        if self.request.user.is_authenticated():
            ctx['user_infos'] = {'pinned': self.request.user.id in self._op_comment.pins()}
            if self.request.user.is_staff:
                ctx['admin_infos'] = {self._op_comment.id: self._op_comment.admin_info}
                # For replies we only use the username, so grab those all in one query and put them in admin_infos.
                ctx['usernames'] = Comment.visible.filter(id__in=_all_replies.keys()).values('id', 'author__username')
                for reply_dict in ctx['usernames']:
                    ctx['admin_infos'][reply_dict['id']] = {'username': reply_dict['author__username']}

        ctx['replies_channel'] = self._op_comment.replies_channel.sync()

        # Get relevant sidebar data
        remix_of, reply_to = [], []
        # Remix of
        if self._op_content and self._op_content.remix_of:
            op_remix_of_caption = self._op_content.remix_of.first_caption
            if op_remix_of_caption:
                remix_of = [op_remix_of_caption.details]
            ctx['op_remix_of_caption'] = op_remix_of_caption
        # Reply to
        if self._op_comment.parent_comment and self._op_comment.parent_comment.is_visible():
            reply_to = [self._op_comment.parent_comment.details]

        (
            (op_comment,),
            (linked_comment,),
            remix_of,
            reply_to,
            replies,
            recent_replies,
            top_replies,
            replied,
        ) = CachedCall.many_multicall(
            [self.op_comment],
            [self.linked_comment],
            remix_of,
            reply_to,
            replies,
            recent_replies,
            top_replies,
            replied,
        )

        op_comment.is_my_post = bool(self._op_comment.author == self.request.user)
        op_comment.moderated = op_comment.visibility not in Visibility.public_choices

        linked_comment = TemplateComment(linked_comment, is_op=(linked_comment.id == op_comment.id),
                                        request=self.request, title=op_comment.title)

        if self.page_current == 1 and op_comment.has_content():
            first_comment_with_content = op_comment
        else:
            first_comment_with_content = None
            for reply in replies:
                if reply.has_content():
                    first_comment_with_content = reply
                    break

        last_comment_with_content = None
        for reply in reversed(replies):
            if reply.has_content():
                last_comment_with_content = reply
                break

        comment_to_expand = first_comment_with_content
        if self.gotoreply:
            comment_to_expand = linked_comment

        ctx.update({
            'op_comment': op_comment,
            'linked_comment': linked_comment,
            'remix_of': remix_of,
            'reply_to': reply_to,
            'replies': replies,
            'recent_replies': recent_replies,
            'top_replies': top_replies,
            'top_remixes': [reply for reply in top_replies if reply.has_content()],
            'replied': replied,

            'linked_comment': linked_comment,
            'large_thread_view': len(replies) >= 50,
            'title': getattr(op_comment, 'title', None),

            'first_comment_with_content': first_comment_with_content,
            'last_comment_with_content': last_comment_with_content,
            'comment_to_expand': comment_to_expand,
        })

        return ctx
 def test_many_multicall(self):
     f1, f2, f3, f4, f5, f6 = [CachedCall('key_%s' % n, CB(retvalue=n)) for n in [1,2,3,4,5,6]]
     
     self.assertEquals([[1], [2,3], [4,5,6]], CachedCall.many_multicall([f1], [f2, f3], [f4, f5, f6]))
 def from_ids(cls, comment_ids):
     """ Returns a list of CommentDetails instances. Does not include user pins. """
     from canvas.models import Comment
     details = [Comment.details_by_id(comment_id) for comment_id in comment_ids]
     return CachedCall.many_multicall(details)[0]
예제 #16
0
def view(request, short_id, option=None):
    from apps.monster.jinja_tags import monster_image_tile

    view_data = CommentViewData(request, short_id)
    main_comment = view_data.op_comment
    replies = [Comment.details_by_id(cid) for cid in view_data.reply_ids]
    has_replies = len(replies) > 0
    complete_link = option and (option == 'complete')
    if complete_link and request.user.is_anonymous():
        fact.record('monster_start_flow', request, {'monster_id': short_id})
    reply_id = None

    if option:
        try:
            reply_id = int(option)
        except ValueError:
            pass

    (
        (main_comment,),
        replies
    ) = CachedCall.many_multicall(
        [main_comment],
        replies,
    )

    replies = [reply for reply in replies if not reply.is_collapsed]

    monster_part = MonsterPart.get_by_comment(main_comment)
    main_comment_details = main_comment
    main_comment = TileDetails(main_comment)

    made_bottom = False
    made_top = main_comment.comment.real_author == request.user.username

    linked_monster_footer_image = ""
    current_monster_index = 0

    for i in range(len(replies)):
        reply = replies[i]
        if reply_id is not None and reply.id == int(reply_id):
            current_monster_index = i
        elif reply.real_author == request.user.username and reply_id is None:
            current_monster_index = i
            made_bottom = True

    try:
        if (has_replies
                and replies[current_monster_index].reply_content
                and replies[current_monster_index].reply_content.footer):
            linked_monster_footer_image = replies[current_monster_index].reply_content.footer['name']
    except (AttributeError, IndexError):
        pass

    made_part = made_top or made_bottom

    if made_part:
        CompletedMonsterSet(request.user).sadd(main_comment.comment.id)

    can_make_bottom = (not made_part) and complete_link
    can_invite = made_top

    # incomplete monster without an invite link, send to monster index
    if not has_replies and not complete_link and not can_invite:
        return HttpResponseRedirect('/monster')

    ctx = {
        'can_invite': can_invite,
        'can_make_bottom': can_make_bottom,
        'current_monster_index': current_monster_index,
        'domain': settings.DOMAIN,
        'made_bottom': made_bottom,
        'made_part': made_part,
        'made_top': made_top,
        'main_comment': main_comment,
        'monster_content': main_comment.comment.reply_content,
        'og_image_url': linked_monster_footer_image.replace("https", "http", 1),
        'monster_group': MONSTER_GROUP,
        'monster_name': main_comment.comment.title,
        'replies': MonsterTileDetails.from_shared_op_details_with_viewer_stickers(request.user, main_comment_details, replies),
        'request': request,
        'short_id': main_comment.comment.short_id(),
        'start_content': Content.all_objects.get(id=Content.SMALL_DRAW_FROM_SCRATCH_PK).details(),
    }

    return r2r_jinja('monster/view.html', ctx)