|
/** |
|
* Schedule a function to run on the next tick |
|
* This is useful to wait for the DOM to render changes that have just been made |
|
* |
|
* @param {function} func |
|
*/ |
|
function setImmediate(func) { |
|
setTimeout(func, 0); |
|
} |
|
|
|
/** |
|
* Timeout as a promise |
|
* @param {int} time - time in milliseconds to wait |
|
* @return {Promise} |
|
*/ |
|
function timeout(time) { |
|
return new Promise(function(resolve, reject) { |
|
setTimeout(resolve, time) |
|
}); |
|
} |
|
|
|
/** |
|
* Return a promise that resolves once a function returns true |
|
* |
|
* @param {function() : bool} conditionFunc |
|
* @return {Promise} |
|
*/ |
|
function wait(conditionFunc) { |
|
return new Promise(function(resolve, reject) { |
|
var interval; |
|
interval = setInterval(function() { |
|
if (conditionFunc()) { |
|
clearInterval(interval); |
|
resolve(); |
|
} |
|
}, 100); |
|
}); |
|
} |
|
|
|
/** |
|
* Round a number to a specified number of decmial places |
|
* |
|
* Javascript's Math.round function doesn't support specifying decimal places |
|
* |
|
* @param {number} number |
|
* @param {int} decimalPlaces |
|
* @return {number} |
|
*/ |
|
function round(number, decimalPlaces) { |
|
var offset = Math.pow(10, decimalPlaces); |
|
return Math.round(number * offset) / offset; |
|
} |
|
|
|
/** |
|
* Calculate the average of the recent price history for the selected trading card |
|
* |
|
* @return {int} dollars |
|
*/ |
|
function calcAveragePrice() { |
|
// Use the last 100 data points displayed in the visible price history graph |
|
// This is equal to about five days most of the time |
|
var data = SellItemDialog.m_plotPriceHistory.data; |
|
var recent = data[0].slice(-100); |
|
|
|
var recentTotal = recent.reduce((sum, item) => { |
|
// item is an array in the form: [dateString, priceInDollars, number] |
|
return sum + item[1]; |
|
}, 0); |
|
|
|
return recentTotal / recent.length; |
|
} |
|
|
|
/** |
|
* Calculate the price to sell the current selection for |
|
* |
|
* @return {number} dollars |
|
*/ |
|
function calcSalePrice() { |
|
var avg = calcAveragePrice(); |
|
var price = round(avg * 0.9, 2); |
|
|
|
// Print the amount details in the console |
|
var name = document.getElementById('market_sell_dialog_item_name').innerText; |
|
console.log('Will list %s for %f (average is %f)', name, price, avg); |
|
|
|
return price; |
|
} |
|
|
|
/** |
|
* Perform all UI actions to sell the selected card |
|
* @return {Promise} - promise to be resolved once the sale operation is complete |
|
*/ |
|
function sellSelection() { |
|
return new Promise(function(resolve, reject) { |
|
// Trigger Steam's trade dialog to display for the selected card |
|
SellCurrentSelection(); |
|
|
|
wait(function() { |
|
// Wait for the price history graph to be rendered |
|
// At this point we know the trading dialog is completely ready to use |
|
return jQuery('#pricehistory:visible').length > 0; |
|
}).then(function() { |
|
// Calculate sale price using the graph data |
|
var price = calcSalePrice(); |
|
|
|
// Update the "buyer pays" field in the UI (converted to dollars, truncated to 2 dp) |
|
document.getElementById('market_sell_buyercurrency_input').value = price.toFixed(2); |
|
return timeout(50); |
|
}).then(function() { |
|
// Call their event handler to register the amount we're selling for in their code |
|
SellItemDialog.OnBuyerPriceInputKeyUp(); |
|
return timeout(50); |
|
}).then(function() { |
|
|
|
// Accept terms of sale |
|
document.getElementById('market_sell_dialog_accept_ssa').checked = true; |
|
SellItemDialog.OnAccept(new Event('click')); |
|
|
|
// Wait for the UI to update |
|
return timeout(50); |
|
}).then(function() { |
|
// Click the sell button |
|
document.getElementById('market_sell_dialog_accept').click(); |
|
|
|
// Wait for the final OK button to be visible |
|
return wait(function() { |
|
return jQuery('#market_sell_dialog_ok:visible').length > 0; |
|
}); |
|
}).then(function() { |
|
// Click the sell confirmation button |
|
document.getElementById('market_sell_dialog_ok').click(); |
|
resolve(); |
|
}); |
|
}); |
|
} |
|
|
|
function process(index, cards) { |
|
// Click the "Sell" button in the inventory to bring up the sell dialog for this item |
|
var node = cards[index]; |
|
node.click(); |
|
|
|
timeout(100) |
|
.then(function() { |
|
return sellSelection() |
|
}) |
|
.then(function() { |
|
// Once selection is sold, wait for the UI to return |
|
return wait(function() { |
|
return SellItemDialog.m_bWaitingOnServer === false |
|
&& jQuery('#inventories:visible').length > 0; |
|
}) |
|
}) |
|
.then(function() { |
|
// Process the next item |
|
if (cards[index + 1]) { |
|
process(index + 1, cards); |
|
} else { |
|
console.log('Done!'); |
|
} |
|
}); |
|
} |
|
|
|
function doHax() { |
|
// Get all of the links for trading cards rendered on the current page |
|
// (This may include cards that aren't visible in on the current 25-per-page view) |
|
cards = document.querySelectorAll('.inventory_item_link[href^="#753_6"]'); |
|
|
|
if (cards.length) { |
|
console.log('Starting to process %d cards', cards.length); |
|
process(0, cards); |
|
} else { |
|
console.log('No cards to process'); |
|
} |
|
} |
Hello. I can use this once and then an exception is raised. Can you fix that? Thanks sweetie.