Example #1
0
def run(filename):
    b = Blockchain()
    # automatically resume from where we left off
    # previous + last + 1
    start_block = get_previous_block_num(get_last_line(filename)) + 2
    upstream_blk = b.get_current_block()
    checkin_count = 0

    print("Our local block: {}".format(start_block))
    print("The Upstream block: {}".format(b.get_current_block_num()))
    print("Progress: {}%\n".format(
        progress(start_block, b.get_current_block_num())))

    with open(filename, 'a+') as file:
        checkin_ts = time.time()
        for block in b.stream_from(start_block=start_block, full_blocks=True):
            if checkin_ts + 10 < time.time():
                pdone = progress(int(block['block_id'][:8], base=16),
                                 b.get_current_block_num())
                dl_rate = checkin_count / 10

                print("Rate: {}blk/sec, Progress: {}%".format(dl_rate, pdone))
                checkin_ts = time.time()
                checkin_count = 0

            file.write(json.dumps(block, sort_keys=True) + '\n')
            checkin_count += 1
def run():
    blockchain = Blockchain()
    head_block = blockchain.get_current_block_num()
    start_block = head_block - (int(sys.argv[1]))
    stream = blockchain.stream_from(start_block=start_block)
    block_count = int(sys.argv[1])
    current_block = start_block
    stats = {}
    operations = 0
    counter = 0

    print("Starting from block {} for {} blocks\n".format(
        start_block, block_count))

    for post in stream:
        if post['block'] != current_block:
            counter += 1
            print("Block {}/{} {:.2f}%".format(counter, block_count,
                                               counter / block_count * 100))
            current_block = post['block']
        elif post['block'] == start_block + block_count:
            break

        operation = post['op'][0]

        if operation not in stats:
            stats[operation] = 1
        else:
            stats[operation] += 1
        operations += 1

    print("operations {}\n".format(operations))
    for operation in stats:
        print(operation, stats[operation])
Example #3
0
def get_start_block(start_block:int = None, blockchain: Blockchain=None):
    start_block = None
    try:
        if isinstance(start_block, int) and start_block < 0:
            start_block = blockchain.get_current_block_num() - start_block
    except Exception:
        logger.exception('service error')
        start_block = None
    logger.debug('get_start_block', start_block=start_block)
    return start_block
Example #4
0
def run():
    blockchain = Blockchain()
    id = blockchain.get_current_block_num()
    global current_id
    if id != current_id:
        block = blockchain.get_current_block()
        thread = threading.Thread(target=parse_next_block, args=(block, ))
        print("Start new thread", thread.name)
        thread.start()
        current_id = id
    threading.Timer(1, run).start()
def run():
    # Global variables for creating threads
    steem = Steem(['https://api.steemit.com'])
    blockchain = Blockchain(steem)
    head_block = blockchain.get_current_block_num()
    block_count = int(sys.argv[1])
    amount_of_threads = int(sys.argv[2])
    blocks_per_thread = int(block_count / amount_of_threads)
    start_block = head_block - block_count
    threads = []

    # Calculate start_block and end_block for each thread
    for thread_id in range(0, amount_of_threads):
        thread = myThread(thread_id, start_block,
                          start_block + blocks_per_thread - 1,
                          blocks_per_thread, blockchain)
        thread.start()
        threads.append(thread)
        start_block = start_block + blocks_per_thread

    # Wait for all the threads to finish
    for t in threads:
        t.join()
Example #6
0
def run():
    start = time.clock()
    blockchain = Blockchain()
    head_block = blockchain.get_current_block_num() - int(sys.argv[1])
    block_count = int(sys.argv[1])
    amount_of_threads = int(sys.argv[2])
    n = int(block_count / amount_of_threads)
    start = head_block - block_count
    threads = []

    queueLock = threading.Lock()
    workQueue = queue.Queue(amount_of_threads)

    for x in range(0, amount_of_threads):
        thread = myThread(x, start, start + n - 1, n, blockchain, workQueue,
                          queueLock)
        thread.start()
        threads.append(thread)
        start = start + n

    print()

    for t in threads:
        t.join()

    merged_data = {}

    while not workQueue.empty():
        data = workQueue.get()
        for key in data:
            if key not in merged_data:
                merged_data[key] = data[key]
            else:
                merged_data[key] += data[key]

    print(merged_data)
class Steem_node():
    def __init__(self, acount, number):
        self.tag = 'vote'
        self.account = account
        self.number = number
        self.nodes = [
            'https://api.steemit.com', 'https://rpc.buildteam.io',
            'https://rpc.steemviz.com'
        ]
        self.steem = Steem(nodes=self.nodes)
        self.b = Blockchain(self.steem)
        self.timestamp = None
        self.block = self.b.get_current_block_num()
        print('Booted\nConnected to: {}'.format(self.nodes[0]))

    def send_sms(self, memo):
        print(twilio_api.send_sms(self.number, memo))

    # Convert rshares to dollar value
    # Author: emrebeyler
    # Source: https://goo.gl/dV7yVa
    def convert_rshares(self, rshares):
        reward_fund = self.steem.get_reward_fund()
        reward_balance, recent_claims = (reward_fund["reward_balance"],
                                         reward_fund["recent_claims"])
        base_price = self.steem.get_current_median_history_price()["base"]

        fund_per_share = Amount(reward_balance).amount / float(recent_claims)
        payout = float(rshares) * fund_per_share * Amount(base_price).amount
        return payout

    def process_vote(self, vote):
        print(vote)
        voter = vote['voter']
        author = vote['author']
        permlink = vote['permlink']
        weight = vote['weight']

        # Verify that utopian-io is the voter and that is votes on account
        if voter == 'utopian-io' and author == account:
            print(f"\nVoter: {voter}\nAuthor: {author}\nPermlink: {permlink}" +
                  f"\nWeight: {weight}\n{self.timestamp}\n")

            # Construct post from the permlink to retrieve vote rshares
            post = Post(f'@{self.account}/{permlink}', self.steem)

            # Look for utopian in active_votes
            active_votes = post['active_votes']
            for vote in active_votes:
                if vote['voter'] == 'utopian-io':
                    payout = self.convert_rshares(vote['rshares'])

            # Construct sms
            url = f"http://steemit.com/@{self.account}/{permlink}"
            body = (f"Upvote from Utopian-io for ${payout:.2f}\n" +
                    f"\n{url}\n\nBlock: {self.block}" + f"\n{self.timestamp}")
            self.send_sms(body)

    def run(self):
        print(self.block)

        while True:
            try:
                # stream full blocks
                stream = self.b.stream_from(start_block=self.block,
                                            full_blocks=True)

                # process each block indiviudally
                for block in stream:
                    self.timestamp = block['timestamp']
                    print(f'{self.timestamp} Block: {self.block}', end='\r')

                    # go over each transaction indivually, process if tag is
                    # met and update index
                    for transaction in block['transactions']:
                        if transaction['operations'][0][0] == self.tag:
                            transfer = transaction['operations'][0][1]
                            self.process_vote(transfer)

                    self.block += 1

            except Exception as e:
                # common exception for api.steemit.com
                # when the head block is reached
                s = ("TypeError('an integer is"
                     " required (got type NoneType)',)")
                if repr(e) == s:
                    time.sleep(3)
Example #8
0
def scrape_operations(mongo):
    """Fetch all operations from last known block forward."""
    settings = Settings(mongo)
    blockchain = Blockchain(mode="irreversible")
    last_block = settings.last_block()

    # handle batching
    _batch_size = 100
    _head_block_num = blockchain.get_current_block_num()
    batch_dicts = []

    history = blockchain.history(start_block=last_block, )

    def custom_merge(*args):
        return list(set(filter(bool, flatten(args))))

    def schedule_batch(_batch_dicts):
        """Send a batch to background worker, and reset _dicts container"""
        _batch = merge_with(custom_merge, *_batch_dicts)
        if _batch:
            batch_update_async.delay(_batch)

    log.info('\n> Fetching operations, starting with block %d...' % last_block)
    for operation in history:
        # handle comments
        if operation['type'] in ['comment', 'delete_comment']:
            post_identifier = "@%s/%s" % (operation['author'],
                                          operation['permlink'])
            if operation['type'] == 'delete_comment':
                delete_comment(mongo, post_identifier)
            else:
                with suppress(TypeError):
                    upsert_comment(
                        mongo,
                        '%s/%s' % (operation['author'], operation['permlink']))

        # if we're close to blockchain head, enable batching
        recent_blocks = 20 * 60 * 24 * 1  # 1 days worth of blocks
        if last_block > _head_block_num - recent_blocks:
            batch_dicts.append(parse_operation(operation))

        # insert operation
        with suppress(DuplicateKeyError):
            transform = compose(strip_dot_from_keys, json_expand, typify)
            mongo.Operations.insert_one(transform(operation))

        # if this is a new block, checkpoint it, and schedule batch processing
        if operation['block_num'] != last_block:
            print("last block:", last_block)
            last_block = operation['block_num']
            settings.update_last_block(last_block - 1)

            if last_block % 10 == 0:
                _head_block_num = blockchain.get_current_block_num()

            if last_block % _batch_size == 0:
                schedule_batch(batch_dicts)
                batch_dicts = []

            if last_block % 100 == 0:
                log.info("#%s: (%s)" % (last_block, blockchain.steem.hostname))
Example #9
0
                                    "[Normal Process] SneakPeek Bot comment already present. Ignore and go to next iteration"
                                )
                                t_ignore = 1
                                break

                        if (t_ignore == 1):
                            continue
                        #newpid = os.fork()
                        print("[Normal Process] CAT (Func-MAIN()): %s" % cat)
                        # Threading is required in order to make sure
                        # that main loop doesn't miss a single block on the blockchain
                        # while processing the current match.
                        # Time processing traces added
                        nthread = printposts(cat, comment)
                        nthread.start()
        except:
            print("[Exception] Error Occurred @ Block No: ",
                  blck.get_current_block_num())
            exc_type, exc_value, exc_traceback = sys.exc_info()
            print("[Exception] Type : ", exc_type)
            print("[Exception] Value : ", exc_value)
            #Enough information present in Type and Value, incase further information is required then use following
            print("[Exception] Traceback : ")
            traceback.print_tb(exc_traceback)

# Filter tags for Alerts Settings
# [Normal Process]
# [All Trace]
# [Future]
# [Exception]
Example #10
0
            })

    def last_block(self):
        return self._settings.find_one().get('last_block', 1)

    def update_last_block(self, block_num):
        return self._settings.update_one({},
                                         {"$set": {
                                             'last_block': block_num
                                         }})


settings = Settings(mongo)
blockchain = Blockchain()

BLOCK_NUM = settings.last_block() or blockchain.get_current_block_num()
print(BLOCK_NUM)

# BLOCK_NUM = 26052441
# print(BLOCK_NUM)  # POST 26052437


def fix_legacy_json(json):
    # Coordinates
    if 'location' in json and isinstance(json['location'], dict):
        if json['location'].keys() >= {'name', 'lat', 'lng'}:
            json['location'] = {
                'geometry': {
                    'type':
                    'Point',
                    'coordinates':
Example #11
0
from steem.post import Post
from steem.instance import set_shared_steemd_instance
from steem.steemd import Steemd
from steem.amount import Amount
from steem.blockchain import Blockchain

#steemd_nodes = ['https://api.steemit.com']
steemd_nodes = ['https://rpc.buildteam.io']  #worked best
set_shared_steemd_instance(Steemd(nodes=steemd_nodes))
steem = Steem(nodes=steemd_nodes)

blockchain = Blockchain()

timeframe = 24 * 60 * 60

last_block = blockchain.get_current_block_num()
print(
    'Current Block:',
    str(last_block),
)
trail_24h_block = int(last_block - (timeframe / 3))
print(
    '24-hours-ago block:',
    str(trail_24h_block),
)

boosters = [
    'votebuster',
    'smartsteem',
    'mrswhale',
    'adriatik',
Example #12
0
class Requests:
    def __init__(self, private_posting_key):
        self.s = Steem(keys=[private_posting_key])
        self.b = Blockchain(steemd_instance=self.s)
        self.api = Api()
        self.settings = self.api.settings()

    def get_current_block_num(self):
        return self.b.get_current_block_num()

    def find_match(self, name, type, tournament_id=None, round=0):
        if type == "Ranked:":
            json_data = {"match_type": type}
        elif type == "Tournament":
            json_data = {
                "match_type": type,
                "settings": {
                    "tournament_id": tournament_id,
                    "round": round
                }
            }
        else:
            json_data = {"match_type": type}

        self.s.custom_json('sm_find_match',
                           json_data,
                           required_posting_auths=[name])

    def find_match_transaction(self, player, old_trx):
        #TODO add break condition, e.g. 5 minutes or validity block
        while True:
            try:
                block_num = self.b.get_current_block_num()
                for r in self.api.get_from_block(block_num):
                    if r["type"] == "find_match":
                        if r["id"] != old_trx:
                            if r["player"] == player:
                                print(r["id"])
                                return r["id"]

            except:
                print("Error while trying to get current block")

    def enter_tournament(self, id, name):
        json_data = {"tournament_id": id, "signed_pw": ""}

        self.s.custom_json('sm_enter_tournament',
                           json_data,
                           required_posting_auths=[name])

    def tournament_checkin(self, id, name):
        json_data = {"tournament_id": id, "signed_pw": ""}

        self.s.custom_json('sm_tournament_checkin',
                           json_data,
                           required_posting_auths=[name])

    def submit_team(self, trx_id, team, name):
        """
        Submits a Steem Monsters team for the given match search transaction
        :param trx_id: search transaction id
        :param team: list of UID's corresponding to Monsters (Summoner at index 0, Remaining team 1-n
        :param name: player name
        """
        secret = self.generate_key()
        hash = self.generate_team_hash(team[0], team[1:], secret)

        json_data = {
            "trx_id": trx_id,
            "team_hash": hash,
            "summoner": team[0],
            "monsters": team[1:],
            "secret": secret
        }

        self.s.custom_json('sm_submit_team',
                           json_data,
                           required_posting_auths=[name])

    def generate_key(self, length=10):
        return ''.join(
            choice(string.ascii_letters + string.digits)
            for i in range(length))

    def generate_team_hash(self, summoner, monsters, secret):
        m = hashlib.md5()
        m.update((summoner + ',' + ','.join(monsters) + ',' +
                  secret).encode("utf-8"))
        team_hash = m.hexdigest()
        return team_hash

    def open_card_pack(self, player, edition):
        """
        Opens a card pack and prints the transaction details

        Parameters:
        player (String): Name of the player
        edition (int): open pack of edition n, e.g. 1 for beta
        """

        self.s.custom_json("sm_open_pack", {"edition": edition},
                           required_posting_auths=[player])
        while True:
            for r in self.api.get_from_block(self.b.get_current_block_num()):

                if r["type"] == "open_pack":

                    if r["player"] == player:
                        print(r)
                        return r["id"]

    def claim_reward(self, name, quest_id, type):

        json_data = {"type": type, "quest_id": quest_id}

        self.s.custom_json('sm_claim_reward',
                           json_data,
                           required_posting_auths=[name])

    def start_quest(self, name, type):

        json_data = {"type": type}

        self.s.custom_json('sm_start_quest',
                           json_data,
                           required_posting_auths=[name])
Example #13
0
class YoBlockchainFollower(YoBaseService):
    service_name = 'blockchain_follower'

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        # init blockchain
        steemd_url = self.yo_app.config.steemd_url

        self.steemd = steem.steemd.Steemd(nodes=[steemd_url])
        self.blockchain = Blockchain(steemd_instance=self.steemd)
        self.start_block = self.yo_app.config.steemd_start_block

        self.last_block_num_handled = 0

        # init ops handlers
        self.op_map = defaultdict(list)
        self.op_map.update({
            'vote': [self.handle_vote],
            'account_update': [self.handle_account_update],
            'transfer': [self.handle_send, self.handle_receive],
            'custom_json': [self.handle_follow, self.handle_resteem],
            'withdraw_vesting': [self.handle_power_down],
            'comment': [self.handle_mention, self.handle_comment]
        })

        start_block = self.get_start_block()
        self.ops_func = self.blockchain.stream_from(
            start_block=start_block, batch_operations=True)
        self.ops = lambda: self.execute_sync(next, self.ops_func)

    def get_start_block(self):
        start_block = None
        try:
            if isinstance(self.start_block, int) and self.start_block < 0:
                start_block = self.blockchain.get_current_block_num() - self.start_block
        except Exception:
            self.log.exception('service error')
            start_block = None
        self.log.debug('get_start_block', start_block=start_block)
        return start_block

    async def store_notification(self, notifications):
        return await self.db.create_notifications(notifications)

    # pylint gets confused about these for some reason
    # pylint: disable=no-member
    async def handle_vote(self, op):
        vote_info = op['op'][1]
        self.log.info(
            'handle_vote',
            permlink=vote_info['permlink'],
            author=vote_info['author'],
            voter=vote_info['voter'],
            weight=vote_info['weight'])

        return [
            dict(
                trx_id=op['trx_id'],
                from_username=vote_info['voter'],
                to_username=vote_info['author'],
                json_data=json.dumps(vote_info),
                notify_type=VOTE,
                priority_level=Priority.LOW.value)
        ]

    async def handle_follow(self, op):
        if op['op'][1]['id'] != 'follow':
            self.log.debug('handle_follow noop')
            return []

        op_data = op['op'][1]
        follow_data = json.loads(op_data['json'])
        if follow_data[0] != 'follow':
            return []

        follower = follow_data[1]['follower']
        following = follow_data[1]['following']

        if len(op_data['required_posting_auths']) != 1:
            self.log.error('inavlid follow op, got %d posting auths, expected 1',
                           op_data['required_posting_auths'])
            return []

        if op_data['required_posting_auths'][0] != follower:
            self.log.error('invalid follow op, follower must be signer')
            return []
        self.log.debug('handle_follow', follower=follower, following=following)

        return [
            dict(
                trx_id=op['trx_id'],
                from_username=follower,
                to_username=following,
                json_data=json.dumps(follow_data[1]),
                notify_type=FOLLOW,
                priority_level=Priority.LOW.value)
        ]

    async def handle_account_update(self, op):
        op_data = op['op'][1]
        self.log.debug('handle_account_update', account=op_data['account'])
        return [
            dict(
                trx_id=op['trx_id'],
                to_username=op_data['account'],
                json_data=json.dumps(op_data),
                notify_type=ACCOUNT_UPDATE,
                priority_level=Priority.LOW.value)
        ]

    async def handle_send(self, op):
        op_data = op['op'][1]
        send_data = {
            'amount': op_data['amount'],
            'from': op_data['from'],
            'memo': op_data['memo'],
            'to': op_data['to'],
        }
        self.log.debug(
            'handle_send',
            _from=send_data['from'],
            amount=send_data['amount'],
            to=send_data['to'])
        return [
            dict(
                trx_id=op['trx_id'],
                to_username=send_data['from'],
                json_data=json.dumps(send_data),
                notify_type=SEND_STEEM,
                priority_level=Priority.LOW.value)
        ]

    async def handle_receive(self, op):
        op_data = op['op'][1]
        receive_data = {
            'amount': op_data['amount'],
            'from': op_data['from'],
            'memo': op_data['memo'],
            'to': op_data['to'],
        }
        self.log.debug(
            'handle_receive',
            to=receive_data['to'],
            amount=receive_data['amount'],
            _from=receive_data['from'])
        return [
            dict(
                trx_id=op['trx_id'],
                to_username=receive_data['to'],
                from_username=receive_data['from'],
                json_data=json.dumps(receive_data),
                notify_type=RECEIVE_STEEM,
                priority_level=Priority.LOW.value)
        ]

    async def handle_power_down(self, op):
        op_data = op['op'][1]
        self.log.debug(
            'handle_power_down',
            account=op_data['account'],
            amount=op_data['vesting_shares'])
        return [
            dict(
                trx_id=op['trx_id'],
                to_username=op_data['account'],
                json_data=json.dumps(op_data),
                notify_type=POWER_DOWN,
                priority_level=Priority.LOW.value)
        ]

    async def handle_mention(self, op):
        comment_data = op['op'][1]
        haystack = comment_data['body'] + '\n'
        data = {
            'author': comment_data['author'],
            'permlink': comment_data['permlink'],
        }
        notifications = []
        for match in set(re.findall(MENTION_PATTERN, haystack)):
            self.log.debug('handle_mention', author=data['author'], mentioned=match)
            notifications.append(
                dict(
                    trx_id=op['trx_id'],
                    to_username=match,
                    from_username=data['author'],
                    json_data=json.dumps(data),
                    notify_type=MENTION,
                    priority_level=Priority.LOW.value))
        return notifications

    async def handle_comment(self, op):
        self.log.debug('handle_comment', op=['op'][0])
        op_data = op['op'][1]
        if op_data['parent_author'] == '':
            # top level post
            return []
        parent_id = '@' + op_data['parent_author'] + '/' + op_data['parent_permlink']
        parent = steem.post.Post(parent_id)
        note_type = COMMENT_REPLY if parent.is_comment() else POST_REPLY
        self.log.debug(
            'handle_comment',
            note_type=note_type,
            author=op_data['author'],
            parent_id=parent_id)
        return [
            dict(
                trx_id=op['trx_id'],
                to_username=op_data['parent_author'],
                from_username=op_data['author'],
                json_data=json.dumps(op_data),
                notify_type=note_type,
                priority_level=Priority.LOW.value)
        ]

    async def handle_resteem(self, op):
        op_data = op['op'][1]
        resteem_data = json.loads(op_data['json'])
        if resteem_data[0] != 'reblog':
            self.log.debug('handle_resteem noop')
            return []

        account = resteem_data[1]['account']
        author = resteem_data[1]['author']
        permlink = resteem_data[1]['permlink']
        if len(op_data['required_posting_auths']) != 1:
            self.log.error('inavlid resteem op, got %d posting auths, expected 1',
                           op_data['required_posting_auths'])
            return []
        if op_data['required_posting_auths'][0] != account:
            self.log.error('invalid resteem op, account must be signer')
            return []
        self.log.debug(
            'handle_resteem', account=account, author=author, permlink=permlink)
        return [
            dict(
                trx_id=op['trx_id'],
                from_username=account,
                to_username=author,
                json_data=json.dumps(resteem_data[1]),
                notify_type=RESTEEM,
                priority_level=Priority.LOW.value)
        ]

    # pylint: enable=no-member

    async def notify(self, blockchain_op):
        """ Handle notification for a particular op
        """
        op_type = blockchain_op['op'][0]
        futures = [handler(blockchain_op) for handler in self.op_map[op_type]]
        if futures:
            self.log.debug(
                'operation triggering handlers', op_type=op_type, handlers=futures)
            return await asyncio.gather(*futures)
        else:
            self.log.debug('skipping operation', op_type=op_type)
            return []

    async def ops_iter(self):
        start_block = self.get_start_block()
        ops_func = self.blockchain.stream_from(
            start_block=start_block, batch_operations=True)
        while True:
            ops = await self.execute_sync(next, ops_func)
            yield ops

    async def main_task(self):
        self.log.debug('main task executed')
        async for ops in self.ops_iter():
            block_num = ops[0]['block']
            self.log.debug('main task', op_in_block=len(ops), block_num=block_num)

            unstored_notifications = await asyncio.gather(
                *[self.notify(op) for op in ops])
            combined_notifications = list(
                itertools.chain(*itertools.chain(*unstored_notifications)))

            logger.debug(
                'main_task',
                block_num=block_num,
                op_count=len(ops),
                unstored_count=sum(map(len, unstored_notifications)),
                combined_notifications=len(combined_notifications))
            resp = await self.store_notification(combined_notifications)
            if resp:
                self.last_block_num_handled = block_num
Example #14
0
class Upvotebot():
    def __init__(self):
        self.node_index = 0
        self.nodes = [
            'https://api.steemit.com', 'https://rpc.buildteam.io',
            'https://rpc.steemviz.com'
        ]
        self.steemPostingKey = os.environ.get('steemPostingKey')
        self.steem = Steem(wif=self.steemPostingKey, nodes=self.nodes)
        self.b = Blockchain(self.steem, mode='head')
        self.block = self.b.get_current_block_num()

        self.upvote_list = []
        self.trail_list = []
        self.day = None
        self.hour = None
        self.timestamp = None

        self.db = database.Database()

    # Voting is done via Steemconnect with the steemconnect plugin from
    # @emre: https://github.com/emre/steemconnect-python-client
    # Set client_id and client_sercret
    # Sign up at: https://v2.steemconnect.com/dashboard
    #
    # To perform a vote the access_token is fetched from the DB and checked
    # to not be expired, if so it is renewed and stored inside the DB.
    # Votes are then removed from the queue and their log is updated.
    # When a vote fails it gets added to the error database for manual review.
    def vote(self, voter, author, permlink, weight, type):
        result = self.db.get_user_auth(voter)
        access_token, refresh_token, expire_on = result[0]
        dt = datetime.now()
        c = Client(
            client_id=CLIENT_ID,
            client_secret=CLIENT_SECRET,
            access_token=access_token,
        )

        try:
            # Verify access_token
            if dt > expire_on:
                access_token = self.refresh_token(refresh_token)
                result = c.refresh_access_token(
                    refresh_token,
                    "login,vote"  # scopes
                )
                access_token = result['access_token']
                refresh_token = result['refresh_token']
                expires_in = result['expires_in']
                self.db.update_authentication_tokens(
                    voter,
                    access_token,
                    refresh_token,
                    expires_in,
                    self.timestamp,
                )
                print('Updated access token\n')

            # Perform vote
            if not self.is_already_voted(voter, author, permlink):
                vote = Vote(voter, author, permlink, weight)
                result = c.broadcast([vote.to_operation_structure()])

            # Log vote
            if 'error' in result:
                message = result['error_description']
                self.db.add_to_error_log(
                    voter,
                    author,
                    permlink,
                    weight,
                    type,
                    message,
                    self.timestamp,
                )
            else:
                message = 'Succes'
                if type == 'vote':
                    self.db.update_log(
                        voter,
                        permlink,
                        message,
                        'vote_log',
                    )
                elif type == 'trail':
                    self.db.update_log(
                        voter,
                        permlink,
                        message,
                        'trail_log',
                    )
                print(f"Voter: {voter}\nAuthor: {author}\n" +
                      f"Permlink: {permlink}\nWeight: {weight}\n" +
                      "Upvote succes\n")
        except Exception as error:
            print(voter, author, permlink, weight, error)
            self.db.add_to_error_log(
                voter,
                author,
                permlink,
                weight,
                type,
                error,
                self.timestamp,
            )

    # Trails with a delay of 0 are immediatly voted upon. Else the expire_on
    # time of the vote is calculated and added to the queue. The weight of
    # vote is relative between the weight of the vote casted by the voter that
    # is being trailed and the trailer who has set a custom relative weight.
    def add_trail_to_queue(self, trail, author, permlink, weight):
        for voter in self.db.get_trail_voters(trail):
            voter, voter_weight, limit, delay = voter
            vote_log = self.db.get_trail_log(voter, trail, self.timestamp)
            upvote_weight = weight / 100 * voter_weight / 100
            print(f"\nTrail: {trail}\nVoter: {voter}\nAuthor: {author}\n" +
                  f"Weight: {upvote_weight}\nLimit: {limit}\nDelay: {delay}\n")

            if delay != 0:
                self.db.add_trail_to_queue(
                    trail,
                    author,
                    voter,
                    upvote_weight,
                    limit,
                    delay,
                    permlink,
                    self.timestamp,
                )
            elif len(vote_log) < limit:
                self.db.add_to_trail_log(
                    author,
                    voter,
                    permlink,
                    upvote_weight,
                    self.timestamp,
                )
                self.vote(voter, author, permlink, weight, type)

    # The time for when a vote is to be made is calculated from the current
    # block time + the delay. If the delay is 0 an immediate vote is performed.
    # Votes get added to the queue and log
    def add_to_queue(self, author, permlink):
        for vote in self.db.get_votes(author):
            voter, weight, limit, delay = vote
            vote_log = self.db.get_vote_log(voter, author, self.timestamp)
            print(f"\nVoter: {voter}\nWeight: {weight}\nLimit: " +
                  f"{limit}\nDelay: {delay}")

            if delay != 0:
                self.db.add_to_queue(
                    author,
                    voter,
                    weight,
                    limit,
                    delay,
                    permlink,
                    self.timestamp,
                )
            elif len(vote_log) < limit:
                self.db.add_to_vote_log(
                    author,
                    voter,
                    permlink,
                    weight,
                    self.timestamp,
                )
                self.vote(voter, author, permlink, weight, type)

    # Go thourgh all the active votes and look if the voter has already
    # voted on this post.
    def is_already_voted(self, voter, author, permlink):
        try:
            identifier = f"@{author}/{permlink}"
            post = Post(identifier, self.steem)
            active_votes = post['active_votes']
            for vote in active_votes:
                if vote['voter'] == voter:
                    return 1
            return 0
        except Exception as error:
            return 0

    # Posts are verified to be the initial post and not an update
    def is_new_post(self, author, permlink):
        identifier = f"@{author}/{permlink}"
        post = Post(identifier, self.steem)
        created = post['created']
        last_update = post['last_update']

        if created != last_update:
            return 0
        else:
            return 1

    # Comment is checked to be of the post type and not a comment to a post.
    # Posts are then added to queue
    def process_comment(self, comment):
        parent_author = comment['parent_author']
        author = comment['author']

        if parent_author == '' and author in self.upvote_list:
            permlink = comment['permlink']
            if self.is_new_post(author, permlink):
                print(f'\n\n{self.timestamp} Block: {self.block}')
                print(f"New post\nAuthor: {author}")
                self.add_to_queue(author, permlink)

    # Votes are checked for their voter and if the voter is being trailed
    def process_vote(self, vote):
        trail = vote['voter']

        if trail in self.trail_list:
            author = vote['author']
            permlink = vote['permlink']
            weight = vote['weight']
            print(f"\n\nTrail: {trail}\nAuthor: {author}\nPermlink: " +
                  f"{permlink}\nWeight: {weight}\n")

            self.add_trail_to_queue(trail, author, permlink, weight)

    # Each block the queue is fetched and checked for votes that have reached
    # their maturity time.
    def process_queue(self):
        dt = datetime.strptime(self.timestamp, '%Y-%m-%dT%H:%M:%S')
        result = self.db.get_queue()

        if len(result) > 0:
            for vote in result:
                id, voter, author, permlink, weight, type, expire_on = vote
                if dt > expire_on:
                    self.vote(voter, author, permlink, weight, type)
                    self.db.remove_from_queue(id)

    # Stream block indefinitely, process each block for comments
    # Stream is set to head mode
    def run(self):
        stream = self.b.stream_from(
            start_block=self.block,
            full_blocks=True,
        )

        while True:
            try:
                for block in stream:
                    # Set block time and process queue
                    self.timestamp = block['timestamp']
                    print(f'{self.timestamp} Block: {self.block}', end='\r')
                    self.process_queue()

                    # Fetch author to be upvoted list
                    self.upvote_list = []
                    for author in self.db.get_authors():
                        author = re.sub(
                            '[^A-Za-z0-9^-]+',
                            '',
                            author[0].lower(),
                        )
                        self.upvote_list.append(author)

                    # Fetch trails to be tracked
                    self.trail_list = []
                    for trail in self.db.get_trails():
                        trail = re.sub(
                            '[^A-Za-z0-9^-]+',
                            '',
                            trail[0].lower(),
                        )
                        self.trail_list.append(trail)

                    # Look at each single transaxtion
                    for transaction in block['transactions']:
                        transaction_type = transaction['operations'][0][0]
                        if transaction_type == 'comment':
                            comment = transaction['operations'][0][1]
                            self.process_comment(comment)
                        elif transaction_type == 'vote':
                            vote = transaction['operations'][0][1]
                            self.process_vote(vote)

                    self.block += 1

            except Exception as e:
                print(e)
                # common exception for api.steemit.com
                # when the head block is reached
                s = ("TypeError('an integer is"
                     " required (got type NoneType)',)")
                if repr(e) == s:
                    time.sleep(1)
                else:
                    stream = self.b.stream_from(
                        start_block=self.block,
                        full_blocks=True,
                    )
                    continue
		print(len(resteems))
		print("================================================================\n")
		comments_detail = steem.get_content_replies(author_adj, postdetails[3])
		print(len(comments_detail))
# MAIN
if __name__ == "__main__":
	while 1:
		try:
			for comment in steem.stream_comments():
				#match = re.search(r'(?i)(!)StatsBot(!*)', comment['body'])
				#if match is None:
				#	continue
				#else:
					#print("[Normal_Traces] StateBot Summoned. Initiating the process")
					if (comment.is_main_post()):
						continue
					else:
						url_string = comment['url'].split("#")
						print('https://steemit.com%s' %(url_string[0])) 
						thread_one = print_stats(url_string[0], comment['author'])
						thread_one.start()
						break
		except Exception as e:
			print("[Exception] Error Occurred @ Block No: ", BlockInfo.get_current_block_num())
			exc_type, exc_value, exc_traceback = sys.exc_info()
			print("[Exception] Type : ", exc_type)
			print("[Exception] Value : ", exc_value)
			print("[Exception] Traceback : ")
			traceback.print_tb(exc_traceback)
		break