// farmer.js
//
// data object representing an farmer
//
// Copyright 2013, StatusNet Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
var _ = require("underscore"),
async = require("async"),
uuid = require("node-uuid"),
DatabankObject = require("databank").DatabankObject,
OpenFarmGame = require("./openfarmgame"),
Host = require("./host"),
Plot = require("./plot");
var Farmer = DatabankObject.subClass("farmer");
Farmer.schema = {
"farmer": {
pkey: "id",
fields: ["name",
"coins",
"plots",
"token",
"secret",
"inbox",
"outbox",
"created",
"updated"]
},
"farmerlist": {
pkey: "id"
}
};
Farmer.fromPerson = function(person, token, secret, callback) {
var id = person.id,
farmer,
bank = Farmer.bank();
if (id.substr(0, 5) == "acct:") {
id = id.substr(5);
}
if (!person.links ||
!person.links["activity-inbox"] ||
!person.links["activity-inbox"].href) {
callback(new Error("No activity inbox."));
return;
}
if (!person.links ||
!person.links["activity-outbox"] ||
!person.links["activity-outbox"].href) {
callback(new Error("No activity inbox."));
return;
}
if (!person.followers ||
!person.followers.url) {
callback(new Error("No followers."));
return;
}
async.waterfall([
function(callback) {
Plot.create({owner: id}, callback);
},
function(plot, callback) {
Farmer.create({id: id,
name: person.displayName,
homepage: person.url,
coins: 25,
plots: [plot.uuid],
token: token,
secret: secret,
created: Date.now(),
updated: Date.now(),
inbox: person.links["activity-inbox"].href,
outbox: person.links["activity-outbox"].href,
followers: person.followers.url},
callback);
}
], callback);
};
// Keep a list of existing farmers so we can do periodic updates
Farmer.prototype.afterCreate = function(callback) {
var farmer = this,
bank = Farmer.bank();
bank.append("farmerlist", 0, farmer.id, function(err, list) {
if (err) {
callback(err);
} else {
callback(null);
}
});
};
// Deleted farmers come off the list
Farmer.prototype.afterDel = function(callback) {
var farmer = this;
async.parallel([
function(callback) {
var bank = Farmer.bank();
bank.remove("farmerlist", 0, farmer.id, callback);
},
function(callback) {
var bank = Plot.bank();
async.forEach(farmer.plots,
function(plotID, callback) {
bank.del("plot", plotID, callback);
},
callback);
}
], function(err, results) {
if (err) {
callback(err);
} else {
callback(null);
}
});
};
Farmer.prototype.joinActivity = function(callback) {
var farmer = this,
game = OpenFarmGame.asService(),
content = "" + farmer.name + " " +
" joined " +
"" + game.displayName + "";
farmer.postActivity({verb: "join",
content: content,
object: game},
callback);
};
Farmer.prototype.buyActivity = function(plot, callback) {
var farmer = this,
obj = plot.asObject(),
content = "" + farmer.name + " " +
" bought " +
"a new plot";
farmer.postActivity({verb: "purchase",
content: content,
object: obj},
callback);
};
Farmer.prototype.plantActivity = function(crop, callback) {
var farmer = this,
obj = crop.asObject(),
content = "" + farmer.name + " " +
" planted " +
"" + obj.displayName + "";
farmer.postActivity({verb: "http://openfarmgame.com/schema/verb/plant",
content: content,
object: obj},
callback);
};
Farmer.prototype.tearUpActivity = function(crop, callback) {
var farmer = this,
obj = crop.asObject(),
content = "" + farmer.name + " " +
" tore up a field of " +
obj.displayName;
farmer.postActivity({verb: "http://openfarmgame.com/schema/verb/tear-up",
content: content,
object: obj},
callback);
};
Farmer.prototype.waterActivity = function(crop, callback) {
var farmer = this,
obj = crop.asObject(),
content = "" + farmer.name + " " +
" watered " +
"" + obj.displayName + "";
farmer.postActivity({verb: "http://openfarmgame.com/schema/verb/water",
content: content,
object: obj},
callback);
};
Farmer.prototype.harvestActivity = function(crop, callback) {
var farmer = this,
obj = crop.asObject(),
content = "" + farmer.name + " " +
" harvested " +
"" + obj.displayName + "";
farmer.postActivity({verb: "http://openfarmgame.com/schema/verb/harvest",
content: content,
object: obj},
callback);
};
Farmer.getHostname = function(id) {
var parts = id.split("@"),
hostname = parts[1].toLowerCase();
return hostname;
};
Farmer.prototype.getHost = function(callback) {
var farmer = this,
hostname = Farmer.getHostname(farmer.id);
Host.get(hostname, callback);
};
Farmer.prototype.postActivity = function(act, callback) {
var farmer = this;
async.waterfall([
function(callback) {
farmer.getHost(callback);
},
function(host, callback) {
var oa = host.getOAuth(),
json = JSON.stringify(act);
oa.post(farmer.outbox, farmer.token, farmer.secret, json, "application/json", callback);
},
function(data, response, callback) {
var posted;
if (response.statusCode >= 400 && response.statusCode < 600) {
callback(new Error("Error " + response.StatusCode + ": " + data));
} else if (!response.headers ||
!response.headers["content-type"] ||
response.headers["content-type"].substr(0, "application/json".length) != "application/json") {
callback(new Error("Not application/json"));
} else {
try {
posted = JSON.parse(data);
callback(null, posted);
} catch (e) {
callback(e, null);
}
}
}
], callback);
};
module.exports = Farmer;