2 changed files with 263 additions and 2 deletions
@ -1,8 +1,45 @@ |
|||
## AlwaysWin-ntsmhf Bookmarklet |
|||
# AlwaysWin-ntsmhf Tampermonkey |
|||
|
|||
To load the Tampermonkey script: |
|||
* Install the [Tampermonkey Chrome Extension] (https://www.tampermonkey.net/) |
|||
* Click on the Extension and select **Create a new script...** |
|||
* Copy the contents of [tampermonkey.js](tampermonkey.js) into the editor and save the changes |
|||
* Modify the *countiesToWin[]* array to contain the countyId's you wish to win the bid on. |
|||
|
|||
## Wishlist / Todo |
|||
[] Bidcap for any row |
|||
[x] Save settings to local storage |
|||
[x] Retrieve settings from local storage |
|||
[x] Inject div |
|||
[] start/stop buttons |
|||
[x] How often should the status check be performed? |
|||
[x] randomize refresh value to avoid detection |
|||
[] show rowAction1 array //AlwaysWin |
|||
[] show rowAction2 array //AlwaysTie |
|||
[] show rowAction3 array //WatchTie |
|||
[] PriceChangeOverTime Chart |
|||
[] For each countyRow inject |
|||
[] "rowAction" dropdown with options: |
|||
0 - Ignore |
|||
1 - Ensure I am highest bidder |
|||
2 - Make sure I am Tied |
|||
3 - Only watch tied bid |
|||
[] save to analytics checkbox |
|||
[] county bidcap |
|||
[] Option to sell leads that don't fit your criteria but you can't return on the secondary market. |
|||
[] Store tie values for statistical analysis over time. |
|||
|
|||
|
|||
|
|||
# AlwaysWin-ntsmhf Bookmarklet - Original route (probably abandoning) |
|||
|
|||
Version: 0.1 |
|||
|
|||
To load the bookmark go to the [AlwaysWin-ntsmhf Bookmarklet site](https://info.qhrei.com/temp/alwayswin-ntsmhf/index.htm) |
|||
|
|||
Drag & drop the above link into your bookmarks to save it.</small> |
|||
Drag & drop the above link into your bookmarks to save it. |
|||
|
|||
Compiled JavaScript thanks to [Google's Closure Compiler](https://closure-compiler.appspot.com/home) |
|||
|
|||
|
|||
|
|||
|
@ -0,0 +1,224 @@ |
|||
// ==UserScript==
|
|||
// @name AlwaysWin -ntsmhf
|
|||
// @namespace http://tampermonkey.net/
|
|||
// @version 0.1
|
|||
// @description Make sure you are positioned where you want to be in the bidding for each county.
|
|||
// @author Steven Allen
|
|||
// @match https://leads.needtosellmyhousefast.com/app
|
|||
// @require https://code.jquery.com/jquery-3.7.1.min.js
|
|||
// @icon https://www.google.com/s2/favicons?sz=64&domain=needtosellmyhousefast.com
|
|||
// @grant none
|
|||
// ==/UserScript==
|
|||
|
|||
'use strict'; |
|||
//Load our settings
|
|||
//localStorage.removeItem('alwayswin_settings');
|
|||
|
|||
console.log("Loading settings"); |
|||
var alwaysWinSettingsString = localStorage.getItem('alwayswin_settings'); |
|||
//console.log(alwaysWinSettingsString);
|
|||
|
|||
if(alwaysWinSettingsString == null || alwaysWinSettingsString == undefined) { |
|||
const defaultSettings = {"isReloadEnabled":true, "minSecondsBetweenReloads": 60, "maxSecondsBetweenReloads":300}; |
|||
const defaultSettingsString = JSON.stringify(defaultSettings); |
|||
localStorage.setItem('alwayswin_settings',defaultSettingsString); |
|||
alwaysWinSettingsString = defaultSettingsString; |
|||
} |
|||
|
|||
var alwaysWinSettings = JSON.parse(alwaysWinSettingsString); |
|||
console.log(alwaysWinSettings); |
|||
|
|||
////////////
|
|||
// Div injection and auto reload functions
|
|||
////////////
|
|||
function getRandomNumberBetween(min, max) { |
|||
min = Number(min); |
|||
max = Number(max); |
|||
return Math.floor(Math.random() * (max - min) + min); |
|||
} |
|||
|
|||
function getCheckedValue() { |
|||
if(reloadIsEnabled()) { |
|||
return "checked"; |
|||
} |
|||
return; |
|||
} |
|||
|
|||
function addAlwaysWinStyle(css) { |
|||
var head, style; |
|||
head = document.getElementsByTagName('head')[0]; |
|||
if (!head) { return; } |
|||
style = document.createElement('style'); |
|||
style.type = 'text/css'; |
|||
style.innerHTML = css; |
|||
head.appendChild(style); |
|||
} |
|||
|
|||
function saveSettings() { |
|||
let isReloadEnabledValue = document.querySelector("[name='isReloadEnabled']").checked; |
|||
let minSecondsBetweenReloadsValue = document.querySelector("[name='minSecondsBetweenReloads']").value; |
|||
let maxSecondsBetweenReloadsValue = document.querySelector("[name='maxSecondsBetweenReloads']").value; |
|||
|
|||
const latestSettings = { |
|||
"isReloadEnabled": isReloadEnabledValue, |
|||
"minSecondsBetweenReloads": minSecondsBetweenReloadsValue, |
|||
"maxSecondsBetweenReloads": maxSecondsBetweenReloadsValue |
|||
}; |
|||
const latestSettingsString = JSON.stringify(latestSettings); |
|||
localStorage.setItem('alwayswin_settings',latestSettingsString); |
|||
|
|||
alwaysWinSettingsString = latestSettings; |
|||
|
|||
return latestSettings; |
|||
} |
|||
|
|||
function reload() { |
|||
console.log("Saving settings..."); |
|||
let alwaysWinSettings = saveSettings(); |
|||
|
|||
console.log("Its time to perform a reload."); |
|||
console.log("isEnabled: "+ alwaysWinSettings.isReloadEnabled); |
|||
console.log("secondsBetweenReloads:"+ alwaysWinSettings.minSecondsBetweenReloads +" - "+ alwaysWinSettings.maxSecondsBetweenReloads); |
|||
if(!reloadIsEnabled() ) { |
|||
console.log("Reload is not enabled"); |
|||
return; |
|||
} |
|||
console.log("Reload is enabled. Reloading..."); |
|||
location.reload(); |
|||
} |
|||
|
|||
function reloadIsEnabled(){ |
|||
var checkedValue = alwaysWinSettings.isReloadEnabled ?? false;// document.querySelector("[name='isReloadEnabled']").checked;
|
|||
if(checkedValue == true) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////////
|
|||
// Always win code to find and take the highest/tie bid
|
|||
////////////////////////////////////////////////////////////////////////////////////
|
|||
function getCountyInfo(countyId){ |
|||
//<tr><th><div class="form-group form-row ml-1 mb-0"><label class="switch"><input class="subscription-status" type="checkbox" data-subscription_id="84035" checked=""><span class="async-slider round active"></span></label>
|
|||
//<div class="ml-3"><label class="col-form-label"><a href="/app/subscription/84035">WASHINGTON, OR</a></label>
|
|||
//</div></div></th>
|
|||
//<td><div class="bid-controller input-group input-group-sm" data-subscription_id="84035" data-baseprice_default="75" data-base_price="75" data-top_bid="300" data-investor="24304">
|
|||
//<div class="input-group-prepend"><span class="input-group-text bid-status top-bid" data-bid_status=" Top Bid"> Top Bid</span>
|
|||
//<button class="btn btn-outline-primary bid-controller-btn bid-controller-btn--decrement" data-operation="decrement" type="button"><i class="icon ion-minus-round"></i></button></div>
|
|||
//<input class="bid-controller--bid" readonly="readonly" size="4" style="text-align: center" type="text" value="425" name="investor_bid">
|
|||
//<div class="input-group-append">
|
|||
//<button class="btn btn-outline-primary bid-controller-btn bid-controller-btn--increment" data-operation="increment" type="button"><i class="icon ion-plus-round"></i></button>
|
|||
//<button class="btn btn-primary btn-sm bid-controller-btn bid-controller-btn--save" type="button" data-operation="save" disabled="disabled">Save</button>
|
|||
//</div></div></td></tr>
|
|||
|
|||
var county = document.querySelector('[data-subscription_id="'+ countyId +'"].subscription-status') |
|||
let countyRow = county.closest("tr"); |
|||
let bidController = {}; |
|||
bidController.countyRow = countyRow; |
|||
|
|||
const bidIncriment = 25; //This is hard coded into site but could change later.
|
|||
let num_bid = Number(countyRow.querySelector('.bid-controller--bid').value); |
|||
let num_tieBid = Number(countyRow.querySelector('.bid-controller').dataset.top_bid); |
|||
let num_floorBid = num_tieBid - bidIncriment; |
|||
let num_winningBid = num_tieBid + bidIncriment; |
|||
let num_clicksToMinWin = 1; |
|||
let winGap = (num_tieBid - num_bid); |
|||
if(winGap < 1) { |
|||
num_clicksToMinWin = (winGap / bidIncriment) + 1; |
|||
} else if(winGap > 0) { |
|||
num_clicksToMinWin = (winGap + bidIncriment) / bidIncriment; |
|||
} |
|||
|
|||
bidController.isEnabled = county.checked; |
|||
bidController.id = county.dataset.subscription_id; |
|||
bidController.name = county.closest("div").getElementsByTagName('a')[0].innerText; |
|||
bidController.bid = num_bid; |
|||
bidController.tieBid = num_tieBid; |
|||
bidController.floorBid = num_floorBid; |
|||
bidController.winningBid = num_winningBid; |
|||
bidController.status = countyRow.querySelector(".bid-status").innerText;//.trim(); //countyRow.querySelector(".bid-status").dataset.bid_status;
|
|||
bidController.isWinning = (num_bid > num_tieBid); |
|||
bidController.isWinningByTooMuch = (num_bid > num_winningBid); |
|||
bidController.clicksToMinWin = num_clicksToMinWin; |
|||
bidController.btnSave = countyRow.querySelector('.bid-controller-btn--save'); |
|||
bidController.btnBidUp = countyRow.querySelector('.bid-controller-btn--increment'); |
|||
bidController.btnBidDown = countyRow.querySelector('.bid-controller-btn--decrement'); |
|||
return bidController; |
|||
} |
|||
|
|||
function winCounty(countyJson, saveChanges) { |
|||
let countyInfo = countyJson.id + " "+ countyJson.name; |
|||
//console.log(countyJson.isWinning +" = "+ countyJson.tieBid +" > "+ countyJson.bid);
|
|||
//console.log(countyJson.isWinningByTooMuch +" = "+ countyJson.bid +" > "+ countyJson.winningBid);
|
|||
//console.log("clicksToMinWin: "+ countyJson.clicksToMinWin);
|
|||
//console.log(countyJson);
|
|||
if(countyJson.clicksToMinWin == 0) { |
|||
//if we made it here no changes were needed to win by just the right amount
|
|||
//Nothing else to do to win optimally
|
|||
console.log(countyInfo +" is already winning by just the right amount"); |
|||
} else if(countyJson.clicksToMinWin > 0) { |
|||
console.log(countyInfo +" is currently loosing. Increasing bid now"); |
|||
for(var i = 0; i < countyJson.clicksToMinWin; i++) { |
|||
console.log("calling btnBidUp.click() for "+ countyInfo); |
|||
countyJson.btnBidUp.click(); |
|||
} |
|||
if(saveChanges) { |
|||
console.log("calling btnSave.click() for "+ countyInfo); |
|||
countyJson.btnSave.click(); |
|||
} |
|||
} else if (countyJson.clicksToMinWin < 0) { |
|||
console.log(countyInfo +" is winning by too much. Decreasing bid now"); |
|||
let clicksRemaining = Math.abs(countyJson.clicksToMinWin); |
|||
while(clicksRemaining > 0) { |
|||
console.log("calling btnBidDown.click() for "+ countyInfo); |
|||
countyJson.btnBidDown.click(); |
|||
clicksRemaining--; |
|||
} |
|||
if(saveChanges) { |
|||
console.log("calling btnSave.click() for "+ countyInfo); |
|||
countyJson.btnSave.click(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
jQuery(window).on('load',function() { |
|||
console.log("Page loaded at: "+ new Date()); |
|||
|
|||
let minSecondsBetweenReloads = alwaysWinSettings.minSecondsBetweenReloads ?? 30; |
|||
let maxSecondsBetweenReloads = alwaysWinSettings.maxSecondsBetweenReloads ?? 60; |
|||
let isReloadEnabled = alwaysWinSettings.isReloadEnabled ?? false; |
|||
|
|||
let secondsBetweenReloads = getRandomNumberBetween(minSecondsBetweenReloads, maxSecondsBetweenReloads); |
|||
console.log("Next reload should occur in "+ secondsBetweenReloads +" seconds"); |
|||
|
|||
//Inject our controls
|
|||
var newHTML = document.createElement ('div'); |
|||
newHTML.innerHTML = '<div id="alwaysWin-ntsmhf"><label for="isReloadEnabled">AlwaysWin:</label><input type="checkbox" name="isReloadEnabled" '+ getCheckedValue() +'/><br/><label for="minSecondsBetweenReloads">Reload Every</label>:<input id="minSecondsBetweenReloads" type="text" size="3" name="minSecondsBetweenReloads" value="'+minSecondsBetweenReloads+'" /> to <input id="maxSecondsBetweenReloads" type="text" size="3" name="maxSecondsBetweenReloads" value="'+maxSecondsBetweenReloads+'" /> seconds</div>'; |
|||
|
|||
addAlwaysWinStyle('#alwaysWin-ntsmhf { position: fixed; top: 0px; left: 0px; background-color: #DDDDDD; border-radius: 5px; padding:2px; box-shadow: 5px 5px 3px #777777;}'); |
|||
document.body.appendChild (newHTML); |
|||
|
|||
//// Now do the winning
|
|||
var countiesToWin = []; |
|||
countiesToWin.push("84035"); //washington, OR
|
|||
countiesToWin.push("87833"); //marion, OR
|
|||
//countiesToWin.push("84038"); //benton, OR
|
|||
//countiesToWin.push("84037"); //clackamas, OR
|
|||
|
|||
//var countiesToTie = [];
|
|||
//countiesToTie.push("84034"); //cascade, MT
|
|||
//countiesToTie.push("84038"); //benton, OR
|
|||
//countiesToTie.push("84037"); //clackamas, OR
|
|||
//tieCounty(getCountyInfo(countiesToTie[0].id);
|
|||
|
|||
let okToSaveChanges = true; |
|||
let countiesToWinCount = countiesToWin.length; |
|||
for(var i = 0; i < countiesToWinCount; i++) { |
|||
let currentEntity = getCountyInfo(countiesToWin[i]) |
|||
winCounty(currentEntity,okToSaveChanges); |
|||
} |
|||
|
|||
//Refresh the page when we are suposed to
|
|||
let interval = setInterval(reload, secondsBetweenReloads*1000); |
|||
|
|||
}); |
Loading…
Reference in new issue