예제 #1
0
    def _notifs(cls, post, pid, level, payout):
        # pylint: disable=too-many-locals,too-many-branches
        author = post['author']
        author_id = Accounts.get_id(author)
        parent_author = post['parent_author']
        date = post['last_update']

        # reply notif
        if level == 'insert' and parent_author and parent_author != author:
            irredeemable = parent_author in Mutes.all()
            parent_author_id = Accounts.get_id(parent_author)
            if not irredeemable and not cls._muted(parent_author_id, author_id):
                ntype = 'reply' if post['depth'] == 1 else 'reply_comment'
                Notify(ntype, src_id=author_id, dst_id=parent_author_id,
                       score=Accounts.default_score(author), post_id=pid,
                       when=date).write()

        # mentions notif
        if level in ('insert', 'update'):
            accounts = set(filter(Accounts.exists, mentions(post['body'])))
            accounts -= {author, parent_author}
            score = Accounts.default_score(author)
            if score < 30: max_mentions = 5
            elif score < 60: max_mentions = 10
            else: max_mentions = 25
            if len(accounts) <= max_mentions:
                penalty = min([score, 2 * (len(accounts) - 1)])
                for mention in accounts:
                    mention_id = Accounts.get_id(mention)
                    if (not cls._mentioned(pid, mention_id)
                            and not cls._muted(mention_id, author_id)):
                        Notify('mention', src_id=author_id,
                               dst_id=mention_id, post_id=pid, when=date,
                               score=(score - penalty)).write()
            else:
                url = '@%s/%s' % (author, post['permlink'])
                log.info("skip %d mentions in %s", len(accounts), url)

        # votes notif
        url = post['author'] + '/' + post['permlink']
        if url in cls._votes:
            voters = cls._votes[url]
            del cls._votes[url]
            net = float(post['net_rshares'])
            ratio = float(payout) / net if net else 0
            for vote in post['active_votes']:
                rshares = int(vote['rshares'])
                if vote['voter'] not in voters or rshares < 10e9: continue
                contrib = int(1000 * ratio * rshares)
                if contrib < 20: continue # < $0.020

                voter_id = Accounts.get_id(vote['voter'])
                if not cls._voted(pid, author_id, voter_id):
                    score = min(100, (len(str(contrib)) - 1) * 25) # $1 = 75
                    payload = "$%.3f" % (contrib / 1000)
                    Notify('vote', src_id=voter_id, dst_id=author_id,
                           when=vote['time'], post_id=pid, score=score,
                           payload=payload).write()
예제 #2
0
    def follow_op(cls, account, op_json, date):
        """Process an incoming follow op."""
        op = cls._validated_op(account, op_json, date)
        if not op:
            return

        # perform delta check
        new_state = op['state']
        old_state = cls._get_follow_db_state(op['flr'], op['flg'])
        if new_state == (old_state or 0):
            return

        # insert or update state
        if old_state is None:
            sql = """INSERT INTO hive_follows (follower, following,
                     created_at, state) VALUES (:flr, :flg, :at, :state)"""
        else:
            sql = """UPDATE hive_follows SET state = :state
                      WHERE follower = :flr AND following = :flg"""
        DB.query(sql, **op)

        # track count deltas
        if not DbState.is_initial_sync():
            if new_state == 1:
                Follow.follow(op['flr'], op['flg'])
                if old_state is None:
                    score = Accounts.default_score(op_json['follower'])
                    Notify('follow', src_id=op['flr'], dst_id=op['flg'],
                           when=op['at'], score=score).write()
            if old_state == 1:
                Follow.unfollow(op['flr'], op['flg'])
예제 #3
0
    def reblog(cls, account, op_json, block_date):
        """Handle legacy 'reblog' op"""
        if ('account' not in op_json or 'author' not in op_json
                or 'permlink' not in op_json):
            return
        blogger = op_json['account']
        author = op_json['author']
        permlink = op_json['permlink']

        if blogger != account:
            return  # impersonation
        if not all(map(Accounts.exists, [author, blogger])):
            return

        post_id, depth = Posts.get_id_and_depth(author, permlink)

        if depth > 0:
            return  # prevent comment reblogs

        if not post_id:
            log.debug("reblog: post not found: %s/%s", author, permlink)
            return

        author_id = Accounts.get_id(author)
        blogger_id = Accounts.get_id(blogger)

        if 'delete' in op_json and op_json['delete'] == 'delete':
            DB.query(
                "DELETE FROM hive_reblogs WHERE account = :a AND "
                "post_id = :pid LIMIT 1",
                a=blogger,
                pid=post_id)
            if not DbState.is_initial_sync():
                FeedCache.delete(post_id, blogger_id)

        else:
            sql = (
                "INSERT INTO hive_reblogs (account, post_id, created_at) "
                "VALUES (:a, :pid, :date) ON CONFLICT (account, post_id) DO NOTHING"
            )
            DB.query(sql, a=blogger, pid=post_id, date=block_date)
            if not DbState.is_initial_sync():
                FeedCache.insert(post_id, blogger_id, block_date)
                Notify('reblog',
                       src_id=blogger_id,
                       dst_id=author_id,
                       post_id=post_id,
                       when=block_date,
                       score=Accounts.default_score(blogger)).write()