Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- var sha1 = require("./sha1").hex;
- var http = require("http");
- var mysql = require('./mysql');
- var settings = require("./settings");
- if(Array.prototype.clear === undefined)
- Array.prototype.clear = function()
- {
- for(var i=this.length; i>=0; i--)
- delete this[i];
- this.length = 0;
- return this;
- }
- if(Array.prototype.contains === undefined)
- Array.prototype.contains = function(element)
- {
- return this.indexOf(element)!=-1;
- }
- if(Array.prototype.add === undefined)
- Array.prototype.add = function(element)
- {
- if(!this.contains(element))
- this.push(element);
- }
- if(Array.prototype.remove === undefined)
- Array.prototype.remove = function(value)
- {
- for(var i=0; i<this.length; i++)
- if(this[i] === value)
- this.splice(i--, 1);
- return this;
- }
- if(Array.prototype.clean === undefined)
- Array.prototype.clean = function()
- {
- for(var i=0; i<this.length; i++)
- if(this[i] === undefined
- || this[i] === null)
- this.splice(i--, 1);
- return this;
- }
- if(Array.prototype.clear === undefined)
- Array.prototype.clear = function()
- {
- for(var i=this.length; i>=0; i--)
- delete this[i];
- this.length = 0;
- return this;
- }
- function JSONResponse(database, request, response)
- {
- var self = this;
- this._user = undefined;
- this._database = database;
- this._request = request;
- this._response = response;
- this._JSONObject = {
- errors:[]
- };
- this._time = new Date();
- this._cookie = {};
- var rawcookie = request.headers.cookie
- ?request.headers.cookie.split(/;\s*/)
- :[];
- for(var i=0; i<rawcookie.length; i++)
- {
- rawcookie[i] = rawcookie[i].split("=");
- this._cookie[rawcookie[i][0]] = unescape(rawcookie[i][1]);
- }
- this._params = request.url.substr(1).split("/");
- console.log(this._params);
- response.writeHead(200,{"Content-Type": "application/json"});
- this.getTime = function()
- {
- return self._time;
- }
- this.getCookie = function(key)
- {
- return self._cookie[key];
- }
- /**
- * Get the currently logged in user. Calls the callback method with the user
- * that is logged in, or with NULL if there is no login.
- * @param cb The callback function.
- */
- this.validateLogin = function(cb)
- {
- if(this._user !== undefined)
- {
- cb(self._user);
- return;
- }
- if(!self.getCookie("login"))
- {
- self._user = null;
- cb(self._user);
- return;
- }
- var loginstr = self.getCookie("login").split(",");
- var userId = parseInt(loginstr[0]);
- var passHash = loginstr[1];
- self._database.getUser(userId, function(user)
- {
- user.checkPassword(passHash, function(isValid)
- {
- self._user = isValid?user:null;
- cb(self._user);
- });
- });
- }
- this.addError = function(message)
- {
- self._JSONObject.errors.push(message);
- }
- this.getParam = function(i)
- {
- return self._params[i];
- }
- this.getParams = function()
- {
- return self._params;
- }
- this.getUser = function()
- {
- return self._user;
- }
- this.set = function(key, value)
- {
- self._JSONObject[key] = value;
- }
- this.get = function(key)
- {
- return self._JSONObject[key];
- }
- this.end = function()
- {
- self._response.end(JSON.stringify(self._JSONObject));
- }
- }
- function Database(sqlClient)
- {
- var self = this;
- /** @var The MySQL Client connection. */
- this._sql = sqlClient;
- /** @var A cache with Product-objects. */
- this._products = {};
- /** @var A cache with User-objects. */
- this._users = {};
- /** @var A cache with Bid-objects. */
- this._bids = {};
- /** @var An array with on-bid-placed-event listeners. */
- this._onBidPlacedEventListeners = [];
- /**
- *
- */
- this._triggerOnBidPlacedEventListeners = function(bid)
- {
- for(var i=0; i<self._onBidPlacedEventListeners.length; i++)
- self._onBidPlacedEventListeners[i](bid);
- }
- /**
- * Add a on-bid-placed-event-listener. The function will be called everytime
- * a bid is placed on any product. The callback will be given a
- * Bid-object which the bid was placed on as a first parameter.
- * @param cb The event-listener.
- */
- this.addOnBidPlacedEventListener = function(cb)
- {
- self._onBidPlacedEventListeners.add(cb);
- }
- this.removeOnBidPlacedEventListener = function(cb)
- {
- self._onBidPlacedEventListeners.remove(cb);
- }
- /**
- * Get a product from this database. Calls a callback method with the
- * retrieved Product-object on completion, or with NULL if the Product
- * doesn't exist.
- * @param id The id of the product to get.
- * @param cb The callback.
- */
- this.getProduct = function(id, cb)
- {
- id = parseInt(id);
- if(self._products[id] !== undefined)
- {
- cb(self._products[id]);
- return;
- }
- self._sql.query("SELECT title, UNIX_TIMESTAMP(timeStart) as time "
- +"FROM products WHERE id = ? LIMIT 1",
- [id],
- function(err, results, fields)
- {
- if(err)
- throw err;
- self._products[id] = results.length == 0
- ?null
- :new Product(self, id,
- results[0].title,
- new Date(results[0].time*1000));
- if(self._products[id])
- self._products[id].addOnBidPlacedEventListener(
- self._triggerOnBidPlacedEventListeners);
- cb(self._products[id]);
- });
- }
- /**
- * Get a user from this database. Calls a callback method with the retrieved
- * User-object on completion, or with NULL if there is no user with that id.
- * @param id The id of the user.
- * @param cb The callback.
- */
- this.getUser = function(id, cb)
- {
- id = parseInt(id);
- if(self._users[id] !== undefined)
- {
- cb(self._users[id]);
- return;
- }
- self._sql.query("SELECT username FROM users WHERE id = ? LIMIT 1",
- [id],
- function(err, results, fields)
- {
- if(err)
- throw err;
- self._users[id] = results.length == 0
- ?null
- :new User(self, id, results[0].username);
- cb(self._users[id]);
- });
- }
- /**
- * Get a bid from this database. Calls a callback method with the retrieved
- * Bid-object on completion, or with NULL if there is no bid with that id.
- * @param id The id of the bid.
- * @param cb The callback.
- */
- this.getBid = function(id, cb)
- {
- id = parseInt(id);
- if(self._bids[id] !== undefined)
- {
- cb(self._bids[id]);
- return;
- }
- self._sql.query("SELECT id, product, centiTime, user "
- +"FROM bids WHERE id = ? LIMIT 1",
- [id],
- function(err, results, fields)
- {
- if(err)
- throw err;
- if(results.length == 0)
- {
- self._bids[id] = null;
- cb(self._bids[id]);
- return;
- }
- var bidUser = undefined;
- var bidProduct = undefined;
- var bidAdditionalDataCallback = function()
- {
- if(bidUser === undefined
- || bidProduct === undefined)
- return;
- var time = new Date( bidProduct.getStartTime().getTime()
- + results[0].centiTime*10);
- self._bids[id] = new Bid(self, id, bidProduct,
- new Date(time), bidUser);
- cb(self._bids[id]);
- }
- self.getUser(results[0].user, function(user)
- {
- bidUser = user;
- bidAdditionalDataCallback();
- });
- self.getProduct(results[0].product, function(product)
- {
- bidProduct = product;
- bidAdditionalDataCallback();
- });
- });
- }
- }
- function User(db, id, username)
- {
- var self = this;
- this._database = db;
- this._id = id;
- this._username = username;
- this.getId = function()
- {
- return self._id;
- }
- this.getUsername = function()
- {
- return self._username;
- }
- /**
- * Check a user's password. Calls a callback after checking is done. The
- * callback will be called with a boolean as a first parameter, containing
- * TRUE if the given passwordhash did match the password or FALSE otherwise.
- */
- this.checkPassword = function(passhash, cb)
- {
- this._database._sql.query("SELECT COUNT(1) FROM users "
- +"WHERE id = ? AND password = UNHEX(?) LIMIT 1",
- [this.getId(), passhash],
- function(err, results, fields)
- {
- if(err)
- throw err;
- cb(results.length > 0);
- });
- }
- }
- function Product(db, id, title, time)
- {
- var self = this;
- this._database = db;
- this._id = id;
- this._title = title;
- this._time = time;
- this._lastBid = null;
- this._secondLastBid = null;
- /** @var An array with on-bid-placed-event listeners. */
- this._onBidPlacedEventListeners = [];
- /**
- *
- */
- this._triggerOnBidPlacedEventListeners = function(bid)
- {
- for(var i=0; i<self._onBidPlacedEventListeners.length; i++)
- self._onBidPlacedEventListeners[i](bid);
- }
- /**
- * Add a on-bid-placed-event-listener. The function will be called everytime
- * a bid is placed on any product. The callback will be given a
- * Bid-object which the bid was placed on as a first parameter.
- * @param cb The event-listener.
- */
- this.addOnBidPlacedEventListener = function(cb)
- {
- self._onBidPlacedEventListeners.add(cb);
- }
- this.removeOnBidPlacedEventListener = function(cb)
- {
- self._onBidPlacedEventListeners.remove(cb);
- }
- /**
- * Get the id of this product.
- * @type Number
- * @return the id
- */
- this.getId = function()
- {
- return self._id;
- }
- this.getTitle = function()
- {
- return self._title;
- }
- /**
- * Get the time this Product will start.
- * @type Date
- * @return The time
- */
- this.getStartTime = function()
- {
- return self._time;
- }
- this.placeBid = function(time, user, cb)
- {
- var centiTime = (time.getTime() - self.getStartTime().getTime())/10;
- self._database._sql.query(
- "INSERT INTO bids (product, centiTime, user) VALUES(?,?,?)",
- [self.getId(), centiTime, user.getId()],
- function(err, results, fields)
- {
- if(err)
- throw err;
- db.getBid(results.insertId, function(bid)
- {
- self._triggerOnBidPlacedEventListeners(bid);
- cb(bid);
- });
- });
- }
- }
- function Bid(db, id, product, time, user)
- {
- var self = this;
- this._database = db;
- this._id = id;
- this._product = product;
- this._time = time;
- this._user = user;
- this.getId = function()
- {
- return self._id;
- }
- /**
- * Get the time this Bid was placed.
- * @type Date
- * @return The time
- */
- this.getTime = function()
- {
- return self._time;
- }
- this.getProduct = function()
- {
- return self._product;
- }
- this.getUser = function()
- {
- return self._user;
- }
- }
- function handleJSONResponse(response)
- {
- switch(response.getParam(0))
- {
- case "place-bid":
- var bidProduct = undefined;
- var bidUser = undefined;
- var productAndUserFetchedCallback = function()
- {
- if(bidProduct === undefined
- || bidUser === undefined)
- return;
- if(!bidUser||!bidProduct)
- {
- if(!bidUser)
- response.addError("Placing a bid requires a login.");
- if(!bidProduct)
- response.addError("Product does not exist.");
- response.end();
- return;
- }
- bidProduct.placeBid(response.getTime(), bidUser,
- function(bid)
- {
- response.set("bid", {
- id: bid.getId(),
- time: bid.getTime().getTime(),
- user: {
- id: bid.getUser().getId(),
- username: bid.getUser().getUsername()
- },
- product: {
- id: bid.getProduct().getId(),
- title: bid.getProduct().getTitle(),
- time: bid.getProduct().getStartTime().getTime()
- }
- });
- response.end();
- });
- }
- db.getProduct(response.getParam(1), function(product)
- {
- bidProduct = product;
- productAndUserFetchedCallback();
- });
- response.validateLogin(function(user)
- {
- bidUser = user;
- productAndUserFetchedCallback();
- });
- break;
- case "next-bid":
- db.addOnBidPlacedEventListener(function(bid)
- {
- response.set("bid", {
- id: bid.getId(),
- time: bid.getTime().getTime(),
- user: {
- id: bid.getUser().getId(),
- username: bid.getUser().getUsername()
- },
- product: {
- id: bid.getProduct().getId(),
- title: bid.getProduct().getTitle(),
- time: bid.getProduct().getStartTime().getTime()
- }
- });
- response.end();
- });
- break;
- case "product-info":
- db.getProduct(response.getParam(1), function(product)
- {
- response.set("product", {
- id: product.getId(),
- title: product.getTitle(),
- time: product.getStartTime().getTime()
- });
- response.end();
- });
- break;
- case "ping":
- response.end();
- break;
- default:
- response.addError("Unknown Command");
- response.end();
- }
- }
- var client = mysql.Client();
- client.host = settings.sqlHost;
- client.user = settings.sqlUser;
- client.password = settings.sqlPass;
- client.connect();
- client.useDatabase(settings.sqlDatabase);
- var db = new Database(client);
- http.createServer(function(request, response)
- {
- var jsonresponse = new JSONResponse(db, request, response);
- handleJSONResponse(jsonresponse);
- }).listen(settings.httpPort);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement