Shoutbox

Gettin data from "/" commands - Printable Version

-Shoutbox (https://shoutbox.menthix.net)
+-- Forum: MsgHelp Archive (/forumdisplay.php?fid=58)
+--- Forum: Messenger Plus! for Live Messenger (/forumdisplay.php?fid=4)
+---- Forum: Scripting (/forumdisplay.php?fid=39)
+----- Thread: Gettin data from "/" commands (/showthread.php?tid=74609)

Gettin data from "/" commands by Lobo on 05-22-2007 at 07:46 PM

Hi all!

I know how to add and trap "/" commands, but my question is how to grab the param data...for example If I type:
/Joel somedata
How do I get only somedata?
Thanks! (6)


RE: Gettin data from "/" commands by saralk on 05-22-2007 at 08:03 PM

I don't know what method you use to trap "/" commands, but you normally use ChatWndSendMessage(Message).

Then the variable Message, is the whole message that was sent, including to bit after the parameter, so you can get all the data you want from there.

e.g.

code:
function OnEvent_ChatWndSendMessage(ChatWnd, Message) {
var checkExpCommand = /^\/command/i
if ( checkExpCommand.test(Message) ) {
  Param = Message.replace(checkExpCommand, "");           
}
}

RE: Gettin data from "/" commands by vikke on 05-22-2007 at 08:05 PM

You can do:

code:
var Command = "/Joel";
if(Message.substr(0, Command.length) == Command)
{
  // The /Joel command was used.
}

And then you get the param by:
code:
var Param = Message.substr(Command.length, Message.length);

Edit: This is all done in the ChatWndSendMessage event. Read the scripting documentation for more information.
RE: Gettin data from "/" commands by markee on 05-22-2007 at 08:59 PM

This method is my favourite and it VERY well written.  If there is anyway that people should get commands in general it is using this method posted by CookieRevised

CookieRevised's reply to [Release] Exit WLM


RE: Gettin data from "/" commands by DarkGhost on 05-22-2007 at 11:41 PM

ahh thank you i wqas looking for this

also if i do

code:
function OnEvent_ChatWndSendMessage(ChatWnd, Message) {
if (Message == "/woot") {
Debug.Trace("WOOT");
}
}

how can i make it so it doesnt say "Messenger Plus CAN NOT FIND THIS COMMAND" or w.e
RE: Gettin data from "/" commands by CookieRevised on 05-23-2007 at 12:09 AM

quote:
Originally posted by DarkGhost
also if i do
code:
function OnEvent_ChatWndSendMessage(ChatWnd, Message) {
    if (Message == "/woot") {
        Debug.Trace("WOOT");
    }
}

how can i make it so it doesnt say "The command you entered was not recognized"
you need to return something.

Either you must return a string, which indicates that your script has handled the message.
Or either you don't use the return statement at all or you return the numerical value 0, which indicates that your script hasn't handled the message (and thus the error "not a command") is shown if no other script exists which can handle the command...

In case your script does handle the message or command you can:
- choose to return an empty string. This will remove the message (thus the command text) from the typing area in the conversation, so the user can continue typing. Nothing is send to the server.
- or you return the result of the command handling, as a string.....


See the Plus! scripting documentation for the OnEvent_ChatWndSendMessage event. It is explained there also.
Also see the examples given in the link which markee posted.


code:
function OnEvent_ChatWndSendMessage(oChatWnd, sMessage) {
    if (/^\/([^ \n\r\v\xA0\/][^ \n\r\v\xA0]*)[\s\xA0]?([\s\S]*)/.exec(sMessage)) {
        var command = RegExp.$1.toLowerCase();
        var parameter = RegExp.$2;
        switch (command) {
            case 'myname':
                // <- Lets tell the function we handled the command. Pass something back to the conversation.
                MsgPlus.DisplayToast("Handled Command", "'" + command + "'\n'" + parameter + "'");
                Debug.Trace("command handled/recognized: '" + command + "', parameter: '" + parameter + "'");
                return "Hi, I'm a cookie!";
            case 'donothing':
                // <- We recognize the command, but we return the same message/command as-is.
                //    This is usually BAD code since it will cause the "command not recognized" error from
                //    Messenger Plus! to pop up if other scripts didn't recognized it. However, it could be
                //    used to intercept commands from other scripts and act upon them without disturbing the output.
                MsgPlus.DisplayToast("Handled Command", "'" + command + "'\n'" + parameter + "'");
                Debug.Trace("command handled/recognized: '" + command + "', parameter: '" + parameter + "'");
                return sMessage;
            case 'showcommand':
                // <- We recognize the command, and we return the same message/command as a text by adding a
                //    second slash. Since it is interpreted as text from that point on by Messenger Plus!,
                //    you wont get the "command not recognized" error.
                MsgPlus.DisplayToast("Handled Command", "'" + command + "'\n'" + parameter + "'");
                Debug.Trace("command handled/recognized: '" + command + "', parameter: '" + parameter + "'");
                return "/" + sMessage;
            case 'clearme':
                // <- Lets tell the function we handled the command. But nothing needs to be passed back to
                //    the conversation and nothing needs to be send to the server; so let's simply clear the
                //    text from the typing area.
                MsgPlus.DisplayToast("Handled Command", "'" + command + "'\n'" + parameter + "'");
                Debug.Trace("command handled/recognized: '" + command + "', parameter: '" + parameter + "'");
                return "";
            case 'wrongcode':
                // <- We recognize the command and act upon it, but we return nothing or 0, so Messenger Plus!
                //    does not know we did handle the command. This is BAD code because it will also cause the
                //    "command not recognized" error from Messenger Plus! to pop up.
                MsgPlus.DisplayToast("Handled Command", "'" + command + "'\n'" + parameter + "'");
                Debug.Trace("command handled/recognized: '" + command + "', parameter: '" + parameter + "'");
                return 0;
            default:
                // <- We don't recognize any other commands, so we return nothing or 0.
                //    Let the other installed and running scripts handle what is written in the conversation.
                MsgPlus.DisplayToast("Unhandled Command", "'" + command + "'\n'" + parameter + "'");
                Debug.Trace("command recieved but not handled/recognized: '" + command + "', parameter: '" + parameter + "'");
                // no return statement here.... or return 0
                return 0;
        }
    }
}
Thus, we handle five different commands in this script for popping up a toast:
   /MyName            The script will recognize it (and no error is shown). A different message is send back to the conversation.
   /DoNothing          The script will recognize it but an error is shown! Such code should be avoided.
   /ShowCommand   The script will recognize it (and no error is shown). The command text is shown in the conversation.
   /ClearMe             The script will recognize it (and no error is shown). Nothing is done, except for the typing area which is cleared.
   /WrongCode         The script will recognize it but an error is also shown! Such code should be avoided.

Any other command you try (and which isn't recognized by Messenger Plus! or by any other script) will generate the "command not recognized" error from Messenger Plus!.


Note: in JScript, ending a function with return 0 is exactly the same as not using the return statement at all. This is because, by default, if a function ends it always has 0 as its return value already.

PS: regular expression improved a bit, thanks to Markee.
RE: Gettin data from "/" commands by DarkGhost on 05-23-2007 at 12:32 AM

k ty
    if (/^\/([^\s\/]+)\s*([\s\S]*)$/.exec(sMessage) !== null) { whats this mean? - also is there a way i can just like make it so the person who typed /command can only see the message


RE: Gettin data from "/" commands by CookieRevised on 05-23-2007 at 12:56 AM

quote:
Originally posted by DarkGhost
if (/^\/([^\s\/]+)\s*([\s\S]*)$/.exec(sMessage) !== null) { whats this mean?
It is a regular expression.

Download and read the JScript 5.6 Documentation > "Regular Expression Object" and "Regular Expression Syntax"

There are also many threads on these forums which are about regular expressions, including snippets and code examples.

To see what the above regular expression does, see the link posted by markee which explains it.

In short: this one checks if the message of the user is a command and it splits up the message into the command part and the optional parameter part.

quote:
Originally posted by DarkGhost
also is there a way i can just like make it so the person who typed /command can only see the message
Show a messagebox to the user. Or show a Messenger Plus! toast with the MsgPlus.DisplayToast function, etc....

;)




PS: Try not to double post. Instead, click on the edit button beneath your last post if you want to add something before someone replies.

PS: always read the given links; They are given for a reaon. Try to use the search function of the forum.

RE: Gettin data from "/" commands by Lobo on 05-23-2007 at 07:14 PM

Ah...thanks all for your tips!!! :)


RE: Gettin data from "/" commands by markee on 02-04-2008 at 11:52 AM

I just wanted to update Cookie's regex to something that is a little better IMHO

code:
if (/^\/([^\s\/]\S*)\s*(.*)/.exec(sMessage) !== null) {

Cookie's old code didn't allow for / to be used elsewhere through the command (you can't use it to begin the command, but it is possible to use it later.  There is no point having $ at the end of the expression due to the greedy nature of quantifiers.  And finally [\s\S] is simply the equivalent of ".".

I think I should also give people an example of having parameters that are ALWAYS a single word, it is best to use the following instead:

code:
if (/^\/([^\s\/]\S*)\s*(\S*)/.exec(sMessage) !== null) {

and then for multiple paramters seperated by spaces (you will still need to do a split on the RegExp.$2 variable to get all of these variables seperated, or use of methods involving regex if you want to avoid blank variables):

code:
if (/^\/([^\s\/]\S*)\s*((?:\S+\s)*)/.exec(sMessage) !== null) {

If you want a different way to seperate between the parameters then you can use something like square braces (ie. "[param and with spaces]").  I'll use up to 3 params in this example:

code:
if (/^\/([^\s\/]\S*)\s*(?:\[.*?\]\s*(?:\[.*?\]\s*(?:\[.*?\])?)?)?/.exec(sMessage) !== null) {

This then becomes useful for when you are trying to find matching Plus! tags.  But this is getting off-topic and a lot more advanced when it comes to Regex.  If you have any questions, or want to see some other examples then please ask and I'll be happy to help (better to do it here so everyone can apreciate the beauty of regex)
RE: Gettin data from "/" commands by CookieRevised on 12-07-2009 at 01:39 AM

I know this is an old thread, but here are some important things I never bothered to reply with before because it is rather much. But still, since this topic comes up now and then:

quote:
Originally posted by markee
And finally [\s\S] is simply the equivalent of "."
Nope, it's not though. There is a difference.

"." matches any single character, except "\n".
"[\s\S]" matches any single character, including "\n".

Build-in Messenger Plus! commands do allow for "\n" in their parameters.
So "[\s\S]*" should definitely be used for the parameter string syntax instead of ".*".

eg: /me is<ctrl+enter>testing.

---------

markee, I actually don't agree upon those other comments and examples either though (about defining seperate parameters directly in that first regular expression).
Your third example doesn't even work at all.

Anyways, only the first spacing character is ignored with build-in Plus! commands. Every other character following that first spacing character is actually part of the parameter (and _not_ part of the seperator anymore in case it is another spacing character). So the captured parameter string (RegExp.$2) should contain all the spacing characters, except the first one.

What you later do with that captured parameter string (RegExp.$2) is up to a next procedure. Eg: trimming the spaces, splitting it up into multiple parameters, etc.
This also makes for much better practice and versatile, yet consistant, code imho. Because then you have a clear and seperated way of handling the parameter part, across multiple commands which can have each their own syntaxis. And you will also have an easy way to tell Plus! (and consequently the user) if the command was recognized but if there were some parameters missing or wrong.

Defining those seperated parameters directly in to that first main regular expression makes this harder in many (but granted, not all) cases.









However, you're correct about the possebility of the slash being part of the command as long as it isn't the second character.
But so is a <tab> character! And speaking of special characters, <hard space> (\xA0 = <alt+0160> or <alt+255>) can't be part of it as Plus! does consider this to be a spacing character.

So, the second part, "\S*", isn't entirly correct either, it should actually be "[^ \n\r\v\xA0]*".
notice the lack of \t and \f, and the addition of \xA0.

This has similar implications for the other parts too, see below:

---------

Similar, the second character, the one right after the first slash, isn't actually correctly defined as "[^\s\/]" either.
We know that:
  //test
  /<space>test
     => are NOT recognized as a possible command strings, but as literal texts (special case with //test though)

But in addition:
  /<hard space>test
     => is NOT recognized as a possible command string either as Plus! considers <hard space> to be a spacing character (RegExp rules do not).
  /<tab>test
  /<form feed>test
     => is recognized as a possible command string though, as Plus! does not consider a <tab> or <form feed> to be a spacing character (RegExp rules do).

Thus, the first part, "[^\s\/]", should actually be "[^ \n\r\v\xA0\/]".

---------

Then there is the seperation character between the command and its parameter.
There should actually be only 1 spacing character and that is always ignored, no matter what spacing character it is.
The rest of the spacing characters, if they are present, belong to the parameter string itself.

This single spacing character can be a <space>, but it can also be a <newline> (\n), a <return> (\r), a <vertical tab> (\v), and the <hard space> character (\xA0).
eg: /me<ctrl+enter>is testing.

However, it can not be a <tab> (\t) or a <form feed> (\f) as those are considered non-spacing characters by Plus!.
eg: /me<ctrl+tab>is testing.

So instead of "\s*" for the seperation character, you should use "[ \n\r\v\xA0]?".

But, if you implement the above syntaxis for the command string (first and second part), you could instead use "[\s\xA0]?" for the seperation character because the trailing <tab> and the <form feed> would already be captured as part of the command string itself in case they occur. But be carefull, you can not simply replace the entire command part "\/([^ \n\r\v\xA0\/][^ \n\r\v\xA0]*)" with the literal command string if you only want to check upon one command. For that, see below.








CONCLUSSION

As such: to seperate the command from its parameter string, just like Messenger Plus! does, one should use:
code:
if (/^\/([^ \n\r\v\xA0\/][^ \n\r\v\xA0]*)[ \n\r\v\xA0]?([\s\S]*)/.exec(sMessage)) {
    var command = RegExp.$1.toLowerCase();
    var parameter = RegExp.$2;
or
code:
if (/^\/([^ \n\r\v\xA0\/][^ \n\r\v\xA0]*)[\s\xA0]?([\s\S]*)/.exec(sMessage)) {
    var command = RegExp.$1.toLowerCase();
    var parameter = RegExp.$2;
Of course, most people would use simpler regular expressions or comparissons, but this one is the most correct one I can think of to mimic command handling exactly as it is done in Messenger Plus! internally. Any other syntax does not behave the same (especially not when you use \s and \S).

--

If you have only one command in your script you can not simply replace the first capture syntax with the command string. Instead you should use:
code:
if (/^\/mycommand(?:[ \n\r\v\xA0]([\s\S]*))?$/.exec(sMessage)) {
    var parameter = RegExp.$1;
This to avoid non-spacing characters like the <tab> and <form feed> (in regards to the Plus! command syntax that is) to be handled as spacing-characters, but yet to allow for the other spacing characters and ignoring them in the capture.

Notice that we do use "$" here to indicate the end of the string because we also used "?" to indicate that the match can happen 0 or 1 time.
If we didn't use "$" then the "?" would be interpreted as a non-greedy identifier. Using "{0,1}" instead will not work here either.
Also notice the use of "?:" to ignore the single seperator character between the command and the parameter in the capture.





TO RECAP

For more than one command:
code:
if (/^\/([^ \n\r\v\xA0\/][^ \n\r\v\xA0]*)(?:[ \n\r\v\xA0]([\s\S]*))?$/.exec(sMessage)) {
if (/^\/([^ \n\r\v\xA0\/][^ \n\r\v\xA0]*)[ \n\r\v\xA0]?([\s\S]*)/.exec(sMessage)) {
if (/^\/([^ \n\r\v\xA0\/][^ \n\r\v\xA0]*)[\s\xA0]?([\s\S]*)/.exec(sMessage)) {
    var command = RegExp.$1.toLowerCase();
    var parameter = RegExp.$2;
All will produce the same behaviour and result, where the first and longest form is the most versatile because you can simply replace the command capture with the literal command string as shown below:

For a single command:
code:
if (/^\/mycommand(?:[ \n\r\v\xA0]([\s\S]*))?$/.exec(sMessage)) {
    var parameter = RegExp.$1;