Skip to content

Commit

Permalink
Added new features
Browse files Browse the repository at this point in the history
- Ability to change vote weight / bid windows
- Blacklist
- Option to auto-refund invalid bids (with no-refund list)
- Disabled mode to refund all bids
  • Loading branch information
MattyIce committed Nov 30, 2017
1 parent 98d4f7c commit fc79074
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 16 deletions.
10 changes: 8 additions & 2 deletions README.md
@@ -1,24 +1,30 @@
# Post Promoter - Steem Bid-Based Voting Bot

## Installation
```
```
$ git clone https://github.com/MattyIce/postpromoter.git
```

## Configuration
Set the POSTING_KEY environment variable to the private posting key of the bot account:
Set the POSTING_KEY and ACTIVE_KEY environment variables to the private posting and active keys of the bot account. Active key is only required for refunds.
```
export POSTING_KEY=[posting_key]
export ACTIVE_KEY=[active_key]
```

Set the following options in config.json:
```
{
"disabled_mode": false, // Set this to true to refund all funds sent to the bot
"account": "yourbotaccount",
"min_bid": 0.1,
"max_bid": 999,
"batch_vote_weight": 100,
"max_post_age": 144, // In hours, 144 hours = 6 days
"allow_comments": true,
"blacklist": ["account1", "account2"], // List of blacklisted accounts
"refunds_enabled": true,
"no_refund": ["bittrex", "poloniex", "openledger", "blocktrades"], // Don't refund transactions from these accounts!
"promotion_content": "You got a {weight}% upvote from @postpromoter courtesy of @{sender}!" // Change this to whatever you want the bot to post as a comment when it votes, or leave it out or blank for no comment
}
```
Expand Down
5 changes: 5 additions & 0 deletions config.json
@@ -1,8 +1,13 @@
{
"disabled_mode": false,
"account": "postpromoter",
"min_bid": 0.1,
"max_bid": 999,
"batch_vote_weight": 100,
"max_post_age": 144,
"allow_comments": true,
"blacklist": ["account1", "account2"],
"refunds_enabled": true,
"no_refund": ["bittrex", "poloniex", "openledger", "blocktrades"],
"promotion_content": "You got a {weight}% upvote from @postpromoter courtesy of @{sender}!"
}
59 changes: 45 additions & 14 deletions postpromoter.js
Expand Up @@ -8,6 +8,7 @@ var outstanding_bids = [];
var config = null;
var start_time = new Date();
var posting_key = process.env.POSTING_KEY;
var active_key = process.env.ACTIVE_KEY;

steem.api.setOptions({ url: 'https://api.steemit.com' });

Expand All @@ -16,8 +17,6 @@ console.log("\n *START* \n");
startProcess();

function startProcess() {
//console.log("Begin Processing...");

// Load the settings from the config file each time so we can pick up any changes
config = JSON.parse(fs.readFileSync("config.json"));

Expand All @@ -41,7 +40,6 @@ function startProcess() {
}
}

//console.log("End Processing...");
setTimeout(startProcess, 5000);
}

Expand All @@ -52,7 +50,7 @@ function startVoting(bids) {

for(var i = 0; i < bids.length; i++) {
// Calculate the vote weight to be used for each bid based on the amount bid as a percentage of the total bids
bids[i].weight = Math.round(10000 * (bids[i].amount / total));
bids[i].weight = Math.round(config.batch_vote_weight * 100 * (bids[i].amount / total));
}

vote(bids);
Expand Down Expand Up @@ -86,7 +84,7 @@ function vote(bids) {

// If there are more bids, vote on the next one after 20 seconds
if(bids.length > 0)
setTimeout(function() { vote(bids); }, 20000);
setTimeout(function() { vote(bids); }, 30000);
}

function getTransactions() {
Expand All @@ -99,20 +97,27 @@ function getTransactions() {
if(ts > start_time && trans[0] > last_trans) {

// We only care about SBD transfers to the bot
if (op[0] == 'transfer' && op[1].to == account.name && op[1].amount.indexOf('SBD') > 0) {
var amount = parseFloat(op[1].amount.replace(" SBD", ""));
console.log("\nIncoming Bid! From: " + op[1].from + ", Amount: " + amount + " SBD, memo: " + op[1].memo);
if (op[0] == 'transfer' && op[1].to == account.name) {
var amount = parseFloat(op[1].amount);
var currency = utils.getCurrency(op[1].amount);
console.log("\nIncoming Bid! From: " + op[1].from + ", Amount: " + op[1].amount + ", memo: " + op[1].memo);

// Check for min and max bid values in configuration settings
var min_bid = config.min_bid ? parseFloat(config.min_bid) : 0;
var max_bid = config.max_bid ? parseFloat(config.max_bid) : 9999;

if(amount < min_bid) {
if(config.disabled_mode) {
// Bot is disabled, refund all Bids
refund(op[1].from, amount, currency, 'Bot is disabled!');
} else if(amount < min_bid) {
// Bid amount is too low
console.log('Invalid Bid - ' + amount + ' is less than min bid amount of ' + parseFloat(config.min_bid));
refund(op[1].from, amount, currency, 'Min bid amount is ' + config.min_bid);
} else if (amount > max_bid) {
// Bid amount is too high
console.log('Invalid Bid - ' + amount + ' is greater than max bid amount of ' + parseFloat(config.max_bid));
refund(op[1].from, amount, currency, 'Max bid amount is ' + config.max_bid);
} else if(currency != 'SBD') {
// Sent STEEM instead of SBD
refund(op[1].from, amount, currency, 'Only SBD bids accepted!');
} else {
// Bid amount is just right!
checkPost(op[1].memo, amount, op[1].from);
Expand All @@ -131,27 +136,36 @@ function checkPost(memo, amount, sender) {
var permLink = memo.substr(memo.lastIndexOf('/') + 1);
var author = memo.substring(memo.lastIndexOf('@') + 1, memo.lastIndexOf('/'));

// Make sure the author isn't on the blacklist!
if(config.blacklist && config.blacklist.indexOf(author) >= 0)
{
console.log('Invalid Bid - @' + author + ' is on the blacklist!');
return;
}

steem.api.getContent(author, permLink, function (err, result) {
if (!err && result && result.id > 0) {

// If comments are not allowed then we need to first check if the post is a comment
if(!config.allow_comments && (result.parent_author != null && result.parent_author != '')) {
console.log('Invalid Post - Comments not allowed!')
refund(sender, amount, 'SBD', 'Bids not allowed on comments.');
return;
}

var created = new Date(result.created + 'Z');

// Get the list of votes on this post to make sure the bot didn't already vote on it (you'd be surprised how often people double-submit!)
var votes = result.active_votes.filter(function(vote) { return vote.voter == account.name; });
var already_voted = votes.length > 0 && (new Date() - new Date(votes[0].time + 'Z') > 20 * 60 * 1000);

if(already_voted || (new Date() - created) >= (config.max_post_age * 60 * 60 * 1000)) {
// This post is already voted on by this bot or the post is too old to be voted on
console.log('Invalid Post - ' + (already_voted ? 'Already Voted' : 'Post older than max age'));
refund(sender, amount, 'SBD', (already_voted ? 'Already Voted' : 'Post older than max age'));
return;
}
} else {
// Invalid memo
console.log('Invalid Post - Invalid Memo');
refund(sender, amount, 'SBD', 'Invalid Memo');
return;
}

Expand All @@ -160,3 +174,20 @@ function checkPost(memo, amount, sender) {
outstanding_bids.push({ amount: amount, sender: sender, post: result });
});
}

function refund(sender, amount, currency, reason) {
// Make sure refunds are enabled and the sender isn't on the no-refund list (for exchanges and things like that).
if(!config.refunds_enabled || (config.no_refund && config.no_refund.indexOf(sender) >= 0)) {
console.log("Invalid bid - " + reason + ' NO REFUND');
return;
}

// Issue the refund.
steem.broadcast.transfer(active_key, config.account, sender, utils.format(amount, 3) + ' ' + currency, 'Refund for invalid bid - ' + reason, function(err, response) {
if(err)
console.log(err, response);
else {
console.log('Refund of ' + amount + ' ' + currency + ' sent to @' + sender + ' for reason: ' + reason);
}
});
}
5 changes: 5 additions & 0 deletions utils.js
Expand Up @@ -91,6 +91,10 @@ function timeTilFullPower(account){
return effective_vesting_shares;
}

function getCurrency(amount) {
return amount.substr(amount.indexOf(' ') + 1);
}

function format(n, c, d, t) {
var c = isNaN(c = Math.abs(c)) ? 2 : c,
d = d == undefined ? "." : d,
Expand All @@ -106,5 +110,6 @@ function format(n, c, d, t) {
getVoteValue: getVoteValue,
timeTilFullPower: timeTilFullPower,
getVestingShares: getVestingShares,
getCurrency: getCurrency,
format: format
}

0 comments on commit fc79074

Please sign in to comment.