Exemple #1
0
class Reply(Document):
    """评论回复
    owner: 回复者
    reply: 被用户回复的评论回复
    comment: 所属评论ID
    content: 内容
    create_at: 创建时间
    """
    collection = DB.replies

    CACHED_OBJS = CacheDict(max_len=100, max_age_seconds=30)

    COMMENT_REPLY_IDS = 'reply:comment:%(cid)s'  # 评论的回复队列

    def format(self):
        _reply = Reply.get_one(str(self.reply), check_online=False)
        from_user = User.get_one(str(self.owner), check_online=False)
        to_user = User.get_one(str(_reply.owner),
                               check_online=False) if _reply else None
        data = {
            'reply_id':
            str(self._id),
            'reply_from':
            from_user and from_user.format(exclude_fields=['is_followed']),
            'reply_to':
            to_user and to_user.format(exclude_fields=['is_followed']),
            'content':
            self.content,
            'reply_count':
            self.reply_count or 0,
            'create_at':
            self.create_at
        }
        return data

    def create_model(self):
        _id = super(Reply, self).create_model()
        if _id:
            # 更新评论回复数
            comment = Comment.get_one(str(self.comment), check_online=False)
            comment.update_model({'$inc': {'reply': 1}})
            # 更新回复的回复数
            if self.reply:
                _reply = Reply.get_one(str(self.reply), check_online=False)
                _reply.update_model({'$inc': {'reply_count': 1}})

            key = self.COMMENT_REPLY_IDS % ({'cid': str(self.comment)})
            # 列表为空时key对应的value是一个string
            try:
                if Redis.exists(key):
                    Redis.zadd(key, self.create_at, str(_id))
            except exceptions.ResponseError:
                Redis.delete(key)
        return _id

    def delete_model(self):
        ret = super(Reply, self).delete_model()
        self.collection.update({"reply": self._id}, {"$set": {"reply": None}})
        if ret:
            # 更新评论回复数
            comment = Comment.get_one(str(self.comment), check_online=False)
            comment.update_model({'$inc': {'reply': -1}})
            # 更新回复的回复数
            if self.reply:
                _reply = Reply.get_one(str(self.reply), check_online=False)
                _reply.update_model({'$inc': {'reply_count': -1}})

            key = self.COMMENT_REPLY_IDS % ({'cid': str(self.comment)})
            try:
                Redis.zrem(key, str(self._id))
            except exceptions.ResponseError:
                Redis.delete(key)
        return ret

    @classmethod
    def init(cls):
        doc = super(Reply, cls).init()
        doc.reply_count = 0
        return cls(doc)

    @classmethod
    def delete_comment_replies(cls, cid):
        ret = cls.collection.delete_many({'comment': ObjectId(cid)})
        return ret.deleted_count

    @classmethod
    @util.cached_zset(lambda cls, cid: cls.COMMENT_REPLY_IDS % ({
        'cid': cid
    }),
                      snowslide=True)
    def _load_comment_reply_ids(cls, cid):
        replies = list(
            cls.collection.find({
                'comment': ObjectId(cid)
            }, {
                '_id': 1,
                'create_at': 1
            }).sort("create_at", pymongo.DESCENDING))
        ret = list()
        for c in replies:
            if 'create_at' in c:
                ret.extend([c['create_at'], str(c['_id'])])
        return tuple(ret)

    @classmethod
    def comment_reply_ids(cls, cid, page=None, pagesize=None, maxs=None):
        """获取评论的回复id
        """
        key = cls.COMMENT_REPLY_IDS % ({'cid': cid})
        if not Redis.exists(key):
            cls._load_comment_reply_ids(cid)
        try:
            if maxs:
                ids = Redis.zrangebyscore(key,
                                          '(%.6f' % (maxs),
                                          '+inf',
                                          start=0,
                                          num=pagesize)
            else:
                start = (page - 1) * pagesize
                stop = start + pagesize - 1
                ids = Redis.zrange(key, start, stop)
        except exceptions.ResponseError:
            # 列表为空时key对应的value是一个string
            ids = []
        return list(ids)
Exemple #2
0
class DaTangVideo(Document):
    """视频
    """
    collection = DB.datang_videos

    CACHED_OBJS = CacheDict(max_len=100, max_age_seconds=5)

    GAME_HOTVIDEO_IDS = "dtvideos:hotgame:%(date)s:%(gid)s"  # 游戏人气视频队列
    USER_GAME_VIDEO_IDS = "dtvideos:user:%(uid)s:game:%(gid)s"  # 用户为某个游戏创建的视频队列

    def format(self, exclude_fields=[]):
        author_ex_fields = []
        game_ex_fields = []
        for field in exclude_fields:
            if field.startswith('author__'):
                _, _field = field.split('__')
                author_ex_fields.append(_field)
            elif field.startswith('game__'):
                _, _field = field.split('__')
                game_ex_fields.append(_field)

        vid = str(self._id)
        data = {
            'video_id': vid,
            'ratio': self.ratio,
            'title': self.title,
            'url': '%s/datang/videos/%s/play' % (app.config.get('SERVER_URL'), vid),
            'is_liked': False,
            'author': self.author,
            'cover': "%s%s" % (app.config.get("MEDIA_URL"), self.cover),
            'like_count': self.like,
            'create_at': self.create_at,
            'is_favored': False,
            'game': self.game,
            'comment_count': self.comment_count,
            'vv': self.vv,
            'duration': self.duration and int(self.duration),
            'tags': self.tags,
            'share_url': None,
            'status': self.status if self.status else None,
            'is_online': self.online
        }
        return data

    @property
    def online(self):
        _is_online = super(DaTangVideo, self).online
        return _is_online or self.status in [const.ELITE]

    def create_model(self):
        _id = super(DaTangVideo, self).create_model()
        if _id:
            if self.online:
                key = self.USER_GAME_VIDEO_IDS % ({'uid': str(self.author), 'gid': str(self.game)})
                try:
                    if Redis.exists(key):
                        Redis.zadd(key, self.create_at, str(_id))
                except exceptions.ResponseError:
                    Redis.delete(key)

        return _id

    def update_model(self, data={}):
        obj = super(DaTangVideo, self).update_model(data)
        if obj:
            # 下线-->上线
            if self.offline and obj.online:
                key = self.USER_GAME_VIDEO_IDS % ({'uid': str(self.author), 'gid': str(self.game)})
                try:
                    if Redis.exists(key):
                        Redis.zadd(key, self.create_at, str(self._id))
                except exceptions.ResponseError:
                    Redis.delete(key)

        return obj

    def delete_model(self):
        ret = super(DaTangVideo, self).delete_model()
        if ret:
            key = self.USER_GAME_VIDEO_IDS % ({'uid': str(self.author), 'gid': str(self.game)})
            try:
                Redis.zrem(key, str(self._id))
            except exceptions.ResponseError:
                Redis.delete(key)

        return ret

    def real_url(self):
        if self.url.lower().startswith('http://'):
            return self.url
        return urljoin(app.config.get('VIDEO_URL'), self.url)

    @classmethod
    def init(cls):
        doc = super(DaTangVideo, cls).init()
        doc.cover = 0
        doc.url = ''
        doc.like = 0
        doc.vv = 0
        doc.comment_count = 0
        doc.status = const.ONLINE
        return cls(doc)

    @classmethod
    @util.cached_list(lambda cls, gid: cls.GAME_HOTVIDEO_IDS % ({'date': time.strftime("%Y%m%d"),
                                                                 'gid': gid}),
                      timeout=86400, snowslide=True)
    def _load_game_hotvideo_ids(cls, gid):
        videos = list(cls.collection.find(
            {
                'game': ObjectId(gid),
                'create_at': {'$gte': int(time.time()) - const.POPULAR_VIDEO.get("time_range")},
                '$or': [{'status': {'$exists': False}},
                        {'status': {'$in': [const.ONLINE, const.ELITE]}}]
            },
            {'_id': 1, 'vv': 1}
        ).sort("vv", pymongo.DESCENDING))

        if len(videos) < const.POPULAR_VIDEO.get("max_video_num", 30):
            videos = list(cls.collection.find(
                {
                    'game': gid,
                    'create_at': {'$gte': int(time.time()) - 30 * 24 * 60 * 60},
                    '$or': [{'status': {'$exists': False}},
                            {'status': {'$in': [const.ONLINE, const.ELITE]}}]
                },
                {'_id': 1, 'vv': 1}
            ).sort("vv", pymongo.DESCENDING))

        vids = [v['_id'] for v in videos]
        return vids

    @classmethod
    def game_hotvideo_ids(cls, gid, page, pagesize, maxs=None):
        key = cls.GAME_HOTVIDEO_IDS % ({'date': time.strftime("%Y%m%d"), 'gid': gid})
        if not Redis.exists(key):
            cls._load_game_hotvideo_ids(gid)
        try:
            start = (page - 1) * pagesize if page else 0
            stop = (start + pagesize - 1) if pagesize else -1
            ids = Redis.lrange(key, start, stop)
        except exceptions.ResponseError:
            ids = []
        return list(ids)

    @classmethod
    @util.cached_zset(lambda cls, uid, gid: cls.USER_GAME_VIDEO_IDS % ({'uid': uid, 'gid': gid}))
    def _load_user_game_video_ids(cls, uid, gid):
        videos = list(cls.collection.find(
            {
                'author': uid,
                'game': gid,
                '$or': [{'status': {'$exists': False}},
                        {'status': {'$in': [const.ONLINE, const.ELITE]}}]
            },
            {'_id': 1, 'create_at': 1}
        ).sort("create_at", pymongo.DESCENDING))
        ret = list()
        for i in videos:
            ret.extend([i['create_at'], str(i['_id'])])
        return tuple(ret)

    @classmethod
    def user_game_video_ids(cls, uid, gid, page=None, pagesize=None, maxs=None):
        key = cls.USER_GAME_VIDEO_IDS % ({'uid': uid, 'gid': gid})
        if not Redis.exists(key):
            cls._load_user_game_video_ids(uid, gid)
        try:
            if maxs:
                ids = Redis.zrevrangebyscore(key, '(%.6f' % (maxs), '-inf', start=0, num=pagesize)
            else:
                start = (page - 1) * pagesize
                stop = start + pagesize - 1
                ids = Redis.zrevrange(key, start, stop)
        except exceptions.ResponseError:
            ids = []
        return list(ids)
Exemple #3
0
class Comment(Document):
    """评论
    """
    collection = DB.comments

    CACHED_OBJS = CacheDict(max_len=100, max_age_seconds=5)

    VIDEO_COMMENT_IDS = 'comments:video:%(vid)s'  # 某个视频的评论队列

    def format(self):
        author = User.get_one(str(self.author), check_online=False)
        uid = request.authed_user and str(request.authed_user._id)
        data = {
            'author':
            author and author.format(exclude_fields=['is_followed']),
            'comment_id':
            str(self._id),
            'video_id':
            self.video and str(self.video),
            'content':
            self.content,
            'create_at':
            self.create_at,
            'reply':
            self.reply or 0,
            'like':
            self.like or 0,
            'liked':
            UserLikeComment.get_by_ship(uid, str(self._id)) is not None
            if uid else False,
        }
        return data

    def create_model(self):
        _id = super(Comment, self).create_model()
        if _id:
            # 更新视频评论数
            from wanx.models.video import Video
            video = Video.get_one(str(self.video), check_online=False)
            video.update_model({'$inc': {'comment_count': 1}})

            key = self.VIDEO_COMMENT_IDS % ({'vid': str(self.video)})
            # 列表为空时key对应的value是一个string
            try:
                if Redis.exists(key):
                    Redis.zadd(key, self.create_at, str(_id))
            except exceptions.ResponseError:
                Redis.delete(key)
        return _id

    def delete_model(self):
        ret = super(Comment, self).delete_model()
        if ret:
            # 更新视频评论数
            from wanx.models.video import Video
            video = Video.get_one(str(self.video), check_online=False)
            video.update_model({'$inc': {'comment_count': -1}})

            key = self.VIDEO_COMMENT_IDS % ({'vid': str(self.video)})
            try:
                Redis.zrem(key, str(self._id))
            except exceptions.ResponseError:
                Redis.delete(key)
            # 删除全部回复
            Reply.delete_comment_replies(str(self._id))
        return ret

    @classmethod
    def init(cls):
        doc = super(Comment, cls).init()
        doc.like = 0
        doc.reply = 0
        doc.status = const.ONLINE
        return cls(doc)

    @classmethod
    @util.cached_zset(lambda cls, video_id: cls.VIDEO_COMMENT_IDS %
                      ({
                          'vid': video_id
                      }),
                      snowslide=True)
    def _load_video_comment_ids(cls, video_id):
        comments = list(
            cls.collection.find(
                {
                    'video': ObjectId(video_id),
                    '$or': [{
                        'status': {
                            '$exists': False
                        }
                    }, {
                        'status': 0
                    }]
                }, {
                    '_id': 1,
                    'create_at': 1
                }).sort("create_at", pymongo.DESCENDING))
        ret = list()
        for c in comments:
            if 'create_at' in c:
                ret.extend([c['create_at'], str(c['_id'])])
        return tuple(ret)

    @classmethod
    def video_comment_ids(cls, video_id, page=None, pagesize=None, maxs=None):
        """获取视频相关评论的id
        """
        key = cls.VIDEO_COMMENT_IDS % ({'vid': video_id})
        if not Redis.exists(key):
            cls._load_video_comment_ids(video_id)
        try:
            if maxs:
                ids = Redis.zrevrangebyscore(key,
                                             '(%.6f' % (maxs),
                                             '-inf',
                                             start=0,
                                             num=pagesize)
            else:
                start = (page - 1) * pagesize
                stop = start + pagesize - 1
                ids = Redis.zrevrange(key, start, stop)
        except exceptions.ResponseError:
            # 列表为空时key对应的value是一个string
            ids = []
        return list(ids)

    @classmethod
    def video_comment_count(cls, video_id):
        key = cls.VIDEO_COMMENT_IDS % ({'vid': video_id})
        if not Redis.exists(key):
            cls._load_video_comment_ids(video_id)
        try:
            count = Redis.zcard(key)
        except exceptions.ResponseError:
            count = 0
        return count