nikeee / node-ts

Node.js TeamSpeak® 3 Server Query client implemented in TypeScript
GNU Lesser General Public License v3.0
38 stars 6 forks source link

Events Example #9

Closed Sir-Will closed 9 years ago

Sir-Will commented 9 years ago

hey,

could you show me an example for events? I don't understand how to use them. (in node.js)

nikeee commented 9 years ago

The notification system is pretty much the same as in gwTumm/node-teamspeak.

The TeamSpeak 3 Query API provides a way to register notifications that will be sent to the client. A common example for this is the notification that occurrs as soon as someone messages or pokes the query client.

Quoting the docs:

Registers for a specified category of events on a virtual server to receive notification messages. Depending on the notifications you've registered for, the server will send you a message on every event in the view of your ServerQuery client (e.g. clients joining your channel, incoming text messages, server configuration changes, etc). The event source is declared by the event parameter while id can be used to limit the notifications to a specific channel.

To tell the server that you want to get notified when a specific event occurs, you need to send a servernotifyregister message:

client.send("servernotifyregister", {
    event: "textprivate" /* event type (see ts3 query docs) */
}, [/* no options */]);

As soon as the server responds with a success message, the client emit the event with the name that was passed to the event parameter. Depending on the event you registered, there are several parameters that come with the event.

To add an event listener to the textprivate event that was previously registered on the server do this:

client.on("textprivate", function(data) {
    /* this callback gets invoked */
    console.log("Got private message!");
    console.dir(data); // print out event-specific data
});

If you don't want to be notified anymore about some event, you can send the servernotifyunregister message:

client.send("servernotifyunregister", {
    event: "textprivate" /* event type (see ts3 query docs) */
}, [/* no options */]);

Note that the event listener is still there if you don't remove it, but it certanly won't get fired since you told the server not to send these anymore. If you want to get rid of them, too, you can use the standard nodejs removeAllListeners:

client.removeAllListeners("textprivate");

However, there are events that don't need to be registered, for exampe error, timeout and close. These events depend on the underlying TCP socket connection status, so no approval/registration by the server is needed.

client.on("timeout", function(){
    console.log("Connection timed out. :/");
});

For a list of all exposed events by the Query API, have a look at the docs.

To conclude, you can to something like this:

client.send("servernotifyregister", { event: "textprivate" }, []).then(() => {
    console.log("notification successfully registered");
    console.log("Creating local event handler");
    client.on("textprivate", data => {
        console.log("Got private message!");
        console.dir(data); // print out event-specific data
    });
});

I'll put these samples in the readme.

Note: The event type that needs to be passed to the server to register the notification isnt always the same string as the one you use for your local event handler. E.g. you can register an event of type "server" and then hook up an event handler that handles "clientmove".

Sir-Will commented 9 years ago

Ah thanks. How do I add the options? I tried this:

cl.send("servernotifyregister", 
    {event: "channel"}, [id: 2]
);

but it throws the error Unexpected token.

nikeee commented 9 years ago

Actually, this query command has no options. The channel id is just another parameter.

cl.send("servernotifyregister", {
         event: "channel",
         id: 1339
     },
     [/* nope */]
);

The difference between parameters and options is that parameters take values, options are just switches (see docs for more details). This is the reason why the options is an array, not a dictionary/object like the parameters.

Sir-Will commented 9 years ago

Hm, this seems not to do anything: (I'm sorry for the newbie questions.)

var ts3 = require("node-ts");
var util = require("util"); // Include node utils

var cl = new ts3.TeamSpeakClient("#"); // create a new client

cl.send("login", {
        client_login_name: "#",
        client_login_password: "#"
    });
cl.send("use", {sid: 1});

cl.send("servernotifyregister", 
    {event: "channel", id: 2}, []
);

cl.on("channel", function(data) {
    console.log("Got information");
    console.dir(data);
});
nikeee commented 9 years ago

As I noted above, the event you have to hook up isn't always the same string as the event type you registered to. If you register the type channel for Id 2, you receive multiple events.

This site is German but you should get the point: http://redeemer.biz/medien/artikel/ts3-query-notify/ This article is pretty essential because the events aren't documented.

Omit the event name when using the API. E.g. notifycliententerview becomes cliententerview.

Oh, well. Seems that I made a mistake above. The event name for a private message isn't the same as the event type. It should hook up to "textmessage" and register "textprivate" (see linked article above).

Sir-Will commented 9 years ago

Oh thanks, your typo in "testmessage" confused me btw^^

I'm from germany too so that's no issue ;)

If I watch clientmoved with event channel and id 0 it shows the same data twice if I switch an channel instead of one with the channel id of the start and one of the target. Any idea why?

nikeee commented 9 years ago

The Id 0 stands for all channels, so you get clientmoved twice because the client left one channel and joined another (as written in the German article I posted).

Sir-Will commented 9 years ago

Which id do you mean? I get this if I switch once the channel:

[ { clientmoved: '', ctid: 9, reasonid: 0, clid: 7 } ]
[ { clientmoved: '', ctid: 9, reasonid: 0, clid: 7 } ]

What I need is the ID of the channel where the player is coming from.

nikeee commented 9 years ago

Just edited my post. If you subscribe to channel 0, you subscribe to all channels. The source channel should be cfid, the destination channel ctid. If there is no cfid, the cfid might be just 0, so the client just joined the server. But it also could be possible that there is no cfid field. Just try a little bit or view messages using telnet.

Maybe using clientleftview/cliententerview can solve your problem, too.

Sir-Will commented 9 years ago

Okay. cfid seems not to work as it throws undefined, hm. notifycliententerview does have it but get only triggered if a user connects to the server.

Sir-Will commented 9 years ago

How can I see the error of the command I have send?

nikeee commented 9 years ago

You should be able to use the catch/fail-Mechanismen mechanism of Q promises.

Sir-Will commented 9 years ago

I tried this:

function createChannel(data) {
    console.log(data);

    cl.send("channelcreate", {channel_name: "Test"}, function(err, response, rawResponse){
        console.log(util.inspect(response));
    });
}

but it throws an error.

What exactly do you mean?

nikeee commented 9 years ago

Using then(fn).fail(fn):

function createChannel(data) {
    console.log(data);
    cl.send("channelcreate", {channel_name: "Test"}).then(function(data) {
        console.log("Success!");
    })
    .fail(function(err) {
        console.log("Fail. :(");
        console.dir(err);
    });
}

Or using then(fn, fn):

function createChannel(data) {
    console.log(data);
    cl.send("channelcreate", {channel_name: "Test"}).then(function(data) {
        console.log("Success!");
    }, function(err) {
        console.log("Fail. :(");
        console.dir(err);
    });
}

This has to do with Q, not node-ts. See their docs for more samples.

If you are not familiar with Q promises, you can use node-teamspeak, which uses standard node-callbacks instead of promises.

Sir-Will commented 9 years ago

Ah, thanks. I appreciate your help :)

Sir-Will commented 9 years ago

@nikeee would it be possible to send you a private message somewhere?

Sir-Will commented 9 years ago

I currenlty get this error:

Logged in :)
events.js:85
      throw er; // Unhandled 'error' event
            ^
Error: This socket has been ended by the other party
    at Socket.writeAfterFIN [as write] (net.js:289:12)
    at TeamSpeakClient.checkQueue (G:\Downloads\TS3Bot\node_modules\node-ts\dist\index.js:210:26)
    at LineStream.<anonymous> (G:\Downloads\TS3Bot\node_modules\node-ts\dist\index.js:109:23)
    at LineStream.emit (events.js:107:17)
    at readableAddChunk (_stream_readable.js:163:16)
    at LineStream.Readable.push (_stream_readable.js:126:10)
    at LineStream.Transform.push (_stream_transform.js:140:32)
    at LineStream._pushBuffer (G:\Downloads\TS3Bot\node_modules\node-ts\node_modules\byline\lib\byline.js:123:17)
    at LineStream._flush (G:\Downloads\TS3Bot\node_modules\node-ts\node_modules\byline\lib\byline.js:137:8)
    at LineStream.<anonymous> (_stream_transform.js:130:12)

After I got this error I can no longer connect to the server and need to restart the server.

nikeee commented 9 years ago

Could you post some code? I'm currently pretty short on time.

Sir-Will commented 9 years ago

The issue is probably in this clientmoved event as this is the last thing I added. Also the disconnect happens after the second clientmove.

nikeee commented 9 years ago

There is a limit for the amount of commands a query client can send to the server. If the client hits it, the server disconnects the client (some kind of abusing prevention). Have you tried increasing the limit?

Sir-Will commented 9 years ago

Where can I increase it? I couldn't find anything about it.

nikeee commented 9 years ago

Well, it's described in the docs under "Whitelisting and Blacklisting". Shouldn't be hard to find. Again, this seems not bo be an issue of node-ts. If you have problems using the Query API, head over to the TeamSpeak Forums.

Sir-Will commented 9 years ago

Ah thanks, That seems to have fixed it.

nikeee commented 9 years ago

I'll close this for now. IF you have further issues, just open a new issue or send me a mail (see package.json). Thanks!

Sir-Will commented 9 years ago

Okay, thanks for your help!