def __init__(self): super().__init__() # self.authors = {} self.posts_num = 0 self.voted_posts = 0 self.curator = SteemAccount(self.by()) self.followings = self.curator.get_followings()
def _get_reply_body(self, message_id, author): account = SteemAccount(author) comments_num = account.remaining_comments() or '' daily_comments_num = round(account.daily_recovery_comments(), 1) or '' return get_message(message_id).format( name=author, comments_num=comments_num, daily_comments_num=daily_comments_num)
def get_votes(self, authors, up=None): votes = [] for author in authors: acc = SteemAccount(author=author) my_votes = acc.get_votes(up) for v in my_votes: v['voter'] = author votes += my_votes return votes
class CnReaderVoter(VoteRecipe): def __init__(self): super().__init__() # self.authors = {} self.posts_num = 0 self.voted_posts = 0 self.curator = SteemAccount(self.by()) self.followings = self.curator.get_followings() def mode(self): return "query.comment.post" def config(self): return { "account": RESTEEM_ACCOUNT, "days": CURATION_CYCLE, "reblog": True } def by(self): return VOTER_ACCOUNT def what_to_vote(self, ops): if not self.ops.is_upvoted_by(self.by()): logger.info("We will vote the post {}".format(self.ops.get_url())) self.posts_num += 1 return True return False def who_to_vote(self, author): if not author in self.followings: self.curator.follow(author) logger.info("follow the new author @{}".format(author)) self.followings.append(author) return True def when_to_vote(self, ops): return VOTE_TIMING # mins def how_to_vote(self, post): self.voted_posts += 1 logger.info("voting {} / {} posts".format(self.voted_posts, self.posts_num)) weight = self.voter.estimate_vote_pct_for_n_votes( days=CURATION_CYCLE, n=self.posts_num) * VOTE_PERCENTAGE if weight > UPVOTE_LIMIT: weight = UPVOTE_LIMIT return weight def after_success(self, res): if self.voted_posts == self.posts_num: logger.info("Done with voting. Exit.") sys.exit()
def _get_daily_blog_body(self, message_id): delta = 0.05 daily_replies = self._get_replies("welcome", 1.0 - delta) # 1 days weekly_replies = self._get_replies("welcome", 7.0 - delta) # 7 days daily_total = len(daily_replies) weekly_total = len(weekly_replies) articles = [ ("@{}".format(r['receiver']), "<a href=\"{}\">{}</a>".format(self._get_accessible_url(r['url']), r['title'])) for r in daily_replies ] articles_table = build_table(["作者", "文章"], articles) stats = [] for r in weekly_replies: author = r['receiver'] account = SteemAccount(author) steemd_link = "{}/@{}".format(STEEMD_HOST, author) row = ("@{}".format(author), round(account.age_in_days(), 1), round(account.reputation(), 1), "<a href=\"{}\">{}%</a>".format( steemd_link, round(account.rc_percentage(), 1)), round(account.steem_power(), 1), account.follower_count(), account.post_count()) stats.append(row) stats = sorted(stats, key=(lambda row: row[1]), reverse=False) stats_table = build_table( ["新人", "天数", "声望", "活动能量", "Steem Power", "粉丝数", "发帖数"], stats) return get_message(message_id).format(daily_total=daily_total, weekly_total=weekly_total, articles_table=articles_table, stats_table=stats_table)
class ClaimBot: def __init__(self): self.claimer_author = settings.get_env_var(PILOT_ACCOUNT_KEY) or DEFAULT_PILOT_ACCOUNT self.claimer_account = SteemAccount(author=self.claimer_author) def get_users(self): users = [] delegations = self.claimer_account.incoming_delegations() for delegation in delegations: vesting_shares = float(delegation["vesting_shares"]["amount"]) if vesting_shares > MINIMUM_SP_DELEGATION: users.append(delegation["delegator"]) return users def claim_all_accounts(self): users = self.get_users() logger.info("The current users are : {}".format(users)) for user in users: logger.info("Claim rewards for @{}".format(user)) self.claim_all_scot_tokens(user) def claim_scot_token(self, author, token): claimer = Claimer(author) claimer.claim_scot_token(token) def claim_all_scot_tokens(self, author): claimer = Claimer(author) claimer.claim_all_scot_tokens()
def who_to_vote(self, author): if author in BLACKLIST: logger.info("Skip [{}] who is in my blacklist".format(author)) return False account = SteemAccount(author) if account.reputation() < ACCOUNT_REPUTATION_THRESHOLD: logger.info("Skip [{}] whose reputation is too low".format(author)) return False if self.authors.get(author) is None: self.authors[author] = 1 self.posts_num += 1 return True elif self.authors.get(author) < VOTE_PER_ACCOUNT_LIMIT: self.authors[author] += 1 self.posts_num += 1 return True elif self.authors.get(author) >= VOTE_PER_ACCOUNT_LIMIT: return False return False
def _add_reply_record(self, receiver, message_id, post, timestamp=None): if receiver and message_id and post: if not self._has_reply_record(receiver, message_id): timestamp = timestamp or datetime.now(pytz.utc) reply = { "receiver": receiver, "reputation": SteemAccount(receiver).reputation(), "message_id": message_id, "url": post.get_url(), "title": post.get_comment().title, "updated": timestamp } self.db.insert_reply(reply) logger.info( "Add reply to author @{} with message [{}] into database". format(receiver, message_id)) return True return False
def curation_rewards(username): if username.startswith("@"): username = username.replace("@", "") s = get_steem_conn() account = Account(username, s).set_account_deta() info = s.get_dynamic_global_properties() checkpoint_val = request.args.get("checkpoint") total_sp, total_rshares, checkpoints = get_curation_rewards( SteemAccount(username, steemd_instance=s), info, checkpoint_val=checkpoint_val) return render_template( "curation_rewards.html", account=account, total_sp=round(total_sp, 2), total_rshares=total_rshares, checkpoints=checkpoints, )
def update_config(self, incremental=False): if not self.account: return domain = self._get_domain() organization = BLOG_ORGANIZATION logo = BLOG_AVATAR favicon = BLOG_FAVICON language = settings.get_env_var("LANGUAGE") or "en" a = SteemAccount(self.account) author = self.account name = self._yaml_compatible(a.get_profile("name"), "") avatar = self._yaml_compatible(a.avatar(), "") # about = a.get_profile("about") or "" location = self._yaml_compatible(a.get_profile("location"), "") website = self._yaml_compatible(a.get_profile("website"), "''") incremental = "true" if incremental else "false" # build config file with template template = get_message("config") config = template.format(organization=organization, domain=domain, language=language, name=name, author=author, incremental=incremental) filename = CONFIG_FILE with open(filename, "w", encoding="utf-8") as f: f.write(config) logger.info("{} file has been updated for the account @{}".format( filename, author)) # build config theme file with template template = get_message("config.theme") config = template.format(organization=organization, favicon=favicon, logo=logo, author=author, name=name, location=location, avatar=avatar, website=website) filename = CONFIG_THEME_FILE with open(filename, "w", encoding="utf-8") as f: f.write(config) logger.info("{} file has been updated for the account @{}".format( filename, author))
def __init__(self, author): self.author = author self.account = SteemAccount(self.author) self.vp_limit = {}
class Voter: def __init__(self, author): self.author = author self.account = SteemAccount(self.author) self.vp_limit = {} def vote(self, post, weight=100): if post: if weight and weight >= -100 and weight <= 100: if weight > 0: if self.has_vp(up=True): return self._upvote(post, weight) else: logger.error("{} has no enough VP for upvote".format( self.author)) else: if self.has_vp(up=False): return self._downvote(post, weight) else: logger.error("{} has no enough VP for downvote".format( self.author)) else: logger.error( "Failed: the vote weight {} exceeds the range [-100, 100]". format(weight)) return False def _upvote(self, post, weight): c = SteemComment(comment=post) if not c.is_upvoted_by(self.author): post.upvote(weight=weight, voter=self.author) logger.info( "Upvoted to [{}] [{}] with weight [{:.2f}] successfully". format(post.title, c.get_url(), weight)) return True else: logger.info( "Skip upvote because I already upvoted this post [{}] [{}]". format(post.title, c.get_url())) return False def _downvote(self, post, weight): c = SteemComment(comment=post) if not c.is_downvoted_by(self.author): post.downvote(weight=weight, voter=self.author) logger.info( "Downvoted to [{}] [{}] with weight [{:.2f}] successfully". format(post.title, c.get_url(), weight)) return True else: logger.info( "Skip downvote because I already downvoted this post [{}] [{}]" .format(post.title, c.get_url())) return False def estimate_vote_value_for_token(self, symbol, weight=100, up=True): token_voting_power = self.account.get_scot_voting_power(symbol, up) scot_staked = self.account.get_scot_staked(symbol) multiplier = self.account.get_vote_multiplier(symbol, up) pending_rshares = scot_token_info(symbol, "pending_rshares") reward_pool = scot_token_info(symbol, "reward_pool") precision = scot_token_info(symbol, "precision") author_curve_exponent = scot_token_config(symbol, "author_curve_exponent") # print ("estimate_vote_value", token_voting_power, scot_staked, pending_rshares, reward_pool, author_curve_exponent, multiplier) def apply_reward_curve(rshares): return pow(max(0, rshares), author_curve_exponent) * reward_pool / pending_rshares direction = 1 if up else -1 rshares = float(up) * float(scot_staked) * min( abs(multiplier * weight), 100) * float(token_voting_power) / (10000 * 100) # newValue = apply_reward_curve(voteRshares + rshares); # print ("reshares", rshares) value = apply_reward_curve(rshares) return round(value / pow(10, precision), precision) def estimate_vote_pct_for_token(self, symbol, value): up = True if value >= 0 else False token_voting_power = self.account.get_scot_voting_power(symbol, up) scot_staked = self.account.get_scot_staked(symbol) multiplier = self.account.get_vote_multiplier(symbol, up) pending_rshares = scot_token_info(symbol, "pending_rshares") reward_pool = scot_token_info(symbol, "reward_pool") precision = scot_token_info(symbol, "precision") author_curve_exponent = scot_token_config(symbol, "author_curve_exponent") # print ("get_vote_pct_for_token", token_voting_power, scot_staked, pending_rshares, reward_pool, author_curve_exponent, multiplier) def get_rshares_from_reward(reward): return pow(pending_rshares * reward / reward_pool, 1.0 / author_curve_exponent) if token_voting_power and scot_staked and pending_rshares and reward_pool and author_curve_exponent and multiplier: # calculation method # vote_value = vote_weight / 100 * voting_power / 100 * rshares / pending_rshares * reward_pool # reference: https://busy.org/@holger80/palnet-how-to-check-your-voting-power-and-your-pal-vote-value value = value * pow(10, precision) rshares = get_rshares_from_reward(value) # print ("reshares", rshares) vote_weight = 10000.0 * rshares / float( token_voting_power) / float(scot_staked / 100.0) / multiplier return vote_weight else: return None def set_vp_limit(self, token, limit): if token and limit: self.vp_limit[token] = limit def get_vp_limit(self, token): if token and token in self.vp_limit: return self.vp_limit[token] else: return 0 def has_vp(self, token=None, up=True): if token: vp = self.account.get_scot_voting_power(token, up) if vp: if float(vp) / 100 >= self.get_vp_limit(token): return True return False else: for k, v in self.vp_limit.items(): vp = self.account.get_scot_voting_power(k, up) if not vp or float(vp) / 100 < float(v): return False return True def estimate_vote_pct_for_n_votes(self, days, n): total_SBD = self.account.account.steem.sp_to_sbd( sp=self.account.steem_power()) * 10 * float(days) return float(self.account.account.get_vote_pct_for_SBD( total_SBD / n)) / 100
def __init__(self, account): self.account = SteemAccount(account) self.transfers = None self.se_wallet = Wallet(self.account.author)
def __init__(self): self.claimer_author = settings.get_env_var(PILOT_ACCOUNT_KEY) or DEFAULT_PILOT_ACCOUNT self.claimer_account = SteemAccount(author=self.claimer_author)