Browse files

lots of features and style changes!

  • Loading branch information...
1 parent fff42e2 commit 73d7686b41df77206f82cace06393b8f6f25029d @zackster committed Apr 7, 2012
Showing with 359 additions and 248 deletions.
  1. +14 −16 TODO
  2. +47 −33 app.js
  3. +19 −41 authentication/auth-server.js
  4. +28 −1 feedback/feedback-server.js
  5. +45 −13 log.js
  6. +55 −21 rooms/models.js
  7. +21 −14 scripts/email_listeners.js
  8. +12 −18 static/chat-init.js
  9. +17 −25 static/chat.js
  10. +29 −32 static/comm.js
  11. +17 −1 static/css/style.css
  12. +10 −2 users/models.js
  13. +6 −0 utils.js
  14. +16 −28 views/chat.jade
  15. +1 −1 views/index.jade
  16. +22 −2 views/privacy-policy.jade
View
30 TODO
@@ -1,25 +1,26 @@
-5) Email for listeners letting them know their rank and top15 status
-7) Ask Treya ETA on training modules
-8) Checkbox: let my venter see my forums username (on by default)
-9) Put points and leaderboard on right side of chat (ajaxy)
-11 Measure waiting times - poll every 5 seconds. ( User ID, Venter / Listener, Queue position, Start Time, Now )
-12 outline privacy policy as per forum thread
+abuse mod tool
+19 Don't auto reconnect - if you are a listener and your venter leaves.
+20 make sure to hook up feedback to logged conversations so i can analyze
+5) Implement utils/emailer with pony or node_mailer, and templates. https://github.com/substack/node-pony
+ http://blog.nodejitsu.com/sending-emails-in-node
+
+If listeners aren't logged in, say "You can create an account here! and then come back to log in when youre done. will open in new window"
+ make sure experience works smoothly, including the IP address checking (for neg ratings)
+Ask listeners to fill out an explanation for why they rated the person good
+
+
+
13 show scrolling "TIP" bar linking to suicide threads, suicide hotline number, etc.
14 Chat expands to fill browser
-16 don't show location if they are far away
-17 make app validate in http://validator.w3.org/check# for html5
-18 use sprites to reduce resources
-19 Don't auto reconnect - if you are a listener and your venter leaves.
-
+
+
- make authServer and feedbackServer into singletons
- let user save conversation to PDF
- neg feedback responsivity?
- bans? reprimands? encouragement to learn?
-<<<<<<< HEAD
-
- anthony, incentives for top listeners - creditcovers for top listeners? t shirts if they make a forum post explaining their listening
@@ -29,7 +30,4 @@
- sneakpeeq credit for top listeners
- Implement selenium and saucelabs for CompassionPit
3) 301 redirect on /forum and /forums and /forums/
-4) automatically award listeners credit if they have been talking for >10 minutes and have not been awarded negative feedback
-10 Copyright date
=======
->>>>>>> 3f7033ef04109d2536935d5cc6b826932f3d716e
View
80 app.js
@@ -2,11 +2,14 @@
/*global setInterval: false */
//just for debugging -- looking for errors that would trigger disconnects, and any other problems
//todo - modify log.js to insert this into the database .
+
+var util = require("util");
+
process.on('uncaughtException',
function(err) {
- console.log("We found an uncaught exception.");
- console.log(err);
- console.log(err.stack);
+ util.puts("We found an uncaught exception.");
+ util.puts(err);
+ util.puts(err.stack);
});
(function() {
@@ -69,15 +72,12 @@ function(err) {
app.get("/",
function(req, res, next) {
- console.log(req.query);
- console.log(req.cookies);
var opts = {
loggedOut: false,
roomCounts: getRoomCounts()
// TODO: make sure this is cached in memory
};
if (req.query && req.query.logout === 'true') {
- console.log("Xxx");
opts.loggedOut = true;
}
res.render('index', opts);
@@ -137,31 +137,39 @@ function(err) {
app.get("/vent",
function(req, res) {
res.render("chat", {
- type: "venter"
+ type: "venter",
+ layout: 'layout'
});
});
app.get("/listen",
function(req, res) {
if ((process.env.NODE_ENV || "development") === 'development') {
res.render("chat", {
- type: "listener"
+ type: "listener",
+ layout: 'layout'
});
}
else {
authServer.checkLogin(req,
function(username) {
if (username) {
vB_dao.getEmailAndJoindateForUser(username, function(vB_info) {
- console.log(vB_info);
res.render("chat", {
type: "listener",
+ layout: 'layout',
email: vB_info.email,
created_at: vB_info.created_at,
show_intercom: true
});
});
- } else {
+ } else if(feedbackServer.ipAddressHasNeverReceivedNegativeFeedback(req.headers['x-forwarded-for'] || req.address.address)) {
+ res.render("chat", {
+ layout: 'layout',
+ type: "listener",
+ show_intercom: false
+ });
+ } else {
res.render("listener-registration");
}
});
@@ -266,11 +274,11 @@ function(err) {
socket.set('authorization',
function(handshakeData, callback) {
- console.log('calling authorization inside socketio');
- console.log(handshakeData);
- console.log(callback);
- console.log("Do we have client info?");
- console.log(this.client);
+ // console.log('calling authorization inside socketio');
+ // console.log(handshakeData);
+ // console.log(callback);
+ // console.log("Do we have client info?");
+ // console.log(this.client);
/// cookies = handshakeData.headers.cookie
var headers = handshakeData.headers;
@@ -327,10 +335,10 @@ function(err) {
});
}
} else {
- console.log("Received message with unknown handler: " + data.t);
+ throw new Error("Received message with unknown handler: " + data.t);
}
} else {
- console.log("Received improper message", JSON.stringify(data));
+ throw new Error("Received improper message", JSON.stringify(data));
}
}));
@@ -447,41 +455,46 @@ function(err) {
* Request the current position the client is in the queue for
*/
socketHandlers.queue = function(client, user, _, callback) {
- callback(Room.getQueuePosition(user.id));
+
+ var queue_info = Room.getQueuePosition(user.id);
+ log.logWaitTime({
+ userid: user.id,
+ user_type: queue_info.user_type,
+ queuePosition: queue_info.queue_position,
+ join_time: user.join_time,
+ current_time: new Date().getTime()
+ });
+
+ callback(queue_info.queue_position);
};
socketHandlers.authenticateUser = function(client, user, data, callback) {
authServer.login(user.id, data.username, data.password,
function(success) {
- if (success) {
- console.log("Login success!");
+ if (success) {
feedbackServer.creditFeedback({
id: user.id,
username: data.username
});
callback(true);
}
else {
- console.log("Login failed!");
callback(false);
}
});
};
socketHandlers.updateHUD = function(client, user, data, callback) {
- console.log(client);
- console.log('------------------------------------------------');
- console.log(user);
- console.log(data);
- console.log(callback);
+ // console.log(client);
+ // console.log('------------------------------------------------');
+ // console.log(user);
+ // console.log(data);
+ // console.log(callback);
var listenerId = user.id;
- console.log('update HUD ...');
feedbackServer.getLeaderboardForUser(listenerId,
function(info) {
- console.log('got the info.....');
- console.log(callback.toString());
callback(info);
});
@@ -497,20 +510,22 @@ function(err) {
}
var listenerId = room.conversation.listener.userId;
+ console.log('Adding feedback...');
feedbackServer.addFeedback({
venter: venterId,
listener: listenerId,
direction: data.direction
});
+ console.log('Sending acknowledgement....');
+ console.log('sending to: ', listenerId);
room.sendToUser(listenerId, "received-feedback", data.direction);
};
/**
* Request to join a channel based on the provided type
*/
socketHandlers.join = function(client, user, data, callback) {
- console.log('join request');
var type = data.type;
if (type !== "venter") {
type = "listener";
@@ -574,7 +589,6 @@ function(err) {
};
socketHandlers.counts = function(client, user, _, callback) {
- console.log("Calling back with getRoomCounts");
callback(getRoomCounts());
};
@@ -593,9 +607,9 @@ function(err) {
cssHash: cssHash
});
- console.log("Registering app routes");
+ util.puts("Registering app routes");
registerAppRoutes(app);
- console.log("Registering Socket.IO");
+ util.puts("Registering Socket.IO");
registerSocketIO(app);
app.listen(config.port);
View
60 authentication/auth-server.js
@@ -20,25 +20,33 @@
Server.prototype.userInfo = function(id, callback) {
var client = this.getMySQLClient();
- client.query("SELECT * FROM user WHERE userid = ? LIMIT 1", [id], function selectCb(err, results, fields) {
+ client.query("SELECT * FROM user WHERE userid = ? LIMIT 1", [id], function (err, results, fields) {
if(err) {
throw err;
}
- callback.call(null, results[0]);
+ callback(results[0]);
+ client.end();
+ });
+ };
+
+ Server.prototype.getEmailAddressFromUsername = function(username, callback) {
+ var client = this.getMySQLClient();
+ client.query("SELECT email FROM user WHERE username = ? LIMIT 1", [username], function (err, results, fields) {
+ if(err) {
+ throw err;
+ }
+ callback(results[0].email);
client.end();
});
};
Server.prototype.markLoggedIn = function(user, callback) {
var self = this;
- // console.log("user", user);
this.userInfo(user, function(uinfo) {
- // console.log("Mark logged in being callled");
- // console.log("Uinfo", uinfo);
var client = self.getMySQLClient();
var epoch_in_seconds = Date.now() / 1000; // vBulletin stores epoch in seconds, Date.now() returns a value in ms
- client.query("UPDATE user SET lastactivity = ? WHERE userid = ? LIMIT 1", [epoch_in_seconds, user], function updateCb(err, results, fields) {
+ client.query("UPDATE user SET lastactivity = ? WHERE userid = ? LIMIT 1", [epoch_in_seconds, user], function (err, results, fields) {
if(err) {
throw err;
}
@@ -58,23 +66,15 @@
var self = this; // Server context
this.getCookie(req.cookies.bb_userid, req.cookies.bb_password, function(user) {
- // console.log("Get cookie calling back with user, ", user);
if(user) {
self.markLoggedIn(req.cookies.bb_userid, function(username) {
callback.call(self, username);
});
}
else {
- // console.log("We are invokign self.getSession");
- // console.log(req.cookies);
- // console.log(req);
-
+
self.getSession(req, req.cookies.bb_sessionhash, function(user) {
- console.log('call back of getSession');
- // console.log(user);
if(user) {
- // console.log("WRECK");
- // console.log(req);
self.markLoggedIn(user, function(username) {
callback.call(self, username);
});
@@ -92,7 +92,7 @@
var self = this;
var client = this.getMySQLClient();
- client.query("SELECT * FROM user WHERE userid = ? LIMIT 1", [id], function selectCb(err, results, fields) {
+ client.query("SELECT * FROM user WHERE userid = ? LIMIT 1", [id], function (err, results, fields) {
if(err) {
throw err;
}
@@ -111,8 +111,6 @@
client.end();
});
-
-
};
Server.prototype.getSession = function(req, hash, callback) {
@@ -125,27 +123,17 @@
else {
ip_address = req.headers['x-forwarded-for'] || req.address.address;
}
-
+
var user_agent = req.headers['user-agent'];
var self = this;
var ip = ip_address.split('.').slice(0, 3).join('.');
var newidhash = hashlib.md5(user_agent + ip);
- // console.log("user agent", user_agent);
- // console.log("ip addr", ip_address);
- // console.log("ip", ip);
- // console.log("new id hash", newidhash);
var client = this.getMySQLClient();
- client.query("SELECT * FROM session WHERE sessionhash = ? LIMIT 1", [hash], function selectCb(err, results, fields) {
-
- // console.log("callback from getSession SQL ...");
- // console.log("We searched on the hash,", hash);
- // console.log("---cookies---");
- // console.log(req.cookies);
- // console.log(err, results);
+ client.query("SELECT * FROM session WHERE sessionhash = ? LIMIT 1", [hash], function (err, results, fields) {
if(err) {
throw err;
@@ -171,37 +159,27 @@
Server.prototype.getUsernameFromListenerId = function(listener_id) {
- // console.log("Looking up listener id: %s", listener_id);
- // console.log("Returning: %s", this.logged_in_users[listener_id]);
return this.logged_in_users[listener_id];
};
Server.prototype.login = function (id, username, password, callback) {
- console.log('login called...');
var client = this.getMySQLClient();
client.query('USE '+config.vBulletin.database);
var self = this;
client.query(
- 'SELECT username, password, salt FROM user WHERE username=?', [username], function selectCb(err, results, fields) {
- console.log('ending client');
+ 'SELECT username, password, salt FROM user WHERE username=?', [username], function (err, results, fields) {
client.end();
- console.log("err: %s\nresults: %s\nfields: %s\n", err, results, fields);
if (err) {
throw err;
}
if(!results.length) {
- console.log("Returning false bc no users with that username.");
callback(false);
}
if(results[0].password === hashlib.md5(hashlib.md5(password)+results[0].salt)) {
- console.log("Returning true!");
- console.log(self.logged_in_users);
self.logged_in_users[id] = username;
- console.log(self.logged_in_users);
callback(true);
}
else {
- console.log("Returning false: wrong pw.");
callback(false);
}
client.end();
View
29 feedback/feedback-server.js
@@ -19,7 +19,10 @@
direction: {
type: String,
validate: [function(str) { return (str === 'positive' || str === 'negative'); }]
- }
+ },
+ ipAddress: {
+ type: String
+ } // later we can add in a validate: function, to ensure it's a proper ip address.
}));
@@ -43,6 +46,7 @@
var venter_ip = User.getById(feedback.venter).getIPAddress();
var listener_ip = User.getById(feedback.listener).getIPAddress();
+ instance.ipAddress = listener_ip;
if(venter_ip === listener_ip) {
console.log("We aren't adding feedback since both listener and venter share an IP address.");
@@ -146,6 +150,7 @@
this.getLeaderboardForUser = function(loggedInUser, cb) {
// console.log("glfu");
var scores = self.listenerScores;
+ // console.log("scores,", scores);
var user_scores = [];
_.each(scores, function(score, username, list) {
@@ -183,6 +188,7 @@
break;
}
}
+ // console.log('calling callback');
cb.call(null, {
rank: user_position,
score: logged_in_user_score,
@@ -191,6 +197,7 @@
return;
}
else {
+ // console.log('calling callback');
cb.call(null, {
rank: 'Not On Leaderboard',
score: 'No Score',
@@ -226,6 +233,26 @@
};
+ this.ipAddressHasNeverReceivedNegativeFeedback = function(ip_address, callback) {
+ Feedback.count({
+ ipAddress: ip_address,
+ direction: 'negative'
+ },
+ function(err, docs) {
+ if (err) {
+ console.log("error! " + err);
+ return;
+ }
+ if(docs==0) {
+ callback(true);
+ }
+ else {
+ callback(false);
+ }
+ });
+ };
+
+
};
View
58 log.js
@@ -1,14 +1,14 @@
(function () {
"use strict";
-
+
/*global console: false*/
-
+
var config = require('./config');
-
+
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
- ObjectId = Schema.ObjectId;
-
+ ObjectId = Schema.ObjectId;
+
// TODO: write some merging app that will merge the LogEntries
/**
* Represents a single LogEntry that will be stored in MongoDB
@@ -20,7 +20,19 @@
count: { type: Number, default: 1 }
}));
var LogEntry = exports.LogEntry = mongoose.model('LogEntry');
-
+
+
+
+ mongoose.model('WaitTime', new Schema({
+ userid: { type: String },
+ userType: { type: String },
+ queuePosition: { type: Number },
+ joinTime: { type: Number },
+ currentTime: { type: Number, default: new Date().getTime() }
+ }));
+ var WaitTime = exports.WaitTime = mongoose.model('WaitTime');
+
+
/**
* Represents a single ClientError that will be stored in MongoDB
*/
@@ -33,10 +45,10 @@
time: { type: Date, default: Date.now }
}));
var ClientError = exports.ClientError = mongoose.model('ClientError');
-
+
var logEntries = {};
var logCounts = {};
-
+
/**
* Generate a function that will handle logging for specific severity
*/
@@ -57,7 +69,7 @@
}
};
};
-
+
exports.info = makeLogFunction("info");
exports.warn = makeLogFunction("warn");
exports.error = makeLogFunction("error");
@@ -83,15 +95,35 @@
}
});
};
-
+
+ exports.logWaitTime = function(waiter_info) {
+ var wait_time = new WaitTime( {
+ userId: waiter_info.userid,
+ userType: waiter_info.user_type,
+ queuePosition: waiter_info.queue_position,
+ joinTime: waiter_info.join_time,
+ currentTime: waiter_info.current_time
+ });
+ wait_time.save(function(err) {
+ if(err) {
+ exports.error({
+ event: "Cannot save WaitTime",
+ error: err.toString()
+ });
+ }
+ })
+ };
+
+
+
/**
* Add URL actions to an express app
*/
exports.addActions = function (app) {
app.get("/logs", function (req, res) {
res.render('logs', { logTypes: Object.keys(logEntries) });
});
-
+
app.get("/logs.json", function (req, res) {
var roomData = require('./rooms/models').Room.dumpData();
var result = {
@@ -110,7 +142,7 @@
res.end(JSON.stringify(result));
});
});
-
+
app.post("/log-error", function (req, res) {
var error = new ClientError({
message: req.body.errorMsg,
@@ -131,7 +163,7 @@
res.send("");
});
};
-
+
exports.info({
event: "Server started"
});
View
76 rooms/models.js
@@ -495,8 +495,10 @@
var index = venterQueue.indexOf(userId);
var queue;
var otherQueue;
+ var user_type;
if (index !== -1) {
// venter
+ user_type = 'venter';
queue = venterQueue;
otherQueue = listenerQueue;
} else {
@@ -505,6 +507,7 @@
return -1;
}
// listener
+ user_type = 'listener';
queue = listenerQueue;
otherQueue = venterQueue;
}
@@ -534,7 +537,7 @@
index = 0;
}
- return index;
+ return {queue_position: index, user_type: user_type};
};
/**
@@ -669,6 +672,10 @@
message.d = Array.prototype.slice.call(arguments, 2);
}
}
+
+ // console.log('we will be sending a message of type: %s to userId: %s', type, userId);
+ // console.log('the message is:', message);
+ // console.log('the user <object> is:', user);
user.send(message);
};
@@ -738,12 +745,34 @@
Room.prototype.lookupUserGeoIP = function (userId, callback) {
var user = User.getById(userId);
- if (!user || this.users[userId] !== "listener") {
+ if (!user) { //was: if (!user || this.users[userId] !== "listener") {
callback(null);
} else {
user.lookupGeoIP(callback);
}
- };
+ }
+
+ // takes in: two user IDs
+ // calls back with: geoInfo if users are from same country; otherwise, null
+ Room.prototype.areUsersFromSameCountry = function(userId, otherUserId, callback) {
+ var self = this;
+ self.lookupUserGeoIP(userId, function (geoInfo) {
+ if(geoInfo && geoInfo.data && geoInfo.data.country_name) {
+ self.lookupUserGeoIP(otherUserId, function(geoInfo2) {
+ if(geoInfo2 && geoInfo2.data && geoInfo2.data.country_name && geoInfo2.data.country_name === geoInfo.data.country_name) {
+
+ console.log('They are from Same country.!!');
+
+ callback(geoInfo);
+ return;
+ }
+ });
+ }
+ console.log('They are NOT from same country.');
+ callback(null);
+ return;
+ });
+ }
/**
* Add the provided user to the Room.
@@ -785,24 +814,29 @@
// let the new user know about the other users in the room.
Object.keys(this.users).forEach(function (otherUserId) {
if (otherUserId !== userId) {
- // let the old user know that the new one has joined
- self.lookupUserGeoIP(userId, function (geoInfo) {
- var user = User.getById(userId);
- self.sendToUser(otherUserId, "join", user && user.publicId, type, geoInfo);
- });
- var otherClientType = self.users[otherUserId];
- if (VALID_TYPES[otherClientType]) {
- // let the new user know about the existing old users
- self.lookupUserGeoIP(otherUserId, function (geoInfo) {
- var otherUser = User.getById(otherUserId);
- self.sendToUser(userId, "join", otherUser && otherUser.publicId, otherClientType, geoInfo);
- });
- }
-
- // if (User.getById(userId).elizaUserId && User.getById(otherUserId).elizaUserId) {
- (userInteractions[userId] || (userInteractions[userId] = [])).push(otherUserId);
- (userInteractions[otherUserId] || (userInteractions[otherUserId] = [])).push(userId);
- // }
+
+ self.areUsersFromSameCountry(userId, otherUserId, function(geoInfo) {
+ var user = User.getById(userId);
+ self.sendToUser(otherUserId, "join", user && user.publicId, type, geoInfo); // let the old user know that the new one has joined
+ var otherClientType = self.users[otherUserId];
+ if (VALID_TYPES[otherClientType]) {
+ var otherUser = User.getById(otherUserId);
+ // let the new user know about the existing old users
+ if(otherClientType=='venter') {
+ self.sendToUser(userId, "join", otherUser && otherUser.publicId, otherClientType, null);
+ }
+ else {
+ self.lookupUserGeoIP(otherUserId, function (geoInfo) {
+ self.sendToUser(userId, "join", otherUser && otherUser.publicId, otherClientType, geoInfo);
+ });
+ }
+
+ console.log("other client type", otherClientType);
+ }
+
+ (userInteractions[userId] || (userInteractions[userId] = [])).push(otherUserId);
+ (userInteractions[otherUserId] || (userInteractions[otherUserId] = [])).push(userId);
+ });
}
});
View
35 scripts/email_listeners.js
@@ -1,34 +1,41 @@
(function() {
"use strict";
- var feedbackServer;
var mongoose = require('mongoose'),
+ _ = require("underscore"),
config = require("../config");
mongoose.connect(config.mongodb.uri, function(err) {
if(err) {
throw err;
}
console.log('Connect call-back!');
- feedbackServer = require('.././feedback/feedback-server').feedbackServer();
+
setTimeout(function() { startApp(); }, 5000);
});
var startApp = function() {
- feedbackServer.getLeaderboard(false, function(top15) {
- // console.log(top15);
- // if(username) {
- // feedbackServer.getLeaderboardForUser(username, function(userStats) {
- // // console.log("user stats", userStats);
- // res.render('leaderboard', { scores: top15, username: username, userLeaderboard: userStats});
- // });
- // }
- // else {
- // res.render('leaderboard', { scores: top15, username: username });
- // }
- });
+ var authServer = require('.././authentication/auth-server').authServer();
+ var feedbackServer = require('.././feedback/feedback-server').feedbackServer();
+ var utils = require('.././utils').sendEmailToUser;
+
+ feedbackServer.getLeaderboard(false, function(user_scores) {
+ _.each(user_scores, function(user, key, list) {
+ var username = user.username,
+ score = user.score;
+ feedbackServer.getLeaderboardForUser(username, function(user_stats) {
+ var rank = user_stats.rank,
+ diff = user_stats.diff;
+ authServer.getEmailAddressFromUsername(username, function(email_address) {
+ utils.sendEmailToUser(email_address, 'leaderboard_update', username, score, rank, diff);
+ });
+
+
+ });
+ });
+ });
};
View
30 static/chat-init.js
@@ -1,34 +1,28 @@
(function($,undefined) {
-
"use strict";
- var updateHUD = function() {
- var docready = this;
- docready.comm.request("updateHUD", paintUserLeaderboard);
-
- setTimeout(function() {
- updateHUD.call(docready, null);
- }, 1000*60);
+
+ window.log = function (data) {
+ try {
+ var console = window.console;
+ if (console && console.log) {
+ console.log(data);
+ }
+ } catch (err) {
+ // do nothing
+ }
};
- var paintUserLeaderboard = function(userLeaderboard) {
- $("#score").text('You have ' + userLeaderboard.score + ' points');
- $("#diff").text('But you only need ' + userLeaderboard.diff + ' points ');
- $("#rank").text('So your rank is currently #' + userLeaderboard.rank);
- };
+
$(document).ready(function() {
- var docready = this;
- $("div#Chatmain, div#loggedInAs, div#reputationLogin, div#listenerFeedback, a#meant_to_login, button#register").hide();
+ $("div#Chatmain, div#loggedInAs, div#reputationLogin, div#listenerFeedback, a#meant_to_login, button#register, li.scoreCard").hide();
window.LISTENER_LOGGED_IN = false;
var comm = window.Comm.create();
comm.register();
window.Chat.create();
- updateHUD.call(docready, null);
-
-
});
View
42 static/chat.js
@@ -47,9 +47,7 @@
if(CLIENT_TYPE === 'listener') {
$("div#reputationLogin").show();
}
- else {
- $("div#main").css('height','405px').css('overflow-y','hidden');
- }
+ $("div#main").css('height','405px').css('overflow-y','hidden');
$("div#listenerFeedback button").click(function() {
if(this.id === 'helpful') {
@@ -76,20 +74,7 @@
}
};
- var log = function (data) {
- try {
- var console = window.console;
- if (console && console.log) {
- console.log(data);
- }
- } catch (err) {
- // do nothing
- }
- };
-
- log('creating comm object');
window.comm = window.Comm.create();
- log('comm object creation successful');
var hasPartner = false;
var lastPartnerId = null;
var currentPartnerId = null;
@@ -106,8 +91,6 @@
}, NEW_PARTNER_BUTTON_TIMEOUT);
lastPartnerId = value;
currentPartnerId = value;
- log('last partner id, ' + lastPartnerId);
- log('current partner id, ' + currentPartnerId);
} else {
$("#newPartner")
.addClass("disabled");
@@ -124,7 +107,7 @@
});
comm.on('register', function (first, userId) {
self.progressBar(100);
- log('registered with id, ' + userId);
+ //log('registered with id, ' + userId);
addMessage('System', first ? 'Connected' : 'Reconnected');
requestNewChatChannel(false);
});
@@ -416,19 +399,28 @@
}
});
comm.handler("received-feedback", function(message) {
+ window.comm.request("updateHUD", {}, function(userLeaderboard) {
+ $('li.scoreCard').show().css('display', 'block !important').css('height', 'auto');
+ $("#score").text('Points ' + userLeaderboard.score + ' | Rank ' + userLeaderboard.rank);
+ $("#diff").text('You now need ' + userLeaderboard.diff + ' points to overtake the next spot on the leaderboard');
+ });
+
switch (message) {
case "positive":
if(window.LISTENER_LOGGED_IN) {
- $('div.announce').html('Your venter has rated you as a good listener!');
+ $('div.announce').html('Your venter has rated you a good listener!');
}
else {
- $('div.announce').html('Your venter has rated you as a good listener! Use your <a href="http://www.compassionpit.com/forum/" target="_blank">CompassionPit forums account</a> to tie this feedback to your account:');
+ $('div.announce').html('Your venter has rated you a good listener! Use your <a href="http://www.compassionpit.com/forum/" target="_blank">CompassionPit forums account</a> to tie this feedback to your account:');
}
-
-
break;
case "negative":
- $('div.announce').html('Your venter has indicated that you are not a good listener. Perhaps you could ask them how you can be a better listener?');
+ $('div.announce').html('Your venter has indicated that you are not a good listener. Perhaps you could ask them how you can be a better listener. You will now need to register an account, in order to prevent abuse.');
+ if(!window.LISTENER_LOGGED_IN) {
+ setTimeout(function() {
+ window.location = 'http://www.compassionpit.com/listen';
+ }, 1000*45);
+ }
break;
default:
break;
@@ -460,7 +452,7 @@
if (type !== CLIENT_TYPE) {
var oldUserId = lastPartnerId;
setHasPartner(otherUserId);
- log("join " + otherUserId);
+ // log("join " + otherUserId);
info(false);
var message;
View
61 static/comm.js
@@ -12,21 +12,20 @@
(function (exports, $, undefined) {
"use strict";
+ var updateHUD = function() {
+ window.comm.request("updateHUD", {}, function(userLeaderboard) {
+ $('li.scoreCard').show().css('display', 'block !important').css('height', 'auto');
+ $("#score").text('Points ' + userLeaderboard.score + ' | Rank ' + userLeaderboard.rank);
+ $("#diff").text('You only need ' + userLeaderboard.diff + ' points to overtake the next spot on the leaderboard');
+ });
+ setTimeout(function() {
+ updateHUD.call(this, null);
+ }, 1000*60);
+ };
var VERSION = window.COMPASSION_PIT_VERSION;
window.COMPASSION_PIT_VERSION = undefined;
- var log = function (data) {
- try {
- var console = window.console;
- if (console && console.log) {
- console.log(data);
- }
- } catch (err) {
- // do nothing
- }
- };
-
// amount of time to consider a disconnect a "real" disconnect.
var DISCONNECT_LEEWAY = 10 * 1000;
@@ -80,25 +79,23 @@
socketio_addr = null;
}
- log('determining sio addr');
+ window.log('determining sio addr');
if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)){
socket = io.connect(socketio_addr, {
'connect timeout': 500,
- 'transports': ['xhr-polling'],
+ 'transports': ['xhr-polling'],
'try multiple transports': true,
'reconnect': true,
'reconnection delay': 500,
'reopen delay': 500,
'max reconnection attempts': 10
});
- alert(socket.connection);
}
else {
socket = io.connect(socketio_addr, {
- 'transports': ['flashsocket', 'xhr-polling'],
'max reconnection attempts': 5,
'force new connection': true
});
@@ -108,9 +105,9 @@
var events = {};
- log('declaring emit');
+ window.log('declaring emit');
var emit = function (event) {
- log("Emit was called for event " + event);
+ window.log("Emit was called for event " + event);
var callbacks = has.call(events, event) && events[event];
if (callbacks) {
var args = Array.prototype.slice.call(arguments, 1);
@@ -138,7 +135,7 @@
var sentConnectedEvents = false;
var register = function () {
- log("big register method being called.");
+ window.log("big register method being called.");
currentConnectIndex += 1;
isRegistered = false;
var registerMessage = {
@@ -156,25 +153,25 @@
registerMessage.d.n = lastMessageReceived;
}
socket.json.send(registerMessage);
- log("Sent register message: " + JSON.stringify(registerMessage));
+ window.log("Sent register message: " + JSON.stringify(registerMessage));
window.Chat.progressBar();
$("#initializing").append('<br>'+"Sent register message via socket");
};
socket.on('connect', function () {
- log("socket connect");
+ window.log("socket connect");
window.Chat.progressBar();
$("#initializing").append('<br>'+"Connected to the socket");
- log("We are about to emit connect");
+ window.log("We are about to emit connect");
emit("connect");
- log("We are about to call register");
+ window.log("We are about to call register");
register();
});
var unregister;
socket.on('disconnect', function () {
- log("disconnect");
+ window.log("disconnect");
if (isRegistered) {
isRegistered = false;
@@ -191,7 +188,7 @@
});
socket.on('reconnecting', function (x, y) {
- log('reconnecting. Delay: ' + x + '. Attempts: ' + y);
+ window.log('reconnecting. Delay: ' + x + '. Attempts: ' + y);
});
socket.on('reconnect_failed', function () {
@@ -216,19 +213,19 @@
var lastReceivedMessage = message[4];
var forums_username = message[5];
if(forums_username !== false && window.CLIENT_TYPE==='listener') {
- console.log(forums_username);
$("span#currentUser").html(forums_username);
$("div#reputationLogin").hide();
$("div#loggedInAs").show();
window.LISTENER_LOGGED_IN = true;
+ updateHUD();
}
if (oldUserId && (isNewUser || userId !== oldUserId)) {
unregister();
}
isRegistered = true;
- log("registered " + (isNewUser ? "new user" : "reclaimed user") + " " + userId + "/" + publicUserId);
+ window.log("registered " + (isNewUser ? "new user" : "reclaimed user") + " " + userId + "/" + publicUserId);
$("#initializing").append('<br>'+"Received register message via socket");
window.Chat.progressBar();
@@ -255,10 +252,10 @@
if (handler) {
handler.apply(undefined, arrayify(data.d));
} else {
- log("Unhandled message: " + data.t);
+ window.log("Unhandled message: " + data.t);
}
} else {
- log("Unknown message: " + JSON.stringify(data));
+ window.log("Unknown message: " + JSON.stringify(data));
}
}
});
@@ -267,7 +264,7 @@
var sendBacklog = [];
unregister = function () {
- log("unregister");
+ window.log("unregister");
if (sentConnectedEvents) {
sentConnectedEvents = false;
emit('disconnect');
@@ -291,7 +288,7 @@
}
}
if (backlogMessages.length > 0) {
- log("Sent " + backlogMessages.length + " backlogged messages");
+ window.log("Sent " + backlogMessages.length + " backlogged messages");
for (j = 0, len = backlogMessages.length; j < len; j += 1) {
socket.json.send(backlogMessages[j]);
}
@@ -315,7 +312,7 @@
checkSend();
};
- log('returning from comm');
+ window.log('returning from comm');
return {
on: function (event, callback) {
@@ -344,7 +341,7 @@
socket.socket.reconnect();
},
register: function (userId) {
- log("calling register method");
+ window.log("calling register method");
register();
}
};
View
18 static/css/style.css
@@ -1,3 +1,19 @@
+button#notHelpful {
+ margin-top: 5px;
+}
+button#helpful {
+ margin-top: 10px;
+}
+
+div#scoreCard {
+ color: black;
+ font-size: 12px;
+}
+
+#facebookLikeBoxIFrame {
+ background-color: transparent;
+}
+
span.announcement {
background-color: yellow;
font-size: 1.3em;
@@ -254,7 +270,7 @@ button.login {
}
#status {
- margin: 10px 10px 57px 0px;
+ margin: 10px 10px 27px 0px;
width: 250px;
padding: 10px;
text-align: center;
View
12 users/models.js
@@ -21,6 +21,7 @@
}
this.id = id = id || guid();
this.publicId = publicId = publicId || guid();
+ this.join_time = new Date().getTime();
this.socket = require("../app").socket;
this.messageBacklog = [];
@@ -163,6 +164,7 @@
callback(null);
} else {
require('../app').geoipCity.lookup(ipAddress, function (err, data) {
+
if (err) {
log.error({
event: "GeoIP",
@@ -181,8 +183,14 @@
parts.push(part);
}
}
-
- callback(parts.join(", ") || null);
+
+ var geoIp = parts.join(", ") || null;
+ if(geoIp === null || !data.country_name) {
+ callback(null);
+ }
+ else {
+ callback(geoIp);
+ }
});
}
};
View
6 utils.js
@@ -108,4 +108,10 @@
return hashlib.sha512("CompassionPit$" + hashSalt + "$" + address);
};
+
+ exports.sendEmailToUser = function(email_address, template_name, username, score, rank, diff) {
+ // implement me!
+ // send to email address, using the template template_name, and the four varaibles.
+ };
+
}());
View
44 views/chat.jade
@@ -16,22 +16,22 @@ div(id="main",style="display:none")
form
textarea#inform(type="text", autocomplete="off", size="110")
input#sendmessage(type="submit", value="SEND")
- script
- google_ad_client = "ca-pub-6036766792552196";
- /* CompassionPit Chat 468x60 Bottom */
- google_ad_slot = "6889968105";
- google_ad_width = 468;
- google_ad_height = 60;
- script(src="http://pagead2.googlesyndication.com/pagead/show_ads.js")
+ div#adSenseAd(style="text-align: center; margin: 0px auto")
+ script
+ google_ad_client = "ca-pub-6036766792552196";
+ /* CompassionPit Chat 468x60 Bottom */
+ google_ad_slot = "6889968105";
+ google_ad_width = 468;
+ google_ad_height = 60;
+ script(src="http://pagead2.googlesyndication.com/pagead/show_ads.js")
#right
#buttons1
#status &nbsp;
ul
- li
+ li.scoreCard
div#scoreCard
- span#score
- span#diff
- span#rank
+ div#score
+ div#diff
li
a(href="#", id="newPartner") Find a new partner
li#reportAbuse
@@ -45,11 +45,10 @@ div(id="main",style="display:none")
input(type="checkbox", id="enable_typing")
#{" Visible Typing"}
#typing_status
+ div(class="announce")
//-
div#spinner
- div#reputationLogin
- div(class="announce")
- p Listeners can now optionally log in using their CompassionPit forums account!
+ div#reputationLogin
div(class="form_errors",id="form_errors")
label(class="login")
input(type="text", id="loginUsername", name="loginUsername", class="login", placeholder="Username")
@@ -59,9 +58,9 @@ div(id="main",style="display:none")
br
a(href="javascript:return false;", id="register_account", class="login_mistake") Don't have an account? Register one at the CompassionPit Forums!
div#listenerFeedback
- p Is this person a good listener?
- button(id="helpful") Yes!
- button(id="notHelpful") No
+ p Please give feedback to keep CompassionPit high-quality
+ button(id="helpful") This person is a good listener! =)
+ button(id="notHelpful") This person is a bad listener :-(
div#loggedInAs
p Currently logged in as:&nbsp;
span#currentUser
@@ -93,17 +92,6 @@ div(id="main",style="display:none")
- }
script
- //- Google Website Optimizer Tracking Script
- var _gaq = _gaq || [];
- _gaq.push(['gwo._setAccount', 'UA-17971348-2']);
- _gaq.push(['gwo._trackPageview', '/2386081484/goal']);
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-
-script
window.CLIENT_TYPE = !{JSON.stringify(type)};
script(src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.1/underscore-min.js")
View
2 views/index.jade
@@ -61,5 +61,5 @@ script
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
li
- iframe(src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.compassionpit.com&amp;layout=standard&amp;show_faces=false&amp;width=450&amp;action=like&amp;colorscheme=light&amp;height=35", scrolling="no", frameborder="0", style="border:none; overflow:hidden; width:240px; height:35px;", allowTransparency="true")
+ iframe(src="http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.compassionpit.com&amp;layout=standard&amp;show_faces=false&amp;width=450&amp;action=like&amp;colorscheme=light&amp;height=35", scrolling="no", frameborder="0", style="border:none; overflow:hidden; width:240px; height:35px;", id="facebookLikeBoxIFrame")
.clear
View
24 views/privacy-policy.jade
@@ -4,8 +4,28 @@
:markdown
Privacy Policy
-------------------
- CompassionPit respects your privacy and understands how important it is. All data collected is anonymized and depersonalized.
+ The CompassionPit privacy policy:
+
+ \As a system-level check against abusers, we anonymously collect IP addresses of people who connect, and run them through a hashing algorithm. This means that in the event that our servers somehow got hacked, this would still not be enough information to identify you personally. However, it would be enough information to get an approximate idea of your location.
+
+ \In the past, we have stored chat logs in the server, temporarily; we have to rotate them every so often because the disk runs out of space, and since we are not personally reading or reviewing them, we are willing to throw them away. In the future we may begin to store anonymized chat logs again (with NO no identifiable information!), and to run them through a static analysis tool: in other words, so we can learn from what types of conversations lead to good feelings between the listener and venter. We'll look for certain keywords, such as "love" or smiley faces, or whatever the positive indicators might be. We do NOT tie the chat logs to the listener user ID, and the venter does not have a user ID since there are no accounts for venters.
+
+ \The ONLY person that has access to these logs is me. I will NEVER read your chat conversations directly. I would only, hypothetically, look through them in aggregate to look for particular patterns that lead to users having a positive experience on this site. All of the logs are on a separate server that only I have access to. In fact, there are even special restrictions on the server so that ports are locked down and only particular IP addresses can connect to those ports, SSH and the specially configured port that we're running MongoDB (our database) on.
+
+ \We do not store ANY passwords in plain text. When users log in to vbulletin, the forums software we use, we hash the passwords using a salt, and then run them through an extra hashing algorithm. In other words, if you use a password, even I would not be able to see it, unless I rented thousands of servers and spent a year trying to brute force crack it, which I have no reason for wanting to do.
+
+ \Information is NEVER shared with third parties. I will NEVER sell your email address. In the future to support the site's operations, I may offer certain products for sale, but I will always give you the opportunity of dealing directly with the vendor after I suggest it: I will NEVER give any third party vendors personal information about you. I will NEVER distribute your email address to ANYONE, including moderators of the forums. Your personal identity is PRIVATE unless you explicitly choose to reveal it (for example by typing it out on your user profile on the forums).
+
+ \Cookies are used to identify registered listeners with forums accounts. If you log in to the forums, a cookie will be set on your computer. The same cookie that identifies you as a forum user is what identifies you as a registered listener. If you log out of the forums, your cookies will be deleted -- for both the forums, as well as the main site. If a registered listener chooses to vent while still logged in, NONE of their identifying information as a listener will be stored or read whatsoever. In other words, you are treated anonymously.
+
+ \If at any point you wish to verify the practices in the privacy policy, please feel free to conduct an audit of the application's source code, which is published publicly: http://www.github.com/zackster/CompassionPit--node-
+
+ \We have zero intentions of collecting personal information in the future or of selling your information or even sharing it for free with other third parties. If at any point we start collecting personal information, or revealing it to anyone, you will be given advance notice with an email as well as a notice on the main website.
+
+ \If at any time you wish to delete your CompassionPit forums account, then simply contact me directly, _zachary_@_CompassionPit_._com_, and I will delete your account and all your posts. Furthermore, if you wish to delete one specific post, or have personal information removed, simply contact me directly, and I will remove it promptly.
+
+ \If you have ANY questions about this policy, then please contact me directly: _zachary_@_CompassionPit_._com_.
Contact
-------
- If you have any questions, you can contact us at _zachary_@_CompassionPit_._com_. Please put "CompassionPit Privacy Policy" in the subject line. Thanks!
+ \If you have any questions, you can contact us at _zachary_@_CompassionPit_._com_. Please put "CompassionPit Privacy Policy" in the subject line. Thanks!

0 comments on commit 73d7686

Please sign in to comment.