def _process_legacy(cls, account, op_json, block_date): """Handle legacy 'follow' plugin ops (follow/mute/clear, reblog) follow {follower: {type: 'account'}, following: {type: 'account'}, what: {type: 'list'}} reblog {account: {type: 'account'}, author: {type: 'account'}, permlink: {type: 'permlink'}, delete: {type: 'str', optional: True}} """ if not isinstance(op_json, list): return if len(op_json) != 2: return if first(op_json) not in ['follow', 'reblog']: return if not isinstance(second(op_json), dict): return cmd, op_json = op_json # ['follow', {data...}] if cmd == 'follow': Follow.follow_op(account, op_json, block_date) elif cmd == 'reblog': cls.reblog(account, op_json, block_date)
def _process_legacy(cls, account, op_json, block_date): """Handle legacy 'follow' plugin ops (follow/mute/clear, reblog)""" if not isinstance(op_json, list): return if len(op_json) != 2: return if first(op_json) not in ['follow', 'reblog']: return if not isinstance(second(op_json), dict): return cmd, op_json = op_json # ['follow', {data...}] if cmd == 'follow': Follow.follow_op(account, op_json, block_date) elif cmd == 'reblog': cls.reblog(account, op_json, block_date)
def process_json_follow_op(account, op_json, block_date): """ Process legacy 'follow' plugin ops (follow/mute/clear, reblog) """ if type(op_json) != list: return if len(op_json) != 2: return if first(op_json) not in ['follow', 'reblog']: return if not isinstance(second(op_json), dict): return cmd, op_json = op_json # ['follow', {data...}] if cmd == 'follow': if type(op_json['what']) != list: return what = first(op_json['what']) or 'clear' if what not in ['blog', 'clear', 'ignore']: return if not all([key in op_json for key in ['follower', 'following']]): print("bad follow op: {} {}".format(block_date, op_json)) return follower = op_json['follower'] following = op_json['following'] if follower != account: return # impersonation if not all(filter(is_valid_account_name, [follower, following])): return # invalid input sql = """ INSERT IGNORE INTO hive_follows (follower, following, created_at, state) VALUES (:fr, :fg, :at, :state) ON DUPLICATE KEY UPDATE state = :state """ state = {'clear': 0, 'blog': 1, 'ignore': 2}[what] query(sql, fr=follower, fg=following, at=block_date, state=state) elif cmd == 'reblog': blogger = op_json['account'] author = op_json['author'] permlink = op_json['permlink'] if blogger != account: return # impersonation if not all(filter(is_valid_account_name, [author, blogger])): return post_id, depth = get_post_id_and_depth(author, permlink) if depth > 0: return # prevent comment reblogs if not post_id: print("reblog: post not found: {}/{}".format(author, permlink)) return if 'delete' in op_json and op_json['delete'] == 'delete': query( "DELETE FROM hive_reblogs WHERE account = :a AND post_id = :pid LIMIT 1", a=blogger, pid=post_id) sql = "DELETE FROM hive_feed_cache WHERE account = :account AND post_id = :id" query(sql, account=blogger, id=post_id) else: query( "INSERT IGNORE INTO hive_reblogs (account, post_id, created_at) " "VALUES (:a, :pid, :date)", a=blogger, pid=post_id, date=block_date) sql = "INSERT IGNORE INTO hive_feed_cache (account, post_id, created_at) VALUES (:account, :id, :created_at)" query(sql, account=blogger, id=post_id, created_at=block_date)
def parse_operation(op): """ Update all relevant collections that this op impacts. """ op_type = op['type'] update_accounts_light = set() update_accounts_full = set() update_comments = set() def construct_identifier(): return '@%s/%s' % ( op.get('author', op.get('comment_author')), op.get('permlink', op.get('comment_permlink')), ) def account_from_auths(): return first(op.get('required_auths', op.get('required_posting_auths'))) if op_type in ['account_create', 'account_create_with_delegation']: update_accounts_light.add(op['creator']) update_accounts_full.add(op['new_account_name']) elif op_type in [ 'account_update', 'withdraw_vesting', 'claim_reward_balance', 'return_vesting_delegation', 'account_witness_vote' ]: update_accounts_light.add(op['account']) elif op_type == 'account_witness_proxy': update_accounts_light.add(op['account']) update_accounts_light.add(op['proxy']) elif op_type in ['author_reward', 'comment']: update_accounts_light.add(op['author']) update_comments.add(construct_identifier()) elif op_type == 'cancel_transfer_from_savings': update_accounts_light.add(op['from']) elif op_type == 'change_recovery_account': update_accounts_light.add(op['account_to_recover']) elif op_type == 'comment_benefactor_reward': update_accounts_light.add(op['benefactor']) elif op_type == [ 'convert', 'fill_convert_request', 'interest', 'limit_order_cancel', 'limit_order_create', 'shutdown_witness', 'witness_update' ]: update_accounts_light.add(op['owner']) elif op_type == 'curation_reward': update_accounts_light.add(op['curator']) elif op_type in ['custom', 'custom_json']: update_accounts_light.add(account_from_auths()) elif op_type == 'delegate_vesting_shares': update_accounts_light.add(op['delegator']) update_accounts_light.add(op['delegatee']) elif op_type == 'delete_comment': update_accounts_light.add(op['author']) elif op_type in [ 'escrow_approve', 'escrow_dispute', 'escrow_release', 'escrow_transfer' ]: accs = keep_in_dict( op, ['agent', 'from', 'to', 'who', 'receiver']).values() update_accounts_light.update(accs) elif op_type == 'feed_publish': update_accounts_light.add(op['publisher']) elif op_type in ['fill_order']: update_accounts_light.add(op['open_owner']) update_accounts_light.add(op['current_owner']) elif op_type in ['fill_vesting_withdraw']: update_accounts_light.add(op['to_account']) update_accounts_light.add(op['from_account']) elif op_type == 'pow2': acc = op['work'][1]['input']['worker_account'] update_accounts_light.add(acc) elif op_type in ['recover_account', 'request_account_recovery']: update_accounts_light.add(op['account_to_recover']) elif op_type == 'set_withdraw_vesting_route': update_accounts_light.add(op['from_account']) # update_accounts_light.add(op['to_account']) elif op_type in [ 'transfer', 'transfer_from_savings', 'transfer_to_savings', 'transfer_to_vesting' ]: accs = keep_in_dict( op, ['agent', 'from', 'to', 'who', 'receiver']).values() update_accounts_light.update(accs) elif op_type == 'vote': update_accounts_light.add(op['voter']) update_comments.add(construct_identifier()) # handle followers if op_type == 'custom_json': with suppress(ValueError): cmd, op_json = json.loads(op['json']) # ['follow', {data...}] if cmd == 'follow': accs = keep_in_dict(op_json, ['follower', 'following']).values() update_accounts_light.discard(first(accs)) update_accounts_light.discard(second(accs)) update_accounts_full.update(accs) return { 'accounts': list(update_accounts_full), 'accounts_light': list(update_accounts_light), 'comments': list(update_comments), }
def process_json_follow_op(account, op_json, block_date): """ This method processes any legacy 'follow' plugin ops (follow/mute/clear, reblog) """ if type(op_json) != list: return if first(op_json) not in ['follow', 'reblog']: return if not isinstance(second(op_json), dict): return cmd, op_json = op_json # ['follow', {data...}] if cmd == 'follow': if type(op_json['what']) != list: return what = first(op_json['what']) or 'clear' if what not in ['blog', 'clear', 'ignore']: return follower = op_json['follower'] following = op_json['following'] if follower != account: return # impersonation attempt if not all(filter(is_valid_account_name, [follower, following])): return if what == 'clear': query("DELETE FROM hive_follows WHERE follower = '%s' " "AND following = '%s' LIMIT 1" % (follower, following)) else: fields = { 'follower': follower, 'following': following, 'created_at': block_date, 'is_muted': int(what == 'ignore') } query( "INSERT IGNORE INTO hive_follows (follower, following, created_at, is_muted) " "VALUES (:follower, :following, :created_at, :is_muted) " "ON DUPLICATE KEY UPDATE is_muted = :is_muted", **fields) elif cmd == 'reblog': blogger = op_json['account'] author = op_json['author'] permlink = op_json['permlink'] if blogger != account: return # impersonation if not all(filter(is_valid_account_name, [author, blogger])): return post_id, depth = get_post_id_and_depth(author, permlink) if depth > 0: return # prevent comment reblogs if 'delete' in op_json and op_json['delete'] == 'delete': query( "DELETE FROM hive_reblogs WHERE account = '%s' AND post_id = %d LIMIT 1" % (blogger, post_id)) else: query( "INSERT IGNORE INTO hive_reblogs (account, post_id, created_at) " "VALUES ('%s', %d, '%s')" % (blogger, post_id, block_date))