Refactor ChatRoom#add into multiple functions

Also aggressively deprecate older parts of the protocol that are no
longer used.
This commit is contained in:
Guangcong Luo 2013-04-27 13:03:03 -07:00
parent ff9c2d2bed
commit 7d8ecfb8b8

View File

@ -71,10 +71,13 @@
animateDuration: 100,
extraSpace: 0
});
if (this === app.curSideRoom || this === app.curRoom) {
this.$chatbox.focus();
}
}
},
focus: function() {
this.$chatAdd.find('textarea').focus();
if (this.$chatbox) this.$chatbox.focus();
},
destroy: function() {
this.send('/lobbychat off');
@ -90,297 +93,7 @@
autoscroll = true;
}
for (var i = 0; i < log.length; i++) {
if (typeof log[i] === 'string') {
if (log[i].substr(0,1) !== '|') log[i] = '||'+log[i];
var row = log[i].substr(1).split('|');
switch (row[0]) {
case 'c':
case 'chat':
log[i] = {
name: row[1],
message: row.slice(2).join('|')
};
break;
case 'b':
case 'B':
log[i] = {
action: 'battle',
room: row[1],
name: row[2],
name2: row[3],
silent: (row[0] === 'B')
};
break;
case 'j':
case 'J':
log[i] = {
action: 'join',
name: row[1],
silent: (row[0] === 'J')
};
break;
case 'l':
case 'L':
log[i] = {
action: 'leave',
name: row[1],
silent: (row[0] === 'L')
};
break;
case 'n':
case 'N':
log[i] = {
action: 'rename',
name: row[1],
oldid: row[2],
silent: true
};
break;
case 'raw':
log[i] = {
rawMessage: row.slice(1).join('|')
};
break;
case 'refresh':
// refresh the page
document.location.reload(true);
break;
case 'formats':
var isSection = false;
var section = '';
BattleFormats = {};
for (var j=1; j<row.length; j++) {
if (isSection) {
section = row[j];
isSection = false;
} else if (row[j] === '') {
isSection = true;
} else {
var searchShow = true;
var challengeShow = true;
var team = null;
var name = row[j];
if (name.substr(name.length-2) === ',#') { // preset teams
team = 'preset';
name = name.substr(0,name.length-2);
}
if (name.substr(name.length-2) === ',,') { // search-only
challengeShow = false;
name = name.substr(0,name.length-2);
} else if (name.substr(name.length-1) === ',') { // challenge-only
searchShow = false;
name = name.substr(0,name.length-1);
}
BattleFormats[toId(name)] = {
id: toId(name),
name: name,
team: team,
section: section,
searchShow: searchShow,
challengeShow: challengeShow,
rated: challengeShow && searchShow,
isTeambuilderFormat: challengeShow && searchShow && !team,
effectType: 'Format'
};
}
}
break;
case '':
default:
log[i] = {
message: row.slice(1).join('|')
};
break;
}
}
if (log[i].name && log[i].message) {
var userid = toUserid(log[i].name);
var color = hashColor(userid);
// if (me.ignore[userid] && log[i].name.substr(0, 1) === ' ') continue;
// Add this user to the list of people who have spoken recently.
this.markUserActive(userid);
this.$joinLeave = null;
this.joinLeave = {
'join': [],
'leave': []
};
var clickableName = '<span style="cursor:pointer" onclick="return rooms.lobby.formChallenge(\'' + userid + '\');">' + Tools.escapeHTML(log[i].name.substr(1)) + '</span>';
var message = log[i].message;
var isHighlighted = this.getHighlight(message);
if (isHighlighted) {
notify({
type: 'highlight',
user: log[i].name
});
}
var highlight = isHighlighted ? ' style="background-color:#FDA;"' : '';
var chatDiv = '<div class="chat"' + highlight + '>';
var timestamp = this.getTimestamp(log[i].pm ? 'pms' : 'lobby');
if (log[i].name.substr(0, 1) !== ' ') clickableName = '<small>' + Tools.escapeHTML(log[i].name.substr(0, 1)) + '</small>'+clickableName;
if (log[i].pm) {
var pmuserid = (userid === me.userid ? toUserid(log[i].pm) : userid);
if (!me.pm[pmuserid]) me.pm[pmuserid] = '';
var pmcode = '<div class="chat">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em> ' + messageSanitize(message) + '</em></div>';
for (var j = 0; j < me.popups.length; j++) {
if (pmuserid === me.popups[j]) break;
}
if (j == me.popups.length) {
// This is a new PM.
me.popups.unshift(pmuserid);
notify({
type: 'pm',
user: log[i].name
});
}
me.pm[pmuserid] += pmcode;
if (me.popups.length && me.popups[me.popups.length - 1] === pmuserid) {
this.updatePopup(pmcode);
} else {
this.updatePopup();
}
this.$chat.append('<div class="chat">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <span class="message-pm"><i style="cursor:pointer" onclick="selectTab(\'lobby\');rooms.lobby.popupOpen(\'' + pmuserid + '\')">(Private to ' + Tools.escapeHTML(log[i].pm) + ')</i> ' + messageSanitize(message) + '</span></div>');
//} else if (log[i].act) {
// this.$chat.append('<div class="chat"><strong style="' + color + '">&bull;</strong> <em' + (log[i].name.substr(1) === app.user.get('name') ? ' class="mine"' : '') + '>' + clickableName + ' <i>' + message + '</i></em></div>');
} else if (message.substr(0,2) === '//') {
this.$chat.append(chatDiv + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em' + (log[i].name.substr(1) === app.user.get('name') ? ' class="mine"' : '') + '>' + messageSanitize(message.substr(1)) + '</em></div>');
} else if (message.substr(0,4).toLowerCase() === '/me ') {
this.$chat.append(chatDiv + timestamp + '<strong style="' + color + '">&bull;</strong> <em' + (log[i].name.substr(1) === app.user.get('name') ? ' class="mine"' : '') + '>' + clickableName + ' <i>' + messageSanitize(message.substr(4)) + '</i></em></div>');
} else if (message.substr(0,5).toLowerCase() === '/mee ') {
this.$chat.append(chatDiv + timestamp + '<strong style="' + color + '">&bull;</strong> <em' + (log[i].name.substr(1) === app.user.get('name') ? ' class="mine"' : '') + '>' + clickableName + '<i>' + messageSanitize(message.substr(5)) + '</i></em></div>');
} else if (message.substr(0,10).toLowerCase() === '/announce ') {
this.$chat.append(chatDiv + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <span class="message-announce">' + messageSanitize(message.substr(10)) + '</span></div>');
} else if (message.substr(0,6).toLowerCase() === '/warn ') {
overlay('rules', {warning: message.substr(6)});
} else if (message.substr(0,14).toLowerCase() === '/data-pokemon ') {
this.$chat.append('<div class="message"><ul class=\"utilichart\">'+Chart.pokemonRow(Tools.getTemplate(message.substr(14)),'',{})+'<li style=\"clear:both\"></li></ul></div>');
} else if (message.substr(0,11).toLowerCase() === '/data-item ') {
this.$chat.append('<div class="message"><ul class=\"utilichart\">'+Chart.itemRow(Tools.getItem(message.substr(11)),'',{})+'<li style=\"clear:both\"></li></ul></div>');
} else if (message.substr(0,14).toLowerCase() === '/data-ability ') {
this.$chat.append('<div class="message"><ul class=\"utilichart\">'+Chart.abilityRow(Tools.getAbility(message.substr(14)),'',{})+'<li style=\"clear:both\"></li></ul></div>');
} else if (message.substr(0,11).toLowerCase() === '/data-move ') {
this.$chat.append('<div class="message"><ul class=\"utilichart\">'+Chart.moveRow(Tools.getMove(message.substr(11)),'',{})+'<li style=\"clear:both\"></li></ul></div>');
} else {
// Normal chat message.
this.$chat.append(chatDiv + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em' + (log[i].name.substr(1) === app.user.get('name') ? ' class="mine"' : '') + '>' + messageSanitize(message) + '</em></div>');
}
} else if (log[i].name && log[i].action === 'battle') {
var id = log[i].room;
var matches = this.parseBattleID(id);
if (!matches) {
continue; // bogus room ID could be used to inject JavaScript
}
var format = (matches ? matches[1] : '');
if (log[i].silent && !Tools.prefs('showbattles')) continue;
this.$joinLeave = null;
this.joinLeave = {
'join': [],
'leave': []
};
var id = log[i].room;
var battletype = 'Battle';
if (log[i].format) {
battletype = log[i].format + ' battle';
if (log[i].format === 'Random Battle') battletype = 'Random Battle';
}
this.$chat.append('<div class="message"><a href="' + Config.locprefix+id + '" onclick="selectTab(\'' + id + '\'); return false" class="battle-start">' + battletype + ' started between <strong style="' + hashColor(toUserid(log[i].name)) + '">' + Tools.escapeHTML(log[i].name) + '</strong> and <strong style="' + hashColor(toUserid(log[i].name2)) + '">' + Tools.escapeHTML(log[i].name2) + '</strong>.</a></div>');
} else if (log[i].message) {
this.$chat.append('<div class="message">' + Tools.escapeHTML(log[i].message) + '</div>');
} else if (log[i].rawMessage) {
this.$chat.append('<div class="message">' + Tools.sanitizeHTML(log[i].rawMessage) + '</div>');
} else if (log[i].evalRulesRedirect || log[i].evalRawMessage) {
// TODO: This will be removed in due course.
window.location.href = 'http://pokemonshowdown.com/rules';
} else if (log[i].name && (log[i].action === 'join' || log[i].action === 'leave' || log[i].action === 'rename')) {
var userid = toUserid(log[i].name);
if (log[i].action === 'join') {
if (log[i].oldid) delete this.users[toUserid(log[i].oldid)];
if (!this.users[userid]) this.userCount.users++;
this.users[userid] = log[i].name;
this.userList.add(userid);
this.userList.updateUserCount();
this.userList.updateNoUsersOnline();
} else if (log[i].action === 'leave') {
if (this.users[userid]) this.userCount.users--;
delete this.users[userid];
this.userList.remove(userid);
this.userList.updateUserCount();
this.userList.updateNoUsersOnline();
} else if (log[i].action === 'rename') {
if (log[i].oldid) delete this.users[toUserid(log[i].oldid)];
this.users[userid] = log[i].name;
this.userList.remove(log[i].oldid);
this.userList.add(userid);
continue;
}
if (log[i].silent && !Tools.prefs('showjoins')) continue;
if (!this.$joinLeave) {
this.$chat.append('<div class="message"><small>Loading...</small></div>');
this.$joinLeave = this.$chat.children().last();
}
this.joinLeave[log[i].action].push(log[i].name);
var message = '';
if (this.joinLeave['join'].length) {
var preList = this.joinLeave['join'];
var list = [];
var named = {};
for (var j = 0; j < preList.length; j++) {
if (!named[preList[j]]) list.push(preList[j]);
named[preList[j]] = true;
}
for (var j = 0; j < list.length; j++) {
if (j >= 5) {
message += ', and ' + (list.length - 5) + ' others';
break;
}
if (j > 0) {
if (j == 1 && list.length == 2) {
message += ' and ';
} else if (j == list.length - 1) {
message += ', and ';
} else {
message += ', ';
}
}
message += Tools.escapeHTML(list[j]);
}
message += ' joined';
}
if (this.joinLeave['leave'].length) {
if (this.joinLeave['join'].length) {
message += '; ';
}
var preList = this.joinLeave['leave'];
var list = [];
var named = {};
for (var j = 0; j < preList.length; j++) {
if (!named[preList[j]]) list.push(preList[j]);
named[preList[j]] = true;
}
for (var j = 0; j < list.length; j++) {
if (j >= 5) {
message += ', and ' + (list.length - 5) + ' others';
break;
}
if (j > 0) {
if (j == 1 && list.length == 2) {
message += ' and ';
} else if (j == list.length - 1) {
message += ', and ';
} else {
message += ', ';
}
}
message += Tools.escapeHTML(list[j]);
}
message += ' left<br />';
}
this.$joinLeave.html('<small style="color: #555555">' + message + '</small>');
}
this.addRow(log[i]);
}
if (autoscroll) {
this.$chatFrame.scrollTop(this.$chat.height());
@ -390,6 +103,280 @@
$children.slice(0,100).remove();
}
},
addRow: function(line) {
var name, name2, room, action, silent, oldid;
if (typeof line === 'string') {
if (line.substr(0,1) !== '|') line = '||'+line;
var row = line.substr(1).split('|');
switch (row[0]) {
case 'c':
case 'chat':
this.addChat(row[1], row.slice(2).join('|'));
break;
case 'b':
case 'B':
var id = row[1];
name = row[2];
name2 = row[3];
silent = (row[0] === 'B');
var matches = this.parseBattleID(id);
if (!matches) {
return; // bogus room ID could be used to inject JavaScript
}
var format = (matches ? matches[1] : '');
if (silent && !Tools.prefs('showbattles')) return;
this.addJoinLeave();
var battletype = 'Battle';
if (format) {
battletype = format + ' battle';
if (format === 'Random Battle') battletype = 'Random Battle';
}
this.$chat.append('<div class="message"><a href="' + Config.locprefix+id + '" onclick="selectTab(\'' + id + '\'); return false" class="battle-start">' + battletype + ' started between <strong style="' + hashColor(toUserid(name)) + '">' + Tools.escapeHTML(name) + '</strong> and <strong style="' + hashColor(toUserid(name2)) + '">' + Tools.escapeHTML(name2) + '</strong>.</a></div>');
break;
case 'j':
case 'J':
this.addJoinLeave('join', row[1], null, row[0] === 'J');
break;
case 'l':
case 'L':
this.addJoinLeave('leave', row[1], null, row[0] === 'L');
break;
case 'n':
case 'N':
this.addJoinLeave('rename', row[1], row[2], true);
break;
case 'refresh':
// refresh the page
document.location.reload(true);
break;
case 'formats':
this.parseFormats(row);
break;
case 'raw':
this.$chat.append('<div class="message">' + Tools.sanitizeHTML(row.slice(1).join('|')) + '</div>');
break;
case '':
default:
this.$chat.append('<div class="message">' + Tools.escapeHTML(row.slice(1).join('|')) + '</div>');
break;
}
}
},
parseFormats: function(formatsList) {
var isSection = false;
var section = '';
BattleFormats = {};
for (var j=1; j<formatsList.length; j++) {
if (isSection) {
section = formatsList[j];
isSection = false;
} else if (formatsList[j] === '') {
isSection = true;
} else {
var searchShow = true;
var challengeShow = true;
var team = null;
var name = formatsList[j];
if (name.substr(name.length-2) === ',#') { // preset teams
team = 'preset';
name = name.substr(0,name.length-2);
}
if (name.substr(name.length-2) === ',,') { // search-only
challengeShow = false;
name = name.substr(0,name.length-2);
} else if (name.substr(name.length-1) === ',') { // challenge-only
searchShow = false;
name = name.substr(0,name.length-1);
}
BattleFormats[toId(name)] = {
id: toId(name),
name: name,
team: team,
section: section,
searchShow: searchShow,
challengeShow: challengeShow,
rated: challengeShow && searchShow,
isTeambuilderFormat: challengeShow && searchShow && !team,
effectType: 'Format'
};
}
}
},
addJoinLeave: function(action, name, oldid, silent) {
var userid = toUserid(name);
if (!action) {
this.$joinLeave = null;
this.joinLeave = {
'join': [],
'leave': []
};
return;
} else if (action === 'join') {
if (oldid) delete this.users[toUserid(oldid)];
if (!this.users[userid]) this.userCount.users++;
this.users[userid] = name;
this.userList.add(userid);
this.userList.updateUserCount();
this.userList.updateNoUsersOnline();
} else if (action === 'leave') {
if (this.users[userid]) this.userCount.users--;
delete this.users[userid];
this.userList.remove(userid);
this.userList.updateUserCount();
this.userList.updateNoUsersOnline();
} else if (action === 'rename') {
if (oldid) delete this.users[toUserid(oldid)];
this.users[userid] = name;
this.userList.remove(oldid);
this.userList.add(userid);
return;
}
if (silent && !Tools.prefs('showjoins')) return;
if (!this.$joinLeave) {
this.$chat.append('<div class="message"><small>Loading...</small></div>');
this.$joinLeave = this.$chat.children().last();
}
this.joinLeave[action].push(name);
var message = '';
if (this.joinLeave['join'].length) {
var preList = this.joinLeave['join'];
var list = [];
var named = {};
for (var j = 0; j < preList.length; j++) {
if (!named[preList[j]]) list.push(preList[j]);
named[preList[j]] = true;
}
for (var j = 0; j < list.length; j++) {
if (j >= 5) {
message += ', and ' + (list.length - 5) + ' others';
break;
}
if (j > 0) {
if (j == 1 && list.length == 2) {
message += ' and ';
} else if (j == list.length - 1) {
message += ', and ';
} else {
message += ', ';
}
}
message += Tools.escapeHTML(list[j]);
}
message += ' joined';
}
if (this.joinLeave['leave'].length) {
if (this.joinLeave['join'].length) {
message += '; ';
}
var preList = this.joinLeave['leave'];
var list = [];
var named = {};
for (var j = 0; j < preList.length; j++) {
if (!named[preList[j]]) list.push(preList[j]);
named[preList[j]] = true;
}
for (var j = 0; j < list.length; j++) {
if (j >= 5) {
message += ', and ' + (list.length - 5) + ' others';
break;
}
if (j > 0) {
if (j == 1 && list.length == 2) {
message += ' and ';
} else if (j == list.length - 1) {
message += ', and ';
} else {
message += ', ';
}
}
message += Tools.escapeHTML(list[j]);
}
message += ' left<br />';
}
this.$joinLeave.html('<small style="color: #555555">' + message + '</small>');
},
addChat: function(name, message) {
var userid = toUserid(name);
var color = hashColor(userid);
var pm = false;
// if (me.ignore[userid] && name.substr(0, 1) === ' ') continue;
// Add this user to the list of people who have spoken recently.
this.markUserActive(userid);
this.$joinLeave = null;
this.joinLeave = {
'join': [],
'leave': []
};
var clickableName = '<span style="cursor:pointer" class="username" data-userid="' + userid + '">' + Tools.escapeHTML(name.substr(1)) + '</span>';
var isHighlighted = this.getHighlight(message);
if (isHighlighted) {
// notify({
// type: 'highlight',
// user: name
// });
}
var highlight = isHighlighted ? ' style="background-color:#FDA;"' : '';
var chatDiv = '<div class="chat"' + highlight + '>';
var timestamp = this.getTimestamp('lobby');
if (name.substr(0, 1) !== ' ') clickableName = '<small>' + Tools.escapeHTML(name.substr(0, 1)) + '</small>'+clickableName;
if (pm) {
var pmuserid = (userid === me.userid ? toUserid(pm) : userid);
if (!me.pm[pmuserid]) me.pm[pmuserid] = '';
var pmcode = '<div class="chat">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em> ' + messageSanitize(message) + '</em></div>';
for (var j = 0; j < me.popups.length; j++) {
if (pmuserid === me.popups[j]) break;
}
if (j == me.popups.length) {
// This is a new PM.
me.popups.unshift(pmuserid);
notify({
type: 'pm',
user: name
});
}
me.pm[pmuserid] += pmcode;
if (me.popups.length && me.popups[me.popups.length - 1] === pmuserid) {
this.updatePopup(pmcode);
} else {
this.updatePopup();
}
this.$chat.append('<div class="chat">' + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <span class="message-pm"><i style="cursor:pointer" onclick="selectTab(\'lobby\');rooms.lobby.popupOpen(\'' + pmuserid + '\')">(Private to ' + Tools.escapeHTML(pm) + ')</i> ' + messageSanitize(message) + '</span></div>');
} else if (message.substr(0,4).toLowerCase() === '/me ') {
this.$chat.append(chatDiv + timestamp + '<strong style="' + color + '">&bull;</strong> <em' + (name.substr(1) === app.user.get('name') ? ' class="mine"' : '') + '>' + clickableName + ' <i>' + messageSanitize(message.substr(4)) + '</i></em></div>');
} else if (message.substr(0,5).toLowerCase() === '/mee ') {
this.$chat.append(chatDiv + timestamp + '<strong style="' + color + '">&bull;</strong> <em' + (name.substr(1) === app.user.get('name') ? ' class="mine"' : '') + '>' + clickableName + '<i>' + messageSanitize(message.substr(5)) + '</i></em></div>');
} else if (message.substr(0,10).toLowerCase() === '/announce ') {
this.$chat.append(chatDiv + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <span class="message-announce">' + messageSanitize(message.substr(10)) + '</span></div>');
} else if (message.substr(0,6).toLowerCase() === '/warn ') {
overlay('rules', {warning: message.substr(6)});
} else if (message.substr(0,14).toLowerCase() === '/data-pokemon ') {
this.$chat.append('<div class="message"><ul class="utilichart">'+Chart.pokemonRow(Tools.getTemplate(message.substr(14)),'',{})+'<li style=\"clear:both\"></li></ul></div>');
} else if (message.substr(0,11).toLowerCase() === '/data-item ') {
this.$chat.append('<div class="message"><ul class="utilichart">'+Chart.itemRow(Tools.getItem(message.substr(11)),'',{})+'<li style=\"clear:both\"></li></ul></div>');
} else if (message.substr(0,14).toLowerCase() === '/data-ability ') {
this.$chat.append('<div class="message"><ul class="utilichart">'+Chart.abilityRow(Tools.getAbility(message.substr(14)),'',{})+'<li style=\"clear:both\"></li></ul></div>');
} else if (message.substr(0,11).toLowerCase() === '/data-move ') {
this.$chat.append('<div class="message"><ul class="utilichart">'+Chart.moveRow(Tools.getMove(message.substr(11)),'',{})+'<li style=\"clear:both\"></li></ul></div>');
} else {
// Normal chat message.
if (message.substr(0,2) === '//') message = message.substr(1);
this.$chat.append(chatDiv + timestamp + '<strong style="' + color + '">' + clickableName + ':</strong> <em' + (name.substr(1) === app.user.get('name') ? ' class="mine"' : '') + '>' + messageSanitize(message) + '</em></div>');
}
},
getHighlight: function(message) {
var highlights = Tools.prefs('highlights') || [];
if (!app.highlightRegExp) {