Tidied up the tell handler a bit:
- fixed quoted name parsing to not choke if the first token is just a quote. - also fixed to not choke if the user types the message using some non-space whitespace characters. - fixed history mistell erasing for multi-word usernames. - use quotes in the history line only if the user used quotes. - added hooks for easy subclassing git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4047 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -922,6 +922,15 @@ public class ChatDirector extends BasicDirector
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that after mogrification the message is not too long.
|
||||||
|
* @return an error message if it is too long, or null.
|
||||||
|
*/
|
||||||
|
protected String checkLength (String msg)
|
||||||
|
{
|
||||||
|
return null; // everything's ok by default
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a hashmap containing all command handlers that match the
|
* Returns a hashmap containing all command handlers that match the
|
||||||
* specified command (i.e. the specified command is a prefix of their
|
* specified command (i.e. the specified command is a prefix of their
|
||||||
@@ -1203,64 +1212,62 @@ public class ChatDirector extends BasicDirector
|
|||||||
SpeakService speakSvc, final String command, String args,
|
SpeakService speakSvc, final String command, String args,
|
||||||
String[] history)
|
String[] history)
|
||||||
{
|
{
|
||||||
// there should be at least two arg tokens: '/tell target word'
|
if (StringUtil.isBlank(args)) {
|
||||||
StringTokenizer tok = new StringTokenizer(args);
|
|
||||||
if (tok.countTokens() < 2) {
|
|
||||||
return "m.usage_tell";
|
return "m.usage_tell";
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the handle starts with a quote, keep tacking on words until
|
final boolean useQuotes = args.startsWith("\"");
|
||||||
// we find the end quote
|
String[] bits = parseTell(args);
|
||||||
String handle = tok.nextToken();
|
String handle = bits[0];
|
||||||
if (handle.startsWith("\"")) {
|
String message = bits[1];
|
||||||
while (!handle.endsWith("\"") && tok.hasMoreTokens()) {
|
|
||||||
handle = handle + " " + tok.nextToken();
|
|
||||||
}
|
|
||||||
if (!handle.endsWith("\"")) {
|
|
||||||
return "m.usage_tell";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now strip off everything after the handle for the message
|
// validate that we didn't eat all the tokens making the handle
|
||||||
int uidx = args.indexOf(handle);
|
|
||||||
String message = args.substring(uidx + handle.length()).trim();
|
|
||||||
if (StringUtil.isBlank(message)) {
|
if (StringUtil.isBlank(message)) {
|
||||||
return "m.usage_tell";
|
return "m.usage_tell";
|
||||||
}
|
}
|
||||||
|
|
||||||
// strip the quotes off of the handle
|
|
||||||
if (handle.startsWith("\"")) {
|
|
||||||
handle = handle.substring(1, handle.length()-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure we're not trying to tell something to ourselves
|
// make sure we're not trying to tell something to ourselves
|
||||||
BodyObject self = (BodyObject)_ctx.getClient().getClientObject();
|
BodyObject self = (BodyObject)_ctx.getClient().getClientObject();
|
||||||
if (handle.equalsIgnoreCase(self.getVisibleName().toString())) {
|
if (handle.equalsIgnoreCase(self.getVisibleName().toString())) {
|
||||||
return "m.talk_self";
|
return "m.talk_self";
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear out from the history any tells that are mistypes
|
// and lets just give things an opportunity to sanitize the name
|
||||||
for (Iterator iter = _history.iterator(); iter.hasNext(); ) {
|
Name target = normalizeAsName(handle);
|
||||||
String hist = (String) iter.next();
|
|
||||||
if (hist.startsWith("/" + command) &&
|
|
||||||
(new StringTokenizer(hist).countTokens() > 2)) {
|
|
||||||
iter.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// mogrify the chat
|
// mogrify the chat
|
||||||
message = mogrifyChat(message);
|
message = mogrifyChat(message);
|
||||||
|
String err = checkLength(message);
|
||||||
|
if (err != null) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear out from the history any tells that are mistypes
|
||||||
|
for (Iterator iter = _history.iterator(); iter.hasNext(); ) {
|
||||||
|
String hist = (String) iter.next();
|
||||||
|
if (hist.startsWith("/" + command)) {
|
||||||
|
String harg = hist.substring(command.length() + 1).trim();
|
||||||
|
// we blow away any historic tells that have msg content
|
||||||
|
if (!StringUtil.isBlank(parseTell(harg)[1])) {
|
||||||
|
iter.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// store the full command in the history, even if it was mistyped
|
// store the full command in the history, even if it was mistyped
|
||||||
final String histEntry = command + " \"" + handle + "\" " + message;
|
final String histEntry = command + " " +
|
||||||
|
(useQuotes ? ("\"" + target + "\"") : target.toString()) +
|
||||||
|
" " + message;
|
||||||
history[0] = histEntry;
|
history[0] = histEntry;
|
||||||
|
|
||||||
// request to send this text as a tell message
|
// request to send this text as a tell message
|
||||||
requestTell(new Name(handle), message, new ResultListener() {
|
requestTell(target, escapeMessage(message), new ResultListener() {
|
||||||
public void requestCompleted (Object result) {
|
public void requestCompleted (Object result) {
|
||||||
// replace the full one in the history with just:
|
// replace the full one in the history with just:
|
||||||
// /tell "<handle>"
|
// /tell "<handle>"
|
||||||
String newEntry = "/" + command + " \"" + result + "\" ";
|
String newEntry = "/" + command + " " +
|
||||||
|
(useQuotes ? ("\"" + result + "\"")
|
||||||
|
: String.valueOf(result)) + " ";
|
||||||
_history.remove(newEntry);
|
_history.remove(newEntry);
|
||||||
int dex = _history.lastIndexOf("/" + histEntry);
|
int dex = _history.lastIndexOf("/" + histEntry);
|
||||||
if (dex >= 0) {
|
if (dex >= 0) {
|
||||||
@@ -1276,6 +1283,51 @@ public class ChatDirector extends BasicDirector
|
|||||||
|
|
||||||
return ChatCodes.SUCCESS;
|
return ChatCodes.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the tell into two strings, handle and message. If either
|
||||||
|
* one is null then the parsing did not succeed.
|
||||||
|
*/
|
||||||
|
protected String[] parseTell (String args)
|
||||||
|
{
|
||||||
|
String handle, message;
|
||||||
|
if (args.startsWith("\"")) {
|
||||||
|
int nextQuote = args.indexOf('"', 1);
|
||||||
|
if (nextQuote == -1 || nextQuote == 1) {
|
||||||
|
handle = message = null; // bogus parsing
|
||||||
|
|
||||||
|
} else {
|
||||||
|
handle = args.substring(1, nextQuote).trim();
|
||||||
|
message = args.substring(nextQuote + 1).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
StringTokenizer st = new StringTokenizer(args);
|
||||||
|
handle = st.nextToken();
|
||||||
|
message = args.substring(handle.length() + 1).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new String[] { handle, message };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn the user-entered string into a Name object, doing
|
||||||
|
* any particular normalization we want to do along the way
|
||||||
|
* so that "/tell Bob" and "/tell BoB" don't both show up in history.
|
||||||
|
*/
|
||||||
|
protected Name normalizeAsName (String handle)
|
||||||
|
{
|
||||||
|
return new Name(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape or otherwise do any final processing on the message
|
||||||
|
* prior to sending it.
|
||||||
|
*/
|
||||||
|
protected String escapeMessage (String msg)
|
||||||
|
{
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Implements <code>/broadcast</code>. */
|
/** Implements <code>/broadcast</code>. */
|
||||||
@@ -1288,8 +1340,15 @@ public class ChatDirector extends BasicDirector
|
|||||||
return "m.usage_broadcast";
|
return "m.usage_broadcast";
|
||||||
}
|
}
|
||||||
|
|
||||||
// mogrify and request to broadcast
|
// mogrify and verify length
|
||||||
requestBroadcast(mogrifyChat(args));
|
args = mogrifyChat(args);
|
||||||
|
String err = checkLength(args);
|
||||||
|
if (err != null) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// request the broadcast
|
||||||
|
requestBroadcast(args);
|
||||||
|
|
||||||
// note the command to be stored in the history
|
// note the command to be stored in the history
|
||||||
history[0] = command + " ";
|
history[0] = command + " ";
|
||||||
|
|||||||
Reference in New Issue
Block a user