Shoutbox

script command error - "Command Requiers Parameter" - 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: script command error - "Command Requiers Parameter" (/showthread.php?tid=67584)

script command error - "Command Requiers Parameter" by Baggins on 10-23-2006 at 12:17 AM

The scriptMenu function looks like this

code:
function OnGetScriptCommands()
{
     var ScriptCommands = "<ScriptCommands>";
        ScriptCommands += "<Command>";
        ScriptCommands += "<Name>act</Name>";
        ScriptCommands += "<Description>Send a custom action message that doesn't start with your name.</Description>";
        ScriptCommands += "<Parameters>&lt;Message&gt;</Parameters>";
        ScriptCommands += "</Command>";
        ScriptCommands += "</ScriptCommands>";
    return ScriptCommands;

}

but when i type "/act Hello" it pops up saying "The Command You Entered Requiers a Parameter"

if you need to see the command parsing function just tell me.

Thanks
RE: script command error - "Command Requiers Parameter" by deAd on 10-23-2006 at 12:24 AM

Post the command parsing function please, I think it's in there as Plus! doesn't have a command error like that..


RE: script command error - "Command Requiers Parameter" by Baggins on 10-23-2006 at 12:27 AM

code:
function OnEvent_ChatWndSendMessage(ChatWnd, Message)
{
    if (Message.substr(0, 4) == "/act")
    {
        Debug.Trace("Recognized");
        var split = Message.split(" ");
        nick = Messenger.MyName;
        var msg = "/me";
        Messenger.MyName = split[1];
        for (i = 2; i < split.Length; i++)
        {
            msg += split[i];
        }
        MsgPlus.AddTimer("restoreNick", 100);
        return msg;
    }
    Debug.Trace("Not Recognized");
}

There

EDIT: If this helps, is gets far enough to change my nick but not far enough to return anything
RE: script command error - "Command Requiers Parameter" by matty on 10-23-2006 at 12:47 AM

I am at work so I can't test this but here you go.

code:
function OnEvent_ChatWndSendMessage(ChatWnd, Message) {
    var mCommand = new Array();
    mCommand = Message.split(' ');
   
    if (mCommand[0] == '/act'){
        Debug.Trace("Recognized");
        var nick = Messenger.MyName;
        var msg = '/me ';
        Messenger.MyName = mCommand[1];
        for (i = 2; i < mCommand.Length; i++) {
            msg += mCommand[i];
        }
        MsgPlus.AddTimer('restoreNick', 100);
        return msg;
    } else { Debug.Trace('Not Recognized'); }
}



quote:
Originally posted by billboy1001
code:
var msg = "/me";

This is your error right here

/ me requires a parameter. So the code must be:
quote:
Originally posted by billboy1001
code:
var msg = "/me ";


RE: script command error - "Command Requiers Parameter" by Baggins on 10-23-2006 at 12:53 AM

quote:
Originally posted by Matty
function OnEvent_ChatWndSendMessage(ChatWnd, Message) {
    var mCommand = new Array();
    mCommand = Message.split(' ');
   
    if (mCommand[0] == '/act'){
        Debug.Trace("Recognized");
        var nick = Messenger.MyName;
        var msg = "/me";
        Messenger.MyName = mCommand[1];
        for (i = 2; i < mCommand.Length; i++) {
            msg += mCommand[i];
        }
        MsgPlus.AddTimer("restoreNick", 100);
        return msg;
    } else { Debug.Trace("Not Recognized"); }
}
No doesn't work
RE: script command error - "Command Requiers Parameter" by matty on 10-23-2006 at 12:57 AM

Check out my edit at the bottom of the post.


RE: script command error - "Command Requiers Parameter" by deAd on 10-23-2006 at 01:31 AM

I stand corrected, this error message does exist in plus :O specifically for the /me command. I tried it with /all.

Working code *should* be:

code:
function OnEvent_ChatWndSendMessage(ChatWnd, Message) {
    var mCommand = new Array();
    mCommand = Message.split(' ');
   
    if (mCommand[0] == '/act'){
        Debug.Trace("Recognized");
        var nick = Messenger.MyName;
        var msg = "/me ";
        Messenger.MyName = mCommand[1];
        for (i = 2; i < mCommand.Length; i++) {
            msg += mCommand[i];
        }
        MsgPlus.AddTimer("restoreNick", 100);
        return msg;
    } else { Debug.Trace("Not Recognized"); }
}

edit: didn't see matty had posted the correction as well..nevermind :P
RE: script command error - "Command Requiers Parameter" by CookieRevised on 10-23-2006 at 10:59 AM

billboy1001 (and others), now that you know what the cause was for that error, there are some other major pitfalls in your script and things you should now about:

first, as a sidenote, note that the above fixed scripts all made the nick variable local. Since you use a timer to restore the nickname, that variable should be global (as you did it in your original script) and not local as in the fixed snippets.

1) May I suggest not to use mCommand = Message.split(' '); and that code to get the parameters. It is bound to produce not the result you want when you (accidently or not) have more than one space. Hence the nickname wont always be in mCommand[1].

And if you forget to enter some text to be used for the me command on the parameter line, the script will produce that same "command needs parameter" too.

2) The use of timers:
Be extremely carefull with that. I also use the timer event (obviously), but do you make sure in that event that the logged in user is still the same user who started the timer? If not, and you sign out before the timer has triggered, you actually will change the nickname of the newly logged in user.

Also, by the use of the timer as you use it, there is no garantee that the timer will be triggered after the /me command has done its job. The timer might as well be triggered before the /me command, and thus the script will not restore your nickname properly.

3) When you return a message in the OnEvent_ChatWndSendMessage() with the /me command, it will _not_ be interpreted as a command, but as a pure text. This is probably a bug in Messenger Plus! Live. <= fixed in latest Plus! version.

4) Nickchanges and commands take their time (though it usually is performed within some milliseconds; it still takes some milliseconds time). This means that you can not expect the nickchange to have happened before you send the /me command and that you can not expect the /me command to have happened before restoring the nickname.


As you see, what you want to do seems easy enough, but it is actually far from strait forward...

But, first things first. Suppose problem 2, 3 and 4 don't exist, then you still should be using something like this instead:

code:
function OnEvent_ChatWndSendMessage(oChatWnd, sMessage) {
        if (new RegExp(/^\/act\s+(\S+)\s+(.+)$/i).exec(sMessage) != null) {
                var nick = Messenger.MyName;
                Messenger.MyName = RegExp.$1;
                MsgPlus.AddTimer("restoreNick", 100);
                return "/me " + RegExp.$2;
        }
}
Notice how much shorter and strait forward the code actually is...
And may I also suggest:
code:
function OnGetScriptCommands() {
        return "<ScriptCommands>"
                +    "<Command>"
                +        "<Name>act</Name>"
                +        "<Description>Sends an action message that starts with a custom name</Description>"
                +        "<Parameters>&lt;name&gt; &lt;message&gt;</Parameters>"
                +    "</Command>"
                + "</ScriptCommands>";
}

Now, as for the rest of the problems. Those can only be dealed with if you make a script which will trigger an action and wait for that action to be ended before doing another action.

So you need to wait until the name has changed before you actually can perform the /me command. Then you have to wait till that is finished and only then you can change the nick back.

You would think you could do all this by using a combination of the events: OnEvent_MyNameChange, OnEvent_ChatWndSendMessage or OnEvent_ChatWndReceiveMessage.

However, this will not work!!!

First of all, OnEvent_ChatWndReceiveMessage isn't always triggered when you send a new command message back to the chatwindow in response to an OnEvent_ChatWndSendMessage event.

Second, and most importantly, all those events are triggered _before_ the message is handled or nick is changed. So if you do something in those event functions it will not be performed after those events (as we need it to be), but before the events!

To fix all this you _must_ revert back to a dirty workaround using a timer. There is no other way around it (using only pure scripting):

The fixed code:
code:
var oldNick = "";
var actNick = "";
var actMessage = "";
var actWindow = new Object();
var actWindowHandle = 0;

function OnEvent_ChatWndSendMessage(oChatWnd, sMessage) {
    // Check if the command is in the form: /act<some spaces><nickname><some spaces><message>
    if (new RegExp(/^\/act\s*(\S*)\s*(.*)$/).exec(sMessage) != null) {
        // Store needed variables
        actNick = RegExp.$1;        // our action nick
        actMessage = RegExp.$2;    // our action message
        actWindow = oChatWnd;
        actWindowHandle = oChatWnd.Handle;

        // Check if all required parameters are filled in
        // (return "/me" is a crude trick to show the "parameter required" error)
        if (actNick === "" || actMessage === "") return "/me";

        // If we are still in a previous action process don't update the oldNick variable
        if (oldNick === "") oldNick = Messenger.MyName;
        // Change our nick
        Messenger.MyName = actNick;

        // Wait for the nick to be changed
        MsgPlus.AddTimer("pollNickChange", 100);

        return "";
    }
}

function OnEvent_Timer(sTimerId) {
    if (sTimerId === "pollNickChange") {
        if (Messenger.MyName === actNick) {
            // Nick has been changed, we are now ready to send our action message
            // Check if the chatwindow still exists(!) and if we actually can send something
            var lpClassName = Interop.Allocate(28);
            Interop.Call("User32", "GetClassNameW", actWindowHandle, lpClassName, 14);
            if (lpClassName.ReadString(0) === "IMWindowClass")
                if (actWindow.EditChangeAllowed) {
                    actWindow.SendMessage("/me " + actMessage);
                }
            // Wait for the message to be send                   
            MsgPlus.AddTimer("pollMsgChange", 1000);
        } else {
            // Nick hasn't been changed yet, check again in 100 milliseconds
            MsgPlus.AddTimer("pollNickChange", 100);
        }
    }
    if (sTimerId === "pollMsgChange") {
        // Change our nick back to what it was
        // Note: there is no clean way to check if a message has been recieved and
        //       interpreted properly by Plus! unless you also add a sniffer to this script!!!
        //       This is also the reason why this, already complex, script doesn't always work either.
        Messenger.MyName = oldNick;
        oldNick = "";
    }
}

function OnEvent_Signout(sEmail) {
    // Make sure the timers are not running when the user signs out
    // Very important to prevent name changes of other users who might sign in afterwards
    MsgPlus.CancelTimer("pollNickChange");
    MsgPlus.CancelTimer("pollMsgChange");
    oldNick = "";
}

function OnGetScriptCommands() {
    return    "<ScriptCommands>"
        +        "<Command>"
        +            "<Name>act</Name>"
        +            "<Description>Sends an action message that starts with a custom name</Description>"
        +            "<Parameters>&lt;name&gt; &lt;message&gt;</Parameters>"
        +        "</Command>"
        +    "</ScriptCommands>";
}


But still note that even this, already complex, script is still not always doing what you want!!! People can say it works nicely, but it really doesn't! I have been busy with it all day long (see posting time and this final edit time) (and discovered certain bugs in Plus! with it also) and I can safely say that doing what you want todo in a proper way so it always works is as good as impossible to do with pure scripting.

All this is an extremely good example of how something seems strait forward, but in fact is really hard (impossible) todo.

If you want something which will always work (in whatever condition it is used in; this means using the command a few times quickly (eg: quicktexts), not producing errors when the nick change limit is reached, detecting when a message is interpreted, etc), you need to deal with all this on the protocol level...


;)
RE: script command error - "Command Requiers Parameter" by Baggins on 10-23-2006 at 08:30 PM

first:
the nick variable is global
second:
who in the world would have the time to read all that CRAP you just posted? this is why i did not quote you.
third:
Th e new chat wnd send message funciton you proposed works perfectly, thanks


RE: script command error - "Command Requiers Parameter" by foaly on 10-23-2006 at 08:35 PM

quote:
Originally posted by billboy1001
who in the world would have the time to read all that CRAP you just posted? this is why i did not quote you.
believe me it's not crap... and if you took the time to read it you might learn something...
RE: script command error - "Command Requiers Parameter" by CookieRevised on 10-23-2006 at 08:36 PM

quote:
Originally posted by billboy1001
the nick variable is global
please take the time to read my post properly:
quote:
Originally posted by CookieRevised
first, as a sidenote, note that the above fixed scripts all made the nick variable local. Since you use a timer to restore the nickname, that variable should be global (as you did it in your original script) and not local as in the fixed snippets.

quote:
Originally posted by billboy1001
who in the world would have the time to read all that CRAP you just posted? this is why i did not quote you.
thank you for calling hours of work crap...

quote:
Originally posted by billboy1001
The new chat wnd send message funciton you proposed works perfectly, thanks
you're welcome...
RE: script command error - "Command Requiers Parameter" by Baggins on 10-23-2006 at 09:00 PM

actually now that i did take the time to read, and with a few modifications my script is working perfectly now.

EDIT: how can i make a regular expression to split "hello world, hi" into "hello" and "world, hi" will

code:
RegExp(/^\s+(\S+)\s+(.+)$/i).exec(sMessage)
do it?

RE: script command error - "Command Requiers Parameter" by CookieRevised on 10-23-2006 at 09:14 PM

Make a quicktext with the command and/or perform many custom actions quickly after eachother, you'll see it will screw up.

This is because events are fired before the actual event occurs, not afterwards..., using timers is always tricky and errors could always happen because of timers triggering too soon or too late..., and you can't catch a message being interpreted (the /me command being processed on screen and "« I" being replaced by your nickname) with scripting...

So, you can't make something fail-proof for this, unless you revert to making a proxy and sending your own messages directly via the protocol.

In other words: your script might work, but it will not work perfectly

;)


RE: RE: script command error - "Command Requiers Parameter" by Baggins on 10-23-2006 at 09:21 PM

quote:
Originally posted by CookieRevised
Make a quicktext with the command and/or perform many custom actions quickly after eachother, you'll see it will screw up.

This is because events are fired before the actual event occurs, not afterwards..., using timers is always tricky and errors could always happen because of timers triggering too soon or too late..., and you can't catch a message being interpreted (the /me command being processed on screen and "« I" being replaced by your nickname) with scripting...

So, you can't make something fail-proof for this, unless you revert to making a proxy and sending your own messages directly via the protocol.

In other words: your script might work, but it will not work perfectly

;)

but how do i write a regex to split at the first space without the /act
RE: RE: script command error - "Command Requiers Parameter" by CookieRevised on 10-23-2006 at 09:24 PM

quote:
Originally posted by billboy1001
actually now that i did take the time to read, and with a few modifications my script is working perfectly now.

EDIT: how can i make a regular expression to split "hello world, hi" into "hello" and "world, hi" will
code:
RegExp(/^\s+(\S+)\s+(.+)$/i).exec(sMessage)
do it?


teaching regular expressions via a post here is way to difficult. I suggest you read up on some tutorials. And start by learning the syntax of regular expressions as used in JScript:
* MSDN: Regular Expression Syntax
* MSDN: Regular Expression Object
* some unofficial tutorial (this tutorial is specifically for JavaScript, not JScipt. There are differences!
* etc...

The proper code for what you want could be something like:
code:
RegExp(/^(\S+)\s+(.+)$/i).exec(sMessage)
RegExp.$1 will be "hello"
RegExp.$2 will be "world, hi"

Note that for the above regular expression the sMessage variable _must_ be in the form of "something<at least 1 spacing character>something" or it will not work.

See my long previous post, it includes two pieces of code which split a string into "something" and "all the rest".
RE: RE: RE: script command error - "Command Requiers Parameter" by Baggins on 10-23-2006 at 09:26 PM

quote:
Originally posted by CookieRevised
quote:
Originally posted by billboy1001
actually now that i did take the time to read, and with a few modifications my script is working perfectly now.

EDIT: how can i make a regular expression to split "hello world, hi" into "hello" and "world, hi" will
code:
RegExp(/^\s+(\S+)\s+(.+)$/i).exec(sMessage)
do it?


teaching regular expressions via a post here is way to difficult. I suggest you read up on some tutorials. And start by learning the syntax of regular expressions as used in JScript:
* MSDN: Regular Expression Syntax
* MSDN: Regular Expression Object
* some unofficial tutorial
* etc...

The proper code for what you want could be something like:
code:
RegExp(/^(\S+)\s+(.+)$/i).exec(sMessage)
RegExp.$1 will be "hello"
RegExp.$2 will be "world, hi"

sweet, thank you
sorry bout the crap thing