def test_witness_update(): # TODO: Remove when witness_update is fixed. return wif = '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3' c = Commit(steemd_instance=Steemd(nodes=[]), keys=[wif]) signing_key = 'BMT1111111111111111111111111111111114T1Anm' props = { 'account_creation_fee': '0.500 BMT', 'maximum_block_size': 65536, 'sbd_interest_rate': 0 } rpc_error = None try: c.witness_update(signing_key=signing_key, account='test', props=props, url='foo') except RPCError as e: rpc_error = str(e) else: raise Exception('expected RPCError') assert 'tx_missing_active_auth' in rpc_error
def test_transfer(): wif = '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3' c = Commit(steemd_instance=Steemd(nodes=[]), keys=[wif]) rpc_error = None try: c.transfer('test2', '1.000', 'STEEM', 'foo', 'test') except RPCError as e: rpc_error = str(e) else: raise Exception('expected RPCError') assert 'tx_missing_active_auth' in rpc_error
def claim_rewards(steem, account_name): logger.info('Logged In. Checking for rewards.') account = steem.get_account(account_name) rewards = reward_available(account) if rewards: logger.info('Claiming rewards.') commit = Commit(steem) commit.claim_reward_balance(account=account_name) logger.info( 'Rewards are claimed. %s STEEM, %s SBD, %s VESTS', rewards["steem"], rewards["sbd"], rewards["vesting"], )
def test_claim_reward(): wif = '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3' c = Commit(steemd_instance=Steemd(nodes=[]), keys=[wif]) rpc_error = None try: c.claim_reward_balance(account='test', reward_steem='1.000 STEEM', reward_vests='0.000000 VESTS', reward_sbd='0.000 SBD') except RPCError as e: rpc_error = str(e) else: raise Exception('expected RPCError') assert 'tx_missing_posting_auth' in rpc_error
def test_witness_set_properties(): wif = '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3' c = Commit(steemd_instance=Steemd(nodes=[]), keys=[wif]) signing_key = 'STM1111111111111111111111111111111114T1Anm' props = [ ['account_creation_fee', 'd0070000000000000354455354530000'], ['key', ('032d2a4af3e23294e0a1d9dbc46e0272d' '8e1977ce2ae3349527cc90fe1cc9c5db9')] ] rpc_error = None try: c.witness_set_properties( signing_key=signing_key, props=props, account='test') except RPCError as e: rpc_error = str(e) else: raise Exception('expected RPCError') assert 'tx_missing_other_auth' in rpc_error
def run(args): log.info("Market summary mode activated", args=args) if args is None or len(args) < 3: raise ValueError( "You must specify a currency pair, title, and one or more tags") pair = args[0] title = args[1] tags = args[2:] log.debug("initializing...") steem = Steem(keys=[account.key]) commit = Commit(steem) api = Poloniex() market = Market(commit, api, pair) log.debug("ready", steem=steem, commit=commit, api=api, market=market) market.summarize(title, tags)
def __init__(self, steemd_instance, bot_account): self.s = steemd_instance self.commit = Commit(steemd_instance=self.s) self.bot_account = bot_account self.debug = bool(1)
def reconnect(self): """Creates a new Steemd and Commit""" self.steemd = Steemd(nodes=self.nodes.copy(), **self.kwargs.copy()) self.commit = Commit(steemd_instance=self.steemd, no_broadcast=self.no_broadcast, **self.kwargs.copy())
from steem import Steem from steem.commit import Commit s = Steem() query = { "limit": 5, #number of posts "tag": "" #tag of posts } # post list from trending post list posts = s.get_discussions_by_trending(query) title = 'Please choose post to reblog: ' options = [] # post list for post in posts: options.append('@' + post["author"] + '/' + post["permlink"]) # get index and selected post option, index = pick(options, title) pprint.pprint("You selected: " + option) account = input("Enter your username? ") wif = input("Enter your Posting private key? ") # commit or build transaction c = Commit(steem=Steem(keys=[wif])) # broadcast transaction c.resteem(option, account=account)
class Game: def __init__(self, steemd_instance, bot_account): self.s = steemd_instance self.commit = Commit(steemd_instance=self.s) self.bot_account = bot_account self.debug = bool(1) def build_permlink(self): return str(uuid.uuid4()) def get_sample_comment(self, user): data = { 'derasmo': 'vorstellung-von-mir-und-meiner-projektidee', 'flurgx': 're-derasmo-vorstellung-von-mir-und-meiner-projektidee-20180213t210718018z', 'kurodevs': 're-derasmo-vorstellung-von-mir-und-meiner-projektidee-20180213t203220853z' } if user in data: return data[user] return bool(0) def get_valid_votes(self, votes, limit): v_votes = [] s_votes = sorted(votes, key=lambda tmp: tmp['time']) if self.debug: for vote in s_votes: if self.get_sample_comment(vote['voter']) != bool(0): v_votes.append(vote) else: v_votes = s_votes return itertools.islice(v_votes, limit) def post_to_webhooks(self, score): hook = Webhook(None) hook.set_author( name=self.bot_account, url="http://steemit.com/@%s" % self.bot_account, icon="https://img.busy.org/@%s?height=100&width=100" % self.bot_account, ) hook.add_field( name="Message", value=score, ) for hook_url in HOOKS: hook.url = hook_url hook.post() def post(self, title, body, author, permlink=None, reply_identifier=None, beneficiaries=None): print('post parameter') print('--------------------') print('title: ' + title) print('author: ' + author) if permlink is not None: print('permlink: ' + permlink) if reply_identifier is not None: print('reply_identifier: ' + reply_identifier) if beneficiaries is not None: print('beneficiearies: ') print(beneficiaries) print('') if self.debug: permlink = self.get_sample_comment(author) print('---') print('Called post but post will not be submitted') print( 'Function was called with %(auth)s as author and %(ttl)s as the title' % { 'auth': author, 'ttl': title }) print('A permlink was created: %(link)s' % {'link': permlink}) print('The posts content:') print(body) elif permlink is not None: self.commit.post(title, body, author, permlink, reply_identifier) else: permlink = self.build_permlink() self.commit.post(title, body, author, permlink, reply_identifier) return permlink def evaluate(self, results): output = '<div>The game has finished. Voting results are:</div>' for voter, result in results.items(): oLine = '<div>' + voter + ': ' + str(result) + '</div>' output = output + oLine thanks = '<div>Thanks for participating. If you want to support me in this project please consider voting on this comment.</div>' output = output + thanks return output def start_game(self): self.post_to_webhooks('A game has started!') #settings duration_hours = 12 duration_minutes = 0 duration_seconds = 0 limit = 2 # 1. create post title = 'testing a bot' body = 'This post is auto generated and ment for testing pupose. You can read in more detail what it\'s all about in the [introdutction post](https://steemit.com/@derasmo/vorstellung-von-mir-und-meiner-projektidee). All rewards go to @deutschbot, because I use his code, @markus.light, because he volunteered, and @reeceypie, because @ocd resteemed a post I liked.' permlink = 'testing-a-bot-bot-bot' beneficiaries = [{ 'account': '@deutschbot', 'weight': 2500 }, { 'account': '@markus.light', 'weight': 3750 }, { 'account': '@reeceypie', 'weight': 3750 }] permlink = self.post(title, body, self.bot_account, permlink=permlink, beneficiaries=beneficiaries) # 2. catch upvotes and create comments postid = "@" + self.bot_account + "/" + permlink start = time.time() duration = duration_hours * 360 + duration_minutes * 60 + duration_seconds voters = [] permlinks = {} while time.time() < start + duration: if len(voters) < limit: votes = self.s.get_active_votes(self.bot_account, permlink) if len(votes) > 0: # sort votes by time and cut off above limit v_votes = self.get_valid_votes(votes, limit) for vote in v_votes: if vote['voter'] not in voters: if len(voters) < 1: comment_body = vote[ 'voter'] + 'is collecting for @mack-bot. In Addition to the users mentioned in the post @mack-bot will receive a share. Please vote if you want them to win.' comment_beneficiaries = [{ 'account': '@deutschbot', 'weight': 2500 }, { 'account': '@markus.light', 'weight': 2500 }, { 'account': '@reeceypie', 'weight': 2500 }, { 'account': '@mack-bot', 'weight': 2500 }] else: comment_body = '@' + vote[ 'voter'] + 'is collecting for @spaminator. In Addition to the users mentioned in the post @spaminator will receive a share. Please vote if you want them to win.' comment_beneficiaries = [{ 'account': '@deutschbot', 'weight': 2500 }, { 'account': '@markus.light', 'weight': 2500 }, { 'account': '@reeceypie', 'weight': 2500 }, { 'account': '@spaminator', 'weight': 2500 }] if self.debug and self.get_sample_comment( vote['voter']) != bool(0): self.post_to_webhooks(vote['voter'] + ' joined the game.') voters.append(vote['voter']) permlinks[vote['voter']] = self.post( '', comment_body, vote['voter'], reply_identifier=postid, beneficiaries=comment_beneficiaries) elif self.debug == bool(0): self.post_to_webhooks(vote['voter'] + ' joined the game.') voters.append(vote['voter']) permlink = 'testing-a-bot-bot-bot-comment-' + len( voters) permlinks[vote['voter']] = self.post( '', comment_body, self.bot_account, permlink=permlink, reply_identifier=postid, beneficiaries=comment_beneficiaries) time.sleep(5) # 3. post summary results = {} for voter in voters: if self.debug: votes = self.s.get_active_votes(voter, permlinks[voter]) else: votes = self.s.get_active_votes(self.bot_account, permlinks[voter]) results[voter] = len(votes) results_body = self.evaluate(results) self.post_to_webhooks(results_body) self.post('', results_body, self.bot_account, reply_identifier=postid)
def __init__(self, steem, config): self.steem = steem self.account = config["account"] self.mysql_uri = config["mysql_uri"] self.config = config self.commit = Commit(steem)
class TransactionListener(object): def __init__(self, steem, config): self.steem = steem self.account = config["account"] self.mysql_uri = config["mysql_uri"] self.config = config self.commit = Commit(steem) def get_table(self, table): db = dataset.connect(self.mysql_uri) return db[table] @property def properties(self): props = self.steem.get_dynamic_global_properties() if not props: logger.info('Couldnt get block num. Retrying.') return self.properties return props @property def last_block_num(self): return self.properties['head_block_number'] @property def block_interval(self): config = self.steem.get_config() return config["STEEMIT_BLOCK_INTERVAL"] def process_block(self, block_num, retry_count=0): block_data = self.steem.get_block(block_num) if not block_data: if retry_count > 3: logger.error('Retried 3 times to get this block: %s Skipping.', block_num) return logger.error('Couldnt read the block: %s. Retrying.', block_num) self.process_block(block_num, retry_count=retry_count + 1) logger.info('Processing block: %s', block_num) if 'transactions' not in block_data: return self.check_block(block_num) dump_state(self.properties) def run(self, start_from=None): if start_from is None: last_block = load_checkpoint( fallback_block_num=self.last_block_num, ) logger.info('Last processed block: %s', last_block) else: last_block = start_from while True: while (self.last_block_num - last_block) > 0: last_block += 1 self.process_block(last_block) dump_checkpoint(last_block) # Sleep for one block block_interval = self.block_interval logger.info('Sleeping for %s seconds.', block_interval) time.sleep(block_interval) def daily_message(self): post_list = [] query = {"limit": 15, "tag": "tr"} # limit for 5 posts for p in self.steem.get_discussions_by_hot(query): metadata = json.loads(p["json_metadata"]) if metadata and 'utopian-io' in metadata["tags"]: continue if metadata and 'sndbox' in metadata["tags"]: continue if p["author"] == "turbot": continue link = "https://steemit.com/@%s/%s" % (p["author"], p["permlink"]) author_link = "https://steemit.com/%s" % p["author"] post = Post(link, steemd_instance=self.steem) try: self.upvote(post, 20) time.sleep(4) pass except Exception as error: logger.error(error) post_list.append("- [%s](%s) - [@%s](%s)" % (p["title"], link, p["author"], author_link)) body = open(self.config["daily_message"]).read() body = body.replace("$post_list", "\n".join(post_list)) today = date.today().strftime("%Y.%m.%d") self.steem.commit.post( "Son 24 saatte turbot tarafından oylanan yazılar (%s)" % today, body, "turbot", tags=["tr", "turbot"]) def upvote(self, post, weight=+5): full_link = "@%s/%s" % (post["author"], post["permlink"]) already_upvoted = self.get_table('upvote').find_one( author=post["author"], permlink=post["permlink"]) if already_upvoted: logger.info('Already voted. Skipping. %s', full_link) return resp = post.commit.vote(post.identifier, weight, account=self.account) if not resp: logger.error("Failed upvoting. %s", full_link) def handle_command(self, post): if post["author"] in self.config["blacklisted_users"]: logger.info("User on blacklist. (%s). Skipping", post["permlink"]) return # welcome command if re.findall("@%s\s!(welcome)" % self.account, post["body"]): main_post = Post(post.root_identifier, steemd_instance=self.steem) already_welcomed = self.get_table('welcome').find_one( author=main_post["author"]) if already_welcomed: logger.info("This user: %s already welcomed. Skipping" % main_post["author"]) return body = open(self.config["welcome_message"]).read() body = body.replace("$username", main_post["author"]) main_post.reply( body=body, author=self.account, ) if not main_post.is_main_post(): logger.info("Skipping. Not a main post.") return try: self.upvote(main_post) except Exception as e: logger.error(e) logger.info("Replied and upvoted user: %s", main_post["author"]) self.get_table('welcome').insert( dict( author=main_post["author"], permlink=main_post["permlink"], created_at=str(datetime.now()), )) if self.config["send_welcome_gift"] == "yes": self.commit.transfer(main_post["author"], self.config["welcome_gift"], memo=self.config["welcome_gift_message"], asset="SBD", account=self.account) # handle help commands help_commands = [ "creating_new_accounts", "bots", "curation_rewards", "downvote", "esteem", "security", "voting_power", "upvote", "tag_spam", "comment_spam", "wallet", "plagiarism", "posting" ] for command in help_commands: if re.findall("@%s\s!(%s)" % (self.account, command), post["body"]): message_path = "%s%s.md" % (self.config["help_commands_path"], command) main_post = Post(post.root_identifier, steemd_instance=self.steem) body = open(message_path).read() body = body.replace("$username", main_post["author"]) if not main_post.is_main_post(): logger.info("Skipping. Not a main post.") return main_post.reply( body=body, author=self.account, ) logger.info("Posted %s command reply." % command) def check_block(self, block_num): operation_data = self.steem.get_ops_in_block(block_num, virtual_only=False) for operation in operation_data: operation_type, raw_data = operation["op"][0:2] if operation_type == "comment": try: post = Post(raw_data, steemd_instance=self.steem) except Exception as error: logger.error(error) continue if post.is_main_post(): # we're only interested in comments. continue if "@" + self.account in post["body"]: try: self.handle_command(post) except Exception as e: logger.error(e)
def __init__(self, steem): self.steem = steem self.commit = Commit(steem) self.watch_account = settings.BOT_ACCOUNT
class TransactionListener(object): def __init__(self, steem): self.steem = steem self.commit = Commit(steem) self.watch_account = settings.BOT_ACCOUNT @property def last_irreversible_block_num(self): props = self.steem.get_dynamic_global_properties() if not props: logger.info('Couldnt get block num. Retrying.') return self.last_irreversible_block_num return props['last_irreversible_block_num'] @property def block_interval(self): config = self.steem.get_config() return config["STEEMIT_BLOCK_INTERVAL"] @property def upvote_weight(self): min_weight, max_weight = settings.UPVOTE_WEIGHTS return float(random.randint(min_weight, max_weight)) def process_block(self, block_id, retry_count=0): block_data = self.steem.get_block(block_id) if not block_data: if retry_count > 3: logger.error('Retried 3 times to get this block: %s Skipping.', block_id) return logger.error('Couldnt read the block: %s. Retrying.', block_id) self.process_block(block_id, retry_count=retry_count + 1) logger.info('Processing block: %s', block_id) if 'transactions' not in block_data: return for tx in block_data['transactions']: for operation in tx['operations']: operation_type, operation_data = operation[0:2] if operation_type == 'transfer': self.process_transfer(operation_data, block_data, block_id) def process_transfer(self, op, block_data, block_id): if op["to"] == self.watch_account: logger.info("%d | %s | %s -> %s: %s -- %s" % (block_id, block_data["timestamp"], op["from"], op["to"], op["amount"], op["memo"])) if "SBD" in op['amount']: amount_in_float = float(op['amount'].split(' ')[0]) if amount_in_float < settings.MINIMUM_SBD_FOR_UPVOTE: self.refund( op, 'Minimum SBD for upvote: %s' % settings.MINIMUM_SBD_FOR_UPVOTE) return self.upvote(op) else: logger.info('There is a transfer but its not SBD. Ignoring.') def refund(self, op, message): refund_key = db.refund_key(op['from'], op['memo'], op['amount']) if db.already_refunded(op['from'], op['memo'], op['amount']): logger.info('This is already refunded. Skipping. %s', refund_key) return refund_amount, asset = op['amount'].split(' ') if float(refund_amount) > 0.5: logger.error('Too much for a auto-refund. Skipping.') return self.commit.transfer(op['from'], float(refund_amount), memo=message, asset=asset, account=self.watch_account) logger.info('Refunded %s for invalid request.', op['from']) db.add_refund(op['from'], op['memo'], op['amount']) def upvote(self, op): try: post = Post(op['memo']) except ValueError: logger.info('Invalid identifier: %s', op['memo']) self.refund(op, message='invalid url') return try: weight = self.upvote_weight post.upvote(weight=weight, voter=self.watch_account) except VotingInvalidOnArchivedPost as e: logger.info('Archived post. Cannot upvote. %s', op['memo']) self.refund(op, message='Couldnt vote. Archived post. %s' % op['memo']) return except Exception as e: if 'already voted' in e.args[0]: self.refund(op, message='Already upvoted. %s' % op['memo']) logger.info('Already voted: %s. Skipping.', op['memo']) return if 'Read timed' in e.args[0]: logger.info('Node is not responding. Trying again to upvote.') return self.upvote(op) logger.info('Upvoted %s with weight: %s', op['memo'], weight) def run(self): last_block = db.load_checkpoint( fallback_block_num=self.last_irreversible_block_num, ) logger.info('Last processed block: %s', last_block) while True: while (self.last_irreversible_block_num - last_block) > 0: last_block += 1 self.process_block(last_block) db.dump_checkpoint(last_block) # Sleep for one block block_interval = self.block_interval logger.info('Sleeping for %s seconds.', block_interval) time.sleep(block_interval)
def run(): log.info("Timely post mode activated") log.debug("initializing...") steem = Steem(keys=[cred.key]) account = Account(cred.id, steem) chain = Blockchain(steem) commit = Commit(steem) log.debug("ready", steem=steem, account=account, blockchain=chain, commit=commit) # Because subsequent edits to a post show up as separate post entries in the blockchain, # we'll keep a list of candidates keyed by the post identifier which the edits share. candidates = {} log.info("Checking post history...") history = map(Post, account.history(filter_by=['comment'])) # FIXME: use steem.get_posts() instead? for post in history: if post.is_main_post(): log.debug("found a top-level post", post=post, tags=post.tags) if post.tags[0] == cred.id and 'boiled' not in post.tags: candidates[post.identifier] = post if len(candidates) > 0: log.info("Found one or more historical posts to process", posts=candidates) deleting = [] for key, post in candidates.items(): result = process(commit, post) if result or result is None: deleting.append(key) for key in deleting: del candidates[key] log.info("Watching for new posts...") while True: stream = map(Post, chain.stream(filter_by=['comment'])) try: for post in stream: if post.is_main_post() and post.author == cred.id: log.debug("found a top-level post", post=post, tags=post.tags) if len(post.tags) == 2 and post.tags[0] == cred.id and post.tags[1] == cred.id: candidates[post.identifier] = post deleting = [] for key, post in candidates.items(): result = process(commit, post) if result or result is None: deleting.append(key) for key in deleting: del candidates[key] except PostDoesNotExist as e: log.debug("Post has vanished", exception=e) except RPCError as e: log.error("RPC problem while streaming posts", exception=e)
def get_steem_committer(self): retval = Commit(steemd_instance=self.steemd_rpc, debug=self.debug_mode, keys=self.keys) return retval
# globals misses = 0 failover_after = 5 counter = 0 # witness witness_url = "https://yourwebsite.com" witness_props = { "account_creation_fee": "3.000 STEEM", "maximum_block_size": 65536, "sbd_interest_rate": 0, } b = Blockchain(steemd_instance=s) t = Commit(steemd_instance=s, no_broadcast=debug, keys=steem_keys) def l(msg, slack=False): caller = inspect.stack()[1][3] print("[{}] {}".format(str(caller), str(msg))) sys.stdout.flush() def get_witness_key(): return s.get_witness_by_account(steem_account)['signing_key'] def get_misses(): return s.get_witness_by_account(steem_account)['total_missed']