Posts Tagged ‘update


[Javascript/Php] Neopets Auction Bot Project (3)

The latest update to the auction bot.

The reason for it being private, is nothing to do with me being selfish or anything, but the fact that this script queries my MySQL database between 6-10 times a minute, and I dont want it to run too slowly. Ive posted everything required to set it up here, however, if you need help, feel free to contact me (Details: my contact details -> about)

Its almost fully automated now, refreshing, opening, closing pages correctly.
There are only a few things to sort out, but to the average user these problems aren’t noticeable (check the grease monkey var for the script after running it for a while -_-)

Source for the PHP remains the same, so check the other posts.
Below is the greasemonkey script:

// ==UserScript==
// @name           Aucti0n b0t - sim0n
// @namespace      Neopets
// @description
// @include*
// ==/UserScript==

function getElementsByAttribute(oElm, strTagName, strAttributeName, strAttributeValue){
	var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
	var arrReturnElements = new Array();
	var oAttributeValue = (typeof strAttributeValue != "undefined")? new RegExp("(^|\\s)" + strAttributeValue + "(\\s|$)") : null;
	var oCurrent;
	var oAttribute;
	for(var i=0; i<arrElements.length; i++){
		oCurrent = arrElements[i];
		oAttribute = oCurrent.getAttribute && oCurrent.getAttribute(strAttributeName);
		if(typeof oAttribute == "string" && oAttribute.length > 0){
			if(typeof strAttributeValue == "undefined" || (oAttributeValue && oAttributeValue.test(oAttribute))){
	return arrReturnElements;
function createErrorBox(docTitle, boxHeight, content, contentSize) {
	if(docTitle != "") { document.title = docTitle };
	var size = "100px;";
	if(boxHeight != '') { size = boxHeight + "px"; }
	var darkenScreen = document.createElement('div');
	darkenScreen.setAttribute('style', 'position:fixed;left:0;top:0;width:100%;height:100%;background:#000000;opacity:0.8');
	var errorBox = document.createElement('div');
	var left = (document.documentElement.clientWidth /2)-150;
	errorBox.setAttribute('style', 'width:300px; ' + size + ' border:#990000 thick solid; background:#CCCCCC;padding:6px;position:fixed;left:' + left + 'px;top:100px;');
	for(var i = 1; i<contentSize; i++) {
function closeWindow() {
	var errorTitle = document.createElement('span');
	errorTitle.setAttribute('style', 'font-family:Georgia; text-align:center; font-weight:bold;z-index:9999');
	var errorBold = document.createElement('b');
	var errorItalic = document.createElement('i');

	var elemArray = {
		1 : errorTitle,
		2 : document.createElement('br'),
		3 : errorBold,
		4 : document.createTextNode(' is false.'),
		5 : document.createElement('br'),
		6 : document.createTextNode('To enable it, navigate to about:config and change the value from False to True')

	createErrorBox('Close error - click for details', '', elemArray, 7);
function removeImages() {
	var images=document.images;
	for(var x=0;x<images.length;i++){
function parseUrl(max_price) {
	return String(document.location).substring(String(document.location).lastIndexOf("=")+1);
function removeBidCookie(link) {
	var curID = link.replace(/.*auction_id=(\d*).*/, "$1");
	var cur = String(GM_getValue('currentAuctions'));
	cur = cur.replace(curID + "|", "");
	GM_setValue('currentAuctions', cur);

//Main Page Functions
function queryNeopetItem(item, complete) {
	//Create a httpRequest, the php script returns a list of items max price + sell price
	//maxprice[0]	sellprice[0]
	//maxprice[1]	sellprice[1]
	//maxprice[n-1]	sellprice[n-1]
	//maxprice[n]	sellprice[n]
	//complete is a function that parses the responseText
	url = "" + item;
		method: "POST",
		url: url,
		onload: function(xhr) { complete(xhr.responseText); }
function comp(text) {
	//Splits each line
	var items = text.split("\n");
	//We only want 20 lines (20 items per page)
	for(var i = 0;i<20;i++) {
		if(items[i] == "" || String(items[i]) == "undefined") {
			//Item not in database
		} else {
			//Split max/min price
			var item = items[i].split("\t");
			//Get the items current price, check its less
			var cur_price = table[0].rows[i+1].cells[6].innerHTML.replace(/<b>(\d*)<\/b> NP/, "$1");
			if(Number(cur_price)<=Number(item[0])) {
				//If it is less, check if its a NF auction or not
				if(table[0].rows[i+1].cells[3].innerHTML.toLowerCase().indexOf("<b>[nf]</b>") != -1) {
					//If it is, ignore it
				} else {
					//Else, open the page in a new tab
					doAuction(table[0].rows[i+1].cells[2].getElementsByTagName('a')[0], item[0]);
			} else {
function doAuction(link, max_price) {
	//Used to open the selected auction in a new tab with max price in the url
	var curID = link.href.replace(/.*auction_id=(\d*)/, "$1");
	var cur = String(GM_getValue('currentAuctions'));
	if(cur=="undefined") {cur="";}
	if(cur.indexOf(curID) == -1) {
		var x = cur + curID + "|";
		GM_setValue('currentAuctions', x);
		GM_openInTab(link.href + "&maxprice=" + max_price);
		GM_log("Opened: " + curID);

//Script testing

var url = String(document.location);
if(url.indexOf('placebid') == -1 && url.indexOf('bids') == -1) {

	//The main auction page - Create list of items
	var table = getElementsByAttribute(document.body, "table", "align", "center");
	var queryString = "";
	for(var i=1;i<table[0].rows.length - 1;i++) {
		queryString = queryString + table[0].rows[i].cells[2].innerHTML.replace(/<a href=\".*\">(.*)<\/a>/, "$1") + "|";
	queryString = queryString + table[0].rows[table[0].rows.length-1].cells[2].innerHTML.replace(/<a href=\".*\">(.*)<\/a>/, "$1")
	//Query the database
	queryNeopetItem(queryString, comp);

	var minTime = 6;
	var maxTime = 10;
	var PERIOD = (maxTime * 1000 - minTime * 1000) * Math.random() + minTime * 1000;
	setTimeout('location.reload(true)', PERIOD);

} else if(url.indexOf('bids') != -1 && url.indexOf('maxprice') != -1) {

	//Place bid
	if ((window.find("Time Left in Auction :  Closed" , false, true) == false) && (window.find("Oops! - Invalid Auction ID") == false)) {
		//Valid auction
		var max_price = parseUrl();
		var name = getElementsByAttribute(document.getElementById('header'), 'td', 'class', 'user medText')[0].firstChild.nextSibling.textContent;
		var table = getElementsByAttribute(document.body, 'table', 'cellpadding', 4)[0];
		var lastbidder = "";
		if(table) {
			lastbidder = table.rows[1].cells[0].textContent.substring(1);
		if(lastbidder==name) {
			//If last bidder was user reload after 2 seconds
			setTimeout('location.reload(true)', 3);
		} else {
			//Else, check to make sure its worth paying for
			if(Number(document.getElementsByName('amount')[0].value) <= Number(max_price)) {
				//Modify the form to add our max price
				var forms = document.getElementsByTagName("form");
				for(var i=0;i<forms.length;i++) {
					if(forms[i].getAttribute('action') == "auctions.phtml?type=placebid") {
						forms[i].setAttribute('action', "auctions.phtml?type=placebid&maxprice=" + max_price)
				//Submit the form
				var button = getElementsByAttribute(document.body, 'input', 'value', 'Place a Bid')[0];
			} else {
				//too expensive */.
				GM_log("Closed: " + url);
	} else {
		// Will need to add in checking later on for who won the bid */.
		GM_log("Closed: " + url);
} else if(url.indexOf('placebid') != -1) {

	//After placing bid
	var max_price = parseUrl();
	if(document.body.innerHTML.indexOf("BID SUCCESSFUL") != -1) {
		//Bid worked
		var link = document.getElementsByTagName('a');
		var s = ''
		for(var i = 0; i < link.length; i++) {
			var str = link[i].href;
			str = str.substr(0, 59)
			if(str == s) { document.location = link[i].href + "&maxprice=" + max_price; }
	} else if(document.body.innerHTML.indexOf("The current asking price for this item") != -1) {
		//Bid not enough error
		var link = document.getElementsByTagName('a');
		var s = ''
		for(var i = 0; i < link.length; i++) {
			var str = link[i].href;
			str = str.substr(0, 59)
			if(str == s) { document.location = link[i].href + "&maxprice=" + max_price; }
	} else if(document.body.innerHTML.indexOf("You must wait a few more seconds") != -1) {
		//Too fast
	} else if(document.body.innerHTML.indexOf("You don't have enough money to place that bid") != -1 || document.body.innerHTML.indexOf("This auction is closed") != -1 || document.body.innerHTML.indexOf("Invalid Auction ID") != -1) {
		//Not enough money or auction is over */.


Theres also a clue in this post as to how you can easily access my host if you want, its kinda… obvious.

Remember, this isnt the final product. Its still being worked on.


[Note] Neopets Autobidder Progress

This is the current workup for the neopets auction bot:

Currently, i have all the complex coding done, just have to work out the last few bugs here and there, and then decide how to integrate the bot with an auto stocker (wether to pass the sell price from url to url, until it reaches the stock, or to just query again later on).

Main Auction Page
Create list of items to query
Send request to php
Return list of items maxprice & sell price
Parse list
Loop through each row
Check if item is in list
If it is, check if its a NF only auction
If its not, check to see if maxprice is less than the current price
If it is, check to see if the page is on the ignore list
If it isnt, open the page in a new tab with max price as an url paramater (possibly also sell price?)
Add opened page to ignore list (greasemonkey var?)
Wait between 7 and 15 seconds, refresh page

Bid Page
Parse max price from url
Get username from page
Check to see if the auction is over/invalid/too expensive
If it is, close the page
If it isnt, Check to see if the last bidder was the user
If it is, refresh the page
If it isnt,
modify the form to pass the maxprice in the url when submitted (possibly also sell price)
submit the bid

Bid Submission
Parse max price from url
Check if bid successful (find BID SUCCESSFUL)
If yes,
find link on page (loop through ‘a’ elements)
modify link to pass the maxprice in the url when submitted (possibly also sell price)
If no, check reason
If not enough money, close
If need to wait, history back
If bid twice in a row, back : (Sorry, you are not allowed to bid on an auction two times in a row)


[VB.Net] RandomString Generator II

An updated version of my random string generator.
This version is more versatile than the last, allowing for more flexibility in the output.

''' A function to generate random strings
''' The length of the returned string.
''' Define a custom set of characters that are possible to be chosen
''' Determines if the string should contain Alphabetical Characters. Default = True
''' Determines if the string should contain Numerical Characters. Default = True
''' Determines if the string should contain Symbols. Default = False
''' Determines if the string should contain Upper Case characters
''' Determines if the string should contain Lower Case characters
''' A random string of the desired length.
Private Function RandomString(ByVal StringLength As Integer, Optional ByVal CustomCharacters As String = "", Optional ByVal Letters As Boolean = True, Optional ByVal Numbers As Boolean = True, Optional ByVal Symbols As Boolean = False, Optional ByVal UpperCase As Boolean = True, Optional ByVal LowerCase As Boolean = True) As String
    Dim randomG As New Random
    Dim randomN As Integer
    Const pwNumbers As String = "0123456789"
    Const pwSymbols As String = "`¬!""£$%^&*()_)+-=[]{};':@#~/?.>,<|"""
    Dim str As String = ""
    While str.Length < StringLength
        Dim pwcharList As String = ""
        If Letters = True Then pwcharList &= pwChars
        If Numbers = True Then pwcharList &= pwNumbers
        If Symbols = True Then pwcharList &= pwSymbols
        pwcharList &= CustomCharacters
        randomN = randomG.Next(0, pwcharList.Length)
        If UpperCase = True And LowerCase = True Then
            Dim randomN2 = randomG.Next(0, 2)
            If randomN2 = 0 Then
                str &= Char.ToUpper(pwcharList(randomN), System.Globalization.CultureInfo.CurrentCulture)
                str &= Char.ToLower(pwcharList(randomN), System.Globalization.CultureInfo.CurrentCulture)
            End If
        ElseIf UpperCase = True Then
            str &= Char.ToUpper(pwcharList(randomN), System.Globalization.CultureInfo.CurrentCulture)
        ElseIf LowerCase = True Then
            str &= Char.ToLower(pwcharList(randomN), System.Globalization.CultureInfo.CurrentCulture)
            str &= pwcharList(randomN)
        End If
    End While
    Return str
End Function

As you can see, this version is slightly more complicated than the last, but as stated, it also allows for far more flexibility in the output strings.
Ill go over the function slightly:

Private Function RandomString( _
ByVal StringLength As Integer, _
    Optional ByVal CustomCharacters As String = "", _
    Optional ByVal Letters As Boolean = True, _
    Optional ByVal Numbers As Boolean = True, _
    Optional ByVal Symbols As Boolean = False, _
    Optional ByVal UpperCase As Boolean = True, _
    Optional ByVal LowerCase As Boolean = True) _
As String

The key thing to note about this version, is the introduction of the CustomCharacters paramater. This allows you to make random strings, but using your own predefined arrays of characters.

For example, if i was to use this:

Debug.WriteLine(RandomString(20, "", False, False, False))

It would output something like this:
As to make the string, it only uses characters from the CustomCharacters parameter.

So, what use is this?
It allows you to make “random strings” that, are more recognisable, for example, using:

Debug.WriteLine(RandomString(40, "simonsimonsimonsimonsimonsimon", False, False, False, True, True))

You would get:

Which could then be made more complex by allowing symbols, but also increasing the length of the CustomCharacters (So it is still more likley to pick on of the characters from ‘simon’):

Debug.WriteLine(RandomString(40, "simonsimonsimonsimonsimonsimonsimonsimonsimonsimonsimonsimon", False, False, True, True, True))

Would return: